rjsf-team/react-jsonschema-form

What is the recommended approach to translate labels, descriptions, etc?

Closed this issue ยท 17 comments

Prerequisites

  • I have read the documentation;
  • In the case of a bug report, I understand that providing a SSCCE example is tremendously useful to the maintainers.

Description

I am attempting to implement label/description/help translation using react-intl in a custom FieldTemplate and am trying to get the path to the current field. I can almost use the id property like id.split('_').slice(1) except field names may have _ as part of their name, and the root id name can change (uiSchema["ui:rootFieldId"]) and may contain _ also.

Is there some other way to get the path to the current property? If not, can I request the id field separator in utils toIdSchema() and ArrayField be changed to a double underscore __ similar to BEM notation. So 'myroot__foo_bar__0__qux'.split('__').slice(1) would yield ['foo_bar', '0', 'qux']? This also works for field names that begin with a single underscore as sometimes used to denote private or reserved field names like in CouchDB _id and _deleted.

Perhaps this approach is completely flawed when taking into account definitions etc. Another approach may be to recursively traverse the schema object and definitions separately, building up the path as I go, and add a title, description and help attribute to each object property.

How are others translating the labels, field titles, descriptions, help text etc?

Steps to Reproduce

N/A

Expected behavior

N/A

Actual behavior

N/A

Version

0.51.0

Hi, I'm not super familiar with react-intl, but I would have expected translating labels and things to happen at the schema layer, before it gets rendered. I wouldn't object to a PR adding a method to get the path to the current element. There's also an outstanding PR to parametrize the separator in #688, and if olzraiti's comments are addressed I would be willing to merge that too.

ugogo commented

On my side, I used a custom FieldTemplate

// FieldTemplate.jsx

const FormTemplate = ({ id, children, label, rawErrors, required, schema }) => {
...
return (
    <FormField errored={isErrored}>
      <FormLabel
        i18n={label}
        inputId={id}
        required={required}
      />

      { children }

      { !!rawErrors.length && (
        <FormErrors errors={rawErrors} />
      )}
    </FormField>
  );
// FormLabel.jsx
const FormLabel = ({ i18n, inputId, required }) => (
  <label htmlFor={inputId}>
    <FormattedMessage id={i18n} />
    { required ? '*' : null }
  </label>
);

Not sure this is the best way to do it because you have to rewrite some logic, but you'll have a full control on the displayed items, i18n included

Is there some good solution please?

I originally tried adding custom widgets and field templates etc and had a dodgy function to get the property path and attempt look up the title, description and help text during render. Getting the property path is not really possible, especially when definitions are also used.

In the end, we wrote a intlSchema method to transform the json schema (returns new object, original schema is not touched) before passing to react-jsonschema-form, updating the title, description and help properties if found in the locale text. I'm using redux, so I used this method in the redux connector when passing the schema to my react component. I also use redux-intl so I was able to easily pass all the intl messages to my helper.

I hope this points you in the right direction. I'll post a Codepen example with my recursive method soon.

Cheers,
Brendan

Here is an example Codepen with my recursive intlSchema method.

https://codepen.io/bjbrewster/pen/xQeRKR

Cheers,
Brendan

Closing this in favor of #1195.

Sorry, I misread -- ajv-i18n is only for localizing errors, but this issue is about localizing labels, descriptions, etc. of the entire form. Reopening.

lol, thanks for that. I was wondering how the other issue superseded this.

@bjbrewster your solution looks good. Based on your work, do you think there might be a way to add this functionality into the core library react-jsonschema-form (or at least make it easier to integrate internationalization libraries)?

This translations thing is a big issue.

Assumption that field value equals to field label is a poor design decision in general. For example, Angular forms have a clear distinction between field values and labels.

I'd suggest adding a separate prop for field labels and option labels.

Anyways, many thanks for a very helpful library.

After year I am handling with this issue again.
I have implemented LinguiJS but labels are crying that <Trans> macro is not string:

Warning: Failed prop type: Invalid prop `label` of type `object` supplied to `DefaultTemplate`, expected `string`.
    in DefaultTemplate (created by SchemaField)
    in SchemaField (created by ObjectField)
    in fieldset (created by DefaultObjectFieldTemplate)
    in DefaultObjectFieldTemplate (created by ObjectField)
    in ObjectField (created by SchemaField)
    in div (created by WrapIfAdditional)
    in WrapIfAdditional (created by DefaultTemplate)
    in DefaultTemplate (created by SchemaField)
    in SchemaField (created by Form)
    in form (created by Form)
    in Form (created by Context.Consumer)
    in div (created by Context.Consumer)
    in div (created by Context.Consumer)
    in div (created by Context.Consumer)
    in div (created by Layout)
    in div (created by Layout)
    in main (created by Layout)
    in div (created by Layout)
    in Layout (created by Event)
    in Event (created by _default)
    in I18nProvider (created by LangProvider)
    in LangProvider (created by _default)
    in _default
    in Suspense (created by AppContainer)
    in Container (created by AppContainer)
    in AppContainer

Please can you think to this in V2?
#1409

@landsman

After year I am handling with this issue again.
I have implemented LinguiJS but labels are crying that <Trans> macro is not string:

This might be a separate issue -- and I've seen those warnings in the console before. Could you open a new issue with a minimal reproduction of the problem? That would help.

this issue is still in open status, I haven't found any documentation or any sample given in live playground examples. Is there a recommended way to translate UI field labels as well as error messages?

n3ps commented

While waiting for a "recommended" approach, what are the drawbacks of adding a custom property (ie. translation key) in the schema and using that in a custom FieldTemplate component to lookup the translation?

You can definitely do that, its just a shame to duplicate the property names and paths when creating the translation key and also add translation keys for help and description fields if you need them.

@bjbrewster With the advent of the idSeparator property, you can now control whether to use the _ or some other delimiter. This should solve your problem. On a separate note, we are planning to provide the ability to localize the RJSF internal strings in the near future. Closing