Skip to content

Commit

Permalink
refactor: don't auto-merge translations
Browse files Browse the repository at this point in the history
  • Loading branch information
Benehiko committed Oct 11, 2023
1 parent 999d392 commit 005c5a6
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 51 deletions.
77 changes: 56 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,50 +85,85 @@ your browser!
## Internalization (i18n)

Ory Elements supports translations out-of-the-box with the `IntlProvider`. The
`IntlProvider` is required by Ory Elements and allows the language to be mapped
correctly, specifically American English.
`IntlProvider` is required by Ory Elements and maps American English as the
default language.

```tsx
import { ThemeProvider } from "@ory/elements"

const RootComponent = () => {
return (
<ThemeProvider>
<IntlProvider>// children</IntlProvider>
</ThemeProvider>
)
}
```

To switch the language the UI should use, you can pass in the language code
through the `locale` prop.

```tsx
import { ThemeProvider } from "@ory/elements"

const RootComponent = () => {
return (
<ThemeProvider>
<IntlProvider locale="nl" defaultLocale="en">
// children
</IntlProvider>
</ThemeProvider>
)
}
```

The `IntlProvider` has the ability to accept custom translations through a
`CustomLanguageFormats` type. You can specify to the `<IntlProvider>` that you
would like to use a `CustomTranslations` instead of the
`SupportedLanguages (default)` type which will require providing the
`customTranslations` prop.

When providing a translation, it is important to note that it will be merged
with an existing supported language, with your provided values taking precedent.
This is to allow modifying only one key from an already supported language,
rather than modifying the entire translation file :)
More information on the Ory messages can be found
[in the docs](https://www.ory.sh/docs/kratos/concepts/ui-user-interface#ui-message-codes)

When providing a translation, you can merge an existing supported locale from
Ory Elements so that you do not need to provide all keys for the entire
tranlsation file :)

For example, I want to adjust the English translation to say `Email` instead of
`ID` when a Login card is shown. So I provide the key-value pair
`"identities.messages.1070004": "Email"`. Ory Elements will now use the updated
value `Email` instead of `ID` for this specific label, but will still keep the
other defaults in-tact.

Another scenario is when we add partial keys to an unsupported language such as
`af` (Afrikaans). I add my key-value only for one entry
`"identities.messages.1070004": "E-posadres"`, however, the language has no
default inside Ory Elements. As a safe-guard we fall-back to English for the
rest of the labels.

More information on the Ory messages can be found
[in the docs](https://www.ory.sh/docs/kratos/concepts/ui-user-interface#ui-message-codes)
`"identities.messages.1070004": "Email"`. Another unsupported language such as
`af` (Afrikaans) is also added only for one entry
`"identities.messages.1070004": "E-posadres"`. We merge the supported `en`
locale from Ory Elements so that we don't need to provide all key-value pairs.

```tsx
import { ThemeProvider, IntlProvider, CustomTranslations } from "@ory/elements"
import {
ThemeProvider,
IntlProvider,
CustomTranslations,
locales,
} from "@ory/elements"

const RootComponent = () => {
const myCustomTranslations: CustomLanguageFormats = {
...locales,
en: {
"login.title": "Login",
...locales.en,
"identities.messages.1070004": "Email",
},
af: {
// fallback to English on other labels
...locales.en,
"identities.messages.1070004": "E-posadres",
},
}

return (
<ThemeProvider>
<IntlProvider<CustomTranslations>
customTranslations={myCustomTranslations}
locale="en"
locale="af"
defaultLocale="en"
>
// children
Expand Down
12 changes: 5 additions & 7 deletions examples/nextjs-spa/src/components/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
IntlProvider,
Nav,
ThemeProvider,
locales,
} from "@ory/elements"
import Head from "next/head"

Expand All @@ -13,27 +14,24 @@ interface LayoutProps {

export default function Layout({ children }: LayoutProps) {
// adds custom translations labels to the default translations
// this merges the custom translations with the default translations
// if a custom language is provided, but no standard translation
// exists, the english translation will be merged instead for missing values.
//
// For example, if you provide a custom translation for the "login.title" label
// in the "af" language (Afrikaans), but no standard translation exists for "af",
// the english translation will be used for the remaining labels.
//
// You can also contribute your custom translations to the Ory Elements project
// by submitting a pull request to the following repository:
// https://github.com/ory/elements
const customTranslations: CustomLanguageFormats = {
en: {
...locales.en,
"login.title": "Login",
"identities.messages.1070004": "Email",
},
nl: {
...locales.nl,
"login.title": "Inloggen",
"identities.messages.1070004": "E-mail",
},
af: {
// merging English since no default Afrikaans translations are available
...locales.en,
"login.title": "Meld aan",
"identities.messages.1070004": "E-posadres",
},
Expand Down
12 changes: 5 additions & 7 deletions examples/preact-spa/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
CustomTranslations,
IntlProvider,
ThemeProvider,
locales,
} from "@ory/elements-preact"

// Ory Elements
Expand All @@ -33,27 +34,24 @@ import "@ory/elements-preact/style.css"

const Main = () => {
// adds custom translations labels to the default translations
// this merges the custom translations with the default translations
// if a custom language is provided, but no standard translation
// exists, the english translation will be merged instead for missing values.
//
// For example, if you provide a custom translation for the "login.title" label
// in the "af" language (Afrikaans), but no standard translation exists for "af",
// the english translation will be used for the remaining labels.
//
// You can also contribute your custom translations to the Ory Elements project
// by submitting a pull request to the following repository:
// https://github.com/ory/elements
const customTranslations: CustomLanguageFormats = {
en: {
...locales.en,
"login.title": "Login",
"identities.messages.1070004": "Email",
},
nl: {
...locales.nl,
"login.title": "Inloggen",
"identities.messages.1070004": "E-mail",
},
af: {
// merging English since no default Afrikaans translations are available
...locales.en,
"login.title": "Meld aan",
"identities.messages.1070004": "E-posadres",
},
Expand Down
12 changes: 5 additions & 7 deletions examples/react-spa/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
IntlProvider,
CustomTranslations,
CustomLanguageFormats,
locales,
} from "@ory/elements"

// optional global css reset
Expand Down Expand Up @@ -34,27 +35,24 @@ import "@ory/elements/assets/jetbrains-mono-font.css"
import "@ory/elements/style.css"

// adds custom translations labels to the default translations
// this merges the custom translations with the default translations
// if a custom language is provided, but no standard translation
// exists, the english translation will be merged instead for missing values.
//
// For example, if you provide a custom translation for the "login.title" label
// in the "af" language (Afrikaans), but no standard translation exists for "af",
// the english translation will be used for the remaining labels.
//
// You can also contribute your custom translations to the Ory Elements project
// by submitting a pull request to the following repository:
// https://github.com/ory/elements
const customTranslations: CustomLanguageFormats = {
en: {
...locales.en,
"login.title": "Login",
"identities.messages.1070004": "Email",
},
nl: {
...locales.nl,
"login.title": "Inloggen",
"identities.messages.1070004": "E-mail",
},
af: {
// merging English since no default Afrikaans translations are available
...locales.en,
"login.title": "Meld aan",
"identities.messages.1070004": "E-posadres",
},
Expand Down
14 changes: 5 additions & 9 deletions src/react-components/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ export type CustomLanguageFormats = {

export interface CustomTranslations {
customTranslations: Partial<CustomLanguageFormats>
locale?: (typeof LanguageCodes)[number]
defaultLocale?: (typeof LanguageCodes)[number]
locale: (typeof LanguageCodes)[number]
defaultLocale: (typeof LanguageCodes)[number]
}

const isCustomTranslations = (o: unknown): o is CustomTranslations => {
Expand Down Expand Up @@ -226,17 +226,13 @@ export const IntlProvider = <

const intlProps = isCustomTranslations(props)
? {
locale: props.locale ?? "en",
locale: props.locale,
defaultLocale: props.defaultLocale,
messages: merge(
{},
translation,
props.customTranslations[props.locale ?? "en"],
),
messages: props.customTranslations[props.locale],
}
: {
locale: props.locale ?? "en",
defaultLocale: props.defaultLocale,
defaultLocale: props.defaultLocale ?? "en",
messages: translation,
}

Expand Down

0 comments on commit 005c5a6

Please sign in to comment.