Module:Other Languages: Difference between revisions
Jump to navigation
Jump to search
ReinDevildom (talk | contribs) Created page with "local p = {} local lib = require('Module:Feature') local KOrm = require('Module:Ko-rm') local i18n = require('Module:I18n').loadMessages('Other Languages') local SelectiveSpan = require('Module:Lang').SelectiveSpan local search = lib.inArray local ne = lib.isNotEmpty local ie = lib.isEmpty local langOrder = {'en', 'zhs', 'zht', 'ja', 'ko', 'es', 'fr', 'ru', 'th', 'vi', 'de', 'id', 'pt', 'tr', 'it'} local categories = mw.html.create() local noCat = {} loc..." |
m Protected "Module:Other Languages" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) |
||
(No difference)
| |||
Revision as of 22:07, 29 August 2025
This Lua module is used primarily on pages in the Main namespace. It can be found on 544 pages, or on about 72.92% of those pages.
Edits to this Lua module will be widely noticed. To avoid large-scale disruption and unnecessary server load, any changes to this Lua module should be tested in its sandbox or testcases subpages. The tested changes can then be added to this page in one single edit by an administrator or a content moderator.
Please consider discussing any changes in the wiki's Discord.
This module implements {{Other Languages}}.
local p = {}
local lib = require('Module:Feature')
local KOrm = require('Module:Ko-rm')
local i18n = require('Module:I18n').loadMessages('Other Languages')
local SelectiveSpan = require('Module:Lang').SelectiveSpan
local search = lib.inArray
local ne = lib.isNotEmpty
local ie = lib.isEmpty
local langOrder = {'en', 'zhs', 'zht', 'ja', 'ko', 'es', 'fr', 'ru', 'th', 'vi', 'de', 'id', 'pt', 'tr', 'it'}
local categories = mw.html.create()
local noCat = {}
local Notes = {reuse={}}
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
parentFirst = true,
removeBlanks = false,
wrappers = {'Template:Other Languages'}
})
if ne(args['Transclude']) then
local new_index = lib.split(args['Transclude'], '#')
local transclude = lib.split(new_index[1], ';')
p.Transclude(args, transclude[1], transclude[2], new_index[2])
else
local Y = 1
while ne(args['Transclude_' .. tostring(Y)]) or ne(args[Y]) do
local new_index = lib.split((args['Transclude_' .. tostring(Y)] or args[Y]), '#')
local transclude = lib.split(new_index[1], ';')
p.Transclude(args, transclude[1], transclude[2], new_index[2])
Y = Y + 1
end
end
p.ParseNotes(args)
return p._main(args, frame)
end
--- Entry point for other modules.
-- @param args The table of arguments for which to generate an HTML table
-- @param frame Optional argument to specify a frame, which will be used for its extensionTag.
-- If not specified, the current frame will be used.
function p._main(args, frame)
local out
if ne(args['1_en']) then
categories:wikitext('[[Category:Other Languages with Multiple Tables]]')
out = mw.html.create('div'):css{['display']='flex', ['column-gap'] = '15px', ['flex-direction'] = 'row', ['flex-wrap'] = 'wrap'}
local Y = 1
local y = tostring(Y)
while args[y .. '_en'] do
local entry = out:tag('div')
entry:tag('h3'):wikitext(args[y .. '_header'] or args[y .. '_en'])
entry:node(p.Table(args, frame, (y .. '_')))
--continue loop
Y = Y+1
y = tostring(Y)
end
else
out = p.Table(args, frame)
end
return tostring(out:node(require('Module:Namespace detect').main{["main"]=categories})) .. (not args.noref and frame:extensionTag{ name = 'references', args = { group = '•' } } or '')
end
function p.Table(args, frame, prefix)
prefix = prefix or ''
local TLcol = false
--[[list of all lang codes and some settings used in the loop
['lang_code'] = {
rm = setting for the loop to check if lang should have rm,
span = lang code to use in the transcript span if different from base lang code
}
--]]
local lang = {
['zhs'] = { rm = true, span = 'zh-Hans' },
['zht'] = { rm = true, span = 'zh-Hant' },
['ja'] = { rm = true },
['ko'] = { rm = true },
['ru'] = { rm = true },
['th'] = { rm = true }
}
--initialize the table in html syntax and the category variable
local articletable = mw.html.create('table'):addClass('article-table'):newline()
--header row
local tr = articletable:tag('tr')
tr:tag('th'):wikitext('Language')
tr:tag('th'):wikitext(args.name or 'Official Name')
--check if any [lang]_tl exists to show tl column if true
local validTable = false
for _, langCode in ipairs(langOrder) do
if ne(args[prefix .. langCode]) then
if langCode ~= 'en' then validTable = true end
if args[prefix .. 'default_hidden'] or args['default_hidden'] then
if ((ne(args[prefix .. langCode .. '_tl']) or ne(args[prefix .. 'zh_tl'])) and TLcol == false) then
tr:tag('th'):wikitext('Literal Meaning')
TLcol = true
end
else
if ((args[prefix .. langCode .. '_tl'] or args[prefix .. 'zh_tl']) and TLcol == false) then
tr:tag('th'):wikitext('Literal Meaning')
TLcol = true
end
end
end
end
if not validTable then categories:wikitext('[[Category:Empty Other Languages]]') end
--start loop to create the lang rows with langOrder as iterator list to determine the order of the rows
for i, langCode in ipairs(langOrder) do
--variables for ease of use
local Tx = args[prefix .. langCode] or nil
local Tl = args[prefix .. langCode .. '_tl'] or nil
local Rm = args[prefix .. langCode .. '_rm'] or nil
local Loanword = args[prefix .. langCode .. '_lang'] or nil
local Loanword_Tl = args[prefix .. langCode .. '_lang_tl'] or nil
local Note = args[prefix .. langCode .. '_note'] or nil
local Lang = lang[langCode] or {}
--default to pagename if en transcript is not given
if langCode == 'en' then
if Tx then if ie(Tx) then Tx = mw.title.getCurrentTitle().text end else Tx = mw.title.getCurrentTitle().text end
end
--do a check for if transcript for the lang exists and is not blank, move on to next lang if false
if Tx then
if ie(Tx) then
if not noCat[prefix .. langCode] then
categories:wikitext('[[Category:Incomplete Transcripts for Other Languages]][[Category:',string.upper(langCode),' Transcript Missing]]')
end
elseif Tx == '_UNAVAILABLE' then
if not noCat[prefix .. langCode] then
categories:wikitext('[[Category:Unavailable Transcripts for Other Languages]][[Category:',string.upper(langCode),' Unavailable Transcripts]]')
end
else
local tr = articletable:tag('tr')
--open and close "Language" column cell with value and open "Official Name" column cell with transcript
tr:tag('td'):wikitext(i18n:msg(langCode))
local td = tr:tag('td')
local displayTx = Tx
if langCode == 'zhs' or langCode == 'zht' or langCode == 'ja' then
displayTx = Tx
:gsub('·', '・') -- convert halfwidth middle dot to fullwidth middle dot
elseif langCode == 'ko' then
displayTx = KOrm.strip(Tx) -- strip TX from keywords used in Module:Ko-rm
:gsub('·', '・') -- convert halfwidth middle dot to fullwidth middle dot
elseif langCode == 'fr' then
displayTx = Tx
:gsub(' !', ' !') -- add after/before punctuation so it does not break from the text it relates to
:gsub(' %?', ' ?') --
:gsub(' :', ' :') --
:gsub(' ~', ' ~') --
:gsub(' %-', ' -') --
:gsub(' &', ' &') --
:gsub(' »', ' »') --
:gsub('« ', '« ') --
elseif langCode == 'ru' then
displayTx = p.ruBreak(Tx) -- add <wbr> after hyphens as chromium based browsers do not support Russian properly
elseif langCode == 'th' then
displayTx = Tx
:gsub('%.%.%.', '...<wbr>') -- add <wbr> after ellipses as they do not break properly due to not spacing in Thai, making scroll horizontally
elseif langCode == 'de' then
displayTx = Tx
:gsub('%.%.%.', '...<wbr>') -- add <wbr> after ellipses as they do not break properly due to not spacing in German, making scroll horizontally
end
local code = Lang.span or langCode
td:node(SelectiveSpan(displayTx,code,(code == 'vi' and true or false)))
--lang notes next to transcript if corresponding translation parameter is blank or translation column is not shown
--general lang note
if ((ie(Tl) and TLcol) or TLcol == false) then
for _, ref in ipairs(Notes) do
if ref.langs[prefix .. langCode] then
td:wikitext( frame:extensionTag{ name = 'ref', content = ref.ref, args = { name = prefix .. ref.langs.name, group = '•' } } )
end
end
if Notes.reuse[prefix .. langCode] then
td:wikitext( frame:extensionTag{ name = 'ref', args = { name = Notes.reuse[prefix .. langCode], group = '•' } } )
end
end
-- romanization section
if Lang.rm then
--automatic russian romanization through [[Module:Ru-rm]]
if langCode == 'ru' then
local ru_rm = p.CleanTT(mw.text.unstrip(Tx))
ru_rm = require('Module:Ru-rm')._main{ru_rm}
--display romanization only if it differs from transcript
if p.CleanTT(mw.text.unstrip(Tx)) ~= ru_rm then
td:wikitext('<br />'):tag('small'):tag('i'):wikitext(ru_rm)
end
--automatic korean romanization through [[Module:Ko-rm]]
elseif langCode == 'ko' then
local ko_rm = p.CleanTT(mw.text.unstrip(Tx))
local ko_mode = args.ko_mode or '1'
--if manual rm exists, use it, otherwise automatic, and add category if param exists but no manual rm was given
if ko_mode == '2' then
--debug mode, **DO NOT SAVE WITH THIS SETTING, ONLY PREVIEW**
mw.logObject(Tx, 'Raw tx')
mw.logObject(ko_rm, 'Input to ko_rm')
ko_rm = KOrm._main{ko_rm, capi = 1, nn = args[prefix .. 'ko_nn'] or nil, ni = args[prefix .. 'ko_ni'] or nil, bcred = args[prefix .. 'ko_bcred'] or nil}
td:wikitext('<br />Auto-Rm: ['):tag('small'):tag('i'):wikitext(ko_rm):done():wikitext(']')
td:wikitext('<br />Manual-Rm: ['):tag('small'):tag('i'):wikitext((Rm or '')):done():wikitext(']')
elseif (Rm and ne(Rm) and ko_mode == '1') then
td:wikitext('<br />'):tag('small'):tag('i'):wikitext(Rm)
elseif ko_mode == '1' then
ko_rm = KOrm._main{ko_rm, capi = 1, nn = args[prefix .. 'ko_nn'] or nil, ni = args[prefix .. 'ko_ni'] or nil, bcred = args[prefix .. 'ko_bcred'] or nil}
if Rm == '' and not noCat[prefix .. 'ko_rm'] then categories:wikitext('[[Category:KO Romanization Missing]]') end
--display romanization only if it differs from transcript
if mw.text.unstrip(Tx) ~= ko_rm then
td:wikitext('<br />'):tag('small'):tag('i'):wikitext(ko_rm)
end
end
if Rm ~= nil then
ko_rm2 = require('Module:Ko-rm')._main{ko_rm, capi = 1, nn = args[prefix .. 'ko_nn'] or nil, ni = args[prefix .. 'ko_ni'] or nil, bcred = args[prefix .. 'ko_bcred'] or nil}
if not noCat[prefix .. 'ko_rm'] and ne(Rm) then
if Rm == ko_rm2 then
categories:wikitext('[[Category:Korean Manual Romanization Matches Automatic]]')
else
categories:wikitext('[[Category:Korean Manual Romanization Mismatches Automatic]]')
end
end
end
--automatic korean romanization through [[Module:Ja-rm]]
elseif langCode == 'ja' then
local ja_rm = p.CleanTT(mw.text.unstrip(Tx))
ja_rm = require('Module:Ja-rm')._main{ja_rm, errorcat=true}
if ne(Rm) then
-- manual rm
td:wikitext('<br />'):tag('small'):tag('i'):wikitext(Rm)
if ja_rm ~= '' then
categories:wikitext(
'[[Category:Japanese Manual Romanization ',
lib.ternary(string.lower(Rm):gsub('[%s%-\']', '') == string.lower(ja_rm):gsub('%[%[category:.+$', ''):gsub('[%s%-\']', ''), 'Matches', 'Mismatches'),
' Automatic]]'
)
end
elseif ja_rm ~= '' and ja_rm~=Tx then
-- valid automatic rm
td:wikitext('<br />'):tag('small'):tag('i'):wikitext(ja_rm)
end
if ja_rm == '' and Rm == '' and not noCat[prefix .. 'ja_rm'] then categories:wikitext('[[Category:JA Romanization Missing]]') end
elseif Rm and (langCode == 'zhs' or langCode == 'zht') then
td:wikitext('<br />'):tag('small'):tag('i'):tag('span'):attr('lang', 'zh-rm'):wikitext(Rm)
if ie(Rm) and not noCat[prefix .. langCode .. '_rm'] then categories:wikitext('[[Category:',string.upper(langCode),' Romanization Missing]]') end
--general romanization inclusion
elseif Rm then
td:wikitext('<br />'):tag('small'):tag('i'):wikitext(Rm)
if ie(Rm) and not noCat[prefix .. langCode .. '_rm'] then categories:wikitext('[[Category:',string.upper(langCode),' Romanization Missing]]') end
end
end
--translation section
if Tl and TLcol then
local td = tr:tag('td')
--special format for translations which are non-english loanwords
if (Loanword and Loanword_Tl) then
local CODE = mw.loadData('Module:Lang/code')[Loanword] or nil
if CODE and ne(Loanword_Tl) then td:wikitext(Tl, '<br />(<u>', CODE, '</u>: ', Loanword_Tl, ')')
elseif CODE then td:wikitext('<u>', CODE, '</u>: ', Tl) end
if ie(Tl) and not noCat[prefix .. langCode .. '_tl'] then categories:wikitext('[[Category:',string.upper(langCode),' Translation With Missing Loanword Language]]') end
if ie(Loanword_Tl) and not noCat[prefix .. langCode .. '_lang_tl'] then categories:wikitext('[[Category:',string.upper(langCode),' Loanword With Missing Translation]]') end
--special format for translations which are english loanwords
elseif Loanword then
local CODE = mw.loadData('Module:Lang/code')[Loanword] or nil
if CODE then td:wikitext('<u>', CODE, '</u>: ', Tl) end
if ie(Tl) and not noCat[prefix .. langCode .. '_tl'] then categories:wikitext('[[Category:',string.upper(langCode),' Translation With Missing Loanword Language]]') end
--general [lang]_tl formatting
else
td:wikitext(Tl)
end
if ne(Tl) then
for _, ref in ipairs(Notes) do
if ref.langs[prefix .. langCode] then
td:wikitext( frame:extensionTag{ name = 'ref', content = ref.ref, args = { name = prefix .. ref.langs.name, group = '•' } } )
end
end
if Notes.reuse[prefix .. langCode] then
td:wikitext( frame:extensionTag{ name = 'ref', args = { name = Notes.reuse[prefix .. langCode], group = '•' } } )
end
end
if TLcol == true and ie(Tl) and not noCat[prefix .. langCode .. '_tl'] then
categories:wikitext('[[Category:',string.upper(langCode),' Translation Missing]]')
end
--default behaviour if no [lang]_tl but shown "Literal Meaning" column
elseif TLcol then
--special zh_tl when zhs logic
if (args[prefix .. 'zh_tl'] and search({'zhs','zht'},langCode)) then
if ne(args[prefix .. 'zht']) and langCode == 'zhs' then
local td = tr:tag('td')
td:attr('rowspan',2):wikitext(args[prefix .. 'zh_tl'])
for _, ref in ipairs(Notes) do
if ref.langs[prefix .. 'zh'] then
td:wikitext( frame:extensionTag{ name = 'ref', content = ref.ref, args = { name = prefix .. ref.langs.name, group = '•' } } )
end
end
if Notes.reuse[prefix .. 'zh'] then
td:wikitext( frame:extensionTag{ name = 'ref', args = { name = Notes.reuse[prefix .. 'zh'], group = '•' } } )
end
elseif ne(args[prefix .. 'zhs']) and langCode == 'zht' then
-- do nothing
else
local td = tr:tag('td')
td:wikitext(args[prefix .. 'zh_tl'])
for _, ref in ipairs(Notes) do
if ref.langs[prefix .. 'zh'] then
td:wikitext( frame:extensionTag{ name = 'ref', content = ref.ref, args = { name = prefix .. ref.langs.name, group = '•' } } )
end
end
if Notes.reuse[prefix .. 'zh'] then
td:wikitext( frame:extensionTag{ name = 'ref', args = { name = Notes.reuse[prefix .. 'zh'], group = '•' } } )
end
end
if ie(args[prefix .. 'zh_tl']) and not noCat[prefix .. 'zh_tl'] then categories:wikitext('[[Category:ZH Translation Missing]]') end
--default behaviour if "Literal Meaning" column is shown but no [lang]_tl
else
tr:tag('td'):wikitext('—')
end
end
end
end
--end of loop
end
--check for administrative categories
if (args[prefix .. 'default_hidden'] or args['default_hidden']) and TLcol == true then
categories:wikitext('[[Category:TL Parameters Filled In Despite default_hidden Given]]')
end
if args['hide_tl'] or args['multi'] then
categories:wikitext('[[Category:Pages Using Deprecated Template Parameters]]')
end
if ne(args['revise']) then
categories:wikitext('[[Category:Other Languages Revision Requests]]')
end
--return finished table
return articletable
end
function p.Transclude(retArgs, page, og_index, new_index)
local Parser = require('Module:Parser').getTemplateArgs
local frame = mw.getCurrentFrame()
local og_prefix = ''
local new_index = new_index or og_index or 0
if ne(og_index) then
og_prefix = tostring(og_index) .. '_'
end
local params = Parser(page, {only='Other Languages'})
local at_least_one = false
if params == nil then
categories:wikitext('[[Category:Other Languages Invalid Transclusions]]')
return
end
local new_prefix = tostring(new_index) .. '_'
if new_prefix == '0_' then
new_prefix = ''
end
for param, value in pairs(params) do
local retParam = param
if (tonumber(retParam) ~= nil and tonumber(retParam) == new_index+1)
or (retParam == 'Transclude' and new_index == 0)
or (retParam == ('Transclude_' .. tostring(new_index))) then
error('\n[[Category:Other Languages Invalid Transclusions]]Attempted transclusion of a transcluded table, please utilize the page with the original table [possibly: ' .. value .. ' ]')
elseif retParam:find('^%d_') then
retParam = param:gsub('^%d+_', new_prefix, 1)
elseif new_prefix ~= '' then
retParam = new_prefix .. retParam
end
if retArgs[retParam] == nil and (not param:find('revise')) then
if (og_prefix ~= '' and param:find('^' .. og_prefix)) or (og_prefix == '' and (not param:find('^%d+_'))) then
retArgs[retParam] = frame:preprocess(value)
noCat[retParam] = true
at_least_one = true
end
elseif retArgs[retParam] == '{nil}' then
retArgs[retParam] = nil
end
end
if not at_least_one then
categories:wikitext('[[Category:Other Languages Invalid Transclusions]]')
else
categories:wikitext('[[Category:Other Languages Transcluding Tables]]')
end
end
function p.ParseNotes(args)
-- table concat in sentence format
local function join(tab)
if #tab == 0 then return ''
elseif #tab == 1 then return tab[1]
elseif #tab == 2 then return tab[1] .. ' and ' .. tab[2]
else
local last = table.remove(tab, #tab)
result = table.concat(tab, ', ') .. ', and ' .. last
return result
end
end
local parsedNotes = {}
for param, value in pairs(args) do
if type(param) == 'string' and param:find('_note$') and ne(value) then
param = param:gsub('_note$', '')
local note = { ref = {}, langs = { name = param }, prefix = '' }
local prefix = ''
parsedNotes[param] = true
if param:find('^%d+_') then
prefix, param = string.match(param, '^(%d+_)(.-)$')
note.prefix = prefix
note.langs.name = param
end
-- zhs and zht checks as they're different length
if math.fmod(#param, 2) == 1 and param:find('zht') and not param:find('zhs')then
param = param:gsub('zht', '')
note.langs[note.prefix .. 'zht'] = true
table.insert(note.ref, i18n:msg('zht-ref'))
elseif math.fmod(#param, 2) == 1 and param:find('zhs') and not param:find('zht') then
param = param:gsub('zhs', '')
note.langs[note.prefix .. 'zhs'] = true
table.insert(note.ref, i18n:msg('zhs-ref'))
elseif math.fmod(#param, 2) == 0 and param:find('zht') and param:find('zhs') then
param = param:gsub('zht', ''):gsub('zhs', '')
note.langs[note.prefix .. 'zht'] = true
note.langs[note.prefix .. 'zhs'] = true
table.insert(note.ref, i18n:msg('zhs-ref'))
table.insert(note.ref, i18n:msg('zht-ref'))
end
-- rest of langs
for lang in string.gmatch(param, '%w%w') do
note.langs[note.prefix .. lang] = true
table.insert(note.ref, i18n:msg(lang .. '-ref'))
end
-- build ref content and include in return
note.ref = '<b>' .. join(note.ref) .. ':</b> ' .. value
table.insert(Notes, note)
end
end
for param, value in pairs(args) do
if type(param) == 'string' and param:find('_noteName$') and ne(value) and parsedNotes[value] then
Notes.reuse[param:gsub('_noteName$', '')] = value
end
end
end
function p.CleanTT(tx)
local full = tx
local result = tx
for tooltip, display in string.gmatch(full, '<span[^>]+title="([^>]-)">(.-)</span>') do
search_str = '<span[^>]+title="' .. tooltip .. '">(' .. display .. ')</span><span[^>]+><span[^>]+>' .. display .. '</span><span[^>]+>' .. tooltip .. '</span></span>'
result = result:gsub(search_str, display)
end
return result
end
function p.ruBreak(tx)
local split = {}
local allowed = true
--separate the string through unicode codepoints as default lua split cannot handle non-UTF-8 characters
for c in mw.ustring.gcodepoint(tx) do
table.insert(split, mw.ustring.char(c))
end
-- mw.logObject(split,'split') --debug
--separate the split string into ASCII and non-ASCII, include anything inside '<>' as ASCII to not mess with html tags rendering
local loopnum = 1
local html, ref = 0, false
while split[loopnum] do
--check for start of ref tag
if split[loopnum] == '\'' and split[loopnum+1] == '"' and split[loopnum+2] == '`' then
ref = true
end
--check for start of html
if (split[loopnum] == '<' and split[loopnum+1]:find('%w')) then
html = html + 1
end
if (split[loopnum]:find('%-') and html == 0 and ref == false) then
split[loopnum] = '-<wbr>'
end
--check for end of ref tag
if split[loopnum] == '`' and split[loopnum+1] == '"' and split[loopnum+2] == '\'' then
ref = false
end
--check for end of html
if (split[loopnum] == '|' or (split[loopnum] == ']' and split[loopnum+1] == ']')) then
link = false
end
loopnum = loopnum + 1
end
return table.concat(split, '')
end
return p