Added string localization - #293
Conversation
|
one note: It's a little hack so I could test localization easily without reloading the ffxiv client. I could simplify this to always use the FFXIV client language. Also, if a key does not exist for a given language, it defaults to english. so if you selected Italian in Dalamud, you'll see english UI localization. |
Have we considered always following the Dalamud language instead, or are there issues with that? I think we should probably be consistent and always follow one or the other, and following Dalamud feels more consistent from a user expectation standpoint for a Dalamud plugin compared to following the game language, I think. |
| internal static readonly IReadOnlyDictionary<XivChatType, XivChatType> GmBaseChatTypes = | ||
| new Dictionary<XivChatType, XivChatType> | ||
| { | ||
| [XivChatType.GmTell] = XivChatType.TellIncoming, | ||
| [XivChatType.GmSay] = XivChatType.Say, | ||
| [XivChatType.GmShout] = XivChatType.Shout, | ||
| [XivChatType.GmYell] = XivChatType.Yell, | ||
| [XivChatType.GmParty] = XivChatType.Party, | ||
| [XivChatType.GmFreeCompany] = XivChatType.FreeCompany, | ||
| [XivChatType.GmLinkshell1] = XivChatType.Ls1, | ||
| [XivChatType.GmLinkshell2] = XivChatType.Ls2, | ||
| [XivChatType.GmLinkshell3] = XivChatType.Ls3, | ||
| [XivChatType.GmLinkshell4] = XivChatType.Ls4, | ||
| [XivChatType.GmLinkshell5] = XivChatType.Ls5, | ||
| [XivChatType.GmLinkshell6] = XivChatType.Ls6, | ||
| [XivChatType.GmLinkshell7] = XivChatType.Ls7, | ||
| [XivChatType.GmLinkshell8] = XivChatType.Ls8, | ||
| [XivChatType.GmNoviceNetwork] = XivChatType.NoviceNetwork, | ||
| }; |
There was a problem hiding this comment.
Does this get treated as equivalent for runtime TTS purposes? It looks like this inconsistently collapses these for the config UI but not actually in the TTS pipeline, if I'm not mistaken. If nothing else this probably benefits from a unit test.
There was a problem hiding this comment.
I validated with unit tests that these do not collapse - the current code now simply uses this to map {chatType} to GM {chatType} for display purposes for GM chat types.
| { | ||
| internal static class ChatTypeMap | ||
| { | ||
| internal static readonly IReadOnlyDictionary<int, uint> LogFilterRowIds = |
There was a problem hiding this comment.
Can these be resolved via a sheet join at runtime? If possible, I think that would be better long term than this.
There was a problem hiding this comment.
Done, I think. let me know if there's a better pattern, I'm somewhat new to the sheet data.
| var portStr = port.ToString(); | ||
|
|
||
| var didUpdate = ImGui.InputText("Port", ref portStr, 5, ImGuiInputTextFlags.CharsDecimal); | ||
| var didUpdate = ImGui.InputText(Strings.Get("MegaphonePort"), ref portStr, 5, ImGuiInputTextFlags.CharsDecimal); |
There was a problem hiding this comment.
We can probably inject Localizer for backends?
There was a problem hiding this comment.
I reworked this a little bit, but the intention of Localizer was to provide convenience methods like HasGameData, which allows us to gather info from lumina when necessary. It really wasn't intended to be the middleware for getting string values.
Localizer sets the culture based on dalamud's language setting, and that culture travels through to static Strings.Get(str) and Strings.KeyName calls.
| internal static bool TryGetLogFilterName(IDataManager data, ClientLanguage language, int chatType, out string name) | ||
| { | ||
| name = string.Empty; | ||
| return data.GetExcelSheet<LogFilter>(language)?.FirstOrDefault(row => |
There was a problem hiding this comment.
Does this seem to perform fine in-game? This comes out to what I think (?) is an O(m log(n)) scan over m supported/known chat types and n LogFilter rows each frame in ConfigurationWindow (FirstOrDefault iterates the table until hitting the matching LogKind, which gets further through in table for each chat type).
I think we should memoize this; if it's not really noticeable while the tab is open then it's fine for now and that can be a follow-up, otherwise we should do it here I think. Just a static Dictionary field should be fine for this either way.
There was a problem hiding this comment.
that's a good callout. in testing I did not notice issues, but I will address this
| } | ||
|
|
||
| return finalWords.Append(words.Last()).ToString(); | ||
| return $"[{chatType}]"; |
There was a problem hiding this comment.
We should probably fall back to SplitWords(chatType) here?
Adds localization to the 4 languages supported natively by the FFXIV client: English, French, German, and Japanese.
See the Demo Video for clarity, and a breakdown of where the translations come from and how they were validated. See also the attached translation TSV files referenced in the video.
Strings.fr.tsv
Strings.ja.tsv
Strings.de.tsv