UI localization and i18n
Reactodia has a built-in support for UI text strings localization. Each UI component in the library that displays text labels or descriptions resolves them from translation bundles via Translation interface.
Translation bundle
Localized texts are organized in a form of plain JSON objects called TranslationBundle.
The bundle have the following structure:
{
"$schema": "../i18n.schema.json",
"component_name": {
"some_action.label": "Some Action",
"some_action.title": "Performs some action",
"truncate_data.command": "Truncate Data",
"graph_edge.label": "{{start}} → {{end}}",
...
},
...
}
Built-in translation bundles references the JSON schema to validate mistyped or unknown translation keys.
This schema is available as @reactodia/workspace/i18n/i18n.schema.json
and can be used with external JSON validation tool (e.g. ajv-cli)
to check the translations.
To provide customized translation, all bundles with localized strings can be passed to DefaultTranslation instance provided with translation option to createWorkspace():
function TranslationOverride() {
const {defaultLayout} = Reactodia.useWorker(Layouts);
const [workspace] = React.useState(() => Reactodia.createWorkspace({
defaultLayout,
translation: new Reactodia.DefaultTranslation({
bundles: [
{
'default_workspace': {
'search_section_entity_types.label': 'Class Tree',
'search_section_entity_types.title': 'Class tree hierarchy',
}
},
// Fallback bundle with built-in "en" translation strings
Reactodia.DefaultTranslationBundle,
],
})
}));
return (
<Reactodia.WorkspaceProvider workspace={workspace}>
<Reactodia.DefaultWorkspace />
</Reactodia.Workspace>
);
}
Additional built-in or custom translation can be used the same way by loading the JSON bundle externally and
pass them with bundles property in the high priority to low priority order.
It is also possible to exclude default en translation @reactodia/workspace/i18n/translations/en.reactodia-translation.json by omitting DefaultTranslationBundle from bundles array:
import enUkTranslation from './en-uk.reactodia-translation.json';
import deTranslation from './de.reactodia-translation.json';
function MultipleTranslations() {
const {defaultLayout} = Reactodia.useWorker(Layouts);
const [workspace] = React.useState(() => Reactodia.createWorkspace({
defaultLayout,
translation: new Reactodia.DefaultTranslation({
bundles: [deTranslation, enUkTranslation],
}),
}));
return (
<Reactodia.WorkspaceProvider workspace={workspace}>
<Reactodia.DefaultWorkspace />
</Reactodia.Workspace>
);
}
Using translation in the custom components
The localization mechanism can be used for a custom component nested inside the Workspace by getting a Translation instance which can be used to format localizable strings.
useTranslation() hook can be used to acquire the Translation object.
In the following example, additional custom translation keys are added to the workspace to provide localizable component labels:
function MyComponent() { const t = Reactodia.useTranslation(); return ( <Reactodia.ToolbarAction title={t.text('my_component.do_action.title')} onSelect={() => alert('Done')}> {t.text('my_component.do_action.label')} </Reactodia.ToolbarAction> ); } function CustomTranslationKeys() { const {defaultLayout} = Reactodia.useWorker(Layouts); const [workspace] = React.useState(() => Reactodia.createWorkspace({ defaultLayout, translation: new Reactodia.DefaultTranslation({ bundles: [ { 'my_component': { 'do_action.label': 'Do the impossible!', 'do_action.title': 'Perform the impossible action', } }, Reactodia.DefaultTranslationBundle, ], }), })); return ( <div className='reactodia-live-editor'> <Reactodia.WorkspaceProvider workspace={workspace}> <Reactodia.DefaultWorkspace actions={<MyComponent />} /> </Reactodia.WorkspaceProvider> </div> ); } render(<CustomTranslationKeys />);
Translation context
Translation mechanism can be used outside the workspace context in other parts of an application when needed by establishing the context with <TranslationProvider> in order to make use of useTranslation() hook:
function App() {
const translation = React.useMemo(() => new Reactodia.DefaultTranslation({
bundles: [/*...*/],
}), []);
return (
<Reactodia.TranslationProvider translation={translation}>
{/* app components */}
</Reactodia.TranslationProvider>
);
}