Skip to content

Commit

Permalink
Allow nested keys in namespaces (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
aralroca authored Jan 8, 2020
1 parent 30d55fc commit fa76ce9
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 5,756 deletions.
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -529,7 +530,27 @@ Each index of `components` array corresponds with `<index></index>` 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

Expand Down
214 changes: 138 additions & 76 deletions __tests__/useTranslation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(
<I18nProvider lang="en" namespaces={{}}>
<Inner />
</I18nProvider>
)
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(<Inner />)
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(
<I18nProvider lang="en" namespaces={{}}>
<Inner />
</I18nProvider>
)
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(<Inner />)
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(
<TestEnglish namespaces={{ ns: nested }} i18nKey={i18nKey} />
)
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(
<TestEnglish
namespaces={{ ns: nested }}
i18nKey={i18nKey}
query={{ count: 2 }}
/>
)
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(
<TestEnglish
namespaces={{ ns: nested }}
i18nKey={i18nKey}
query={{ count: 1 }}
/>
)
expect(container.textContent).toContain(expected)
})
})

describe('plurals', () => {
test('should work with singular | count=1', () => {
const i18nKey = 'ns:withsingular'
Expand Down Expand Up @@ -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(
<I18nProvider lang="en" namespaces={{}}>
<Inner />
</I18nProvider>
)
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(<Inner />)
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(
<I18nProvider lang="en" namespaces={{}}>
<Inner />
</I18nProvider>
)
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(<Inner />)
expect(container.textContent).toBe(expected)
})
})
})
9 changes: 7 additions & 2 deletions examples/static-site/locales/ca/more-examples.json
Original file line number Diff line number Diff line change
Expand Up @@ -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</1> 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"
}
"dynamic-namespaces-link": "Veure un exemple de càrrega dinàmica",
"nested-example": {
"very-nested": {
"nested": "Exemple anidat!"
}
}
}
9 changes: 7 additions & 2 deletions examples/static-site/locales/en/more-examples.json
Original file line number Diff line number Diff line change
Expand Up @@ -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</1> inside the translation</0>",
"no-functional-example": "Translation done from a no-functional component",
"dynamic-namespaces-link": "See an example of dynamic namespace"
}
"dynamic-namespaces-link": "See an example of dynamic namespace",
"nested-example": {
"very-nested": {
"nested": "Nested example!"
}
}
}
9 changes: 7 additions & 2 deletions examples/static-site/locales/es/more-examples.json
Original file line number Diff line number Diff line change
Expand Up @@ -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</1> dentro de la traducción</0>",
"no-functional-example": "Traducción hecha desde un componente no funcional",
"dynamic-namespaces-link": "Ver un ejemplo de carga dinámica"
}
"dynamic-namespaces-link": "Ver un ejemplo de carga dinámica",
"nested-example": {
"very-nested": {
"nested": "¡Ejemplo anidado!"
}
}
}
4 changes: 3 additions & 1 deletion examples/static-site/pages_/more-examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ export default function MoreExamples() {
/>
<NoFunctionalComponent />
<br />
{t`more-examples:nested-example.very-nested.nested`}
<br />
<Link href={`/${lang}/more-examples/dynamic-namespace`}>
{t('more-examples:dynamic-namespaces-link')}
<a>{t('more-examples:dynamic-namespaces-link')}</a>
</Link>
<style jsx>{`
.red {
Expand Down
Loading

0 comments on commit fa76ce9

Please sign in to comment.