ਮੌਡਿਊਲ:Currency
This code is invoked from
See the template code for a description of the parameters. Other modules may use this code. The entry point for other modules is The data file Module:Currency/Presentation holds required currency presentation characteristics.
require('strict')
local p = {}
local lang = mw.language.getContentLanguage(); -- language object for this wiki
local presentation ={}; -- table of tables that contain currency presentation data
local properties;
--[[--------------------------< I S _ S E T >------------------------------------------------------------------
Whether variable is set or not. A variable is set when it is not nil and not empty.
]]
local function is_set( var )
return not (var == nil or var == '');
end
--[[--------------------------< M A K E _ S H O R T _ F O R M _ N A M E >-------------------------------------
Assembles value and symbol according to the order specified in the properties table for this currency code
]]
local function make_short_form_name (amount, code, linked, passthrough)
local symbol;
local position = properties[code].position;
if linked then
symbol = string.format ('[[%s|%s]]', properties[code].page, properties[code].symbol); -- make wikilink of page and symbol
else
symbol = properties[code].symbol;
end
if not passthrough then
amount = lang:formatNum (tonumber(amount)); -- add appropriate comma separators
end
amount = amount:gsub ('^%-', '−'); -- replace the hyphen with unicode minus
if 'b' == position then -- choose appropriate format: unspaced before the amount
return string.format ('%s%s', symbol, amount);
elseif 'bs' == position then -- spaced before the amount
return string.format ('%s %s', symbol, amount);
elseif 'a' == position then -- unspaced after the amount
return string.format ('%s%s', amount, symbol);
elseif 'as' == position then -- spaced after the amount
return string.format ('%s %s', amount, symbol);
elseif 'd' == position then -- special case that replaces the decimal separator with symbol (Cifrão for CVE is the only extant case)
if passthrough then
return string.format('%s%s', symbol, amount)
end
local digits, decimals; -- this code may not work for other currencies or on other language wikis
if amount:match ('[%d,]+%.%d+') then -- with decimal separator and decimals
digits, decimals = amount:match ('([%d,]+)%.(%d+)')
amount = string.format ('%s%s%s', digits, symbol, decimals); -- insert symbol
elseif amount:match ('[%d,]+%.?$') then -- with or without decimal separator
digits = amount:match ('([%d,]+)%.?$')
amount = string.format ('%s%s00', digits, symbol); -- add symbol and 00 ($00)
end
amount = amount:gsub (',', '%.'); -- replace grouping character with period
return amount;
end
return amount .. ' <span style="font-size:inherit" class="error">{{currency}} – definition missing position ([[Template:Currency/doc#Error_messages|help]])</span>'; -- position not defined
end
--[[--------------------------< M A K E _ N A M E >----------------------------------------------------------
Make a wikilink from the currency's article title and its plural (if provided). If linked is false, returns only
the article title (unlinked)
]]
local function make_name (linked, page, plural)
if not linked then
if not is_set (plural) then
return page; -- just the page
elseif 's' == plural then -- if the simple plural form
return string.format ('%ss', page); -- append an 's'
else
return plural; -- must be the complex plural form (pounds sterling v. dollars)
end
else
if not is_set (plural) then
return string.format ('[[%s]]', page);
elseif 's' == plural then -- if the simple plural form
return string.format ('[[%s]]s', page);
else
return string.format ('[[%s|%s]]', page, plural); -- must be the complex plural form (pounds sterling v. dollars)
end
end
end
--[[--------------------------< M A K E _ L O N G _ F O R M _ N A M E >---------------------------------------
assembles a long-form currency name from amount and name from the properties tables; plural for all values not equal to 1
]]
local function make_long_form_name (amount, code, linked, passthrough)
local name, formatted;
if not is_set (properties[code].page) then
return '<span style="font-size:inherit" class="error">{{currency}} – definition missing page ([[Template:Currency/doc#Error_messages|help]])</span>';
end
if not passthrough then
amount = tonumber (amount); -- make sure it's a number
end
if 1 == amount then
name = make_name (linked, properties[code].page); -- the singular form
elseif is_set (properties[code].plural) then -- plural and there is a plural form
name = make_name (linked, properties[code].page, properties[code].plural);
else
name = make_name (linked, properties[code].page); -- plural but no separate plural form so use the singular form
end
if not passthrough then
formatted = lang:formatNum (amount)
else
formatted = amount
end
return string.format ('%s %s', formatted, name); -- put it all together
end
--[[--------------------------< R E N D E R _ C U R R E N C Y >------------------------------------------------
Renders currency amount with symbol or long-form name.
Also, entry point for other modules. Assumes that parameters have been vetted; amount is a number, code is upper
case string, long_form is boolean; all are required.
]]
local function render_currency (amount, code, long_form, linked, fmt, passthrough)
local name;
local result;
presentation = mw.loadData ('Module:Currency/Presentation'); -- get presentation data
if presentation.currency_properties[code] then -- if code is an iso 4217 code
properties = presentation.currency_properties;
elseif presentation.code_translation[code] then -- not iso 4217 but can be translated
code = presentation.code_translation[code]; -- then translate
properties = presentation.currency_properties;
elseif presentation.non_standard_properties[code] then -- last chance, is it a non-standard code?
properties = presentation.non_standard_properties;
else
return '<span style="font-size:inherit" class="error">{{currency}} – invalid code ([[Template:Currency/doc#Error_messages|help]])</span>';
end
if long_form then
result = make_long_form_name (amount, code, linked, passthrough); --
else
result = make_short_form_name (amount, code, linked, passthrough);
end
if 'none' == fmt then -- no group separation
result = result:gsub ('(%d%d?%d?),', '%1'); -- strip comma separators
elseif 'gaps' == fmt then -- use narrow gaps
result = result:gsub ('(%d%d?%d?),', '<span style="margin-right:.25em;">%1</span>'); -- replace comma seperators
elseif fmt and 'commas' ~= fmt then -- if not commas (the default) then error message
return '<span style="font-size:inherit" class="error">{{currency}} – invalid format ([[Template:Currency/doc#Error_messages|help]])</span>';
end
return result; -- done
end
--[[--------------------------< P A R S E _ F O R M A T T E D _ N U M B E R >----------------------------------
replacement for lang:parseFormattedNumber() which doesn't work; all it does is strip commas.
This function returns a string where all comma separators have been removed from the source string. If the source
is malformed: has characters other than digits, commas, and decimal points; has too many decimal points; has commas
in in appropriate locations; then the function returns nil.
]]
local function parse_formatted_number (amount)
local count;
local parts = {};
local digits = {};
local decimals;
local sign = '';
local _;
if amount:find ('[^%-−%d%.,]') then -- anything but sign, digits, decimal points, or commas
return nil;
end
amount = amount:gsub ('−', '-'); -- replace unicode minus with hyphen
_, count = amount:gsub('%.', '') -- count the number of decimal point characters
if 1 < count then
return nil; -- too many dots
end
_, count = amount:gsub(',', '') -- count the number of grouping characters
if 0 == count then
return amount; -- no comma separators so we're done
end;
if amount:match ('[%-][%d%.,]+') then -- if the amount is negative
sign, amount = amount:match ('([%-])([%d%.,]+)'); -- strip off and save the sign
end
parts = mw.text.split (amount, '.', true); -- split amount into digits and decimals
decimals = table.remove (parts, 2) or ''; -- if there was a decimal portion, remove from the table and save it
digits = mw.text.split (parts[1], ',') -- split amount into groups
for i, v in ipairs (digits) do -- loop through the groups
if 1 == i then -- left-most digit group
if (3 < v:len() or not is_set (v)) then -- first digit group: 1, 2, 3 digits; can't be empty string (first char was a comma)
return nil;
end
else
if v and 3 ~= v:len() then -- all other groups must be three digits long
return nil;
end
end
end
return sign .. table.concat (digits) .. '.' .. decimals; -- reassemble without commas and return
end
--[[--------------------------< C O N V E R T _ S T R I N G _ T O _ N U M E R I C >------------------------------------------------
Converts quantified number/string combinations to a number e.g. 1 thousand to 1000.
]]
local function convert_string_to_numeric (amount)
local quantifiers = {['thousand'] = 1000, ['million'] = 1000000, ['m'] = 1000000, ['billion'] = 1000000000, ['b'] = 1000000000, ['trillion'] = 1000000000000};
local n, q = amount:match ('([%-−]?[%d%.,]+)%s*(%a+)$'); -- see if there is a quantifier following a number; zero or more space characters
if nil == n then
n, q = amount:match ('([%-−]?[%d%.,]+) (%a+)$') -- see if there is a quantifier following a number; nbsp html entity ({{format price}} output
end
if nil == n then return amount end; -- if not <number><space><quantifier> return amount unmolested
n = n:gsub (',', ''); -- strip comma separators if present
q = q:lower(); -- set the quantifier to lower case
if nil == quantifiers[q] then return amount end; -- if not a recognized quantifier
return tostring (n * quantifiers[q]); -- return a string, not a number
end
--[[--------------------------< C U R R E N C Y >--------------------------------------------------------------
Template:Currency entry point. The template takes three parameters:
positional (1st), |amount=, |Amount= : digits and decimal points only
positional (2nd), |type=, |Type= : code that identifies the currency
|first= : uses currency name instead of symbol
]]
local function currency (frame)
local args = require('Module:Arguments').getArgs (frame);
local amount, code;
local long_form = false;
local linked = true;
local passthrough = false;
if not is_set (args[1]) then
return '<span style="font-size:inherit" class="error">{{currency}} – invalid amount ([[Template:Currency/doc#Error_messages|help]])</span>';
end
-- amount = lang:parseFormattedNumber(args[1]); -- if args[1] can't be converted to a number then error (this just strips grouping characters)
-- if args[1]:find ('[^%d%.]') or not amount then -- non-digit characters or more than one decimal point (because lag:parse... is broken)
-- return '<span style="font-size:inherit" class="error">{{currency}} – invalid amount ([[Template:Currency/doc#Error_messages|help]])</span>';
-- end
-- This allows us to use {{currency}} while actually following [[MOS:CURRENCY]] as regards "billion", "million", "M", "bn", etc.
if not (args['passthrough'] == 'yes') then -- just pass whatever string is given through.
amount = convert_string_to_numeric (args[1]);
amount = parse_formatted_number(amount); -- if args[1] can't be converted to a number then error
if not amount then
return '<span style="font-size:inherit" class="error">{{currency}} – invalid amount ([[Template:Currency/doc#Error_messages|help]])</span>';
end
else
amount = args[1]
end
if not is_set(args[2]) then -- if not provided
code = 'USD'; -- default to USD
else
code = args[2]:upper(); -- always upper case; used as index into data tables which all use upper case
end
if args[3] then -- this is the |first= parameter TODO: make this value meaningful? y, yes, true?
long_form = true;
end
if 'no' == args[4] then -- this is the |linked= parameter; defaults to 'yes'; any value but 'no' means yes
linked = false;
end
return render_currency (amount, code, long_form, linked, args['fmt'], (args['passthrough'] == 'yes'))
end
return {
currency = currency, -- template entry point
_render_currency = render_currency, -- other modules entry point
}
|
Index:
pl ar de en es fr it arz nl ja pt ceb sv uk vi war zh ru af ast az bg zh-min-nan bn be ca cs cy da et el eo eu fa gl ko hi hr id he ka la lv lt hu mk ms min no nn ce uz kk ro simple sk sl sr sh fi ta tt th tg azb tr ur zh-yue hy my ace als am an hyw ban bjn map-bms ba be-tarask bcl bpy bar bs br cv nv eml hif fo fy ga gd gu hak ha hsb io ig ilo ia ie os is jv kn ht ku ckb ky mrj lb lij li lmo mai mg ml zh-classical mr xmf mzn cdo mn nap new ne frr oc mhr or as pa pnb ps pms nds crh qu sa sah sco sq scn si sd szl su sw tl shn te bug vec vo wa wuu yi yo diq bat-smg zu lad kbd ang smn ab roa-rup frp arc gn av ay bh bi bo bxr cbk-zam co za dag ary se pdc dv dsb myv ext fur gv gag inh ki glk gan guw xal haw rw kbp pam csb kw km kv koi kg gom ks gcr lo lbe ltg lez nia ln jbo lg mt mi tw mwl mdf mnw nqo fj nah na nds-nl nrm nov om pi pag pap pfl pcd krc kaa ksh rm rue sm sat sc trv stq nso sn cu so srn kab roa-tara tet tpi to chr tum tk tyv udm ug vep fiu-vro vls wo xh zea ty ak bm ch ny ee ff got iu ik kl mad cr pih ami pwn pnt dz rmy rn sg st tn ss ti din chy ts kcg ve
Portal di Ensiklopedia Dunia