localization について
Godot 4.3+向けのローカライズガイドです。GDScriptとC#の例で、翻訳ファイル、実行時の言語切り替え、多言語UIの扱いを説明します。
主な機能
- 01tr()による翻訳対象テキストの指定
- 02CSVとPOの翻訳ファイル
- 03実行時のロケール切り替え
- 04RTLレイアウトとロケール対応の書式
- 05Godot 4.6+のCSV複数形とコンテキスト
活用シーン
- 01ゲームUIへの多言語テキスト追加
- 02実行時のゲーム言語切り替え
- 03RTLレイアウトと翻訳文のはみ出し確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jame581/ godotprompter --skill localizationインストール後、Claude Code で/localizationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/csv-plural-context.mdeditor-preview.mdlocale-formatting.mdrtl-support.md詳細
Godot 4.3+ でのローカライズ
すべての例は、非推奨 API を使用しない Godot 4.3+ を対象としています。まず GDScript、次に C# を扱います。
関連スキル: Control ノードとテーマ管理については godot-ui、言語設定の保存については save-load、ロケールごとのレイアウト調整については responsive-ui を参照してください。
1. 基本概念
Godot のローカライズの仕組み
tr()(Godot の翻訳関数)を使って、ユーザーに表示するすべての文字列を囲みます- キーと翻訳済みの文字列を対応付けた翻訳ファイル(CSV または PO)を作成します
- 翻訳ファイルを
Translationリソースとしてインポートします TranslationServer.set_locale()を使って、実行時にロケールを切り替えます
text、tooltip_text、または placeholder_text プロパティを持つすべての Control ノードは、その値が翻訳キーと一致すると自動的に翻訳されます。
翻訳キーの方式
| 方式 | キーの例 | メリット | デメリット |
|---|---|---|---|
| セマンティックキー | MENU_START_GAME | 意図が明確で、見つけやすい | デフォルト言語へのフォールバックが必要 |
| 英語をキーとして使用 | Start Game | コードが読みやすく、英語用の対応表が不要 | 英語のテキストを変更すると壊れる |
推奨: 本番環境ではセマンティックキー(
MENU_START_GAME)を使用してください。英語をキーとして使用する方法は、プロトタイプや個人プロジェクトに限ってください。
2. 翻訳ファイル
CSV 形式
最もシンプルな形式です。1 列目はキーで、以降の列にはロケールコードを指定します。
keys,en,cs,de,ja
MENU_START,Start Game,Začít hru,Spiel starten,ゲームスタート
MENU_OPTIONS,Options,Nastavení,Optionen,オプション
MENU_QUIT,Quit,Ukončit,Beenden,終了
PLAYER_HEALTH,Health: %d,Zdraví: %d,Gesundheit: %d,体力: %d
ITEM_COLLECTED,%s collected!,%s sebráno!,%s gesammelt!,%sを入手!
プロジェクト内に translations.csv として保存します。Godot はインポート時に形式を自動検出します。
インポート設定(インポートドック):
- 区切り文字:カンマ(デフォルト)、セミコロン、またはタブ
- 圧縮:デフォルトで有効です。
?context/?pluralを使用するファイルではスキップされ、OptimizedTranslationとして保存されます(§10)
PO 形式(Gettext)
業界標準の形式で、翻訳チームや Poedit、Weblate、Crowdin などのツールで推奨されています。
POT テンプレートを作成する(messages.pot):
msgid "MENU_START"
msgstr ""
msgid "MENU_OPTIONS"
msgstr ""
msgid "MENU_QUIT"
msgstr ""
msgid "PLAYER_HEALTH"
msgstr ""
ロケールファイルを作成する(例:チェコ語用の cs.po):
msgid "MENU_START"
msgstr "Začít hru"
msgid "MENU_OPTIONS"
msgstr "Nastavení"
msgid "MENU_QUIT"
msgstr "Ukončit"
msgid "PLAYER_HEALTH"
msgstr "Zdraví: %d"
翻訳の登録
プロジェクト設定 → ローカライズ → 翻訳 → 追加... → .csv または .po ファイルを選択します。
または、実行時に登録します。
var translation := load("res://translations/cs.po") as Translation
TranslationServer.add_translation(translation)
var translation = GD.Load<Translation>("res://translations/cs.po");
TranslationServer.AddTranslation(translation);
⚠️ Godot 4.7 での変更点:
OptimizedTranslation.generate()はboolを返すようになりました(以前はvoid)。GDScript および C# のソース互換性はありますが、バイナリ互換性はありません。この関数を呼び出すプリコンパイル済み C# プラグインは再コンパイルしてください。4.7 移行ガイドを参照してください。
POT 生成フック(Godot 4.7+)
カスタムの EditorTranslationParserPlugin で _customize_strings() をオーバーライドできます。この関数は POT の生成中、すべてのファイルの解析後に一度呼び出され、抽出された文字列の最終リストにエントリーを追加または削除できます。
@tool
extends EditorTranslationParserPlugin
func _customize_strings(strings: Array[PackedStringArray]) -> Array[PackedStringArray]:
strings.append(PackedStringArray(["Test 1", "context", "test 1 plurals", "test 1 comment"]))
# Drop internal strings that begin with "$".
return strings.filter(func(s): return not s[0].begins_with("$"))
#if TOOLS
using System.Linq;
using Godot;
public partial class CommentAwareParser : EditorTranslationParserPlugin
{
public override Godot.Collections.Array<string[]> _CustomizeStrings(Godot.Collections.Array<string[]> strings)
{
strings.Add(new[] { "Test 1", "context", "test 1 plurals", "test 1 comment" });
// Drop internal strings that begin with "$".
return new Godot.Collections.Array<string[]>(strings.Where(s => !s[0].StartsWith("$")));
}
}
#endif
Godot 4.7+: POT ジェネレーターは
Control.accessibility_nameとaccessibility_descriptionも抽出するため、手動で列挙しなくてもアクセシビリティ関連の文字列を翻訳できます。(GH-117134)
3. コードでの tr() の使用
GDScript
# Basic translation
var label_text: String = tr("MENU_START") # "Start Game" or translated equivalent
# With format arguments
var health_text: String = tr("PLAYER_HEALTH") % current_health
# "Health: 85" or "Zdraví: 85"
# With string arguments
var collected_text: String = tr("ITEM_COLLECTED") % item_name
# "Sword collected!" or "Meč sebráno!"
# Pluralization (Godot 4.x)
var count := 5
var msg: String = tr_n("ONE_ENEMY", "MANY_ENEMIES", count)
# Needs plural forms in the translation: PO, or CSV `?plural` rows on Godot 4.6+ (§10)
C#
string labelText = Tr("MENU_START");
// string.Format ignores GDScript-style %d — substitute it yourself.
string healthText = Tr("PLAYER_HEALTH").Replace("%d", currentHealth.ToString());
// Pluralization
string msg = TrN("ONE_ENEMY", "MANY_ENEMIES", count);
Control の自動翻訳
Label、Button、RichTextLabel などの Control ノードは、text プロパティの値が翻訳キーと一致すると、自動的に翻訳されます。テキストにはキーを設定します。
Button.text = "MENU_START" → displays "Start Game" (en) or "Začít hru" (cs)
ヒント: 特定の Control で自動翻訳を無効にするには、
auto_translate_modeをDISABLEDに設定します。
Godot 4.7+:
Control.translation_context: StringNameは、コントロールごとの翻訳コンテキストを設定します。このコンテキストは、表示テキストの翻訳と翻訳テンプレートの生成の両方に使用されます。tr()のコンテキスト引数に相当するプロパティです(C#:TranslationContext)。(GH-115340)
4. 実行時のロケール切り替え
GDScript
# Switch language
func set_language(locale_code: String) -> void:
TranslationServer.set_locale(locale_code)
# All Control nodes with translation keys update automatically
# Get current locale
var current: String = TranslationServer.get_locale() # e.g. "en", "cs", "de"
# Get available locales
var locales: PackedStringArray = TranslationServer.get_loaded_locales()
C#
public void SetLanguage(string localeCode)
{
TranslationServer.SetLocale(localeCode);
}
string current = TranslationServer.GetLocale();
言語選択メニュー
extends Control
@onready var language_button: OptionButton = %LanguageButton
var _locales: Array[Dictionary] = [
{"code": "en", "name": "English"},
{"code": "cs", "name": "Čeština"},
{"code": "de", "name": "Deutsch"},
{"code": "ja", "name": "日本語"},
]
func _ready() -> void:
for locale in _locales:
language_button.add_item(locale["name"])
# Set current selection
var current_locale: String = TranslationServer.get_locale()
for i in _locales.size():
if _locales[i]["code"] == current_locale:
language_button.selected = i
break
language_button.item_selected.connect(_on_language_selected)
func _on_language_selected(index: int) -> void:
TranslationServer.set_locale(_locales[index]["code"])
# Save preference — SettingsManager is a user-created autoload (see save-load skill)
SettingsManager.set_setting("general", "locale", _locales[index]["code"])
5. 右から左(RTL)への対応
アラビア語、ヘブライ語、ペルシア語では、Control に layout_direction(LOCALE は現在のロケールに自動追従します)と、URL やパスが完全に反転しないようにする structured_text_type を設定し、対象の文字体系をカバーするフォントを用意する必要があります。Godot のデフォルトフォントは対応していません。ロケールが変わるたびに、レイアウト方向を再設定してください。TranslationServer にはシグナルがありません。_notification をオーバーライドし、Node.NOTIFICATION_TRANSLATION_CHANGED(MainLoop にも同じ名前の定数があります)を監視してください。購読処理を行わないため、切断するハンドラーもありません。
詳しい手順、コントロールごとのプロパティ一覧、混在する方向のテキストに使う BBCode、C# の LocaleAwarePanel については、references/rtl-support.md を参照してください。
6. ロケール対応の書式設定
GDScript には、ロケール対応の桁区切りや日付書式設定がありません。"%d" % 1234567 は常に 1234567 になるため、桁区切りは手動で行います(TextServer.format_number() は数字をロケールの数字体系に変換するだけです)。C# では対応しています。TranslationServer.GetLocale() から CultureInfo を取得し(_ を - に置き換えます)、ToString("N"/"C"/"d", culture) を使用してください。
両方のヘルパーの詳しい説明は、references/locale-formatting.md を参照してください。
7. プロジェクト構成
推奨されるファイル構成
res://
├── translations/
│ ├── game.csv # Main game translations
│ ├── ui.csv # UI-specific translations
│ └── items.csv # Item names and descriptions
├── fonts/
│ ├── default_font.ttf # Latin, Cyrillic
│ └── cjk_font.ttf # Chinese, Japanese, Korean
└── themes/
└── default_theme.tres # Font assignments per locale
翻訳キーの規約
# Category_Context_Description
MENU_MAIN_START # Main menu, start button
MENU_MAIN_QUIT # Main menu, quit button
HUD_HEALTH_LABEL # In-game HUD, health label
DIALOGUE_NPC_GREETING # NPC dialogue, greeting line
ITEM_SWORD_NAME # Inventory item name
ITEM_SWORD_DESC # Inventory item description
8. よくある問題
| 症状 | 原因 | 解決方法 |
|---|---|---|
| 翻訳キーがテキストの代わりに表示される | 翻訳ファイルが Project Settings に登録されていない | Project Settings → Localization → Translations に追加します |
| ロケールを切り替えてもテキストが更新されない | tr() ではなく文字列リテラルを使用している | ユーザーに表示する文字列をすべて tr() で囲みます |
| シーン変更後に Label にキーが表示される | このシーンでまだ実行されていないコードによって、実行時に翻訳が追加されている | 翻訳を実行時ではなく Project Settings に登録します |
| RTL テキストが LTR で描画される | layout_direction が設定されていない | ルート Control で RTL または LOCALE に設定します |
| フォントに文字が表示されない | フォントに必要な Unicode 範囲が含まれていない | 対象の文字体系をカバーするフォントをインポートします(Noto Sans を推奨) |
| CSV で複数形が機能しない | Godot 4.6 より前の CSV には複数形がなく、4.6 以降では ?plural 列または継続行が不足している | 4.6 以降では ?plural 列を追加します(§10)。4.6 より前では PO を使用します |
翻訳で %s がそのまま表示される | tr() の結果をフォーマットせず、キーとして使用している | tr("KEY") % value を使用し、tr("KEY" % value) は使わないでください |
9. エディターでのロケールプレビュー(Godot 4.5 以降)
Godot 4.5 では、2D エディターの View メニューに Preview Translation サブメニューが追加されます。エディターのビューポートで、読み込み済みの任意のロケールに切り替えて再描画できるため、翻訳が長くなった場合のはみ出しを見つけたり、Play モードに入らずに RTL のレイアウトを確認したりできます。エディター内のみの機能であり、エクスポートしたビルドには影響しません。
手順と QA 上の利点については、references/editor-preview.md を参照してください。
10. CSV の複数形とコンテキストへの対応(Godot 4.6 以降)
Godot 4.6 では、CSV 翻訳に任意のヘッダー列 ?context と ?plural、さらに任意の ?pluralrule 行が追加され、コンテキストの曖昧さ解消と複数形(以前は PO のみ対応)が CSV でも使えるようになりました。追加の複数形は空のキーを持つ継続行に記述するため、ロシア語、ポーランド語、アラビア語など、複数形が 3 種類以上ある言語にも対応できます。Control の自動翻訳ではこれらの行はスキップされるため、自分で tr() / tr_n() を呼び出してください。
列のリファレンス、CSV の例、tr() / tr_n() の使用方法(GDScript + C#)については、references/csv-plural-context.md を参照してください。
11. 実装チェックリスト
- ユーザー向けのすべての文字列で
tr()を使用している(または、Control ノードの翻訳キーとして設定している) - 翻訳ファイル(CSV または PO)が「プロジェクト設定 → ローカライズ → 翻訳」に登録されている
- 実行時に
TranslationServer.set_locale()で言語を切り替えられる - ゲームの起動時に言語設定が保存・復元される
- フォントが対象言語の文字セット(ラテン文字、CJK、アラビア文字など)をすべてカバーしている
- RTL 言語では、ルート UI コンテナの
layout_directionがRTLまたはLOCALEに設定されている - フォーマット文字列(
%s、%d)はtr()の後に適用している(前ではなく) - 翻訳キーの命名規則に一貫性がある
- UI レイアウトが言語によるテキストの長さの違いに対応している(幅をハードコードしていない)
- すべての対象言語に複数形を指定している — PO、または Godot 4.6 以降では CSV の
?plural行を使用 - 翻訳の品質確認にはテスト実行ではなく、エディターロケールプレビュー(2D エディターの「表示 → 翻訳をプレビュー」)を使用している(Godot 4.5 以降)
- 同じキーが異なる UI コンテキストで異なる意味を持つ場合は、CSV の
?context列を使用している(Godot 4.6 以降) - CSV の複数形には
?plural列を使用し、追加の複数形ごとに継続行を 1 行追加している(?pluralrule行はロケールの規則を上書きする場合のみ使用)(Godot 4.6 以降)