Skip to main content

คู่มือโลคัลไลเซชันเกม Godot อย่างครบถ้วน

ตั้งแต่ TranslationServer จนถึงแบบอักษรสำรอง ทำโลคัลไลเซชันเกม Godot ด้วย CSV, ไฟล์ PO, GDScript และการแปลอัตโนมัติด้วย AI

1

พื้นฐาน TranslationServer

TranslationServer ในตัวของ Godot เป็นแกนกลางระบบโลคัลไลเซชัน โหลดทรัพยากรคำแปลตอนเริ่มต้นและค้นหาคีย์ผ่านฟังก์ชัน tr() ทุกการเรียก tr() ใน GDScript จะผ่าน 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 ดีกว่า menu_start_button_text_label
3

ไฟล์แปล PO / Gettext

ไฟล์ PO (Portable Object) เป็นมาตรฐานอุตสาหกรรมสำหรับโลคัลไลเซชันซอฟต์แวร์ Godot 4.x รองรับ PO โดยตรงพร้อมพหูพจน์ การแยกบริบท และความคิดเห็นนักแปล สร้างหนึ่งไฟล์ .po ต่อภาษาในไดเรกทอรี locale/

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 รองรับ msgctxt สำหรับแยกบริบท เช่น 'OPEN' ที่เป็นคำกริยาเทียบกับคำคุณศัพท์ msgid_plural สำหรับพหูพจน์ และความคิดเห็นนักแปล (บรรทัด #.) เพื่อให้บริบทเกี่ยวกับตำแหน่งและวิธีใช้ข้อความ
4

การใช้คำแปลใน GDScript

ใช้ tr() ที่ใดก็ได้ใน GDScript เพื่อแปลข้อความ ใช้ร่วมกับตัวดำเนินการ % ของ 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 รองรับลำดับแบบอักษรสำรอง เมื่อรูปอักขระหายจากแบบอักษรหลัก Godot จะตรวจแบบอักษรสำรองตามลำดับ หากไม่มี ข้อความที่ไม่ใช่ละตินจะแสดงเป็นสี่เหลี่ยมว่าง

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
ใช้ตระกูลแบบอักษร Noto ของ Google ซึ่งครอบคลุมสคริปต์ Unicode เกือบทั้งหมด เพิ่ม Noto Sans JP, Noto Sans KR, Noto Sans SC และ Noto Sans Arabic เป็นแบบอักษรสำรอง สำหรับเกมพิกเซลอาร์ต ให้พิจารณา Noto Sans Mono หรือแบบอักษรบิตแมปที่มีชุด CJK ระวังขนาดรวม เพราะแบบอักษร CJK เต็มอาจมีขนาด 15-20 MB ต่อไฟล์
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() จะเขียนทับผลแปลอัตโนมัติ สำหรับข้อความไดนามิก ให้ใช้ tr() อย่างชัดเจนในโค้ด และเพราะระบบใช้ tr() กับค่าข้อความตามตัวอักษร พร็อพเพอร์ตี text ต้องมีคีย์คำแปล ไม่ใช่ข้อความต้นฉบับที่มนุษย์อ่านได้
8

การใช้ภาษาสำรองอัจฉริยะด้วย LocaleChain

TranslationServer ของ Godot จะถอยไปใช้ภาษาเริ่มต้นของโปรเจกต์ทันทีเมื่อไม่มีรูปแบบตามภูมิภาค ผู้เล่น pt-BR ที่มีเพียง pt-PT จึงเห็นอังกฤษ LocaleChain แก้ด้วยการผสานคำแปลจากลำดับภาษาสำรองที่กำหนดค่าได้เข้า TranslationServer ตอนกำหนดค่า

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

ทำให้การแปลเกมเป็นอัตโนมัติ

เมื่อตั้งค่าโลคัลไลเซชันเสร็จแล้ว ให้แปลไฟล์ CSV หรือ PO ด้วย AI ทำให้การแปลข้อความเกม UI คำอธิบายไอเท็ม และบทสนทนาเป็นอัตโนมัติจาก IDE หรือไปป์ไลน์ CI/CD

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 จับคีย์ที่หายไปและตัวยึดตำแหน่งเสียหายก่อนส่งขึ้นใช้งาน แล้วทดสอบ UI ด้วยคำแปลจำลองผ่าน i18n-pseudo ก่อนคำแปลจริงจะมาถึง

ข้อผิดพลาดที่พบบ่อย

ยังไม่ได้นำเข้าไฟล์แปล

Godot ต้องนำเข้าไฟล์ .csv และ .po ก่อนใช้ หากคำแปลไม่แสดง ให้ตรวจว่าไฟล์อยู่ใน Project Settings > Localization > Translations สำหรับ CSV ให้ตรวจว่า Godot สร้างไฟล์ .translation ในไดเรกทอรี .godot/imported/ แล้ว

ค่า CSV ที่มีจุลภาคหรือเครื่องหมายคำพูดทำให้แยกวิเคราะห์เสียหาย

ค่าที่มีจุลภาคต้องครอบด้วยเครื่องหมายคำพูดคู่ ค่าที่มีเครื่องหมายคำพูดคู่ต้องหลีกเป็น "" เครื่องหมายที่หายไปทำให้ทั้งแถวแยกผิดและมักเลื่อนคอลัมน์ถัดไปโดยไม่แจ้งเตือน

ข้อความ CJK หรืออาหรับแสดงสี่เหลี่ยมว่าง

แบบอักษรหลักไม่มีรูปอักขระของสคริปต์เหล่านี้ เพิ่มแบบอักษรสำรองในทรัพยากร Theme หรือ LabelSettings หากไม่มี รูปอักขระจะเป็นสี่เหลี่ยมว่าง ใช้ Noto Sans รุ่นต่างๆ เพื่อครอบคลุม Unicode

จำนวนรูปพหูพจน์ในส่วนหัว PO ไม่ถูกต้อง

หากค่า nplurals ในส่วนหัว PO ไม่ตรงกับจำนวนรายการ msgstr จริง Godot อาจหยุดทำงานหรือแสดงรูปพหูพจน์ผิด ตรวจว่าส่วนหัว Plural-Forms ตรงกับข้อกำหนด CLDR ของแต่ละภาษาเป้าหมายเสมอ

Auto Translate ถูกโค้ดเขียนทับ

การตั้งพร็อพเพอร์ตี text ของโหนดใน GDScript หลัง _ready() จะเขียนทับผลแปลอัตโนมัติ ให้ใช้แปลอัตโนมัติทั้งหมด โดยตั้งในเครื่องมือแก้ไขและไม่ตั้งในโค้ด หรือใช้ 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