React 今更だけど改めて Validation ライブラリ yup の日本語化
React + Typescript + MUIv5 + React Hook Form + yup で開発環境を作成しています。
今回は yup の日本語化についての記事です。
yupのバージョン:0.32.11
yup の日本語化についてはいくつか記事がヒットしましたが、アプリケーションへの導入方法についての情報が見つからなかったので、改めて記事にしました。
yup の日本語化
ロケールが定義できる項目
yup の locale.d.ts ファイルを見てみると下記のような定義になっています。
mixed、string、number、date、boolean、object、array についてロケールが定義できます。
export interface LocaleObject {
mixed?: MixedLocale;
string?: StringLocale;
number?: NumberLocale;
date?: DateLocale;
boolean?: BooleanLocale;
object?: ObjectLocale;
array?: ArrayLocale;
}
mixed、string、number、date、boolean、object、array のそれぞれのロケールを見てみます。
日本語ロケールは以下の項目に定義できることがわかります。
export interface MixedLocale {
default?: Message;
required?: Message;
oneOf?: Message<{values: any;}>;
notOneOf?: Message<{values: any;}>;
notType?: Message;
defined?: Message;
}
export interface StringLocale {
length?: Message<{length: number;}>;
min?: Message<{min: number;}>;
max?: Message<{max: number;}>;
matches?: Message<{regex: RegExp;}>;
email?: Message<{regex: RegExp;}>;
url?: Message<{regex: RegExp;}>;
uuid?: Message<{regex: RegExp;}>;
trim?: Message;
lowercase?: Message;
uppercase?: Message;
}
export interface NumberLocale {
min?: Message<{min: number;}>;
max?: Message<{max: number;}>;
lessThan?: Message<{less: number;}>;
moreThan?: Message<{more: number;}>;
positive?: Message<{more: number;}>;
negative?: Message<{less: number;}>;
integer?: Message;
}
export interface DateLocale {
min?: Message<{min: Date | string;}>;
max?: Message<{max: Date | string;}>;
}
export interface BooleanLocale {
isValue?: Message;
}
export interface ObjectLocale {
noUnknown?: Message;
},
export interface ArrayLocale {
length?: Message<{length: number;}>;
min?: Message<{min: number;}>;
max?: Message<{max: number;}>;
}
日本語を定義する
上記で確認した 「ロケールが定義できる項目」 を参考に日本語を定義していきます。
日本語の定義の仕方
たとえば上記 locale.d.ts ファイル MixedLocale の required プロパティを確認します。
export interface MixedLocale {
required: Message;
}
この場合の日本語定義は以下のようになります。
required: (prm: MessageParams) => {`${prm.label}は必須入力です`}
MessageParams には label 以外にも以下のようなものが定義されています。
export interface MessageParams {
path: string; // 変数名
value: any;
originalValue: any;
label: string;
type: string;
}
たとえば検証スキーマを下記のように書いたとします。
MessageParams の pathは「name」に、label は「名称」に、value には入力値がセットされます。
export const createSchema = yup.object({
name: yup.string().label('名称').required(),
})
次に locale.d.ts ファイル NumberLocale の min プロパティを確認します。
Message のジェネリクスで、{min: number;}
が追加定義されています。
export interface NumberLocale {
min?: Message<{min: number;}>;
}
この場合の日本語定義を MessageParams & {min: number}
とすることで、追加の値が min プロパティにセットされます。
required: (prm: MessageParams & {min: number}) => {`${prm.label}は${prm.min}以上で入力してください`}
検証スキーマを下記のようにすると、prm.min の値は「18」なります。
export const createSchema = yup.object({
age: yup.string().label('年齢').min(18),
})
日本語の定義ファイルを作成する
日本語の定義の仕方がわかったので、日本語定義ファイルを作成しsetLocale
で yup にセットします。
ファイル名はなんでもいいですが、yupJpConfig.ts というファイル名で作成しました。
label はスキーマで定義されるかわからないので、定義された場合だけ出力するようにしています。
2022/05/12 サンプル変更
ファイル名は何でもいいですが、yup.locale.ts というファイル名で作成しました。
「export default yup」しておき、yupを使用する個所ではimport yup from 'yup.locale.ts '
とこのファイル経由でyupを使用します。
import * as yup from 'yup'
import { MessageParams } from "yup/lib/types"
const labelText = (prm: MessageParams) => {
return prm.label ? `${prm.label}は`: ''
}
const jpConfig = {
mixed: {
default: (prm: MessageParams) => `${labelText(prm)}無効です`,
required: (prm: MessageParams) => `${labelText(prm)}必須の入力項目です`,
oneOf: (prm: MessageParams & {values: any}) => `${labelText(prm)}次の値のいずれかでなければなりません:${prm.values}`,
notOneOf: (prm: MessageParams & {values: any}) => `${labelText(prm)}次の値のいずれかであってはなりません:${prm.values}`,
notType: `形式が違います`,
defined: ``
},
string: {
length: (prm: MessageParams & {length: number}) => `${labelText(prm)}${prm.length}文字でなければなりません`,
min: (prm: MessageParams & {min: number}) => `${labelText(prm)}少なくとも${prm.min}文字でなければなりません`,
max: (prm: MessageParams & {max: number}) => `${labelText(prm)}最大${prm.max}文字でなければなりません`,
matches: (prm: MessageParams & {regex: RegExp}) => `${labelText(prm)}次の形式と一致する必要があります: "${prm.regex}"`,
email: (prm: MessageParams & {regex: RegExp}) => `${labelText(prm)}メールアドレス形式である必要があります`,
url: (prm: MessageParams & {regex: RegExp}) => `${labelText(prm)}有効なURLでなければなりません`,
uuid: (prm: MessageParams & {regex: RegExp}) => `${labelText(prm)}有効なUUIDでなければなりません`,
trim: (prm: MessageParams) => `${labelText(prm)}前後にスペースを入れてはいけません`,
lowercase: (prm: MessageParams) => `${labelText(prm)}小文字でなければなりません`,
uppercase: (prm: MessageParams) => `${labelText(prm)}大文字でなければなりません`,
},
number: {
min: (prm: MessageParams & {min: number}) => `${labelText(prm)}${prm.min}以上である必要があります`,
max: (prm: MessageParams & {max: number}) => `${labelText(prm)}${prm.max}以下でなければなりません`,
lessThan: (prm: MessageParams & {less: number}) => `${labelText(prm)}${prm.less}より小さくなければなりません`,
moreThan: (prm: MessageParams & {more: number}) => `${labelText(prm)}${prm.more}より大きくなければなりません`,
positive: (prm: MessageParams & {more: number}) => `${labelText(prm)}正の数でなければなりません`,
negative: (prm: MessageParams & {less: number}) => `${labelText(prm)}負の数でなければなりません`,
integer: (prm: MessageParams) => `${labelText(prm)}整数でなければなりません`,
},
date: {
min: (prm: MessageParams & {min: Date | string}) => `${labelText(prm)}${prm.min}より後でなければなりません`,
max: (prm: MessageParams & {max: Date | string}) => `${labelText(prm)}${prm.max}より前でなければなりません`,
},
boolean: {
isValue: (prm: MessageParams) => `${labelText(prm)}値が必要です`,
},
object: {
noUnknown: (prm: MessageParams) => `${labelText(prm)}オブジェクトシェイプで指定されていないキーを含めることはできません`,
},
array: {
length: (prm: MessageParams & {length: number}) => `${labelText(prm)}${prm.length}個が必要です`,
min: (prm: MessageParams & {min: number}) => `${labelText(prm)}${prm.min}個以上の項目が必要です`,
max: (prm: MessageParams & {max: number}) => `${labelText(prm)}${prm.max}個以下の項目が必要です`,
},
}
yup.setLocale(jpConfig)
export default yup
アプリケーションに導入する
アプリケーションのルートコンポーネントなどで、作成した日本語定義ファイルを import します。
※ココがわからず少し手間取ってしまいました😫
他の方法(日本語定義ファイル自体を default export して使う)もありますが、アプリケーションルートで日本語定義ファイルを読み込んでしまう方が、簡単な上 import 先をうっかり間違えてしまうということもありません。
他のコンポーネントなどで yup を使用する時は import yup from 'yup.locale.ts
と先ほど作成した「yup.locale.ts」ファイル経由でyupを使用します。
import yup from 'yup.locale.ts
export const createSchema = yup.object({
name: yup.string().lable('名称').required()
})
以上、Validation ライブラリ yup の日本語化 でした。
Discussion