Jump to content

Module:Other Languages

From The Petit Planet Wiki
Revision as of 13:04, 9 November 2025 by ReisuDesign (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...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module may be created at Module:Other Languages/doc

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('&mdash;')
					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>&nbsp;' .. 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