Jump to content
Toggle menu
  • 8 articles
  • 75 files
  • 7 users
  • 37.8K edits
Neodyland Wiki
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:Ordinal: Difference between revisions

From Neodyland Wiki
comment out FormantNum import, as we currently access via template expansion
Improve scoping, so only the public functions are accessible to users of this module
Line 16: Line 16:
-- === Dependencies ======================
-- === Dependencies ======================
-- =======================================
-- =======================================
local i18n      = require('Module:I18n/ordinal')        -- get localized translations of ordinals
local i18n      = require('Module:I18n/ordinal')        -- get localized translations of ordinals
local fallback  = require('Module:Fallback')            -- get fallback functions
local fallback  = require('Module:Fallback')            -- get fallback functions
local yesno    = require('Module:Yesno')              -- boolean value interpretation
local yesno    = require('Module:Yesno')              -- boolean value interpretation
--local formatnum = require('Module:Formatnum')          -- number formatting
local formatnum = require('Module:Formatnum')          -- number formatting
local roman    = require('Module:Roman')              -- roman numeral conversion (primarily for French)
local roman    = require('Module:Roman')              -- roman numeral conversion (primarily for French)
-- =======================================
-- === Public Functions ==================
-- =======================================


--[[
--[[
Line 107: Line 112:
end
end
output = p._OrdinalCore( value, lang, style, gender, nosup )
output = OrdinalCore( value, lang, style, gender, nosup )
else
else
if debug then
if debug then
output = p._error( "not a number", input )
output = output_error( "not a number", input )
end
end
end
end
else
else
if debug then
if debug then
output = p._error( "not a number", '' )
output = output_error( "not a number", '' )
end
end
end
end
Line 122: Line 127:
end
end


-- =======================================
-- === Private Functions =================
-- =======================================


--[[
--[[
This function is the core functionality for adding the appropriate ordinal suffix to a given integer.
This function is the core functionality for adding the appropriate ordinal suffix to a given integer.
]]
]]
function p._OrdinalCore( value, lang, style, gender, nosup )
function OrdinalCore( value, lang, style, gender, nosup )
-- Just in case someone breaks the internationalization code, fix the english scheme
-- Just in case someone breaks the internationalization code, fix the english scheme
if i18n.SchemeFromLang['en'] == nil then
if i18n.SchemeFromLang['en'] == nil then
Line 163: Line 171:
suffix = scheme['suffix_'..mod10] or scheme.suffix or ''
suffix = scheme['suffix_'..mod10] or scheme.suffix or ''
end
end
output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( suffix, scheme.superscript, nosup, period)
output = FormatNum(value, scheme.formatlang or lang) .. Superscript( suffix, scheme.superscript, nosup, period)
elseif rules == 'suffix' then
elseif rules == 'suffix' then
output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( scheme.suffix or '', scheme.superscript, nosup, period)
output = FormatNum(value, scheme.formatlang or lang) .. Superscript( scheme.suffix or '', scheme.superscript, nosup, period)
elseif rules == 'prefix' then
elseif rules == 'prefix' then
output = (scheme.prefix or '') .. p._FormatNum(value, scheme.formatlang or lang)
output = (scheme.prefix or '') .. FormatNum(value, scheme.formatlang or lang)
elseif rules == 'mod10-suffix' then
elseif rules == 'mod10-suffix' then
local index = math.floor(math.abs(value)) % 10
local index = math.floor(math.abs(value)) % 10
local suffix = scheme['suffix_'..index] or scheme.suffix or ''
local suffix = scheme['suffix_'..index] or scheme.suffix or ''
output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( suffix, scheme.superscript, nosup, period)
output = FormatNum(value, scheme.formatlang or lang) .. Superscript( suffix, scheme.superscript, nosup, period)
elseif rules == 'gendered-suffix' then
elseif rules == 'gendered-suffix' then
local suffix = scheme['suffix_'..gender] or scheme.suffix or ''
local suffix = scheme['suffix_'..gender] or scheme.suffix or ''
output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( suffix, scheme.superscript, nosup, period)
output = FormatNum(value, scheme.formatlang or lang) .. Superscript( suffix, scheme.superscript, nosup, period)
elseif rules == 'gendered-suffix-one' then
elseif rules == 'gendered-suffix-one' then
local suffix
local suffix
Line 182: Line 190:
suffix = scheme['suffix_'..gender] or scheme.suffix or ''
suffix = scheme['suffix_'..gender] or scheme.suffix or ''
end
end
output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( suffix, scheme.superscript, nosup, period)
output = FormatNum(value, scheme.formatlang or lang) .. Superscript( suffix, scheme.superscript, nosup, period)
elseif rules == 'suffix-one' then
elseif rules == 'suffix-one' then
local suffix
local suffix
Line 190: Line 198:
suffix = scheme.suffix or ''
suffix = scheme.suffix or ''
end
end
output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( suffix, scheme.superscript, nosup, period)
output = FormatNum(value, scheme.formatlang or lang) .. Superscript( suffix, scheme.superscript, nosup, period)
elseif rules == 'pl' then
elseif rules == 'pl' then
output = p._PolishOrdinal(value, gender)
output = PolishOrdinal(value, gender)
else
else
output = p._FormatNum(value, lang)
output = FormatNum(value, lang)
end  
end  
Line 205: Line 213:
resort to a custom function for Polish ordinals rather than the centralized localization table.
resort to a custom function for Polish ordinals rather than the centralized localization table.
]]
]]
function p._PolishOrdinal( value, gender )
function PolishOrdinal( value, gender )
local suffix = ''
local suffix = ''
local mod100 = math.floor(math.abs(value)) % 100
local mod100 = math.floor(math.abs(value)) % 100
Line 260: Line 268:
end
end
end
end
return p._FormatNum(value, 'pl') .. '-' .. suffix
return FormatNum(value, 'pl') .. '-' .. suffix
end
end


Line 267: Line 275:
Helper function to generate superscripted content
Helper function to generate superscripted content
]]
]]
function p._Superscript( str, superscript, nosup, period )
function Superscript( str, superscript, nosup, period )
if superscript and (not nosup) then
if superscript and (not nosup) then
return period .. '<sup>' .. str .. '</sup>'
return period .. '<sup>' .. str .. '</sup>'
Line 278: Line 286:
--[[
--[[
Helper function to call Formatnum.  This really should be invoking Formatnum via the module directly, but
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.
the Formatnum module doesn't currently have a Lua-friendly method, just a template method.  We optimize this
as much as possible by creating a child frame object to call Formatnum instead of using template expansion.
]]
]]
function p._FormatNum( value, lang )
function FormatNum( value, lang )
if lang == 'roman' then
if lang == 'roman' then
return roman._Numeral(value)
return roman._Numeral(value)
else
else
return mw.getCurrentFrame():expandTemplate({title = 'Template:Formatnum', args = {value, lang}})
-- return mw.getCurrentFrame():expandTemplate({title = 'Template:Formatnum', args = {value, lang}})
local parentFrame = mw.getCurrentFrame():newChild{title = "Module:Ordinal", args = {value, lang}}
local newFrame = parentFrame:newChild{title = 'Module:Formantnum', args = {} }
return formatnum.main(newFrame)
end
end
end
end
Line 292: Line 304:
Helper function to handle error messages.
Helper function to handle error messages.
]]
]]
function p._error( error_str, value )
function output_error( error_str, value )
     return '<strong class="error"><span title="Error: ' .. error_str .. '">' .. value .. '</span></strong>';
     return '<strong class="error"><span title="Error: ' .. error_str .. '">' .. value .. '</span></strong>';
end
end


return p
return p

Revision as of 04:30, 29 December 2014

Module documentation[ create · purge ]
This documentation is transcluded from Module:Ordinal/doc.
--[[  
 
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)

-- =======================================
-- === Public Functions ==================
-- =======================================

--[[
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=|lang=|style=|gender=|nosup=|debug=}}
{{#invoke:Ordinal|Ordinal}} - uses the caller's parameters
 
Parameters
    1: Positive integer number. 
    lang: language
    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.	
    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
	
	local output = p._Ordinal( 
		args[1],  						-- positive integer number
		lang,							-- language
		args["style"],					-- allows to set presentation style
		args["gender"], 				-- allows to specify gender (m, f, or n)
		yesno(args["nosup"], false),	-- set nosup to "y" to suppress superscripts
		yesno(args["debug"], false)		-- Set debug=y to output error messages
	)
	
	return output
end


--[[
This function will add the appropriate ordinal suffix to a given integer. 

Parameters
	input: Numeral as a positive integer or string.
	lang: Language code as a string (e.g. 'en', 'de', etc.).
	style: Presentation style as a string (e.g. 'd', 'roman', etc.).
	gender: Gender as a string ('m', 'f', 'n').  Use empty string '' to leave gender unspecified.
	nosup: Boolean, set to true to force the ordinals to display without superscript.
	debug: Boolean, set to true to output error messages.

Error Handling:
   Unless debug is true, any error results in value being echoed to the output.
]]
function p._Ordinal( input, lang, style, gender, nosup, debug )	
	local output = input
	
	if input then
		local value = tonumber(input)
		if value and (value > 0) then
		
			-- Normalize style, the style 'roman year' is an alias for 'roman'
			style = string.lower(style or '')
			if style == 'roman year' then
				style = 'roman'
			end
			
			-- Normalize gender parameter
			gender = string.lower(gender or '')
			if (gender ~= 'm') and (gender ~= 'f') and (gender ~= 'n') then
				gender = ''
			end
	
			-- 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
			
			output = OrdinalCore( value, lang, style, gender, nosup )
		else
			if debug then
				output = output_error( "not a number", input )
			end
		end
	else
		if debug then
			output = output_error( "not a number", '' )
		end
	end
		
	return output
end

-- =======================================
-- === Private Functions =================
-- =======================================

--[[
This function is the core functionality for adding the appropriate ordinal suffix to a given integer.
]]
function OrdinalCore( value, lang, style, gender, nosup )	
	-- 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 (and possibly style)
	local scheme = i18n.Scheme[schemeSpecifier .. '/' .. style] or i18n.Scheme[schemeSpecifier]
	
	-- process scheme by applying rules identified by Scheme
	local output = ''
	local period = (scheme.period and '.') or ''
	local rules = 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 = FormatNum(value, scheme.formatlang or lang) .. Superscript( suffix, scheme.superscript, nosup, period)
	elseif rules == 'suffix' then
		output = FormatNum(value, scheme.formatlang or lang) .. Superscript( scheme.suffix or '', scheme.superscript, nosup, period)
	elseif rules == 'prefix' then
		output = (scheme.prefix or '') .. 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 = FormatNum(value, scheme.formatlang or lang) .. Superscript( suffix, scheme.superscript, nosup, period)
	elseif rules == 'gendered-suffix' then
		local suffix = scheme['suffix_'..gender] or scheme.suffix or ''
		output = FormatNum(value, scheme.formatlang or lang) .. Superscript( suffix, scheme.superscript, nosup, period)
	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 = FormatNum(value, scheme.formatlang or lang) .. Superscript( suffix, scheme.superscript, nosup, period)
	elseif rules == 'suffix-one' then
		local suffix
		if value == 1 then
			suffix = scheme['suffix_1'] or scheme.suffix or ''
		else
			suffix = scheme.suffix or ''
		end
		output = FormatNum(value, scheme.formatlang or lang) .. Superscript( suffix, scheme.superscript, nosup, period)
	elseif rules == 'pl' then
		output = PolishOrdinal(value, gender)
	else
		output = FormatNum(value, lang)
	end 
	
	return output
end


--[[
Helper function to generate Polish ordinals.  Polish rules are more complex than most, so we 
resort to a custom function for Polish ordinals rather than the centralized localization table.
]]
function PolishOrdinal( value, gender )
	local suffix = ''
	local mod100 = math.floor(math.abs(value)) % 100
	if (mod100 >= 10) and (mod100 <= 19) then
		if gender == 'f' then
			suffix = 'ta'
		elseif gender == 'n' then
			suffix = 'te'
		else
			suffix = 'ty'
		end
	else
		local mod10 = math.floor(math.abs(value)) % 10
		if (mod10 == 1) then
			if gender == 'f' then
				suffix = 'sza'
			elseif gender == 'n' then
				suffix = 'sze'
			else
				suffix = 'szy'
			end
		elseif (mod10 == 2) then
			if gender == 'f' then
				suffix = 'ga'
			elseif gender == 'n' then
				suffix = 'gie'
			else
				suffix = 'gi'
			end
		elseif (mod10 == 3) then
			if gender == 'f' then
				suffix = 'cia'
			elseif gender == 'n' then
				suffix = 'cie'
			else
				suffix = 'ci'
			end
		elseif (mod10 == 7) or (mod10 == 8) then
			if gender == 'f' then
				suffix = 'ma'
			elseif gender == 'n' then
				suffix = 'me'
			else
				suffix = 'my'
			end
		else
			if gender == 'f' then
				suffix = 'ta'
			elseif gender == 'n' then
				suffix = 'te'
			else
				suffix = 'ty'
			end
		end
	end
	return FormatNum(value, 'pl') .. '-' .. suffix
end


--[[
Helper function to generate superscripted content
]]
function Superscript( str, superscript, nosup, period )
	if superscript and (not nosup) then
		return period .. '<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.  We optimize this
as much as possible by creating a child frame object to call Formatnum instead of using template expansion.
]]
function FormatNum( value, lang )
	if lang == 'roman' then
		return roman._Numeral(value)
	else
		-- return mw.getCurrentFrame():expandTemplate({title = 'Template:Formatnum', args = {value, lang}})
		local parentFrame = mw.getCurrentFrame():newChild{title = "Module:Ordinal", args = {value, lang}}
		local newFrame = parentFrame:newChild{title = 'Module:Formantnum', args = {} }
		return formatnum.main(newFrame)
	end
end
	

--[[
Helper function to handle error messages.
]]
function output_error( error_str, value )
    return '<strong class="error"><span title="Error: ' .. error_str .. '">' .. value .. '</span></strong>';
end

return p
Cookies help us deliver our services. By using our services, you agree to our use of cookies.