From f1f2192b7b8b580aca4e40474120da93c5099ffd Mon Sep 17 00:00:00 2001 From: Tphamtranba <119475427+Bapham12@users.noreply.github.com> Date: Tue, 13 Jan 2026 21:27:52 +0700 Subject: [PATCH 1/2] Implement Formatnum module in Lua This module replaces Template:Formatnum functionality with a Lua implementation, providing number formatting based on language and precision. --- Other/Formatnum.lua | 143 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 Other/Formatnum.lua diff --git a/Other/Formatnum.lua b/Other/Formatnum.lua new file mode 100644 index 0000000..d5aafb2 --- /dev/null +++ b/Other/Formatnum.lua @@ -0,0 +1,143 @@ +-- This module is intended to replace the functionality of Template:Formatnum and related templates. +local p = {} -- Holds functions to be returned from #invoke, and functions to make available to other Lua modules. + +--[[ +Helper functions used to avoid redundant code. +]] + +local function getArgs(frame) + local args = {} + for key, value in pairs(frame:getParent().args) do + args[key] = value + end + for key, value in pairs(frame.args) do + args[key] = value + end + return args +end + +function p.main(frame) + local args = getArgs(frame) + local prec = args.prec or '' + local sep = args.sep or '' + local number = args[1] or args.number or '' + local lang = args[2] or args.lang or '' + -- validate the language parameter within MediaWiki's caller frame + if lang:lower() == "none" then + -- no language, so do nothing + elseif lang == "arabic-indic" then -- only for back-compatibility ("arabic-indic" is not a SupportedLanguage) + lang = "fa" -- better support than "ks" + elseif lang == '' or not mw.language.isSupportedLanguage(lang) then + -- Note that 'SupportedLanguages' are not necessarily 'BuiltinValidCodes', and so they are not necessarily + -- 'KnownLanguages' (with a language name defined at least in the default localisation of the local wiki). + -- But they all are ValidLanguageCodes (suitable as Wiki subpages or identifiers: no slash, colon, HTML tags, or entities) + -- In addition, they do not contain any capital letter in order to be unique in page titles (restriction inexistant in BCP47), + -- but they may violate the standard format of BCP47 language tags for specific needs in MediaWiki. + -- Empty/unspecified and unsupported languages are treated here in Commons using the user's language, + -- instead of the local 'ContentLanguage' of the Wiki. + lang = frame:callParserFunction( "int", "lang" ) -- get user's chosen language + if not mw.language.isSupportedLanguage(lang) then + lang = mw.language.getContentLanguage().code + end + end + return p.formatNum(number, lang, prec, sep ~= '') +end + +local digit = { -- substitution of decimal digits for languages not supported by mw.language:formatNum() in core Lua libraries for MediaWiki + ["ml-old"] = { '൦', '൧', '൨', '൩', '൪', '൫', '൬', '൭', '൮', '൯' }, + ["mn"] = { '᠐', '᠑', '᠒', '᠓', '᠔', '᠕', '᠖', '᠗', '᠘', '᠙'}, + ["ta"] = { '௦', '௧', '௨', '௩', '௪', '௫', '௬', '௭', '௮', '௯'}, + ["te"] = { '౦', '౧', '౨', '౩', '౪', '౫', '౬', '౭', '౮', '౯'}, + ["th"] = { '๐', '๑', '๒', '๓', '๔', '๕', '๖', '๗', '๘', '๙'} +} + +function p.formatNum(number, lang, prec, compact) + -- Do not alter the specified value when it is not a valid number, return it as is + local value = tonumber(number) + if value == nil then + return number + end + -- Basic ASCII-only formatting (without paddings) + number = tostring(value) + + -- Check the presence of an exponent (incorrectly managed in mw.language:FormatNum() and even forgotten due to an internal bug, e.g. in Hindi) + local exponent + local pos = string.find(number, '[Ee]') + if pos ~= nil then + exponent = string.sub(number, pos + 1, string.len(number)) + number = string.sub(number, 1, pos - 1) + else + exponent = '' + end + + -- Check the minimum precision requested + prec = tonumber(prec) -- nil if not specified as a true number + if prec ~= nil then + prec = math.floor(prec) + if prec < 0 then + prec = nil -- discard an incorrect precision (not a positive integer) + elseif prec > 14 then + prec = 14 -- maximum precision supported by tostring(number) + end + end + + -- Preprocess the minimum precision in the ASCII string + local dot + if (prec or 0) > 0 then + pos = string.find(number, '.', 1, true) -- plain search, no regexp + if pos ~= nil then + prec = pos + prec - string.len(number) -- effective number of trailing decimals to add or remove + dot = '' -- already present + else + dot = '.' -- must be added + end + else + dot = '' -- don't add dot + prec = 0 -- don't alter the precision + end + + if lang ~= nil and mw.language.isKnownLanguageTag(lang) == true then + -- Convert number to localized digits, decimal separator, and group separators + local language = mw.getLanguage(lang) + if compact then + number = language:formatNum(tonumber(number), { noCommafy = 'y' }) -- caveat: can load localized resources for up to 20 languages + else + number = language:formatNum(tonumber(number)) -- caveat: can load localized resources for up to 20 languages + end + -- Postprocessing the precision + if prec > 0 then + local zero = language:formatNum(0) + number = number .. dot .. mw.ustring.rep(zero, prec) + elseif prec < 0 then + -- TODO: rounding of last decimal; here only truncate decimals in excess + number = mw.ustring.sub(number, 1, mw.ustring.len(number) + prec) + end + -- Append the localized base-10 exponent without grouping separators (there's no reliable way to detect a localized leading symbol 'E') + if exponent ~= '' then + number = number .. 'E' .. language:formatNum(tonumber(exponent),{noCommafy=true}) + end + else -- not localized, ASCII only + -- Postprocessing the precision + if prec > 0 then + number = number .. dot .. mw.string.rep('0', prec) + elseif prec < 0 then + -- TODO: rounding of last decimal; here only truncate decimals in excess + number = mw.string.sub(number, 1, mw.string.len(number) + prec) + end + -- Append the base-10 exponent + if exponent ~= '' then + number = number .. 'E' .. exponent + end + end + + -- Special cases for substitution of ASCII digits (missing support in Lua core libraries for some languages) + if digit[lang] then + for i, v in ipairs(digit[lang]) do + number = mw.ustring.gsub(number, tostring(i - 1), v) + end + end + + return number +end + +return p From 104c7c2dbe774f93db8ffa6ff8ac0d5d064846ae Mon Sep 17 00:00:00 2001 From: Tphamtranba <119475427+Bapham12@users.noreply.github.com> Date: Tue, 13 Jan 2026 21:30:17 +0700 Subject: [PATCH 2/2] Remove Luacheck linter from GitHub Actions workflow Removed Luacheck linter step from workflow. --- .github/workflows/main.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cce7b98..5ba239e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,5 +6,3 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Luacheck linter - uses: lunarmodules/luacheck@v1