yupのv1を使ってNext.jsで多言語対応を行う方法
2023-03-30
yup の v1 がリリースされて少し経ちましたが、ロケールの設定についてはバグが多いです。
バグの内容については Issue を見ていただくとして、今回は Next.js で暫定対応を行う方法を書いていこうと思います。
事象
英語 → 日本語のケースは問題ないのだが、日本語 → 英語のケースだと yup
内の defaultLocale
が正しく取得できないことがわかった。
対策
Next.js の動的に環境変数を作成する方法で強引に defaultLocale
を作成した。
パッケージおよびバージョン
{
"dependencies": {
"@hookform/resolvers": "^3.0.0",
"@types/node": "18.15.10",
"@types/react": "18.0.29",
"@types/react-dom": "18.0.11",
"next": "13.2.4",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.43.8",
"typescript": "5.0.2",
"yup": "^1.0.2",
"yup-locale-ja": "^1.0.0"
}
}
実装
const { defaultLocale } = require("yup");
/** @type {import('next').NextConfig} */
const nextConfig = {
env: {
defaultLocale: JSON.stringify(defaultLocale),
},
};
module.exports = nextConfig;
import { useRouter } from "next/navigation";
import { useForm } from "react-hook-form";
import * as jp from "yup-locale-ja";
import { yupResolver } from "@hookform/resolvers/yup";
import { setLocale, object, string, InferType } from "yup";
setLocale(jp.descriptive);
const schema = object({
piyo: string().label("PIYO").required(),
});
type FieldValues = InferType<typeof schema>;
export default function Hoge() {
const { formState, handleSubmit, register } = useForm<FieldValues>({
defaultValues: {
piyo: "",
},
resolver: yupResolver(schema),
});
const router = useRouter();
return (
<>
<h1>JP</h1>
<form
onSubmit={handleSubmit((values) => {
router.push("/fuga");
})}
>
<input {...register("piyo")} />
<p>{formState.errors.piyo?.message}</p>
<button>submit</button>
</form>
</>
);
}
import { yupResolver } from "@hookform/resolvers/yup";
import { useRouter } from "next/navigation";
import { useForm } from "react-hook-form";
import { setLocale, object, string, InferType } from "yup";
setLocale(JSON.parse(process.env.defaultLocale || ""));
const schema = object({
piyo: string().label("PIYO").required(),
});
type FieldValues = InferType<typeof schema>;
export default function Fuga() {
const { formState, handleSubmit, register } = useForm<FieldValues>({
defaultValues: {
piyo: "",
},
resolver: yupResolver(schema),
});
const router = useRouter();
return (
<>
<h1>EN</h1>
<form
onSubmit={handleSubmit((values) => {
router.push("/hoge");
})}
>
<input {...register("piyo")} />
<p>{formState.errors.piyo?.message}</p>
<button>submit</button>
</form>
</>
);
}
実装を見てもらったわかる通り、めちゃくちゃ強引です。
言わずもがな良い実装方法ではないので、公式に早く対応してほしいなぁと思いつつ。