Skip to main content

i18n

note

Please note that the renderer sets themselves are not yet translatable. You can find the current status here: https://github.com/eclipsesource/jsonforms/issues/1826

The translate functionality of JSON Forms is integrated into the core component. In order to translate JSON Forms, you need to set a translation function and provide it to the JSON Forms component:

const translator = (key, defaultMessage) => {
console.log(`Key: ${key}, Default Message: ${defaultMessage}`);
return defaultMessage;
};
const [locale, setLocale] = useState<'de'|'en'>('de');
const translation = useMemo(() => translator(locale), [locale]);
<JsonForms
i18n={{locale: locale, translate: translation}}
...
/>

The i18n prop consist of three components: locale, translate and translateError.

locale#

Allows to specify the current locale of the application. This can be used by renderers to render locale specific UI elements, for example for locale-aware formatting of numbers.

translate#

Allows to provide a translation function, which handles the actual translation.

caution

The translate function should be side effect free and should be stable (memoized) to avoid unnecessary re-renderings, i.e. the translate function should only change if there are new translations.

The type of the translate is

(key: string, defaultMessage: string | undefined) => string | undefined)

and there for has the following parameters:

key#

The key is used to identify the string, that needs to be translated. It can be set using the UI Schema, the JSON Schema or is generated by default based on the property path.

UI Schema option#

The key can be set via the i18n UI Schema option:

{
"type": "Control",
"label": "name",
"scope": "#/properties/name",
"options": {
"i18n": "customName"
}
}

Therefore the translation will be invoked with customName.label & customName.description.

JSON Schema#

The key can also be set with the custom JSON Schema i18n option:

{
"name": {
"type": "string",
"i18n": "myCustomName"
}
}

Therefore the translation will be invoked with myCustomName.label & myCustomName.description.

Default: Property path#

If none of the above is set, the property path will be used as the key.

{
"properties": {
"firstName": {
"type": "string"
},
"address": {
"type": "object",
"properties": {
"street": {
"type": "string"
}
}
},
"comments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
}
}
}
}
}

The paths in the above example would be:

  • firstName.label & firstName.description
  • address.label & address.description
  • address.street.label & address.street.description
  • comments.message.label & comments.message.description (the path for arrays will not contain indices)

defaultMessage#

The default message is provided by JSON Forms and can act as a fallback or could be translated.

note

If the defaultMessage is undefined you should also return undefined if you don't have a translation for the given key. Returning an empty string (or something similar) instead may result in undesired behavior. JSON Forms will use undefined when the message could be skipped or another more generic key could be tried.

values#

values can contain additional context for the current translation. For example all error translations will have the AJV error object as part of the values object.

translateError#

The translateError function is called whenever a single message is to be extracted from an AJV error object.

The type of the translateError function is

(error: ErrorObject, translate: Translator, uischema?: UISchemaElement) => string
  • The error is the AJV error object
  • translate is the i18n translate function handed over to JSON Forms
  • In cases where a UI Schema Element can be correlated to an error it will also be handed over
  • The translateError function always returns a string

Usually this method does not need to be customized as JSON Forms already provides a sensible default implementation. A reason to customize this method could be to integrate third party frameworks like ajv-i18n.

For more information about how errors can be customized, see the following section:

Error Customizations#

For each control a list of errors is determined. This section describes the default behavior of JSON forms to offer translation support for them.

<i18nkey>.error.custom#

Before invoking the translateError function, JSON Forms will check whether a <i18nkey>.error.custom translation exists. This is useful if there are many JSON Schema validaton keywords defined for a single property, but a single cohesive message shall be displayed.

If no <i18nkey>.error.custom message is returned by the translate function, translateError will be called for each AJV error and the results combined.

The default implementation of translateError will invoke translate multiple times to determine the best message for the given error. Therefore it's usually not necessary to customize translateError itself. By default error it works like this:

<i18nkey> in the sections below refers to the key of the field (see key section above).

Evaluation order#

<i18nkey>.error.<keyword>#

Example keys: name.error.required, address.street.error.pattern

The default translateError will first look for a concrete message for a specific field and a specific error type.

error.<keyword>#

Example keys: error.required, error.pattern

After checking field specific translations, translateError will then look for form-wide translations of errors, independent of each respective field. This is useful to customize for example required or pattern messages for all properties.

error message#

At last the default translateError implementation will check whether the message of the error object has a specific translation.

Default AJV error message#

If none of the above apply, the message provided by the AJV error object will be used.

Example#

Consider the following schema for an object attribute:

{
phone: {
type: "string",
minLength: 10,
pattern: "^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$"
}
}

The order in which the error keys are evaluated is the following:

  • phone.error.custom: if this is set, the pattern and minLength errors will be ignores and just this message is used
  • phone.error.pattern & phone.error.minLength
  • error.pattern & error.minLength

Enum translation#

Enum translations are based on the respective entries:

  • For JSON Schema enum, the stringified value is used.
  • For JSON Schema oneOf enums which consist of (title, const) pairs a specialized i18n key or title is used.

Therefore, in order to translate enum values, an additional key is checked for each enum entry. For example: Let's assume we have an enum attribute gender, which looks like this:

{
gender: {
type: "string",
enum: ["male", "female", "other"]
}
}

In this case the translate function will be invoked with the keys gender.male, gender.female and gender.other to translate these enum values. In case gender had an i18n property, it would be used instead, i.e. <i18nkey>.male etc.

Let's assume we have a oneOf enum attribute gender which looks like this:

{
gender: {
oneOf: [
{
title: "Male",
const: 0
},
{
title: "Female",
const: "f",
i18n: "fem"
},
{
const: null
}
]
}
}

Here the requested keys are:

  • gender.Male - property path + title of the oneOf entry
  • fem - direct usage of the i18n property for the oneOf entry
  • null - the title attribute is missing, therefore the null value is stringified to 'null'.

Access translation in custom renderer sets#

If you want to directly access the i18n properties within a custom renderer, you can use the JSON Forms context for that:

const ctx = useJsonForms();
const locale = ctx.i18n.locale;
const translate = ctx.i18n.translate;
const translateError = ctx.i18n.translateError;

With this you can for example change phone number patterns based on the current locale for validation.

Example#


Current language: de