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 for the following locales:
NOTE: The sv-SE
translation are in a beta phase, as it's not 100% finalised and may change when officially approved by UX.
You can easily change one, some or all of them by using a React provider – the Eufemia Provider.
Here are the default strings located:
// Included by defaultimport enGB from '@dnb/eufemia/shared/locales/en-GB'import nbNO from '@dnb/eufemia/shared/locales/nb-NO'import enGB_forms from '@dnb/eufemia/extensions/forms/constants/locales/en-GB'import nbNO_forms from '@dnb/eufemia/extensions/forms/constants/locales/nb-NO'// Additional locales you can addimport svSE from '@dnb/eufemia/shared/locales/sv-SE'import svSE_forms from '@dnb/eufemia/extensions/forms/constants/locales/sv-SE'
How to 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 to 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 to 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="sv-SE" title="Svenska" /><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 to add Eufemia provided locales
Eufemia components
Eufemia provides component translations for the following locales:
NOTE: The sv-SE
translation are in a beta phase, as it's not 100% finalised and may change when officially approved by UX.
To include e.g. sv-SE
you can use the following code:
import { Provider } from '@dnb/eufemia/shared'import svSE from '@dnb/eufemia/shared/locales/sv-SE'render(<Provider translations={svSE} locale="sv-SE">Your app</Provider>,)
Eufemia Forms
Eufemia provides forms translations for the following locales:
NOTE: The sv-SE
translation are in a beta phase, as it's not 100% finalised and may change when officially approved by UX.
You can provide forms translations to the translations
property within the Form.Handler component like this:
import { Form } from '@dnb/eufemia/src/extensions/forms'import svSE_forms from '@dnb/eufemia/extensions/forms/constants/locales/sv-SE'render(<Form.Handler translations={svSE_forms} locale="sv-SE">Your form</Form.Handler>,)
How ever, instead of providing the forms translations per form, you can also provide them globally using the Provider
component.
If so, you can use the mergeTranslations
function from @dnb/eufemia/shared
to merge the forms translations with the shared translations like this:
import { Provider, mergeTranslations } from '@dnb/eufemia/shared'import svSE from '@dnb/eufemia/shared/locales/sv-SE'import svSE_forms from '@dnb/eufemia/extensions/forms/constants/locales/sv-SE'const translations = mergeTranslations(svSE, svSE_forms)render(<Provider translations={translations} locale="sv-SE">Your app, including Eufemia Forms</Provider>,)
How to add new locales
Create a new file (nn-NO.js
) containing all the strings:
export default {'nn-NO': {GlobalError: {404: {title: 'Me finn ikkje sida du leitar etter …',},},},}
And add the file, like so:
import Provider from '@dnb/eufemia/shared/Provider'import myTranslations from './locales/nn-NO'render(<Provider translations={myTranslations}><MyApp>Eufemia components</MyApp></Provider>,)
Add or update the locales during runtime
import Provider from '@dnb/eufemia/shared/Provider'import Context from '@dnb/eufemia/shared/Context'import myTranslations from './locales/nn-NO'const ChangeLocale = () => {const { update, locale } = React.useContext(Context)// Add new localesupdate({ locales: myTranslations, locale: 'nn-NO' })return locale}render(<Provider><MyApp>...<ChangeLocale />...</MyApp></Provider>,)