i18n
Astar Management のロケールは ja と ja-plain(やさしい日本語)のみ です。英語ロケールは存在しません。en キーを追加しないでください。
原則は i18n-first: ユーザーに見えるすべての文字列は、必ず i18n キー経由で書きます。テンプレートに直書きした文字列は、ja-plain の差し替えや将来の用語統一を素通りしてしまいます。
一次資料は frontend/i18n/CONVENTIONS.md です。新しい key をどこに置くか迷ったときは、必ずこのページより先にそちらを確認してください。ここではその要点と、実際に事故が起きた罠を説明します。
二層 + グロッサリーの構造
frontend/i18n/locales/ja/
├── glossary.json ← Astar 固有 entity 名の SSoT(最上位)
├── general.json
├── foundation/ ← 横断的な共通 UI 文言
│ ├── actions.json ← 動詞 / ボタン
│ ├── common.json ← フィールド名 / 一般語 / ステータス
│ ├── form.json ← バリデーション / submit / cancel
│ ├── table.json ← ソート / フィルター / ページネーション
│ ├── navigation.json ← サイドバー / breadcrumb
│ ├── messages.json ← トースト / 確認ダイアログ
│ ├── pickers.json ← icon picker / color picker
│ ├── search.json
│ └── datetime.json
└── modules/{name}/domain.json ← module 固有のドメイン文言のみ
新しい key を追加するときの参照優先順序は次の3段階です。
glossary.entitiesに該当があれば@:glossary.entities.Xで参照するfoundation.{section}に該当があれば@:foundation.{section}.Xで参照する- どちらにも無ければ
modules/{name}/domain.jsonに新規追加する
module の domain.json に書いてよいのは、foundation のテンプレートでは表現できない、その module 固有のドメイン文言だけです。共通語彙を module 側で再定義しないでください。
glossary — entity 名の唯一の出所
glossary.entities は Astar 固有の18個の正準名詞(table / workspace / dashboard / record / template / role / user / member / widget / property / calendarEvent / storageDevice / tenant / folder / resource / document / file / view)の SSoT です。これらの語は 他のどこにも bare 文字列で書きません。
// ❌ module 内で entity 名を hardcode
{ "modules": { "table": { "title": "テーブル" } } }
// ✅ linked message 経由
{ "modules": { "table": { "title": "@:glossary.entities.table" } } }
vue-i18n の @:foo.bar 構文で別 key を参照します。
{
"modules": {
"table": {
"title": "@:glossary.entities.table",
"subtitle": "{count}個の@:glossary.entities.table",
"actions": {
"create": "@:glossary.entities.table を作成"
}
}
}
}
- 単独参照:
"@:glossary.entities.table" - 文中埋込:
"新しい@:glossary.entities.table" - 補間との併用:
"{count}個の@:glossary.entities.table" - ネストした linked message は使いません(深さ1まで)
entity 名を hardcode してはいけない理由は実利的です。glossary を linked message 化しておけば、ja-plain 側は glossary.entities を上書きするだけで全 module の用語が一括で切り替わります。 module 内に bare 文字列で書いてしまうと、その module だけ ja-plain の用語統一から漏れます。
foundation — 共通語彙の SSoT
エンティティに紐づかない属性名や動詞は foundation 側に集約します。
- フィールド名(名前・説明・ステータス・タイプ・カテゴリ・タグ・アイコン・作成日時 …)→
foundation.common.fieldsが SSoT。各 module で再定義しません。 - 動詞・ボタン文言(保存・キャンセル・削除・編集・新規作成・追加・検索・フィルター・エクスポート・コピー・複製 …)→
foundation.actionsが SSoT。
// Do: foundation テンプレート + glossary entity の組み合わせ
toast.success(t('foundation.messages.success.targetCreated', { target: t('glossary.entities.table') }))
// Don't: foundation で表現できるテキストを module domain.json に書く
toast.success(t('modules.table.messages.created')) // ❌
ja/index.ts マウント漏れの罠
frontend/i18n/locales/ja/index.ts は、foundation/*.json と modules/*/domain.json を1ファイルずつ import し、最終的な messages オブジェクトへ 手作業で列挙して マウントするファイルです。
// import 部分
import tagDomain from './modules/tag/domain.json'
// マウント部分(messages オブジェクトの組み立て)
modules: {
// ...
tag: tagDomain.modules.tag,
// ...
}
i18n キーが JSON ファイルに存在していても、この index.ts の import / マウント列挙に追加されていなければ、そのキーは実行時に解決されません。t('modules.newFeature.title') は生のキー文字列がそのまま画面に表示され、値は空になります。
これは lint(missing-key チェック)では検出できません。JSON ファイル上はキーが存在しているため、静的解析からは問題なく見えるからです。新しい module の domain.json を追加したときは、必ず ja/index.ts の import とマウントの両方に追記し、実際に画面を目視で確認してください。 L3 のビジュアル検証が唯一の実効的な検知手段です。
動的キー namespace
t() に動的に組み立てたキー(t(modules.${moduleName}.title) のような形)を使う場合、ESLint の usedKeys リストへの登録が必要です。登録漏れは missing-key lint で検知されます。
過剰和訳禁止
ja-plain(やさしい日本語)は ja の差分 overlay ですが、ユーザーがすでに知っている外来語まで無理に和訳しません。次のカテゴリは 横文字のまま残します。
- 人系: メンバー / ユーザー
- 装飾系: アイコン / タグ / バッジ
- 記録系: メモ / ノート / コメント
- 分類系: タイプ / カテゴリ / ステータス
- 動作系: コピー / ペースト / キャンセル / プレビュー
- ファイル系: ファイル / フォルダ / ダウンロード / アップロード
- UI系: メニュー / サイドバー / ボタン / リンク / ログイン / パスワード
- 意味ズレ語: ストレージデバイス / リソース / クラウドストレージ
和訳を採用してよいかどうかは次の3条件が すべて YES の場合のみです。1つでも NO なら横文字のままにします。
- Excel / freee / kintone 日本語版に一般化された置換語があるか
- 法律事務員(紙文化が長い人)にとって紙文化と繋がる語か
- 意味のズレや概念の欠落が起きないか
新しい module を追加するときの手順
i18n/locales/ja/modules/{name}/domain.jsonを作成する- entity 名は
@:glossary.entities.X経由で参照し、bare 文字列で書かない - 共通フィールド名・動詞は
@:foundation.{section}.X経由で参照する - module 固有のドメイン文言だけを
domain.jsonに書く ja/index.tsの import とマウント列挙の両方に追記する(上記の罠を参照)- ja-plain 側は基本的に書かない(主要 module 以外は ja に fall back する)