name = lang_table[code];
elseif lang_dep_table[code] then -- try the iana deprecated tag/name table
name = lang_dep_table[code];
end  
if lang_dep_table[code] and cat then -- because deprecated code may have been overridden to en.wiki preferred name
table.insert (maint_cats, substitute (cfg.language_name_get_t.deprecated_cat, {code}));
table.insert (maint_msgs, substitute (cfg.language_name_get_t.deprecated_msg, {code}));
end  
return name; -- name from data tables or nil
end  
----------------------------< T E X T _ S C R I P T _ M A T C H _ T E S T >----------------------------------  
IETF script subtag should match the script of the <text>. This module does not attempt to know all scripts and
what they look like. It does know what Latn script looks like so when <text> is written using other than the Latn
script, the IETF script subtag, if present, should not be Latn.  
Conversely, when <text> is written using the Latn script, the IETF script subtag, if present, should be Latn.  
For the purposes of this test, Latf (Fraktur) and Latg (Gaelic) are considered to be equivalent to Latn because
unicode treats these two scripts as font-specific variants of Latn.  
Returns an error message when mismatch detected; nil else.  
local function text_script_match_test (script, is_latn_text, pos, char)
local scripts_t = {['latf'] = true, ['latg'] = true, ['latn'] = true}; -- unicode 'latn' scripts; 'latf' and 'latg' are font variants so there are no Fraktur or Gaelic codepoints
if is_set (script) then -- don't bother with the rest of this if <script> is nil or empty string
script = script:lower; -- lower case to index into <scripts_t>
if is_latn_text then -- when text is wholly Latn script
if not scripts_t[script] then -- but a non-Latn script is specified
return cfg.text_script_match_test_t.latn_txt_mismatch; -- emit an error message
end
else -- when text is not wholly Latn script
if scripts_t[script] then -- but a Latn script is specified
return substitute (cfg.text_script_match_test_t.latn_scr_mismatch, {pos, char}); -- emit an error message with position of first offending character
end
end
end
end  
----------------------------< B I N A R Y _ S E A R C H >---------------------------------------------------  
conducts a binary search of <ranges_t> for a sub-range that holds <target>.  
returns boolean true if a sub-range holding <target> is found; boolean false else.  
local function binary_search (target, ranges_t)
local idx_bot = 1; -- initialize to index of first key
local idx_top = sizeof_ranges_t; -- initialize to index of last key (number of keys)  
if (target < ranges_t[idx_bot][1]) or (target > ranges_t[idx_top][2]) then -- invalid; target out of range
return; -- abandon
end  
local idx_mid; -- calculated index of range midway between top index and bottom index
local flag = false; -- flag to tell us when we've evaluated last (highest) range in <ranges_t>  
while 1 do
idx_mid = math.ceil ((idx_bot + idx_top) / 2); -- get the mid-point in the <ranges_t> sequence
if (target >= ranges_t[idx_mid][1]) and (target <= ranges_t[idx_mid][2]) then -- indexed range low value <= target <= indexed range high value
return true; -- we found the range that holds the <target> character; return true  
elseif (target > ranges_t[idx_mid][2]) then -- is <target> > indexed range high value?
idx_bot = idx_mid; -- adjust <idx_bot> up  
else -- here when <target> less than indexed range low value
idx_top = idx_mid - 1; -- adjust <idx_top> down
end  
if flag then
break; -- here when we just evaluated the last range and <target> not found
end  
if not flag and (idx_bot == idx_top) then -- set true just before we evaluate the last (highest) range in <ranges_t>
flag = true;
end
end
end  
--italic=yes)  
local function is_latin (text, tag)
local count;
text, count = text:gsub ('^%(%((.+)%)%)$', '%1'); -- remove accept-as-written markup if present
if 0 ~= count then
return true, text; -- markup present so assume that <text> is Latn-script
end  
local pos = 0; -- position counter for error messaging
for codepoint in mw.ustring.gcodepoint (text) do -- fetch each code point
pos = pos + 1; -- bump the position counter  
if not is_latn_data.singles_t[codepoint] and -- codepoint not found in the singles list?
not binary_search (codepoint, is_latn_data.ranges_t) and -- codepoint not a member of a listed range?
not (tag and is_latn_data.specials_t[codepoint] and is_latn_data.specials_t[codepoint][tag]) then -- not a language-specific codepoint?
return false, text, pos, mw.ustring.char (codepoint); -- codepoint not known; return false with codepoint position and character representation
end
end
return true, text; -- is known; return <text>
end  
----------------------------< _ L A N G >--------------------------------------------------------------------  
Entry point for .  
There should be no reason to set parameters in the
<includeonly></includeonly>  
Parameters are received from the template's (parent ).  
local function _lang (args)
local out = {};
local language_name; -- used to make category names
local category_name; -- same as language_name except that it retains any parenthetical disambiguators (if any) from the data set
local subtags = {}; -- IETF subtags script, region, variant, and private
local code; -- the language code
local msg; -- for error messages
local tag = 'span'; -- initial value for make_text_html
local template = args.template or cfg.templates_t.lang;  
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};  
validate_cat_args (args); -- determine if categorization should be suppressed  
if args[1] and args.code then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'1', cfg.lang_t.conflict_n_param_types.code}), args, template);
else
args.code = args[1] or args.code; -- prefer args.code
end  
if args[2] and args.text then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'2', cfg.lang_t.conflict_n_param_types.text}), args, template);
else
args.text = args[2] or args.text; -- prefer args.text
end  
msg = validate_text (template, args); -- ensure that |text= is set
if is_set (msg) then -- msg is an already-formatted error message
return msg;
end  
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate html tag with text trimmed accordingly  
args.rtl = args.rtl == cfg.keywords_t.affirmative; -- convert to boolean: 'yes' -> true, other values -> false  
args.proto, msg = validate_proto (args.proto); -- return boolean, or nil, or nil and error message flag
if msg then
return make_error_msg (substitute (cfg.lang_t.invalid_proto, {msg}), args, template);
end  
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (args.code); -- |script=, |region=, |variant= not supported because they should be part of args.code (} in )  
if msg then
return make_error_msg (msg, args, template);
end  
local is_latn_text, pos, char;
is_latn_text, args.text, pos, char= is_latin (args.text, code); -- make a boolean  
msg = text_script_match_test (subtags.script, is_latn_text, pos, char)
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end  
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end  
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls
if ('latn' == subtags.script) or -- script is latn
(this_wiki_lang_tag ~= code and not is_set (subtags.script) and not has_poem_tag (args.text) and is_latn_text) then -- text not this wiki's language, no script specified and not in poem markup but is wholly latn script (auto-italics)
args.italic = 'italic'; -- DEFAULT for templates is upright; but if latn script set for font-style:italic
else
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style
end
end