モジュール:Lang/utilities

require('strict');
----------------------------------------------------------------------------------------------
return true if code is one of the listed Chinese, Japanese, Korean ISO 639 codes, false else.
local function is_cjk_code (code)
local cjk =
		{
		'zh' = true, 'cdo' = true, 'cjy' = true, 'cmn' = true,			-- Chinese language codes
		'cpi' = true, 'cpx' = true, 'czh' = true, 'czo' = true,
		'gan' = true, 'hak' = true, 'hsn' = true, 'ltc' = true,
		'lzh' = true, 'mnp' = true, 'nan' = true, 'och' = true,
		'wuu' = true, 'yue' = true, 'zhx' = true,
		'ja' = true, 'jpx' = true, 'ojp' = true,							-- Japanese language codes
		'ko' = true, 'okm' = true, 'oko' = true,							-- Korean language codes
		}
	return cjkcode or false;
end
------------------------------------------------------------------------------------
Created for use with Template:Infobox book and Template:Infobox document and perhaps others to replace hard-coded
italic markup in the call to .  This module attempts to make sure that  correctly applies italic
markup according to MOS:FOREIGNITALIC.  
local function set_italics (frame)
	local code = frame.args1 or frame.args'code' or ;						-- empty string causes 'yes' return;  will handle the missing code error
	local text = frame.args2 or frame.args'text' or ;						-- empty string causes 'yes' return;  will handle the missing text error
	
	local is_latn = require ("Module:Unicode data").is_Latin;
	
	if is_cjk_code (code) and not is_latn (text) then							-- is_latn() is in Module:Lang
		return  'no';															-- only case for 'no' 
	end
	return 'yes';																-- everything else is yes
end
--------------------------------------------------------------------------------------------
implements 
Module entry point from an template=Link language
(in )
local function in_lang (frame)
	local getArgs = require ('Module:Arguments').getArgs;
	local synonym_table = mw.loadData ('Module:Lang/ISO 639 synonyms');				-- ISO 639-2/639-2T code translation to 639-1 code
	local args = getArgs(frame);
	local list = {};
	local cats = {};
	local maint_msgs = {};
	
	if not args1 then
		local template = (args'template' and table.concat ({': '})) or ;	-- make template name (if provided by the template)
		return table.concat ({'error: ', template, 'missing language tag'});
	end
	local module = 'Module:Lang' .. (frame:getTitle():match ('/sandbox') or );	-- if this module is the sandbox,
	local name_from_tag = require (module)._name_from_tag;						-- use Module:Lang/sandbox; Module:Lang else
	local namespace = mw.title.getCurrentTitle().namespace;						-- used for categorization
	local this_wiki_lang = mw.language.getContentLanguage().code;				-- get this wiki's language code
	for i, lang in ipairs (args) do
		local code = argsi:lower();
		local t = {code, 'link' = args'link', 'template' = args'template'};	-- build an 'args' table
		lang = name_from_tag (t)												-- get the language name
		table.insert (list, lang)												-- add this language or error message to the list
		if 'ca-valencia' ~= code then											-- except for valencian
			code = code:match ('^%a%a%a?%f^%a');								-- strip off region, script, and variant tags so that they aren't used to make category names
		end
		if synonym_tablecode then												-- if 639-2/639-2T code has a 639-1 synonym
			if (0 == namespace) then
				table.insert (cats, table.concat ({}));
			end
			table.insert (maint_msgs, ' ')
			table.insert (maint_msgs, table.concat ({'code: ', code, ' promoted to code: ', synonym_tablecode}));
			table.insert (maint_msgs, ';');
			code = synonym_tablecode;											-- use the synonym
		end
		if (0 == namespace) then												-- when in article space
			if lang:find ('error') then											-- add error category (message provided by Module:Lang)
				table.insert (cats, );
			elseif this_wiki_lang ~= code then									-- categorize article only when code is not this wiki's language code
				if lang:match ('%%.-%%') then							-- wikilinked individual language name
					lang = lang:match ('%%(.-)%%');
				elseif lang:match ('%%.-%%') then							-- wikilinked collective languages name
					lang = lang:match ('%%(.-)%%');
				end																-- neither of these then plain-text language name
				if lang:find ('languages') then									-- add appropriate language-name category
					table.insert (cats, table.concat ({}));
				else
					table.insert (cats, table.concat ({}));
				end
			end
		end
	end
	
	local result = {'('};							-- opening span and (
--	table.insert (result, 'yes' == args'cap' and 'In ' or 'in ');				-- add capitalized or uncapitalized 'in'
	table.insert (result, mw.text.listToText (list, '、', (2 ');											-- add closing ) and closing span
--	table.insert (result, table.concat (maint_msgs) or );				-- add maint messages, if any
--	table.insert (result, table.concat (cats));									-- add categories
	return table.concat (result);												-- make a big string and done
end
--------------------------------------------------------------------------------
creates an error message for , , and nihongo foot}} when these template are missing 
or  inputs; names the offending template, links to template page, and adds article to Category:Nihongo template errors
local function nihongo_error (template)
	local msg = {'error: }: Japanese or romaji text required (help)');
	if 0 == mw.title.getCurrentTitle().namespace then
		table.insert (msg, );
	end
	return table.concat (msg);	
end
--------------------------------------------------------------------------
shared support function for nihingo(), nihongo3(), and nihongo_foot().  Calculates an index into formatting{}
from set/unset parameters:
	args1 (english) has a value of 8 (set) or 0 (unset)
	args2 (japanese) has a value of 4
	args3 (romaji) has a value of 2
	args4 (extra) has a value of 1
index, the sum of these values, gets the appropriate format string from formatting{} table with associated values
from the formattingindex2 table
local function nihongo_renderer (args, formatting, extra2)
	local output;
	local index = 0;															-- index into formatting{}
	local param_weight = {8, 4, 2, 1};											-- binary parameter weights: 1 = english (8), 2 = japanese (4), 3 = romaji (2), 4 = extra (1)
	for i=1, 5 do																-- spin through args1 – args4
		index = index + (argsi and param_weighti or 0);						-- calculate an index into formatting{}
	end
	output = (0 ~= index) and string.format (formattingindex1 and formattingindex1, formattingindex21, formattingindex22, formattingindex23, formattingindex24) or nil;
	if extra2 then																-- always just attached to the end (if there is an end) so not part of formatting{}
		output = output and (output .. ' ' .. extra2) or  .. extra2;	--  and : place holders for font-weight style spans; akin to stripmarkers, to be replaced
	end																			-- (nihongo and nihongo3) or removed (nihongo foot)
	return output and (output .. ) or ;								-- where there is output, add secret tag close
end
--=-----------------------------------------------------------------------------------------
An experiment to see how to implement  using Module:Lang for language and transliteration markup
, , and  are positional parameters
	: rendered as presented; purports to be English translation of 
	: Japanese language text using Japanese script; TODO: require?
	: Hepburn romanization (transliteration); TODO: in Module:Lang/data change tooltip text to 'Hepburn romanization'?
and  are positional or named: |extra= and |extra2=; mixing can be problematic
	 is rendered as presented preceeded with 
	 is rendered as presented preceeded with 
lead=: takes one value 'yes'; renders language name same as  but also adds Hepburn: ahead of the romanization; TODO: in Module:Lang, turnoff tooltip for transl when |lead=yes
**
local function nihongo (frame)
	local lang_module = require ('Module:Lang' .. (frame:getTitle():match ('/sandbox') or ));	-- if this module is the sandbox, use Module:lang/sandbox; Module:Lang else
	local args = require ('Module:Arguments').getArgs (frame);
	
	local english, japanese, romaji, extra, extra2 = args1, args2, args3, args.extra or args4, args.extra2 or args5;	-- meaningful names
	args4 = extra or args4;													-- ensure that extra is 'positional' for use by nihongo_renderer()
	local lead = 'yes' == args.lead;											-- make boolean
	if not (japanese or romaji) then											-- not present, return an error message
		return nihongo_error ('nihongo');
	end
	if japanese then
		japanese = lead and lang_module._lang_xx_inherit ({'code'='ja', japanese, 'template'='nihongo'}) or lang_module._lang ({'ja', japanese, 'template'='nihongo'});	-- add ja script with/without language prefix
	end
	if romaji then
		romaji = (lead and english and 'Hepburn: ' or ) .. lang_module._transl ({'ja', 'hepburn', romaji}) or nil;
	end
	
	local formatting = {														--  and : place holders for font-weight style spans; akin to stripmarkers, replaced  before function returns
		{'(%s)', {extra}}, 												-- 1 - (extra)
		{'%s', {romaji}},													-- 2 - romaji
		{'%s (%s)', {romaji, extra}},										-- 3 - romaji (extra)
		{'(%s)', {japanese}},												-- 4 - japanese
		{'(%s, %s)', {japanese, extra}},									-- 5 - (japanese, extra)
		{'%s (%s)', {romaji, japanese}},									-- 6 - romaji (japanese)
		{'%s (%s, %s)', {romaji, japanese, extra}},						-- 7 - romaji (japanese, extra)
		{'%s', {english}},												-- 8 - english
		{'%s (%s)', {english, extra}},									-- 9 - english (extra)
		{'%s (%s)', {english, romaji}},									-- 10 - english (romaji)
		{'%s (%s, %s)', {english, romaji, extra}},						-- 11 - english (romaji, extra)
		{'%s (%s)', {english, japanese}},									-- 12 - english (japanese)
		{'%s (%s, %s)', {english, japanese, extra}},						-- 13 - english (japanese, extra)
		{'%s (%s, %s)', {english, japanese, romaji}},						-- 14 - english (japanese, romaji)
		{'%s (%s, %s, %s)', {english, japanese, romaji, extra}},			-- 15 - english (japanese, romaji, extra)
		}
	local ret_string = nihongo_renderer (args, formatting, extra2)
	ret_string = ret_string:gsub (, ):gsub (, );	-- replace 'secret' tags with proper tags
	return ret_string;															-- because gsub returns the number of replacements made as second return value
end
--=extra2=; mixing can be problematic
	 is rendered as presented preceeded with 
	 is rendered as presented preceeded with 
**
local function nihongo3 (frame)
	local lang_module = require ('Module:Lang' .. (frame:getTitle():match ('/sandbox') or ));	-- if this module is the sandbox, use Module:lang/sandbox; Module:Lang else
	local args = require ('Module:Arguments').getArgs (frame);
	
	local english, japanese, romaji, extra, extra2 = args1, args2, args3, args.extra or args4, args.extra2 or args5;	-- meaningful names
	args4 = extra or args4;													-- ensure that extra is 'positional' for use by nihongo_renderer()
	if not (japanese or romaji) then											-- not present, return an error message
		return nihongo_error ('nihongo3');
	end
	japanese = japanese and lang_module._lang ({'ja', japanese}) or nil;
	romaji = romaji and lang_module._transl ({'ja', 'hepburn', romaji}) or nil;
	
	local formatting = {														--  and : place holders for font-weight style spans; akin to stripmarkers, replaced  before function returns
		{'(%s)', {extra}}, 												-- 1 - (extra)
		{'%s', {romaji}},													-- 2 - romaji
		{'%s (%s)', {romaji, extra}},										-- 3 - romaji (extra)
		{'(%s)', {japanese}},												-- 4 - japanese
		{'(%s, %s)', {japanese, extra}},									-- 5 - (japanese, extra)
		{'%s (%s)', {romaji, japanese}},									-- 6 - romaji (japanese)
		{'%s (%s, %s)', {romaji, japanese, extra}},						-- 7 - romaji (japanese, extra)
		{'%s', {english}},												-- 8 - english
		{'%s (%s)', {english, extra}},									-- 9 - english (extra)
		{'%s (%s)', {romaji, english}},									-- 10 - romaji (english)
		{'%s (%s, %s)', {romaji, english, extra}},						-- 11 - romaji (english, extra)
		{'%s (%s)', {english, japanese}},									-- 12 - english (japanese)
		{'%s (%s, %s)', {english, japanese, extra}},						-- 13 - english (japanese, extra)
		{'%s (%s, %s)', {romaji, japanese, english}},						-- 14 - romaji (japanese, english)
		{'%s (%s, %s, %s)', {romaji, japanese, english, extra}},			-- 15 - romaji (japanese, english, extra)
		}
	local ret_string = nihongo_renderer (args, formatting, extra2)
	ret_string = ret_string:gsub (, ):gsub (, );	-- replace 'secret' tags with proper tags
	return ret_string;															-- because gsub returns the number of replacements made as second return value
end
--=-------------------------------------------------------------------------------
An experiment to see how to implement  using Module:Lang for language and transliteration markup
, , and  are positional parameters
	: rendered as presented; purports to be English translation of 
	: Japanese language text using Japanese script; TODO: require?
	: Hepburn romanization (transliteration); TODO: in Module:Lang/data change tooltip text to 'Hepburn romanization'?
and  are positional or named: |extra= and |extra2=; mixing can be problematic
	 is rendered as presented preceeded with 
	 is rendered as presented preceeded with 
is positional or named: |post= is a postscript character preceding the  tag (after )
lead=: takes one value 'yes'; renders language name same as  but also adds Hepburn: ahead of the romanization;
	TODO: in Module:Lang, turnoff tooltip for transl when |lead=yes
	in the live template |lead= also adds the Help:Installing Japanese character sets link; this is not supported in this code (nihongo nor nihongo3 have this support)
group=: the group attribute in  and in 
**
local function nihongo_foot (frame)
	local lang_module = require ('Module:Lang' .. (frame:getTitle():match ('/sandbox') or ));	-- if this module is the sandbox, use Module:lang/sandbox; Module:Lang else
	local args = require ('Module:Arguments').getArgs (frame);
	
	local english, japanese, romaji, extra, extra2 = args1, args2, args3, args.extra or args4, args.extra2 or args5;	-- meaningful names
	args4 = extra or args4;													-- ensure that extra is 'positional' for use by nihongo_renderer()
	local post = args6 or args.post;
	local group = args.group;
	local lead = 'yes' == args.lead;											-- make boolean
	if not (japanese or romaji) then											-- not present, return an error message
		return nihongo_error ('nihongo foot');
	end
	if japanese then
		japanese = lead and lang_module._lang_xx_inherit ({'code'='ja', japanese}) or lang_module._lang ({'ja', japanese});	-- add ja script with/without language prefix
	end
	if romaji then
		romaji = (lead and 'Hepburn: ' or ) .. lang_module._transl ({'ja', 'hepburn', romaji}) or nil;
	end
	
	local formatting = {
		{'%s', {extra}}, 														-- 1 - extra
		{'%s', {romaji}},														-- 2 - romaji
		{'%s, %s', {romaji, extra}},											-- 3 - romaji, extra
		{'%s', {japanese}},														-- 4 - japanese
		{'%s, %s', {japanese, extra}},											-- 5 - japanese, extra
		{'%s %s', {japanese, romaji}},											-- 6 - japanese romaji
		{'%s %s, %s', {japanese, romaji, extra}},								-- 7 - japanese romaji, extra
																				-- from here english is used in the mapping but not rendered by nihongo_renderer so not included in the table
		{, {}},																-- 8 - english
		{'%s', {extra}},														-- 9 - extra
		{'%s', {romaji}},														-- 10 - romaji
		{'%s, %s', {romaji, extra}},											-- 11 - romaji, extra
		{'%s', {japanese}},														-- 12 - japanese
		{'%s, %s', {japanese, extra}},											-- 13 - japanese, extra
		{'%s %s', {japanese, romaji}},											-- 14 - japanese romaji
		{'%s %s, %s', {japanese, romaji, extra}},								-- 15 - japanese romaji, extra
		}
	if english and post then													-- rewrite english to include |post=
		english = english .. post;												-- if english has a value append post else just post
	elseif post then
		english = post;															-- english not set, use post
	elseif not english then														-- neither are set
		english = ;															-- make english an empty string for concatenation
	end
	if japanese or romaji or extra or extra2 then								-- no ref tag when none of these are set (it would be empty)
		local content = nihongo_renderer (args, formatting, extra2);
		content = content:gsub (, ):gsub ('$', , 1);			-- strip secret  and  tags added by nihongo_renderer(); spans not used by this template
		return english .. frame:extensionTag ({name='ref', args={group=group}, content=content});	-- english with attached reference tag
	else
		return english;															-- nothing to be inside ref tag so just return english
	end
end
----------------------------------------------------------------------
return {
	in_lang = in_lang,
	nihongo = nihongo,
	nihongo3 = nihongo3,
	nihongo_foot = nihongo_foot,
	set_italics = set_italics,
	}