Localization
Doodle Engine can display text directly or look it up through a localization key. Write text directly while working in one language. When you are ready to translate the game, use @key references to connect player-facing text to locale files.
For visual editing, see Localization in Studio. This guide explains the files and renderer APIs behind it: locale files, @key references, how resolution works, and how to translate the built-in interface. Localizing is incremental, so direct text and @key references can coexist in one project while you convert it.
Locale Files
Section titled “Locale Files”Create a YAML file for each language in content/locales/. Each entry pairs a localization key with the text for that language:
location.tavern.name: 'The Rusty Tankard'location.tavern.description: 'A cozy tavern with worn wooden tables.'character.bartender.name: 'Greta'bartender.greeting: 'Welcome! What can I do for you?'location.tavern.name: 'La Jarra Oxidada'location.tavern.description: 'Una taberna acogedora con mesas de madera gastadas.'character.bartender.name: 'Greta'bartender.greeting: '¡Bienvenido! ¿Qué puedo hacer por ti?'The filename sets the locale code: en.yaml becomes "en", and es.yaml becomes "es".
For a translation with paragraph breaks, use YAML’s | marker. It keeps the line breaks in the indented text that follows:
bartender.memory: | I've been having a good time.
It's been 84 years.Dialogue using @bartender.memory displays those paragraphs as one entry.
Using @keys
Section titled “Using @keys”Reference locale strings with the @ prefix in YAML content:
id: tavernname: '@location.tavern.name'description: '@location.tavern.description'And in .dlg dialogue files:
NODE start BARTENDER: @bartender.greeting
CHOICE @bartender.choice.hello GOTO hello ENDHow Resolution Works
Section titled “How Resolution Works”When the engine prepares text for the renderer, it resolves each @key reference:
- Looks up the key in the current locale’s data
- If found, returns the translated string
- If the key is missing, displays the
@keyso you can identify the missing translation
The engine does this while building each snapshot. See resolveText.
Changing Language at Runtime
Section titled “Changing Language at Runtime”A new game starts in the en locale. To begin in another language, call
setLocale from the renderer before or after starting the game. Loaded save
data restores the locale stored in that save.
Use the setLocale action:
const { actions } = useGame();actions.setLocale('es');Change the language from your renderer or shell by calling actions.setLocale() or engine.setLocale().
Naming Convention
Section titled “Naming Convention”Use a consistent key naming scheme:
# Locationslocation.<id>.namelocation.<id>.description
# Characterscharacter.<id>.namecharacter.<id>.bio
# Dialogue text<character_id>.<context><character_id>.choice.<choice_name>
# Itemsitem.<id>.nameitem.<id>.description
# Questsquest.<id>.namequest.<id>.descriptionquest.<id>.stage.<stage_id>
# Notificationsnotification.<event_name>
# Narratornarrator.<context>Translate the Built-in Interface
Section titled “Translate the Built-in Interface”Buttons, menus, panel headings, credits, and other text in the built-in renderer use ui.* keys. Add the keys you want to translate to each locale file:
ui.continue: Continuarui.end_dialogue: Terminar diálogoui.settings: Configuraciónui.new_game: Nuevo juegoui.credits: Créditosui.made_with_doodle_engine: Hecho con Doodle Engineui.back: VolverThe renderer uses its English default for a ui.* key omitted from a locale. Some keys contain placeholders such as {day}, {hours}, or {destination}. Keep those placeholders in the translated text so the renderer can insert the current value.
See UI Strings for the complete list of keys and English defaults. See Notifications for displaying short messages from dialogue effects.