Module:Formatnum/sandbox
Appearance
![]() | This is the module sandbox page for Module:Formatnum (diff). See also the companion subpage for test cases (run). |
This module provides a number formatting function. This function can be used from #invoke or from other Lua modules.
This module is used by Module:Complex date
Use from other Lua modules
To use the module from normal wiki pages, no special preparation is needed. If you are using the module from another Lua module, first you need to load it, like this:
local mf = require('Module:Formatnum')
(The mf
variable stands for Module Formatnum; you can choose something more descriptive if you prefer.)
Most functions in the module have a version for Lua and a version for #invoke. It is possible to use the #invoke functions from other Lua modules, but using the Lua functions has the advantage that you do not need to access a Lua frame object. Lua functions are preceded by _
, whereas #invoke functions are not.
main
{{#invoke:Formatnum|main|x|lang=|prec=|sep=}}
mf.formatNum(x, lang, prec, sep)
See also
-- 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 err(msg)
-- Generates wikitext error messages.
return mw.ustring.format('<strong class="error">Formatting error: %s</strong>', msg)
end
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
local function _round(value, precision)
local rescale = math.pow(10, precision or 0);
return math.floor(value * rescale + 0.5) / rescale;
end
--[[
------------------------------------------------------------------------------------
-- isPositiveInteger
--
-- This function returns true if the given value is a positive integer, and false
-- if not. Although it doesn't operate on tables, it is included here as it is
-- useful for determining whether a given table key is in the array part or the
-- hash part of a table.
------------------------------------------------------------------------------------
--]]
function isPositiveInteger(v)
return type(v) == 'number' and v >= 1 and math.floor(v) == v and v < math.huge
end
--[[
------------------------------------------------------------------------------------
-- reverseNumKeys
--
-- This takes a table and returns an array containing the numbers of any numerical
-- keys that have non-nil values, sorted in reverse numerical order.
------------------------------------------------------------------------------------
--]]
local function reverseNumKeys(t)
local nums = {}
for k, v in pairs(t) do
if isPositiveInteger(k) then
nums[#nums + 1] = k
end
end
table.sort(nums, function(a, b) return a > b end)
return nums
end
--[[
------------------------------------------------------------------------------------
-- reverseSparseIpairs
--
-- This is a reverse iterator for sparse arrays. It can be used like a resersed ipairs, but can
-- handle nil values.
------------------------------------------------------------------------------------
--]]
local function reverseSparseIpairs(t)
local nums = reverseNumKeys(t)
local i = 0
local lim = #nums
return function ()
i = i + 1
if i <= lim then
local key = nums[i]
return key, t[key]
else
return nil, nil
end
end
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
--[[
wordify
Usage:
{{#invoke:Formatnum | wordify | x | y | round= | precision= }}
--]]
local usa = {
[6] = 'million',
[9] = 'billion',
[12] = 'trillion',
[15] = 'quadrillion',
[18] = 'quintillion',
[21] = 'sextillion',
[24] = 'septillion',
[27] = 'octillion',
[30] = 'nonillion',
[33] = 'decillion',
[36] = 'undecillion',
[39] = 'duodecillion',
[42] = 'tredecillion',
[45] = 'quattuordecillion',
[48] = 'quindecillion',
[51] = 'sexdecillion',
[54] = 'septendecillion',
[57] = 'octodecillion',
[60] = 'novemdecillion',
[63] = 'vigintillion',
[100] = 'googol',
[303] = 'centillion'
}
local ind = {
[5] = 'lakh',
[7] = 'crore',
[12] = 'lakh crore',
[14] = 'crore crore'
}
local declension = {
['ca'] = { '', function (u)
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "d" then return u .. "s" else return mw.ustring.sub(u, 1, -2) .. "ons" end
end },
['da'] = { '', 'er' },
['de'] = { '', function (u)
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "e" then return u .. "n" else return u .. "en" end
end },
['eo'] = { '', 'j' },
['es'] = { function (arr, i, lang)
if i < 15 then
return buildOne(arr, i, lang)
end
local j = math.floor(i / 6)
if (j*6)+3 == i then
return "mil " .. unit(arr, i-3, lang, 1000), true
else
return buildOne(arr, i, lang)
end
end,
function (u)
if mw.ustring.sub(u, 1, 4) == "mil " then
return u
else
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "o" then return u .. "s" else return mw.ustring.sub(u, 1, -3) .. "ones" end
end
end },
['fr'] = { '', 's' },
['it'] = { '', function (u)
return mw.ustring.sub(u, 1, -2) .. "i"
end },
['la'] = { '', function (u)
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "o" then return u .. "nibus" else return mw.ustring.sub(u, 1, -3) .. "a" end
end },
['no'] = { '', 'er' },
['pl'] = { '', 'y', [5] = 'ów', ["fraction"] = 'a' },
['pt'] = { function (arr, i, lang)
if i < 9 then
return buildOne(arr, i, lang)
end
local j = math.floor(i / 6)
if (j*6)+3 == i then
return "mil " .. unit(arr, i-3, lang, 1000), true
else
return buildOne(arr, i, lang)
end
end,
function (u)
if mw.ustring.sub(u, 1, 4) == "mil " then
return u
else
return mw.ustring.sub(u, 1, -3) .. "ões"
end
end },
['sk'] = { '', function (u)
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "n" then return u .. 'y' else return mw.ustring.sub(u, 1, -2) .. "y" end
end,
[5] = function (u)
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "n" then return u .. 'ov' else return mw.ustring.sub(u, 1, -5) .. "árd" end
end,
["fraction"] = function (u)
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "n" then return u .. 'a' else return mw.ustring.sub(u, 1, -5) .. "árd" end
end
},
['sl'] = { '', function (u)
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "a" then return mw.ustring.sub(u, 1, -2) .. 'i' else return u .. "a" end
end,
function (u)
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "a" then return mw.ustring.sub(u, 1, -2) .. 'e' else return u .. "e" end
end,
[5] = function (u)
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "a" then return mw.ustring.sub(u, 1, -2) else return u .. "ov" end
end,
["fraction"] = function (u)
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "a" then return mw.ustring.sub(u, 1, -2) .. 'e' else return u .. "a" end
end
},
['sv'] = { '', 'er' }
}
local latin = {
['language'] = {
[''] = true,
['ca'] = true,
['da'] = true,
['de'] = true,
['en'] = true,
['eo'] = true,
['es'] = true,
['fr'] = true,
['it'] = true,
['la'] = true,
['nl'] = true,
['no'] = true,
['pl'] = true,
['pt'] = true,
['sk'] = true,
['sl'] = true,
['sv'] = true
},
['exception'] = {
[6] = {
['pt'] = { 'milhão' }
},
[36] = {
['it'] = 'none'
},
[39] = {
['it'] = 'none'
},
[42] = {
['it'] = 'none'
},
[45] = {
['it'] = 'none'
},
[48] = {
['it'] = 'none'
},
[51] = {
['it'] = 'none',
},
[54] = {
['it'] = 'none'
},
[57] = {
['it'] = 'none'
},
[60] = {},
[63] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[66] = {
['de'] = 'none',
['eo'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[69] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[72] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[75] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[78] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[81] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[84] = {
['de'] = 'none',
['eo'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[87] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[90] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[93] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[96] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[99] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[102] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[105] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[108] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[111] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[114] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[117] = {
['de'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[120] = {
['de'] = 'none',
['eo'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
[123] = {
['de'] = 'none',
['eo'] = 'none',
['es'] = 'none',
['it'] = 'none',
['pt'] = 'none'
},
},
['base'] = {
[''] = { 'lli' },
['ca'] = { 'li' },
['da'] = { 'lli' },
['de'] = { 'lli' },
['en'] = { 'lli' },
['eo'] = { 'li' },
['es'] = { 'll' },
['fr'] = { 'lli' },
['it'] = { 'li' },
['la'] = { 'lli' },
['nl'] = { 'lj' },
['no'] = { 'lli' },
['pl'] = { 'li' },
['pt'] = { 'li' },
['sk'] = { 'li' },
['sl'] = { 'lij' },
['sv'] = { 'lj' }
},
['suffix'] = {
[''] = { 'on', 'ard' },
['ca'] = { 'ó', 'ard' },
['da'] = { 'on', 'ard' },
['de'] = { 'on', 'arde' },
['en'] = { 'on', 'ard' },
['eo'] = { 'ono', 'ardo' },
['es'] = { 'ón', 'ardo' },
['fr'] = { 'on', 'ard' },
['it'] = { 'one', 'ardo' },
['la'] = { 'o', 'ardum' },
['nl'] = { 'oen', 'ard' },
['no'] = { 'on', 'ard' },
['pl'] = { 'on', 'ard' },
['pt'] = { 'ão' },
['sk'] = { 'ón', 'arda' },
['sl'] = { 'on', 'arda' },
['sv'] = { 'on', 'ard' }
},
['capitalize'] = {
['de'] = true
},
['prefix'] = { 'mi', 'bi', 'tri', 'quadri', 'quinti', 'sexti', 'septi', 'octi', 'noni', 'deci',
[16] = 'sedeci',
[20] = 'viginti',
[30] = 'triginti',
[40] = 'quadraginti',
[50] = 'quinquaginti',
[60] = 'sexaginti',
[70] = 'septuaginti',
[80] = 'octoginti',
[90] = 'nonaginti',
[100] = 'centi'
},
['unit_prefix'] = { 'un', 'duo', 'tre', 'quattuor', 'quin', 'sex', 'septen', 'octo', 'novem' },
['prefix_exception'] = {
[1] = {},
[2] = {
['eo'] = { 'dui' }
},
[3] = {
['pl'] = { 'try' }
},
[4] = {
['da'] = { 'kvadri' },
['eo'] = { 'kvari' },
['es'] = { 'cuatri' },
['no'] = { 'kvadri' },
['pl'] = { 'kwadry' },
['sk'] = { 'kvadri' },
['sl'] = { 'kvadri' },
['sv'] = { 'kvadri' }
},
[5] = {
['da'] = { 'kvinti' },
['eo'] = { 'kvini' },
['no'] = { 'kvinti' },
['pl'] = { 'kwinty' },
['sk'] = { 'kvinti' },
['sl'] = { 'kvinti' },
['sv'] = { 'kvinti' }
},
[6] = {
['da'] = { 'seksti' },
['eo'] = { 'sesi' },
['no'] = { 'seksti' },
['pl'] = { 'seksty' },
['sl'] = { 'seksti' }
},
[7] = {
['eo'] = { 'sepi' },
['pl'] = { 'septy' },
},
[8] = {
['da'] = { 'okti' },
['de'] = { 'Okti' },
['eo'] = { 'oki' },
['no'] = { 'okti' },
['pl'] = { 'okty' },
['sk'] = { 'okti' },
['sl'] = { 'okti' },
['sv'] = { 'okti' }
},
[9] = {
['eo'] = { 'naŭi' }
},
[10] = {
['de'] = { 'Dezi' },
['eo'] = { 'deki' },
['no'] = { 'desi' },
['pl'] = { 'decy' }
},
[11] = {
},
[12] = {
},
[13] = {
},
[14] = {
},
[15] = {
},
[16] = {
},
[17] = {
},
[18] = {
},
[19] = {
},
[20] = {
}
},
['unit_prefix_exception'] = {
[1] = {},
[2] = {
},
[3] = {
},
[4] = {
['eo'] = { 'kvatuor' },
['es'] = { 'cuatro' }
},
[5] = {
['eo'] = { 'kvin' }
},
[6] = {
['eo'] = { 'seks' }
},
[7] = {
},
[8] = {
['eo'] = { 'okto' }
},
[9] = {
['es'] = { 'noven' }
}
}
}
local function makeprefix(arr, j, lang)
local entry = arr['prefix_exception'][j][(lang or "")]
local p
if entry then
p = entry[1]
else
p = arr['prefix'][j]
if not p then
if j < 11 then
return nil
elseif p < 100 then
local k = math.floor(j / 10)
local d = k * 10
local l = j - d
local unitentry = arr['unit_prefix_exception'][l][(lang or "")]
local u
if unitentry then
u = unitentry[1]
else
u = arr['unit_prefix'][l]
end
local decentry = arr['prefix_exception'][d][(lang or "")]
local x
if decentry then
x = deceentry[1]
else
x = arr['prefix'][d]
end
p = u .. x
else
return nil
end
end
end
if arr['capitalize'][(lang or "")] then
return mw.ustring.upper(mw.ustring.sub(p, 1, 1)) .. mw.ustring.sub(p, 2)
else
return p
end
end
local function buildOne(arr, i, lang)
local j = math.floor(i / 6)
if j < 1 then
return nil
else
local pref = makeprefix(arr, j, lang)
local suf = (j * 6) == i and arr['suffix'][(lang or "")][1] or arr['suffix'][(lang or "")][2]
return pref .. arr['base'][(lang or "")][1] .. suf
end
end
local function makeOne(arr, i, lang)
local top = arr['exception'][i]
local entry = top and top[(lang or "")]
local one = nil
local simplify = nil
if entry then
one, simplify = entry[1], entry['simplify']
end
if one then
return one, simplify
else
if declension[lang] and declension[lang][1] then
local d = declension[lang][1]
if type(d) == 'function' then
return d(arr, i, lang)
end
end
return buildOne(arr, i, lang)
end
end
local function unit(arr, i, lang, r)
local one, simplify = makeOne(arr, i, lang)
local top = arr['exception'][i]
local entry = top and top[(lang or "")]
if r == 1 then
return one, simplify
elseif r == 2 then
if entry and entry[2] then
return entry and entry[2]
elseif declension[lang] and declension[lang][2] then
local d = declension[lang][2]
if type(d) == 'function' then
return d(one)
else
return one .. d
end
else
return one
end
elseif r == 3 or r == 4 then
if entry and entry[3] then
return entry and entry[3]
elseif declension[lang] and declension[lang][3] then
local d = declension[lang][3]
if type(d) == 'function' then
return d(one)
else
return one .. d
end
elseif entry and entry[2] then
return entry and entry[2]
elseif declension[lang] and declension[lang][2] then
local d = declension[lang][2]
if type(d) == 'function' then
return d(one)
else
return one .. d
end
else
return one
end
elseif r == _round(r, 0) then
if entry and entry[5] then
return entry and entry[5]
elseif declension[lang] and declension[lang][5] then
local d = declension[lang][5]
if type(d) == 'function' then
return d(one)
else
return one .. d
end
elseif entry and entry[3] then
return entry and entry[3]
elseif declension[lang] and declension[lang][3] then
local d = declension[lang][3]
if type(d) == 'function' then
return d(one)
else
return one .. d
end
elseif entry and entry[2] then
return entry and entry[2]
elseif declension[lang] and declension[lang][2] then
local d = declension[lang][2]
if type(d) == 'function' then
return d(one)
else
return one .. d
end
else
return one
end
else
if entry and entry["fraction"] then
return entry and entry["fraction"]
elseif declension[lang] and declension[lang]["fraction"] then
local d = declension[lang]["fraction"]
if type(d) == 'function' then
return d(one)
else
return one .. d
end
elseif entry and entry[5] then
return entry and entry[5]
elseif declension[lang] and declension[lang][5] then
local d = declension[lang][5]
if type(d) == 'function' then
return d(one)
else
return one .. d
end
elseif entry and entry[3] then
return entry and entry[3]
elseif declension[lang] and declension[lang][3] then
local d = declension[lang][3]
if type(d) == 'function' then
return d(one)
else
return one .. d
end
elseif entry and entry[2] then
return (r < 2 and one or entry and entry[2])
elseif declension[lang] and declension[lang][2] then
local d = declension[lang][2]
if type(d) == 'function' then
return (r < 2 and one or d(one))
else
return (r < 2 and one or (one .. d))
end
else
return one
end
end
end
local function linkend(u)
return "|" .. u .. "]]"
end
local function unitlink(lk, i, u, lang)
if lk then
if lang == "ca" then
return "[[ca:" .. "Escales curta i llarga" .. linkend(u)
elseif lang == "da" then
return "[[da:" .. "Store tal" .. linkend(u)
elseif lang == "de" then
return "[[de:" .. "Zahlennamen" .. linkend(u)
elseif lang == "eo" then
return "[[eo:" .. "Vortoj por grandegaj nombroj" .. linkend(u)
elseif lang == "fr" then
return "[[fr:" .. (i > 36 and "Noms des grands nombres" or ("Ordres de grandeur de nombres#10" .. i)) .. linkend(u)
elseif lang == "it" then
return "[[it:" .. ("Ordini di grandezza (numeri)#10" .. i) .. linkend(u)
elseif lang == "la" then
return "[[la:" .. "Nomina permagnorum numerorum" .. linkend(u)
elseif lang == "nl" then
return "[[nl:" .. "Lijst van machten van tien" .. linkend(u)
elseif lang == "no" then
return "[[no:" .. "Navn på store tall" .. linkend(u)
elseif lang == "pl" then
return "[[pl:" .. "Liczebniki główne potęg tysiąca" .. linkend(u)
elseif lang == "sk" then
return "[[sk:" .. "Veľké čísla" .. linkend(u)
elseif lang == "sl" then
return "[[sl:" .. "Imena velikih števil" .. linkend(u)
elseif lang == "sv" then
return "[[sv:" .. "Namn på stora tal" .. linkend(u)
else
return "[[en:" .. (i > 39 and "Names of large numbers" or ("Orders of magnitude (numbers)#10" .. i)) .. linkend(u)
end
else
return u
end
end
function p.wordify(frame)
local args = getArgs(frame)
local x = args[1]
local numsys = args.numsys
local prec = args.prec
local lk = args.lk
local lang = args.lang
local simplify = args.simplify
return p._wordify(x, numsys, prec, (lk == "on" and true), lang, (simplify == "yes" and true))
end
function p._wordify(x, numsys, prec, lk, lang, simplify)
if tonumber(x) then
if numsys == nil or numsys == "" or numsys:lower() == "usa" then
for i, v in reverseSparseIpairs(usa) do
local y = x / math.pow(10,i)
local r = _round(y, prec)
if r >= 1 then
if r == 1 and simplify then
return unitlink(lk, i, v, (lang or "en"))
else
return p.formatNum(r, (lang or "en"), prec) .. " " .. unitlink(lk, i, v, (lang or "en"))
end
end
end
return p.formatNum(_round(x, prec), (lang or "en"), prec)
elseif numsys:lower() == "fra" then
if latin['language'][(lang or "")] then
for i = 306, 6, -3 do
local entry = latin['exception'][i]
if not entry or entry[(lang or "")] ~= "none" then
local y = x / math.pow(10,i)
local r = _round(y, prec)
if r >= 1 then
local u, simp = unit(latin, i, lang, r)
if r == 1 and (simplify or simp) then
return unitlink(lk, i, u, (lang or ""))
else
return p.formatNum(r, (lang or "en"), prec) .. " " .. unitlink(lk, i, u, (lang or "en"))
end
end
end
end
end
return p.formatNum(_round(x, prec), (lang or "en"), prec)
elseif numsys:lower() == "ind" then
local y = x / 1E14
local r = _round(y, prec)
if r >= 1 then
if r == 1 and simplify then
return (lk and "[[crore]] crore" or ind[14])
else
return p.formatNum(r, (lang or "en"), prec) .. " " .. (lk and "[[crore]] crore" or ind[14])
end
else
local y = x / 1E12
local r = _round(y, prec)
if r >= 1 then
if r == 1 and simplify then
return (lk and "[[lakh]] [[crore]]" or ind[12])
else
return p.formatNum(r, (lang or "en"), prec) .. " " .. (lk and "[[lakh]] [[crore]]" or ind[12])
end
else
local y = x / 1E7
local r = _round(y, prec)
if r >= 1 then
local v = ind[7]
if r == 1 and simplify then
return (lk and "[[" .. v .. "]]" or v)
else
return p.formatNum(r, (lang or "en"), prec) .. " " .. (lk and "[[" .. v .. "]]" or v)
end
else
local y = x / 1E5
local r = _round(y, prec)
if r >= 1 then
local v = ind[5]
if r == 1 and simplify then
return (lk and "[[" .. v .. "]]" or v)
else
return p.formatNum(r, (lang or "en"), prec) .. " " .. (lk and "[[" .. v .. "]]" or v)
end
else
return p.formatNum(_round(x, prec), (lang or "en"), prec)
end
end
end
end
else
return err("number system not supported")
end
else
return err("Not a number: " .. x)
end
end
--[[
Helper function that interprets the input numerically. If the
input does not appear to be a number, attempts evaluating it as
a parser functions expression.
]]
function p._cleanNumber(number_string)
if type(number_string) == 'number' then
-- We were passed a number, so we don't need to do any processing.
return number_string, tostring(number_string)
elseif type(number_string) ~= 'string' or not number_string:find('%S') then
-- We were passed a non-string or a blank string, so exit.
return nil, nil;
end
-- Attempt basic conversion
local number = tonumber(number_string)
-- If failed, attempt to evaluate input as an expression
if number == nil then
local success, result = pcall(mw.ext.ParserFunctions.expr, number_string)
if success then
number = tonumber(result)
number_string = tostring(number)
else
number = nil
number_string = nil
end
else
number_string = number_string:match("^%s*(.-)%s*$") -- String is valid but may contain padding, clean it.
number_string = number_string:match("^%+(.*)$") or number_string -- Trim any leading + signs.
if number_string:find('^%-?0[xX]') then
-- Number is using 0xnnn notation to indicate base 16; use the number that Lua detected instead.
number_string = tostring(number)
end
end
return number, number_string
end
return p