onChange callback not reflecting translated error messages

Hey! Using JSONForms v3.4.1 here in a react project with a custom renderer set.

I am currently using JSONForms’ internationalization support (i18n) to handle translation of AJV errors. I am attempting to leverage the onChange callback to show an aggregate view of translated error messages outside of JSONForms. However, the errors array that is provided to onChange does not reflect the translated messages that appear under each control. The reason for this appears to be translations are directly passed to each individual control during mapping of state (renderers.ts).

I’ve have tried overriding the content of error within my custom translateError function but this results in a endless cycle of re-rendering.

Barring injecting middleware, or some other custom logic, and performing re-translation, is there any built-in way of achieving this behavior or am I missing something?

Any suggestions would be appreciated - thanks!

Hi @dmar
That is an interesting discovery. Unfortunately, AFAIK you are not missing something and there currently is no builtin approach to get the translated errors in the onChange method.

Thus, I would suggest either translating the errors again outside of JSON Forms or trying out whether doing this in a middleware (see documentation) works without triggering and endless re-render loop. You could try to react to the UPDATE_DATA, UPDATE_CORE and INIT actions and then replace the message property of each ErrorObject inline.

Best regards,
Lucas

This should work. I did the same in the past with ajv-i18n to translate the errors, see here. Can you post how you did try it?

Sadly no, I think using the middleware to translate errors on the fly is the best approach. Alternatively using the error translator to permanently modify the errors could be a viable approach.

Thanks for the reply @sdirix / @lucas-koehler,

My translateError function looks something like this:

const errorTranslator = (error, t, uischema) => {
  const errorLocalized = getLocalizedError(...);
  
  // Override the error from AJV
  error.message = errorLocalized;

  return errorLocalized;
}

But, upon further review, the translateError override isn’t the only culprit here. In my onChange function, I call the set function of a state variable called resolvedErrors so I’m able to render them.That set function seems to be what trips this useEffect hook in JsonFormsContext.tsx.

For the moment, I’ve found the following work around:

const onChange = ({data, errors}) => {
 const errorsEqual = resolvedErrors?.length === errors?.length &&
    resolvedErrors.every((error, index) => {
      return error.message === errors[index].message;
    });

  if (!errorsEqual) {
    setResolvedErrors(errors);
  }
}

This seems to prevent the endless re-render cycle. But what I’m still confused about is the cycle is caused by both the useState hook and the override in translateError working in conjunction. I’ve found this is also the case if the override is performed from within a middleware.

On it’s own, your onChange should not trigger an endless rendering cycle. However if you hand over a new instance of schema, data or ajv with each render call to JSON Forms, then you will end up in an endless cycle. That’s because JSON Forms will determine that it needs to re-validate and produce a new onChange message, you then set a state variable and hand over a new schema, data, or ajv to JSON Forms etc. etc.