模块:Lang:修订间差异
imported>Vozhuo // Edit via Wikiplus |
imported>Vozhuo // Edit via Wikiplus |
||
| 第8行: | 第8行: | ||
local p = {}; | local p = {}; | ||
local initial_style_state; -- set by | local initial_style_state; -- set by lang_xx_inherit() and lang_xx_italic() | ||
local getArgs = require ('Module:Arguments').getArgs; | local getArgs = require ('Module:Arguments').getArgs; | ||
| 第63行: | 第63行: | ||
]] | ]] | ||
function p.is_latn (text) | |||
local latn = table.concat ( | local latn = table.concat ( | ||
{ | { | ||
| 第78行: | 第78行: | ||
'\239\172\128-\239\172\134', -- Alphabetic Presentaion Forms U+FB00-U+FB06 (EF AC 80 - EF AC 86) | '\239\172\128-\239\172\134', -- Alphabetic Presentaion Forms U+FB00-U+FB06 (EF AC 80 - EF AC 86) | ||
'\239\188\129-\239\188\188', -- Halfwidth and Fullwidth Forms U+FF01-U+FF3C (EF BC 81 - EF BC BC) | '\239\188\129-\239\188\188', -- Halfwidth and Fullwidth Forms U+FF01-U+FF3C (EF BC 81 - EF BC BC) | ||
'–', -- ndash | |||
'—', -- mdash | |||
'«', '»', -- guillemets commonly used in several 'Latn' languages | |||
']', -- close the set | ']', -- close the set | ||
}); | }); | ||
text = mw.text.decode (text, true); -- replace numeric and named html entities with their unicode characters | |||
text = mw.ustring.gsub (text, '%[%[[^|]+|([^%]]+)%]%]', '%1'); -- remove the link and markup from complex wikilink in case interwiki to non-Latn wikipedia | text = mw.ustring.gsub (text, '%[%[[^|]+|([^%]]+)%]%]', '%1'); -- remove the link and markup from complex wikilink in case interwiki to non-Latn wikipedia | ||
return not is_set (mw.ustring.gsub (text, latn, '')); -- replace all latn characters with empty space; if result is all empty space, text is latn | return not is_set (mw.ustring.gsub (text, latn, '')); -- replace all latn characters with empty space; if result is all empty space, text is latn | ||
end | |||
--[[--------------------------< I N V E R T _ I T A L I C S >------------------------------------------------- | |||
This function attempts to invert the italic markup a args.text by adding/removing leading/trailing italic markup | |||
in args.text. Like |italic=unset, |italic=invert disables automatic italic markup. Individual leading/trailing | |||
apostrophes are converted to their html numeric entity equivalent so that the new italic markup doesn't become | |||
bold markup inadvertently. | |||
Leading and trailing wiki markup is extracted from args.text into separate table elements. Addition, removal, | |||
replacement of wiki markup is handled by a string.gsub() replacement table operating only on these separate elements. | |||
In the string.gsub() matching pattern, '.*' matches empty string as well as the three expected wiki markup patterns. | |||
This function expects that markup in args.text is complete and correct; if it is not, oddness may result. | |||
]] | |||
local function invert_italics (source) | |||
local invert_pattern_table = { -- leading/trailing markup add/remove/replace patterns | |||
[""]="\'\'", -- empty string becomes italic markup | |||
["\'\'"]="", -- italic markup becomes empty string | |||
["\'\'\'"]="\'\'\'\'\'", -- bold becomes bold italic | |||
["\'\'\'\'\'"]="\'\'\'", -- bold italic become bold | |||
}; | |||
local seg = {}; | |||
source = source:gsub ("%f[\']\'%f[^\']", '&'); -- protect single quote marks from being interpreted as bold markup | |||
seg[1] = source:match ('^(\'\'+%f[^\']).+') or ''; -- get leading markup, if any; ignore single quote | |||
seg[3] = source:match ('.+(%f[\']\'\'+)$') or ''; -- get trailing markup, if any; ignore single quote | |||
if '' ~= seg[1] and '' ~= seg[3] then -- extract the 'text' | |||
seg[2] = source:match ('^\'\'+%f[^\'](.+)%f[\']\'\'+$') -- from between leading and trailing markup | |||
elseif '' ~= seg[1] then | |||
seg[2] = source:match ('^\'\'+%f[^\'](.+)') -- following leading markup | |||
elseif '' ~= seg[3] then | |||
seg[2] = source:match ('(.+)%f[\']\'\'+$') -- preceding trailing markup | |||
else | |||
seg[2] = source -- when there is no markup | |||
end | |||
seg[1] = seg[1]:gsub (".*", invert_pattern_table, 1); -- replace leading markup according to pattern table | |||
seg[3] = seg[3]:gsub (".*", invert_pattern_table, 1); -- replace leading markup according to pattern table | |||
return table.concat (seg); -- put it all back together and done | |||
end | end | ||
| 第109行: | 第158行: | ||
no - force args.text to be rendered in normal font; returns 'normal' | no - force args.text to be rendered in normal font; returns 'normal' | ||
unset - disables font control so that font-style applied to text is dictated by markup inside or outside the template; returns 'inherit' | unset - disables font control so that font-style applied to text is dictated by markup inside or outside the template; returns 'inherit' | ||
invert - disables font control so that font-style applied to text is dictated by markup outside or inverted inside the template; returns 'invert' | |||
]] | ]] | ||
local function validate_italic (italic, italics) | local function validate_italic (italic, italics) | ||
local properties = {['yes'] = 'italic', ['no'] = 'normal', ['unset'] = 'inherit', ['default'] = nil}; | local properties = {['yes'] = 'italic', ['no'] = 'normal', ['unset'] = 'inherit', ['invert'] = 'invert', ['default'] = nil}; | ||
if italic and italics then -- return nil and an error message if both are set | if italic and italics then -- return nil and an error message if both are set | ||
| 第241行: | 第291行: | ||
elseif source:match ('^%a%a%a?%-%d%d%d%d$') then -- ll-variant (where variant is 4 digits) | 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)$'); | code, variant = source:match ('^(%a%a%a?)%-(%d%d%d%d)$'); | ||
elseif source:match ('^%a%a%a?%-[%a%d][%a%d][%a%d][%a%d][%a%d] | elseif source:match ('^%a%a%a?%-[%a%d][%a%d][%a%d][%a%d][%a%d][%a%d]?[%a%d]?[%a%d]?$') then -- ll-variant (where variant is 5-8 alnum characters) | ||
code, variant = source:match ('^(%a%a%a?)%-([%a%d][%a%d][%a%d][%a%d][%a%d][%a%d]?[%a%d]?[%a%d]?)$'); | code, variant = source:match ('^(%a%a%a?)%-([%a%d][%a%d][%a%d][%a%d][%a%d][%a%d]?[%a%d]?[%a%d]?)$'); | ||
| 第415行: | 第465行: | ||
]] | ]] | ||
local function make_text_span (code, text, rtl, style, size) | local function make_text_span (code, text, rtl, style, size, language) | ||
local span = {}; | local span = {}; | ||
local style_added = ''; | local style_added = ''; | ||
| 第421行: | 第471行: | ||
if text:match ('^%*') then | if text:match ('^%*') then | ||
table.insert (span, '*'); -- move proto language text prefix outside of italic markup if any; use numeric entity because plan splat confuses MediaWiki | table.insert (span, '*'); -- move proto language text prefix outside of italic markup if any; use numeric entity because plan splat confuses MediaWiki | ||
text = text:gsub ('^%*', ''); -- remove the | text = text:gsub ('^%*', ''); -- remove the splat from the text | ||
end | end | ||
| 第449行: | 第499行: | ||
end | end | ||
table.insert (span, table.concat ({style_added, '>'})); | if is_set (language) then | ||
table.insert (span, table.concat ({style_added, ' title=\"', language})); --start the title text | |||
if language:find ('languages') then | |||
table.insert (span, ' collective text\"'); -- for collective languages | |||
else | |||
table.insert (span, ' language text\"'); -- for individual languages | |||
end | |||
table.insert (span, '>'); -- close the opening span tag | |||
else | |||
table.insert (span, table.concat ({style_added, '>'})); -- close the style attribute and close opening span tag | |||
end | |||
table.insert (span, text); -- insert the text | table.insert (span, text); -- insert the text | ||
| 第619行: | 第679行: | ||
end | end | ||
local style = args.italic or args.italics; | |||
-- if ('unset' ~= args.italic) and ('unset' ~= args.italics) then -- allow italic markup when |italic=unset or |italics=unset | |||
if ('unset' ~= style) and ('invert' ~=style) then | |||
if args.text:find ("%f[\']\'\'%f[^\']") or args.text:find ("%f[\']\'\'\'\'\'%f[^\']") then -- italic but not bold, or bold italic | |||
return make_error_msg ('text has italic markup', args, template); | |||
end | end | ||
end | end | ||
| 第723行: | 第784行: | ||
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 (is_latn (args.text) and 'en' ~= code) then -- script set to latn or text is wholly latn script but not rendering English | if ('latn' == subtags.script) or (p.is_latn (args.text) and 'en' ~= code) then -- script set to latn or text is wholly latn script but not rendering English | ||
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 | ||
| 第748行: | 第809行: | ||
end | end | ||
if 'invert' == args.italic then | |||
args.text = invert_italics (args.text) | |||
end | |||
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, make_text_span (args.code, args.text, args.rtl, args.italic, args.size)); | table.insert (out, make_text_span (args.code, args.text, 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)); -- maintenance messages and categories | table.insert (out, render_maint(args.nocat)); -- maintenance messages and categories | ||
| 第906行: | 第971行: | ||
if 'no' == args.link then | if 'no' == args.link then | ||
table.insert (out, language_name); -- language name without wikilink | table.insert (out, language_name); -- language name without wikilink | ||
else | --else | ||
-- if language_name:find ('languages') then | |||
-- table.insert (out, make_wikilink (language_name)); -- collective language name uses simple wikilink | |||
-- else | |||
-- table.insert (out, make_wikilink (language_name .. ' language', language_name)); -- language name with wikilink | |||
-- end | |||
end | end | ||
table.insert (out, ':'); -- separator | table.insert (out, ':'); -- separator | ||
end | end | ||
if 'invert' == args.italic then | |||
args.text = invert_italics (args.text) | |||
end | |||
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, make_text_span (args.code, args.text, args.rtl, args.italic, args.size)) | table.insert (out, make_text_span (args.code, args.text, args.rtl, args.italic, args.size)) | ||
if is_set (args.translit) and not is_latn (args.text) then -- transliteration (not supported in {{lang}}); not supported when args.text is wholly latn text (this is an imperfect test) | if is_set (args.translit) and not p.is_latn (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 | ||
| 第953行: | 第1,026行: | ||
table.insert (out, " </small>"); | table.insert (out, " </small>"); | ||
end | end | ||
table.insert (out, table.concat ({ | table.insert (out, table.concat ({''', args.translation, '''})); -- use html entities to avoid wiki markup confusion | ||
end | end | ||