Registering game translations
RU/EN import, resource registration, locale selection and fallback.
Use stable keys for interface text, store translations separately, then register their resources in the project. Importing a table alone does not enable its translations.
Add English and Russian
- Create Locale/ui.csv in the project, saved as UTF-8. Use the complete table below.
- Wait for the editor to import it. The generated resources are Locale/ui.en.translation and Locale/ui.ru.translation, next to the CSV.
- Open Project Settings → Localization → Translations and add both generated .translation resources. Add resources, not ui.csv.
- Set internationalization/locale/fallback to en. Set a Label's Text to PLAY; leave automatic translation enabled on it and its parent hierarchy.
- Start the project. Call TranslationServer.SetLocale("ru") and then TranslationServer.SetLocale("en"). The corresponding text is Играть and Play.
keys,en,ru
PLAY,Play,Играть
ONLY_EN,English fallback,For an equivalent project.reckfell configuration, merge this section into the existing file while the editor is closed:
[internationalization]
locale/fallback="en"
locale/translations=PackedStringArray("asset://Locale/ui.en.translation", "asset://Locale/ui.ru.translation")Do not replace the rest of project.reckfell. Additional translation resources go in the same translations array.
Choose a language explicitly
TranslationServer.SetLocale("ru");
string play = TranslationServer.Translate("PLAY").ToString();These are statements inside a method. Changing the locale selects text; it does not translate arbitrary strings or save the player's preference. Store the selected locale with the rest of your settings and apply it when the game starts.
The locale is standardized: ru-RU becomes ru_RU. A ru_RU request can use the ru resource. Do not depend on an ordering between multiple resources containing the same key for the same locale; give each message one owner.
Missing translations
Lookup first uses the selected locale, then the fallback locale. If neither provides a nonempty translation, Translate returns the key.
| Call with locale ru | Result with the table above |
|---|---|
| Translate("PLAY") | Играть |
| Translate("ONLY_EN") | English fallback |
| Translate("UNKNOWN") | UNKNOWN |
| Translate("play") | play: keys are case-sensitive |
An empty cell does not mean “display nothing”: it leaves that message untranslated for the locale. Add a separate visibility rule when a control must disappear.
Runtime registration
Project registration loads resources on startup. For an optional language pack, use ResourceLoader.Load<Translation>(path), check the result, and pass that resource to TranslationServer.AddTranslation. Loading it alone does not register it. RemoveTranslation stops using the supplied resource.
Keep a reference to resources you intend to remove. Do not load and register the same language pack on every frame. After changing the registered resources, refresh text you calculated yourself; registration is not a replacement for your UI refresh logic.
Diagnose the result
| Symptom | Check |
|---|---|
| PLAY appears literally | Generated resource is registered; locale matches; key and context match exactly |
| Some Russian strings appear in English | Russian cell is empty/missing and fallback is en |
| Locale changes but a computed string stays old | Recalculate it on NotificationTranslationChanged; see the complete Label example in the CSV guide |
| Ordinary Label does not translate | AutoTranslateMode is not disabled by the control or an ancestor; retain the key in Text |
| Letters are missing or boxes appear | Font coverage, fallback fonts and layout: successful lookup does not prove correct glyph rendering |
Use CSV tables for quoting, contexts, plural forms and the complete C# example. Use PO catalogs when maintaining a separate gettext file per language.
Verification boundary
Reckfell 1.0.0 native tests cover actual CSV import, project startup registration, locale normalization, regional matching, missing keys, English fallback and runtime add/remove. The Label example is exercised through locale-change notifications. Editor menu names were checked in source; mouse interaction, rendered fonts, RTL and platform exports were not accepted by these tests.