Skip to main content

Godot 게임 현지화 완벽 가이드

TranslationServer부터 글꼴 대체까지, CSV, PO 파일, GDScript, AI 기반 자동 번역으로 Godot 게임을 현지화하는 방법을 알아보세요.

1

TranslationServer 기본 사항

Godot에 내장된 TranslationServer는 현지화 시스템의 핵심이에요. 시작할 때 번역 리소스를 불러오고 tr() 함수로 키에 해당하는 번역을 찾아요. GDScript에서 호출하는 모든 tr()은 TranslationServer를 거치므로 추가 라이브러리가 필요하지 않아요.

TranslationServer basics
# 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)
TranslationServer는 CSV, PO(Gettext), .translation(바이너리) 형식을 지원해요. OS.get_locale()로 시스템 로케일을 자동 감지하고 일치하는 번역 리소스를 선택해요. TranslationServer.set_locale()을 사용하면 언제든지 로케일을 재정의할 수 있어요.
2

CSV 번역 파일

CSV는 Godot 번역에 사용할 수 있는 가장 간단한 형식이에요. 한 파일에 모든 언어를 열로 보관해요. 첫 번째 열은 키이고 이후 각 열은 로케일이에요. Godot는 .csv 파일을 자동으로 가져와 .translation 리소스를 생성해요.

translations.csv
# 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!"
Importing CSV translations
# 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 files
쉼표나 줄바꿈이 포함된 값은 큰따옴표로 감싸세요. 값에 큰따옴표가 포함되어 있으면 ""로 이스케이프하세요. 키는 짧고 설명적으로 작성하세요. menu_start_button_text_label보다 MENU_START가 좋아요.
3

PO / Gettext 번역 파일

PO(Portable Object) 파일은 소프트웨어 현지화의 업계 표준이에요. Godot 4.x는 복수형, 문맥 구분, 번역가 주석을 포함한 PO를 기본으로 지원해요. locale/ 디렉터리에 언어마다 하나의 .po 파일을 만드세요.

locale/ja.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枚のコインを集めました。"
Loading PO files
# 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)
PO 파일은 문맥 구분(예: 동사 'OPEN'과 형용사 'OPEN')에 msgctxt를, 복수형에 msgid_plural을, 문자열이 어디서 어떻게 사용되는지 알려 주는 번역가 주석에 #. 줄을 사용할 수 있어요.
4

GDScript 번역 사용법

GDScript 어디에서나 tr()을 사용해 문자열을 번역할 수 있어요. 문자열 서식 지정에는 GDScript의 % 연산자를 함께 사용하세요. 안정적인 로케일 관리를 위해 로케일 감지, 저장, 전환과 신호 처리를 담당하는 Autoload 스크립트를 만드세요.

Using tr() in scenes
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 (Autoload)
# 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()
TranslationServer.set_locale()로 로케일을 변경해도 장면에 이미 렌더링된 텍스트는 자동으로 업데이트되지 않아요. 로케일을 변경한 뒤 보이는 모든 레이블, 버튼, 텍스트 노드에 tr()을 직접 다시 적용해야 해요. 로케일 관리자의 신호를 사용해 UI 장면이 새로 고침하도록 알리세요.
5

복수형과 플레이스홀더

Godot는 PO 파일의 복수형을 통해 복수형을 처리해요. 각 언어는 PO 헤더에서 자체 복수형 수식을 정의해요. GDScript의 % 연산자는 위치 기반 플레이스홀더(문자열은 %s, 정수는 %d)를 처리해요. 명명된 플레이스홀더에는 String.replace()를 사용하세요.

Plural forms by language
# 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 монет."
Placeholder formatting
# 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))
'if count == 1' 같은 복수형 로직을 하드코딩하지 마세요. 언어마다 복수형 규칙이 크게 달라요. 영어는 2가지, 러시아어는 3가지, 아랍어는 6가지, 일본어는 1가지 형식을 사용해요. 형식 선택은 PO 복수형 시스템에 맡기세요. CSV 파일은 복수형을 지원하지 않으므로 복수형이 필요한 콘텐츠에는 PO 파일을 사용하세요.
6

CJK, 아랍어 등을 위한 글꼴 대체

게임의 기본 글꼴에는 일본어, 한국어, 중국어, 아랍어, 태국어 문자가 없을 수 있어요. Godot 4.x는 글꼴 대체 체인을 지원해요. 기본 글꼴에 글리프가 없으면 순서대로 대체 글꼴을 확인해요. 이를 설정하지 않으면 비라틴 문자가 빈 사각형으로 표시돼요.

Font fallback setup
# 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)
RTL support
# 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
거의 모든 Unicode 문자 체계를 지원하는 Google Noto 글꼴 모음을 사용하세요. Noto Sans JP, Noto Sans KR, Noto Sans SC, Noto Sans Arabic을 대체 글꼴로 추가하세요. 픽셀 아트 게임이라면 Noto Sans Mono나 CJK 하위 집합을 포함한 비트맵 글꼴도 고려해 보세요. 전체 CJK 글꼴은 각각 15~20MB일 수 있으므로 총 글꼴 크기에 유의하세요.
7

장면 및 UI 현지화

Godot 장면을 현지화하는 방법은 세 가지예요. _ready()에서 tr()을 사용하거나, 편집기의 Auto Translate 속성을 사용하거나, RTL 언어처럼 다른 레이아웃이 필요한 언어에 완전히 다른 장면을 로드할 수 있어요.

Scene localization approaches
# 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())
Auto Translate는 노드의 text 속성에만 적용돼요. _ready() 이후 코드에서 text를 동적으로 설정하면 자동 번역 결과를 덮어써요. 동적으로 업데이트되는 텍스트에는 항상 코드에서 tr()을 명시적으로 사용하세요. 또한 자동 번역은 리터럴 text 값에 tr()을 적용하므로 text 속성에는 사람이 읽는 원문이 아니라 번역 키가 있어야 해요.
8

LocaleChain을 활용한 스마트 로케일 폴백

Godot의 TranslationServer는 지역 변형이 없을 때 프로젝트의 기본 로케일로 바로 대체해요. pt-PT 번역만 있으면 pt-BR 플레이어는 포르투갈어 대신 영어를 보게 돼요. LocaleChain은 설정 가능한 폴백 체인의 번역을 구성 시점에 병합해 이 문제를 해결해요.

LocaleChain plugin
# 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()
LocaleChain은 순수 GDScript 애드온이라 네이티브 확장이나 엔진 수정이 필요하지 않아요. Godot AssetLib에서 설치하거나 addons/locale_chain/ 폴더를 프로젝트에 복사하세요. CSV, PO, .translation 파일과 함께 작동해요.
9

게임 번역 자동화

현지화 설정이 끝나면 AI로 CSV 또는 PO 파일을 번역하세요. IDE나 CI/CD 파이프라인에서 게임 문자열, UI 텍스트, 아이템 설명, 대화를 바로 자동 번역할 수 있어요.

Terminal
# 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
점진적으로 번역하세요. 원본 파일에 새 키를 추가하면 전체를 다시 생성하지 말고 변경분만 번역하세요. 이렇게 하면 서사 대화나 문화적으로 민감한 콘텐츠에서 사람이 검토한 번역을 보존할 수 있어요.

번역 품질 자동화

i18n-validate로 누락된 키와 손상된 플레이스홀더를 출시 전에 찾아내세요. 실제 번역이 도착하기 전에는 i18n-pseudo의 의사 번역으로 UI를 테스트하세요.

흔한 실수

가져오지 않은 번역 파일

Godot에서 .csv와 .po 파일을 사용하려면 먼저 가져와야 해요. 번역이 표시되지 않으면 Project Settings > Localization > Translations에 파일이 나열되어 있는지 확인하세요. CSV의 경우 Godot가 .godot/imported/ 디렉터리에 .translation 파일을 생성했는지도 확인하세요.

쉼표나 따옴표가 있는 CSV 값의 구문 분석 실패

쉼표가 포함된 값은 큰따옴표로 감싸야 해요. 큰따옴표가 포함된 값은 ""로 이스케이프해야 해요. 따옴표가 하나라도 빠지면 전체 행이 잘못 분석되고 이후의 모든 열이 밀릴 수 있으며, 오류가 눈에 띄지 않는 경우도 많아요.

빈 사각형으로 표시되는 CJK 또는 아랍어 텍스트

기본 글꼴에 해당 문자 체계의 글리프가 없어요. Theme 또는 LabelSettings 리소스에 대체 글꼴을 추가하세요. 대체 글꼴이 없으면 누락된 글리프가 빈 사각형으로 표시돼요. Unicode를 폭넓게 지원하려면 Noto Sans 변형을 사용하세요.

PO 헤더의 잘못된 복수형 개수

PO 헤더의 nplurals 값이 실제 msgstr 항목 수와 일치하지 않으면 Godot가 비정상 종료되거나 잘못된 복수형을 표시할 수 있어요. 각 대상 언어에서 Plural-Forms 헤더가 CLDR 사양과 일치하는지 항상 확인하세요.

코드로 덮어쓴 Auto Translate 결과

_ready() 이후 GDScript에서 노드의 text 속성을 설정하면 자동 번역 결과를 덮어써요. 자동 번역만 사용하거나(편집기에서 text를 설정하고 코드에서는 설정하지 않음) 코드에서 tr()만 사용하세요. 두 방식을 섞으면 동작이 일관되지 않아요.

권장 프로젝트 구조

Project Structure
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을 확인하지 않고 프로젝트의 기본 로케일로 바로 대체해요.

Terminal
# Install from Godot Asset Library
# Search: locale-chain-godot
Configuration
var lc = LocaleChain.new()
lc.configure({
    "pl": ["pl_PL", "en"],
    "pt_BR": ["pt", "en"],
    "zh_Hant_HK": ["zh_Hant", "zh", "en"],
})

지원되는 프레임워크 전체 목록과 75개의 기본 제공 체인은 로케일 폴백 가이드에서 확인하세요. Learn more →

Godot 현지화 FAQ