ローカライゼーション
キーからテキストへのルックアップ、実行時の言語切り替え、プレイヤーが言語を変更すると即座に更新される UI テキスト。
UI テキストをハードコードせずに、ゲームを多言語で出荷しましょう。
| インターフェース | ILocalizationService |
| オフスイッチ | NullLocalization |
| アセンブリ | CommonGameSystem.Localization(オプション — Unity 組み込みの uGUI パッケージが必要) |
| 起動 | ブート時に自動登録。翻訳テーブルのロードは利用者側で行う |
できること
メニューに "Start" を直接書く代わりに、キー — "menu.start" のような安定した識別子 — を書きます。Localization サービスは実行時にそのキーを現在の言語のテキストへ解決します。プレイヤーが設定メニューで言語を切り替えると、画面上のすべての LocalizedText コンポーネントが即座に更新されます — シーンのリロードも再起動も不要です。
翻訳の欠落でゲームがクラッシュすることはありません。現在の言語でルックアップに失敗するとフォールバック言語(デフォルトは英語)にフォールバックし、それでも失敗した場合はキーそのものが返されます。UI には常に何かが表示されます。
翻訳は LocalizationTableAsset ScriptableObject に格納します — Inspector で入力するか、スプレッドシートから生成できるプレーンなデータアセットです。言語は標準の BCP-47 言語タグで識別します。ブラウザーや OS が使うのと同じ短いコードで、"en"、"ko"、"ja"、"zh-CN" などです。
このモジュールは独立したオプションアセンブリに含まれているため、プロジェクトから uGUI を削除するとアセンブリが除外されるだけです — フレームワークの残りは引き続きコンパイルされ、起動します。
クイックスタート
起動スクリプトでサービスを解決し、テーブルを一度だけロードします:
using CommonGameSystem.Core;
using UnityEngine;
[DefaultExecutionOrder(100)] // Run after the framework has started.
public class GameStartup : MonoBehaviour
{
[SerializeField] private LocalizationTableAsset[] tables; // assign in the Inspector
private ILocalizationService _loc;
private void Awake()
{
_loc = ServiceLocator.Resolve<ILocalizationService>();
_loc.LoadTables(tables);
// Optional: start in the player's OS language.
_loc.SetLocale(LocaleId.FromSystemLanguage(Application.systemLanguage));
}
}
以降は、どのスクリプトからでも Get でテキストを取得できます:
string title = _loc.Get("menu.title");
API リファレンス
ルックアップ
string Get(string key)— キーを解決します: 現在の言語 → フォールバック言語 → キーそのもの、の順です。決してスローしません。string Get(string key, params object[] args)— 同じルックアップの後、結果をインバリアントカルチャのstring.Formatでフォーマットします。不正なフォーマット文字列の場合はスローせず、未フォーマットのテキストを返します。bool TryGet(string key, out string value)— 副作用のないルックアップです。キーがない場合はfalseを返します(valueにはキーが設定されます)。何もログに出さないため、警告のスパムなしにキーの存在を調べるのに便利です。
言語の切り替え
void SetLocale(string localeId)— アクティブな言語を切り替えます。Event Bus にLocaleChangedイベントを発行し、選択を Configuration サービス経由で保存するため、セッションをまたいで保持されます。string CurrentLocale { get; }— アクティブなロケール ID。IReadOnlyList<string> AvailableLocales { get; }— ロード済みテーブルから見つかったロケール ID の一覧。言語選択 UI はこのリストから構築してください。string GetLocaleDisplayName(string localeId)— その言語自身での言語名(たとえば韓国語なら"한국어")。言語選択 UI 用です。未設定の場合は ID にフォールバックします。
セットアップ
void LoadTables(IReadOnlyList<LocalizationTableAsset> tables)— 翻訳テーブルをロードし、保存済み(またはデフォルト)の言語をアクティブにします。起動時に一度だけ呼んでください。
静的ヘルパー
LocaleId.FromSystemLanguage(SystemLanguage)—Application.systemLanguageを BCP-47 タグにマッピングします(たとえばSystemLanguage.Korean→"ko")。初回起動時にプレイヤーの OS 言語を自動検出するのに使います。
LocalizedText コンポーネント
静的な UI テキストならコードは一切不要です。uGUI の Text または TextMeshPro コンポーネントに LocalizedText コンポーネントをアタッチし、Inspector でキーを設定してください。コンポーネントは有効化時にテキストを取得し、言語が変わるたびに再取得します。
値を埋め込む動的なテキストには SetArgs を使います:
using CommonGameSystem.Core;
using UnityEngine;
public class ScoreDisplay : MonoBehaviour
{
private LocalizedText _locText;
private void Start()
{
_locText = GetComponent<LocalizedText>();
}
public void SetScore(int newScore)
{
// Table entry: "score.current" = "Score: {0}" → displays "Score: 42"
_locText.SetArgs(newScore);
}
}
例: 言語ボタン
using CommonGameSystem.Core;
using UnityEngine;
public class LanguageMenu : MonoBehaviour
{
private ILocalizationService _loc;
private void Start()
{
_loc = ServiceLocator.Resolve<ILocalizationService>();
}
// Wire this to a UI button, passing "en", "ko", "ja", ...
public void OnLanguageButtonClicked(string localeId)
{
_loc.SetLocale(localeId); // Every LocalizedText on screen updates live.
}
}
選択は自動的に保存されます — 次のセッションはプレイヤーが選んだ言語で始まります。
無効化する
ServiceLocator.Replace<ILocalizationService>(new NullLocalization());
Get(key) はキーをそのまま返し、SetLocale と LoadTables は静かな no-op になり、何もログに残りません。軽量ビルドやテストでローカライゼーションを完全に取り除くのに使ってください。
よくある落とし穴
- メインスレッド専用。 ワーカースレッドから
GetやSetLocaleを呼ぶとInvalidOperationExceptionがスローされます。MonoBehaviour のコールバックはすべて安全です。 - サービスをキャッシュする。
Update()での解決は、毎フレームのディクショナリ検索の繰り返しです。代わりにAwake()かStart()で参照をキャッシュしてください。 - ロケール ID は完全一致が必要。
"EN"は"en"ではなく、Application.systemLanguage.ToString()は"ko"ではなく"Korean"を返します。自動検出にはLocaleId.FromSystemLanguage()を使い、テーブルには小文字の BCP-47 タグを使ってください。 LocalizedTextは有効化のたびに再購読する。 プールされた UI プレハブ(ダメージ数値、トースト)では、プールの 1 サイクルごとにLocaleChangedへの購読と購読解除が発生します。これは正しい挙動で、再アクティブ化時に現在の言語を反映するためですが、高頻度のプールには注意してください。動的なテキストの更新にはSetArgsを優先してください。- シャットダウン順序。 サービスは起動順の逆順でシャットダウンするため、Localization サービスが Event Bus より先に破棄されることがあります。その後に
LocaleChangedイベントが届いた場合、LocalizedTextは静かに握りつぶします — テキストは更新されませんが、クラッシュもしません。 - カスタム型は IL2CPP で
link.xmlが必要。 ローカライゼーションキーを持つ独自の設定型をシリアライズする場合は、プロジェクトのlink.xmlでそれらが保持されるようにしてください。出荷されるフレームワークアセンブリは自身の型をすでに保持しています。
関連ページ
- Event Bus —
LocaleChangedイベント - Configuration — 言語の選択が保存される場所
- UI Framework — ローカライズ済みテキストを載せるパネルと画面