NMSE supports UI string localisation for menus, tabs, dialog messages, toolbar labels, status bar text, panel labels, section headers, grid column headers, context menus, and all other user-visible controls. This is separate from the game-data localisation (item names, descriptions, etc.) which uses NMS internal localisation keys.
The Data/UiStrings.cs class provides:
| Method | Description |
|---|---|
SetDirectory(path) |
Sets the directory containing UI string JSON files |
Load(bcp47Tag) |
Loads a language (always loads en-GB.json as fallback) |
Get(key) |
Returns the localised string, English fallback, or raw key |
GetOrNull(key) |
Returns the localised string or null if missing |
Format(key, args) |
Returns the localised string with string.Format() arguments |
TotalKeyCount |
Number of keys defined in the English fallback |
TranslatedCount |
Number of keys in the active (non-English) language |
IsActive |
Whether a non-English language is currently loaded |
Reset() |
Clears all state (used in unit tests) |
UI string JSON files are stored in Resources/ui/lang/{bcp47}.json:
Resources/
ui/
lang/
en-GB.json ← Source of truth (English)
fr-FR.json ← French
de-DE.json ← German
ja-JP.json ← Japanese
... (16 files total)
Keys use dot-delimited hierarchical naming:
{
"menu.file": "&File",
"menu.file.save": "&Save",
"tab.player": "&Player",
"player.health": "Health:",
"status.loaded_save": "Loaded: {0} ({1}ms)",
"dialog.save_success": "Save file written successfully!",
"settlement.perk": "Perk {0}:",
"bytebeat.data_channel": "Data [{0}]:"
}| Prefix | Scope |
|---|---|
menu.* |
Main menu items (File, Edit, Tools, Language, Help) |
tab.* |
Top-level tab page titles |
toolbar.* |
Toolbar labels |
status.* |
Status bar messages |
dialog.* |
Dialog/message box messages, file dialog titles and filters |
common.* |
Shared strings (Cargo, Technology, filter, Unknown, Max Supported, etc.) |
player.* |
Player panel labels, section headers, coordinates |
starship.* |
Starship panel labels and buttons |
multitool.* |
Multi-tool panel labels and buttons |
freighter.* |
Freighter panel labels |
settlement.* |
Settlement panel labels and stats |
companion.* |
Companion panel labels, traits, seeds |
exocraft.* |
Exocraft panel labels |
frigate.* |
Frigate panel labels, stats, traits |
squadron.* |
Squadron panel labels |
discovery.* |
Discovery panel labels, tabs, columns |
milestone.* |
Milestone panel labels and sections |
bytebeat.* |
ByteBeat panel labels and sections |
account.* |
Account/rewards panel |
base.* |
Base panel tabs |
inventory.* |
Inventory grid labels, context menu |
item_picker.* |
Item picker dialog buttons, columns, placeholders |
recipe.* |
Recipe panel columns |
raw_json.* |
JSON editor labels, context menu |
export_config.* |
Export config tabs and buttons |
fleet.* |
Fleet panel tabs |
exosuit.* |
Exosuit tabs |
app.* |
Application-level strings |
MainForm.LoadDatabase()– Sets the UI lang directory viaUiStrings.SetDirectory()MainForm.ApplyStartupLanguage()– CallsUiStrings.Load()andApplyUiLocalisation()MainForm.OnLanguageSelected()– Reloads UI strings on language switchMainForm.ApplyUiLocalisation()– Pushes translated strings to:- Main menu items (File, Edit, Tools, Language, Help)
- Toolbar labels (Directory, Save Slot, File, Browse, Load, Save)
- Tab page titles (Player, Exosuit, Multi-tools, etc.)
- Panel
ApplyUiLocalisation()methods – Each of the 20 panels has its ownApplyUiLocalisation()method that updates:- Form labels (e.g. "Health:", "Shield:", "Name:", stat labels)
- Section headers (e.g. "Player Statistics", "Song Details")
- Buttons (Export, Import, Generate, etc.)
- Tab sub-pages (General, Cargo, Technology, etc.)
- Grid column headers
- Context menu items
- Filter/search placeholders
- Dynamic count labels (via
UiStrings.Format())
- Status bar – UI string count is included in the
_itemCountLabeltotal - Language status – UI string count shown in language-switch status message
Labels created by AddRow() or AddSectionHeader() in *.Designer.cs files return
the Label reference, which is stored as a private field. The corresponding
ApplyUiLocalisation() method updates these labels on language switch:
// In Designer.cs – store the label reference:
_healthLabel = AddRow(leftLayout, "Health:", _healthField, leftRow++);
// In Panel.cs – update on language change:
public void ApplyUiLocalisation()
{
_healthLabel.Text = UiStrings.Get("player.health");
}For en-GB and en-US, menu items and tab page labels include & mnemonic markers
that underline a letter for keyboard navigation:
{
"menu.file": "&File", // Underlines 'F'
"tab.player": "&Player", // Underlines 'P'
"tab.starships": "&Starships" // Underlines 'S'
}Non-English languages typically omit the & prefix since accelerator keys are
language-specific and may not apply to translated strings.
- No logic impact: UI strings are display-only. All filtering, comparison, and save I/O logic uses English internal values from the data layer.
- Fallback chain: Active language -> English fallback -> raw key string
- Format safety:
UiStrings.Format()catchesFormatExceptionfrom mismatched placeholders and returns the unformatted template.
| BCP 47 | Language |
|---|---|
| en-GB | English (Great Britain) – Source |
| en-US | English (United States) |
| fr-FR | French |
| de-DE | German |
| it-IT | Italian |
| es-ES | Spanish (Spain) |
| es-419 | Latin American Spanish |
| pt-PT | Portuguese (Portugal) |
| pt-BR | Brazilian Portuguese |
| nl-NL | Dutch |
| pl-PL | Polish |
| ru-RU | Russian |
| ja-JP | Japanese |
| ko-KR | Korean |
| zh-CN | Simplified Chinese |
| zh-TW | Traditional Chinese |
- Add the English string to
Resources/ui/lang/en-GB.json - Add corresponding translations to all other 15 language files
- Reference the key in code via
UiStrings.Get("your.key")orUiStrings.Format("your.key", args) - For panel labels: store the
Labelreference and add an update call inApplyUiLocalisation() - For
en-GB/en-US: include&mnemonic prefixes for menu/tab items (e.g."&File")
All 16 language files contain 1158 keys each (0 missing).
A class-by-class audit of every C# file is maintained in
localisation-audit.md. This covers all files in UI/,
Core/, and Data/ directories and documents which strings are localised, which
were addressed, and which are intentionally excluded (internal identifiers, proper
nouns, single-character grades).
Unit tests are in NMSE.Tests/UiStringsTests.cs (17 tests) covering:
- Loading and fallback behaviour
- Language switching
- Format placeholder substitution
- Error handling for missing files/keys
- TranslatedCount and TotalKeyCount properties
Logic tests in NMSE.Tests/LogicTests.cs load en-GB.json via UiStrings so that
assertions on localised fallback strings (e.g. "Unknown", "Multitool 1") continue
to pass.