react-jsonschema-formにて、バリデーションのエラーメッセージをローカライズしてみる

これは「react-jsonschema-formのカレンダー | Advent Calendar 2023 - Qiita」の11日目の記事です。

今回は、react-jsonschema-form (RJSF) にて、バリデーションのエラーメッセージをローカライズしてみます。

  目次

 

環境

  • react-jsonschema-form 5.15.0
  • React 18.2.0
  • React Router 6.20.1
  • ajv-i18n 4.2.0

 

RJSFのバリデーションエラーメッセージのローカライズについて

RJSFのバリデーションでは、

より、RJSFでもローカライズが可能です。
Validation | react-jsonschema-form

 
ただ、RJSFとは別に ajv-i18n をインストールする必要があります。

# インストール
$ npm install ajv-i18n

added 5 packages, removed 4 packages, changed 2 packages, and audited 297 packages in 3s

55 packages are looking for funding
  run `npm fund` for details

1 moderate severity vulnerability

To address all issues, run:
  npm audit fix

Run `npm audit` for details.


# moderate severity vulnerabilityが表示されたので、画面に表示されたコマンドを実行
$ npm audit fix

changed 2 packages, and audited 297 packages in 2s

55 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

 

ajv-i18nにおける、日本語の対応状況

ajv-i18nリポジトリにあるREADMEには、localeごとの対応状況が記載されています。
https://github.com/ajv-validator/ajv-i18n

これによると、日本語の場合 JSON Schema draft 4 までサポートしているようでした。

 
ajv-i18nJSON Schema draft 4 サポートだとしたら、RJSFではどのように表示されるか気になりました。

そこで、

  • draft 4 に対応している minimum
  • draft 6 で対応している const

の入力項目を用意して動作を確認してみます。

import {RJSFSchema} from "@rjsf/utils";
import Form from "@rjsf/mui";
import {customizeValidator} from "@rjsf/validator-ajv8";
import localizer from 'ajv-i18n' // npm installが必要

export const NotExistsLocalizerForm = () => {
  const schema: RJSFSchema = {
    title: "Not Exists Localizer Form",
    type: "object",
    required: [],
    properties: {
      stringInput: {
        type: "string",
        const: "りんご"
      },
      integerInput: {
        type: "integer",
        minimum: 100
      }
    }
  }

  const validator = customizeValidator({}, localizer.ja)

  return (
    <div style={{width: '400px'}}>
      <Form
        schema={schema}
        validator={validator}
        noHtml5Validate
      />
    </div>
  )
}

 
その結果、

  • minimumは日本語化された
  • constは日本語化されず、英語となった

となりました。

 

JSON Schema draft 6以降のメッセージを日本語化する

JSON Schema draft 6以降のメッセージだけが英語というのも見栄えが良くないので、日本語化する方法を探してみます。

まず、 avj-i18n の実装を見たところ、翻訳データは以下のファイルに記載されていました。
https://github.com/ajv-validator/ajv-i18n/blob/master/messages/index.js

このファイルについて、 localizeディレクトリにあるREADMEを見ると

This folder contains compiled localization functions.

Do not edit *.js files directly, edit JSON Schema messages in messages/index.js and JSON Type Definition messages in messages/jtd.js.

If this folder doesn't have any locale sub-folders, run npm run build.

https://github.com/ajv-validator/ajv-i18n/tree/master/localize

とあったことから、自分でカスタマイズしたものを導入するのは難しそうでした。

 
そこで、日本語化する方法としては以下の2つが考えてみました。

  • 自分でlocalizerを作る
  • バリデーションのエラーメッセージを変更する

 

自分でlocalizerを作る

まずは、RJSFのLocalization (L12n) supportページにあった、自分でlocalizerを作る方法をためします。
https://rjsf-team.github.io/react-jsonschema-form/docs/usage/validation/#localization-l12n-support

 
最初に、const だけメッセージを差し替える localizer を作ります。

const localizer = (errors: null | ErrorObject[] = []) => {
  if (!(errors && errors.length)) return;

  errors.forEach(function (error) {
    let outMessage = ''

    switch (error.keyword) {
      case 'const': {
        outMessage = "指定した文字を入力してください"
        break
      }

      default: {
        outMessage = error.message.toString()
      }
    }

    error.message = outMessage
  })
}

 
続いて、 customizeValidator 関数を使ってvalidatorを生成し、Formのpropsに渡します。

const validator = customizeValidator({}, localizer)

return (
  <div style={{width: '400px'}}>
    <Form
      schema={schema}
      validator={validator}
      noHtml5Validate
    />
  </div>
)

 
動かしてみたところ、

  • const のエラーメッセージは日本語に差し替わった
  • minimum のエラーメッセージは英語になった

となりました。

RJSFのドキュメントに

You must process all the cases which you need by yourself.

とあった通り、自分でlocalizerを作る場合はすべてのキーを用意する必要があるようです。

 

バリデーションのエラーメッセージを変更する

もう一つは、バリデーションのエラーメッセージを変更する方法です。

これは10日目でふれた、Formのprops transformErrors を使う方法です。

 
今回は、 error.name === "const" のときに、エラーメッセージを差し替える関数を用意します。

const transformErrors = (errors: RJSFValidationError[], _uiSchema: typeof schema) => {
  return errors.map((error) => {
    if (error.name === "const") {
      error.message = "指定した文字を入力してください"
      error.stack = "[Stack] 指定した文字を入力してください"
    }

    return error
  })
}

 
あとは、この関数と customizeValidator で生成したvalidatorをFormに渡します。

const validator = customizeValidator({}, localizer.ja)

return (
  <div style={{width: '400px'}}>
    <Form
      schema={schema}
      validator={validator}
      transformErrors={transformErrors}
      noHtml5Validate
    />
  </div>
)

 
動かしてみたところ、

  • const のエラーメッセージは transformErrors 由来
  • minimum のエラーメッセージは localizer.ja 由来

となり、両方のメッセージとも日本語化されました。

 

ソースコード

Githubにあげました。
https://github.com/thinkAmi-sandbox/rjsf_advent_calendar_2023

今回のプルリクはこちら。
https://github.com/thinkAmi-sandbox/rjsf_advent_calendar_2023/pull/10