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 HTML dintre de la traducció", "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 HTML inside the translation", "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 HTML dentro de la traducción", "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')}