From c1ff6ee4bee743d574e240bbb7fe096731b3c21d Mon Sep 17 00:00:00 2001 From: Vati Date: Thu, 9 Apr 2026 01:46:07 +0400 Subject: [PATCH] feat: localization --- Core/Main.lua | 57 +++++----- Core/SharedData.lua | 2 +- Core/Tooltip.lua | 22 ++-- Core/Utils.lua | 119 ++++++++++++++------ Data/EquipmentScanner.lua | 4 +- Localization.lua | 221 +++++++++++++++++++++++++++++++++++++- Sorting/BagReplacer.lua | 8 +- Sorting/SortEngine.lua | 6 +- UI/BagFrame.lua | 32 +++--- UI/BankFrame.lua | 34 +++--- UI/ItemButton.lua | 20 ++-- UI/MailboxFrame.lua | 10 +- UI/QuestItemBar.lua | 4 +- UI/SettingsPopup.lua | 94 ++++++++-------- 14 files changed, 453 insertions(+), 180 deletions(-) diff --git a/Core/Main.lua b/Core/Main.lua index cd1a54b..a458b9a 100644 --- a/Core/Main.lua +++ b/Core/Main.lua @@ -2,6 +2,7 @@ -- Sets up all modules and auto-save system local addon = Guda +local L = Guda_L local Main = {} addon.Modules.Main = Main @@ -10,7 +11,7 @@ addon.Modules.Main = Main function Main:Initialize() -- Wait for PLAYER_LOGIN to ensure saved variables are loaded addon.Modules.Events:OnPlayerLogin(function() - addon:Print("Initializing...") + addon:Print(L["Initializing..."]) -- Initialize database addon.Modules.DB:Initialize() @@ -38,7 +39,7 @@ function Main:Initialize() end -- Initialize UI - addon:Print("Initializing UI...") + addon:Print(L["Initializing UI..."]) addon.Modules.BagFrame:Initialize() addon.Modules.BankFrame:Initialize() addon.Modules.MailboxFrame:Initialize() @@ -100,7 +101,7 @@ function Main:Initialize() end addon:Debug("Initialization complete") - addon:Print("Ready! Type /guda to open bags") + addon:Print(L["Ready! Type /guda to open bags"]) end, "Main") end @@ -135,24 +136,24 @@ function Main:SetupSlashCommands() elseif msg == "debug" then -- Toggle debug addon.DEBUG = not addon.DEBUG - addon:Print("Debug mode: %s", addon.DEBUG and "ON" or "OFF") + addon:Print(L["Debug mode: %s"], addon.DEBUG and L["ON"] or L["OFF"]) elseif msg == "debugsort" then -- Toggle debug sort (verbose sorting output) addon.DEBUG_SORT = not addon.DEBUG_SORT - addon:Print("Debug sort mode: %s", addon.DEBUG_SORT and "ON" or "OFF") + addon:Print(L["Debug sort mode: %s"], addon.DEBUG_SORT and L["ON"] or L["OFF"]) elseif msg == "debugcat" then -- Toggle debug category view (for troubleshooting layout issues) addon.DEBUG_CATEGORY = not addon.DEBUG_CATEGORY - addon:Print("Debug category mode: %s", addon.DEBUG_CATEGORY and "ON" or "OFF") + addon:Print(L["Debug category mode: %s"], addon.DEBUG_CATEGORY and L["ON"] or L["OFF"]) elseif msg == "quest" then -- Toggle quest bar local show = not addon.Modules.DB:GetSetting("showQuestBar") addon.Modules.DB:SetSetting("showQuestBar", show) addon.Modules.QuestItemBar:Update() - addon:Print("Quest bar: %s", show and "ON" or "OFF") + addon:Print(L["Quest bar: %s"], show and L["ON"] or L["OFF"]) elseif msg == "track" then -- Toggle tracked items bar visibility @@ -172,7 +173,7 @@ function Main:SetupSlashCommands() elseif addon.Modules.SettingsPopup and addon.Modules.SettingsPopup.Toggle then addon.Modules.SettingsPopup:Toggle() else - addon:Print("Settings window not available") + addon:Print(L["Settings window not available"]) end elseif msg == "cleanup" then @@ -184,7 +185,7 @@ function Main:SetupSlashCommands() if addon.Modules.Utils and addon.Modules.Utils.PrintPerformanceStats then addon.Modules.Utils:PrintPerformanceStats() else - addon:Print("Performance stats not available") + addon:Print(L["Performance stats not available"]) end -- Also show category cache stats if addon.Modules.CategoryManager and addon.Modules.CategoryManager.GetCacheStats then @@ -215,7 +216,7 @@ function Main:SetupSlashCommands() -- Reset performance statistics if addon.Modules.Utils and addon.Modules.Utils.ResetPerformanceStats then addon.Modules.Utils:ResetPerformanceStats() - addon:Print("Performance stats reset") + addon:Print(L["Performance stats reset"]) end -- Also clear category cache if addon.Modules.CategoryManager and addon.Modules.CategoryManager.ClearCache then @@ -235,35 +236,35 @@ function Main:SetupSlashCommands() local bagFrame = getglobal("Guda_BagFrame") local bankFrame = getglobal("Guda_BankFrame") if (bagFrame and bagFrame:IsShown()) or (bankFrame and bankFrame:IsShown()) then - addon:Print("Cannot reset pool while bag/bank frames are open. Close them first.") + addon:Print(L["Cannot reset pool while bag/bank frames are open. Close them first."]) else if Guda_ResetButtonPool then Guda_ResetButtonPool() - addon:Print("Button pool reset. Pool is now empty.") + addon:Print(L["Button pool reset. Pool is now empty."]) else - addon:Print("Button pool reset function not available.") + addon:Print(L["Button pool reset function not available."]) end end elseif msg == "help" then -- Show help - addon:Print("Commands:") - addon:Print("/guda - Toggle bags") - addon:Print("/guda bank - Toggle bank") - addon:Print("/guda mail - Toggle mailbox") - addon:Print("/guda settings - Open settings") - addon:Print("/guda sort - Sort bags") - addon:Print("/guda sortbank - Sort bank") - addon:Print("/guda track - Toggle item tracking") - addon:Print("/guda debug - Toggle debug mode") - addon:Print("/guda debugsort - Toggle sort debug output") - addon:Print("/guda cleanup - Remove old characters") - addon:Print("/guda perf - Show performance stats") - addon:Print("/guda perfreset - Reset performance stats") - addon:Print("/guda poolreset - Reset button pool (debug)") + addon:Print(L["Commands:"]) + addon:Print(L["/guda - Toggle bags"]) + addon:Print(L["/guda bank - Toggle bank"]) + addon:Print(L["/guda mail - Toggle mailbox"]) + addon:Print(L["/guda settings - Open settings"]) + addon:Print(L["/guda sort - Sort bags"]) + addon:Print(L["/guda sortbank - Sort bank"]) + addon:Print(L["/guda track - Toggle item tracking"]) + addon:Print(L["/guda debug - Toggle debug mode"]) + addon:Print(L["/guda debugsort - Toggle sort debug output"]) + addon:Print(L["/guda cleanup - Remove old characters"]) + addon:Print(L["/guda perf - Show performance stats"]) + addon:Print(L["/guda perfreset - Reset performance stats"]) + addon:Print(L["/guda poolreset - Reset button pool (debug)"]) else - addon:Print("Unknown command. Type /guda help for commands") + addon:Print(L["Unknown command. Type /guda help for commands"]) end end diff --git a/Core/SharedData.lua b/Core/SharedData.lua index 292d1a7..1a78755 100644 --- a/Core/SharedData.lua +++ b/Core/SharedData.lua @@ -100,7 +100,7 @@ function SharedData:Initialize() end if importCount > 0 then - addon:Print("Imported " .. importCount .. " character(s) from other accounts") + addon:Print(format(Guda_L["Imported %d character(s) from other accounts"], importCount)) end -- Clean up the global to free memory diff --git a/Core/Tooltip.lua b/Core/Tooltip.lua index 422dab5..707b49f 100644 --- a/Core/Tooltip.lua +++ b/Core/Tooltip.lua @@ -325,16 +325,16 @@ function Tooltip:AddInventoryInfo(tooltip, link) tooltip:AddLine(" ") -- Inventory label in exact bag frame title color - tooltip:AddLine("|cFFFFD200Inventory|r") + tooltip:AddLine("|cFFFFD200" .. Guda_L["Inventory"] .. "|r") -- Total line with cyan label and white count (reuse module-level table) - local totalText = "|cFF00FFFFTotal|r: |cFFFFFFFF" .. totalCount .. "|r" + local totalText = "|cFF00FFFF" .. Guda_L["Total"] .. "|r: |cFFFFFFFF" .. totalCount .. "|r" local breakdownParts = _breakdownParts local bpIndex = 0 - if totalBags > 0 then bpIndex = bpIndex + 1; breakdownParts[bpIndex] = "|cFF00FFFFBags|r: |cFFFFFFFF" .. totalBags .. "|r" end - if totalBank > 0 then bpIndex = bpIndex + 1; breakdownParts[bpIndex] = "|cFF00FFFFBank|r: |cFFFFFFFF" .. totalBank .. "|r" end - if totalMail > 0 then bpIndex = bpIndex + 1; breakdownParts[bpIndex] = "|cFF00FFFFMail|r: |cFFFFFFFF" .. totalMail .. "|r" end - if totalEquipped > 0 then bpIndex = bpIndex + 1; breakdownParts[bpIndex] = "|cFF00FFFFEquipped|r: |cFFFFFFFF" .. totalEquipped .. "|r" end + if totalBags > 0 then bpIndex = bpIndex + 1; breakdownParts[bpIndex] = "|cFF00FFFF" .. Guda_L["Bags"] .. "|r: |cFFFFFFFF" .. totalBags .. "|r" end + if totalBank > 0 then bpIndex = bpIndex + 1; breakdownParts[bpIndex] = "|cFF00FFFF" .. Guda_L["Bank"] .. "|r: |cFFFFFFFF" .. totalBank .. "|r" end + if totalMail > 0 then bpIndex = bpIndex + 1; breakdownParts[bpIndex] = "|cFF00FFFF" .. Guda_L["Mail"] .. "|r: |cFFFFFFFF" .. totalMail .. "|r" end + if totalEquipped > 0 then bpIndex = bpIndex + 1; breakdownParts[bpIndex] = "|cFF00FFFF" .. Guda_L["Equipped"] .. "|r: |cFFFFFFFF" .. totalEquipped .. "|r" end for i = bpIndex + 1, table.getn(breakdownParts) do breakdownParts[i] = nil end local breakdownText = "" @@ -356,23 +356,23 @@ function Tooltip:AddInventoryInfo(tooltip, link) local sharedSeparatorShown = false for _, charInfo in ipairs(characterCounts) do if charInfo.isShared and not sharedSeparatorShown then - tooltip:AddLine("|cFF80C0FFOther Accounts|r") + tooltip:AddLine("|cFF80C0FF" .. Guda_L["Other Accounts"] .. "|r") sharedSeparatorShown = true end local r, g, b = GetClassColor(charInfo.classToken) local pIndex = 0 if charInfo.bagCount > 0 then - pIndex = pIndex + 1; parts[pIndex] = "|cFF00FFFFBags|r: |cFFFFFFFF" .. charInfo.bagCount .. "|r" + pIndex = pIndex + 1; parts[pIndex] = "|cFF00FFFF" .. Guda_L["Bags"] .. "|r: |cFFFFFFFF" .. charInfo.bagCount .. "|r" end if charInfo.bankCount > 0 then - pIndex = pIndex + 1; parts[pIndex] = "|cFF00FFFFBank|r: |cFFFFFFFF" .. charInfo.bankCount .. "|r" + pIndex = pIndex + 1; parts[pIndex] = "|cFF00FFFF" .. Guda_L["Bank"] .. "|r: |cFFFFFFFF" .. charInfo.bankCount .. "|r" end if charInfo.mailCount > 0 then - pIndex = pIndex + 1; parts[pIndex] = "|cFF00FFFFMail|r: |cFFFFFFFF" .. charInfo.mailCount .. "|r" + pIndex = pIndex + 1; parts[pIndex] = "|cFF00FFFF" .. Guda_L["Mail"] .. "|r: |cFFFFFFFF" .. charInfo.mailCount .. "|r" end if charInfo.equippedCount > 0 then - pIndex = pIndex + 1; parts[pIndex] = "|cFF00FFFFEquipped|r: |cFFFFFFFF" .. charInfo.equippedCount .. "|r" + pIndex = pIndex + 1; parts[pIndex] = "|cFF00FFFF" .. Guda_L["Equipped"] .. "|r: |cFFFFFFFF" .. charInfo.equippedCount .. "|r" end for i = pIndex + 1, table.getn(parts) do parts[i] = nil end diff --git a/Core/Utils.lua b/Core/Utils.lua index 7c0d1cf..5dcb4b5 100644 --- a/Core/Utils.lua +++ b/Core/Utils.lua @@ -291,12 +291,12 @@ end -- Print current performance statistics (for debugging) function Utils:PrintPerformanceStats() local stats = self:GetPerformanceStats() - addon:Print("=== Guda Performance Stats ===") - addon:Print("Frame Budget: %.0fms", stats.frameBudget * 1000) - addon:Print("Last Update: %.1fms", stats.lastUpdateDuration * 1000) + addon:Print(Guda_L["=== Guda Performance Stats ==="]) + addon:Print(Guda_L["Frame Budget: %.0fms"], stats.frameBudget * 1000) + addon:Print(Guda_L["Last Update: %.1fms"], stats.lastUpdateDuration * 1000) addon:Print("Avg Update: %.1fms", stats.averageUpdateDuration * 1000) - addon:Print("Total Updates: %d", stats.totalUpdates) - addon:Print("Budget Exceeded: %d times", stats.budgetExceededCount) + addon:Print(Guda_L["Total Updates: %d"], stats.totalUpdates) + addon:Print(Guda_L["Budget Exceeded: %d times"], stats.budgetExceededCount) addon:Print("Work Queue: %d items", stats.workQueueSize) end @@ -987,6 +987,55 @@ end -- Returns: "soul", "herb", "enchant", "quiver", "ammo", or nil -- This is the consolidated bag type detection function with tooltip fallback +-- ============================================================================= +-- Locale-independent type resolution +-- ============================================================================= +-- WoW's GetItemInfo returns LOCALIZED type/subtype strings ("Quiver" on enUS, +-- "箭袋" on zhCN, etc.). We resolve the local-client strings at runtime by +-- querying a few reference itemIDs that exist in every WoW 1.12 client, so +-- the rest of the code can match against the local language without hardcoding. +local localizedBagTypes = {} -- lowercased localized subType -> "quiver"/"ammo"/... +local localizedProjectiles = {} -- localized subType (any case) -> "arrow"/"bullet" +local localizedTypesResolved = false + +-- Reference itemIDs guaranteed to exist in every WoW 1.12 client. +-- Soul/herb/enchant bag IDs are intentionally omitted because they vary per +-- server (TurtleWoW custom items, etc.) — those still use the English fallback. +local BAG_REFERENCE_ITEMS = { + [2101] = "quiver", -- Light Quiver + [2102] = "ammo", -- Small Ammo Pouch +} +local PROJECTILE_REFERENCE_ITEMS = { + [2512] = "arrow", -- Rough Arrow + [2516] = "bullet", -- Light Shot +} + +local function ResolveLocalizedTypes() + if localizedTypesResolved then return end + local allResolved = true + + for itemID, key in pairs(BAG_REFERENCE_ITEMS) do + -- Position 6 in TurtleWoW GetItemInfo signature is itemType (subType) + local _, _, _, _, _, itemType = GetItemInfo(itemID) + if itemType then + localizedBagTypes[string.lower(itemType)] = key + else + allResolved = false + end + end + + for itemID, key in pairs(PROJECTILE_REFERENCE_ITEMS) do + local _, _, _, _, _, itemType = GetItemInfo(itemID) + if itemType then + localizedProjectiles[itemType] = key + else + allResolved = false + end + end + + if allResolved then localizedTypesResolved = true end +end + function Utils:GetSpecializedBagType(bagID) -- Skip backpack, bank, and keyring if bagID == 0 or bagID == -1 or bagID == -2 then @@ -1012,6 +1061,12 @@ function Utils:GetSpecializedBagType(bagID) if itemType then local typeLower = string.lower(itemType) + -- Locale-independent: match against resolved local-client strings + ResolveLocalizedTypes() + if localizedBagTypes[typeLower] then + return localizedBagTypes[typeLower] + end + if string.find(typeLower, "soul bag") or string.find(typeLower, "soul pouch") then return "soul" end @@ -1176,17 +1231,28 @@ function Utils:GetConsumableRestoreTag(bagID, slotID, itemLink) return tag end --- Check if item is Arrow or Bullet (for Quiver routing) +-- Check if item is Arrow or Bullet (for Quiver routing). +-- Locale-independent: also matches against the local client's translated +-- subtype strings, resolved from reference vanilla items at runtime. function Utils:IsArrowOrBullet(itemType) if not itemType then return false end - -- Exact matching only - return itemType == "Arrow" or itemType == "Bullet" + if itemType == "Arrow" or itemType == "Bullet" then return true end + ResolveLocalizedTypes() + return localizedProjectiles[itemType] ~= nil end -- Check if item is Ammo (any type - for Ammo Pouch) function Utils:IsAmmo(itemType) - if not itemType then return false end - return itemType == "Arrow" or itemType == "Bullet" + return self:IsArrowOrBullet(itemType) +end + +-- Returns "arrow", "bullet", or nil for the given item subtype string. +function Utils:GetProjectileKind(itemType) + if not itemType then return nil end + if itemType == "Arrow" then return "arrow" end + if itemType == "Bullet" then return "bullet" end + ResolveLocalizedTypes() + return localizedProjectiles[itemType] end -- Get preferred container type for an item @@ -1206,13 +1272,14 @@ function Utils:GetItemPreferredContainer(itemLink) local itemName, _, itemRarity, itemLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture = self:GetItemInfoSafe(itemID) if not itemType then return nil end - -- Only route PROJECTILE category items that are specifically arrows or bullets - if itemCategory == "Projectile" then - if itemType == "Arrow" then - return "quiver" - elseif itemType == "Bullet" then - return "ammo" - end + -- Locale-independent projectile routing. Don't gate on itemCategory string + -- (it's localized); the projectile kind lookup already covers both English + -- and the local client's strings via runtime-resolved reference items. + local projectileKind = self:GetProjectileKind(itemType) + if projectileKind == "arrow" then + return "quiver" + elseif projectileKind == "bullet" then + return "ammo" end -- Route herbs to herb bags (robust: category/subtype OR texture pattern fallback) @@ -1387,15 +1454,12 @@ function Utils:IsHerbItem(itemLink) local name, _, quality, iLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture = self:GetItemInfoSafe(itemID) - if itemCategory ~= "Trade Goods" then - return false - end - if not itemTexture then return false end - -- Normalize and check texture name + -- Texture path is locale-independent (English in every WoW client), + -- so we don't need to gate on the localized "Trade Goods" category. local tex = string.lower(itemTexture) tex = string.gsub(tex, "^interface\\\\icons\\\\", "") @@ -1418,14 +1482,7 @@ function Utils:IsEnchantingItem(itemLink) local name, _, quality, iLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture = self:GetItemInfoSafe(itemID) - if itemCategory ~= "Trade Goods" then - -- Some private servers may report Enchanting directly as type - if itemType ~= "Enchanting" and itemSubType ~= "Enchanting" then - return false - end - end - - -- If explicit Enchanting subtype/type, accept immediately + -- Explicit English subtype (rare but possible on some servers) if itemType == "Enchanting" or itemSubType == "Enchanting" then return true end @@ -1434,7 +1491,7 @@ function Utils:IsEnchantingItem(itemLink) return false end - -- Normalize and check texture name + -- Texture path is locale-independent — primary signal for non-English clients. local tex = string.lower(itemTexture) tex = string.gsub(tex, "^interface\\\\icons\\\\", "") diff --git a/Data/EquipmentScanner.lua b/Data/EquipmentScanner.lua index d145ec8..95e98fe 100644 --- a/Data/EquipmentScanner.lua +++ b/Data/EquipmentScanner.lua @@ -89,12 +89,12 @@ function EquipmentScanner:Initialize() -- Player logged in - save equipment data addon.Modules.Events:OnPlayerLogin(function() playerLoggedIn = true - addon:Print("Scanning equipped items...") + addon:Print(Guda_L["Scanning equipped items..."]) -- Delay scan to ensure character is fully loaded (uses pooled timer) Guda_ScheduleTimer(2.0, function() EquipmentScanner:SaveToDatabase() - addon:Print("Equipped items scanned and saved!") + addon:Print(Guda_L["Equipped items scanned and saved!"]) end) end, "EquipmentScanner") diff --git a/Localization.lua b/Localization.lua index 1ceb838..87c4fb3 100644 --- a/Localization.lua +++ b/Localization.lua @@ -1,16 +1,32 @@ -- Guda Localization +-- +-- Pattern mirrored from GudaPlates_Locale.lua: a single Guda_L table holding the +-- English defaults, then per-locale override blocks. Call sites use +-- Guda_L["English string"] (or `local L = Guda_L`). Missing keys gracefully +-- render English, since the keys ARE the English strings. +-- +-- Supported locales: enUS (default), zhCN, esES, ptBR, deDE, ruRU. +-- Translators: copy any L[...] line into the matching locale block below and +-- replace the right-hand value. --- Keybinding localization +Guda_L = {} +local L = Guda_L + +-- ============================================================================ +-- Keybindings (WoW-conventional globals — must stay as BINDING_*) +-- ============================================================================ BINDING_HEADER_GUDA = "Guda" BINDING_NAME_GUDA_TOGGLE_BAGS = "Toggle Bags" BINDING_NAME_GUDA_TOGGLE_BANK = "Toggle Bank" BINDING_NAME_GUDA_USE_QUEST_ITEM_1 = "Quest Bar 1" BINDING_NAME_GUDA_USE_QUEST_ITEM_2 = "Quest Bar 2" --- Additional localization strings can be added here +-- ============================================================================ +-- Settings tooltips (legacy L_* globals — referenced from SettingsPopup.lua) +-- Kept as globals for compatibility; do not remove. +-- ============================================================================ L_SHOW_TOOLTIP_COUNTS = "Tooltip Extension" L_SHOW_TOOLTIP_COUNTS_TT = "Show how many of this item you have across all your characters in the item tooltip." - L_LOCK_BAGS_TT = "Lock the bag frames in place so they cannot be moved by dragging." L_HIDE_BORDERS_TT = "Hide the thick borders around the bag and bank frames for a cleaner look." L_QUALITY_BORDER_EQ_TT = "Show a color-coded border around equipped items based on their quality (Common, Rare, Epic, etc.)." @@ -20,3 +36,202 @@ L_SHOW_QUEST_BAR_TT = "Show a bar for quickly accessing quest-related items." L_HOVER_BAGLINE_TT = "Minimizes the bag container to show only the main bag and keyring. Hover over the main bag to view the other bags." L_HIDE_BAGLINE_TT = "Hides bag slots 1-4 from the footer. Click the main bag to show a flyout with all bag slots." L_HIDE_FOOTER_TT = "Hide the bottom section of the bag frame containing money and bag slots." + +-- ============================================================================ +-- English (default / enUS) +-- ============================================================================ + +-- Init / lifecycle (Core/Main.lua, Data/EquipmentScanner.lua, Core/Tooltip.lua) +L["Initializing..."] = "Initializing..." +L["Initializing UI..."] = "Initializing UI..." +L["Ready! Type /guda to open bags"] = "Ready! Type /guda to open bags" +L["Initializing tooltip module..."] = "Initializing tooltip module..." +L["Tooltip integration enabled - Inventory displays above vendor price"] = "Tooltip integration enabled - Inventory displays above vendor price" +L["Scanning equipped items..."] = "Scanning equipped items..." +L["Equipped items scanned and saved!"] = "Equipped items scanned and saved!" + +-- Slash command help (Core/Main.lua) +L["Commands:"] = "Commands:" +L["/guda - Toggle bags"] = "/guda - Toggle bags" +L["/guda bank - Toggle bank"] = "/guda bank - Toggle bank" +L["/guda mail - Toggle mailbox"] = "/guda mail - Toggle mailbox" +L["/guda settings - Open settings"] = "/guda settings - Open settings" +L["/guda sort - Sort bags"] = "/guda sort - Sort bags" +L["/guda sortbank - Sort bank"] = "/guda sortbank - Sort bank" +L["/guda track - Toggle item tracking"] = "/guda track - Toggle item tracking" +L["/guda debug - Toggle debug mode"] = "/guda debug - Toggle debug mode" +L["/guda debugsort - Toggle sort debug output"] = "/guda debugsort - Toggle sort debug output" +L["/guda cleanup - Remove old characters"] = "/guda cleanup - Remove old characters" +L["/guda perf - Show performance stats"] = "/guda perf - Show performance stats" +L["/guda perfreset - Reset performance stats"] = "/guda perfreset - Reset performance stats" +L["/guda poolreset - Reset button pool (debug)"] = "/guda poolreset - Reset button pool (debug)" +L["Unknown command. Type /guda help for commands"] = "Unknown command. Type /guda help for commands" +L["Debug mode: %s"] = "Debug mode: %s" +L["Debug sort mode: %s"] = "Debug sort mode: %s" +L["Debug category mode: %s"] = "Debug category mode: %s" +L["Quest bar: %s"] = "Quest bar: %s" +L["ON"] = "ON" +L["OFF"] = "OFF" +L["Settings window not available"] = "Settings window not available" +L["Performance stats not available"] = "Performance stats not available" +L["Performance stats reset"] = "Performance stats reset" +L["Cannot reset pool while bag/bank frames are open. Close them first."] = "Cannot reset pool while bag/bank frames are open. Close them first." +L["Button pool reset. Pool is now empty."] = "Button pool reset. Pool is now empty." +L["Button pool reset function not available."] = "Button pool reset function not available." + +-- Bag/Bank/Mail frame chrome (UI/BagFrame.lua, UI/BankFrame.lua, UI/MailboxFrame.lua) +L["%s's Bags"] = "%s's Bags" +L["%s's Bank"] = "%s's Bank" +L["%s's Mailbox"] = "%s's Mailbox" +L["Bank"] = "Bank" +L["Bank Bag Slot %d"] = "Bank Bag Slot %d" +L["Backpack"] = "Backpack" +L["Keyring"] = "Keyring" +L["Bag %d"] = "Bag %d" +L["Bag Slots"] = "Bag Slots" +L["Search, try ~equipment"] = "Search, try ~equipment" +L["Search bank..."] = "Search bank..." +L["Search mailbox..."] = "Search mailbox..." +L["Use Guda Bank UI"] = "Use Guda Bank UI" +L["Switched to Guda bank UI"] = "Switched to Guda bank UI" +L["No Mail"] = "No Mail" +L["No mailbox data found for this character.\n\nVisit a mailbox in-game to save your mail data."] = "No mailbox data found for this character.\n\nVisit a mailbox in-game to save your mail data." +L["Current realm gold"] = "Current realm gold" + +-- Sort / sell prints (UI/BagFrame.lua, UI/BankFrame.lua, Sorting/SortEngine.lua, Sorting/BagReplacer.lua) +L["Cannot sort another character's bags!"] = "Cannot sort another character's bags!" +L["Cannot sort in read-only mode!"] = "Cannot sort in read-only mode!" +L["Bags are already sorted!"] = "Bags are already sorted!" +L["Bank is already sorted!"] = "Bank is already sorted!" +L["Bank must be open to sort!"] = "Bank must be open to sort!" +L["Sorting already in progress, please wait..."] = "Sorting already in progress, please wait..." +L["Restacked %d stack(s)"] = "Restacked %d stack(s)" +L["Sold %d junk item(s)"] = "Sold %d junk item(s)" +L["Bag replaced successfully!"] = "Bag replaced successfully!" +L["Cannot replace bag: another replacement is in progress."] = "Cannot replace bag: another replacement is in progress." +L["Cannot replace bag while sorting is in progress."] = "Cannot replace bag while sorting is in progress." +L["Cannot replace bag during combat."] = "Cannot replace bag during combat." + +-- Item-button protection prints (UI/ItemButton.lua) +L["Cannot sell %s — item is protected"] = "Cannot sell %s — item is protected" +L["Cannot disenchant %s — item is protected"] = "Cannot disenchant %s — item is protected" +L["Cannot delete %s — item is protected"] = "Cannot delete %s — item is protected" +L["Slot pinned %s (skipped during sort)"] = "Slot pinned %s (skipped during sort)" +L["Slot unpinned %s"] = "Slot unpinned %s" +L["%s set protection removed"] = "%s set protection removed" +L["%s set protection restored"] = "%s set protection restored" +L["%s locked"] = "%s locked" +L["%s unlocked"] = "%s unlocked" + +-- Quest item bar (UI/QuestItemBar.lua) +L["Item is not currently in your bags (loading from database)."] = "Item is not currently in your bags (loading from database)." + +-- Tooltip integration (Core/Tooltip.lua) +L["Inventory"] = "Inventory" +L["Other Accounts"] = "Other Accounts" +L["Total"] = "Total" +L["Bags"] = "Bags" +L["Mail"] = "Mail" +L["Equipped"] = "Equipped" + +-- SharedData (Core/SharedData.lua) +L["Imported %d character(s) from other accounts"] = "Imported %d character(s) from other accounts" + +-- Performance stats (Core/Utils.lua) +L["=== Guda Performance Stats ==="] = "=== Guda Performance Stats ===" +L["Frame Budget: %.0fms"] = "Frame Budget: %.0fms" +L["Last Update: %.1fms"] = "Last Update: %.1fms" +L["Total Updates: %d"] = "Total Updates: %d" +L["Budget Exceeded: %d times"] = "Budget Exceeded: %d times" + +-- Settings popup (UI/SettingsPopup.lua) — labels, sliders, checkboxes, buttons +L["Guda Settings"] = "Guda Settings" +L["Appearance"] = "Appearance" +L["Options"] = "Options" +L["Automation"] = "Automation" +L["View"] = "View" +L["Columns"] = "Columns" +L["Icon"] = "Icon" +L["Icon Options"] = "Icon Options" +L["Quest Bar"] = "Quest Bar" +L["Tracked"] = "Tracked" +L["Theme"] = "Theme" +L["Bag View"] = "Bag View" +L["Bank View"] = "Bank View" +L["Bag columns"] = "Bag columns" +L["Bank columns"] = "Bank columns" +L["Background Transparency"] = "Background Transparency" +L["Icon size"] = "Icon size" +L["Icon font size"] = "Icon font size" +L["Icon spacing"] = "Icon spacing" +L["Quest bar size"] = "Quest bar size" +L["Tracked bar size"] = "Tracked bar size" +L["Junk item opacity"] = "Junk item opacity" +L["Lock Window"] = "Lock Window" +L["Hide Frame Borders"] = "Hide Frame Borders" +L["Equipment Borders"] = "Equipment Borders" +L["Other Item Borders"] = "Other Item Borders" +L["Show Search Bar"] = "Show Search Bar" +L["Show Quest Bar"] = "Show Quest Bar" +L["Show All Bags"] = "Show All Bags" +L["Hide Footer"] = "Hide Footer" +L["Reverse Stack Sort"] = "Reverse Stack Sort" +L["Merge"] = "Merge" +L["Group:"] = "Group:" +L["Mark:"] = "Mark:" +L["Any rule"] = "Any rule" +L["All rules"] = "All rules" +L["Edit Category (Built-in)"] = "Edit Category (Built-in)" +L["Edit Category"] = "Edit Category" +L["Rules (%d/%d):"] = "Rules (%d/%d):" +L["Mark Unusable Items"] = "Mark Unusable Items" +L["Equip Set Categories"] = "Equip Set Categories" +L["Mark Equipment Sets"] = "Mark Equipment Sets" +L["Auto Lock Set Items"] = "Auto Lock Set Items" +L["Show Category Count"] = "Show Category Count" +L["Auto Sell Junk"] = "Auto Sell Junk" +L["Auto Open Bags"] = "Auto Open Bags" +L["Auto Close Bags"] = "Auto Close Bags" +L["White Items as Junk"] = "White Items as Junk" +L["pfUI Transparency"] = "pfUI Transparency" +L["Edit"] = "Edit" +L["Save"] = "Save" +L["Cancel"] = "Cancel" +L["+ Add Category"] = "+ Add Category" +L["+ Add Rule"] = "+ Add Rule" +L["Reset Defaults"] = "Reset Defaults" +L["Select Type"] = "Select Type" +L["Select Value"] = "Select Value" +L["Tracking Items:"] = "Tracking Items:" +L["Locked Items:"] = "Locked Items:" +L["Pin Slot:"] = "Pin Slot:" +L["Moving Bars:"] = "Moving Bars:" + +-- ============================================================================ +-- Locale overrides +-- Translators: copy any L["..."] = "..." line above into the matching block +-- below and replace the right-hand value with the translation. +-- ============================================================================ +local locale = GetLocale and GetLocale() or "enUS" + +if locale == "zhCN" then + -- Chinese (Simplified) — translations go here + -- L["Guda Settings"] = "Guda 设置" + +elseif locale == "esES" then + -- Spanish — translations go here + -- L["Guda Settings"] = "Ajustes de Guda" + +elseif locale == "ptBR" then + -- Portuguese (Brazilian) — translations go here + -- L["Guda Settings"] = "Configurações Guda" + +elseif locale == "deDE" then + -- German — translations go here + -- L["Guda Settings"] = "Guda Einstellungen" + +elseif locale == "ruRU" then + -- Russian — translations go here + -- L["Guda Settings"] = "Настройки Guda" + +end diff --git a/Sorting/BagReplacer.lua b/Sorting/BagReplacer.lua index ce95e7d..b1285a1 100644 --- a/Sorting/BagReplacer.lua +++ b/Sorting/BagReplacer.lua @@ -299,7 +299,7 @@ local function FinalizeReplacement() waitingForLocks = false onLocksCleared = nil BagReplacer.inProgress = false - addon:Print("Bag replaced successfully!") + addon:Print(Guda_L["Bag replaced successfully!"]) -- Invalidate bag scanner cache BEFORE update so it does a full rescan -- (bag slot count changed, incremental update can't handle that) @@ -479,7 +479,7 @@ function BagReplacer:Execute(targetBagID, invSlot) -- Guard: already in progress if self.inProgress then addon:DebugSort("[BagReplacer] Blocked: replacement already in progress") - addon:Print("Cannot replace bag: another replacement is in progress.") + addon:Print(Guda_L["Cannot replace bag: another replacement is in progress."]) return end @@ -487,14 +487,14 @@ function BagReplacer:Execute(targetBagID, invSlot) local SortEngine = addon.Modules.SortEngine if SortEngine and SortEngine.sortingInProgress then addon:DebugSort("[BagReplacer] Blocked: sorting in progress") - addon:Print("Cannot replace bag while sorting is in progress.") + addon:Print(Guda_L["Cannot replace bag while sorting is in progress."]) return end -- Guard: combat if UnitAffectingCombat("player") then addon:DebugSort("[BagReplacer] Blocked: in combat") - addon:Print("Cannot replace bag during combat.") + addon:Print(Guda_L["Cannot replace bag during combat."]) return end diff --git a/Sorting/SortEngine.lua b/Sorting/SortEngine.lua index 695e727..79f3dc4 100644 --- a/Sorting/SortEngine.lua +++ b/Sorting/SortEngine.lua @@ -1779,7 +1779,7 @@ function SortEngine:SortBankPass() propertyCache = {} if not addon.Modules.BankScanner:IsBankOpen() then - addon:Print("Bank must be open to sort!") + addon:Print(Guda_L["Bank must be open to sort!"]) return 0 end @@ -1849,7 +1849,7 @@ end function SortEngine:SortBank() if not addon.Modules.BankScanner:IsBankOpen() then - addon:Print("Bank must be open to sort!") + addon:Print(Guda_L["Bank must be open to sort!"]) return 0 end @@ -1935,7 +1935,7 @@ end function SortEngine:ExecuteSort(sortFunction, analyzeFunction, updateFrame, sortType) -- Check if sorting is already in progress if self.sortingInProgress then - addon:Print("Sorting already in progress, please wait...") + addon:Print(Guda_L["Sorting already in progress, please wait..."]) return false, "sorting in progress" end diff --git a/UI/BagFrame.lua b/UI/BagFrame.lua index 16fd423..4dd2321 100644 --- a/UI/BagFrame.lua +++ b/UI/BagFrame.lua @@ -156,7 +156,7 @@ function Guda_BagFrame_OnLoad(self) -- Set up search box placeholder local searchBox = getglobal(self:GetName().."_SearchBar_SearchBox") if searchBox then - searchBox:SetText("Search, try ~equipment") + searchBox:SetText(Guda_L["Search, try ~equipment"]) searchBox:SetTextColor(0.5, 0.5, 0.5, 1) end @@ -859,7 +859,7 @@ function BagFrame:Update() end if titleFont and displayName then - titleFont:SetText(string.format("%s's Bags", displayName)) + titleFont:SetText(string.format(Guda_L["%s's Bags"], displayName)) end -- Display items @@ -1604,7 +1604,7 @@ end -- Check if search is currently active function BagFrame:IsSearchActive() - return searchText and searchText ~= "" and searchText ~= "Search, try ~equipment" + return searchText and searchText ~= "" and searchText ~= Guda_L["Search, try ~equipment"] end -- Check if item passes search filter (pfUI style) @@ -1729,7 +1729,7 @@ function BagFrame:UpdateBagSlotsInfo(bagData, isOtherChar) infoFrame:EnableMouse(true) infoFrame:SetScript("OnEnter", function() GameTooltip:SetOwner(this, "ANCHOR_TOP") - GameTooltip:AddLine("Bag Slots", 1, 1, 1) + GameTooltip:AddLine(Guda_L["Bag Slots"], 1, 1, 1) GameTooltip:AddLine(" ") -- Regular bags if this.regularTotal then @@ -2209,7 +2209,7 @@ local function CreateMoneyTooltip() -- Header label f.header = f:CreateFontString(nil, "OVERLAY", "GameFontNormal") f.header:SetPoint("TOPLEFT", f, "TOPLEFT", 10, -10) - f.header:SetText("Current realm gold") + f.header:SetText(Guda_L["Current realm gold"]) f.header:SetTextColor(1, 0.82, 0) -- Header money frame (total) — anchored to right edge, same row as header @@ -2778,7 +2778,7 @@ end function Guda_BagFrame_ClearSearch() local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox") if searchBox then - searchBox:SetText("Search, try ~equipment") + searchBox:SetText(Guda_L["Search, try ~equipment"]) searchBox:SetTextColor(0.5, 0.5, 0.5, 1) searchBox:ClearFocus() end @@ -2797,7 +2797,7 @@ end function Guda_BagFrame_OnSearchChanged(self) local text = self:GetText() -- Ignore placeholder text - if text == "Search, try ~equipment" then + if text == Guda_L["Search, try ~equipment"] then text = "" end if text ~= searchText then @@ -2884,7 +2884,7 @@ end function Guda_BagFrame_Sort() if currentViewChar then - addon:Print("Cannot sort another character's bags!") + addon:Print(Guda_L["Cannot sort another character's bags!"]) return end @@ -2903,7 +2903,7 @@ function Guda_BagFrame_Sort() ) if not success and message == "already sorted" then - addon:Print("Bags are already sorted!") + addon:Print(Guda_L["Bags are already sorted!"]) end end @@ -2917,7 +2917,7 @@ function Guda_BagFrame_MergeStacks() -- Check if sorting is already in progress if addon.Modules.SortEngine.sortingInProgress then - addon:Print("Sorting already in progress, please wait...") + addon:Print(Guda_L["Sorting already in progress, please wait..."]) return end @@ -3042,7 +3042,7 @@ function Guda_BagFrame_MergeStacks() end -- Refresh the view BagFrame:Update() - addon:Print("Restacked " .. totalMoves .. " stack(s)") + addon:Print(format(Guda_L["Restacked %d stack(s)"], totalMoves)) return end @@ -3739,7 +3739,7 @@ function Guda_BagSlot_OnEnter(button, bagID) if bagID == 0 then -- Backpack tooltip - GameTooltip:SetText("Backpack", 1.0, 1.0, 1.0) + GameTooltip:SetText(Guda_L["Backpack"], 1.0, 1.0, 1.0) local numSlots = GetContainerNumSlots(0) GameTooltip:AddLine(string.format("%d Slots", numSlots), 0.8, 0.8, 0.8) if hiddenBags[bagID] then @@ -3750,7 +3750,7 @@ function Guda_BagSlot_OnEnter(button, bagID) Guda_BagFrame_HighlightBagSlots(0) elseif bagID == -2 then -- Keyring tooltip - GameTooltip:SetText("Keyring", 1.0, 1.0, 1.0) + GameTooltip:SetText(Guda_L["Keyring"], 1.0, 1.0, 1.0) local numSlots = GetContainerNumSlots(-2) or 0 GameTooltip:AddLine(string.format("%d Slots", numSlots), 0.8, 0.8, 0.8) if hiddenBags[bagID] then @@ -3775,7 +3775,7 @@ function Guda_BagSlot_OnEnter(button, bagID) Guda_BagFrame_HighlightBagSlots(bagID) else -- Empty slot - GameTooltip:SetText(string.format("Bag %d", bagID), 1.0, 1.0, 1.0) + GameTooltip:SetText(string.format(Guda_L["Bag %d"], bagID), 1.0, 1.0, 1.0) GameTooltip:AddLine("Empty", 0.5, 0.5, 0.5) if hiddenBags[bagID] then GameTooltip:AddLine("(Hidden - Right-Click to show)", 0.8, 0.5, 0.5) @@ -4134,7 +4134,7 @@ function BagFrame:Initialize() if not isMerchantOpen then this:SetScript("OnUpdate", nil) if soldCount > 0 then - addon:Print("Sold " .. soldCount .. " junk item(s).") + addon:Print(format(Guda_L["Sold %d junk item(s)"], soldCount)) end return end @@ -4149,7 +4149,7 @@ function BagFrame:Initialize() else this:SetScript("OnUpdate", nil) if soldCount > 0 then - addon:Print("Sold " .. soldCount .. " junk item(s).") + addon:Print(format(Guda_L["Sold %d junk item(s)"], soldCount)) end end end) diff --git a/UI/BankFrame.lua b/UI/BankFrame.lua index ccaa7fe..92d1c9b 100644 --- a/UI/BankFrame.lua +++ b/UI/BankFrame.lua @@ -135,7 +135,7 @@ function Guda_BankFrame_OnLoad(self) -- Set up search box placeholder local searchBox = getglobal(self:GetName().."_SearchBar_SearchBox") if searchBox then - searchBox:SetText("Search bank...") + searchBox:SetText(Guda_L["Search bank..."]) searchBox:SetTextColor(0.5, 0.5, 0.5, 1) end @@ -641,7 +641,7 @@ function BankFrame:Update() bankData = addon.Modules.DB:GetCharacterBank(currentViewChar) isOtherChar = true charName = currentViewChar - getglobal("Guda_BankFrame_Title"):SetText(currentViewChar .. "'s Bank") + getglobal("Guda_BankFrame_Title"):SetText(format(Guda_L["%s's Bank"], currentViewChar)) else -- Viewing current character's bank -- Use live data if bank is officially open OR if we can access bank data @@ -660,11 +660,11 @@ function BankFrame:Update() if useLiveData then -- Bank is accessible - use live data bankData = addon.Modules.BankScanner:GetBankData() - getglobal("Guda_BankFrame_Title"):SetText(playerName .. "'s Bank") + getglobal("Guda_BankFrame_Title"):SetText(format(Guda_L["%s's Bank"], playerName)) else -- Bank is truly closed - use saved data (read-only mode) bankData = addon.Modules.DB:GetCharacterBank(playerName) - getglobal("Guda_BankFrame_Title"):SetText(playerName .. "'s Bank") + getglobal("Guda_BankFrame_Title"):SetText(format(Guda_L["%s's Bank"], playerName)) end end @@ -1579,7 +1579,7 @@ end -- Check if search is currently active function BankFrame:IsSearchActive() - return searchText and searchText ~= "" and searchText ~= "Search bank..." + return searchText and searchText ~= "" and searchText ~= Guda_L["Search bank..."] end -- Check if item passes search filter (pfUI style) @@ -1592,7 +1592,7 @@ end function Guda_BankFrame_OnSearchChanged(self) local text = self:GetText() -- Ignore placeholder text - if text == "Search bank..." then + if text == Guda_L["Search bank..."] then text = "" end if text ~= searchText then @@ -1605,7 +1605,7 @@ end function Guda_BankFrame_ClearSearch() local searchBox = getglobal("Guda_BankFrame_SearchBar_SearchBox") if searchBox then - searchBox:SetText("Search bank...") + searchBox:SetText(Guda_L["Search bank..."]) searchBox:SetTextColor(0.5, 0.5, 0.5, 1) if searchBox.ClearFocus then searchBox:ClearFocus() end end @@ -1625,12 +1625,12 @@ end -- Bank button handler function Guda_BankFrame_Sort() if isReadOnlyMode or currentViewChar then - addon:Print("Cannot sort in read-only mode!") + addon:Print(Guda_L["Cannot sort in read-only mode!"]) return end if not addon.Modules.BankScanner:IsBankOpen() then - addon:Print("Bank must be open to sort!") + addon:Print(Guda_L["Bank must be open to sort!"]) return end @@ -1649,7 +1649,7 @@ function Guda_BankFrame_Sort() ) if not success and message == "already sorted" then - addon:Print("Bank is already sorted!") + addon:Print(Guda_L["Bank is already sorted!"]) end end @@ -1668,7 +1668,7 @@ function Guda_BankFrame_MergeStacks() -- Check if sorting is already in progress if addon.Modules.SortEngine.sortingInProgress then - addon:Print("Sorting already in progress, please wait...") + addon:Print(Guda_L["Sorting already in progress, please wait..."]) return end @@ -1795,7 +1795,7 @@ function Guda_BankFrame_MergeStacks() addon.Modules.ItemDetection:ClearCache() end BankFrame:Update() - addon:Print("Restacked " .. totalMoves .. " stack(s)") + addon:Print(format(Guda_L["Restacked %d stack(s)"], totalMoves)) return end @@ -1884,7 +1884,7 @@ function Guda_BankFrame_SwitchToGudaUI() -- Update the custom bank frame in interactive mode BankFrame:ShowCurrentCharacter() - addon:Print("Switched to Guda bank UI") + addon:Print(Guda_L["Switched to Guda bank UI"]) end -- Create button on Blizzard BankFrame to switch to Guda UI @@ -1927,7 +1927,7 @@ function BankFrame:CreateGudaButtonOnBlizzardUI() gudaButton:SetScript("OnEnter", function() GameTooltip:SetOwner(this, "ANCHOR_LEFT") - GameTooltip:SetText("Use Guda Bank UI") + GameTooltip:SetText(Guda_L["Use Guda Bank UI"]) GameTooltip:Show() end) @@ -2658,7 +2658,7 @@ function Guda_BankBagSlot_OnEnter(button, bagID) if bagID == -1 then -- Main bank bag tooltip - GameTooltip:SetText("Bank", 1.0, 1.0, 1.0) + GameTooltip:SetText(Guda_L["Bank"], 1.0, 1.0, 1.0) local numSlots = 24 GameTooltip:AddLine(string.format("%d Slots", numSlots), 0.8, 0.8, 0.8) if hiddenBankBags[bagID] then @@ -2684,13 +2684,13 @@ function Guda_BankBagSlot_OnEnter(button, bagID) ResetCursor() elseif isPurchased then -- Empty purchased slot (no hide/show text, no purchase cursor) - GameTooltip:SetText(string.format("Bank Bag Slot %d", bankButtonID or -1), 1.0, 1.0, 1.0) + GameTooltip:SetText(string.format(Guda_L["Bank Bag Slot %d"], bankButtonID or -1), 1.0, 1.0, 1.0) GameTooltip:AddLine("Empty", 0.8, 0.8, 0.8) -- Reset cursor for empty purchased slots ResetCursor() else -- Unpurchased slot (no hide/show text, show purchase cursor) - GameTooltip:SetText(string.format("Bank Bag Slot %d", bankButtonID or -1), 1.0, 1.0, 1.0) + GameTooltip:SetText(string.format(Guda_L["Bank Bag Slot %d"], bankButtonID or -1), 1.0, 1.0, 1.0) local cost = GetBankSlotCost(numSlots) GameTooltip:AddLine(addon.Modules.Utils:FormatMoney(cost, false, true), 1, 1, 1) -- Show purchase cursor (coin icon) diff --git a/UI/ItemButton.lua b/UI/ItemButton.lua index 63a7a20..11bfd16 100644 --- a/UI/ItemButton.lua +++ b/UI/ItemButton.lua @@ -695,13 +695,13 @@ UseContainerItem = function(bag, slot, ...) if itemID and DB:IsItemProtected(itemID) then -- Block selling at merchant if MerchantFrame and MerchantFrame:IsVisible() then - addon:Print("Cannot sell " .. link .. " — item is protected") + addon:Print(format(Guda_L["Cannot sell %s — item is protected"], link)) return end -- Block disenchant/milling/prospecting (spell targeting an item) if SpellIsTargeting and SpellIsTargeting() then SpellStopTargeting() - addon:Print("Cannot disenchant " .. link .. " — item is protected") + addon:Print(format(Guda_L["Cannot disenchant %s — item is protected"], link)) return end end @@ -739,7 +739,7 @@ local function HookDeletePopup(dialogName) local originalOnShow = StaticPopupDialogs[dialogName].OnShow StaticPopupDialogs[dialogName].OnShow = function() if cursorProtectedLink then - addon:Print("Cannot delete " .. cursorProtectedLink .. " — item is protected") + addon:Print(format(Guda_L["Cannot delete %s — item is protected"], cursorProtectedLink)) ClearCursor() cursorProtectedLink = nil this:Hide() @@ -1092,9 +1092,9 @@ function Guda_ItemButton_OnLoad(self) if EquipSets and EquipSets.IsInSet and EquipSets:IsInSet(itemID) then local isNowExcepted = addon.Modules.DB:ToggleSetProtectionException(itemID) if isNowExcepted then - addon:Print(link .. " set protection removed") + addon:Print(format(Guda_L["%s set protection removed"], link)) else - addon:Print(link .. " set protection restored") + addon:Print(format(Guda_L["%s set protection restored"], link)) end -- Refresh bag/bank frames if addon.Modules.BagFrame and addon.Modules.BagFrame.Update then @@ -1108,9 +1108,9 @@ function Guda_ItemButton_OnLoad(self) end local isNowLocked = addon.Modules.DB:ToggleItemLock(itemID) if isNowLocked then - addon:Print(link .. " locked") + addon:Print(format(Guda_L["%s locked"], link)) else - addon:Print(link .. " unlocked") + addon:Print(format(Guda_L["%s unlocked"], link)) end -- Refresh bag/bank frames if addon.Modules.BagFrame and addon.Modules.BagFrame.Update then @@ -1133,9 +1133,9 @@ function Guda_ItemButton_OnLoad(self) itemName = " " .. this.itemData.link end if isNowPinned then - addon:Print("Slot pinned" .. itemName .. " (skipped during sort)") + addon:Print(format(Guda_L["Slot pinned %s (skipped during sort)"], itemName)) else - addon:Print("Slot unpinned" .. itemName) + addon:Print(format(Guda_L["Slot unpinned %s"], itemName)) end -- Refresh to show/hide pin icon if addon.Modules.BagFrame and addon.Modules.BagFrame.Update then @@ -1204,7 +1204,7 @@ function Guda_ItemButton_OnLoad(self) local itemID = addon.Modules.Utils:ExtractItemID(link) if itemID and addon.Modules.DB:IsItemProtected(itemID) then SpellStopTargeting() - addon:Print("Cannot disenchant " .. link .. " — item is protected") + addon:Print(format(Guda_L["Cannot disenchant %s — item is protected"], link)) return end end diff --git a/UI/MailboxFrame.lua b/UI/MailboxFrame.lua index 8a70c1b..270511c 100644 --- a/UI/MailboxFrame.lua +++ b/UI/MailboxFrame.lua @@ -30,7 +30,7 @@ function Guda_MailboxFrame_OnLoad(self) -- Set up search box placeholder local searchBox = getglobal(self:GetName().."_SearchBar_SearchBox") if searchBox then - searchBox:SetText("Search mailbox...") + searchBox:SetText(Guda_L["Search mailbox..."]) searchBox:SetTextColor(0.5, 0.5, 0.5, 1) end @@ -148,7 +148,7 @@ function MailboxFrame:Update() charName = string.sub(charFullName, 1, dashPos - 1) end - getglobal("Guda_MailboxFrame_Title"):SetText(charName .. "'s Mailbox") + getglobal("Guda_MailboxFrame_Title"):SetText(format(Guda_L["%s's Mailbox"], charName)) -- Filter items based on search text local filteredItems = {} @@ -175,7 +175,7 @@ function MailboxFrame:Update() local emptyMessage = getglobal("Guda_MailboxFrame_EmptyMessage") if emptyMessage then if totalItems == 0 then - emptyMessage:SetText("No mailbox data found for this character.\n\nVisit a mailbox in-game to save your mail data.") + emptyMessage:SetText(Guda_L["No mailbox data found for this character.\n\nVisit a mailbox in-game to save your mail data."]) emptyMessage:Show() else emptyMessage:Hide() @@ -333,7 +333,7 @@ function MailboxFrame:DisplayItems(items, charFullName, totalMails) local paginationText = getglobal("Guda_MailboxFrame_Pagination_Text") if paginationText then if totalMails == 0 then - paginationText:SetText("No Mail") + paginationText:SetText(Guda_L["No Mail"]) else paginationText:SetText(string.format("%d/%d (items: %d)", currentPage, totalPages, totalMails or 0)) end @@ -344,7 +344,7 @@ end function Guda_MailboxFrame_OnSearchTextChanged() local searchBox = getglobal("Guda_MailboxFrame_SearchBar_SearchBox") local text = searchBox:GetText() - if text == "Search mailbox..." then + if text == Guda_L["Search mailbox..."] then searchText = "" else searchText = string.lower(text) diff --git a/UI/QuestItemBar.lua b/UI/QuestItemBar.lua index 9eddf17..20b36d5 100644 --- a/UI/QuestItemBar.lua +++ b/UI/QuestItemBar.lua @@ -272,7 +272,7 @@ function QuestItemBar:Update() button:SetScript("OnClick", function() if this.fromDB then - addon:Print("Item is not currently in your bags (loading from database).") + addon:Print(Guda_L["Item is not currently in your bags (loading from database)."]) return end @@ -613,7 +613,7 @@ function QuestItemBar:UpdateFlyout(parent) btn:SetScript("OnClick", function() if this.fromDB then - addon:Print("Item is not currently in your bags (loading from database).") + addon:Print(Guda_L["Item is not currently in your bags (loading from database)."]) return end diff --git a/UI/SettingsPopup.lua b/UI/SettingsPopup.lua index 206edbb..c3ae153 100644 --- a/UI/SettingsPopup.lua +++ b/UI/SettingsPopup.lua @@ -39,7 +39,7 @@ function Guda_SettingsPopup_OnLoad(self) Guda:ApplyBackdrop(self, "DEFAULT_FRAME") local title = getglobal(self:GetName().."_Title") - title:SetText("Guda Settings") + title:SetText(Guda_L["Guda Settings"]) -- Increase title font size local titleFont, _, titleFlags = title:GetFont() if titleFont then @@ -405,7 +405,7 @@ function Guda_SettingsPopup_BagColumnsSlider_OnLoad(self) getglobal(self:GetName().."High"):SetText("20") local text = getglobal(self:GetName().."Text") - text:SetText("Bag columns") + text:SetText(Guda_L["Bag columns"]) -- Increase font size local font, _, flags = text:GetFont() @@ -443,7 +443,7 @@ function Guda_SettingsPopup_BankColumnsSlider_OnLoad(self) getglobal(self:GetName().."High"):SetText("20") local text = getglobal(self:GetName().."Text") - text:SetText("Bank columns") + text:SetText(Guda_L["Bank columns"]) -- Increase font size local font, _, flags = text:GetFont() @@ -481,7 +481,7 @@ function Guda_SettingsPopup_BgTransparencySlider_OnLoad(self) getglobal(self:GetName().."High"):SetText("100%") local text = getglobal(self:GetName().."Text") - text:SetText("Background Transparency") + text:SetText(Guda_L["Background Transparency"]) -- Increase font size local font, _, flags = text:GetFont() @@ -540,7 +540,7 @@ function Guda_SettingsPopup_IconSizeSlider_OnLoad(self) getglobal(self:GetName().."High"):SetText("64px") local text = getglobal(self:GetName().."Text") - text:SetText("Icon size") + text:SetText(Guda_L["Icon size"]) -- Increase font size local font, _, flags = text:GetFont() @@ -580,7 +580,7 @@ function Guda_SettingsPopup_IconFontSizeSlider_OnLoad(self) getglobal(self:GetName().."High"):SetText("20px") local text = getglobal(self:GetName().."Text") - text:SetText("Icon font size") + text:SetText(Guda_L["Icon font size"]) -- Increase font size local font, _, flags = text:GetFont() @@ -620,7 +620,7 @@ function Guda_SettingsPopup_IconSpacingSlider_OnLoad(self) getglobal(self:GetName().."High"):SetText("20px") local text = getglobal(self:GetName().."Text") - text:SetText("Icon spacing") + text:SetText(Guda_L["Icon spacing"]) -- Increase font size local font, _, flags = text:GetFont() @@ -666,7 +666,7 @@ function Guda_SettingsPopup_QuestBarSizeSlider_OnLoad(self) getglobal(self:GetName().."High"):SetText("64px") local text = getglobal(self:GetName().."Text") - text:SetText("Quest bar size") + text:SetText(Guda_L["Quest bar size"]) -- Increase font size local font, _, flags = text:GetFont() @@ -701,7 +701,7 @@ function Guda_SettingsPopup_TrackedBarSizeSlider_OnLoad(self) getglobal(self:GetName().."High"):SetText("64px") local text = getglobal(self:GetName().."Text") - text:SetText("Tracked bar size") + text:SetText(Guda_L["Tracked bar size"]) -- Increase font size local font, _, flags = text:GetFont() @@ -734,7 +734,7 @@ end function Guda_SettingsPopup_LockBagsCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Lock Window") + text:SetText(Guda_L["Lock Window"]) -- Increase font size local font, _, flags = text:GetFont() @@ -781,7 +781,7 @@ end function Guda_SettingsPopup_HideBordersCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Hide Frame Borders") + text:SetText(Guda_L["Hide Frame Borders"]) -- Increase font size local font, _, flags = text:GetFont() @@ -840,7 +840,7 @@ end function Guda_SettingsPopup_QualityBorderEquipmentCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Equipment Borders") + text:SetText(Guda_L["Equipment Borders"]) -- Increase font size local font, _, flags = text:GetFont() @@ -888,7 +888,7 @@ end function Guda_SettingsPopup_QualityBorderOtherCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Other Item Borders") + text:SetText(Guda_L["Other Item Borders"]) -- Increase font size local font, _, flags = text:GetFont() @@ -936,7 +936,7 @@ end function Guda_SettingsPopup_ShowSearchBarCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Show Search Bar") + text:SetText(Guda_L["Show Search Bar"]) -- Increase font size local font, _, flags = text:GetFont() @@ -993,7 +993,7 @@ end function Guda_SettingsPopup_ShowQuestBarCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Show Quest Bar") + text:SetText(Guda_L["Show Quest Bar"]) -- Increase font size local font, _, flags = text:GetFont() @@ -1035,7 +1035,7 @@ end function Guda_SettingsPopup_HoverBaglineCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Show All Bags") + text:SetText(Guda_L["Show All Bags"]) -- Increase font size local font, _, flags = text:GetFont() @@ -1087,7 +1087,7 @@ end function Guda_SettingsPopup_HideFooterCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Hide Footer") + text:SetText(Guda_L["Hide Footer"]) -- Increase font size local font, _, flags = text:GetFont() @@ -1181,7 +1181,7 @@ function Guda_SettingsPopup_JunkOpacitySlider_OnLoad(self) getglobal(self:GetName().."High"):SetText("100%") local text = getglobal(self:GetName().."Text") - text:SetText("Junk item opacity") + text:SetText(Guda_L["Junk item opacity"]) -- Increase font size local font, _, flags = text:GetFont() @@ -1225,7 +1225,7 @@ end function Guda_SettingsPopup_MarkUnusableCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Mark Unusable Items") + text:SetText(Guda_L["Mark Unusable Items"]) -- Increase font size local font, _, flags = text:GetFont() @@ -1273,7 +1273,7 @@ end function Guda_SettingsPopup_ShowEquipSetCategoriesCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Equip Set Categories") + text:SetText(Guda_L["Equip Set Categories"]) local font, _, flags = text:GetFont() if font then @@ -1315,7 +1315,7 @@ end function Guda_SettingsPopup_MarkEquipmentSetsCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Mark Equipment Sets") + text:SetText(Guda_L["Mark Equipment Sets"]) local font, _, flags = text:GetFont() if font then @@ -1357,7 +1357,7 @@ end function Guda_SettingsPopup_AutoLockSetItemsCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Auto Lock Set Items") + text:SetText(Guda_L["Auto Lock Set Items"]) local font, _, flags = text:GetFont() if font then @@ -1389,7 +1389,7 @@ end function Guda_SettingsPopup_ShowCategoryCountCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Show Category Count") + text:SetText(Guda_L["Show Category Count"]) local font, _, flags = text:GetFont() if font then @@ -1431,7 +1431,7 @@ end function Guda_SettingsPopup_AutoVendorJunkCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Auto Sell Junk") + text:SetText(Guda_L["Auto Sell Junk"]) local font, _, flags = text:GetFont() if font then @@ -1463,7 +1463,7 @@ end function Guda_SettingsPopup_AutoOpenBagsCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Auto Open Bags") + text:SetText(Guda_L["Auto Open Bags"]) local font, _, flags = text:GetFont() if font then @@ -1495,7 +1495,7 @@ end function Guda_SettingsPopup_AutoCloseBagsCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Auto Close Bags") + text:SetText(Guda_L["Auto Close Bags"]) local font, _, flags = text:GetFont() if font then @@ -1527,7 +1527,7 @@ end function Guda_SettingsPopup_WhiteItemsJunkCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("White Items as Junk") + text:SetText(Guda_L["White Items as Junk"]) local font, _, flags = text:GetFont() if font then @@ -1643,7 +1643,7 @@ function Guda_SettingsPopup_ThemeDropdown_OnLoad(self) -- Add label above dropdown local label = self:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") label:SetPoint("BOTTOMLEFT", self, "TOPLEFT", 20, 2) - label:SetText("Theme") + label:SetText(Guda_L["Theme"]) label:SetTextColor(1, 0.82, 0, 1) end @@ -1761,7 +1761,7 @@ function Guda_SettingsPopup_BagViewDropdown_OnLoad(self) local label = self:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") label:SetPoint("BOTTOMLEFT", self, "TOPLEFT", 20, 2) - label:SetText("Bag View") + label:SetText(Guda_L["Bag View"]) label:SetTextColor(1, 0.82, 0, 1) end @@ -1800,7 +1800,7 @@ function Guda_SettingsPopup_BankViewDropdown_OnLoad(self) local label = self:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") label:SetPoint("BOTTOMLEFT", self, "TOPLEFT", 20, 2) - label:SetText("Bank View") + label:SetText(Guda_L["Bank View"]) label:SetTextColor(1, 0.82, 0, 1) end @@ -1808,7 +1808,7 @@ end function Guda_SettingsPopup_ReverseStackSortCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") if text then - text:SetText("Reverse Stack Sort") + text:SetText(Guda_L["Reverse Stack Sort"]) -- Increase font size local font, _, flags = text:GetFont() @@ -1901,7 +1901,7 @@ local function GetCategoryRowFrame(index) editBtn:SetWidth(40) editBtn:SetHeight(18) editBtn:SetPoint("LEFT", nameText, "RIGHT", 5, 0) - editBtn:SetText("Edit") + editBtn:SetText(Guda_L["Edit"]) editBtn:SetScript("OnClick", function() local catId = this:GetParent().categoryId if catId then @@ -1991,7 +1991,7 @@ local function GetCategoryRowFrame(index) end) local mergeLabel = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") mergeLabel:SetPoint("RIGHT", mergeCheckbox, "LEFT", -2, 0) - mergeLabel:SetText("Merge") + mergeLabel:SetText(Guda_L["Merge"]) mergeLabel:SetTextColor(0.8, 0.8, 0.8) row.mergeCheckbox = mergeCheckbox row.mergeLabel = mergeLabel @@ -2141,12 +2141,12 @@ function Guda_SettingsPopup_CategoriesTab_Update() -- Set button texts local addBtn = getglobal("Guda_SettingsPopup_AddCategoryButton") if addBtn then - addBtn:SetText("+ Add Category") + addBtn:SetText(Guda_L["+ Add Category"]) end local resetBtn = getglobal("Guda_SettingsPopup_ResetCategoriesButton") if resetBtn then - resetBtn:SetText("Reset Defaults") + resetBtn:SetText(Guda_L["Reset Defaults"]) end end @@ -2262,13 +2262,13 @@ function Guda_CategoryEditor_OnLoad(self) -- Set button texts local addBtn = getglobal("Guda_CategoryEditor_AddRuleButton") - if addBtn then addBtn:SetText("+ Add Rule") end + if addBtn then addBtn:SetText(Guda_L["+ Add Rule"]) end local saveBtn = getglobal("Guda_CategoryEditor_SaveButton") - if saveBtn then saveBtn:SetText("Save") end + if saveBtn then saveBtn:SetText(Guda_L["Save"]) end local cancelBtn = getglobal("Guda_CategoryEditor_CancelButton") - if cancelBtn then cancelBtn:SetText("Cancel") end + if cancelBtn then cancelBtn:SetText(Guda_L["Cancel"]) end -- Create group EditBox if it doesn't exist if not getglobal("Guda_CategoryEditor_GroupEditBox") then @@ -2277,7 +2277,7 @@ function Guda_CategoryEditor_OnLoad(self) -- Label local groupLabel = self:CreateFontString("Guda_CategoryEditor_GroupLabel", "OVERLAY", "GameFontNormalSmall") groupLabel:SetPoint("LEFT", nameBox, "RIGHT", 14, 0) - groupLabel:SetText("Group:") + groupLabel:SetText(Guda_L["Group:"]) groupLabel:SetTextColor(0.7, 0.7, 0.7) -- EditBox @@ -2299,7 +2299,7 @@ function Guda_CategoryEditor_OnLoad(self) local markLabel = self:CreateFontString("Guda_CategoryEditor_MarkLabel", "OVERLAY", "GameFontNormalSmall") markLabel:SetPoint("TOPLEFT", self, "TOPLEFT", 20, -78) - markLabel:SetText("Mark:") + markLabel:SetText(Guda_L["Mark:"]) markLabel:SetTextColor(0.7, 0.7, 0.7) -- "None" button (first) @@ -2360,14 +2360,14 @@ function Guda_CategoryEditor_OnLoad(self) if anyRadio then local label = anyRadio:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") label:SetPoint("LEFT", anyRadio, "RIGHT", 2, 0) - label:SetText("Any rule") + label:SetText(Guda_L["Any rule"]) end local allRadio = getglobal("Guda_CategoryEditor_MatchAll") if allRadio then local label = allRadio:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") label:SetPoint("LEFT", allRadio, "RIGHT", 2, 0) - label:SetText("All rules") + label:SetText(Guda_L["All rules"]) end end @@ -2413,9 +2413,9 @@ function Guda_CategoryEditor_Open(categoryId) local title = getglobal("Guda_CategoryEditor_Title") if title then if categoryDef.isBuiltIn then - title:SetText("Edit Category (Built-in)") + title:SetText(Guda_L["Edit Category (Built-in)"]) else - title:SetText("Edit Category") + title:SetText(Guda_L["Edit Category"]) end end @@ -2498,7 +2498,7 @@ local function GetRuleRowFrame(index) typeBtn:SetWidth(120) typeBtn:SetHeight(22) typeBtn:SetPoint("LEFT", row, "LEFT", 0, 0) - typeBtn:SetText("Select Type") + typeBtn:SetText(Guda_L["Select Type"]) typeBtn.ruleIndex = index typeBtn:SetScript("OnClick", function() Guda_CategoryEditor_ShowTypeDropdown(this, this.ruleIndex) @@ -2527,7 +2527,7 @@ local function GetRuleRowFrame(index) valueBtn:SetWidth(140) valueBtn:SetHeight(22) valueBtn:SetPoint("LEFT", typeBtn, "RIGHT", 5, 0) - valueBtn:SetText("Select Value") + valueBtn:SetText(Guda_L["Select Value"]) valueBtn.ruleIndex = index valueBtn:SetScript("OnClick", function() Guda_CategoryEditor_ShowValueDropdown(this, this.ruleIndex) @@ -2672,7 +2672,7 @@ function Guda_CategoryEditor_UpdateRulesDisplay() -- Update rules count label local rulesLabel = getglobal("Guda_CategoryEditor_RulesLabel") if rulesLabel then - rulesLabel:SetText("Rules (" .. numRules .. "/" .. MAX_RULES .. "):") + rulesLabel:SetText(format(Guda_L["Rules (%d/%d):"], numRules, MAX_RULES)) end -- Update scroll frame