(Adding a feature) Where do I add a transliterate function, and under which section in options should the toggle be?
DavidPHH opened this issue · 15 comments
Many addons usually have a toggle to allow you to transliterate names from cyrillic to latin script. eg:
Elvui:
I opened this issue some months back: #268, in order to figure out where the name substituion would happen, I've had the fix since then in my own version and it's always worked perfectly with no issues (no performance lost, no conflict with names that shouldn't get transliterated, etc).
Example of it in the world
How it's done
This transliterate function takes in a string, and converts cyrillic characters into the appropriate latin alphabet's equivalent. Due to the way that string.gsub works it does nothing with non cyrillic names. Names can never be a mix between the two since russian realms are only allowed to use cyrillic script for player/guild names, and non russian realms aren't allowed to use it, this is a restriction put in by Blizzard.
function transliterate(s)
if not s then
return s
end
if string.len(s) <= 1 then
return s
end
local sub = {
["А"] = "A", ["а"] = "a", ["Б"] = "B", ["б"] = "b", ["В"] = "V", ["в"] = "v", ["Г"] = "G", ["г"] = "g", ["Д"] = "D", ["д"] = "d", ["Е"] = "E",
["е"] = "e", ["Ё"] = "e", ["ё"] = "e", ["Ж"] = "Zh", ["ж"] = "zh", ["З"] = "Z", ["з"] = "z", ["И"] = "I", ["и"] = "i", ["Й"] = "Y", ["й"] = "y",
["К"] = "K", ["к"] = "k", ["Л"] = "L", ["л"] = "l", ["М"] = "M", ["м"] = "m", ["Н"] = "N", ["н"] = "n", ["О"] = "O", ["о"] = "o", ["П"] = "P",
["п"] = "p", ["Р"] = "R", ["р"] = "r", ["С"] = "S", ["с"] = "s", ["Т"] = "T", ["т"] = "t", ["У"] = "U", ["у"] = "u", ["Ф"] = "F", ["ф"] = "f",
["Х"] = "Kh", ["х"] = "kh", ["Ц"] = "Ts", ["ц"] = "ts", ["Ч"] = "Ch", ["ч"] = "ch", ["Ш"] = "Sh", ["ш"] = "sh", ["Щ"] = "Shch", ["щ"] = "shch",
["Ъ"] = "", ["ъ"] = "", ["Ы"] = "Y", ["ы"] = "y", ["Ь"] = "", ["ь"] = "", ["Э"] = "E", ["э"] = "e", ["Ю"] = "Yu", ["ю"] = "yu", ["Я"] = "Ya",
["я"] = "ya", [" "] = " "
}
s = string.gsub(s, ' ', ' ') -- Deals with spaces so that sub can work with cyrillic guild names that have spaces
local out = string.gsub(s, "..", sub) -- '..' pattern matches a single cyrillic letter, or double space from above which gets replaced by single space
return out
end
Where does this function gets used?
healthtext.lua
in the fuction Addon.SetCustomText()
instead of customtext:SetText(subtext or "")
this becomes customtext:SetText(transliterate(subtext) or "")
similarly in TidyPlatesCore.lua
in the function UpdateIndicator_Name()
this replaces the line there visual.name:SetText(transliterate(unit.name))
What's left to do?
Pretty much just add a toggle somewhere in the settings so users can enable or disable (disabled by default) this transliterate function. then modify the previous functions to call transliterate only if the setting is enabled. How this is done? No clue but I'm trying to figure out.
The other thing is I currently have the transliterate function defined in both those files which is obviously not the way to go, in which file and how should I include it as an addon-wide function?
Why?
I believe this is a massively useful feature, especially for us EU players. I neither speak russian nor am able to read cyrillic but since I play in EU realms I encounter many russian players. Even replacing the font with some other custom font (which I'd never want to do) wouldn't let me read the names since I don't know that alphabet.
I don't believe this is some niché-only-i-want-it feature, all the addons I use that deal with names, except threatplates has a transliteration option, and I bet many fellow EU users would appreciate this being added.
TLDR: Please help me figure out how to add a toggle button in the settings, and where to insert my transliteration function so it's an addon-wide function. I don't mind doing it myself, or if someone else implements this feature and does a pull request themselves.
Yeah, it really makes a good feature. Right now, I am still fighing with bugs in 10.2, so I had to postpone 10.3 for quite some time now. Still, I try to add it there. I'll keep you updated here. In any case, thanks for providing this feature here. It would be a shame not to add it.
Brilliant, thank you! I'll be looking forward to it. Let me know if you need anything from my side.
That's true, might have been because of that. The version I had (that i modified to add the transliterate function) before this is 10.1.4
pastebin: https://pastebin.com/raw/zQ4BhKMx
Profile I was using was "Bajheera Standard" and character name is Kyrian
I'll run a dungeon with default settings to see if anything occurs.
Sidenote that settings file in the pastebin is as it was before I upgraded to this alpha (before logging in as well), after upgrading all I did was enable the translit setting and changed nothing else.
Nevermind, did a dungeon and I'm spammed with A LOT of errors. Constantly getting "your ui has too many errors" message throughout the run (only during pulls). Some mobs (and the first boss in spires) didn't have a healthbar. I tried disabling the transliterate but nothing changed so I'm not entirely sure if it's because of this function or another alpha feature. (also I never had any bugs with my own scuffed implementation but that might be because it's an older version? My scuffed one was using the 9.0 addon)
Bugsack of bugs that happened during my run:
Bug 1
3701x ...Ons\TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:308: attempt to call upvalue 'ThreatDetailsFunction' (a nil value)
[string "@TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua"]:308: in function `UpdateFrame'
[string "@TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua"]:61: in function `?'
[string "@TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua"]:40: in function <...ns\TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:30>
Locals:
self = <table> {
RegistedUnitEvents = <table> {
}
UpdateAllFrames = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:113
UnregisterAllEvents = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:97
UpdateSettings = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:338
WidgetHandler = <table> {
}
RegisterUnitEvent = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:71
OnDisable = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:106
UNIT_THREAT_LIST_UPDATE = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:54
RegisterEvent = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:62
OnUnitAdded = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:115
Create = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:74
UpdateLayout = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:331
UpdateFrame = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:261
OnEnable = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:101
Name = "Threat"
EnabledForStyle = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:111
IsEnabled = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:97
RAID_TARGET_UPDATE = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:66
UnregisterEvent = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:82
UpdateAllFramesAndNameplateColor = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:124
}
widget_frame = <unnamed> {
0 = <userdata>
unit = <table> {
}
RightTexture = <unnamed> {
}
PixelSnapDisabled = true
Active = true
LeftTexture = <unnamed> {
}
Percentage = <unnamed> {
}
}
unit = <table> {
guid = "Creature-0-4242-2285-23003-163457-00011142B2"
isMouseover = false
class = ""
IsFocus = false
IsBossOrRare = false
style = "normal"
TP_DetailedUnitType = "Elite"
level = 60
isMarked = false
red = 0.999998
isInCombat = true
threatSituation = "LOW"
levelcolorRed = 1
threatValue = 0
health = 384503
blue = 0
unitid = "nameplate3"
name = "Forsworn Vanguard"
HasUnlimitedAuras = true
isMini = false
type = "NPC"
isElite = true
levelcolorBlue = 0
isBoss = false
healthmax = 384503
isTarget = false
levelcolorGreen = 0.820000
NPCID = "163457"
isTapped = false
classification = "elite"
isCasting = false
CustomStyleAura = false
IsInterrupted = false
reaction = "HOSTILE"
green = 0
isRare = false
}
db = <table> {
UseHeuristicInInstances = false
art = <table> {
}
ON = true
dps = <table> {
}
marked = <table> {
}
useAlpha = true
AdditiveAlpha = false
UseThreatTable = true
useScale = true
useType = true
toggle = <table> {
}
tank = <table> {
}
useHPColor = true
AdditiveScale = false
}
unique_setting = nil
style = "dps"
threat_situation = "LOW"
db_threat_value = <table> {
InsideAnchor = false
UseThreatColor = true
CustomColor = <table> {
}
Show = true
Font = <table> {
}
OnlyInGroups = true
Anchor = "LEFT"
SecondPlayersName = true
HorizontalOffset = -6
VerticalOffset = 0
}
(*temporary) = nil
(*temporary) = "nameplate3"
(*temporary) = <table> {
InsideAnchor = false
UseThreatColor = true
CustomColor = <table> {
}
Show = true
Font = <table> {
}
OnlyInGroups = true
Anchor = "LEFT"
SecondPlayersName = true
HorizontalOffset = -6
VerticalOffset = 0
}
(*temporary) = "attempt to call upvalue 'ThreatDetailsFunction' (a nil value)"
Addon = <table> {
UIScaleChanged = <function> defined @TidyPlates_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua:1778
CheckForIncompatibleAddons = <function> defined @TidyPlates_ThreatPl
Bug 2
100x invalid key to 'next'
[string "=[C]"]: in function `(for generator)'
[string "@TidyPlates_ThreatPlates\Libs\LibDogTag-Unit-3.0\LibDogTag-Unit-3.0-20210228122115.lua"]:49: in function <...lates\Libs\LibDogTag-Unit-3.0\LibDogTag-Unit-3.0.lua:46>
[string "@TidyPlates_ThreatPlates\Libs\LibDogTag-Unit-3.0\LibDogTag-Unit-3.0-20210228122115.lua"]:56: in function <...lates\Libs\LibDogTag-Unit-3.0\LibDogTag-Unit-3.0.lua:55>
Locals:
(*temporary) = <table> {
party1target = true
party3target = true
}
(*temporary) = "party2targettarget"
Bug 3
15x ...aceTidyPlates_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua:675: unexpected symbol near 'if'
Locals:
Bug 4 (this one seems to reference elvui? maybe irrelevant)
3x TidyPlates_ThreatPlates\Core.lua:167: attempt to call method 'EnableCastBars' (a nil value)
[string "@TidyPlates_ThreatPlates\Core.lua"]:167: in function `ReloadTheme'
[string "@TidyPlates_ThreatPlates\Core.lua"]:408: in function <TidyPlates_ThreatPlates\Core.lua:400>
[string "=[C]"]: ?
[string "@ElvUI\Libraries\Ace3\AceAddon-3.0\AceAddon-3.0-13.lua"]:70: in function <...s\ElvUI\Libraries\Ace3\AceAddon-3.0\AceAddon-3.0.lua:65>
[string "@ElvUI\Libraries\Ace3\AceAddon-3.0\AceAddon-3.0-13.lua"]:527: in function `EnableAddon'
[string "@ElvUI\Libraries\Ace3\AceAddon-3.0\AceAddon-3.0-13.lua"]:630: in function <...s\ElvUI\Libraries\Ace3\AceAddon-3.0\AceAddon-3.0.lua:615>
[string "=[C]"]: ?
[string "=[C]"]: in function `LoadAddOn'
[string "@FrameXML\UIParent.lua"]:508: in function `UIParentLoadAddOn'
[string "@Rarity\Core\Collections-Collections.lua"]:63: in function `ScanToys'
[string "@Rarity\Core\Collections-Collections.lua"]:307: in function `ScanExistingItems'
[string "@Rarity\Core.lua"]:175: in function `DoEnable'
...
[string "=[C]"]: ?
[string "@ElvUI_SLE\core\toolkit.lua"]:265: in function `InitializeModules'
[string "@ElvUI_SLE\core\core.lua"]:129: in function `?'
[string "@ElvUI\Libraries\LibElvUIPlugin-1.0\LibElvUIPlugin-1.0-38.lua"]:306: in function <...\Libraries\LibElvUIPlugin-1.0\LibElvUIPlugin-1.0.lua:302>
[string "=[C]"]: in function `Initialize'
[string "@ElvUI\init.lua"]:163: in function <ElvUI\init.lua:162>
[string "=[C]"]: ?
[string "@ElvUI\Libraries\Ace3\AceAddon-3.0\AceAddon-3.0-13.lua"]:70: in function <...s\ElvUI\Libraries\Ace3\AceAddon-3.0\AceAddon-3.0.lua:65>
[string "@ElvUI\Libraries\Ace3\AceAddon-3.0\AceAddon-3.0-13.lua"]:527: in function `EnableAddon'
[string "@ElvUI\Libraries\Ace3\AceAddon-3.0\AceAddon-3.0-13.lua"]:630: in function <...s\ElvUI\Libraries\Ace3\AceAddon-3.0\AceAddon-3.0.lua:615>
bug 5 and 6
5x TidyPlates_ThreatPlates\Functions\healthtext.lua:365: 'end' expected (to close 'function' at line 348) near 's'
Locals:
5x TidyPlates_ThreatPlates\Functions\healthtext.lua:350: unexpected symbol near 'if'
Locals:
Note that at the start of each bugsack entry it says something lie 5x
indicating it happened 5 times (i think), these are in order of frequency.
Hm, the reason might actually be related to another new functions, maybe an error in the settings migration for the new Auras widget (in a quick check, I did not get these Lua errors in an instance). Can you send me your TidyPlates_ThreatPlates.lua settings file, so that I can check if it is related to something like this? (To quickcheck, you could create a new profile with default settings and see if the error still occurs. But that might not be possible because of the Lua errors you get.)
Ok, guess more testing is needed :) Actually, the last bug (5/6) seems like it's a syntax error like a missing ) or end ... a rather obvious error normally.
Hm, maybe it's related to being in a group. I added a feature that the threat value (in ThreatWidget, which is referenced in the errors) can be disabled/enabled depending on being in a group. I don't have time to test it today, but I'll try to find out as soon as possible what is causing this.
Ok I ran a few tests:
- Solod spires of ascenscion normal with the settings from pastebin - 0 errors
- Ran spires of ascencion normal with a group with the settings from pastebin - "There are too many errors in your UI" message
- Ran spires of ascencion normal with a group, but with a brand new settings file (deleted old ones) - "There are too many errors in your UI" message
In both 2 and 3 it's just this error (same as Bug no 1 from my previous comment)
852x ...Ons\TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:308: attempt to call upvalue 'ThreatDetailsFunction' (a nil value)
[string "@TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua"]:308: in function `UpdateFrame'
[string "@TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua"]:135: in function `OnUnitAdded'
[string "@TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua"]:358: in function `OnUnitAdded'
[string "@TidyPlates_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua"]:328: in function <...s_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua:314>
[string "@TidyPlates_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua"]:357: in function <...s_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua:344>
[string "@TidyPlates_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua"]:455: in function <...s_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua:450>
[string "@TidyPlates_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua"]:1230: in function `?'
[string "@TidyPlates_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua"]:1024: in function <...s_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua:1023>
Locals:
self = <table> {
RegistedUnitEvents = <table> {
}
UpdateAllFrames = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:113
UnregisterAllEvents = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:97
UpdateSettings = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:338
WidgetHandler = <table> {
}
RegisterUnitEvent = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:71
OnDisable = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:106
UNIT_THREAT_LIST_UPDATE = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:54
RegisterEvent = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:62
OnUnitAdded = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:115
Create = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:74
UpdateLayout = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:331
UpdateFrame = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:261
OnEnable = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:101
Name = "Threat"
EnabledForStyle = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:111
IsEnabled = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:97
RAID_TARGET_UPDATE = <function> defined @TidyPlates_ThreatPlates\Widgets\ThreatWidget.lua:66
UnregisterEvent = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:82
UpdateAllFramesAndNameplateColor = <function> defined @TidyPlates_ThreatPlates\Widgets\WidgetHandler.lua:124
}
widget_frame = <unnamed> {
0 = <userdata>
unit = <table> {
}
RightTexture = <unnamed> {
}
PixelSnapDisabled = true
Active = true
LeftTexture = <unnamed> {
}
Percentage = <unnamed> {
}
}
unit = <table> {
guid = "Creature-0-4254-2285-4725-163459-0001117046"
isMouseover = false
class = ""
IsFocus = false
IsBossOrRare = false
level = 60
red = 0.999998
levelcolorRed = 1
unitid = "nameplate3"
HasUnlimitedAuras = false
name = "Forsworn Mender"
isElite = true
levelcolorBlue = 0
isBoss = false
healthmax = 34520
isTarget = false
levelcolorGreen = 0.820000
NPCID = "163459"
health = 20899
style = "dps"
isTapped = false
type = "NPC"
blue = 0
TP_DetailedUnitType = "Elite"
CustomStyleAura = false
IsInterrupted = false
isMarked = false
isInCombat = true
threatSituation = "LOW"
threatValue = 0
reaction = "HOSTILE"
green = 0
classification = "elite"
isRare = false
isCasting = false
isMini = false
}
db = <table> {
UseHeuristicInInstances = false
art = <table> {
}
ON = true
dps = <table> {
}
marked = <table> {
}
useAlpha = true
AdditiveAlpha = false
UseThreatTable = true
useScale = true
useType = true
toggle = <table> {
}
tank = <table> {
}
useHPColor = true
AdditiveScale = false
}
unique_setting = nil
style = "dps"
threat_situation = "LOW"
db_threat_value = <table> {
InsideAnchor = false
UseThreatColor = true
CustomColor = <table> {
}
Show = true
Font = <table> {
}
OnlyInGroups = true
Anchor = "LEFT"
SecondPlayersName = true
HorizontalOffset = -6
VerticalOffset = 0
}
(*temporary) = nil
(*temporary) = "nameplate3"
(*temporary) = <table> {
InsideAnchor = false
UseThreatColor = true
CustomColor = <table> {
}
Show = true
Font = <table> {
}
OnlyInGroups = true
Anchor = "LEFT"
SecondPlayersName = true
HorizontalOffset = -6
VerticalOffset = 0
}
(*temporary) = "attempt to call upvalue 'ThreatDetailsFunction' (a nil value)"
Addon = <table> {
UIScaleChanged = <function> defined @TidyPlates_ThreatPlates\TidyPlatesInternal\TidyPlatesCore.lua:1778
CheckForIncompatibleAddons = <function> defined @TidyPlates_ThreatPlates\Co
Doesn't seem like it's related to settings then? Might be you just didn't encounter any issues if you ran it solo, I couldn't get a single bug to happen by soloing spires.
A current alpha version is now available here: https://github.com/Backupiseasy/ThreatPlates/releases/tag/10.3.0-alpha5
It transliterates names, status text (for guilds) as well as cast target, interruptor, and target of target. That's all I could think of until now.
No worries, tell me if you want any further testing from me ^^
Just did a new (group) run with just this addon enabled and same error.
There is now a new version available that should work better: https://github.com/Backupiseasy/ThreatPlates/releases/tag/10.3.0-alpha6
I also optimized some stuff regarding expensive text functions (hopefully).
You might have to reset your profile or set the value under Threat System - Value to same valid value (it was initialized wrong which was causing the above error).