
Godot 게임 현지화 완벽 가이드
TranslationServer부터 글꼴 대체까지, CSV, PO 파일, GDScript, AI 기반 자동 번역으로 Godot 게임을 현지화하는 방법을 알아보세요.
TranslationServer 기본 사항
Godot에 내장된 TranslationServer는 현지화 시스템의 핵심이에요. 시작할 때 번역 리소스를 불러오고 tr() 함수로 키에 해당하는 번역을 찾아요. GDScript에서 호출하는 모든 tr()은 TranslationServer를 거치므로 추가 라이브러리가 필요하지 않아요.
# TranslationServer is Godot's built-in localization system.
# It loads translations at startup and resolves keys via tr().
# Set the game's locale
TranslationServer.set_locale("ja")
# Get the current locale
var current = TranslationServer.get_locale() # "ja"
# Translate a key — works everywhere in GDScript
var text = tr("MENU_START") # "ゲームスタート"
# Translate with context (Godot 4.x)
var text = tr("OPEN", "verb") # "Open" (action)
var text = tr("OPEN", "adj") # "Open" (state)CSV 번역 파일
CSV는 Godot 번역에 사용할 수 있는 가장 간단한 형식이에요. 한 파일에 모든 언어를 열로 보관해요. 첫 번째 열은 키이고 이후 각 열은 로케일이에요. Godot는 .csv 파일을 자동으로 가져와 .translation 리소스를 생성해요.
# translations.csv
# First column = key, subsequent columns = locale codes
keys,en,ja,de,es
MENU_START,Start Game,ゲームスタート,Spiel starten,Iniciar juego
MENU_SETTINGS,Settings,設定,Einstellungen,Configuración
MENU_QUIT,Quit,終了,Beenden,Salir
ITEM_SWORD,Sword,剣,Schwert,Espada
ITEM_SHIELD,Shield,盾,Schild,Escudo
DIALOG_GREETING,"Hello, adventurer!",冒険者よ、こんにちは!,"Hallo, Abenteurer!","¡Hola, aventurero!"# In Godot Editor:
# 1. Place your .csv file in the project (e.g., res://translations.csv)
# 2. Godot auto-imports it — creates .translation resources
# 3. Go to Project > Project Settings > Localization > Translations
# 4. Add the generated .translation filesPO / Gettext 번역 파일
PO(Portable Object) 파일은 소프트웨어 현지화의 업계 표준이에요. Godot 4.x는 복수형, 문맥 구분, 번역가 주석을 포함한 PO를 기본으로 지원해요. locale/ 디렉터리에 언어마다 하나의 .po 파일을 만드세요.
# translations.po — Gettext format for Godot
# Place in res://locale/ja.po
msgid ""
msgstr ""
"Language: ja\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=1; plural=0;\n"
# Simple translation
msgid "MENU_START"
msgstr "ゲームスタート"
# Translation with context (disambiguates identical source strings)
msgctxt "verb"
msgid "OPEN"
msgstr "開く"
msgctxt "adj"
msgid "OPEN"
msgstr "開いている"
# Plural form
msgid "You collected %d coin."
msgid_plural "You collected %d coins."
msgstr[0] "%d枚のコインを集めました。"# Project Settings > Localization > Translations
# Add each .po file:
# res://locale/en.po
# res://locale/ja.po
# res://locale/de.po
# res://locale/es.po
# Or load programmatically:
func _ready():
var translation = load("res://locale/ja.po")
TranslationServer.add_translation(translation)GDScript 번역 사용법
GDScript 어디에서나 tr()을 사용해 문자열을 번역할 수 있어요. 문자열 서식 지정에는 GDScript의 % 연산자를 함께 사용하세요. 안정적인 로케일 관리를 위해 로케일 감지, 저장, 전환과 신호 처리를 담당하는 Autoload 스크립트를 만드세요.
extends Control
func _ready():
# Simple key lookup
$TitleLabel.text = tr("MENU_START")
# With string formatting (positional)
$GreetingLabel.text = tr("DIALOG_GREETING_NAME") % [player_name]
# With multiple placeholders
$StatusLabel.text = tr("PLAYER_STATUS") % [player_name, level, health]
# Context-aware translation (Godot 4.x)
$ActionButton.text = tr("OPEN", "verb")
# Update UI when locale changes
TranslationServer.set_locale("de")
_update_ui()
func _update_ui():
# Re-apply all translated strings
$TitleLabel.text = tr("MENU_START")
$GreetingLabel.text = tr("DIALOG_GREETING_NAME") % [player_name]# locale_manager.gd — Register as Autoload in Project Settings
extends Node
signal locale_changed(new_locale: String)
const SUPPORTED_LOCALES = ["en", "ja", "de", "es", "fr", "ko", "zh"]
func _ready():
var system_locale = OS.get_locale_language()
if system_locale in SUPPORTED_LOCALES:
set_locale(system_locale)
else:
set_locale("en")
func set_locale(locale: String):
TranslationServer.set_locale(locale)
locale_changed.emit(locale)
func get_locale() -> String:
return TranslationServer.get_locale()복수형과 플레이스홀더
Godot는 PO 파일의 복수형을 통해 복수형을 처리해요. 각 언어는 PO 헤더에서 자체 복수형 수식을 정의해요. GDScript의 % 연산자는 위치 기반 플레이스홀더(문자열은 %s, 정수는 %d)를 처리해요. 명명된 플레이스홀더에는 String.replace()를 사용하세요.
# Godot uses Gettext PO plural rules.
# Each language defines its own plural formula.
# English (2 forms: one, other)
msgid "You collected %d coin."
msgid_plural "You collected %d coins."
msgstr[0] "You collected %d coin."
msgstr[1] "You collected %d coins."
# Japanese (1 form: other — no singular/plural distinction)
msgid "You collected %d coin."
msgid_plural "You collected %d coins."
msgstr[0] "%d枚のコインを集めました。"
# Russian (3 forms: one, few, many)
msgid "You collected %d coin."
msgid_plural "You collected %d coins."
msgstr[0] "Вы собрали %d монету."
msgstr[1] "Вы собрали %d монеты."
msgstr[2] "Вы собрали %d монет."# GDScript string formatting with tr()
# Positional placeholders with %
var msg = tr("SCORE_MSG") % [score] # "Score: %d" → "Score: 1500"
var msg = tr("STATS") % [name, level, hp] # "%s — Lv %d — HP: %d"
# Named placeholders (manual replacement)
var template = tr("WELCOME_BACK")
var msg = template.replace("{player}", name).replace("{days}", str(days))CJK, 아랍어 등을 위한 글꼴 대체
게임의 기본 글꼴에는 일본어, 한국어, 중국어, 아랍어, 태국어 문자가 없을 수 있어요. Godot 4.x는 글꼴 대체 체인을 지원해요. 기본 글꼴에 글리프가 없으면 순서대로 대체 글꼴을 확인해요. 이를 설정하지 않으면 비라틴 문자가 빈 사각형으로 표시돼요.
# Godot 4.x supports font fallback chains.
# When a glyph is missing from the primary font, fallbacks are checked in order.
# In the Editor:
# 1. Create a LabelSettings or Theme resource
# 2. Set the primary font (e.g., Noto Sans for Latin)
# 3. Add fallback fonts: Noto Sans JP, KR, SC, Arabic
# Programmatically:
func setup_fonts():
var font = FontFile.new()
font.load_dynamic_font("res://fonts/NotoSans-Regular.ttf")
var fallback_jp = FontFile.new()
fallback_jp.load_dynamic_font("res://fonts/NotoSansJP-Regular.ttf")
font.add_fallback(fallback_jp)
$Label.add_theme_font_override("font", font)# Right-to-left (RTL) support for Arabic, Hebrew, etc.
# In the Editor:
# Select your Control node > Layout > Text Direction = RTL
# Programmatically:
func setup_rtl():
var locale = TranslationServer.get_locale()
var rtl_locales = ["ar", "he", "fa", "ur"]
if locale.substr(0, 2) in rtl_locales:
$Label.text_direction = Control.TEXT_DIRECTION_RTL
$Container.layout_direction = Control.LAYOUT_DIRECTION_RTL장면 및 UI 현지화
Godot 장면을 현지화하는 방법은 세 가지예요. _ready()에서 tr()을 사용하거나, 편집기의 Auto Translate 속성을 사용하거나, RTL 언어처럼 다른 레이아웃이 필요한 언어에 완전히 다른 장면을 로드할 수 있어요.
# Approach 1: Translate in _ready() using tr()
extends Control
func _ready():
$StartButton.text = tr("MENU_START")
$SettingsButton.text = tr("MENU_SETTINGS")
$QuitButton.text = tr("MENU_QUIT")
# Approach 2: Use auto-translate in the editor
# Set the Text property to the translation key (e.g., "MENU_START")
# and enable "Auto Translate" on the node.
# Approach 3: Locale-specific scenes for complex layouts
func load_localized_scene():
var locale = TranslationServer.get_locale().substr(0, 2)
var path = "res://ui/main_menu_%s.tscn" % locale
if ResourceLoader.exists(path):
add_child(load(path).instantiate())
else:
add_child(load("res://ui/main_menu_en.tscn").instantiate())LocaleChain을 활용한 스마트 로케일 폴백
Godot의 TranslationServer는 지역 변형이 없을 때 프로젝트의 기본 로케일로 바로 대체해요. pt-PT 번역만 있으면 pt-BR 플레이어는 포르투갈어 대신 영어를 보게 돼요. LocaleChain은 설정 가능한 폴백 체인의 번역을 구성 시점에 병합해 이 문제를 해결해요.
# LocaleChain for Godot — smart locale fallback
# Install from Godot AssetLib or copy addons/locale_chain/ into your project
# Problem: Godot's TranslationServer falls back directly to the default locale.
# A pt-BR player with only pt-PT translations sees English, not Portuguese.
# Solution: One-line setup
func _ready():
LocaleChain.configure() # Uses built-in fallback chains
# Now pt-BR falls back to pt-PT → pt → default
# es-MX falls back to es-419 → es → default
# zh-Hant-HK falls back to zh-Hant-TW → zh-Hant → default
# Custom configuration:
func _ready():
# Override specific chains
LocaleChain.configure({"pt-BR": ["pt"]})
# Full custom — only your chains
LocaleChain.configure(
{"pt-BR": ["pt-PT", "pt"], "es-MX": ["es-419", "es"]},
false # don't merge defaults
)
# Reset to original state
LocaleChain.reset()게임 번역 자동화
현지화 설정이 끝나면 AI로 CSV 또는 PO 파일을 번역하세요. IDE나 CI/CD 파이프라인에서 게임 문자열, UI 텍스트, 아이템 설명, 대화를 바로 자동 번역할 수 있어요.
# Translate your Godot locale files with AI
# CSV files:
# In your IDE, ask your AI assistant:
> Translate translations.csv to Japanese, Korean, and German
# PO files:
> Translate locale/en.po to ja, ko, de
# Or use the CLI in CI/CD:
npx i18n-agent translate locale/en.po --lang ja,ko,de
# The tool preserves:
# - CSV column structure and delimiters
# - PO msgctxt, msgid_plural, and plural forms
# - Placeholder syntax (%s, %d, {name})
# - Comments and metadata headers번역 품질 자동화
흔한 실수
가져오지 않은 번역 파일
쉼표나 따옴표가 있는 CSV 값의 구문 분석 실패
빈 사각형으로 표시되는 CJK 또는 아랍어 텍스트
PO 헤더의 잘못된 복수형 개수
코드로 덮어쓴 Auto Translate 결과
권장 프로젝트 구조
my_godot_game/
├── addons/
│ └── locale_chain/ # LocaleChain plugin (optional)
│ ├── fallback_map.gd
│ ├── locale_chain.gd
│ └── plugin.cfg
├── fonts/
│ ├── NotoSans-Regular.ttf # Primary font (Latin)
│ ├── NotoSansJP-Regular.ttf # Japanese fallback
│ ├── NotoSansKR-Regular.ttf # Korean fallback
│ └── NotoSansArabic-Regular.ttf # Arabic fallback
├── locale/
│ ├── en.po # English (source)
│ ├── ja.po # Japanese
│ ├── de.po # German
│ ├── es.po # Spanish
│ └── ar.po # Arabic
├── translations.csv # Alternative: CSV format
├── scenes/
│ └── ui/
│ ├── main_menu.tscn
│ └── settings_menu.tscn
├── scripts/
│ ├── locale_manager.gd # Autoload for locale management
│ └── ui/
│ └── main_menu.gd
├── project.godot
└── export_presets.cfg다른 번역 형식:
지금 i18n Agent 사용해 보기
번역 파일을 여기에 드롭
JSON, YAML, PO, XML, CSV, Markdown, Properties
또는 클릭하여 파일 선택
대상 언어
locale-chain-godot를 활용한 로케일 폴백
pl_PL 같은 지역 로케일에 번역 키가 없으면 Godot는 상위 로케일 pl을 확인하지 않고 프로젝트의 기본 로케일로 바로 대체해요.
# Install from Godot Asset Library
# Search: locale-chain-godotvar lc = LocaleChain.new()
lc.configure({
"pl": ["pl_PL", "en"],
"pt_BR": ["pt", "en"],
"zh_Hant_HK": ["zh_Hant", "zh", "en"],
})지원되는 프레임워크 전체 목록과 75개의 기본 제공 체인은 로케일 폴백 가이드에서 확인하세요. Learn more →