i18n jsonファイルのキーの不一致をTypeScriptで防いでいる話
2024/05/10
#i18n
この記事は3分で読めます
i18nあるある
json ファイルの typo を防ぎたい を読んで、あるある、と思った。
翻訳リソースファイルを複数用意する場合に、キーが微妙に一致してなくて...みたいな問題が起こりがち。片方には作成済みだがもう片方には漏れていて、みたいなのもありがち。
なので、TypeScriptでキーが一致することを検証するようにしている。
(ただし、2ヶ国語対応だからできているという面もある。大量の言語、大量のJSONファイル、大量のキーがある場合にワークする方法ではないと思う。)
TSファイルの動的生成
翻訳ファイルが存在しているディレクトリを読みに行き、以下のようなファイルを生成している。
(genI18NextDts.js
の詳細は省略。普通に、fs
でディレクトリを読んで、いい感じにテンプレートリテラルなど使って内容を組み立てているだけなので。)
/** This file is generated by scripts/genI18NextDts.mjs */ import authJa from '../../../public/locales/ja/auth.json'; import commonJa from '../../../public/locales/ja/common.json'; //... import authEn from '../../../public/locales/en/auth.json'; import commonEn from '../../../public/locales/en/common.json'; // ... type IsEqual<T, U> = (T extends U ? (U extends T ? true : false) : false) & ([T, U] extends [{[k: string]: unknown}, {[k: string]: unknown}] ? { [K in keyof T | keyof U]: K extends keyof T ? K extends keyof U ? IsEqual<T[K], U[K]> : false : false; }[keyof T | keyof U] extends true ? true : false : true); // eslint-disable-next-line @typescript-eslint/no-unused-vars function assertTypeIsEqual<T extends true>(): void {} // Check that all locales have the same keys assertTypeIsEqual<IsEqual<typeof authJa, typeof authEn>>(); assertTypeIsEqual<IsEqual<typeof commonJa, typeof commonEn>>(); // ...
こうしておくと、ビルド時にチェックが走る。えらい。 ただし、「どのキーが漏れているか」まではエラーとして出せていないので、改善の余地はある。 また、そもそもTSの型チェック機構に乗っかるのではなく、普通に動的なテストとして実装してしまうのもありだとは思う。