VOOZH about

URL: https://en.wikipedia.org/wiki/Module:Currency

⇱ Module:Currency - Wikipedia


Jump to content
From Wikipedia, the free encyclopedia
👁 Image
Module documentation
[view] [edit] [history] [purge]
👁 Warning
This Lua module is used on approximately 5,200 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them.
Related pages

This code is invoked from {{Currency}}. All of the template parameters are passed in the module's frame.

{{#invoke:Currency|currency|<amount>|<code>|<first>|<linked>|<passthrough>}}

See the template code for a description of the parameters.

Other modules may use this code. The entry point for other modules is _render_currency (amount, code, long_form, linked). See the function render_currency() for detail.

The data file Module:Currency/Presentation holds required currency presentation characteristics.

require('strict')
localp={}
locallang=mw.language.getContentLanguage();-- language object for this wiki
localpresentation={};-- table of tables that contain currency presentation data
localproperties;
--[[--------------------------< I S _ S E T >------------------------------------------------------------------
Whether variable is set or not. A variable is set when it is not nil and not empty.
]]
localfunctionis_set(var)
returnnot(var==nilorvar=='');
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
]]
localfunctionmake_short_form_name(amount,code,linked,passthrough)
localsymbol;
localposition=properties[code].position;
iflinkedthen
symbol=string.format('[[%s|%s]]',properties[code].page,properties[code].symbol);-- make wikilink of page and symbol
else
symbol=properties[code].symbol;
end
ifnotpassthroughthen
amount=lang:formatNum(tonumber(amount));-- add appropriate comma separators
end
amount=amount:gsub('^%-','−');-- replace the hyphen with unicode minus
if'b'==positionthen-- choose appropriate format: unspaced before the amount
returnstring.format('%s%s',symbol,amount);
elseif'bs'==positionthen-- spaced before the amount
returnstring.format('%s&nbsp;%s',symbol,amount);
elseif'a'==positionthen-- unspaced after the amount
returnstring.format('%s%s',amount,symbol);
elseif'as'==positionthen-- spaced after the amount
returnstring.format('%s&nbsp;%s',amount,symbol);
elseif'd'==positionthen-- special case that replaces the decimal separator with symbol (Cifrão for CVE is the only extant case)
ifpassthroughthen
returnstring.format('%s%s',symbol,amount)
end
localdigits,decimals;-- this code may not work for other currencies or on other language wikis
ifamount: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
elseifamount: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
returnamount;
end
returnamount..' <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)
]]
localfunctionmake_name(linked,page,plural)
ifnotlinkedthen
ifnotis_set(plural)then
returnpage;-- just the page
elseif's'==pluralthen-- if the simple plural form
returnstring.format('%ss',page);-- append an 's'
else
returnplural;-- must be the complex plural form (pounds sterling v. dollars)
end
else
ifnotis_set(plural)then
returnstring.format('[[%s]]',page);
elseif's'==pluralthen-- if the simple plural form
returnstring.format('[[%s]]s',page);
else
returnstring.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
]]
localfunctionmake_long_form_name(amount,code,linked,passthrough)
localname,formatted;
ifnotis_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
ifnotpassthroughthen
amount=tonumber(amount);-- make sure it's a number
end
if1==amountthen
name=make_name(linked,properties[code].page);-- the singular form
elseifis_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
ifnotpassthroughthen
formatted=lang:formatNum(amount)
else
formatted=amount
end
returnstring.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.
]]
localfunctionrender_currency(amount,code,long_form,linked,fmt,passthrough)
localname;
localresult;
presentation=mw.loadData('Module:Currency/Presentation');-- get presentation data
ifpresentation.currency_properties[code]then-- if code is an iso 4217 code
properties=presentation.currency_properties;
elseifpresentation.code_translation[code]then-- not iso 4217 but can be translated
code=presentation.code_translation[code];-- then translate
properties=presentation.currency_properties;
elseifpresentation.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
iflong_formthen
result=make_long_form_name(amount,code,linked,passthrough);-- 
else
result=make_short_form_name(amount,code,linked,passthrough);
end
if'none'==fmtthen-- no group separation
result=result:gsub('(%d%d?%d?),','%1');-- strip comma separators
elseif'gaps'==fmtthen-- use narrow gaps
result=result:gsub('(%d%d?%d?),','<span style="margin-right:.25em;">%1</span>');-- replace comma seperators
elseiffmtand'commas'~=fmtthen-- 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
returnresult;-- 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.
]]
localfunctionparse_formatted_number(amount)
localcount;
localparts={};
localdigits={};
localdecimals;
localsign='';
local_;
ifamount:find('[^%-−%d%.,]')then-- anything but sign, digits, decimal points, or commas
returnnil;
end
amount=amount:gsub('−','-');-- replace unicode minus with hyphen
_,count=amount:gsub('%.','')-- count the number of decimal point characters 
if1<countthen
returnnil;-- too many dots
end
_,count=amount:gsub(',','')-- count the number of grouping characters 
if0==countthen
returnamount;-- no comma separators so we're done
end;
ifamount: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 
fori,vinipairs(digits)do-- loop through the groups
if1==ithen-- left-most digit group
if(3<v:len()ornotis_set(v))then-- first digit group: 1, 2, 3 digits; can't be empty string (first char was a comma)
returnnil;
end
else
ifvand3~=v:len()then-- all other groups must be three digits long
returnnil;
end
end
end
returnsign..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.
]]
localfunctionconvert_string_to_numeric(amount)
localquantifiers={['thousand']=1000,['million']=1000000,['m']=1000000,['billion']=1000000000,['b']=1000000000,['trillion']=1000000000000};
localn,q=amount:match('([%-−]?[%d%.,]+)%s*(%a+)$');-- see if there is a quantifier following a number; zero or more space characters
ifnil==nthen
n,q=amount:match('([%-−]?[%d%.,]+)&nbsp;(%a+)$')-- see if there is a quantifier following a number; nbsp html entity ({{format price}} output
end
ifnil==nthenreturnamountend;-- 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
ifnil==quantifiers[q]thenreturnamountend;-- if not a recognized quantifier
returntostring(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
]]
localfunctioncurrency(frame)
localargs=require('Module:Arguments').getArgs(frame);
localamount,code;
locallong_form=false;
locallinked=true;
localpassthrough=false;
ifnotis_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.
ifnot(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
ifnotamountthen
return'<span style="font-size:inherit" class="error">{{currency}} – invalid amount ([[Template:Currency/doc#Error_messages|help]])</span>';
end
else
amount=args[1]
end
ifnotis_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
ifargs[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
returnrender_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
}