Appearance
Metanaka Nuxt i18n Rule
Nuxt app 内でユーザーに見える文言、validation message key、locale file を扱うときに使う、このリポジトリ固有の i18n ルール。
source と output
feature 固有の翻訳 source は、その feature の近くに置く。 feature directory が未作成の場合も、source は新しい feature slice の i18n/ 配下に作る。
text
app/features/<feature>/i18n/ja.json
app/features/<feature>/i18n/en.jsonshared または app-wide な message source は、その文言を所有する shared concept の近くに置く。
text
app/shared/<concept>/i18n/ja.json
app/shared/<concept>/i18n/en.jsonNuxt が読む locale file だけを i18n/ 配下に置き、生成物として扱う。
text
i18n/locales/ja.json
i18n/locales/en.jsoni18n/locales/*.json を直接の編集場所にしない。feature source または shared concept source を編集してから merge する。
ディレクトリルール
feature ディレクトリは基本的にフラットだが、i18n だけは例外として i18n/ ディレクトリを切る。
text
app/features/host/
model.ts
use-room-create.ts
use-room-create.test.ts
i18n/
ja.json
en.jsonhost/ja.json や host/en.json のように i18n file を feature root にフラット配置しない。
shared 配下も概念単位で slice 化する。共有文言は app/shared/i18n のような横断ディレクトリに集めず、所有する shared concept の i18n/ に置く。
text
app/shared/server-error/
model.ts
resolve-server-error-keys.ts
i18n/
ja.json
en.jsonkey 命名
feature が所有する message は feature namespace 配下に置く。shared concept が所有する message は shared concept namespace 配下に置く。所有者の namespace に置くことで、他 feature や他 shared concept の key との競合を防ぐ。
json
{
"host": {
"error": {
"wolfCountInvalid": "ウルフ人数は整数で選択してください。",
"wolfCountMin": "ウルフ人数は1人以上にしてください。"
}
}
}基本形は次の通り。
text
<owner>.<category>.<shortCamelCaseName>短い action や label で category を切るほどではない場合は、次の形も許可する。
text
<owner>.<leaf>例:
host.error.wolfCountInvalidhost.error.wolfCountMinhost.error.voteSecondsInvalidhost.createroom.notFound.titleserverError.error.SE10001
owner namespace で十分に文脈が分かる場合、過剰に深い key は避ける。
text
error.front.roomCreate.voteSeconds.invalid代わりに次を優先する。
text
host.error.voteSecondsInvalid命名規則
- leaf key は camelCase にする。例:
wolfCountInvalid。wolf_count_invalidは使わない。 - category object は
error、form、summary、notFoundのように短くする。 - feature が所有する message は feature name を top-level namespace にする。
- shared concept が所有する message は concept name を camelCase にした top-level namespace にする。例:
server-errorconcept はserverError。 common、appなどの曖昧な shared namespace は原則として使わず、明確な所有 concept に寄せる。アプリのブランドや最上位 shell のように本当に app-wide なものだけappを使う。ja.jsonとen.jsonの key set は一致させる。- 後段の表示境界で
t(key)する値は、code 上では i18n key として持つ。 - Firestore、共有 game state、round history、validation schema に翻訳済み display string を保存しない。
所有権と再定義禁止
他 feature または他 shared concept が所有している言葉は、利用側の i18n で再定義しない。文言の責務は、その概念を所有する feature または shared concept が持つ。
例えば feature/user/i18n が user.displayName を定義している場合、feature/host/i18n では host.displayName を再定義しない。host 側の UI で表示名ラベルが必要なら、t("user.displayName") のように user feature が所有する key を参照する。
再定義してよいのは、利用側 feature 固有の意味や文脈を持つ場合だけにする。
text
user.displayNameは user が所有する一般的な表示名。
text
host.hostDisplayNameHelpは host のルーム作成文脈に固有の補助文。
validation と Zod
このリポジトリでは Zod v4 を前提にする。Zod schema の message は、UI で表示される validation error の i18n key として使ってよい。
ts
wolfCount: z.number("host.error.wolfCountInvalid")
.int("host.error.wolfCountInvalid")
.min(1, "host.error.wolfCountMin")composable や form state では、Zod issue の message をそのまま入れる。
ts
error.value[field] = issue.messageschema が具体的な key を持てる場合、composable 側で field name から i18n key を組み立てない。
Zod 用の i18n key は定数化せず、schema の message に直接文字列で書く。
merge workflow
source locale file を編集したら、Nuxt project root で merge する。
bash
pnpm run i18n:mergepnpm run i18n:merge が存在しない場合は、この skill に同梱している merge script を Nuxt project root の scripts/merge-i18n.mjs に配置し、package.json に実行コマンドを追加する。
text
.codex/skills/metanaka-nuxt-i18n-rule/scripts/merge-i18n.mjsjson
{
"scripts": {
"i18n:merge": "node scripts/merge-i18n.mjs"
}
}同梱 script は次を満たす。
app/features/*/i18n/{ja,en}.jsonを読む。app/shared/*/i18n/{ja,en}.jsonを読む。i18n/locales/{ja,en}.jsonを書く。- source directory に
ja.jsonだけ、またはen.jsonだけがある場合は失敗する。 - 同じ i18n source directory 内で
jaとenの key set が違う場合は失敗する。
typecheck、build、dev の前に pretc、prebuild、predev などの package script で merge が走る構成なら、それに従う。
検証
i18n file を編集したら実行する。
bash
pnpm run i18n:mergeこの command は Nuxt project root で実行する。 review や編集禁止の評価で merge を実行できない場合は、実行すべき command と作業 directory を成果物や review comment に明記する。
i18n key を consume する code に触った場合は、狭い unit test と typecheck も実行する。