Skip to content

feat(options): a Translate item names checkbox under the language - #127

Merged
Mosch0512 merged 10 commits into
mainfrom
feat/item-names-translation-option
Oct 22, 2026
Merged

Mosch0512 merged 10 commits into
mainfrom
feat/item-names-translation-option

Conversation

@Mosch0512

@Mosch0512 Mosch0512 commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

Summary

A Translate item names checkbox in the options window, right under the language (Interface tab, both themes). Unticked, item names stay English while every other text keeps the chosen language — for players who know the items by their English names.

  • On by default, so nothing changes until a player unticks it.
  • Applies at once: inventory, tooltips, ground labels, chat messages and the editor's item lists show the English names from the item JSONs. Saved as [UI] TranslateItemNames in config.ini.
  • The label is in all eleven game languages (German: "Gegenstandsnamen übersetzen").

How it works

  • GameConfig reads and writes [UI] TranslateItemNames (default 1); config.ini.template lists it.
  • CItemDataHandler::SetTranslateItemNames holds the setting: start-up gives it the saved value, the options window the new one. Data::Items::GetItemNameLocale picks the language of the item names: the UI language, or English when the setting is off. The handler applies it at load, on a language change and when the setting changes, and refills ItemAttribute.
  • ItemDatabase::GetNameVersion counts the changes of the shown item names (a stored item, or another language of the names). The item help window, the editor's namesake labels, the Item Categories rows and the effect browser's item list compare it, so they take the names again when the option changes. A language change does not raise the item version, so the item tools' open edits stay.
  • The editor's CSV and S6E3 exports keep writing the names of the UI language.

Not covered (on purpose)

Only the item name follows the setting. The rest of the tooltip is still built in code with UI texts and stays in the chosen language: the "Excellent" prefix, option lines, and level-based names such as Box of Kundun +1 or jewel bundles. The planned tooltip data rework replaces that code.

Note

The MU Helper's pickup keywords (sven-n#840) match the shown item name, so with the setting off they match the English names.

Testing

  • test_item_database (the item name language; the name version), test_item_database_files (loading with the option off, a language change while it is off, turning it on and off; the help window rebuilds when the item names change), theme_file_interface_tests, rml_contract_guard_tests, rml_rcss_syntax, display_settings_contract (GameConfig reads and writes the key, start-up applies it): all pass (Windows, Release, editor on).
  • clang-format 21.1.8 and cppcheck 2.13 on the changed lines/files, as CI runs them: clean.
  • In game against the in-game test server with German selected (before the review fixes): unticked → inventory names and the tooltip title switch to English at once, the rest stays German, TranslateItemNames=0 is saved; ticked again → German names back. Checked in the legacy and modern theme. Also tried by hand on a local OpenMU.
  • Not run yet: the Linux editor-on build, and an in-game check after the review fixes (they changed how start-up applies the saved setting).

…translated

[UI] TranslateItemNames (default 1) picks the language of the item names:
the UI language, or English when it is 0. The item data handler applies it
at load, on a language change and when RefreshItemNames() is called after
the setting changed. The item help window builds its content again when
only the language of the item names changed.
The Interface tab shows it as a part of the language row, in both themes.
Unticked, item names switch to English at once while every other text keeps
the chosen language; the setting is saved in config.ini. The label is in
all eleven game languages.

@Mosch0512 Mosch0512 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: changes requested for two items; the rest is non-blocking. In the game the setting does what the PR says. It is read and saved with the other [UI] keys, both the locale observer and RefreshItemNames go through ItemNameLocale(), and the item help window builds its content again when only the item name language changes. The two required items are an editor item list that keeps the old names after a toggle, and tests for the part of the change that applies the setting.

Required

  • The effect browser's item list keeps the old-language names after the checkbox changes. It builds again only when the UI language or the item data changes (EffectPreviewView.cpp:357, outside the diff; details below).
  • No test checks that the setting reaches the item names (load, language switch, RefreshItemNames) or that TranslateItemNames is saved (inline, ItemDataHandler.cpp:220).

Non-blocking

  • Each view that caches item names picks its own key for when to build again; one counter on the item database would cover them all (inline, ItemHelpContentKey.cpp:14).
  • The item data handler reads GameConfig itself, so every test that loads item data depends on the config.ini next to the test program (inline, ItemDataHandler.cpp:69).
  • The editor's CSV export now writes English names while the option is off (ItemDataExportAsCSV.cpp:52, outside the diff; details below).
  • SyncTranslateItemNamesRow copies the label sync that SyncRmlModel already has (inline, OptionWindow.cpp:993).
  • A few comments still say item names are in the UI language (ItemDatabase.h:31 and two more, outside the diff; details below).

I read every hunk with its enclosing function, the callers of RefreshItemNames, GetItemHelpContentKey and the new GameConfig getter, every user of SetDisplayLocale and GetDisplayLocale, and every cache in the game and the editor that keeps item names until a version or a language changes. I didn't build or run it. CI: Quality Gates passed; the Windows, Linux and macOS builds were still pending when this was posted.


Outside the diff

src/MuEditor/UI/EffectBrowser/EffectPreviewView.cpp:357

Required. RefreshItems builds the item list from ItemAttribute[itemType].Name and builds it again only when the item database version, the item model version or I18N::GetCurrentLocale() changes. Ticking or unticking Translate item names changes the names in ItemAttribute but none of those three, so the list and its search keep the old names. For example, with the UI in German and an item preview open in the effect browser, untick the option: the list still shows Klinge for (0,5) while the item browser shows Blade, until an item is edited or the language is switched. The docs and the PR description say the editor's item lists follow the setting.

Comparing g_ItemDatabase.GetDisplayLocale() here, as ItemNamesakes::Update and CMuItemCategoriesUI::UpdateRows already do, fixes it. m_itemsLocale would then be a std::string, since GetDisplayLocale() returns one and the current check compares pointers. The comment above the function ("or the language changes") needs the same change.

src/source/Data/DataHandler/ItemData/ItemDataExportAsCSV.cpp:52

Non-blocking. The CSV export writes ItemAttribute[i].Name. Before this PR that was the UI language; now it is English while the option is off, so the language of the exported names depends on a game option the export doesn't mention. If that is intended, a line in the editor docs would say so. If the export should keep the UI language, it can take the names from the item database with an explicit locale, as the S6E3 export does with BuildItemAttributes(locale).

src/source/Data/GameData/ItemData/ItemDatabase.h:31

Non-blocking. Three comments still describe item names as being in the UI language: SetDisplayLocale here ("the names for this UI locale"), ItemToolWindow.cpp:155 ("In the UI language, as the item browser shows it") and EffectPreviewView.cpp:348. Someone who trusts them would key a new cache on I18N::GetCurrentLocale() and repeat the effect browser bug above. "The item name language: the UI language, or English while Translate item names is off" fits all three.

static_cast<CItemDataHandler*>(context)->RefreshItemNames();
}

void CItemDataHandler::RefreshItemNames()

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required. The new tests check GetItemNameLocale, a one-line ternary, and the help window's key. Nothing tests the part that applies the setting: Load with the option off, the locale observer keeping English names after I18N::SetLocale, RefreshItemNames switching the names, and GameConfig reading and writing [UI] TranslateItemNames. If OnLocaleChanged went back to I18N::GetCurrentLocale(), or the WriteBool line went away, every test would still pass, while the game would show translated names again after a language switch or forget the choice on restart.

A test next to "Loading item data fills ItemAttribute in the UI locale" in test_item_database_files.cpp can cover the first three once the handler can be given the setting (see the comment on line 69). test_display_settings_contract.cmake already checks that GameConfig.cpp saves other options (VSync, the look preset); one more require_text there covers this key.


std::string_view ItemNameLocale()
{
return GetItemNameLocale(I18N::GetCurrentLocale(), GameConfig::GetInstance().GetTranslateItemNames());

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking. ItemNameLocale() makes the item data handler read GameConfig::GetInstance(). Every test that loads item data (ShippedItemAttributes, "Loading item data fills ItemAttribute in the UI locale", and others) now constructs GameConfig, which reads the config.ini next to the test program; the build folder has one in tests/data/Release/. A TranslateItemNames=0 there would make the Portuguese and German name checks fail for a reason unrelated to the code, and a test can't turn the option off without writing that file.

If the handler kept the flag itself (for example SetTranslateItemNames(bool), which refreshes the names), with the startup code setting it from GameConfig and the options window calling it, tests could set it directly, and the required test on line 220 is easy to write.

return {itemType,
g_ItemDatabase.GetVersion(),
I18N::LocaleIndex(I18N::GetCurrentLocale()),
I18N::LocaleIndex(g_ItemDatabase.GetDisplayLocale().c_str()),

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking. This fixes the one cache of item names that knew about the change, by adding the item name language to its key. The other views that cache item names each choose their own key: the effect browser compares the UI language (the required item above), while ItemNamesakes and the categories window compare GetDisplayLocale(). SetDisplayLocale raises no version, so each view has to know which language to compare. A second counter on ItemDatabase, raised by SetDisplayLocale and Store and kept apart from GetVersion() so the editor's drafts stay, would give all of them one number to compare. That can also be a follow-up.

Comment thread src/source/UI/Options/OptionWindow.cpp Outdated
CItemDataHandler::GetInstance().RefreshItemNames();
}

void mu::ui::window::COptionWindow::SyncTranslateItemNamesRow(OptionRmlModel& model)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking. SyncTranslateItemNamesRow repeats the body of SyncRmlModel's syncLabel lambda (convert, compare, MarkDirty) and the one-line bool check every other row uses. Rule 4 of docs/CODING_RULES.md: "Before writing new logic, check if something similar already exists. Don't duplicate." If the function is there for rule 1 (extract from a large function you touch), turning syncLabel into a private member and calling it here keeps one copy and still takes code out of SyncRmlModel.

… flag itself

The handler no longer reads GameConfig: start-up sets the flag from
[UI] TranslateItemNames and the options window sets it when the checkbox
changes. Tests that load item data no longer depend on the config.ini next
to the test program, and a test can turn the option off.
…aved

Loading with the option off, a language change while it is off and turning
it on and off again each leave the item names in the expected language. The
display settings contract checks that GameConfig reads and writes
[UI] TranslateItemNames and that start-up gives it to the item data handler.
…ames

ItemDatabase::GetNameVersion counts the changes of the shown item names: a
stored item or another language of the names. The item help window, the
namesake labels and the Item Categories rows compare it instead of each
choosing a language to compare. A language change does not raise the item
version, so the item tools' open edits stay.
…ames

The item list of the effect browser's item preview was built again only
when the items, their models or the UI language changed, so turning
translated item names on or off kept the old names in the list and its
search. It compares the item name version now.
…anguage

Both exports wrote the names ItemAttribute shows, which are English while
translated item names are off. They take the item names of the UI locale
from the item database now, as the bmd export takes each language's.
SyncRmlModel's syncLabel lambda becomes the SyncLabel member, and the
Translate item names row uses it instead of a copy of its body; its
checkbox is synced like every other row's.
The comments that said item names are in the UI language say the item name
language now: the UI language, or English while translated item names are
off. A cache keyed on the UI language alone would miss the option.
@Mosch0512
Mosch0512 merged commit 077c954 into main Oct 22, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant