Jump to content
 







Main menu
   


Navigation  



Main page
Contents
Current events
Random article
About Wikipedia
Contact us
Donate
 




Contribute  



Help
Learn to edit
Community portal
Recent changes
Upload file
 








Search  

































Create account

Log in
 









Create account
 Log in
 




Pages for logged out editors learn more  



Contributions
Talk
 

















Module:Currency






العربية


فارسی
Jawa

Bahasa Melayu
Монгол


پښتو
Português
Scots
Simple English
Slovenščina
Српски / srpski
Srpskohrvatski / српскохрватски
 

Українська

 

Edit links
 









Module
Talk
 

















Read
View source
View history
 








Tools
   


Actions  



Read
View source
View history
 




General  



What links here
Related changes
Upload file
Special pages
Permanent link
Page information
Get shortened URL
Download QR code
Wikidata item
 




Print/export  



Download as PDF
Printable version
 
















Appearance
   

 





Permanently protected module

From Wikipedia, the free encyclopedia
 


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')

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&nbsp;%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&nbsp;%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%.,]+)&nbsp;(%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
 }

Retrieved from "https://en.wikipedia.org/w/index.php?title=Module:Currency&oldid=1117469206"

Hidden category: 
Wikipedia extended-confirmed-protected modules
 



This page was last edited on 21 October 2022, at 22:00 (UTC).

Text is available under the Creative Commons Attribution-ShareAlike License 4.0; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy. Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-profit organization.



Privacy policy

About Wikipedia

Disclaimers

Contact Wikipedia

Code of Conduct

Developers

Statistics

Cookie statement

Mobile view



Wikimedia Foundation
Powered by MediaWiki