require ('Module:No globals');  
----------------------------< I S _ C J K >------------------------------------------------------------------  
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 cjk[code] or false;
end  
----------------------------< S E T _ I T A L I C S >--------------------------------------------------------  
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
local code = .args[1] or .args['code'] or ''; -- empty string causes 'yes' return; will handle the missing code error
local text = .args[2] or .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  
----------------------------< I N _ L A N G >----------------------------------------------------------------  
implements  
Module entry point from an  
<span>(in <language>)</span>  
local function in_lang
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;
local list = {};
local cats = {};
local maint_msgs = {};  
if not args[1] then
local template = (args['template'] and table.concat ({': '})) or ''; -- make template name (if provided by the template)
return table.concat ({'<span style=\"font-size:100%; font-style:normal;\" class=\"error\">error: ', template, 'missing language tag</span>'});
end  
local module = 'Module:Lang' .. (: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 = args[i]: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_table[code] 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, ' <span>')
table.insert (maint_msgs, table.concat ({'code: ', code, ' promoted to code: ', synonym_table[code]}));
table.insert (maint_msgs, '</span>;');
code = synonym_table[code]; -- 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 ('மொழி') then -- add appropriate language-name category
table.insert (cats, table.concat ({''}));
else
table.insert (cats, table.concat ({''}));
end
end
end
end  
local result = {'<span>('}; -- 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 < #list) and ', and ' or ' and ' )); -- and concatenate the language list  
table.insert (result, ')</span>'); -- 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  
----------------------------< N I H O N G O _ E R R O R >----------------------------------------------------  
creates an error message for , , and nihongo foot}} when these template are missing <japanese>
or <romaji> inputs; names the offending template, links to template page, and adds article to Category:Nihongo template errors  
local function nihongo_error (template)
local msg = {'<span>error: : Japanese or romaji text required (help)</span>');
if 0 == mw.title.getCurrentTitle.namespace then
table.insert (msg, '');
end  
return table.concat (msg);
end  
--[[--------------------------< N I H O N G O _ R E N D E R E R >----------------------------------------------  
shared support function for nihingo, nihongo3, and nihongo_foot. Calculates an index into formatting{}
from set/unset parameters:
args[1] (english) has a value of 8 (set) or 0 (unset)
args[2] (japanese) has a value of 4
args[3] (romaji) 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 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 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 (formatting[index][1] and formatting[index][1], formatting[index][2][1], formatting[index][2][2], formatting[index][2][3], formatting[index][2][4]) 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 '<5p4n>' .. extra2; -- <5p4n> and </5p4n>: 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 .. '</5p4n>') or ''; -- where there is output, add secret tag close
end  
--[=[-------------------------< N I H O N G O >----------------------------------------------------------------  
An experiment to see how to implement using Module:Lang for language and transliteration markup  
<English>, <japanese>, and <romaji> are positional parameters
<English>: rendered as presented; purports to be English translation of <kanji/kana>
<japanese>: Japanese language text using Japanese script; TODO: require?
<romaji>: Hepburn romanization (transliteration); TODO: in Module:Lang/data change tooltip text to 'Hepburn romanization'?
<extra> and <extra2> are positional or named: |extra= and |extra2=; mixing can be problematic
<extra> is rendered as presented preceeded with <comma><space>
<extra2> is rendered as presented preceeded with <space>