Urho3D localization is the process of making a C++ game or interactive 2D/3D application understandable in more than one language without breaking its menus, controls, story or saved progress. If you are looking for how to translate an Urho3D game, use Urho3D JSON localization files, or switch the interface language at runtime, this guide explains the built-in Localization subsystem, the E_CHANGELANGUAGE event and the checks needed before release. A reader should finish with a plan they can actually test, not just a translated text file.
The important Urho3D detail is that translating a string collection and updating every visible widget are separate jobs. The engine documents LoadJSONFile, Get, SetLanguage and optional automatic localization for Text widgets. But a language selection can also affect embedded images, layout widths, keyboard prompts and descriptions created by your own application logic. A successful multilingual game preserves the same actions and state in each supported language, while saying those actions naturally to the player.
We will follow a fictional game called Harbor Lanterns, in which a player explores a pier, checks an inventory, reads a warning about deleting an unfinished save and selects a language from the pause menu. All examples are illustrative and do not claim to be an official ready-made Urho3D project. The guide keeps programming responsibilities, linguistic review and player-facing validation distinct so that teams can find errors without blaming translation for every broken screen.
Quick answer: how to localize Urho3D
- Load UTF-8, BOM-free JSON collections through the Urho3D Localization subsystem and define stable, case-sensitive language names and message IDs.
- Keep game logic and save data independent of the translated label; use Get(id) only where text is presented.
- Change languages deliberately with SetLanguage and update custom widgets in response to E_CHANGELANGUAGE.
- Use SetAutoLocalizable(true) for appropriate Text elements where the display value is the message identifier, after validating your UI design.
- Ship fonts and language-specific assets that genuinely render the supported scripts, then test the actual target device.
- Test missing keys, dynamic parameters, plural forms, right-to-left behavior, error states, input and packaged-resource paths.
What this guide covers
This guide is for developers, translators and reviewers working with Urho3D projects. It is an implementation and quality guide, not a claim that Urho3D certifies particular languages or supplies translations. Code examples illustrate a design principle and should be checked against your engine fork and application structure. The central question is whether a person can perform the same intended task in every supported language. If a tool makes that task impossible or confusing, localization is not finished.
Contents
- Understand the engine’s localization boundaries
- Make a reliable catalog and loading plan
- Refresh language-sensitive interfaces
- Solve fonts, text layout and variable messages
- Avoid state and release failures
- Diagnose 30 real-world problems
- Follow a four-week delivery plan
- Check frequently asked questions and sources
A minimal annotated Urho3D pattern
The conceptual example below shows where text lookup and language selection belong. The code assumes the application’s Context and UI lifecycle are already established. The test is not whether a snippet compiles in isolation, but whether a stable message ID is resolved each time the selected language changes.
// Illustrative Urho3D C++ outline; adapt ownership to your project.
Localization* l10n = GetSubsystem<Localization>();
l10n->LoadJSONFile("StringsEnDe.json");
auto* label = new Text(context_);
label->SetText("menu.start");
label->SetAutoLocalizable(true);
// For custom presentation, subscribe to E_CHANGELANGUAGE
// and update visual strings by calling l10n->Get("key").
l10n->SetLanguage("de");
A representative catalog entry could use a stable ID such as menu.start and a map of approved language names to values. In Urho3D’s documented multi-language JSON format, each message ID maps to an object whose properties are language names. Use UTF-8 without a BOM and keep source-controlled copies to make a regression trace possible.
1. Where Urho3D’s own localization system starts and stops
Urho3D provides a dedicated Localization subsystem, unlike a generic renderer that leaves every text lookup to game code. Its strength is that a language change is a named engine event rather than an accidental mutation of scattered labels. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Create a tiny scene with one Start button, one warning and one item description. Put the wording behind stable IDs and let the currently selected language determine only the visible strings, never the underlying commands. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: Do not describe the subsystem as a complete translation management platform. It does not by itself supply reviewed prose, plural grammar for every locale, all script shaping or a multilingual customer-support workflow. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Run the scene with a real second-language collection and verify that identical control actions occur before and after switching. Record exactly which UI elements respond automatically and which need custom event handlers. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
2. Construct an audit-friendly JSON collection
The documented Urho3D string collection maps a string ID to language names and translated values. That structure is approachable, but misspelt identifiers or mixed-case language labels can quietly create separate entries. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Use keys such as menu.start, save.delete_confirm and inventory.lantern_count. Keep the source meaning, screenshot reference, context note and named owner in a companion worksheet outside the runtime JSON. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: Never use the English sentence itself as the unique persistent identity of a save action. Source copy often improves, and a change of punctuation must not orphan translations or alter how code finds a command. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Check JSON decoding and catalog completeness before launching the game. Compare the key sets by machine and have reviewers verify that each equivalent is the right kind of instruction, not merely plausible vocabulary. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
3. Load resources in a known order
The engine documentation shows Localization::LoadJSONFile and explains that files can contain one or several languages. Initialization order matters because it determines what language is initially available and what UI sees on its first draw. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Choose a deterministic catalog loading routine at startup. Record resource names in version control, normalize intended locale identifiers in your own preferences layer and apply the user’s saved choice after the collections are available. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: A packaged binary can succeed on a developer machine because of loose data folders while failing in a distributed build. A missing collection is different from a translation that has not been written. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Test a fresh installation with no saved language preference, then a returning installation with a supported preference, then a returning installation whose former language pack is deliberately absent. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
4. SetLanguage and E_CHANGELANGUAGE are a contract
Urho3D sends E_CHANGELANGUAGE when the active language changes. Text that was produced manually earlier does not know it should refresh unless the application subscribes and reassigns the value. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Subscribe to the event in the component responsible for a widget group, and let that component fetch new display strings from Localization::Get. Also refresh graphics with language-specific wording and recompute dimensions when needed. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: A global event handler that resets the entire scene is too blunt. Refresh presentation while preserving inventory, camera, quest flags, pending confirmation and input focus. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Switch languages while a confirmation dialog is open. The dialog wording should change, the highlighted choice should remain understandable, and clicking either choice must still trigger the original action. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
5. Automatic localization for Text widgets
Urho3D documents Text::SetAutoLocalizable(true), with the initial text acting as the translation identifier. This is useful for stable labels but can surprise developers who place an already translated sentence into that field. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Apply automatic localization to simple labels with explicit keys and let one centralized location define each widget’s purpose. For formatted counters, evaluate whether a separate refresh function is clearer. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: Do not assume auto-localization covers Image, button iconography, tooltip generators or custom components. A widget may be visually tied to Text but still keep other untranslated information in adjacent assets. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Put one automatically localized label beside one manually refreshed text field. Switch three times and inspect that neither double-translates, displays a key or leaves the initial language behind. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
6. Fonts, glyphs and writing-system limits
Urho3D text support and localization lookup solve different tasks. UTF-8 bytes can be correct even when the chosen font omits needed letters or when the rendering path lacks the shaping required by a writing system. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Inventory scripts before selecting licensed font files. Create a test sentence with accents, numbers, punctuation, combining marks and representative target-language words, then render it in the exact UI controls used by the shipped game. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: A square placeholder glyph is not a linguistic error, and right-to-left legibility cannot be inferred from a successful English or Cyrillic test. Avoid claiming full language support when shaping has not been validated. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Capture the same screen on every target graphics backend and device class. Have a fluent reader inspect visual order, glyph joining, cursor behavior and whether a long translated heading obscures actionable controls. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
7. Layout for text expansion and smaller screens
A two-word English button may become a longer phrase elsewhere. Urho3D’s UI layout still has physical size constraints, and localized strings should be measured in their rendered font before a dialog is approved. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Prefer flexible containers and rules that preserve readable font size. Test longest probable text in menu items, narrow inventory slots, subtitle boxes and tooltips, including windows resized by the user. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: Truncating the confirmation verb can reverse or obscure meaning. Treat overflow as a layout problem first, then ask a qualified reviewer for a shorter accurate wording only when design constraints remain. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Test at the narrowest supported resolution with accessibility text scaling where available. The whole message, both actions and the focus indicator must stay visible without requiring an unintended drag. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
8. Numbers, dates, plurals and variables
A translated static string is not always enough for ‘one lantern remaining’ versus ‘two lanterns remaining’. Some languages use several plural categories and the punctuation around numbers and units also differs. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Feed typed values to a locale-aware formatting layer and return a complete localized message. Maintain separate grammatical forms as needed, with explicit zero and large-number tests from the chosen language rules. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: Do not concatenate a number, an English noun and another translated suffix. That construction breaks grammar, can alter meaning and makes translators unable to see the sentence they are expected to create. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Display 0, 1, 2, 5 and 101 objects in each supported locale, including a negative number where the game’s logic permits it. Review wording alongside displayed separators and units. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
9. Stable controls, save files and state
A game can display a localized ‘Continue’ button while still using a language-neutral internal command. That separation is vital when users change languages during play or load older save data. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Make menu actions, resource hashes, quest identifiers and serialized state explicitly independent of the human-readable phrase. Store a language preference separately and migrate it safely when catalogs change. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: If a save records a localized inventory label instead of a stable item ID, opening it in another language may look like a missing item or create duplicate entries. Rewording must not change game identity. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Save the Harbor Lanterns inventory in English, relaunch in a second language, and compare object identity and quantities. Switch back and confirm no extra records or lost flags. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
10. Keyboard input, player names and sorting
Player-created text is data, not translation material. The interface has to support Unicode input, deletion and focus while avoiding accidental rewriting of names or user-entered filenames. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Keep names and chat text as entered. Localize only their surrounding labels, and test search and sorting deliberately if your UI claims to offer culturally appropriate ordering. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: A naive byte-length limit can split a multibyte character; a translated placeholder prompt is not the player’s typed answer. Test data round-trips through saves and network boundaries independently. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Enter accented text and a combining-character sequence in a profile name. Change language, save and reload, then test backspace and selection in the actual target build. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
11. Images, subtitles, audio and mixed-language assets
A scene can use JSON messages correctly and still display English instructions burned into a texture. Audio narration and subtitle timing also need editorial attention if different language editions are offered. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Add text-bearing textures, tutorial cards, voice assets and subtitle tracks to the content inventory. Keep asset identifiers stable and maintain an explicit availability policy when a recording is untranslated. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: Avoid silently advertising an audio language when only text has been translated. Also avoid swapping localized images before verifying copyright, accessibility text and visual placement. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Play a full tutorial segment with the chosen locale. Verify that image text, caption, audio and button wording do not contradict one another about what the player should do. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
12. Fallback policy and meaningful diagnostics
The documented subsystem returns the identifier when a translation is missing and logs a warning. This is a useful signal for development, but a message key on a live confirmation screen is not user-friendly. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Check key coverage in the build pipeline and choose an intentional fallback language for the application layer. Log missing keys without including private player input, and surface a comprehensible safe warning if a critical action lacks wording. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: Do not rely on keys appearing as text as an acceptable fallback for ordinary users. Missing language coverage can be hidden by screenshots taken only in the source language. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Remove one noncritical translation and one critical warning translation in separate test builds. The first should be diagnosed visibly to QA; the second must not permit an unclear irreversible action. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
13. Translator handoff and review
Translation reviewers need to know who speaks, where text appears and whether a phrase names an action, status or object. A JSON key alone seldom supplies enough context for an accurate choice. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Provide screenshots, word-sense notes, available characters, placeholder rules, expected user action and glossary decisions for key terms such as load, save, exit and discard. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: Do not ask reviewers to infer meaning from alphabetical strings or squeeze every sentence into an English-sized control. Give them room to flag ambiguity before the design is frozen. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Ask one reviewer to explain the destructive confirmation in their own words without seeing the English source. Compare their understanding against the actual program behavior. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
14. Build pipelines and reproducible release tests
What works from a source checkout can fail after resource packaging, executable relocation or platform-specific path changes. Translation belongs in the release artifact and not merely in a developer folder. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Make catalog files, font assets and localized textures explicit build inputs. For each target, install from the released package and verify the language selection, relaunch preference and missing-file behavior. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: Do not treat a successful compiler exit as a localization test. Asset paths, encoding and resource inclusion are runtime properties that should be checked after packaging. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Use a clean device or sandbox account for each supported platform. Capture a short evidence record: build version, locale, key scenes, font checks, defects and acceptance owner. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
15. Accessibility and player trust
Translation is useful only when it remains perceivable and operable. A warning can be linguistically exact yet inaccessible when focus order, contrast, audio cues or screen reading assumptions differ. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Check text size, color contrast, keyboard navigation, labels near icons and nonvisual alternatives. Keep language names written recognizably so someone can recover after choosing the wrong language. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: Do not use flags as substitutes for language names or infer a person’s preferred language from nationality. Preserve an accessible route to reset locale preferences. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Ask a new user to find the language control and reverse an accidental selection without instructions. If they cannot, fix navigation before expanding the language list. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
16. A complete first release and sustainable ownership
A narrow, fully tested bilingual slice provides better evidence than many unfinished languages. The person responsible for content must also know what changes trigger re-review. The player’s experience depends on this boundary: the displayed sentence must describe the same action, constraint or information after the language changes. Write down what must remain invariant before making changes to resources.
In a practical implementation, Release only languages with complete critical paths, licensed readable fonts, checked formats and documented fallback. Assign owners for catalog schema, linguistic review, accessibility and the acceptance test. Start with a short complete scene rather than a broad catalog. Put a reviewer-visible source sentence beside the identifier and make one person accountable for verifying the result on an actual device.
The failure to avoid is specific: Do not mark a language ‘supported’ simply because it has 95 percent key coverage. The missing five percent could contain deletion warnings, consent information or recovery instructions. This can survive ordinary unit tests because a key lookup may return something printable even when the player’s task is no longer clear. Read the full screen, not a string in isolation.
Acceptance should be observable. Define a release gate with specific high-risk strings and a minimum end-to-end journey. Retest on each content change rather than relying on the screenshots from the original release. Compare before-and-after screen recordings and note whether the game state, focus, control intent and error-recovery path remained unchanged. A tester should be able to explain the observed behavior in everyday words.
Thirty worked troubleshooting situations
The following situations are independent tests, not a substitute for a complete release matrix. Each one starts with what a user experiences, identifies the plausible source and gives a practical correction. Reproduce the exact failure before changing text: otherwise a font defect, a wrong code path and a poor translation can look identical.
1. The first menu shows message IDs
What a player or tester encounters: A button displays menu.start rather than a readable label. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: The key is absent, the JSON was not loaded or the application asked for the wrong case-sensitive ID. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Inspect LoadJSONFile return handling, compare exact keys and load paths, and give users a safe approved fallback. A verification test is equally important: The published package shows the right action in both languages; missing-key logging identifies the test defect. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
2. Language is correct only on the opening scene
What a player or tester encounters: The pause menu changes language, but inventory descriptions remain in English. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Inventory labels were cached when the scene opened, and their component never subscribed to E_CHANGELANGUAGE. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Refresh the inventory presentation on the event, without rebuilding item identity or overwriting state. A verification test is equally important: The same inventory appears in both languages with equal quantities and no flicker or duplicate objects. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
3. A confirmation closes during switching
What a player or tester encounters: The player opens a delete-save dialog and changes language; the warning disappears. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: The language selection handler unnecessarily rebuilds the scene or closes modal widgets. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Keep the modal and its pending action state; refresh the text and measured dialog dimensions in place. A verification test is equally important: The translated modal stays open and selecting Cancel still preserves the save. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
4. A new key works in editor but not release
What a player or tester encounters: Development shows the latest translation while the packaged game displays an old value. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: The catalog in the distribution directory was not copied or the resource cache contains an earlier file. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Include versioned JSON assets as explicit build dependencies and test a fresh installation. A verification test is equally important: The release package and the development build display the same approved sentence. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
5. One locale is duplicated under two names
What a player or tester encounters: Some strings appear under de while others are recorded under DE. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Urho3D treats language names as case sensitive, creating parallel language entries. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Choose one canonical identifier, migrate catalog keys and verify that the selector points to it. A verification test is equally important: Every translated string resolves under a single supported selection. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
6. A font renders Latin but not another script
What a player or tester encounters: A translated tooltip appears as boxes while Latin words remain readable. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: A font asset lacks required glyphs or the target shaping path is unsupported. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Select a licensed script-capable font and verify the rendering pipeline’s actual shaping support. A verification test is equally important: A native reader confirms legibility on the real device, not just a static text export. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
7. A sentence flows off the pause menu
What a player or tester encounters: The longest translation covers the Resume button. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: The layout inherited fixed widths sized for English without measuring rendered text. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Increase available width, permit suitable wrapping and preserve separate hit targets. A verification test is equally important: The menu stays readable at the narrowest supported resolution. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
8. Plural count reads strangely
What a player or tester encounters: The UI shows an equivalent of ‘1 lanterns’ or misuses zero. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: The game composes a translated noun and numeric value without grammatical selection. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Format an entire message using language-appropriate plural categories and representative counts. A verification test is equally important: A fluent reviewer checks 0, 1, 2, 5 and larger values. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
9. An English texture remains
What a player or tester encounters: A tutorial sign still tells players to press an English-labeled key. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: That instruction was baked into an image and omitted from the string inventory. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Create localized or language-neutral artwork and record its asset mapping. A verification test is equally important: Every published language has a matching instruction scene and correct key action. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
10. Changing language renames an inventory ID
What a player or tester encounters: A second language shows duplicate lantern items. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Display labels were reused as serialized object identifiers. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Separate stable object IDs from catalog keys and migrate any affected save mapping. A verification test is equally important: The original save round-trips through two languages without new objects. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
11. Right-to-left words appear in the wrong order
What a player or tester encounters: A translation contains the right letters but punctuation and flow are reversed. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Unicode storage was mistaken for bidirectional layout and shaping support. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Evaluate the UI text pipeline with the target script and add a proven solution where needed. A verification test is equally important: A reader tests mixed numbers, punctuation and target-language words in context. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
12. Newlines break subtitle alignment
What a player or tester encounters: Subtitles wrap differently after localization and cover a score panel. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Line width and subtitle placement are fixed for the source-language phrase. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Measure actual target-language lines and reposition overlays without hiding state. A verification test is equally important: A full scene playback confirms readability with captions enabled. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
13. Usernames become corrupted
What a player or tester encounters: A player name containing accents changes after reload. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: A byte limit or incompatible encoding is used along the persistence path. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Use Unicode-safe storage and test grapheme-aware input editing where required. A verification test is equally important: Saved names exactly match the entered characters across locale switches. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
14. An unreviewed fallback hides a missing warning
What a player or tester encounters: A critical prompt appears in English in a supposedly translated release. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: The fallback path masks missing target-language coverage during smoke tests. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Require a critical-string coverage report and a reviewer signoff before allowing irreversible actions. A verification test is equally important: No supported locale can proceed through the action with an unknown or misunderstood prompt. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
15. A translator changed a placeholder
What a player or tester encounters: A counter displays a literal variable token or throws an error. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: The catalog edited or deleted a structured placeholder. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Validate placeholders automatically and provide examples of permitted argument names. A verification test is equally important: Every target string formats real numeric inputs without leaking token syntax. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
16. An icon implies the wrong action
What a player or tester encounters: The label says Return but the icon looks like Delete. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Translated copy was updated while text-bearing icons and pictograms stayed unchanged. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Review icon semantics together with target-language labels; replace ambiguous art if necessary. A verification test is equally important: A first-time tester predicts the correct action before clicking. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
17. A long help page loses navigation
What a player or tester encounters: Translated instructions push the Back control below the screen. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: The help layout assumes a fixed text height. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Use scroll containers and clear section structure while keeping controls discoverable. A verification test is equally important: Keyboard and pointer users can reach Back after reading the complete message. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
18. The wrong language survives reinstall
What a player or tester encounters: The language menu starts in a language unavailable in a new build. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: A persisted preference was not checked against shipped catalog availability. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Validate saved language choices against the current list and fall back visibly. A verification test is equally important: The user can identify and change the language immediately after upgrade. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
19. An exception message remains technical
What a player or tester encounters: A player sees a raw C++ error instead of a recovery instruction. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: The failure path skipped localization and displayed a developer string. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Keep diagnostic detail in logs and show a reviewed, actionable localized message. A verification test is equally important: The player can recover without understanding internal engine terms. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
20. A localized tutorial changes controls
What a player or tester encounters: A translated instruction says press the wrong input button. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Keybinding substitutions were translated as ordinary words instead of resolved from live input state. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Insert the current binding through a typed placeholder and review the surrounding grammar. A verification test is equally important: Rebind the action, switch language and confirm the displayed key matches the action. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
21. Multiple JSON collections override unexpectedly
What a player or tester encounters: A later pack silently changes a phrase in an earlier collection. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Resource ownership and collision handling were not defined. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Audit repeated IDs and loading order; make deliberate overrides explicit. A verification test is equally important: A controlled catalog audit shows one intended owner per visible message. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
22. The font license was omitted
What a player or tester encounters: The release ships a font file without clear redistribution permission. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Font selection was treated only as a rendering problem. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Check redistribution terms, attribution requirements and packaged artifacts. A verification test is equally important: The release manifest records the font source, license and actual use. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
23. A debug label leaks onto the player screen
What a player or tester encounters: An internal key or path appears during a runtime error. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Development fallback UI is reused in production. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Separate developer diagnostics from player wording, while retaining logs for investigation. A verification test is equally important: A fresh packaged build presents safe user language with no internal path disclosure. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
24. A translated action is mistaken for a noun
What a player or tester encounters: A menu option uses a noun that readers do not recognize as an instruction. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Translators were given the string without context or screenshots. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Document the verb action and have a native reviewer check it beside the clickable control. A verification test is equally important: A reader independently states the action the control will perform. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
25. Focus order changes after expansion
What a player or tester encounters: An extra-long button pushes focus into an unexpected place. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: The responsive layout was changed without retesting keyboard navigation. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Re-evaluate tab order, active focus and visible focus indicators at target-language dimensions. A verification test is equally important: A user can reach every action without a mouse. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
26. An unsupported language remains selectable
What a player or tester encounters: The language menu offers a pack whose critical strings are unfinished. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: The selector was built from any discovered language name instead of a release-approved list. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Maintain an explicit supported-locale registry with completeness and review gates. A verification test is equally important: Only genuinely released languages appear in public builds. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
27. A language switch interrupts loading
What a player or tester encounters: Changing language during an async scene transition shows mixed-language labels. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Transient components were created with one locale and shown after the selection changed. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Resolve current language at display time, and refresh newly attached components. A verification test is equally important: No mixture remains after completing the transition or reopening the scene. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
28. A date appears with ambiguous ordering
What a player or tester encounters: A dated quest notice could mean April 5 or May 4. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Locale-specific formatting was bypassed by an English numerical template. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Format dates through an appropriate locale-aware layer and prefer clear month names where ambiguity matters. A verification test is equally important: A reader understands the intended date and time zone without guessing. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
29. A support screenshot is no longer reproducible
What a player or tester encounters: A reviewer reports a bug but no one can recreate the old phrase. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Catalog version and build number were missing from test evidence. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Record build, locale, resource revision and reproduction steps without storing personal data. A verification test is equally important: The team can rebuild the exact wording used in the report. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
30. Updates silently degrade translation quality
What a player or tester encounters: An English string changes but its earlier translation stays approved. This is important because it changes how the player interprets the interface, even when the underlying game continues running. Capture the selected locale, screen and exact steps before attempting to fix it.
Why it can happen: Translation review state did not follow source changes. Inspect the boundary involved rather than assuming the translator made an error. Source text, resource loading, font rendering, control layout and state handling are separate places to investigate.
A workable fix: Mark affected target entries for re-review, with the old and new meaning visible to translators. A verification test is equally important: A release comparison shows no stale critical entries. Do the test in a packaged build as well as the development environment, and record any remaining language-specific limitation explicitly.
Four-week implementation plan
Week 1 — Inventory and boundaries
List every user-facing string and text-bearing image, then identify the dangerous actions, recoverable errors, dynamic variables and major scene transitions. Decide which two languages form the first slice, define stable IDs and source context, and record which device and screen sizes the team actually supports. A useful deliverable is a small scene map and a catalog whose keys can be checked mechanically. The team should not claim broad language coverage yet.
Week 2 — Engine wiring and font coverage
Load the real JSON collections, connect language selection to SetLanguage, verify E_CHANGELANGUAGE handling, and run one automatically localized Text label beside one custom widget. Package fonts chosen for the target scripts and deliberately provoke missing keys, long phrases and a locale that is no longer available. Capture comparison screenshots. The deliverable is one functional bilingual user journey with repeatable steps, not a large folder of unfinished words.
Week 3 — Linguistic and accessibility review
Give qualified reviewers screenshots, action definitions, glossary choices and variable examples. Test counts, file names, confirmation language, right-to-left behavior where relevant, keyboard focus and every text-bearing asset. Read each critical action aloud from the user’s perspective. Fix layout where meaning is constrained; do not let a translator silently remove warnings to make a label fit. The deliverable is signed-off key paths and a list of remaining unsupported behaviors.
Week 4 — Clean installation and release gate
Install the packaged build on supported devices, switch languages during play and reload saved data. Test a new profile, an upgraded profile and intentionally absent resources. Record version numbers, platform details, locale, test steps and responsible reviewer. Release only language editions whose critical flows and fallback work. Document how source-copy changes reopen translation review and establish an owner for post-release corrections.
Final release checklist
- All high-risk warnings and destructive confirmations have been reviewed with the action they trigger.
- All approved language names and IDs match the case-sensitive catalog exactly.
- An invalid or absent preference produces a readable and reversible language choice.
- Fresh installations and upgrades include the intended JSON, fonts, textures and subtitle assets.
- Fonts display required letters, punctuation and mixed numeric content on actual supported targets.
- Script shaping and right-to-left behavior have been tested rather than inferred from encoding.
- Switching language refreshes custom UI without changing quest state, saves or player identity.
- Dynamic strings use complete grammatical patterns and correctly typed placeholders.
- User-entered names survive language switches, saves, reloads and input editing.
- Long strings remain readable at small display sizes without hiding actionable controls.
- Audio, images, help and subtitles do not contradict visible prompts.
- Critical missing translations fail safely and trigger a review before publication.
- Accessibility and keyboard navigation are tested in the longest language editions.
- Licenses and redistribution rights are recorded for third-party font and media resources.
- A named owner receives any defect report with language, build number and reproduction steps.
Frequently asked questions
Does Urho3D translate my game automatically?
No. Urho3D supplies a language-aware string lookup subsystem and can update suitable Text objects, but you still author translations, choose fonts, maintain the interface and verify the whole player journey. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
What format should I use for language strings?
The documented subsystem accepts UTF-8 JSON files without a byte-order mark. Structure entries around stable string IDs and language names, and keep exact case consistent across files and source code. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
How does runtime language switching work?
The application selects a language with Localization::SetLanguage. Urho3D sends E_CHANGELANGUAGE, which your application can handle to reassign custom text and other language-dependent presentation. Preserve gameplay state while refreshing. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
What happens when a key is missing?
The documented behavior includes logging a warning and returning the requested identifier. That can aid debugging, but an application needs a deliberate reader-friendly fallback and a blocker for unclear critical text. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
Can I use one font for every language?
Not safely by assumption. Font coverage, shaping, bidirectional behavior and legibility vary by script and rendering setup. Test licensed fonts with representative real strings in the actual target build. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
Will a localized button always fit?
No. A translated phrase may be longer or have different word breaks. Measure the final glyphs, wrap where appropriate and retain a visible action target. Do not shrink critical instructions until they become unreadable. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
How should plural counters work?
Treat a count as data and format a complete phrase according to the target language’s grammatical rules. Some languages use more than two plural categories; zero and larger values require explicit tests. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
Must save files change with the language?
Usually not. Persist stable identifiers and values, not their translated labels. Store the preferred locale separately so the same save can be reopened and understood in another language. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
How do I handle right-to-left languages?
Start with a supported text pipeline and prove shaping, direction, mixed numbers and cursor behavior through native-language review. UTF-8 decoding alone does not establish that the interface supports the script. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
Is a translated tutorial image part of localization?
Yes. Any language inside screenshots, artwork, controls, voice-over or subtitles affects understanding. Include those assets in the inventory and release plan, with clear decisions about which language editions exist. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
Should users be able to override device language?
A visible in-game choice is usually valuable, especially for multilingual households and shared devices. Save their explicit choice and provide a reliable method to return to a familiar language. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
When is a language ready to publish?
When high-risk screens, translations, fonts, assets, persistence and packaged installations pass tests with qualified review. A high percentage of filled JSON entries is not sufficient if the remaining strings govern warnings or recovery. The practical test is to reproduce the behavior in the published configuration, not merely to confirm that a source file contains the intended string.
Official documentation and further reading
Continue learning
This article focuses on Urho3D implementation and testing. For principles of faithful translation and decisions that apply across professions, read the linked translation master. For another framework, choose its dedicated guide instead of copying APIs from an unrelated engine.
Master Art of Translation — complete system · Translate Like a Pro — series index · Previous guide: Allegro 5 localization