diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..69719f8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,19 @@ +name: CI + +on: + push: + pull_request: + +jobs: + checks: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Lua 5.1 + run: | + sudo apt-get update + sudo apt-get install -y lua5.1 + - name: Lua syntax checks + run: ./scripts/check_lua_syntax.sh + - name: Locale parity checks + run: ./scripts/check_locale_parity.py diff --git a/AutoJunkDestroyer-Classic.toc b/AutoJunkDestroyer-Classic.toc index dffd9a0..db431ec 100644 --- a/AutoJunkDestroyer-Classic.toc +++ b/AutoJunkDestroyer-Classic.toc @@ -3,7 +3,7 @@ ## Title: AutoJunkDestroyer ## Author: Milestorme ## Notes: Destroy junk items quickly (full localization + updated libs). -## Version: 1.1.10 +## Version: 1.2.0 ## Category: Bags & Inventory ## IconTexture: Interface/AddOns/AutoJunkDestroyer/AutoJunkDestroyer.tga ## X-Localizations: enUS, deDE, frFR, esES, esMX, itIT, ptBR, ruRU, koKR, zhCN, zhTW diff --git a/AutoJunkDestroyer-TBC.toc b/AutoJunkDestroyer-TBC.toc index 66da444..9f7f0d7 100644 --- a/AutoJunkDestroyer-TBC.toc +++ b/AutoJunkDestroyer-TBC.toc @@ -3,7 +3,7 @@ ## Title: AutoJunkDestroyer ## Author: Milestorme ## Notes: Destroy junk items quickly (full localization + updated libs). -## Version: 1.1.10 +## Version: 1.2.0 ## Category: Bags & Inventory ## IconTexture: Interface/AddOns/AutoJunkDestroyer/AutoJunkDestroyer.tga ## X-Localizations: enUS, deDE, frFR, esES, esMX, itIT, ptBR, ruRU, koKR, zhCN, zhTW diff --git a/AutoJunkDestroyer.lua b/AutoJunkDestroyer.lua index 997d678..6b9aaa3 100644 --- a/AutoJunkDestroyer.lua +++ b/AutoJunkDestroyer.lua @@ -3,7 +3,7 @@ -- Author: Milestorme -- Description: Destroy junk items when bags are full easily -- Safe, BG-aware, works with any number of bags --- Version: 1.1.10 +-- Version: 1.2.0 ------------------------------------------------- -- FUNCTION INDEX ------------------------------------------------- @@ -40,18 +40,12 @@ -- LDB.OnClick() -> Minimap click handler -- LDB.OnTooltipShow() -> Minimap tooltip text --- Slash Commands --- /ajd pause -> Toggle pause --- /ajd toggle -> Toggle popup visibility --- /ajd button [reset] -> Show/reset popup position --- /ajd minimap [show|hide|lock|unlock|reset|pos] - -- Event Handling -- PLAYER_LOGIN -> Initialization -- PLAYER_ENTERING_WORLD -> BG state detection -- PLAYER_REGEN_DISABLED -> Combat start -- PLAYER_REGEN_ENABLED -> Combat end --- BAG_UPDATE -> Bag change handling +-- BAG_UPDATE_DELAYED -> Bag change handling -- PLAYER_LOGOUT -> Persist saved data ------------------------------------------------- @@ -83,13 +77,20 @@ local BG_EXIT_DELAY = 0.5 -- If we leave a BG while in combat, we defer enabling until combat ends. local pendingEnableAfterCombat = false local warnedWaitingForCombat = false +local DEBUG = false ------------------------------------------------- -- Utility ------------------------------------------------- local function Print(msg) -- notes: Unified chat output helper for consistent addon prefix formatting. - DEFAULT_CHAT_FRAME:AddMessage(L["CFF00FF00_DC869E"] .. (L["ADDON_NAME"] or L["ADDON_NAME"]) .. L["R_7FC9D5"] .. msg) + DEFAULT_CHAT_FRAME:AddMessage(L["CFF00FF00_DC869E"] .. L["ADDON_NAME"] .. L["R_7FC9D5"] .. msg) +end + +local function DebugPrint(msg) + if DEBUG then + Print("[debug] " .. tostring(msg)) + end end local function IsInBattleground() @@ -615,6 +616,8 @@ local function InitAceDB() AJD_SanitizeAceDBSV(AutoJunkDestroyerIconDB) -- Install a pre-logout guard by wrapping AceDB.frame OnEvent so we sanitize BEFORE AceDB cleans up. + -- Compatibility note: this depends on stable AceDB internals (frame/GetScript/SetScript); if those + -- internals change, we skip wrapping and continue safely without crashing. if not AceDB.__AJD_PreLogoutWrapped and AceDB.frame and AceDB.frame.GetScript and AceDB.frame.SetScript then local frame = AceDB.frame local orig = frame:GetScript("OnEvent") @@ -631,6 +634,8 @@ local function InitAceDB() if orig then return orig(self, event, ...) end end) AceDB.__AJD_PreLogoutWrapped = true + else + DebugPrint("AceDB pre-logout wrapper skipped (unexpected AceDB frame internals)") end @@ -694,138 +699,6 @@ local function InitAceDB() Print(L["MSG_MINIMAP_ACEDB_OK"]) end -------------------------------------------------- --- Slash Commands -------------------------------------------------- -SLASH_AUTOJUNKDESTROYER1 = "/ajd" -SlashCmdList.AUTOJUNKDESTROYER = function(msg) - -- notes: Slash command router for /ajd. - -- notes: Supports: pause, toggle, threshold, button [reset], minimap [hide/show/lock/unlock/reset/pos] - msg = (msg or ""):lower() - - if msg == "pause" then - userPaused = not userPaused - paused = userPaused or inBattleground - Print(userPaused and L["MSG_PAUSED"] or L["MSG_RESUMED"]) - UpdateButtonVisibility(true) - return - end - - if msg:match("^threshold") then - EnsureSV() - local arg = msg:match("^threshold%s*(.*)$") or "" - if arg == "" then - Print(string.format(L["MSG_THRESHOLD_CURRENT"], math.floor(GetBagUsageThreshold() * 100 + 0.5))) - return - end - - local v = tonumber(arg) - if not v then - Print(L["MSG_THRESHOLD_USAGE"]) - return - end - - -- Allow "90" or "0.90" - if v > 1.0 then v = v / 100 end - if v < 0.50 then v = 0.50 end - if v > 0.99 then v = 0.99 end - - AutoJunkDestroyerDB.settings.bagUsageThreshold = v - Print(string.format(L["MSG_THRESHOLD_SET"], math.floor(v * 100 + 0.5))) - ScheduleBagRefresh(0) - return - end - - if msg:match("^button") then - -- notes: /ajd button -> prints saved popup position; /ajd button reset -> clears saved position. - local arg = msg:match("^button%s*(.*)$") or "" - arg = arg:lower() - - if arg == "reset" then - ResetPopupButtonPosition() - Print(L["MSG_POPUP_RESET"]) - else - EnsureSV() - local p = AutoJunkDestroyerDB.popupButtonPos - if p then - if p.point then - Print("PopupPos (saved): xOfs=" .. tostring(p.x) .. " yOfs=" .. tostring(p.y) .. " (" .. tostring(p.point) .. ")") - else - Print("PopupPos (saved): x=" .. tostring(p.x) .. " y=" .. tostring(p.y)) - end - else - local l, t = button:GetLeft(), button:GetTop() - Print("PopupPos not saved yet. Current left=" .. tostring(l) .. " top=" .. tostring(t)) - end - end - return - end - - if msg:match("^minimap") then - -- notes: /ajd minimap controls LibDBIcon state (hide/show/lock/unlock/reset/pos). - if not db then - Print(L["MSG_MINIMAP_DB_NOT_READY"]) - return - end - - local arg = msg:match("^minimap%s*(.*)$") or "" - arg = arg:lower() - - if arg == "hide" then - db.profile.minimap.hide = true - icon:Hide("AutoJunkDestroyer") - Print(L["MSG_MINIMAP_ICON_HIDDEN"]) - elseif arg == "show" then - db.profile.minimap.hide = false - icon:Show("AutoJunkDestroyer") - Print(L["MSG_MINIMAP_ICON_SHOWN"]) - elseif arg == "lock" then - db.profile.minimap.lock = true - icon:Lock("AutoJunkDestroyer") - Print(L["MSG_MINIMAP_LOCKED"]) - elseif arg == "unlock" then - db.profile.minimap.lock = false - icon:Unlock("AutoJunkDestroyer") - Print(L["MSG_MINIMAP_UNLOCKED"]) - elseif arg == "reset" then - db.profile.minimap.minimapPos = 220 - icon:Refresh("AutoJunkDestroyer", db.profile.minimap) - Print(L["MSG_MINIMAP_RESET"]) - elseif arg == "pos" or arg == "" then - Print("MinimapPos (saved): " .. tostring(db.profile.minimap.minimapPos) .. - " | hide=" .. tostring(db.profile.minimap.hide) .. - " | lock=" .. tostring(db.profile.minimap.lock)) - else - Print("/ajd minimap reset") - end - return - end - - if msg == "toggle" then - -- notes: /ajd toggle shows/hides the popup delete button (only when addon is active). - if paused or inBattleground or InCombat() then - Print(L["MSG_DISABLED_RIGHT_NOW"]) - button:Hide() - return - end - - if button:IsShown() then - button:Hide() - Print(L["MSG_BUTTON_HIDDEN_MINIMAP"]) - else - button:Show() - UpdateButtonText() - Print(L["MSG_BUTTON_SHOWN_MINIMAP"]) - end - return - end - - -- notes: Default help output. - Print("/ajd pause") - Print("/ajd toggle") - Print("/ajd threshold 90") - Print("/ajd minimap reset") -end ------------------------------------------------- -- Events diff --git a/CHANGELOG.md b/CHANGELOG.md index bb9179e..131e92b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,25 @@ # Changelog +## 1.2.0 +### Added +- Added explicit `/ajd resume` and `/ajd status` slash commands. +- Added localized slash-command aliases for core and minimap subcommands across non-English locales. +- Added dedicated `Commands.lua` module to separate slash routing from core logic. +- Added CI workflow and scripts for Lua syntax checks and locale key parity. + +### Changed +- Removed slash command support (`/ajd ...`) and standardized control via minimap left/right-click interactions. +- Localized remaining hardcoded slash-command output strings (popup position, minimap position, and help text). +- Translated newly added slash/minimap/popup status keys into each locale language (instead of English placeholders). +- Improved AceDB pre-logout wrapping notes/guards for forward compatibility diagnostics. +- Updated README slash command docs for pause/resume/status behavior. + +### Fixed +- Cleaned minor code/comment polish issues (`Print` addon-name redundancy and event comment naming). +- Fixed slash alias normalization to avoid UTF-8 breakage by lowercasing ASCII only in command parsing. + + ## 1.1.10 ### Fixed - Consolidated SavedVariables initialization so shard button defaults are always set alongside the bag threshold. diff --git a/CODE_REVIEW.md b/CODE_REVIEW.md new file mode 100644 index 0000000..9624b6d --- /dev/null +++ b/CODE_REVIEW.md @@ -0,0 +1,111 @@ +# AutoJunkDestroyer Code Review + +Date: 2026-02-14 + +## Scope +- `AutoJunkDestroyer.lua` +- `Locales/enUS.lua` plus locale parity spot checks +- `README.md` +- `AutoJunkDestroyer-Classic.toc`, `AutoJunkDestroyer-TBC.toc` + +--- + +## Executive summary +The addon is generally solid: defensive state handling around battleground/combat transitions is clear, bag-refresh debouncing is sensible, and the AceDB data separation plus migration hardening is a strong stability improvement. The highest-value follow-up items are mostly polish and consistency fixes (command/docs drift, localization consistency, and reducing long-file complexity). + +--- + +## Findings and recommendations + +## 1) Command/documentation drift: `/ajd resume` is documented but not implemented +**Severity:** Medium +**Impact:** User confusion and support churn. + +### Evidence +- README documents `/ajd pause` and `/ajd resume`. +- Slash command parser only handles `pause` (toggle), not `resume`. + +### Recommendation +- Add explicit command handling for `resume` (and optionally `status`) so docs and behavior match. +- Alternatively, update README to reflect that `/ajd pause` toggles both states. + +--- + +## 2) Some user-facing strings bypass localization +**Severity:** Low-Medium +**Impact:** Incomplete localization experience for non-English users. + +### Evidence +- Several chat outputs are hardcoded English debug/status strings (e.g., popup position and minimap status printouts) rather than locale keys. + +### Recommendation +- Move remaining hardcoded `Print("...")` strings into locale keys and reuse `L[...]` for all user-visible text. + +--- + +## 3) Single-file complexity is high; split into modules +**Severity:** Medium (maintainability) +**Impact:** Harder future changes, higher regression risk. + +### Evidence +- `AutoJunkDestroyer.lua` currently combines event routing, UI, deletion logic, AceDB migration/hardening, slash commands, and shard utilities. + +### Recommendation +- Split into focused files (e.g., `Core.lua`, `UI.lua`, `Commands.lua`, `Shard.lua`, `Minimap.lua`, `Migration.lua`). +- Keep startup wiring in one entrypoint file. + +--- + +## 4) AceDB wrapper approach is effective but high-risk if upstream internals change +**Severity:** Medium +**Impact:** Potential compatibility risk with future AceDB internals. + +### Evidence +- The code wraps `AceDB.frame`'s `OnEvent` to sanitize DB state before logout. + +### Recommendation +- Keep this guard, but add an in-code note about AceDB version expectations and a safety no-op path if frame/script shapes change. +- Add lightweight self-check logging only in debug mode. + +--- + +## 5) Add automated static checks in CI (syntax + locale key parity) +**Severity:** Medium (quality process) +**Impact:** Prevents accidental breakage before release. + +### Evidence +- Project currently relies on manual validation; locale correctness is important and easy to regress. + +### Recommendation +- Add a simple CI job to run: + - Lua syntax check for addon source files. + - Locale key parity verification against `Locales/enUS.lua`. +- Keep checks lightweight to match addon repo simplicity. + +--- + +## 6) Small correctness/polish opportunities +**Severity:** Low + +### Observations +- `Print()` uses `(L["ADDON_NAME"] or L["ADDON_NAME"])`, which is redundant. +- Inline comments mention some older event names while code registers `BAG_UPDATE_DELAYED`. + +### Recommendation +- Clean tiny redundancies/comments during next maintenance pass. + +--- + +## What is already strong +- Good combat/BG gating and deferred re-enable behavior. +- Debounced bag refresh strategy. +- Sensible SavedVariables clamping/defaults. +- Dedicated `AutoJunkDestroyerIconDB` and migration cleanup around AceDB shape corruption. + +--- + +## Suggested roadmap (minimal risk) +1. Align slash commands and README (`resume` + optional `status`). +2. Finish localization sweep for remaining hardcoded chat strings. +3. Add lightweight CI checks for syntax and locale parity. +4. Incremental modular split of `AutoJunkDestroyer.lua` with no feature changes. diff --git a/Locales/deDE.lua b/Locales/deDE.lua index 0f154b5..c3094a9 100644 --- a/Locales/deDE.lua +++ b/Locales/deDE.lua @@ -47,5 +47,30 @@ L["SOUL_SHARD"] = "Seelensplitter" L["MSG_LOADED"] = "Geladen." +L["MSG_STATUS"] = "Status: benutzerPausiert=%s, effektivPausiert=%s, imSchlachtfeld=%s, imKampf=%s, buttonSichtbar=%s" +L["MSG_MINIMAP_USAGE"] = "Nutzung: /ajd minimap hide|show|lock|unlock|reset|pos" +L["MSG_MINIMAP_POS_SAVED"] = "Minimap-Pos (gespeichert): %s | versteckt=%s | gesperrt=%s" +L["MSG_POPUP_POS_SAVED_REL"] = "Popup-Pos (gespeichert): xVersatz=%s yVersatz=%s (%s)" +L["MSG_POPUP_POS_SAVED_ABS"] = "Popup-Pos (gespeichert): x=%s y=%s" +L["MSG_POPUP_POS_NOT_SAVED"] = "Popup-Pos noch nicht gespeichert. Aktuell links=%s oben=%s" +L["MSG_HELP_PAUSE"] = "Befehl: /ajd pausieren" +L["MSG_HELP_RESUME"] = "Befehl: /ajd fortsetzen" +L["MSG_HELP_STATUS"] = "Befehl: /ajd zustand" +L["MSG_HELP_TOGGLE"] = "Befehl: /ajd umschalten" +L["MSG_HELP_THRESHOLD"] = "Befehl: /ajd schwelle 90" +L["MSG_HELP_MINIMAP_RESET"] = "Befehl: /ajd mini zuruecksetzen" +L["CMD_ALIAS_PAUSE"] = "pause,pausieren" +L["CMD_ALIAS_RESUME"] = "resume,fortsetzen" +L["CMD_ALIAS_STATUS"] = "status,zustand" +L["CMD_ALIAS_TOGGLE"] = "toggle,umschalten" +L["CMD_ALIAS_THRESHOLD"] = "threshold,schwelle" +L["CMD_ALIAS_BUTTON"] = "button,knopf" +L["CMD_ALIAS_MINIMAP"] = "minimap,mini" +L["CMD_ALIAS_MINIMAP_HIDE"] = "hide,verstecken" +L["CMD_ALIAS_MINIMAP_SHOW"] = "show,zeigen" +L["CMD_ALIAS_MINIMAP_LOCK"] = "lock,sperren" +L["CMD_ALIAS_MINIMAP_UNLOCK"] = "unlock,entsperren" +L["CMD_ALIAS_MINIMAP_RESET"] = "reset,zuruecksetzen" +L["CMD_ALIAS_MINIMAP_POS"] = "pos,position" L["CFF00FF00_DC869E"] = "|cff00ff00" L["R_7FC9D5"] = ":|r " diff --git a/Locales/enUS.lua b/Locales/enUS.lua index 24b7e24..0cabaa9 100644 --- a/Locales/enUS.lua +++ b/Locales/enUS.lua @@ -58,5 +58,30 @@ L["SOUL_SHARD"] = "Soul Shard" L["MSG_LOADED"] = "Loaded." +L["MSG_STATUS"] = "Status: userPaused=%s, effectivePaused=%s, inBattleground=%s, inCombat=%s, buttonShown=%s" +L["MSG_MINIMAP_USAGE"] = "Usage: /ajd minimap hide|show|lock|unlock|reset|pos" +L["MSG_MINIMAP_POS_SAVED"] = "MinimapPos (saved): %s | hide=%s | lock=%s" +L["MSG_POPUP_POS_SAVED_REL"] = "PopupPos (saved): xOfs=%s yOfs=%s (%s)" +L["MSG_POPUP_POS_SAVED_ABS"] = "PopupPos (saved): x=%s y=%s" +L["MSG_POPUP_POS_NOT_SAVED"] = "PopupPos not saved yet. Current left=%s top=%s" +L["MSG_HELP_PAUSE"] = "/ajd pause" +L["MSG_HELP_RESUME"] = "/ajd resume" +L["MSG_HELP_STATUS"] = "/ajd status" +L["MSG_HELP_TOGGLE"] = "/ajd toggle" +L["MSG_HELP_THRESHOLD"] = "/ajd threshold 90" +L["MSG_HELP_MINIMAP_RESET"] = "/ajd minimap reset" +L["CMD_ALIAS_PAUSE"] = "pause" +L["CMD_ALIAS_RESUME"] = "resume" +L["CMD_ALIAS_STATUS"] = "status" +L["CMD_ALIAS_TOGGLE"] = "toggle" +L["CMD_ALIAS_THRESHOLD"] = "threshold" +L["CMD_ALIAS_BUTTON"] = "button" +L["CMD_ALIAS_MINIMAP"] = "minimap" +L["CMD_ALIAS_MINIMAP_HIDE"] = "hide" +L["CMD_ALIAS_MINIMAP_SHOW"] = "show" +L["CMD_ALIAS_MINIMAP_LOCK"] = "lock" +L["CMD_ALIAS_MINIMAP_UNLOCK"] = "unlock" +L["CMD_ALIAS_MINIMAP_RESET"] = "reset" +L["CMD_ALIAS_MINIMAP_POS"] = "pos" L["CFF00FF00_DC869E"] = "|cff00ff00" L["R_7FC9D5"] = ":|r " diff --git a/Locales/esES.lua b/Locales/esES.lua index bf40f39..0aa52b9 100644 --- a/Locales/esES.lua +++ b/Locales/esES.lua @@ -47,5 +47,30 @@ L["SOUL_SHARD"] = "Fragmento de alma" L["MSG_LOADED"] = "Cargado." +L["MSG_STATUS"] = "Estado: pausaUsuario=%s, pausaEfectiva=%s, enCampoDeBatalla=%s, enCombate=%s, botonVisible=%s" +L["MSG_MINIMAP_USAGE"] = "Uso: /ajd minimap hide|show|lock|unlock|reset|pos" +L["MSG_MINIMAP_POS_SAVED"] = "Posición minimapa (guardada): %s | oculto=%s | bloqueado=%s" +L["MSG_POPUP_POS_SAVED_REL"] = "Posición del popup (guardada): xDespl=%s yDespl=%s (%s)" +L["MSG_POPUP_POS_SAVED_ABS"] = "Posición del popup (guardada): x=%s y=%s" +L["MSG_POPUP_POS_NOT_SAVED"] = "La posición del popup aún no se guardó. Actual izquierda=%s arriba=%s" +L["MSG_HELP_PAUSE"] = "Comando: /ajd pausa" +L["MSG_HELP_RESUME"] = "Comando: /ajd reanudar" +L["MSG_HELP_STATUS"] = "Comando: /ajd estado" +L["MSG_HELP_TOGGLE"] = "Comando: /ajd alternar" +L["MSG_HELP_THRESHOLD"] = "Comando: /ajd umbral 90" +L["MSG_HELP_MINIMAP_RESET"] = "Comando: /ajd mini reiniciar" +L["CMD_ALIAS_PAUSE"] = "pause,pausa" +L["CMD_ALIAS_RESUME"] = "resume,reanudar" +L["CMD_ALIAS_STATUS"] = "status,estado" +L["CMD_ALIAS_TOGGLE"] = "toggle,alternar" +L["CMD_ALIAS_THRESHOLD"] = "threshold,umbral" +L["CMD_ALIAS_BUTTON"] = "button,boton" +L["CMD_ALIAS_MINIMAP"] = "minimap,mini" +L["CMD_ALIAS_MINIMAP_HIDE"] = "hide,ocultar" +L["CMD_ALIAS_MINIMAP_SHOW"] = "show,mostrar" +L["CMD_ALIAS_MINIMAP_LOCK"] = "lock,bloquear" +L["CMD_ALIAS_MINIMAP_UNLOCK"] = "unlock,desbloquear" +L["CMD_ALIAS_MINIMAP_RESET"] = "reset,reiniciar" +L["CMD_ALIAS_MINIMAP_POS"] = "pos,posicion" L["CFF00FF00_DC869E"] = "|cff00ff00" L["R_7FC9D5"] = ":|r " diff --git a/Locales/esMX.lua b/Locales/esMX.lua index 773ffff..eebe62f 100644 --- a/Locales/esMX.lua +++ b/Locales/esMX.lua @@ -47,5 +47,30 @@ L["SOUL_SHARD"] = "Fragmento de alma" L["MSG_LOADED"] = "Cargado." +L["MSG_STATUS"] = "Estado: pausaUsuario=%s, pausaEfectiva=%s, enCampoDeBatalla=%s, enCombate=%s, botonVisible=%s" +L["MSG_MINIMAP_USAGE"] = "Uso: /ajd minimap hide|show|lock|unlock|reset|pos" +L["MSG_MINIMAP_POS_SAVED"] = "Posición del minimapa (guardada): %s | oculto=%s | bloqueado=%s" +L["MSG_POPUP_POS_SAVED_REL"] = "Posición del popup (guardada): xDespl=%s yDespl=%s (%s)" +L["MSG_POPUP_POS_SAVED_ABS"] = "Posición del popup (guardada): x=%s y=%s" +L["MSG_POPUP_POS_NOT_SAVED"] = "La posición del popup aún no se guardó. Actual izquierda=%s arriba=%s" +L["MSG_HELP_PAUSE"] = "Comando: /ajd pausa" +L["MSG_HELP_RESUME"] = "Comando: /ajd reanudar" +L["MSG_HELP_STATUS"] = "Comando: /ajd estado" +L["MSG_HELP_TOGGLE"] = "Comando: /ajd alternar" +L["MSG_HELP_THRESHOLD"] = "Comando: /ajd umbral 90" +L["MSG_HELP_MINIMAP_RESET"] = "Comando: /ajd mini reiniciar" +L["CMD_ALIAS_PAUSE"] = "pause,pausa" +L["CMD_ALIAS_RESUME"] = "resume,reanudar" +L["CMD_ALIAS_STATUS"] = "status,estado" +L["CMD_ALIAS_TOGGLE"] = "toggle,alternar" +L["CMD_ALIAS_THRESHOLD"] = "threshold,umbral" +L["CMD_ALIAS_BUTTON"] = "button,boton" +L["CMD_ALIAS_MINIMAP"] = "minimap,mini" +L["CMD_ALIAS_MINIMAP_HIDE"] = "hide,ocultar" +L["CMD_ALIAS_MINIMAP_SHOW"] = "show,mostrar" +L["CMD_ALIAS_MINIMAP_LOCK"] = "lock,bloquear" +L["CMD_ALIAS_MINIMAP_UNLOCK"] = "unlock,desbloquear" +L["CMD_ALIAS_MINIMAP_RESET"] = "reset,reiniciar" +L["CMD_ALIAS_MINIMAP_POS"] = "pos,posicion" L["CFF00FF00_DC869E"] = "|cff00ff00" L["R_7FC9D5"] = ":|r " diff --git a/Locales/frFR.lua b/Locales/frFR.lua index 375dd53..d67028b 100644 --- a/Locales/frFR.lua +++ b/Locales/frFR.lua @@ -47,5 +47,30 @@ L["SOUL_SHARD"] = "Fragment d’âme" L["MSG_LOADED"] = "Chargé." +L["MSG_STATUS"] = "Statut : pauseUtilisateur=%s, pauseEffective=%s, enChampDeBataille=%s, enCombat=%s, boutonVisible=%s" +L["MSG_MINIMAP_USAGE"] = "Utilisation : /ajd minimap hide|show|lock|unlock|reset|pos" +L["MSG_MINIMAP_POS_SAVED"] = "Position minimap (enregistrée) : %s | cachée=%s | verrouillée=%s" +L["MSG_POPUP_POS_SAVED_REL"] = "Position popup (enregistrée) : xDécalage=%s yDécalage=%s (%s)" +L["MSG_POPUP_POS_SAVED_ABS"] = "Position popup (enregistrée) : x=%s y=%s" +L["MSG_POPUP_POS_NOT_SAVED"] = "Position popup pas encore enregistrée. Position actuelle gauche=%s haut=%s" +L["MSG_HELP_PAUSE"] = "Commande : /ajd pause" +L["MSG_HELP_RESUME"] = "Commande : /ajd reprendre" +L["MSG_HELP_STATUS"] = "Commande : /ajd etat" +L["MSG_HELP_TOGGLE"] = "Commande : /ajd basculer" +L["MSG_HELP_THRESHOLD"] = "Commande : /ajd seuil 90" +L["MSG_HELP_MINIMAP_RESET"] = "Commande : /ajd mini reinit" +L["CMD_ALIAS_PAUSE"] = "pause" +L["CMD_ALIAS_RESUME"] = "resume,reprendre" +L["CMD_ALIAS_STATUS"] = "status,etat" +L["CMD_ALIAS_TOGGLE"] = "toggle,basculer" +L["CMD_ALIAS_THRESHOLD"] = "threshold,seuil" +L["CMD_ALIAS_BUTTON"] = "button,bouton" +L["CMD_ALIAS_MINIMAP"] = "minimap,mini" +L["CMD_ALIAS_MINIMAP_HIDE"] = "hide,cacher" +L["CMD_ALIAS_MINIMAP_SHOW"] = "show,afficher" +L["CMD_ALIAS_MINIMAP_LOCK"] = "lock,verrouiller" +L["CMD_ALIAS_MINIMAP_UNLOCK"] = "unlock,deverrouiller" +L["CMD_ALIAS_MINIMAP_RESET"] = "reset,reinit" +L["CMD_ALIAS_MINIMAP_POS"] = "pos,position" L["CFF00FF00_DC869E"] = "|cff00ff00" L["R_7FC9D5"] = ":|r " diff --git a/Locales/itIT.lua b/Locales/itIT.lua index e8f6d90..c40815b 100644 --- a/Locales/itIT.lua +++ b/Locales/itIT.lua @@ -47,5 +47,30 @@ L["SOUL_SHARD"] = "Scheggia dell’anima" L["MSG_LOADED"] = "Caricato." +L["MSG_STATUS"] = "Stato: pausaUtente=%s, pausaEffettiva=%s, inCampoDiBattaglia=%s, inCombattimento=%s, pulsanteVisibile=%s" +L["MSG_MINIMAP_USAGE"] = "Uso: /ajd minimap hide|show|lock|unlock|reset|pos" +L["MSG_MINIMAP_POS_SAVED"] = "Posizione minimappa (salvata): %s | nascosta=%s | bloccata=%s" +L["MSG_POPUP_POS_SAVED_REL"] = "Posizione popup (salvata): xOffset=%s yOffset=%s (%s)" +L["MSG_POPUP_POS_SAVED_ABS"] = "Posizione popup (salvata): x=%s y=%s" +L["MSG_POPUP_POS_NOT_SAVED"] = "Posizione popup non ancora salvata. Attuale sinistra=%s alto=%s" +L["MSG_HELP_PAUSE"] = "Comando: /ajd pausa" +L["MSG_HELP_RESUME"] = "Comando: /ajd riprendi" +L["MSG_HELP_STATUS"] = "Comando: /ajd stato" +L["MSG_HELP_TOGGLE"] = "Comando: /ajd commuta" +L["MSG_HELP_THRESHOLD"] = "Comando: /ajd soglia 90" +L["MSG_HELP_MINIMAP_RESET"] = "Comando: /ajd mini resetta" +L["CMD_ALIAS_PAUSE"] = "pause,pausa" +L["CMD_ALIAS_RESUME"] = "resume,riprendi" +L["CMD_ALIAS_STATUS"] = "status,stato" +L["CMD_ALIAS_TOGGLE"] = "toggle,commuta" +L["CMD_ALIAS_THRESHOLD"] = "threshold,soglia" +L["CMD_ALIAS_BUTTON"] = "button,pulsante" +L["CMD_ALIAS_MINIMAP"] = "minimap,mini" +L["CMD_ALIAS_MINIMAP_HIDE"] = "hide,nascondi" +L["CMD_ALIAS_MINIMAP_SHOW"] = "show,mostra" +L["CMD_ALIAS_MINIMAP_LOCK"] = "lock,blocca" +L["CMD_ALIAS_MINIMAP_UNLOCK"] = "unlock,sblocca" +L["CMD_ALIAS_MINIMAP_RESET"] = "reset,resetta" +L["CMD_ALIAS_MINIMAP_POS"] = "pos,posizione" L["CFF00FF00_DC869E"] = "|cff00ff00" L["R_7FC9D5"] = ":|r " diff --git a/Locales/koKR.lua b/Locales/koKR.lua index 922888c..93d2158 100644 --- a/Locales/koKR.lua +++ b/Locales/koKR.lua @@ -47,5 +47,30 @@ L["SOUL_SHARD"] = "영혼의 조각" L["MSG_LOADED"] = "로드됨." +L["MSG_STATUS"] = "상태: 사용자일시정지=%s, 유효일시정지=%s, 전장중=%s, 전투중=%s, 버튼표시=%s" +L["MSG_MINIMAP_USAGE"] = "사용법: /ajd minimap hide|show|lock|unlock|reset|pos" +L["MSG_MINIMAP_POS_SAVED"] = "미니맵 위치(저장됨): %s | 숨김=%s | 잠금=%s" +L["MSG_POPUP_POS_SAVED_REL"] = "팝업 위치(저장됨): x오프셋=%s y오프셋=%s (%s)" +L["MSG_POPUP_POS_SAVED_ABS"] = "팝업 위치(저장됨): x=%s y=%s" +L["MSG_POPUP_POS_NOT_SAVED"] = "팝업 위치가 아직 저장되지 않았습니다. 현재 left=%s top=%s" +L["MSG_HELP_PAUSE"] = "명령어: /ajd 일시정지" +L["MSG_HELP_RESUME"] = "명령어: /ajd 재개" +L["MSG_HELP_STATUS"] = "명령어: /ajd 상태" +L["MSG_HELP_TOGGLE"] = "명령어: /ajd 전환" +L["MSG_HELP_THRESHOLD"] = "명령어: /ajd 임계값 90" +L["MSG_HELP_MINIMAP_RESET"] = "명령어: /ajd 미니맵 초기화" +L["CMD_ALIAS_PAUSE"] = "pause,일시정지" +L["CMD_ALIAS_RESUME"] = "resume,재개" +L["CMD_ALIAS_STATUS"] = "status,상태" +L["CMD_ALIAS_TOGGLE"] = "toggle,전환" +L["CMD_ALIAS_THRESHOLD"] = "threshold,임계값" +L["CMD_ALIAS_BUTTON"] = "button,버튼" +L["CMD_ALIAS_MINIMAP"] = "minimap,미니맵" +L["CMD_ALIAS_MINIMAP_HIDE"] = "hide,숨김" +L["CMD_ALIAS_MINIMAP_SHOW"] = "show,표시" +L["CMD_ALIAS_MINIMAP_LOCK"] = "lock,잠금" +L["CMD_ALIAS_MINIMAP_UNLOCK"] = "unlock,잠금해제" +L["CMD_ALIAS_MINIMAP_RESET"] = "reset,초기화" +L["CMD_ALIAS_MINIMAP_POS"] = "pos,위치" L["CFF00FF00_DC869E"] = "|cff00ff00" L["R_7FC9D5"] = ":|r " diff --git a/Locales/ptBR.lua b/Locales/ptBR.lua index 5257465..52c838c 100644 --- a/Locales/ptBR.lua +++ b/Locales/ptBR.lua @@ -47,5 +47,30 @@ L["SOUL_SHARD"] = "Fragmento de Alma" L["MSG_LOADED"] = "Carregado." +L["MSG_STATUS"] = "Status: pausaUsuario=%s, pausaEfetiva=%s, emCampoDeBatalha=%s, emCombate=%s, botaoVisivel=%s" +L["MSG_MINIMAP_USAGE"] = "Uso: /ajd minimap hide|show|lock|unlock|reset|pos" +L["MSG_MINIMAP_POS_SAVED"] = "Posição do minimapa (salva): %s | oculto=%s | travado=%s" +L["MSG_POPUP_POS_SAVED_REL"] = "Posição do popup (salva): xDesloc=%s yDesloc=%s (%s)" +L["MSG_POPUP_POS_SAVED_ABS"] = "Posição do popup (salva): x=%s y=%s" +L["MSG_POPUP_POS_NOT_SAVED"] = "Posição do popup ainda não salva. Atual esquerda=%s topo=%s" +L["MSG_HELP_PAUSE"] = "Comando: /ajd pausar" +L["MSG_HELP_RESUME"] = "Comando: /ajd retomar" +L["MSG_HELP_STATUS"] = "Comando: /ajd estado" +L["MSG_HELP_TOGGLE"] = "Comando: /ajd alternar" +L["MSG_HELP_THRESHOLD"] = "Comando: /ajd limiar 90" +L["MSG_HELP_MINIMAP_RESET"] = "Comando: /ajd mini redefinir" +L["CMD_ALIAS_PAUSE"] = "pause,pausar" +L["CMD_ALIAS_RESUME"] = "resume,retomar" +L["CMD_ALIAS_STATUS"] = "status,estado" +L["CMD_ALIAS_TOGGLE"] = "toggle,alternar" +L["CMD_ALIAS_THRESHOLD"] = "threshold,limiar" +L["CMD_ALIAS_BUTTON"] = "button,botao" +L["CMD_ALIAS_MINIMAP"] = "minimap,mini" +L["CMD_ALIAS_MINIMAP_HIDE"] = "hide,ocultar" +L["CMD_ALIAS_MINIMAP_SHOW"] = "show,mostrar" +L["CMD_ALIAS_MINIMAP_LOCK"] = "lock,bloquear" +L["CMD_ALIAS_MINIMAP_UNLOCK"] = "unlock,desbloquear" +L["CMD_ALIAS_MINIMAP_RESET"] = "reset,redefinir" +L["CMD_ALIAS_MINIMAP_POS"] = "pos,posicao" L["CFF00FF00_DC869E"] = "|cff00ff00" L["R_7FC9D5"] = ":|r " diff --git a/Locales/ruRU.lua b/Locales/ruRU.lua index a7840a9..145d9ba 100644 --- a/Locales/ruRU.lua +++ b/Locales/ruRU.lua @@ -47,5 +47,30 @@ L["SOUL_SHARD"] = "Осколок души" L["MSG_LOADED"] = "Загружено." +L["MSG_STATUS"] = "Статус: пользовательПауза=%s, эффективнаяПауза=%s, вПолеБоя=%s, вБою=%s, кнопкаПоказана=%s" +L["MSG_MINIMAP_USAGE"] = "Использование: /ajd minimap hide|show|lock|unlock|reset|pos" +L["MSG_MINIMAP_POS_SAVED"] = "Позиция миникарты (сохранена): %s | скрыта=%s | заблокирована=%s" +L["MSG_POPUP_POS_SAVED_REL"] = "Позиция окна (сохранена): xСмещение=%s yСмещение=%s (%s)" +L["MSG_POPUP_POS_SAVED_ABS"] = "Позиция окна (сохранена): x=%s y=%s" +L["MSG_POPUP_POS_NOT_SAVED"] = "Позиция окна ещё не сохранена. Текущая left=%s top=%s" +L["MSG_HELP_PAUSE"] = "Команда: /ajd пауза" +L["MSG_HELP_RESUME"] = "Команда: /ajd продолжить" +L["MSG_HELP_STATUS"] = "Команда: /ajd статус" +L["MSG_HELP_TOGGLE"] = "Команда: /ajd переключить" +L["MSG_HELP_THRESHOLD"] = "Команда: /ajd порог 90" +L["MSG_HELP_MINIMAP_RESET"] = "Команда: /ajd миникарта сброс" +L["CMD_ALIAS_PAUSE"] = "pause,пауза" +L["CMD_ALIAS_RESUME"] = "resume,продолжить" +L["CMD_ALIAS_STATUS"] = "status,статус" +L["CMD_ALIAS_TOGGLE"] = "toggle,переключить" +L["CMD_ALIAS_THRESHOLD"] = "threshold,порог" +L["CMD_ALIAS_BUTTON"] = "button,кнопка" +L["CMD_ALIAS_MINIMAP"] = "minimap,миникарта" +L["CMD_ALIAS_MINIMAP_HIDE"] = "hide,скрыть" +L["CMD_ALIAS_MINIMAP_SHOW"] = "show,показать" +L["CMD_ALIAS_MINIMAP_LOCK"] = "lock,закрепить" +L["CMD_ALIAS_MINIMAP_UNLOCK"] = "unlock,открепить" +L["CMD_ALIAS_MINIMAP_RESET"] = "reset,сброс" +L["CMD_ALIAS_MINIMAP_POS"] = "pos,позиция" L["CFF00FF00_DC869E"] = "|cff00ff00" L["R_7FC9D5"] = ":|r " diff --git a/Locales/zhCN.lua b/Locales/zhCN.lua index 4e2b860..3d5e312 100644 --- a/Locales/zhCN.lua +++ b/Locales/zhCN.lua @@ -47,5 +47,30 @@ L["SOUL_SHARD"] = "灵魂碎片" L["MSG_LOADED"] = "已加载。" +L["MSG_STATUS"] = "状态:用户暂停=%s,实际暂停=%s,位于战场=%s,战斗中=%s,按钮显示=%s" +L["MSG_MINIMAP_USAGE"] = "用法:/ajd minimap hide|show|lock|unlock|reset|pos" +L["MSG_MINIMAP_POS_SAVED"] = "小地图位置(已保存):%s | 隐藏=%s | 锁定=%s" +L["MSG_POPUP_POS_SAVED_REL"] = "弹窗位置(已保存):x偏移=%s y偏移=%s (%s)" +L["MSG_POPUP_POS_SAVED_ABS"] = "弹窗位置(已保存):x=%s y=%s" +L["MSG_POPUP_POS_NOT_SAVED"] = "弹窗位置尚未保存。当前 left=%s top=%s" +L["MSG_HELP_PAUSE"] = "命令:/ajd 暂停" +L["MSG_HELP_RESUME"] = "命令:/ajd 继续" +L["MSG_HELP_STATUS"] = "命令:/ajd 状态" +L["MSG_HELP_TOGGLE"] = "命令:/ajd 切换" +L["MSG_HELP_THRESHOLD"] = "命令:/ajd 阈值 90" +L["MSG_HELP_MINIMAP_RESET"] = "命令:/ajd 小地图 重置" +L["CMD_ALIAS_PAUSE"] = "pause,暂停" +L["CMD_ALIAS_RESUME"] = "resume,继续" +L["CMD_ALIAS_STATUS"] = "status,状态" +L["CMD_ALIAS_TOGGLE"] = "toggle,切换" +L["CMD_ALIAS_THRESHOLD"] = "threshold,阈值" +L["CMD_ALIAS_BUTTON"] = "button,按钮" +L["CMD_ALIAS_MINIMAP"] = "minimap,小地图" +L["CMD_ALIAS_MINIMAP_HIDE"] = "hide,隐藏" +L["CMD_ALIAS_MINIMAP_SHOW"] = "show,显示" +L["CMD_ALIAS_MINIMAP_LOCK"] = "lock,锁定" +L["CMD_ALIAS_MINIMAP_UNLOCK"] = "unlock,解锁" +L["CMD_ALIAS_MINIMAP_RESET"] = "reset,重置" +L["CMD_ALIAS_MINIMAP_POS"] = "pos,位置" L["CFF00FF00_DC869E"] = "|cff00ff00" L["R_7FC9D5"] = ":|r " diff --git a/Locales/zhTW.lua b/Locales/zhTW.lua index fb83ff3..3eb0296 100644 --- a/Locales/zhTW.lua +++ b/Locales/zhTW.lua @@ -47,5 +47,30 @@ L["SOUL_SHARD"] = "靈魂碎片" L["MSG_LOADED"] = "已載入。" +L["MSG_STATUS"] = "狀態:使用者暫停=%s,實際暫停=%s,位於戰場=%s,戰鬥中=%s,按鈕顯示=%s" +L["MSG_MINIMAP_USAGE"] = "用法:/ajd minimap hide|show|lock|unlock|reset|pos" +L["MSG_MINIMAP_POS_SAVED"] = "小地圖位置(已儲存):%s | 隱藏=%s | 鎖定=%s" +L["MSG_POPUP_POS_SAVED_REL"] = "彈出視窗位置(已儲存):x偏移=%s y偏移=%s (%s)" +L["MSG_POPUP_POS_SAVED_ABS"] = "彈出視窗位置(已儲存):x=%s y=%s" +L["MSG_POPUP_POS_NOT_SAVED"] = "彈出視窗位置尚未儲存。目前 left=%s top=%s" +L["MSG_HELP_PAUSE"] = "指令:/ajd 暫停" +L["MSG_HELP_RESUME"] = "指令:/ajd 繼續" +L["MSG_HELP_STATUS"] = "指令:/ajd 狀態" +L["MSG_HELP_TOGGLE"] = "指令:/ajd 切換" +L["MSG_HELP_THRESHOLD"] = "指令:/ajd 臨界值 90" +L["MSG_HELP_MINIMAP_RESET"] = "指令:/ajd 小地圖 重設" +L["CMD_ALIAS_PAUSE"] = "pause,暫停" +L["CMD_ALIAS_RESUME"] = "resume,繼續" +L["CMD_ALIAS_STATUS"] = "status,狀態" +L["CMD_ALIAS_TOGGLE"] = "toggle,切換" +L["CMD_ALIAS_THRESHOLD"] = "threshold,臨界值" +L["CMD_ALIAS_BUTTON"] = "button,按鈕" +L["CMD_ALIAS_MINIMAP"] = "minimap,小地圖" +L["CMD_ALIAS_MINIMAP_HIDE"] = "hide,隱藏" +L["CMD_ALIAS_MINIMAP_SHOW"] = "show,顯示" +L["CMD_ALIAS_MINIMAP_LOCK"] = "lock,鎖定" +L["CMD_ALIAS_MINIMAP_UNLOCK"] = "unlock,解鎖" +L["CMD_ALIAS_MINIMAP_RESET"] = "reset,重設" +L["CMD_ALIAS_MINIMAP_POS"] = "pos,位置" L["CFF00FF00_DC869E"] = "|cff00ff00" L["R_7FC9D5"] = ":|r " diff --git a/README.md b/README.md index 0bdb1fc..c8379c1 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,6 @@ AutoJunkDestroyer adds a simple button to delete grey (junk) items on demand, pl - If there are many, it may ask you to click again to continue. - Minimap icon tooltip shows controls. -## Slash commands -- `/ajd threshold ` — set bag fullness threshold (e.g. `90` or `0.90`). -- `/ajd minimap hide|show|lock|unlock|reset` -- `/ajd pause` / `/ajd resume` ## Localization This addon is fully localized for these client locales: @@ -40,3 +36,4 @@ Bundled (embedded) libraries: - Minimap icon with lock/hide/reset - **Full localization**: enUS, deDE, frFR, esES, esMX, itIT, ptBR, ruRU, koKR, zhCN, zhTW + diff --git a/scripts/check_locale_parity.py b/scripts/check_locale_parity.py new file mode 100755 index 0000000..6191fa6 --- /dev/null +++ b/scripts/check_locale_parity.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +import glob +import re +import sys + + +def locale_keys(path: str): + with open(path, encoding='utf-8') as f: + text = f.read() + return set(re.findall(r'L\["([^"]+)"\]\s*=', text)) + + +def main() -> int: + base_path = 'Locales/enUS.lua' + base = locale_keys(base_path) + ok = True + for path in sorted(glob.glob('Locales/*.lua')): + keys = locale_keys(path) + missing = sorted(base - keys) + extra = sorted(keys - base) + if missing or extra: + ok = False + print(f'{path}: missing={len(missing)} extra={len(extra)}') + if missing: + print(' missing keys:', ', '.join(missing[:10])) + if extra: + print(' extra keys:', ', '.join(extra[:10])) + if ok: + print(f'Locale key parity OK across {len(glob.glob("Locales/*.lua"))} files') + return 0 + return 1 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/scripts/check_lua_syntax.sh b/scripts/check_lua_syntax.sh new file mode 100755 index 0000000..2e8ab3d --- /dev/null +++ b/scripts/check_lua_syntax.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail + +if ! command -v luac >/dev/null 2>&1; then + echo "luac not found; install lua5.1 or lua to run syntax checks" >&2 + exit 1 +fi + +files=(AutoJunkDestroyer.lua) +while IFS= read -r f; do + files+=("$f") +done < <(find Locales -maxdepth 1 -type f -name '*.lua' | sort) + +for f in "${files[@]}"; do + luac -p "$f" +done + +echo "Lua syntax checks passed for ${#files[@]} files"