Jump to content
Toggle menu
  • 8 articles
  • 75 files
  • 7 users
  • 37.8K edits
Neodyland Wiki
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:Formatnum: Difference between revisions

From Neodyland Wiki
m there are other languages for which we'll need digits substitution, simplify the test of languages by just looking if they are defined in digit[lang]
revert my previous edit but keep the code formatting
 
(16 intermediate revisions by 4 users not shown)
Line 2: Line 2:
local p = {}
local p = {}


local digit = { -- substitution of decimal digits for languages not supported by Language:formatNum() in core Lua libraries for MediaWiki
function p.main(frame)
["ml-old"] = { '൦', '൧', '൨', '൩', '൪', '൫', '൬', '൭', '൮', '൯' },
    local args = frame:getParent().args
["mn"]    = { '᠐', '᠑', '᠒', '᠓', '᠔', '᠕', '᠖', '᠗', '᠘', '᠙'},
    local prec    = args.prec or ''
["te"]    = { '౦', '౧', '౨', '౩', '౪', '౫', '౬', '౭', '౮', '౯'},
    local sep    = args.sep or ''
["th"]    = { '๐', '๑', '๒', '๓', '๔', '๕', '๖', '๗', '๘', '๙'}
    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 == "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
    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.main(frame)
function p.formatNum(number, lang, prec, compact)
local pframe = frame:getParent()
 
local config = frame.args
    -- Do not alter the specified value when it is not a valid number, return it as is
local prec  = pframe.args.prec
    local value = tonumber(number)
local number = pframe.args[1]
    if value == nil then
local lang  = pframe.args[2]
        return number
local sep    = pframe.args.sep or ""
    end
if not lang or not mw.language.isSupportedLanguage(lang) then
    -- Basic ASCII-only formatting (without paddings)
lang = frame:preprocess( "{{int:lang}}" )
    number = tostring(value)
end
 
return p._main(number, lang, sep, prec, config)
    -- Check the presence of an exponent (incorrectly managed in mw.language:FormatNum() and even forgotten due to an internal bug, e.g. in Hindi)
end
    local exponent
    local pos = string.find(number, '[Ee]')
function p._main(number, lang, sep, prec, config)
    if pos ~= nil then
-- Preprocessing prec
        exponent = string.sub(number, pos + 1, string.len(number))
local precNum = tonumber(prec)
        number = string.sub(number, 1, pos - 1)
if precNum ~= nil and precNum > 0 and tonumber(number) ~= nil then
    else
if string.find(tostring(number), "%.") ~= nil then
        exponent = ''
if (string.len(number) - string.find(tostring(number), "%.")) < precNum then
    end
precnumber = "" .. number .. string.rep("0", precNum - (string.len(number) - string.find(tostring(number), "%.")))
 
elseif (string.len(number) - string.find(tostring(number), "%.")) > precNum then
    -- Check the minimum precision requested
local proc = string.gsub(number, "0+$", "")
    prec = tonumber(prec) -- nil if not specified as a true number
if (string.len(proc) - string.find(tostring(proc), "%.")) < precNum then
    if prec ~= nil then
precnumber = proc .. string.rep("0", precNum - (string.len(proc) - string.find(tostring(proc), "%.")))
        prec = math.floor(prec)
else
        if prec < 0 then
precnumber = proc
            prec = nil -- discard an incorrect precision (not a positive integer)
end
        elseif prec > 14 then
elseif (string.len(number) - string.find(tostring(number), "%.")) == precNum then
            prec = 14 -- maximum precision supported by tostring(number)
precnumber = number
        end
end
    end
else
 
precnumber = "" .. number .. "." .. string.rep("0", prec)
    -- Preprocess the minimum precision in the ASCII string
end
    local dot
number = precnumber .. "1"
    if (prec or 0) > 0 then
precA = "true"
        pos = string.find(number, '.', 1, true) -- plain search, no regexp
end
        if pos ~= nil then
            prec = pos + prec - string.len(number) -- effective number of trailing decimals to add or remove
if lang == "arabic-indic" then
            dot = '' -- already present
lang = "ks"
        else
end
            dot = mw.ustring.sub (mw.language.new(lang):formatNum(0.1), 2, 2) -- must be added
        end
-- Formatnum
    else
if tonumber(number) ~= nil and mw.language.isKnownLanguageTag(lang) == true then
        dot = '' -- don't add dot
formatnum = mw.getLanguage( lang ):formatNum( tonumber(number) )
        prec = 0 -- don't alter the precision
else
    end
formatnum = number
 
formatA = "true"
    if lang ~= nil and mw.language.isKnownLanguageTag(lang) == true then
end
        -- Convert number to localized digits, decimal separator, and group separators
        local language = mw.getLanguage(lang)
-- Formatnum, special cases for substitution of digits
        if compact then
local numsc = formatnum
            number = language:formatNum(tonumber(number), { noCommafy = 'y' }) -- caveat: can load localized resources for up to 20 languages
if digit[lang] then
        else
for i, v in ipairs( digit[lang] ) do
            number = language:formatNum(tonumber(number)) -- caveat: can load localized resources for up to 20 languages
numsc = mw.ustring.gsub(numsc, tostring(i-1), v)
        end
end
        -- Postprocessing the precision
end
        if prec > 0 then
            local zero = language:formatNum(0)
--Postprocessing prec
            number = number .. dot .. mw.ustring.rep(zero, prec)
if precA == "true" then
        elseif prec < 0 then
postprec = mw.ustring.sub(numsc, 1, (mw.ustring.len(numsc) - 1))
            -- TODO: rounding of last decimal; here only truncate decimals in excess
else
            number = mw.ustring.sub(number, 1, mw.ustring.len(number) + prec)
postprec = numsc
        end
end
 
        -- Append the localized base-10 exponent without grouping separators (there's no reliable way to detect a localized leading symbol 'E')
-- separator
        if exponent ~= '' then
if sep ~= "" and formatA ~= "true" then
            number = number .. 'E' .. language:formatNum(tonumber(exponent),{noCommafy=true})
local replace = mw.ustring.gsub( "", "%%", "%%%%" )
        end
local separator = mw.ustring.sub(mw.getLanguage(lang):formatNum(tonumber("10000")), 3, 3)
    else -- not localized, ASCII only
if tostring(mw.ustring.find(separator, "%s")) == "1" then
        -- Postprocessing the precision
pattern = mw.ustring.format(separator, "%s")
        if prec > 0 then
elseif tostring(mw.ustring.find(separator, "%p")) == "1" then
            number = number .. dot .. mw.string.rep('0', prec)
pattern = mw.ustring.gsub(separator, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1")
        elseif prec < 0 then
else
            -- TODO: rounding of last decimal; here only truncate decimals in excess
pattern = ""
            number = mw.string.sub(number, 1, mw.string.len(number) + prec)
end
        end
return tostring(mw.ustring.gsub( postprec, pattern, replace ))
 
else
        -- Append the base-10 exponent
return postprec
        if exponent ~= '' then
end
            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
end


return p
return p

Latest revision as of 10:30, 28 March 2024

Module documentation[ create · purge ]
This documentation is transcluded from Module:Formatnum/doc.
-- This module is intended to replace the functionality of Template:Formatnum and related templates.
local p = {}

function p.main(frame)
    local args = frame:getParent().args
    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 == "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
    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 = mw.ustring.sub (mw.language.new(lang):formatNum(0.1), 2, 2) -- 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
Cookies help us deliver our services. By using our services, you agree to our use of cookies.