Localization: wrap remaining untranslated strings with L() - #1170
Merged
EllesmereGaming merged 10 commits intoAug 3, 2026
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
A handful of user-facing strings never reach
L(). Some are raw literals passedstraight to
SetText, others are sentences assembled at runtime with..orformat(). They stay English on every client no matter what locale is loaded.Most of them already have translations in the locale files -- the source just
never looks them up.
Locales/koKR.lua(anddeDE,frFR) already ship:Translators did that work and it has been sitting unused. Wrapping the call sites
turns it on for every language at once.
The clearest cases are inconsistencies inside a single file -- same helper,
same
if/else, one branch wrapped and the other not:EUI__General_Options.lua:3845return EllesmereUI.L("Not Bound")EUI_PartyMode_Options.lua:101return "Not Bound"EUI_ActionBars_Options.lua:1961sameEUI_DamageMeters_Options.lua:266sameEllesmereUIDamageMeters.lua:1757ApplyTTHeader(..., L("Damage Taken")):1691ApplyTTHeader(..., "Death Recap")EUI_RaidFrames_BuffManager.lua:4870EllesmereUI.L(typeName):4868titleFS:SetText(ind.name)EUI_RaidFrames_BuffManager.lua:6160EllesmereUI.L("(no spells)"):6150"(" .. ind.name .. ")"EUI_RaidFrames_ManagerPages.lua:541return L("No filters routed"):538names[#names+1] = CAT_VALUES[cat]Runtime-assembled keys become positional formats. The window title built its
own lookup key by concatenation:
A locale previously had to ship
"Overall Damage Done","Overall Healing Done",and so on -- one entry per meter type.
Overall %1$sreplaces all of them. Samestory for
%1$s's %2$s Breakdown(nine combinations),%1$s's Death Recap, andYou may only have %1$d windows active. Word order differs per language, so thesehave to be positional rather than plain
%s.One string had English grammar baked into it. The Mythic Timer death counter
appended an English plural
sat runtime, and calledformat()directly so itnever reached
L()at all:Korean and Chinese have no plural form and Russian has three, so no locale could
express this. Two complete keys let each one handle it its own way.
Files touched
EllesmereUI/EllesmereUI_FirstInstall.luaEllesmereUI/EllesmereUI.luaEllesmereUI/EUI_PartyMode_Options.lua"Not Bound"EllesmereUIDamageMeters/EllesmereUIDamageMeters.lua+ ADD NEWrow, meter type menu, window title, window-limit tooltipEllesmereUIDamageMeters/EUI_DamageMeters_Options.lua"Not Bound"EllesmereUIMythicTimer/EllesmereUIMythicTimer.luaEllesmereUIRaidFrames/EUI_RaidFrames_ManagerPages.luaEllesmereUIRaidFrames/EUI_RaidFrames_BuffManager.luaLocales/_keys.txtregenerated, 649 -> 666. Variable wraps (L(group.header),L(ind.name),L(CAT_VALUES[cat]),L(n)) add nothing, as expected.Locales/koKR.luagains the new format keys and fills in entries that werecorrectly wrapped in source but had no Korean. Four Korean entries that only
existed to patch the runtime-assembled keys are dropped -- they are unreachable
once the source stops building keys at runtime.
On an enUS client
L()returns the key unchanged, so nothing changes visually.Deliberately left alone
EUI.ShowWidgetTooltip(...)andEllesmereUI:ShowConfirmPopup(...)-- both already call
EllesmereUI.L()on their arguments internally(
EllesmereUI_Widgets.lua:1759,EllesmereUI.lua:6344), so wrapping at the callsite would double-wrap. The window-limit tooltip is the one exception: it hands
over an already-assembled sentence, so it needs
Lf()before the call.DM_TYPE_NAMES/ICON_STYLE_VALUESand similar table literals -- they areresolved through
L()at use time; wrapping the table would freeze the value atload time.
issecretvalue()guards ("Unknown","Heal","Melee") andthe unreachable
or "You"inEllesmereUIDamageMeters.lua:3564/:3568(
StripRealmnever returns nil). Happy to cover them in a follow-up."+"and other symbol-only literals.How was it tested?
Tested in game on live retail with a koKR client: the first-run popup, unlock mode
hint, meter home grid, detail tooltip in all four states (breakdown / death recap /
no recap / in combat), meter type menu, window title including the Overall prefix,
the Mythic Timer death counter, and the Not Bound key fields all render translated,
with no load errors and no layout changes.
The three Raid Frames changes live in the 12.1 manager UI (
EUI_RaidFrames_ManagerPages.luaself-gates on
EllesmereUI.IS_121), so those were verified separately on the 12.1PTR: indicator tile names and their spell list lines render translated.
Also re-ran the key extractor to confirm
_keys.txtmatches, and grepped fordouble-wrapped tooltip calls (
ShowWidgetTooltip(..., EllesmereUI.L(...))) -- none.Screenshots
First-run popup:

Damage meter:



Checklist