------------------------------------------------------------------------------

error messaging; keys to this table are the template base names:
	'nihongo', 'nihongo3', 'nihongo krt', 'nihongo foot' → 'nihongo' etc


local err_msg = {
	['nihongo'] = 'Japanese or romaji text required',
	['hanyu'] = 'Chinese or pinyin text required',

local err_cat = {
	['nihongo'] = 'Category:Nihongo template errors',
	['hanyu'] = 'Category:Hanyu template errors',

--------------------------------------------------------------------------------

configuration setting for the various templates. keys to this table are the template names without spacing


local cfg = {
	['nihongo'] = {
		tag = 'ja',
		system = 'hepburn',
		system_link = 'Hepburn',
		err_msg = err_msg.nihongo,
		err_cat = err_cat.nihongo,
	['nihongo3'] = {
		tag = 'ja',
		system = 'hepburn',
		err_msg = err_msg.nihongo,
		err_cat = err_cat.nihongo,
	['nihongo krt'] = {
		tag = 'ja',
		system = 'hepburn',
		err_msg = err_msg.nihongo,
		err_cat = err_cat.nihongo,
	['nihongo foot'] = {
		tag = 'ja',
		system = 'hepburn',
		system_link = 'Hepburn',
		err_msg = err_msg.nihongo,
		err_cat = err_cat.nihongo,
	['hanyu'] = {
		tag = 'zh',
		system = 'pinyin',
		system_link = 'Pinyin',
		err_msg = err_msg.hanyu,
		err_cat = err_cat.hanyu,
	['hanyu3'] = {
		tag = 'zh',
		system = 'pinyin',
		err_msg = err_msg.hanyu,
		err_cat = err_cat.hanyu,
	['hanyu hrt'] = {
		tag = 'zh',
		system = 'pinyin',
		err_msg = err_msg.hanyu,
		err_cat = err_cat.hanyu,
	['hanyu foot'] = {
		tag = 'zh',
		system = 'pinyin',
		system_link = 'Pinyin',
		err_msg = err_msg.hanyu,
		err_cat = err_cat.hanyu,

--------------------------------------------------------------------------------

Creates an error message for , , , and 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 error_message (template)
	local msg = {'');
	if 0 == mw.title.getCurrentTitle.namespace then
		table.insert ;
	end

	return table.concat (msg);	
end

--[[----------------------------------------------------------------------------------------

Shared support function for nihingo, nihongo3, and nihongo_foot. Calculates an index into formatting{}
from set/unset parameters:
	args[1] (english text) has a value of 8 (set) or 0 (unset)
	args[2] (native text) has a value of 4
	args[3] (romanized text) has a value of 2
	args[4] (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 formatting[index][2] table

]]

local function renderer 
	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 args[1] – args[4]
		index = index + (args[i] and param_weight[i] or 0);						-- calculate an index into formatting{}
	end

	output = (0 ~= index) and string.format  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 '') or '';								-- where there is output, add secret tag close
end

------------------------------------------------------------------------------

Add kerning when first or last character of romanized text contacts adjacent opening or closing paranthesis

In this example, without kerning, the romanized characters 'j' and 'V' are italicized so will contact the parentheses
	()

' has not yet been replaced)
 is the return from lang_module._transl so is not wrapped in parentheses


local function romanized_kern 
	if not romanized or ('' == romanized) then									-- if romanized not set
		return ret_string;														-- then we're done
	end

	local romanized_text = romanized:gsub :gsub :gsub :gsub ;	-- strip html tags

	romanized = romanized:gsub ('([%(%)%.%%%+%-%*%?%[%^%$%]])', '%%%1');				-- escape lua pattern characters

	local romanized_has_leading_paren = ret_string:match ('%(' .. romanized);			-- has a value if (; nil else
	local romanized_has_trailing_paren = ret_string:match (romanized .. '%)');		-- has a value if ); nil else

	local kern_lead_pattern = '^[jpy]';											-- list of characters that when italicized contact unitalicized leading parenthesis
	local kern_tail_pattern = '[dfijkltCEFHIJKMNPR-Z\'"%?!%]]$';				-- list of characters that when italicized contact unitalicized trailing parenthesis

	local kern_right = ' capture
	local kern_left = '%1 capture

	if romanized_has_leading_paren and romanized_text:match (kern_lead_pattern) then
		ret_string = ret_string:gsub ('%((' .. romanized .. ')', kern_right);		-- replace plain '(' with kerned '(';  included here to ensure that the correct '(' is kerned
	end
	if romanized_has_trailing_paren and romanized_text:match (kern_tail_pattern) then
		ret_string = ret_string:gsub ('(' .. romanized .. ')%)', kern_left);		-- replace plain ')' with kerned ')';  included here to ensure that the correct ')' is kerned
	end

	return ret_string;															-- done
end

----------------------------------------------------------------------------------------------

Common support for and 

render order: is translated (English), native, romanized

 is used to select the appropriate cfg table


local function common 
	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, native, romanized, extra, extra2 = args[1], args[2], args[3], args.extra or args[4], args.extra2 or args[5];	-- meaningful names
	args[4] = extra or args[4];													-- ensure that extra is 'positional' for use by renderer

	local lead = 'yes' == args.lead;											-- make boolean

	if not (native or romanized) then											-- not present, return an error message
		return error_message (template);
	end
	if native then
		native = lead and lang_module._lang_xx_inherit  or lang_module._lang ;	-- add ja script with/without language prefix
	end
	if romanized then
		romanized = (lead and english and (cfg[template].system_link .. ': ') or '') .. lang_module._transl  or nil;
	end

	local formatting = {														-- : place holders for font-weight style spans; akin to stripmarkers, replaced before function returns

	local ret_string = renderer 
	ret_string = romanized_kern ;						-- kern romanized text when appropriate
	ret_string = ret_string:gsub ('');	-- replace 'secret' tags with proper tags

	return ret_string;															-- because gsub returns the number of replacements made as second return value
end

--------------------------------------

Common support for and 

render order: is romanized, native, translated (English)

 is used to select the appropriate cfg table


local function common_romanized_native_translated 
	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, native, romanized, extra, extra2 = args[1], args[2], args[3], args.extra or args[4], args.extra2 or args[5];	-- meaningful names
	args[4] = extra or args[4];													-- ensure that extra is 'positional' for use by renderer

	if not (native or romanized) then											-- not present, return an error message
		return error_message (template);
	end
	native = native and lang_module._lang  or nil;
	romanized = romanized and lang_module._transl  or nil;
	
	local formatting = {														-- : place holders for font-weight style spans; akin to stripmarkers, replaced before function returns

	local ret_string = renderer 
	ret_string = ret_string:gsub ('');	-- replace 'secret' tags with proper tags
	return ret_string;															-- because gsub returns the number of replacements made as second return value
end

--------------------------------------

Common support for and 

render order: is native, romanized, translated (English)

 is used to select the appropriate cfg table


local function common_native_romanized_translated 
	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, native, romanized, extra, extra2 = args[1], args[2], args[3], args.extra or args[4], args.extra2 or args[5];	-- meaningful names
	args[4] = extra or args[4];													-- ensure that extra is 'positional' for use by renderer

	if not (native or romanized) then											-- not present, return an error message
		return error_message (template);
	end
	native = native and lang_module._lang  or nil;
	romanized = romanized and lang_module._transl  or nil;
	
	local formatting = {														-- : place holders for font-weight style spans; akin to stripmarkers, replaced before function returns

	local ret_string = renderer 
	ret_string = romanized_kern ;						-- kern romanized text when appropriate
	ret_string = ret_string:gsub ('');	-- replace 'secret' tags with proper tags
	return ret_string;															-- because gsub returns the number of replacements made as second return value
end

------------------------------------------------------------------------------------

Common support for and 

render order: is English

 is used to select the appropriate cfg table


local function common_foot 
	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, native, romanized, extra, extra2 = args[1], args[2], args[3], args.extra or args[4], args.extra2 or args[5];	-- meaningful names
	args[4] = extra or args[4];													-- ensure that extra is 'positional' for use by renderer
	local post = args[6] or args.post;
	local group = args.group;
	local ref_name = args.ref_name
	local lead = 'yes' == args.lead;											-- make boolean

	if not (native or romanized) then											-- not present, return an error message
		return error_message (template);
	end
	if native then
		native = lead and lang_module._lang_xx_inherit  or lang_module._lang ;	-- add ja script with/without language prefix
	end
	if romanized then
		romanized = (lead and (cfg[template].system_link .. ': ') or '') .. lang_module._transl  or nil;
	end
	
	local formatting = {
																				-- from here english is used in the mapping but not rendered by renderer so not included in the table

	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 native or romanized or extra or extra2 then								-- no ref tag when none of these are set (it would be empty)
		local content = renderer ;
		content = content:gsub (' tags added by renderer; spans not used by this template

		return english .. frame:extensionTag ;	-- english with attached reference tag
	else
		return english;															-- nothing to be inside ref tag so just return english
	end
end

--[=[-----------------------------------------------------------------------------------------

Implement using Module:Lang for language and transliteration markup

 are positional parameters
	
	: Japanese language text using Japanese script; TODO: require?
	: Hepburn romanization (transliteration); TODO: in Module:Lang/data change tooltip text to 'Hepburn romanization'?
 are positional or named: |extra= and |extra2=; mixing can be problematic
	
	

]=]

local function nihongo (frame)
	return common 
end

--[=[---------------------------------------------------------------------------------------

Implement using Module:Lang for language and transliteration markup

Similar to but changes rendered order and does not support |lead=

 are positional parameters
	
	: Japanese language text using Japanese script; TODO: require?
	: Hepburn romanization (transliteration); TODO: in Module:Lang/data change tooltip text to 'Hepburn romanization'?
 are positional or named: |extra= and |extra2=; mixing can be problematic
	
	

]=]

local function nihongo3 (frame)
	return common_romanized_native_translated 
end

--[=[---------------------------------------------------------------------------------

Implement using Module:Lang for language and transliteration markup

Similar to but changes rendered order and does not support |lead=

 are positional parameters
	
	: Japanese language text using Japanese script; TODO: require?
	: Hepburn romanization (transliteration); TODO: in Module:Lang/data change tooltip text to 'Hepburn romanization'?
	 are positional or named: |extra= and |extra2=; mixing can be problematic
	
	

]=]

local function nihongo_krt (frame)
	return common_native_romanized_translated 
end

--[=[-------------------------------------------------------------------------------

Implement using Module:Lang for language and transliteration markup

 are positional parameters
	
	: Japanese language text using Japanese script; TODO: require?
	: Hepburn romanization (transliteration); TODO: in Module:Lang/data change tooltip text to 'Hepburn romanization'?
 are positional or named: |extra= and |extra2=; mixing can be problematic
	
	
)
	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)

]=]

local function nihongo_foot (frame)
	return common_foot 
end

--[=[---------------------------------------------------------------------------------------------

Implement using Module:Lang for language and transliteration markup

 are positional parameters
	
	: Chinese language text using Chinese script; TODO: require?
	: Pinyin romanization (transliteration); TODO: in Module:Lang/data change tooltip text to 'Pinyin romanization'?
 are positional or named: |extra= and |extra2=; mixing can be problematic
	
	

]=]

local function hanyu (frame)
	return common 
end

--[=[-------------------------------------------------------------------------------------------

Implement using Module:Lang for language and transliteration markup

Similar to but changes rendered order and does not support |lead=

 are positional parameters
	
	: Chinese language text using Chinese script; TODO: require?
	: Pinyin romanization (transliteration); TODO: in Module:Lang/data change tooltip text to 'Pinyin romanization'?
 are positional or named: |extra= and |extra2=; mixing can be problematic
	
	

]=]

local function hanyu3 (frame)
	return common_romanized_native_translated 
end

--[=[-------------------------------------------------------------------------------------

Implement using Module:Lang for language and transliteration markup

Similar to but changes rendered order and does not support |lead=

 are positional parameters
	
	: Chinese language text using Chinese script; TODO: require?
	: Pinyin romanization (transliteration); TODO: in Module:Lang/data change tooltip text to 'Pinyin romanization'?
	 are positional or named: |extra= and |extra2=; mixing can be problematic
	
	

]=]

local function hanyu_hrt (frame)
	return common_native_romanized_translated 
end

--[=[-----------------------------------------------------------------------------------

Implement using Module:Lang for language and transliteration markup

 are positional parameters
	
	: Chinese language text using Chinese script; TODO: require?
	: Pinyin romanization (transliteration); TODO: in Module:Lang/data change tooltip text to 'Pinyin romanization'?
 are positional or named: |extra= and |extra2=; mixing can be problematic
	
	
)
	TODO: in Module:Lang, turnoff tooltip for transl when |lead=yes
	in the live template |lead= also adds the Help:Installing Chinese character sets link; this is not supported in this code (hanyu nor hanyu3 have this support)

]=]

local function hanyu_foot (frame)
	return common_foot 
end

----------------------------------------------------------------------

return {
	nihongo = nihongo,
	nihongo3 = nihongo3,
	nihongokrt = nihongo_krt,													-- TODO: rename function name in to use nihongo_krt; delete this line
	nihongo_krt = nihongo_krt,
	nihongo_foot = nihongo_foot,
	
	hanyu = hanyu,
	hanyu3 = hanyu3,
	hanyu_hrt = hanyu_hrt,
	hanyu_foot = hanyu_foot,