Module:Lang
From Vigyanwiki
Documentation for this module may be created at Module:Lang/doc
--[=[
This is an experiment to see what is required to consolodate all of the myriad {{lang-xx}} templates
and their subtemplates into a single module with a data table
{{lang-es}} has parameters:
{{{1}}} text - required
{{{link}}} or {{{links}}} defaults to 'yes'
{{{lit}}} literal translation
{{language with name}} has parameters:
{{{1}}} iso language code - required
{{{2}}} language name in English - superfluous?
{{{3}}} text - required
{{{4}}} or {{{lit}}} literal translation
{{{link}}} or {{{links}}} set to 'no' disables '{{{2}} language' wikilinks
{{{rtl}}} passed through to {{lang}}
{{{nocat}}} passed through to {{lang}}
{{lang}} has parameters:
{{{1}}} iso language code - required
{{{2}}} text - required
{{{rtl}}} if set to any value, set dir="rtl" attribute and inserts ‎ after the </span> tag
{{{nocat}}} if set to any value, disables categorization
How it works now:
1. {{lang-es}} receives text as {{{1}}} to which it adds italic markup, sets |links to {{{link}}} or {{{links}}} or yes, sets |lit to {{{lit}}}, and calls {{language with name}}. {{{rtl}}} ignored for this example
2. {{language with name}} renders [[Spanish language|Spanish]] ({{{links}}} not set) or Spanish ({{{links}}} set) and calls {{lang}}
3. {{lang}} wraps the text in the <span lang="es">text</span> and adds categorization
]=]
require('Module:No globals');
local p = {};
local getArgs = require ('Module:Arguments').getArgs;
local lang_name_table = require ('Module:Language/name/data');
local lang_data = mw.loadData ('Module:Lang/data'); -- language name override and transliteration tool-tip tables
local namespace = mw.title.getCurrentTitle().namespace; -- used for categorization
--[[--------------------------< I S _ S E T >------------------------------------------------------------------
Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string.
]]
local function is_set( var )
return not (var == nil or var == '');
end
--[[--------------------------< G E T _ I E T F _ P A R T S >--------------------------------------------------
extracts and returns IETF language tag parts:
primary language subtag (required) - 2 or 3 character lower case IANA language code [ll]
script subtag - four character title-case IANA script code [Ssss]
region subtag - two-character upper-case IANA region code [RR]
in any one of these forms
ll (or lll)
ll-Ssss
ll-RR
ll-Ssss-RR
each of ll, Ssss, and RR when used must be valid
returns three values. Valid parts are return as themselves; omitted parts are returned as empty strings, invalid
parts are returned as nil.
]]
local function get_ietf_parts (source)
local code;
local script;
local region;
if not is_set (source) then
return nil, nil, nil;
end
if source:match ('^%a+%-%a+%-%a+$') then -- ll-Ssss-RR
code, script, region = source:match ('^(%l%l%l?)%-(%u%l%l%l)%-(%u%u)$');
elseif source:match ('^%a+%-%a%a%a%a') then -- ll-Ssss
code, script = source:match ('^(%l%l%l?)%-(%u%l%l%l)$');
region = '';
elseif source:match ('^%a+%-%a%a$') then -- ll-RR
code, region = source:match ('^(%l%l%l?)%-(%u%u)$');
script = '';
elseif source:match ('^%a+$') then -- ll-RR
code = source:match ('^(%l%l%l?)$');
script = '';
region = '';
else
return nil, nil, nil; -- don't know what we got but it is malformed
end
if not (lang_data.override[code] or lang_name_table.lang[code]) then
return nil, nil, nil; -- invalid language code, don't know about the others (don't care?)
end
if is_set (script) then
if not lang_name_table.script[script] then
return code, nil, nil; -- language code ok, invalid script, don't know about region (don't care?)
end
end
if is_set (region) then
if not lang_name_table.region[region] then
return code, script, nil;
end
end
return code, script, region; -- return the good bits
end
--[=[-------------------------< M A K E _ E R R O R _ M S G >--------------------------------------------------
]=]
local function make_error_msg (msg)
local out = {};
table.insert (out, '<span style="font-size:100%" class="error">error: ');
table.insert (out, msg);
table.insert (out, '</span>');
return table.concat (out);
end
--[=[-------------------------< M A K E _ W I K I L I N K >----------------------------------------------------
Makes a wikilink; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only
link is provided, returns a wikilink in the form [[L]]; if neither are provided or link is omitted, returns an
empty string.
]=]
local function make_wikilink (link, display)
if is_set (link) then
if is_set (display) then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
else
return '';
end
end
--[[--------------------------< M A K E _ T E X T _ S P A N >--------------------------------------------------
]]
local function make_text_span (code, text, rtl, italic, size)
local span = {};
table.insert (span, '<span lang="'); -- open <span> tag
table.insert (span, code); -- language attribute
table.insert (span, '"');
if 'yes' == rtl then
table.insert (span, ' dir="rtl"'); -- for right to left languages
end
if is_set (size) then -- {{lang}} only
table.insert (span, table.concat ({' style="font-size:', size, ';"'}))
end
table.insert (span, '>'); -- close the opening span tag
if 'yes' == italic then
table.insert (span, table.concat ({"''", text, "''"})); -- text with italic markup
else
table.insert (span, text); -- DEFAULT: text is not italicized
end
table.insert (span, '</span>'); -- close the span
if 'yes' == rtl then
table.insert (span, '‎'); -- make sure the browser knows that we're at the end of the rtl
end
return table.concat (span); -- put it all together and done
end
--[[--------------------------< M A K E _ C A T E G O R Y >----------------------------------------------------
]]
local function make_category (code, language_name, nocat)
local cat = {};
if (0 ~= namespace) or nocat then -- only categorize in article space
return ''; -- return empty string for concatenation
end
table.insert (cat, '[[Category:Articles containing ');
if ('en' == code) or ('eng' == code) then
table.insert (cat, 'explicitly cited English');
elseif 'art' == code then
table.insert (cat, 'constructed')
else
table.insert (cat, language_name);
end
table.insert (cat, '-language text]]');
return table.concat (cat);
end
--[[--------------------------< M A K E _ T R A N S L I T >----------------------------------------------------
return translit <span>...</span> else return empty string
The value |script= is not used in {{transl}} for this purpose; instead it uses |code. Because language scripts
are listed in the {{transl}} switches they are included in the data tables. The script parameter is introduced
at {{Language with name and transliteration}}. If |script= is set, this function uses it in preference to code.
]]
local function make_translit (code, language_name, translit, std, script)
local title;
local tout = {};
local title_table = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards
table.insert (tout, "''<span title=\"");
if not is_set (std) and not is_set (script) then -- when neither standard nor script specified
table.insert (tout, language_name); -- write a generic tool tip
table.insert (tout, ' transliteration');
elseif is_set (std) and is_set (script) then -- when both are specified
if title_table[std][script] then -- and legitimate
table.insert (tout, title_table[std][script]); -- add the appropriate text to the tool tip
else
return ''; -- one or both invalid, set up for an error message
end
elseif is_set (std) then -- script not set, use language code
if not title_table[std] then return ''; end -- invalid standard, setupt for error message
if title_table[std][code] then
table.insert (tout, title_table[std][code]);
else -- code doesn't match
table.insert (tout, title_table[std]['default']); -- so use the standard's default
end
else -- here if script set but std not set
if title_table['NO_STD'][script] then
table.insert (tout, title_table['NO_STD'][script]); -- use script if set
elseif title_table['NO_STD'][code] then
table.insert (tout, title_table['NO_STD'][code]); -- use language code
else
table.insert (tout, language_name); -- write a generic tool tip
table.insert (tout, ' transliteration');
end
end
table.insert (tout, '" class="Unicode" style="white-space:normal; text-decoration:none">');
table.insert (tout, translit);
table.insert (tout, "</span>''");
return table.concat (tout);
end
--[[--------------------------< L A N G >----------------------------------------------------------------------
{{#invoke:lang|lang|code=<code>|text={{{1}}}|rtl={{{rtl|}}}|size={{{size|}}}|nocat={{{nocat|}}}}}
|code = the BCP47 language code
|text = the displayed text in language specified by code
|rtl = boolean true identifies the language specified by code as a right-to-left language
|size = css keyword appropriate for use with css font-size:<size>
|nocat = boolean true inhibits normal categorization; error categories are not affected
]]
function p.lang (frame)
local args = getArgs(frame);
local out = {};
local language_name;
local code, script, region = get_ietf_parts (args.code);
if is_set (code) then
if lang_data.override[code] then
language_name = lang_data.override[code][1]
elseif lang_name_table.lang[code] then
language_name = lang_name_table.lang[code][1]; -- table entries sometimes have multiple names, always take the first one
end
end
if not is_set (language_name) then
-- table.insert (out, '<span style="font-size:100%" class="error">error: unknown language code: ');
-- table.insert (out, args.code or 'missing');
-- table.insert (out, '</span>');
table.insert (out, make_error_msg (table.concat ({'unknown language code: ', args.code or 'missing'})));
if 0 ~= namespace then -- only categorize in article space
table.insert (out, '[[Category:Articles containing unknown language template codes');
if is_set (args.code) then
table.insert (out, '|' .. args.code); -- add a sort key
end
table.insert (out, ']]');
end
return table.concat (out); -- emit an error message and category
end
table.insert (out, make_text_span (args.code, args.text, args.rtl, nil, args.size)); -- italics set to nil here because not supporte by {{lang}}
table.insert (out, make_category (args.code, language_name, args.nocat));
return table.concat (out); -- put it all together and done
end
--[[--------------------------< L A N G _ X X >----------------------------------------------------------------
{{#invoke:lang|lang_xx|code=<code>|text={{{1}}}|link={{{links|{{{link}}}}}}|rtl={{{rtl|}}}|nocat={{{nocat|}}}|italic={{{italic|}}}|lit={{{lit|}}}|translit={{{translit|}}}|script={{{script|}}}|std={{{std|}}}}}
|code = the BCP47 language code
|text = the displayed text in language specified by code
|link = boolean true (default) links language specified by code to associated language article
|rtl = boolean true identifies the language specified by code as a right-to-left language
|nocat = boolean true inhibits normal categorization; error categories are not affected
|italic = boolean true (default) renders displayed text in italic font
|lit = text that is a literal translation of text
for those {{lang-xx}} templates that support transliteration:
|translit = text that is a transliteration of text
|std = the standard that applies to the transliteration
|script = ISO 15924 script name; falls back to code
]]
function p.lang_xx (frame)
local args = getArgs(frame);
if not is_set (args.italic) then
args.italic = 'yes'; -- DEFAULT for {{lang-xx}} templates is to italicize
end
args.size = nil; -- size not supported in {{lang-xx}}
local out = {};
local language_name;
local code, script, region = get_ietf_parts (args.code);
if is_set (code) then
if lang_data.override[code] then
language_name = lang_data.override[code][1]
elseif lang_name_table.lang[code] then
language_name = lang_name_table.lang[code][1]; -- table entries sometimes have multiple names, always take the first one
end
end
local script = args.script or language_name; -- for translit prefer script of language
local translit;
local translit_title;
if not is_set (language_name) then
-- table.insert (out, '<span style="font-size:100%" class="error">error: unknown language code: ');
-- table.insert (out, args.code or 'missing');
-- table.insert (out, '</span>');
table.insert (out, make_error_msg (table.concat ({'unknown language code: ', args.code or 'missing'})));
if 0 ~= namespace then -- only categorize in article space
table.insert (out, '[[Category:Articles containing unknown language template codes');
if is_set (args.code) then
table.insert (out, '|' .. args.code); -- add a sort key
end
table.insert (out, ']]');
end
return table.concat (out); -- emit an error message and category
end
if 'no' == args.link then
table.insert (out, language_name); -- language name without wikilink
else
table.insert (out, make_wikilink (language_name .. ' language', language_name)); -- language name with wikilink
end
table.insert (out, ': '); -- separator
table.insert (out, make_text_span (args.code, args.text, args.rtl, args.italic, args.size))
if is_set (args.translit) then -- transliteration (not supported in {{lang}}); not supported in all {{lang-xx}}
table.insert (out, ', <small>');
translit_title = mw.title.makeTitle (0, 'Romanization of ' .. language_name)
if translit_title.exists then
table.insert (out, make_wikilink ('Romanization of ' .. script or language_name, 'translit.'));
else
table.insert (out, '<abbr title="transliteration">translit.</abbr>');
end
table.insert (out, ' </small>');
translit = make_translit (args.code, language_name, args.translit, args.std, args.script)
if is_set (translit) then
table.insert (out, translit);
else
-- table.insert (out, '<span style="font-size:100%" class="error">error: invalid translit std or script</span>');
table.insert (out, make_error_msg (table.concat ({'invalid translit std: \'', args.std or 'missing', '\' or script: \'', args.script or 'missing', '\''})));
end
end
if is_set (args.lit) then -- translation (not supported in {{lang}})
table.insert (out, ', <small>');
table.insert (out, make_wikilink ('Literal translation', 'lit.'));
table.insert (out, " </small>'");
table.insert (out, args.lit);
table.insert (out, "'");
end
table.insert (out, make_category (args.code, language_name, args.nocat));
return table.concat (out); -- put it all together and done
end
return p;