Module:Lang: Difference between revisions
Jump to navigation
Jump to search
Content added Content deleted
m (variant decode fix;) |
(synch from sandbox;) |
||
Line 6: | Line 6: | ||
require('Module:No globals'); |
require('Module:No globals'); |
||
local p = {}; |
|||
local initial_style_state; -- set by lang_xx_normal() and lang_xx_italic() |
local initial_style_state; -- set by lang_xx_normal() and lang_xx_italic() |
||
local getArgs = require ('Module:Arguments').getArgs; |
local getArgs = require ('Module:Arguments').getArgs; |
||
local unicode = require ("Module:Unicode data"); -- for is_latin() and is_rtl() |
|||
local yesno = require ('Module:Yesno'); |
|||
local lang_name_table = mw.loadData ('Module:Language/name/data'); |
local lang_name_table = mw.loadData ('Module:Language/name/data'); |
||
Line 32: | Line 34: | ||
return not (var == nil or var == ''); |
return not (var == nil or var == ''); |
||
end |
end |
||
--[[--------------------------< I S _ L A T N >---------------------------------------------------------------- |
|||
Returns true if all of text argument is written using Latn script for letters, numbers and punctuationset; false else. |
|||
]] |
|||
p.is_latn = require ('Module:Unicode data').is_Latin |
|||
Line 156: | Line 149: | ||
return; |
return; |
||
end |
end |
||
local yesno = require "Module:Yesno"; |
|||
if false == yesno (args.cat) or true == yesno (args.nocat) then |
if false == yesno (args.cat) or true == yesno (args.nocat) then |
||
Line 172: | Line 164: | ||
]] |
]] |
||
local function in_array( needle, haystack ) |
local function in_array ( needle, haystack ) |
||
if needle == nil then |
if needle == nil then |
||
return false; |
return false; |
||
Line 249: | Line 241: | ||
local function get_ietf_parts (source, args_script, args_region, args_variant) |
local function get_ietf_parts (source, args_script, args_region, args_variant) |
||
local code, script, region, variant, private; -- ietf tag parts |
|||
local code; |
|||
local script = ''; |
|||
local region = ''; |
|||
local variant = ''; |
|||
local private = ''; |
|||
if not is_set (source) then |
if not is_set (source) then |
||
Line 259: | Line 247: | ||
end |
end |
||
local pattern = { -- table of tables holding acceptibe ietf tag patterns and short names of the ietf part captured by the pattern |
|||
if source:match ('^%a%a%a?%-%a%a%a%a%-%a%a%-%d%d%d%d$') then -- ll-Ssss-RR-variant (where variant is 4 digits) |
|||
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 1 - ll-Ssss-RR-variant (where variant is 4 digits) |
|||
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 2 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 4 digits) |
|||
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 3 - ll-Ssss-RR-variant (where variant is 5-8 alnum characters) |
|||
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 4 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters) |
|||
code, script, region, variant = source:match ('^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$'); |
|||
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d%d)$', 's', 'v'}, -- 5 - ll-Ssss-variant (where variant is 4 digits) |
|||
{'^(%a%a%a?)%-(%a%a%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'v'}, -- 6 - ll-Ssss-variant (where variant is 5-8 alnum characters) |
|||
{'^(%a%a%a?)%-(%a%a)%-(%d%d%d%d)$', 'r', 'v'}, -- 7 - ll-RR-variant (where variant is 4 digits) |
|||
{'^(%a%a%a?)%-(%d%d%d)%-(%d%d%d%d)$', 'r', 'v'}, -- 8 - ll-DDD-variant (where region is 3 digits; variant is 4 digits) |
|||
{'^(%a%a%a?)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 9 - ll-RR-variant (where variant is 5-8 alnum characters) |
|||
{'^(%a%a%a?)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 10 - ll-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters) |
|||
{'^(%a%a%a?)%-(%d%d%d%d)$', 'v'}, -- 11 - ll-variant (where variant is 4 digits) |
|||
{'^(%a%a%a?)%-(%w%w%w%w%w%w?%w?%w?)$', 'v'}, -- 12 - ll-variant (where variant is 5-8 alnum characters) |
|||
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)$', 's', 'r'}, -- 13 - ll-Ssss-RR |
|||
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)$', 's', 'r'}, -- 14 - ll-Ssss-DDD (region is 3 digits) |
|||
{'^(%a%a%a?)%-(%a%a%a%a)$', 's'}, -- 15 - ll-Ssss |
|||
{'^(%a%a%a?)%-(%a%a)$', 'r'}, -- 16 - ll-RR |
|||
{'^(%a%a%a?)%-(%d%d%d)$', 'r'}, -- 17 - ll-DDD (region is 3 digits) |
|||
{'^(%a%a%a?)$'}, -- 18 - ll |
|||
{'^(%a%a%a?)%-x%-(%w%w?%w?%w?%w?%w?%w?%w?)$', 'p'}, -- 19 - ll-x-pppppppp (private is 1-8 alnum characters) |
|||
} |
|||
local t = {}; -- table of captures; serves as a translator between captured ietf tag parts and named variables |
|||
elseif source:match ('^%a%a%a?%-%a%a%a%a%-%d%d%d%d$') then -- ll-Ssss-variant (where variant is 4 digits) |
|||
code, script, variant = source:match ('^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d%d)$'); |
|||
elseif source:match ('^%a%a%a?%-%a%a%a%a%-%w%w%w%w%w+$') then -- ll-Ssss-variant (where variant is 5-8 alnum characters) |
|||
code, script, variant = source:match ('^(%a%a%a?)%-(%a%a%a%a)%-(%w%w%w%w%w%w?%w?%w?)$'); |
|||
for i, v in ipairs (pattern) do -- spin through the pattern table looking for a match |
|||
elseif source:match ('^%a%a%a?%-%a%a%-%d%d%d%d$') then -- ll-RR-variant (where variant is 4 digits) |
|||
local c1, c2, c3, c4; -- captures in the 'pattern' from the pattern table go here |
|||
code, region, variant = source:match ('^(%a%a%a?)%-(%a%a)%-(%d%d%d%d)$'); |
|||
elseif source:match ('^%a%a%a?%-%d%d%d%-%d%d%d%d$') then -- ll-DDD-variant (where region is 3 digits; variant is 4 digits) |
|||
c1, c2, c3, c4 = source:match (pattern[i][1]); -- one or more captures set if source matches pattern[i]) |
|||
if c1 then -- c1 always set on match |
|||
elseif source:match ('^%a%a%a?%-%a%a%-%w%w%w%w%w+$') then -- ll-RR-variant (where variant is 5-8 alnum characters) |
|||
code = c1; -- first capture is always code |
|||
code, region, variant = source:match ('^(%a%a%a?)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$'); |
|||
t = { |
|||
elseif source:match ('^%a%a%a?%-%d%d%d%-%w%w%w%w%w+$') then -- ll-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters) |
|||
[pattern[i][2] or 'x'] = c2, -- fill the table of captures with the rest of the captures |
|||
code, region, variant = source:match ('^(%a%a%a?)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$'); |
|||
[pattern[i][3] or 'x'] = c3, -- take index names from pattern table and assign sequential captures |
|||
[pattern[i][4] or 'x'] = c4, -- index name may be nil in pattern[i] table so "or 'x'" spoofs a name for this index in this table |
|||
}; |
|||
script = t.s or ''; -- translate table contents to named variables; |
|||
region = t.r or ''; -- absent table entries are nil so set named ietf parts to empty string for concatenation |
|||
variant= t.v or ''; |
|||
private = t.p or ''; |
|||
break; -- and done |
|||
end |
|||
end |
|||
if not code then |
|||
elseif source:match ('^%a%a%a?%-%d%d%d%d$') then -- ll-variant (where variant is 4 digits) |
|||
code, variant = source:match ('^(%a%a%a?)%-(%d%d%d%d)$'); |
|||
elseif source:match ('^%a%a%a?%-%w%w%w%w%w%w?%w?%w?$') then -- ll-variant (where variant is 5-8 alnum characters) |
|||
code, variant = source:match ('^(%a%a%a?)%-(%w%w%w%w%w+)$'); |
|||
elseif source:match ('^%a%a%a?%-%a%a%a%a%-%a%a$') then -- ll-Ssss-RR |
|||
code, script, region = source:match ('^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)$'); |
|||
elseif source:match ('^%a%a%a?%-%a%a%a%a%-%d%d%d$') then -- ll-Ssss-DDD (region is 3 digits) |
|||
code, script, region = source:match ('^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)$'); |
|||
elseif source:match ('^%a%a%a?%-%a%a%a%a$') then -- ll-Ssss |
|||
code, script = source:match ('^(%a%a%a?)%-(%a%a%a%a)$'); |
|||
elseif source:match ('^%a%a%a?%-%a%a$') then -- ll-RR |
|||
code, region = source:match ('^(%a%a%a?)%-(%a%a)$'); |
|||
elseif source:match ('^%a%a%a?%-%d%d%d$') then -- ll-DDD (region is 3 digits) |
|||
code, region = source:match ('^(%a%a%a?)%-(%d%d%d)$'); |
|||
elseif source:match ('^%a%a%a?$') then -- ll |
|||
code = source:match ('^(%a%a%a?)$'); |
|||
elseif source:match ('^%a%a%a?%-x%-%w%w?%w?%w?%w?%w?%w?%w?$') then -- ll-x-pppppppp) |
|||
code, private = source:match ('^(%a%a%a?)%-x%-(%w+)$'); |
|||
else |
|||
return nil, nil, nil, nil, nil, table.concat ({'unrecognized language tag: ', source}); -- don't know what we got but it is malformed |
return nil, nil, nil, nil, nil, table.concat ({'unrecognized language tag: ', source}); -- don't know what we got but it is malformed |
||
end |
end |
||
Line 442: | Line 434: | ||
--[[--------------------------< |
--[[--------------------------< D I V _ M A R K U P _ A D D >-------------------------------------------------- |
||
adds <i> and </i> tags to list-item text or to implied <p>..</p> text. mixed not supported |
|||
TODO: add support for block: div tags instead of span tags; would need some sort of proper parameter to control the switch |
|||
]] |
|||
For italic style, can't do ''{{lang|xx|text}}'' without using <span/> tags when text is italic because of -Latn, |italic=yes, |
|||
or auto-italics because the wrapping wikimarkup produces this: |
|||
<i><i lang="xx">text</i></i> |
|||
which is later reduced to this: |
|||
<i>text</i> |
|||
This reduction happens in some sort of cleanup process outside the scope of this template/module. |
|||
local function div_markup_add (text, style) |
|||
Until or unless this is fixed italic text must be: |
|||
local implied_p = {}; |
|||
<i><span lang="xx">text</span></i> |
|||
if text:find ('^\n[%*:;#]') then -- look for list markup; list markup must begin at start of text |
|||
if 'italic' == style then |
|||
return mw.ustring.gsub (text, '(\n[%*:;#]+)([^\n]+)', '%1<i>%2</i>'); -- insert italic markup at each list item |
|||
else |
|||
return text; |
|||
end |
|||
end |
|||
if text:find ('\n+') then -- look for any number of \n characters in text |
|||
text = text:gsub ('([^\n])\n([^\n])', '%1 %2'); -- replace single newline characters with a space character which mimics mediawiki |
|||
if 'italic' == style then |
|||
text = text:gsub('[^\n]+', '<p><i>%1</i></p>'); -- insert p and italic markup tags at each impled p (two or more consecutive '\n\n' sequences) |
|||
else |
|||
text = text:gsub ('[^\n]+', '<p>%1</p>'); -- insert p markup at each impled p |
|||
text = text:gsub ('\n', ''); -- strip newline characters |
|||
end |
|||
end |
|||
return text; |
|||
end |
|||
--[[--------------------------< M A K E _ T E X T _ H T M L >-------------------------------------------------- |
|||
Add the html markup to text according to the type of content that it is: <span> or <i> tags for inline content or |
|||
<div> tags for block content |
|||
]] |
]] |
||
local function |
local function make_text_html (code, text, tag, rtl, style, size, language) |
||
local |
local html = {}; |
||
local style_added = ''; |
local style_added = ''; |
||
if text:match ('^%*') then |
if text:match ('^%*') then |
||
table.insert ( |
table.insert (html, '*'); -- move proto language text prefix outside of italic markup if any; use numeric entity because plane splat confuses MediaWiki |
||
text = text:gsub ('^%*', ''); -- remove the splat from the text |
text = text:gsub ('^%*', ''); -- remove the splat from the text |
||
end |
end |
||
if 'span' == tag then -- default html tag for inline content |
|||
if 'italic' == style then |
|||
if 'italic' == style then -- but if italic |
|||
tag = 'i'; -- change to <i> tags |
|||
end |
|||
else -- must be div so go |
|||
text = div_markup_add (text, style); -- handle implied <p>, implied <p> with <i>, and list markup (*;:#) with <i> |
|||
end |
end |
||
table.insert (span, table.concat ({'<span lang="'})); -- open <span> tag |
|||
table.insert (span, table.concat ({code, '\"'})); -- add language attribute |
|||
table.insert (html, table.concat ({'<', tag})); -- open the <i>, <span>, or <div> html tag |
|||
if rtl then |
|||
table.insert (html, table.concat ({' lang="', code, '\"'})); -- add language attribute |
|||
if rtl or unicode.is_rtl(text) then |
|||
table.insert (html, ' dir="rtl"'); -- add direction attribute for right to left languages |
|||
end |
end |
||
if 'normal' == style then -- when |italic=no |
if 'normal' == style then -- when |italic=no |
||
table.insert ( |
table.insert (html, ' style=\"font-style:normal;'); -- override external markup, if any |
||
style_added = '\"'; -- remember that style attribute added and is not yet closed |
style_added = '\"'; -- remember that style attribute added and is not yet closed |
||
end |
end |
||
Line 485: | Line 504: | ||
if is_set (size) then -- when |size=<something> |
if is_set (size) then -- when |size=<something> |
||
if is_set (style_added) then |
if is_set (style_added) then |
||
table.insert ( |
table.insert (html, table.concat ({' font-size:', size, ';'})); -- add when style attribute already inserted |
||
else |
else |
||
table.insert ( |
table.insert (html, table.concat ({' style=\"font-size:', size, ';'})); -- create style attribute |
||
style_added = '\"'; -- remember that style attribute added and is not yet closed |
style_added = '\"'; -- remember that style attribute added and is not yet closed |
||
end |
end |
||
Line 493: | Line 512: | ||
if is_set (language) then |
if is_set (language) then |
||
table.insert ( |
table.insert (html, table.concat ({style_added, ' title=\"', language})); --start the title text |
||
if language:find ('languages') then |
if language:find ('languages') then |
||
table.insert ( |
table.insert (html, ' collective text\"'); -- for collective languages |
||
else |
else |
||
table.insert ( |
table.insert (html, ' language text\"'); -- for individual languages |
||
end |
end |
||
table.insert ( |
table.insert (html, '>'); -- close the opening html tag |
||
else |
else |
||
table.insert ( |
table.insert (html, table.concat ({style_added, '>'})); -- close the style attribute and close opening html tag |
||
end |
end |
||
table.insert ( |
table.insert (html, text); -- insert the text |
||
table.insert ( |
table.insert (html, table.concat ({'</', tag, '>'})); -- close the <i>, <span>, or <div> html tag |
||
if 'italic' == style then |
|||
if rtl then -- legacy; shouldn't be necessary because all of the rtl text is wrapped inside an html tag with dir="rtl" attribute |
|||
table.insert (span, '</i>'); -- close italic style tag |
|||
table.insert (html, '‎'); -- make sure the browser knows that we're at the end of the rtl |
|||
end |
|||
if rtl then -- legacy; shouldn't be necessary because all of the rtl text is wrapped in <span dir="rtl">text</span> |
|||
table.insert (span, '‎'); -- make sure the browser knows that we're at the end of the rtl |
|||
end |
end |
||
return table.concat ( |
return table.concat (html); -- put it all together and done |
||
end |
end |
||
Line 653: | Line 669: | ||
--[ |
--[[--------------------------< V A L I D A T E _ T E X T >---------------------------------------------------- |
||
This function checks the content of args.text and returns empty string if nothing is amiss else it returns an |
This function checks the content of args.text and returns empty string if nothing is amiss else it returns an |
||
Line 659: | Line 675: | ||
Italic rendering is controlled by the |italic= template parameter so italic markup should never appear in args.text |
Italic rendering is controlled by the |italic= template parameter so italic markup should never appear in args.text |
||
either as ''itself |
either as ''itself'' or as '''''bold italic''''' unless |italic=unset or |italic=invert. |
||
] |
]] |
||
local function validate_text (template, args) |
local function validate_text (template, args) |
||
Line 711: | Line 727: | ||
--[[--------------------------< P R O T O _ P R E F I X >------------------------------------------------------ |
--[[--------------------------< P R O T O _ P R E F I X >------------------------------------------------------ |
||
for proto languages, text is prefixed with a splat. We do that here as a flag for |
for proto languages, text is prefixed with a splat. We do that here as a flag for make_text_html() so that a splat |
||
will be rendered outside of italic markup (if used). If the first character in text here is already a splat, we |
will be rendered outside of italic markup (if used). If the first character in text here is already a splat, we |
||
do nothing |
do nothing |
||
Line 723: | Line 739: | ||
return text; |
return text; |
||
end |
|||
--[[--------------------------< H A S _ P O E M _ T A G >------------------------------------------------------ |
|||
looks for a poem strip marker in text; returns true when found; false else |
|||
auto-italic detection disabled when text has poem stripmarker because it is not possible for this code to know |
|||
the content that will replace the stripmarker. |
|||
]] |
|||
local function has_poem_tag (text) |
|||
return text:find ('\127[^\127]*UNIQ%-%-poem%-[%a%d]+%-QINU[^\127]*\127') and true or false; |
|||
end |
|||
--[[--------------------------< H T M L _ T A G _ S E L E C T >------------------------------------------------ |
|||
Inspects content of and selectively trims text. Returns text and the name of an appropriate html tag for text. |
|||
If text contains: |
|||
\n\n text has implied <p>..</p> tags - trim leading and trailing whitespace and return |
|||
If text begins with list markup: |
|||
\n* unordered |
|||
\n; definition |
|||
\n: definition |
|||
\n# ordered |
|||
trim all leading whitespace except \n and trim all trailing whitespace |
|||
If text contains <poem>...</poem> stripmarker, return text unmodified and choose <div>..</div> tags because |
|||
the stripmarker is replaced with text wrapped in <div>..</div> tags. |
|||
]] |
|||
local function html_tag_select (text) |
|||
local tag; |
|||
if has_poem_tag (text) then -- contains poem stripmarker (we can't know the content of that) |
|||
tag = 'div'; -- poem replacement is in div tags so lang must use div tags |
|||
elseif mw.text.trim (text):find ('\n\n+') then -- contains implied p tags |
|||
text = mw.text.trim (text); -- trim leading and trailing whitespace characters |
|||
tag = 'div'; -- must be div because span may not contain p tags (added later by MediaWiki); poem replacement is in div tags |
|||
elseif text:find ('\n[%*:;%#]') then -- if text has list markup |
|||
text = text:gsub ('^[\t\r\f ]*', ''):gsub ('%s*$', ''); -- trim all whitespace except leading newline character '\n' |
|||
tag = 'div'; -- must be div because span may not contain ul, dd, dl, ol tags (added later by MediaWiki) |
|||
else |
|||
text = mw.text.trim (text); -- plain text |
|||
tag = 'span'; -- so span is fine |
|||
end |
|||
return text, tag; |
|||
end |
end |
||
Line 737: | Line 805: | ||
]] |
]] |
||
function |
local function lang (frame) |
||
local args = getArgs(frame |
local args = getArgs (frame, { -- this code so that we can detect and handle wiki list markup in text |
||
valueFunc = function (key, value) |
|||
if 2 == key or 'text' == key then -- the 'text' parameter; do not trim wite space |
|||
return value; -- return untrimmed 'text' |
|||
elseif value then -- all other values: if the value is not nil |
|||
value = mw.text.trim (value); -- trim whitespace |
|||
if '' ~= value then -- empty string when value was only whitespace |
|||
return value; |
|||
end |
|||
end |
|||
return nil; -- value was empty or contained only whitespace |
|||
end -- end of valueFunc |
|||
}); |
|||
local out = {}; |
local out = {}; |
||
local language_name; -- used to make category names |
local language_name; -- used to make category names |
||
Line 744: | Line 825: | ||
local code; -- the language code |
local code; -- the language code |
||
local msg; -- for error messages |
local msg; -- for error messages |
||
local tag = 'span'; -- initial value for make_text_html() |
|||
if args[1] and args.code then |
if args[1] and args.code then |
||
Line 757: | Line 839: | ||
end |
end |
||
msg = validate_text ('lang', args); -- ensure that |text= is set |
msg = validate_text ('lang', args); -- ensure that |text= is set |
||
if is_set (msg) then -- msg is an already-formatted error message |
if is_set (msg) then -- msg is an already-formatted error message |
||
return msg; |
return msg; |
||
end |
end |
||
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate html tag with text trimmed accordingly |
|||
validate_cat_args (args); -- determine if categorization should be suppressed |
validate_cat_args (args); -- determine if categorization should be suppressed |
||
Line 778: | Line 862: | ||
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls |
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls |
||
if ('latn' == subtags.script) or |
if ('latn' == subtags.script) or -- script is latn |
||
('en' ~= code and not is_set (subtags.script) and not has_poem_tag (args.text) and unicode.is_Latin (args.text)) then -- text not English, no script specified and not in poem markup but is wholly latn script (auto-italics) |
|||
args.italic = 'italic'; -- DEFAULT for {{lang}} templates is upright; but if latn script set for font-style:italic |
|||
args.italic = 'italic'; -- DEFAULT for {{lang}} templates is upright; but if latn script set for font-style:italic |
|||
else |
else |
||
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style |
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style |
||
Line 795: | Line 880: | ||
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant); -- format to recommended subtag styles; private omitted because private |
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant); -- format to recommended subtag styles; private omitted because private |
||
subtags.private = subtags.private and table.concat ({code, '-x-', subtags.private}) or nil; -- assemble a complete private ietf subtag; args.code does not get private subtag |
|||
language_name = lang_data.override[table.concat ({code, '-x-', subtags.private})][1]; -- ... args.code does not get private subtag |
|||
if is_set (subtags.private) and lang_data.override[subtags.private] then -- get the language name for categorization |
|||
language_name = lang_data.override[ |
language_name = lang_data.override[subtags.private][1]; -- first look for private use tag language name |
||
elseif lang_data.override[code] then |
|||
language_name = lang_data.override[code][1] -- then language names taken from the override table |
|||
elseif lang_name_table.lang[code] then |
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 |
language_name = lang_name_table.lang[code][1]; -- table entries sometimes have multiple names, always take the first one |
||
end |
end |
||
if 'invert' == args.italic then |
if 'invert' == args.italic and 'span' == tag then -- invert only supported for in-line content |
||
args.text = invert_italics (args.text) |
args.text = invert_italics (args.text) |
||
end |
end |
||
Line 809: | Line 896: | ||
args.text = proto_prefix (args.text, language_name); -- prefix proto-language text with a splat |
args.text = proto_prefix (args.text, language_name); -- prefix proto-language text with a splat |
||
table.insert (out, |
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size, language_name)); |
||
table.insert (out, make_category (code, language_name, args.nocat)); |
table.insert (out, make_category (code, language_name, args.nocat)); |
||
table.insert (out, render_maint(args.nocat)); |
table.insert (out, render_maint(args.nocat)); -- maintenance messages and categories |
||
return table.concat (out); -- put it all together and done |
return table.concat (out); -- put it all together and done |
||
Line 823: | Line 910: | ||
that can have multiple writing systems, it may be appropriate to set |script= as well. |
that can have multiple writing systems, it may be appropriate to set |script= as well. |
||
For each {{lang-xx}} template choose the appropriate entry-point function so that this function |
For each {{lang-xx}} template choose the appropriate entry-point function so that this function knows the default |
||
styling that should be applied to text. |
styling that should be applied to text. |
||
Line 835: | Line 922: | ||
Supported parameters are: |
Supported parameters are: |
||
|code = (required) the IANA language code |
|code = (required) the IANA language code |
||
|script = IANA script code; especially for use with languages that use multiple writing systems |
|script = IANA script code; especially for use with languages that use multiple writing systems |
||
|region = IANA region code |
|region = IANA region code |
||
|variant = IANA variant code |
|variant = IANA variant code |
||
|text = (required) the displayed text in language specified by code |
|text = (required) the displayed text in language specified by code |
||
|link = boolean false ('no') |
|link = boolean false ('no') does not link code-spcified language name to associated language article |
||
|rtl = boolean true ('yes') identifies the language specified by code as a right-to-left language |
|rtl = boolean true ('yes') identifies the language specified by code as a right-to-left language |
||
|nocat = boolean true ('yes') inhibits normal categorization; error categories are not affected |
|nocat = boolean true ('yes') inhibits normal categorization; error categories are not affected |
||
|cat = boolian false ('no') opposite form of |nocat= |
|||
|italic = boolean true ('yes') renders displayed text in italic font; boolean false ('no') renders displayed text in normal font; not set renders according to initial_style_state |
|italic = boolean true ('yes') renders displayed text in italic font; boolean false ('no') renders displayed text in normal font; not set renders according to initial_style_state |
||
|lit = text that is a literal translation of text |
|lit = text that is a literal translation of text |
||
|label = |
|label = 'none' to suppress all labeling (language name, 'translit.', 'lit.') |
||
any other text replaces language-name label - automatic wikilinking disabled |
any other text replaces language-name label - automatic wikilinking disabled |
||
for those {{lang-xx}} templates that support transliteration (those |
for those {{lang-xx}} templates that support transliteration (those templates where |text= is not entirely latn script): |
||
|translit = text that is a transliteration of text |
|translit = text that is a transliteration of text |
||
|translit-std = the standard that applies to the transliteration |
|translit-std = the standard that applies to the transliteration |
||
Line 861: | Line 949: | ||
local function _lang_xx (frame) |
local function _lang_xx (frame) |
||
local args = getArgs(frame, |
local args = getArgs(frame, |
||
{ |
|||
parentFirst= true, -- parameters in the template override parameters set in the {{#invoke:}} |
|||
valueFunc = function (key, value) |
|||
if 1 == key then -- the 'text' parameter; do not trim wite space |
|||
return value; -- return untrimmed 'text' |
|||
elseif value then -- all other values: if the value is not nil |
|||
value = mw.text.trim (value); -- trim whitespace |
|||
if '' ~= value then -- empty string when value was only whitespace |
|||
return value; |
|||
end |
|||
end |
|||
return nil; -- value was empty or contained only whitespace |
|||
end -- end of valueFunc |
|||
}); |
|||
local out = {}; |
local out = {}; |
||
local language_name; -- used to make display text, article links |
local language_name; -- used to make display text, article links |
||
Line 872: | Line 975: | ||
local translit_title; |
local translit_title; |
||
local msg; -- for error messages |
local msg; -- for error messages |
||
local tag = 'span'; -- initial value for make_text_html() |
|||
if args[1] and args.text then |
if args[1] and args.text then |
||
Line 883: | Line 987: | ||
return msg; |
return msg; |
||
end |
end |
||
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate html tag with text trimmed accordingly |
|||
if args[2] and args.translit then |
if args[2] and args.translit then |
||
Line 941: | Line 1,047: | ||
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant); -- format to recommended subtag styles |
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant); -- format to recommended subtag styles |
||
subtags.private = subtags.private and table.concat ({code, '-x-', subtags.private}) or nil; -- assemble a complete private ietf subtag; args.code does not get private subtag |
|||
language_name = lang_data.override[table.concat ({code, '-x-', subtags.private})][1]; -- ... args.code does not get private subtag |
|||
if is_set (subtags.private) and lang_data.override[subtags.private] then -- get the language name for categorization |
|||
language_name = lang_data.override[subtags.private][1]; -- first look for private use tag language name |
|||
elseif lang_data.override[args.code:lower()] then -- look for whole IETF tag in override table |
elseif lang_data.override[args.code:lower()] then -- look for whole IETF tag in override table |
||
language_name = lang_data.override[args.code:lower()][1]; -- args.code:lower() because format_ietf_tag() returns mixed case |
language_name = lang_data.override[args.code:lower()][1]; -- args.code:lower() because format_ietf_tag() returns mixed case |
||
Line 983: | Line 1,091: | ||
args.text = proto_prefix (args.text, language_name); -- prefix proto-language text with a splat |
args.text = proto_prefix (args.text, language_name); -- prefix proto-language text with a splat |
||
table.insert (out, |
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size)) |
||
if is_set (args.translit) and not |
if is_set (args.translit) and not unicode.is_Latin (args.text) then -- transliteration (not supported in {{lang}}); not supported when args.text is wholly latn text (this is an imperfect test) |
||
table.insert (out, ', '); -- comma to separate text from translit |
table.insert (out, ', '); -- comma to separate text from translit |
||
if 'none' ~= args.label then |
if 'none' ~= args.label then |
||
Line 1,038: | Line 1,146: | ||
]] |
]] |
||
function |
local function lang_xx_italic (frame) |
||
initial_style_state = 'italic'; |
initial_style_state = 'italic'; |
||
return _lang_xx (frame); |
return _lang_xx (frame); |
||
Line 1,050: | Line 1,158: | ||
]] |
]] |
||
function |
local function lang_xx_inherit (frame) |
||
initial_style_state = 'inherit'; |
initial_style_state = 'inherit'; |
||
return _lang_xx (frame); |
return _lang_xx (frame); |
||
Line 1,066: | Line 1,174: | ||
]] |
]] |
||
function |
local function name_from_code (frame) |
||
local subtags = {}; -- IETF subtags script, region, variant, and private |
local subtags = {}; -- IETF subtags script, region, variant, and private |
||
local raw_code = frame.args[1]; -- save a copy of the input IETF subtag |
local raw_code = frame.args[1]; -- save a copy of the input IETF subtag |
||
Line 1,115: | Line 1,223: | ||
]] |
]] |
||
function |
local function transl (frame) |
||
local args = getArgs(frame); -- no {{#invoke:}} parameters |
local args = getArgs(frame); -- no {{#invoke:}} parameters |
||
local title_table = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards |
local title_table = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards |
||
Line 1,178: | Line 1,286: | ||
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ |
|||
return p; |
|||
]] |
|||
return { |
|||
lang = lang, -- entry point for {{lang}} |
|||
lang_xx_inherit = lang_xx_inherit, -- entry points for {{lang-??}} |
|||
lang_xx_italic = lang_xx_italic, |
|||
name_from_code = name_from_code, -- used for template documentation; possible use in ISO 639 name from code templates |
|||
transl = transl, -- entry point for {{transl}} |
|||
}; |