Skip to content

Localization

The default constants are defined in the /shared/defaults.js file.

  • The default locale of all components texts is: nb-NO.
  • The default currency is: NOK

Supported component translations

Eufemia components comes with a set of default translated strings.

You can easily change one, some or all of them by using a React provider – the Eufemia Provider.

Here are the default strings located:

import enGB from '@dnb/eufemia/shared/locales/en-GB'
import nbNO from '@dnb/eufemia/shared/locales/nb-NO'

How set the locale

In React based apps, use the shared Eufemia provider:

import Provider from '@dnb/eufemia/shared/Provider'
const myLocale = 'en-GB'
render(
<Provider locale={myLocale}>
<MyApp>Eufemia components</MyApp>
</Provider>,
)

For component based locale, you can also make use of the lang attribute – if really needed:

import Provider from '@dnb/eufemia/shared/Provider'
render(
<Provider locale="en-GB">
<MyApp>
<HelpButton lang="nb-NO" />
</MyApp>
</Provider>,
)

How set locale progressively

You can easily enhance or change translated strings progressively:

import Provider from '@dnb/eufemia/shared/Provider'
render(
<Provider
locale="nb-NO"
translations={{
'nb-NO': {
Modal: { close_title: 'Something' },
},
}}
>
<MyApp>Eufemia components</MyApp>
</Provider>,
)

How change the locale during runtime

You can even change the locale during runtime. Find more info in the Provider docs.

import { Field } from '@dnb/eufemia/extensions/forms'
import Provider from '@dnb/eufemia/shared/Provider'
import Context from '@dnb/eufemia/shared/Context'
const ChangeLocale = () => {
const { setLocale, locale } = React.useContext(Context)
return (
<Field.Selection value={locale} onChange={(value) => setLocale(value)}>
<Field.Option value="nb-NO" title="Norsk" />
<Field.Option value="en-GB" title="English (GB)" />
</Field.Selection>
)
}
render(
<Provider>
<MyApp>
<ChangeLocale />
</MyApp>
</Provider>,
)

Provide your own translations

You can provide your own translations by using the shared Provider. Translation strings with several levels of depth can be given as a flat object with dot-notation, or as a nested object (cascaded).

import Provider from '@dnb/eufemia/shared/Provider'
const nbNO = { myString: 'Min egendefinerte streng' }
const enGB = {
// Cascaded translations
Nested: {
stringWithArgs: 'My custom string with an argument: {myKey}',
},
// Flat translations
'Nested.stringWithArgs': 'My custom string with an argument: {myKey}',
}
const myTranslations = {
'nb-NO': nbNO,
'en-GB': enGB,
}
render(
<Provider translations={myTranslations} locale="en-GB">
<MyApp>
<MyComponent />
</MyApp>
</Provider>,
)

Consume translations in your components

You can use the useTranslation hook to get the strings from the shared context. The hook returns an object with the strings and a formatMessage function you can use to get the translated strings with arguments.

import { useTranslation } from '@dnb/eufemia/shared'
const myTranslations = {
'nb-NO': { myString: 'Min egendefinerte streng' },
'en-GB': {
// Cascaded translations
Nested: {
stringWithArgs: 'My custom string with an argument: {myKey}',
},
// Flat translations
'Nested.stringWithLinebreaks':
'My custom string with a {br}line-break',
},
}
const MyComponent = () => {
const t = useTranslation<typeof myTranslations>()
// Internal translations
const existingString = t.Dropdown.title
// Your translations
const myString = t.myString
// Use the "formatMessage" function to handle strings with arguments
const myStringWithArgsA = t.formatMessage(t.Nested.stringWithArgs, {
myKey: 'myValue',
})
// You can also get the string with a key (dot-notation)
const myStringWithArgsB = t.formatMessage('Nested.stringWithArgs', {
myKey: 'myValue',
})
// Render line-breaks
const jsxOutput = t.renderMessage(t.Nested.stringWithLinebreaks)
return <>MyComponent</>
}
render(
<Provider translations={myTranslations} locale="en-GB">
<MyApp>
<MyComponent />
</MyApp>
</Provider>,
)

Good to know: You can consume the strings with a dot-notated key, directly from the formatMessage function:

formatMessage('myGroup.subString')

TypeScript support

import Provider, { Locales } from '@dnb/eufemia/shared/Provider'
const nbNO = {
myString: 'Min egendefinerte streng',
}
const enGB = {
myString: 'My custom string',
} satisfies typeof nbNO // Ensure the types are compatible
const myTranslations = {
'nb-NO': nbNO,
'en-GB': enGB,
}
// Infer the type of the translations
type MyLocales = keyof typeof myTranslations
type MyTranslation = (typeof myTranslations)[MyLocales]

How to combine with other tools

You can easily combine the locales support it with other translation tools, like react-intl.

Like, having the Eufemia components strings inside a JSON object/file en.json:

{
"Modal.close_title": "Overwrite",
"other.string": "{foo} ({bar} of {max})"
}

and use it like this:

import EufemiaProvider from '@dnb/eufemia/shared/Provider'
import nb from './nb.json' // Has to be an JavaScript object
render(
<EufemiaProvider
locale="nb-NO"
translations={{
'nb-NO': nb,
}}
>
<MyApp>Eufemia components</MyApp>
</EufemiaProvider>,
)

Cascaded object (flat object, dot-notated keys) support

  1. Lets say you have your translation files as JSON object/files en.json:
{
"Modal.close_title": "Overwrite",
"my.string": "string {foo}"
}
  1. and use it with a React hook like this:
import {
useTranslation,
Provider as EufemiaProvider,
} from '@dnb/eufemia/shared'
import nb from './nb.json'
import en from './en.json'
const MyComponent = () => {
const str = useTranslation('my.string', {
foo: 'bar',
})
return str
}
render(
<EufemiaProvider
locale="nb-NO"
translations={{
'nb-NO': nb,
'en-GB': en,
}}
>
<MyComponent />
</EufemiaProvider>,
)
  1. or as a React component:
import {
Translation,
Provider as EufemiaProvider,
} from '@dnb/eufemia/shared'
import nb from './nb.json'
import en from './en.json'
render(
<EufemiaProvider
locale="nb-NO"
translations={{
'nb-NO': nb,
'en-GB': en,
}}
>
<Translation id="my.string" foo="bar" />
</EufemiaProvider>,
)

For TypeScript support, you can use the Translation component with a function. You may also want to make a wrapper, so you can use your own translation types:

import {
Translation,
TranslationProps,
Provider as EufemiaProvider,
} from '@dnb/eufemia/shared'
const translations = {
'nb-NO': { my: { string: 'streng {foo}' } },
'en-GB': { my: { string: 'string {foo}' } },
}
type Translation = (typeof translations)[keyof typeof translations]
// Make a wrapper, so we can use your translation types
const MyTranslation = (props: TranslationProps<Translation>) => (
<Translation {...props} />
)
render(
<EufemiaProvider locale="nb-NO" translations={translations}>
<MyTranslation id={(t) => t.my.string} foo="bar" />
</EufemiaProvider>,
)

How add new locales

Create a new file (sv-SE.js) containing all the strings:

export default {
'sv-SE': {
DatePicker: {
submit_button_text: 'OK',
},
Modal: {
close_title: 'Stänga',
},
Logo: {
alt: 'DNB Logo',
},
},
}

And add the file, like so:

import Provider from '@dnb/eufemia/shared/Provider'
import myTranslations from './locales/sv-SE'
render(
<Provider translations={myTranslations}>
<MyApp>Eufemia components</MyApp>
</Provider>,
)

or add/update the locales during runtime:

import Provider from '@dnb/eufemia/shared/Provider'
import Context from '@dnb/eufemia/shared/Context'
import myTranslations from './locales/sv-SE'
const ChangeLocale = () => {
const { update, locale } = React.useContext(Context)
// Add new locales
update({ locales: myTranslations, locale: 'sv-SE' })
return locale
}
render(
<Provider>
<MyApp>
...
<ChangeLocale />
...
</MyApp>
</Provider>,
)