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(<Providerlocale="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 translationsNested: {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 translationsNested: {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 translationsconst existingString = t.Dropdown.title// Your translationsconst myString = t.myString// Use the "formatMessage" function to handle strings with argumentsconst 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-breaksconst 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 compatibleconst myTranslations = {'nb-NO': nbNO,'en-GB': enGB,}// Infer the type of the translationstype MyLocales = keyof typeof myTranslationstype 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 objectrender(<EufemiaProviderlocale="nb-NO"translations={{'nb-NO': nb,}}><MyApp>Eufemia components</MyApp></EufemiaProvider>,)
Cascaded object (flat object, dot-notated keys) support
- Lets say you have your translation files as JSON object/files
en.json
:
{"Modal.close_title": "Overwrite","my.string": "string {foo}"}
- 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(<EufemiaProviderlocale="nb-NO"translations={{'nb-NO': nb,'en-GB': en,}}><MyComponent /></EufemiaProvider>,)
- 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(<EufemiaProviderlocale="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 typesconst 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 localesupdate({ locales: myTranslations, locale: 'sv-SE' })return locale}render(<Provider><MyApp>...<ChangeLocale />...</MyApp></Provider>,)