Documentation for this module may be created at Модул:zh/doc

local M = {}

local m_data = mw.loadData('Module:zh/data')

local py_detone={
	['ā']='a',['á']='a',['ǎ']='a',['à']='a',
	['ō']='o',['ó']='o',['ǒ']='o',['ò']='o',
	['ē']='e',['é']='e',['ě']='e',['è']='e',
	['ī']='i',['í']='i',['ǐ']='i',['ì']='i',
	['ū']='u',['ú']='u',['ǔ']='u',['ù']='u',
	['ǖ']='ü',['ǘ']='ü',['ǚ']='ü',['ǜ']='ü'
};

local pos_aliases_title={
	['n']='Noun', ['pn']='Proper noun', ['propn']='Proper noun', ['pron']='Pronoun', --things related to nouns
	['v']='Verb', ['a']='Adjective', ['adj']='Adjective', ['adv']='Adverb', --other main POSes
	['prep']='Preposition', ['postp']='Postposition', ['conj']='Conjunction', --sentence modifiers
	['part']='Particle', ['suf']='Suffix', --word modifiers
	['prov']='Proverb', ['id']='Idiom', ['ch']='Idiom', ['cy']='Idiom', ['ph']='Phrase', ['intj']='Interjection', --more than one word
	['cl']='Classifier', ['num']='Numeral', ['abb']='Abbreviation', ['deter']='Determiner' --other
};

local pos_aliases_head={
	['n']='noun', ['pn']='proper noun', ['propn']='proper noun', ['v']='verb', ['a']='adj', --main POSes
	['postp']='post', ['conj']='con', ['part']='particle', ['pron']='pronoun',--sentence modifiers and word modifiers
	['prov']='proverb', ['id']='idiom', ['ch']='idiom', ['cy']='idiom', ['ph']='phrase', ['intj']='interj', --more than one word
	['abb']='abbr', ['cl']='classifier', ['deter']='det' --other
};

local function replace_chars(s, tab)
	local output = {}
	for cp in mw.ustring.gcodepoint(s) do
		local ch = mw.ustring.char(cp)
		table.insert(output, tab[ch] or ch)
	end
	return table.concat(output)
end

function M.sortkey_conv(f)
	local rs = type(f) == 'table' and f.args[1] or f
	local ch = mw.ustring.sub(rs,1,1)
	ch = m_data.sortkeys[ch] or ch
	return ch .. mw.ustring.sub(rs,2,mw.ustring.len(rs))
end

function M.py_detone(f)
	local text = type(f) == 'table' and f.args[1] or f
	return replace_chars(text, py_detone)
end

function M.py_transf(f)
	local text = type(f) == 'table' and f.args[1] or f
	if mw.ustring.match(text, '[āōēīūǖ]') then
		text = text .. '1'
	elseif mw.ustring.match(text, '[áóéíúǘ]') then
		text = text .. '2'
	elseif mw.ustring.match(text, '[ǎǒěǐǔǚ]') then
		text = text .. '3'
	elseif mw.ustring.match(text, '[àòèìùǜ]') then
		text = text .. '4'
	end
	text = replace_chars(text, py_detone)
	return text
end

function M.tone_determ(f)
	local text = type(f) == 'table' and f.args[1] or f
	if mw.ustring.match(text, '[āōēīūǖ]') then
		return '1'
	elseif mw.ustring.match(text, '[áóéíúǘ]') then
		return '2'
	elseif mw.ustring.match(text, '[ǎǒěǐǔǚ]') then
		return '3'
	elseif mw.ustring.match(text, '[àòèìùǜ]') then
		return '4'
	else
		return '5'
	end
end

function M.ts_determ(f)
	local text = type(f) == 'table' and f.args[1] or f
	for cp in mw.ustring.gcodepoint(text) do
		local ch = mw.ustring.char(cp)
		if m_data.ts[ch] then return 'trad' end
		if m_data.st[ch] then return 'simp' end
	end
	return 'both'
end

function M.ts(f)
	local text = type(f) == 'table' and f.args[1] or f
	text = replace_chars(text, m_data.ts)
	return text
end

function M.st(f)
	local text = type(f) == 'table' and f.args[1] or f
	text = replace_chars(text, m_data.st)
	return text
end

function M.py(text,comp,pos,p,is_erhua)
	if not is_erhua then is_erhua = false end
	if type(text) == 'table' then text,comp,pos,p,is_erhua = text.args[1],text.args[2],text.args[3],text.args[4],text.args[5] end
	comp = comp or ''
	local q = {}
	local sum = 0
	textconv = M.ts(text)
	len = mw.ustring.len(text)
	if is_erhua then len = len - 1 end
	text = ''
	if comp ~= '' and comp ~= '12' and comp ~= '21' and not is_erhua then
		for i = 1,mw.ustring.len(comp) do
			sum = sum + tonumber(mw.ustring.sub(comp,i,i))
			q[sum] = 'y'
		end
	end
	if not p then p={} for i=1,100 do p[i]='' end end
	for i = 1,len do
		if p[i] ~= '' then --pronunciation supplied
			text = text .. p[i]
		else
			local char = mw.ustring.sub(textconv,i,i)
			char = m_data.py[char] or char
			if i ~= 1 and not is_erhua then
				if char ~= mw.ustring.sub(textconv,i,i) and mw.ustring.sub(textconv,1,1) ~= "'" then
					if mw.ustring.find(char,'^[aoeāōēáóéǎǒěàòè]') then
						char = "'" .. char
					end
				end
			end
			text = text .. char
		end
		if q[i] == 'y' and i ~= len and not is_erhua then text = text .. ' ' end
	end
	if is_erhua == true then text = text .. 'r' end
	if pos == 'pn' or pos == 'propn' then
		characters = mw.text.split(text,' ')
		for i=1,#characters do
			characters[i] = mw.language.getContentLanguage():ucfirst(characters[i])
		end
		text = table.concat(characters,' ')
	end
	return text
end

function M.py_er(text,comp,pos,p)
	return M.py(text,comp,pos,p,true)
end

function M.pytemp(text,comp,pos,p,is_erhua)
	if not is_erhua then is_erhua = false end
	if type(text) == 'table' then text,comp,pos = text.args[1],text.args[2],text.args[3] or 'n' end
	comp = comp or ''
	local q = {}
	local sum = 0
	textconv = M.ts(text)
	len = mw.ustring.len(text)
	if is_erhua == true then
		len = len - 1
		textconv = mw.ustring.sub(textconv,1,len)
	end
	text = ''
	if comp ~= '' and comp ~= '12' and comp ~= '21' and not is_erhua then
		for i = 1,mw.ustring.len(comp) do
			sum = sum + tonumber(mw.ustring.sub(comp,i,i))
			q[sum] = 'y'
		end
	end
	if not p then p={} for i=1,20 do p[i]='' end end
	for i = 1,len do
		if p[i] ~= '' then --pronunciation supplied
			text = text .. p[i]
		else
			local char = mw.ustring.sub(textconv,i,i)
			if mw.ustring.find(char,'[一不期績绩蹟跡迹嵌框微突帆藩擊击夾夹鞠拈夕汐昔惜息危椰濤涛叔寂馴驯築筑質质播究菌矻識识穴膜餾馏企辱署偽伪蹈諷讽斂敛坊樸朴儲储剖檔档髮轍辙賜赐堤壑酵括懾慑蝸蜗淆攜携崖癌暫暂蟄蛰驟骤液血酪嘌]') then
				text = text .. char
			else
				char = m_data.py[char] or char
				if i ~= 1 and mw.ustring.find(char,'^[aoeāōēáóéǎǒěàòè]') then
					char = "'" .. char
				end
				text = text .. char
			end
		end
		if q[i] == 'y' and i ~= len and not is_erhua then text = text .. ' ' end
	end
	text = mw.ustring.gsub(text," '"," ")
	if pos == 'pn' or pos == 'propn' then
		characters = mw.text.split(text,' ')
		for i=1,#characters do
			characters[i] = mw.language.getContentLanguage():ucfirst(characters[i])
		end
		text = table.concat(characters,' ')
	end
	return text
end

function M.pytemp_er(text,comp,pos,p)
	return M.pytemp(text,comp,pos,p,true)
end

function M.pywordconv(text,p)
	if type(text) == 'table' then text = text.args[1] end
	textconv = M.ts(text)
	len = mw.ustring.len(text)
	text = ''
	if not p then p={} for i=1,20 do p[i]='' end end
	for i = 1,len do
		if p[i] ~= '' then
			text = text .. M.py_transf(p[i])
		else
			char = mw.ustring.sub(textconv,i,i)
			cpy = m_data.py[char] or char
			text = text .. M.py_transf(cpy)
		end
	end
	return text
end

function M.pywordconv_er(text,p)
	if type(text) == 'table' then text = text.args[1] end
	len = mw.ustring.len(text) - 1
	textconv = mw.ustring.sub(M.ts(text),1,len)
	text = ''
	if not p then p={} for i=1,20 do p[i]='' end end
	for i = 1,len do
		if p[i] ~= '' then
			if i == len then p[i] = p[i] .. 'r' end
			text = text .. M.py_transf(p[i])
		else
			char = mw.ustring.sub(textconv,i,i)
			cpy = m_data.py[char] or char
			if i == len then cpy = cpy .. 'r' end
			text = text .. M.py_transf(cpy)
		end
	end
	return text
end

function M.decomp(text,comp)
	if type(text) == 'table' then text,comp = text.args[1],text.args[2] or '' end
	comp = comp or tostring(mw.ustring.len(text))
	local num = tonumber(comp)
	char = mw.ustring.sub(text,num,num)
	return char
end

function M.compdecomp(title,comp)
	if type(title) == 'table' then title,comp = title.args[1],title.args[2] end
	comp = comp or ''
	local start = 1
	local finish = 1
	local sum = 0
	local text = ''
	local p={}
	textlen = mw.ustring.len(title)
	if comp == '' then
		for i = 1,textlen do
			comp = comp .. '1'
		end
	end
	for i = 1,mw.ustring.len(comp) do
		p[i] = tonumber(mw.ustring.sub(comp,i,i))
		sum = sum + p[i]
	end
	if sum ~= textlen then
		comp = ''
		for j = 1,textlen do
			p[j] = tonumber(1)
			comp = comp .. '1'
		end
	end
	for i = 1,mw.ustring.len(comp) do
		if i ~= 1 then start = start + p[i-1] end
		finish = start + p[i] - 1
		text = (text .. '[[' .. mw.ustring.sub(title,start,finish) .. ']]')
	end
	return text
end

function M.compdecompetym(title,comp)
	if type(title) == 'table' then title,comp = title.args[1],title.args[2] end
	comp = comp or ''
	local start = 1
	local finish = 1
	local sum = 0
	local text = ''
	local p={}
	textlen = mw.ustring.len(title)
	if comp == '' then
		for i = 1,textlen do
			comp = (comp .. '1')
		end
	end
	for i = 1,mw.ustring.len(comp) do
		p[i] = tonumber(mw.ustring.sub(comp,i,i))
		sum = sum + p[i]
	end
	if sum ~= textlen then
		comp = ''
		for j = 1,textlen do
			p[j] = tonumber(1)
			comp = (comp .. '1')
		end
	end
	for i = 1,mw.ustring.len(comp) do
		if i ~= 1 then start = start + p[i-1] end
		finish = start + p[i] - 1
		if i ~= 1 then text = (text .. '|') end
		text = (text .. mw.ustring.sub(title,start,finish))
	end
	return text
end

function M.hzbox(title,comp)
	if type(title) == 'table' then title,comp = title.args[1],title.args[2] end
	local id = M.ts_determ(title)
	local text = '{{zh-forms'
	if id == 'simp' then
		text = text .. '|t=' .. M.st(title)
	elseif id == 'trad' then
		text = text .. '|s=' .. M.ts(title)
	end
	text = text .. ((comp and comp ~= "") and ('|type=' .. comp) or '')
	return text .. '}}'
end

function M.hzbox_er(title)
	if type(title) == 'table' then title = title.args[1] end
	len = mw.ustring.len(title)
	if mw.ustring.sub(title,len,len) == '兒' then id = 'trad' else id = 'simp' end
	title = mw.ustring.sub(title,1,len-1)
	text = '{{zh-hanzi-box|'
	if id == 'simp' then
		text = (text .. '[[' .. title .. ']][[儿]]|[[' .. M.st(title) .. '兒]]}}')
	else
		text = (text .. '[[' .. M.ts(title) .. '儿]]|[[' .. title .. ']][[兒]]}}')
	end
	return text
end

function M.sort(title)
	if type(title) == 'table' then title = title.args[1] end
	local text = ''
	len = mw.ustring.len(title)
	title = M.ts(title)
	for i = 1,len do
		charpy = mw.ustring.sub(title,i,i)
		charpy = m_data.py[charpy] or charpy
		text = text .. M.py_transf(charpy)
	end
	return text
end

function M.postitle(pos)
	pos = pos or ''
	if pos == '' then pos = 'n' end
	return pos_aliases_title[pos] or pos
end

function M.poshead(pos)
	pos = pos or ''
	if pos == '' then pos = 'n' end
	return pos_aliases_head[pos] or pos
end

function M.skeys(title)
	if type(title) == 'table' then title = title.args[1] end
	text = mw.ustring.sub(title,1,1)
	text = m_data.skeys[text] or text
	return text
end

function M.chardecomp(title)
	if type(title) == 'table' then title = title.args[1] end
	text = mw.text.split(title,"")
	return table.concat(text,"|")
end

function M.semantics(text,sem1,sem2,name)
	if sem1 ~= '' then
		text = (text .. '\n\n====' .. name .. '====\n* {{zh-l|' .. sem1 .. '}}')
		if sem2 ~= '' then
			text = (text .. '\n* {{zh-l|' .. sem2 .. '}}')
		end
	end
	return text
end

function M.create_er(f)
	return M.create(f,true)
end

local function checkpos(pos)
	for poscode,posname in pairs(pos_aliases_head) do
		if pos == posname then
			return poscode
		end
	end
	for poscode,posname in pairs(pos_aliases_title) do
		if pos == posname then
			return poscode
		end
	end
	return pos
end

function M.headword(title,comp,pos,is_erhua)
	if not is_erhua then is_erhua = false end
	is_table = (type(title) == 'table')
	p = {}
	for i=4,23 do table.insert(p,(is_table and title.args[i] or '')) end
	if type(title) == 'table' then title,comp,pos = title.args[1],title.args[2],title.args[3] end
	text = '{{zh-' .. M.poshead(pos) .. '|'
	id = M.ts_determ(title)
	if id == 'both' then text = text .. 'ts' elseif id == 'simp' then text = text .. 's' else text = text .. 't' end
	if is_erhua then
		text = text .. '|pin=' .. M.py_er(title,comp,pos,p) .. '|pint=' .. M.pywordconv_er(title,p)
		if id == 'simp' then
			text = text .. '|tra=' .. M.st(title) .. '|sim=' .. title
		else
			text = text .. '|tra=' .. title .. '|sim=' .. M.ts(title)
		end
		text = text .. '}}\n\n# {{erhua form'
		if def ~= '' then text = text .. '|' .. def end
	else
		text = text .. '|pin=' .. M.py(title,comp,pos,p) .. '|pint=' .. M.pywordconv(title,p)
		if id == 'simp' then
			text = text .. '|tra=' .. M.st(title) .. '|sim=' .. title
		elseif id == 'trad' then
			text = text .. '|tra=' .. title .. '|sim=' .. M.ts(title)
		end
	end
	return text .. '}}'
end

function M.link(frame)
	local args = frame:getParent().args
	if args[2] and mw.ustring.match(args[2], '[一-龯㐀-䶵]') then
		gloss = args[4] or ''
		tr = args[3] or ''
		text = args[1] .. '/' .. args[2]
	else
		text = args[1] or ''
		if args[2] and (mw.ustring.match(args[2], '[%[%]]') or mw.ustring.match(args[2], '[āōēīūǖáóéíúǘǎǒěǐǔǚàòèìùǜâêîôû̍ⁿ]') or mw.ustring.match(args[2], '[bcdfghjklmnpqrstwz]h?y?[aeiou][aeiou]?[iumnptk]?g?[1-9]')) then
			tr = args[2] or ''
			gloss = args[3] or ''
		else
			tr = ''
			gloss = args[2] or ''
		end
	end
	if args['tr'] and args['tr'] ~= '' then
		tr = args['tr']
		gloss = args[2] or ''
	end
	if text ~= '' and not text:match('[%[%]]') then
		word = mw.text.split(text,"/",true)
		if #word == 1 and M.ts_determ(word[1]) == 'trad' and not mw.ustring.match(word[1], '%*') then
			table.insert(word, M.ts(word[1]))
		end
		for i = 1,#word do
			word[i] = mw.ustring.gsub(word[i], '%*', '')
			word[i] = '<span class="Hani" lang="zh">[[' .. word[i] .. '#Chinese|' .. word[i] .. ']]</span>'
		end
		text = table.concat(word,"/")
	end
	if tr ~= '' or gloss ~= '' then
		text = text .. ' ('
		if tr ~= '' then
			text = text .. tr
			if gloss ~= '' then
				text = text .. ', '
			end
		end
		if gloss ~= '' then
			text = text .. '"' .. gloss .. '"'
		end
		text = text .. ')'
	end
	return text
end

function M.check_pron(text, variety, length)
	if type(text) == 'table' then text, variety = text.args[1], text.args[2] end
	if not text then
		return
	end
	startpoint, address = { ['yue'] = 51, ['hak'] = 19968, ['nan'] = 19968 }, { ['yue'] = 'Jyutping_word/%03d', ['hak'] = 'hak-pron/%02d', ['nan'] = 'nan-pron/%03d' }
	unit = 1000
	first_char = mw.ustring.sub(text, 1, 1)
	codepoints = { ['simp'] = mw.ustring.codepoint(first_char), ['trad'] = mw.ustring.codepoint(M.st(first_char)) }
	texts = { ['simp'] = text, ['trad'] = M.st(text) }
	local result = false
	for identity, codepoint in pairs(codepoints) do
		if length == 1 and variety == "yue" then
			success, data = pcall(mw.loadData, 'Module:zh/data/Jyutping character')
		else
			page_index = math.floor((codepoint - startpoint[variety]) / unit)
			success, data = pcall(mw.loadData,
				('Module:zh/data/' .. address[variety]):format(page_index)
			)
		end
		if success then
			result = data[texts[identity]] or false
		else
			result = false
		end
		if result then
			return result
		end
	end
	return result
end

function M.nan_for_bot()
	text = mw.title.getCurrentTitle().text
	result = M.check_pron(text, 'nan')
	if result then
		return '\n|mn=' .. result
	else
		return
	end
end

function M.create(f,is_erhua)
	if not is_erhua then is_erhua = false end
	local title = f.args[1] or ""
	local comp = f.args[2] or ""
	local pos = f.args[3] or ""
	local def = f.args[4] or ""
	local etym1 = f.args[5] or ""
	local etym2 = f.args[6] or ""
	local etym3 = f.args[7] or ""
	local etym4 = f.args[8] or ""
	local pos2 = f.args[9] or ""
	local def2 = f.args[10] or ""
	local ko = f.args[11] or ""
	local kotrans = f.args[12] or ""
	local kodef = f.args[13] or ""
	local vi = f.args[14] or ""
	local videf = f.args[15] or ""
	p = {}
	for i=16,54 do
		if i<24 or i>42 then
			table.insert(p, f.args[i] or "")
		end
	end
	local etym = f.args[24] or ""
	local syn = f.args[25] or ""
	local ant = f.args[26] or ""
	local der = f.args[27] or ""
	local also = f.args[28] or ""
	local syn2 = f.args[29] or ""
	local ant2 = f.args[30] or ""
	local der2 = f.args[31] or ""
	local also2 = f.args[32] or ""
	local wp = f.args[33] or ""
	local cat = f.args[34] or ""
	local pic = f.args[35] or ""
	local piccap = f.args[36] or ""
	local er = f.args[37] or ""
	local tl = f.args[38] or ""
	local audio = f.args[39] or ""
	local alt = f.args[40] or ""
	local alt2 = f.args[41] or ""
	local alt3 = f.args[42] or ""
	local c = f.args[55] or ""
	local mn = f.args[56] or ""
	local w = f.args[57] or ""
	local m = f.args[58] or ""
	local h = f.args[59] or ""
	local md = f.args[60] or ""
	local mc = f.args[61] or ""
	local oc = f.args[62] or ""
	text = ''
	if pos == '' then pos = 'n' end
	pos = checkpos(pos)
	if pos2 ~= '' then pos2 = checkpos(pos2) end
	text = (text .. '==Chinese==\n')
	if M.ts_determ(title) == 'simp' then
		return text .. '{{zh-see|' .. M.st(title) .. ('}}\n\n[[zh:%s]]'):format(mw.title.getCurrentTitle().text)
	end
	length = mw.ustring.len(title)
	noerhua = mw.ustring.sub(title,1,length-1)
	erhua = mw.ustring.sub(title,length,length)
	text = text .. (is_erhua and M.hzbox_er(title) or M.hzbox(title,comp))
	if wp ~= '' then text = (text .. '\n{{wikipedia|lang=zh}}') end
	if pic ~= '' then text = (text .. '\n[[File:' .. pic .. '|thumb|250px') if piccap ~= '' then text = (text .. '|' .. piccap) end text = (text .. ']]')	end
	if is_erhua then
		text = (text .. '\n\n===Etymology===\n{{zh-compound|' .. noerhua .. '|' .. erhua .. '|')
		if def ~= '' then text = text .. def end
		text = (text .. "|''diminutive suffix''}}\n\n")
		text = (text .. '===Pronunciation===\n{{zh-pron\n\|m=' .. M.pytemp_er(title,comp,pos,p) .. 'r\n|cat=' .. pos)
		if pos2 ~= '' then text = (text .. ',' .. pos2) end
		text = (text .. '\n}}\n\n')
	else
		text = (text .. '\n\n')
		if alt ~= '' then
			text = (text .. '===Alternative forms===\n* {{zh-l|' .. alt .. '}}')
			if alt2 ~= '' then
				text = (text .. '\n* {{zh-l|' .. alt2 .. '}}')
				if alt3 ~= '' then
					text = (text .. '\n* {{zh-l|' .. alt3 .. '}}')
				end
			end
			text = (text .. '\n\n')
		end
		if etym ~= '' then text = (text .. '===Etymology===\n') end
		if etym1 ~= '' then text = (text .. '===Etymology===\n') end
		if etym1 ~= '' then
			text = (text .. '{{zh-compound|' .. M.compdecompetym(title,comp) .. '|' .. etym1)
			if etym2 ~= '' then text = text .. '|' .. etym2 end
			if etym3 ~= '' then text = text .. '|' .. etym3 end
			if etym4 ~= '' then text = text .. '|' .. etym4 end
			text = (text .. '}}\n\n')
		end
		if etym ~= '' then text = (text .. etym .. '\n\n') end
		text = (text .. '===Pronunciation===\n{{zh-pron')
		if m ~= '-' then
			if m ~= '' then
				m_pron = m
				text = (text .. '\n|m=' .. m_pron)
			else
				m_pron = mw.ustring.gsub(M.pytemp(title,comp,pos,p), ',', ', ')
				text = (text .. '\n|m=' .. m_pron)
				if er ~= '' then text = (text .. ',er=' .. er) end
				if tl ~= '' then text = (text .. ',tl=y') end
			end
		end
		if c == '' then c = M.check_pron(title, 'yue', length) or '' end
		if length == 1 or (c ~= '' and c ~= '-') then text = (text .. '\n|c=' .. (c or "")) end
		if h == '' then h = M.check_pron(title, 'hak') or '' end
		if length == 1 or (h ~= '' and h ~= '-') then text = (text .. '\n|h=pfs=' .. (h or "")) end
		if length == 1 or md ~= '' then text = (text .. '\n|md=' .. (md or "")) end
		if mn == '' then mn = M.check_pron(title, 'nan') or '' end
		if length == 1 or (mn ~= '' and mn ~= '-') then text = (text .. '\n|mn=' .. (mn or "")) end
		if length == 1 or w ~= '' then text = (text .. '\n|w=' .. (w or "")) end
		if audio ~= '' then text = (text .. '\n|ma=') if audio ~= 'y' then text = (text .. audio) else text = (text .. 'y') end end
		if length == 1 or mc ~= '' then text = (text .. '\n|mc=' .. (mc ~= "" and mc or 'y')) end
		if length == 1 or oc ~= '' then text = (text .. '\n|oc=' .. (oc ~= "" and oc or 'y')) end
		text = (text .. '\n|cat=' .. pos)
		if pos2 ~= '' then text = (text .. ',' .. pos2) end
		text = (text .. '\n}}\n\n')
	end
	text = (text .. '===' .. (length == 1 and "Definitions" or M.postitle(pos)) .. '===\n')
	text = (text .. '{{zh-' .. (length == 1 and "hanzi" or M.poshead(pos)) .. '}}\n\n')
	if is_erhua then
		text = text .. '# {{context|Mandarin|lang=zh}} {{erhua form'
		if def ~= '' then text = text .. '|' .. def end
		text = text .. '}}'
	else
		text = (text .. '# ' .. (def ~= "" and def or "{{rfdef|lang=zh}}"))
	end
	text = M.semantics(text,syn,syn2,'Synonyms')
	text = M.semantics(text,ant,ant2,'Antonyms')
	text = M.semantics(text,der,der2,'Derived terms')
	if pos2 ~= '' then
		text = text .. '\n\n===' .. M.postitle(pos2) .. '===\n'
		text = text .. '{{zh-' .. M.poshead(pos2) .. '}}\n\n'
		if is_erhua then
			text = text .. '# {{context|Mandarin|lang=zh}} {{erhua form'
			if def2 ~= '' then text = text .. '|' .. def2 end
			text = text .. '}}'
		else
			text = text .. '# ' .. def2
		end
	end
	if also ~= '' then text = (text .. '\n\n===See also===\n* {{zh-l|' .. also .. '}}')
		if also2 ~= '' then text = (text .. '\n* {{zh-l|' .. also2 .. '}}') end
	end
	if cat ~= '' then text = (text .. '\n\n\{\{zh-cat\|' .. cat .. '\}\}') end
	if ko ~= '' then
		text = text .. '\n\n----\n\n==Korean==\n{{ko-hanjatab}}\n\n===Noun===\n{{ko-noun|hj|hangeul=' .. ko .. '}}\n\n# {{hanja form of|' .. ko .. '|' .. kodef .. '}}'
	end
	if vi ~= '' then
		text = text .. '\n\n----\n\n==Vietnamese==\n{{vi-hantutab}}\n\n===' .. M.postitle(pos) .. '===\n{{vi-hantu}}\n\n# {{han tu form of|' .. vi .. '|' .. videf .. '}}'
	end
	if not mw.title.getCurrentTitle().exists then
		text = text .. ('\n\n[[zh:%s]]'):format(mw.title.getCurrentTitle().text)
	end
	return text
end

return M