Jump to content

Module:Ordinal

विकिपीडिया से
commons>RP88 (Add support for Polish ordinals (more complex than most, so we resort to custom code)) के द्वारा 15:16, 27 दिसंबर 2014 के बदलाव
--[[  
 
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 (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 = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( suffix, scheme.superscript, nosup, period)
	elseif rules == 'suffix' then
		output = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( scheme.suffix or '', scheme.superscript, nosup, period)
	elseif rules == 'prefix' then
		output = (scheme.prefix 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, period)
	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, 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 = p._FormatNum(value, scheme.formatlang or lang) .. p._Superscript( suffix, scheme.superscript, nosup, period)
	elseif rules == 'pl' then
		output = p._PolishOrdinal(value)
	else
		output = p._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 p.PolishOrdinal( value )
	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 p._FormatNum(value, 'pl') .. '-' .. suffix
end


--[[
Helper function to generate superscripted content
]]
function p._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.
]]
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