Module:Ordinal
Appearance
--[[
This template will add the appropriate ordinal suffix to a given integer.
Please do not modify this code without applying the changes first at Module:Ordinal/sandbox and testing
at Module:Ordinal/sandbox/testcases and Module talk:Ordinal/sandbox/testcases.
Authors and maintainers:
* User:RP88
]]
local p = {}
-- =======================================
-- === Dependencies ======================
-- =======================================
local i18n = require('Module:I18n/ordinal') -- get localized translations of ordinals
local fallback = require('Module:Fallback') -- get fallback functions
local yesno = require('Module:Yesno') -- boolean value interpretation
local formatnum = require('Module:Formatnum') -- number formatting
local roman = require('Module:Roman') -- roman numeral conversion (primarily for French)
--[[
Ordinal
This function converts an integer value into a numeral followed by ordinal indicator. The output string might
contain HTML tags unless you set nosup=y.
Usage:
{{#invoke:Ordinal|Ordinal|1=|style=|gender=|lang=|nosup=|debug=
Parameters
1: Positive integer number.
style: Presentation style. Different options for different languages. In English there is "style=d" adding -d suffixes to all numbers.
gender: Gender is used in French and Polish language versions. Genders: m for male, f for female and n for neuter.
lang: language
nosup: Set nosup=y to display the ordinals without superscript.
debug: Set debug=y to output error messages.
Error Handling:
Unless debug=y, any error results in parameter 1 being echoed to the output. This reproduces the behavior of the original Ordinal template.
]]
function p.Ordinal( frame )
-- if no argument provided than check parent template/module args
local args = frame.args
if args[1]==nil then
args = frame:getParent().args
end
-- if we don't have a specified language, attempt to use the user's language
local lang = args.lang
if not lang or lang == '' or not mw.language.isValidCode( lang ) then
lang = frame:preprocess('{{int:lang}}')
end
-- set debug, defaulting to false
local debug = yesno(args["debug"], false)
local input = args[1]
local output = input
if input then
local value = tonumber(input)
if value and (value > 0) then
output = p._Ordinal(
value, -- positive integer number
args["style"] or '', -- allows to set presentation style
args["gender"] or '', -- allows to specify gender (m, f, or n)
args["lang"], -- language
yesno(args["nosup"], false) -- set nosup to "y" to suppress superscripts
)
else
if debug then
output = p._error( "not a number", value )
end
end
else
if debug then
output = p._error( "not a number", '' )
end
end
return output
end
--[[
This function will add the appropriate ordinal suffix to a given integer.
]]
function p._Ordinal( value, style, gender, lang, nosup )
-- Normalize style & gender; 'roman year' is an alias for 'roman'
style = string.lower(style)
if style == 'roman year' then
style = 'roman'
end
gender = string.lower(gender)
-- if no language is specified, default to english (caller might want to get user's language)
if not lang or lang == '' then
lang = 'en';
end
-- Just in case someone breaks the internationalization code, fix the english scheme
if i18n.SchemeFromLang['en'] == nil then
i18n.SchemeFromLang['en'] = 'en-scheme'
end
if i18n.Scheme['en-scheme'] == nil then
i18n.Scheme['en-scheme'] = {rules = 'skip-tens', superscript = true, suffix = 'th', suffix_1 = 'st', suffix_2 = 'nd', suffix_3 = 'rd'}
end
-- Add the default scheme (i.e. "<value>.")
if i18n.SchemeFromLang['default'] == nil then
i18n.SchemeFromLang['default'] = 'period-scheme'
end
if i18n.Scheme['period-scheme'] == nil then
i18n.Scheme['period-scheme'] = {rules = 'suffix', suffix = '.'}
end
-- which scheme should we use to format the ordinal value?
-- Use Fallback module to handle languages groups that map to a supported language
local schemeSpecifier = fallback._langSwitch(i18n.SchemeFromLang, lang)
-- Look up scheme based on scheme specifier
local scheme = i18n.Scheme[schemeSpecifier]
-- process scheme by applying rules identified by Scheme
local output = ''
local rules = scheme['rules/'..style] or scheme.rules
if rules == 'skip-tens' then
local suffix
local mod100 = math.floor(math.abs(value)) % 100
if (mod100 >= 10) and (mod100 <= 19) then
suffix = scheme.suffix or ''
else
local mod10 = math.floor(math.abs(value)) % 10
suffix = scheme['suffix_'..mod10] or scheme.suffix or ''
end
output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( suffix, scheme.superscript, nosup)
elseif rules == 'suffix' then
output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( scheme.suffix or '', scheme.superscript, nosup)
elseif rules == 'prefix' then
output = (scheme.suffix or '') .. p._FormatNum(value, scheme.formatlang or lang)
elseif rules == 'mod10-suffix' then
local index = math.floor(math.abs(value)) % 10
local suffix = scheme['suffix_'..index] or scheme.suffix or ''
output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( suffix, scheme.superscript, nosup)
elseif rules == 'gendered-suffix' then
local suffix = scheme['suffix_'..gender] or scheme.suffix or ''
output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( suffix, scheme.superscript, nosup)
elseif rules == 'gendered-suffix-one' then
local suffix
if value == 1 then
suffix = scheme['suffix_1_'..gender] or scheme['suffix_1'] or scheme.suffix or ''
else
suffix = scheme['suffix_'..gender] or scheme.suffix or ''
end
output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( suffix, scheme.superscript, nosup)
else
output = p._FormatNum(value, lang)
end
return output
end
--[[
Helper function to generate superscripted content
]]
function p._Superscript( str, superscript, nosup )
if superscript and (not nosup) then
return '<sup>' .. str .. '</sup>'
else
return str
end
end
--[[
Helper function to call Formatnum. This really should be invoking Formatnum via the module directly, but
the Formatnum module doesn't currently have a Lua-friendly method, just a template method.
]]
function p._FormatNum( value, lang )
if lang == 'roman' then
return roman._HTMLNumeral (value )
else
return mw.getCurrentFrame():expandTemplate({title = 'Template:Formatnum', args = {value, lang}})
end
end
--[[
Helper function to handle error messages.
]]
function p._error( error_str, value )
return '<strong class="error"><span title="Error: ' .. error_str .. '">' .. value .. '</span></strong>';
end
return p