はじめに
プリザンターは 7 つの言語(英語・日本語・中国語・ドイツ語・韓国語・スペイン語・ベトナム語)をサポートしています。ユーザーが言語を切り替えると、画面上のラベルやメッセージが即座にその言語で表示されます。
この多言語対応はどのような仕組みで実現されているのでしょうか。本連載では、プリザンターの多言語対応(i18n)の内部実装を 5 回に分けて詳しくみていきます。
| 回 | テーマ |
|---|---|
| 第 1 回(本記事) | 多言語アーキテクチャ概要編 — 全体設計と構成要素 |
| 第 2 回 | Display 定義と DisplayAccessor 編 — JSON 定義ファイルの構造とアクセサクラス |
| 第 3 回 | CodeDefiner によるコード生成編 — テンプレートから C# / TypeScript を自動生成する仕組み |
| 第 4 回 | 言語解決メカニズム編 — ユーザー言語の決定ロジックとフォールバック |
| 第 5 回 |
クライアントサイド多言語対応編 — TypeScript での言語切り替えと $p.display()
|
バージョン 1.5.1.0 を対象にしています
対応言語一覧
プリザンターが標準でサポートしている言語は以下の 7 つです。
| 言語コード | 言語名 | 言語名(現地語) |
|---|---|---|
en |
英語 | English |
ja |
日本語 | 日本語 |
zh |
中国語 | 中文 |
de |
ドイツ語 | Deutsch |
ko |
韓国語 | 한국어 |
es |
スペイン語 | Español |
vn |
ベトナム語 | Tiếng Việt |
この一覧は Users_Language カラムの ChoicesText で定義されています。
{
"Id": "Users_Language",
"ColumnName": "Language",
"ChoicesText": "en,English\nzh,Chinese\nja,Japanese\nde,German\nko,Korean\nes,Spanish\nvn,Vietnamese",
"Default": "ja"
}
ベトナム語のコードは HTTP の Accept-Language ヘッダーでは vi ですが、プリザンター内部では vn として扱われます。この変換は Context.SessionLanguage() メソッドで行われています。
多言語アーキテクチャの全体像
プリザンターの多言語対応は 3 つの層で構成されています。
それぞれの層の役割を見てみましょう。
定義層
多言語テキストの原データを管理する層です。
| コンポーネント | パス | 役割 |
|---|---|---|
| Display JSON ファイル | App_Data/Displays/*.json |
UI に表示する文字列を 7 言語分定義 |
| カラム定義 | App_Data/Definitions/Definition_Column/*.json |
テーブルカラムのラベルを多言語定義 |
| コード定義テンプレート | App_Data/Definitions/Definition_Code/*.json |
CodeDefiner が生成するコードのテンプレート |
生成層
CodeDefiner ツールが定義層のデータを読み取り、サーバーサイドとクライアントサイドのコードを自動生成する層です。
- 入力: Display JSON + カラム定義 + コード定義テンプレート
-
出力:
Libraries/Responses/Displays.cs(約 28,000 行)やdisplay.tsなどの自動生成コード
実行層
アプリケーション起動時に Display JSON を読み込んで DisplayHash を構築し、リクエストごとにユーザーの言語設定に基づいて表示テキストを解決する層です。
Display JSON の概要
多言語テキストの最小単位は、App_Data/Displays/ ディレクトリに配置された JSON ファイルです。1 ファイルにつき 1 つの表示文字列を定義し、全部で約 1,255 ファイルが存在します。
たとえば「確認」ボタンのテキストは以下のように定義されています。
{
"Id": "Confirm",
"Type": 310,
"Languages": [
{ "Body": "Confirm" },
{ "Language": "zh", "Body": "确认" },
{ "Language": "ja", "Body": "確認" },
{ "Language": "de", "Body": "Bestätigen" },
{ "Language": "ko", "Body": "확인" },
{ "Language": "es", "Body": "Confirmar" },
{ "Language": "vn", "Body": "Xác nhận" }
]
}
ここで注目すべきポイントが 2 つあります。
-
デフォルト言語(英語)には
Languageプロパティがない —Languages配列の先頭要素はLanguageを持たず、これがフォールバック(既定値)として扱われます -
Typeフィールドで用途を分類している — メッセージの種別に応じてTypeが設定されています
Display Type(メッセージ種別)
Type フィールドの値と意味は以下のとおりです。
| 値 | 名称 | 用途 | CSS クラス |
|---|---|---|---|
| 110 | Normal |
通常のラベル・テキスト | — |
| 120 | Date |
日付関連テキスト | — |
| 130 | DateFormat |
日付フォーマット | — |
| 210 | Success |
成功メッセージ | alert-success |
| 220 | Information |
情報メッセージ | alert-information |
| 230 | Warning |
警告メッセージ | alert-warning |
| 240 | Error |
エラーメッセージ | alert-error |
| 310 | Confirmation |
確認ダイアログ | alert-confirm |
| 410 | Validation |
バリデーション | — |
カラム定義の多言語ラベル
テーブルカラムのラベルは Definition_Column/*.json で多言語定義されています。
{
"Id": "Users_Language",
"ModelName": "User",
"TableName": "Users",
"ColumnName": "Language",
"LabelText": "言語",
"LabelText_en": "Language",
"LabelText_zh": "语言",
"LabelText_de": "Sprache",
"LabelText_ko": "언어",
"LabelText_es": "Idioma",
"LabelText_vn": "Ngôn ngữ"
}
LabelText が日本語(主キー)で、LabelText_en / LabelText_zh / LabelText_de / LabelText_ko / LabelText_es / LabelText_vn が各言語のラベルです。これらのラベルは初期化時に Display JSON と同じ DisplayHash に統合されます。
言語解決の概要
ユーザーの言語は Context.Language プロパティに保持されます。解決の優先順位は以下のとおりです。
| 優先度 | 条件 | 取得元 |
|---|---|---|
| 1(最高) | 認証済みユーザー |
UserModel.Language(DB の Users.Language カラム) |
| 2 | クエリ文字列指定 | URL パラメータ ?Language=ja
|
| 3 | セッション保存 | 前回のリクエストで保存された言語 |
| 4 | ブラウザ設定 | HTTP Accept-Language ヘッダーを解析 |
| 5(最低) | システムデフォルト | Parameters.Service.DefaultLanguage |
表示テキスト取得の流れ
言語が決定されると、Displays.Get() メソッドで表示テキストを取得します。
public static string Get(string id, string language, params string[] data)
{
var screen = id;
var key = id + "_" + language;
if (DisplayHash.ContainsKey(key))
screen = DisplayHash[key]; // 言語固有キーを優先
else if (DisplayHash.ContainsKey(id))
screen = DisplayHash[id]; // なければデフォルト(英語)
return data?.Any() == true
? screen.Params(data)
: screen;
}
キーの構造はシンプルです。
| キー形式 | 例 | 意味 |
|---|---|---|
{DisplayId} |
Confirm |
デフォルト(英語) |
{DisplayId}_{Language} |
Confirm_ja |
言語固有テキスト |
たとえば context.Language が "ja" の場合、まず Confirm_ja を探し、見つかれば "確認" を返します。見つからなければ Confirm のデフォルト値 "Confirm" を返します。
まとめ
プリザンターの多言語対応は、以下の 3 層構造で実現されています。
- 定義層 — Display JSON(1,255 ファイル)とカラム定義で多言語テキストを管理
- 生成層 — CodeDefiner が定義データからサーバー/クライアント両方のコードを自動生成
-
実行層 — 起動時に
DisplayHashを構築し、Context.Languageに基づいて表示テキストを解決
次回は、Display JSON とそれを扱う DisplayAccessor クラス群の詳細を見ていきます。