Repository navigation
fix(localization): show translations instead of serialized localized strings - #1245
Merged
Merged
Conversation
…strings A LocalizedString converts implicitly to string, but that conversion returns the serialized value with all translations and metadata, e.g. "Lorencia||zh-CN=勇者大陆||@src=MapNames/Lorencia||@stamp=…". Razor output, StringBuilder.Append, string parameters and comparisons pick it silently. All usages were found by temporarily marking the implicit conversions as obsolete, and fixed depending on their purpose: * Admin panel and live map captions (map editor heading, master skill root headers, merchant heading, map page title, live map names, cash shop item captions, socket option captions) and the ToString() of Item, ItemCraftingResultItem and MiniGameReward use the translation of the current culture. * The mini game entrance announcements are sent in the language of each player, through a new IGameContext.SendGlobalNotificationAsync overload for localized strings. * Published game events contain the neutral text instead of all translations and metadata. * The update plugins and the item drop search compare with the neutral text, so that they also work after the captions were linked to their translations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KESqfok2EbBMX41efgZUvw
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.
Summary
LocalizedStringconverts implicitly tostring, but that conversion returns the serialized value, including all translations and metadata. For example, the map editor heading showedLorencia||zh-CN=勇者大陆||@src=MapNames/Lorencia||@stamp=47cb3df4. The conversion is picked silently by Razor@…output,StringBuilder.Append,stringparameters and==comparisons.To find every usage, I temporarily marked both implicit
LocalizedString → stringoperators[Obsolete]and built the whole solution, including the tests. That gave 55 sites. I evaluated each one; the fix depends on what the text is used for:ToString())SkillListField), merchant heading, map page title, live map names (GameMapInfoAdapter.MapName), cash shop item caption, socket option captions, and theToString()ofItem,ItemCraftingResultItemandMiniGameReward(used as captions in the admin panel)MiniGameStartBasePlugIn). They went out as one raw string to everybody, so configured translations were shown verbatim. The newIGameContext.SendGlobalNotificationAsync(LocalizedString, params object?[])overload formats the text once per culture, likeShowGlobalLocalizedMessageAsyncdoes for resource keys.GameEventPublisherPlugIn)ValueInNeutralLanguage)@src/@stampmetadatax.Name == "Spirit", etc., 17 lines in 10 plugins)Spirit||de=…. A still pending optional update would then not find its data, or throw inSingle(). Applies the same pattern other updates already use. Behavior for not-yet-linked data is unchanged.EditItemDrops)srcmatched everything).TerrainUpdateHelper)Left unchanged on purpose:
BaseInvasionPlugIn:string.IsNullOrWhiteSpace(EndMessage)is an emptiness check of the raw value, which is the right semantics.GensRewardItemsTestandMasterSkillPassivePowerUpsTest, and the operator tests inLocalizedStringTests.Noticed, not changed
EventTicketItems(Season 6 and 0.95d initializers) builds the drop item group descriptions asname + "+" + itemLevel.namecomes fromLocalizedString.FromResource(...), so the result isScroll of Archangel||de=…||@stamp=abcd+1. The level ends up glued to the stamp, and every level of a ticket shows the same caption. Fixing it needs an initializer change plus a configuration update plugin for existing databases (rule 4), so it belongs in its own PR.Testing
[Obsolete]marker only reports the intentional sites listed above (plusEventTicketItems).dotnet test:MUnique.OpenMU.Tests(1883 + 2 new),MUnique.OpenMU.Web.Tests(242),MUnique.OpenMU.Persistence.Initialization.Tests(643, 7 skipped as before) andMUnique.OpenMU.PlugIns.Tests(49) all pass.LocalizedCaptionTestscheck that the captions ofItemCraftingResultItemandMiniGameRewardshow the German translation under a German culture. Both fail without the fix (e.g."Undefined 0 Spirit||de=Geist||@src=ItemNames/Spirit").Startup -demo, Playwright): the map editor heading showsLorencia, and勇者大陆with the zh-CN UI culture. The merchant heading showsAlex.Generated by Claude Code