diff --git a/README.md b/README.md
index 789d1a98..db157885 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,8 @@
- [i18nMiddleware](#i18nmiddleware)
- [7. Plurals](#7-plurals)
- [8. Use HTML inside the translation](#8-use-html-inside-the-translation)
-- [9. Demos](#9-demos)
+- [9. Nested translations](#9-nested-translations)
+- [10. Demos](#10-demos)
- [Static site example](#static-site-example)
- [With server example](#with-server-example)
@@ -529,7 +530,27 @@ Each index of `components` array corresponds with `` of the defin
In the `components` array it's not necessary to pass the children of each element. Children will be calculed.
-## 9. Demos
+## 9. Nested translations
+
+In the namespace is possible to define nested keys like:
+
+```json
+{
+ "nested-example": {
+ "very-nested": {
+ "nested": "Nested example!"
+ }
+ }
+}
+```
+
+In order to use it, you should use "." as id separator:
+
+```js
+t`namespace:nested-example.very-nested.nested`
+```
+
+## 10. Demos
### Static site example
diff --git a/__tests__/useTranslation.test.js b/__tests__/useTranslation.test.js
index d41e68e8..46125ae3 100644
--- a/__tests__/useTranslation.test.js
+++ b/__tests__/useTranslation.test.js
@@ -19,6 +19,144 @@ const TestEnglish = ({ i18nKey, query, namespaces }) => {
describe('useTranslation', () => {
afterEach(cleanup)
+ describe('fallbacks', () => {
+ test('should return the key as fallback WITH PROVIDER', () => {
+ const Inner = () => {
+ const { t } = useTranslation()
+ const test = t('ns:template-string')
+ return (
+ <>
+ {test} | {typeof test}
+ >
+ )
+ }
+
+ const expected = 'ns:template-string | string'
+
+ const { container } = render(
+
+
+
+ )
+ expect(container.textContent).toBe(expected)
+ })
+
+ test('should return the key as fallback WITHOUT PROVIDER', () => {
+ const Inner = () => {
+ const { t } = useTranslation()
+ const test = t('ns:template-string')
+ return (
+ <>
+ {test} | {typeof test}
+ >
+ )
+ }
+
+ const expected = 'ns:template-string | string'
+
+ const { container } = render()
+ expect(container.textContent).toBe(expected)
+ })
+
+ test('should return the key as fallback using a template string WITH PROVIDER', () => {
+ const Inner = () => {
+ const { t } = useTranslation()
+ const test = t`ns:template-string`
+ return (
+ <>
+ {test} | {typeof test}
+ >
+ )
+ }
+
+ const expected = 'ns:template-string | string'
+
+ const { container } = render(
+
+
+
+ )
+ expect(container.textContent).toBe(expected)
+ })
+
+ test('should return the key as fallback using a template string WITHOUT PROVIDER', () => {
+ const Inner = () => {
+ const { t } = useTranslation()
+ const test = t`ns:template-string`
+ return (
+ <>
+ {test} | {typeof test}
+ >
+ )
+ }
+
+ const expected = 'ns:template-string | string'
+
+ const { container } = render()
+ expect(container.textContent).toBe(expected)
+ })
+ })
+
+ describe('nested', () => {
+ test('should work with nested keys', () => {
+ const i18nKey = 'ns:grandfather.parent.child'
+ const expected = 'I am the child'
+ const nested = {
+ grandfather: {
+ parent: {
+ child: expected,
+ },
+ },
+ }
+ const { container } = render(
+
+ )
+ expect(container.textContent).toContain(expected)
+ })
+
+ test('should work with nested keys + plural', () => {
+ const i18nKey = 'ns:grandfather.parent.child'
+ const expected = 'Plural! 2'
+ const nested = {
+ grandfather: {
+ parent: {
+ child: 'Singular {{count}}',
+ child_plural: 'Plural! {{count}}',
+ },
+ },
+ }
+ const { container } = render(
+
+ )
+ expect(container.textContent).toContain(expected)
+ })
+
+ test('should work with nested keys + count=1', () => {
+ const i18nKey = 'ns:grandfather.parent.child'
+ const expected = 'One! 1'
+ const nested = {
+ grandfather: {
+ parent: {
+ child: 'Singular {{count}}',
+ child_1: 'One! {{count}}',
+ },
+ },
+ }
+ const { container } = render(
+
+ )
+ expect(container.textContent).toContain(expected)
+ })
+ })
+
describe('plurals', () => {
test('should work with singular | count=1', () => {
const i18nKey = 'ns:withsingular'
@@ -146,81 +284,5 @@ describe('useTranslation', () => {
)
expect(container.textContent).toContain(expected)
})
-
- test('should return the key as fallback WITH PROVIDER', () => {
- const Inner = () => {
- const { t } = useTranslation()
- const test = t('ns:template-string')
- return (
- <>
- {test} | {typeof test}
- >
- )
- }
-
- const expected = 'ns:template-string | string'
-
- const { container } = render(
-
-
-
- )
- expect(container.textContent).toBe(expected)
- })
-
- test('should return the key as fallback WITHOUT PROVIDER', () => {
- const Inner = () => {
- const { t } = useTranslation()
- const test = t('ns:template-string')
- return (
- <>
- {test} | {typeof test}
- >
- )
- }
-
- const expected = 'ns:template-string | string'
-
- const { container } = render()
- expect(container.textContent).toBe(expected)
- })
-
- test('should return the key as fallback using a template string WITH PROVIDER', () => {
- const Inner = () => {
- const { t } = useTranslation()
- const test = t`ns:template-string`
- return (
- <>
- {test} | {typeof test}
- >
- )
- }
-
- const expected = 'ns:template-string | string'
-
- const { container } = render(
-
-
-
- )
- expect(container.textContent).toBe(expected)
- })
-
- test('should return the key as fallback using a template string WITHOUT PROVIDER', () => {
- const Inner = () => {
- const { t } = useTranslation()
- const test = t`ns:template-string`
- return (
- <>
- {test} | {typeof test}
- >
- )
- }
-
- const expected = 'ns:template-string | string'
-
- const { container } = render()
- expect(container.textContent).toBe(expected)
- })
})
})
diff --git a/examples/static-site/locales/ca/more-examples.json b/examples/static-site/locales/ca/more-examples.json
index 1b947902..26a01e06 100644
--- a/examples/static-site/locales/ca/more-examples.json
+++ b/examples/static-site/locales/ca/more-examples.json
@@ -6,5 +6,10 @@
"plural-example_plural": "És en plural perquè el valor és {{count}}",
"example-with-html": "<0>Aquest és un exempre <1>utilitzant HTML1> dintre de la traducció0>",
"no-functional-example": "Traducció feta des d'un component no funcional",
- "dynamic-namespaces-link": "Veure un exemple de càrrega dinàmica"
-}
\ No newline at end of file
+ "dynamic-namespaces-link": "Veure un exemple de càrrega dinàmica",
+ "nested-example": {
+ "very-nested": {
+ "nested": "Exemple anidat!"
+ }
+ }
+}
diff --git a/examples/static-site/locales/en/more-examples.json b/examples/static-site/locales/en/more-examples.json
index e64c2e77..8d4ac819 100644
--- a/examples/static-site/locales/en/more-examples.json
+++ b/examples/static-site/locales/en/more-examples.json
@@ -6,5 +6,10 @@
"plural-example_plural": "Is in plural because the value is {{count}}",
"example-with-html": "<0>This is an example <1>using HTML1> inside the translation0>",
"no-functional-example": "Translation done from a no-functional component",
- "dynamic-namespaces-link": "See an example of dynamic namespace"
-}
\ No newline at end of file
+ "dynamic-namespaces-link": "See an example of dynamic namespace",
+ "nested-example": {
+ "very-nested": {
+ "nested": "Nested example!"
+ }
+ }
+}
diff --git a/examples/static-site/locales/es/more-examples.json b/examples/static-site/locales/es/more-examples.json
index 9ad1ed9c..5ae9e4c9 100644
--- a/examples/static-site/locales/es/more-examples.json
+++ b/examples/static-site/locales/es/more-examples.json
@@ -6,5 +6,10 @@
"plural-example_plural": "Es en plural porque el valor es {{count}}",
"example-with-html": "<0>Este es un ejemplo <1>usando HTML1> dentro de la traducción0>",
"no-functional-example": "Traducción hecha desde un componente no funcional",
- "dynamic-namespaces-link": "Ver un ejemplo de carga dinámica"
-}
\ No newline at end of file
+ "dynamic-namespaces-link": "Ver un ejemplo de carga dinámica",
+ "nested-example": {
+ "very-nested": {
+ "nested": "¡Ejemplo anidado!"
+ }
+ }
+}
diff --git a/examples/static-site/pages_/more-examples/index.js b/examples/static-site/pages_/more-examples/index.js
index 323cbb4e..1348db4c 100644
--- a/examples/static-site/pages_/more-examples/index.js
+++ b/examples/static-site/pages_/more-examples/index.js
@@ -25,8 +25,10 @@ export default function MoreExamples() {
/>
+ {t`more-examples:nested-example.very-nested.nested`}
+
- {t('more-examples:dynamic-namespaces-link')}
+ {t('more-examples:dynamic-namespaces-link')}