local m_zh = require("Module:zh")
local find = mw.ustring.find
local gsub = mw.ustring.gsub
local match = mw.ustring.match
local sub = mw.ustring.sub
-- Use this when the actual title needs to be known.
local actual_title = mw.title.getCurrentTitle()
-- Use this when testcases need to be able to override the title (for bolding,
-- for instance).
local title = actual_title
local PAGENAME = PAGENAME or title.text
local export = {}
local data = mw.loadData("Module:zh-usex/data")
local variety_list = data.variety_list
local punctuation = data.punctuation
local ref_list = data.ref_list
local pron_correction = data.pron_correction
local polysyllable_pron_correction = data.polysyllable_pron_correction
local zh_format_start_simp = "<span lang=\"zh\" class=\"Hans\">"
local zh_format_start_trad = "<span lang=\"zh\" class=\"Hant\">"
local zh_format_end = "</span>"
local Han_pattern = '[一-鿌㐀-䶵𠀀-]'
local UTF8_char = '[%z\1-\127\194-\244][\128-\191]*'
local tag = "%b<>"
local function make_link(word)
local orig_word = word
word = "[[" .. word .. "]]"
-- Replace "-" with "]][[" between Han characters (optionally with a HTML
-- tag between the Han character and the hyphen). This would be simpler with
-- regex or LPeg.
for i = 1, 2 do
word = word:gsub("()(" .. UTF8_char .. ")%-()(" .. UTF8_char .. ")",
function (pos1, before, pos2, after)
if (before == ">"
and find(word:sub(1, pos1), Han_pattern .. tag .. "$")
or find(before, Han_pattern))
and (after == "<"
and find(word:sub(pos2), "^" .. tag .. Han_pattern)
or find(after, Han_pattern)) then
return before .. "]][[" .. after
end
end)
end
-- If an entire word is bolded in a link, move the tags out of the wikilink syntax.
word = word
:gsub("(%[%[)(</?b>)(.-)(</?b>)(%]%])", "%2%1%3%5%4")
-- Move br tags out of links.
:gsub("(%[%[)(<br ?/?>)", "%2%1")
-- Link to Chinese section.
-- Remove bolding from link target, leave it in link text.
:gsub("%[%[([^|]-)%]%]",
function (word)
return "[[" .. word:gsub("</?b>", "") .. "#Chinese|" .. word .. "]]"
end)
if actual_title.nsText == "Module" then
mw.log(orig_word, "->", word)
end
return word
end
function export.show(frame)
local params = {
[1] = { required = true }, -- example
[2] = {}, -- translation
[3] = {}, -- variety
lit = {},
tr = {},
ref = {}, r = { alias_of = "ref" },
display_type = {}, type = { alias_of = "display_type" },
inline = {},
audio = {}, a = { alias_of = "audio" },
collapsed = { type = "boolean" },
link = { type = "boolean", default = true }, l = { alias_of = "link" },
-- Allow specifying pagename in testcases on documentation page.
pagename = actual_title.nsText == "Module" and {} or nil,
tr_nocap = { type = "boolean" },
}
local args, unrecognized_args = require("Module:parameters").process(frame:getParent().args, params, true)
if args.pagename then
-- Override title in Module namespace.
title = mw.title.new(args.pagename)
PAGENAME = title.text
end
local example = args[1] or error("Example unspecified.")
local translation = args[2]
local literal = args["lit"]
local reference = args["ref"]
local manual_tr = args["tr"]
local display = args["display_type"]
local inline = args["inline"]
local audio_file = args["audio"]
local collapsed = args["collapsed"]
local phonetic = ""
local original_length = mw.ustring.len(gsub(example, "[^一-龯㐀-䶵]", ""))
local variety = args[3] or (ref_list[reference] and ref_list[reference][1] or false) or "MSC"
local variety_data = variety_list[variety] or error("variety " .. variety .. " not recognized.")
local variety_code
if variety_data then
variety_code = variety_data[2]
end
local link = args["link"]
-- link = match(link, "n") == nil -- and not (not match(example, " ") and match(example, "[,。?!﹑]"))
if next(unrecognized_args) then
--[[Special:WhatLinksHere/Template:tracking/zh-usex/unrecognized arg]]
require("Module:debug").track_unrecognized_args(unrecognized_args, "zh-usex")
end
if not translation or translation == '' then -- per standard [[Module:usex]]
translation = '<small>(tolong tambah terjemahan bahasa Melayu untuk contoh ini)</small> [[Kategori:Permintaan untuk terjemahan contoh penggunaan bahasa Cina]]'
end
if not match(example, "'''") then boldify = true end
-- automatically boldify pagetitle if nothing is in bold
if boldify and not punctuation[PAGENAME] then
example = gsub(example, PAGENAME, "'''" .. PAGENAME .. "'''")
example = gsub(example, "''''''", "")
end
-- tidying up the example, making it ready for transcription
example = gsub(example, "([?!,。、“”…;:‘’|()「」『』—《》〈〉· .~])", " %1 ")
example = gsub(example, " — — ", " —— ") -- double em-dash (to be converted to single em-dash later)
example = gsub(example, "^ *", "")
example = gsub(example, " *$", "")
example = gsub(example, " +", " ")
example = gsub(example, "%'%'%'([^%']+)%'%'%'", "<b>%1</b>")
example = gsub(example, "(.)</b>%[([^%[%]]+)%]", function(first, second)
return "<b>"..first.."</b>" ~= second and first.."["..second.."]</b>" or first.."["..first.."]</b>" end)
example = gsub(example, "</b>({[^{}]+})", "%1</b>")
local ruby_start, ruby_mid, ruby_end = "<big><ruby><span class=\"Hani\" style=\"display: inline-flex; flex-direction: column;\">", "</span><rp> (</rp><rt><big>", "</big></rt><rp>)</rp></ruby></big>"
local ruby_words = {}
local trad_words, simp_words, tr_words = {}, {}, {}
simp_exist = (m_zh.ts_determ(gsub(example, "(.)%[%1%]", "")) == "trad" or (match(example, "%[[^%[%]]+%]") and not match(example, "(.)%[%1%]"))) and variety_code ~= "vi"
for word in mw.text.gsplit(example, " ", true) do
if gsub(gsub(word, "%{[^%}]+%}", ""), "%.", "") == PAGENAME and boldify then
word = "<b>" .. word .. "</b>"
end
local trad_word, simp_word, tr_word, ruby_word = word, false, false, ""
-- various tricks for linking and display in trad. and simp.
trad_word = gsub(trad_word, "(.)%[(.)%]", "%1")
trad_word = gsub(trad_word, "{[^{}]*}", "")
trad_word = gsub(trad_word, "[%^%.]", "")
trad_word = gsub(trad_word, "\\", "|")
trad_word = gsub(trad_word, ".", ".")
if simp_exist then
simp_word = match(word, "%[") and gsub(gsub(word .. "占[位]", "([^%[%]]*).%[(.)%]", function(a, b) return m_zh.ts(a) .. b end), "位$", "") or m_zh.ts(word)
simp_word = gsub(simp_word, "{[^{}]*}", "")
simp_word = gsub(simp_word, "[%^%.]", "")
simp_word = gsub(simp_word, "\\", "|")
simp_word = gsub(simp_word, ".", ".")
end
-- produce links
local contain_pagename = (gsub(gsub(gsub(trad_word, "</?b>", ""), "%^", ""), "-", "") == PAGENAME) and not punctuation[PAGENAME]
if match(trad_word, "|") or (link and not match(trad_word, "@") and not punctuation[word] and not contain_pagename) then
trad_word = make_link(trad_word)
if simp_exist then
simp_word = make_link(simp_word)
end
end
trad_word = gsub(trad_word, "@", "")
simp_word = simp_exist and gsub(simp_word, "@", "")
-- same tricks applied to transcription
if not manual_tr and (variety_code == "cmn" or variety_code == "yue" or variety_code == "nan" or variety_code == "hak") then
if punctuation[word] then
tr_word = punctuation[word]
else
real_word = true
local hyphen = variety_code == "nan" or variety_code == "hak"
tr_word = gsub(word, "@", "")
tr_word = gsub(tr_word, "%.", " ")
tr_word = gsub(tr_word, ".+\\", "")
tr_word = gsub(tr_word, "%[[^%[%]]+%]", "")
tr_word = gsub(tr_word, ".</b>(%{[^%}]+%})", "%1</b>")
tr_word = gsub(tr_word, "(.){([^{}]*)}",function(a, b)
if hyphen and not mw.ustring.find(a, "[a-zA-Z]") then
return "-" .. b .. "-"
else
return b
end
end)
for key,val in pairs(polysyllable_pron_correction[variety_code]) do
tr_word = gsub(tr_word, key, val)
end
tr_word = gsub(tr_word, ".", pron_correction[variety_code])
if variety_code == "cmn" then
tr_word = gsub(tr_word, "%-", "")
tr_word = m_zh.py(tr_word)
elseif variety_code == "yue" then
local m_yue_pron = mw.loadData("Module:zh/data/yue-pron")
tr_word = gsub(tr_word, ".", m_yue_pron.jyutping)
tr_word = gsub(tr_word, "([a-z])([1-9])(-?)([1-9]?)", "%1%2%3%4 ")
elseif hyphen then
tr_word = gsub(tr_word, "[一-鿌㐀-䶵 -〿𠀀-]+", function(text)
if m_zh.check_pron(text, variety_code, 1) then
return gsub(m_zh.check_pron(text, variety_code, 1), "/.+$", "")
else
text = gsub(text, ".", function(ch)
if m_zh.check_pron(ch, variety_code, 1) then
return gsub(m_zh.check_pron(ch, variety_code, 1), "/.+$", "") .. "-"
else
return ch
end
end)
return gsub(text, "-$", "")
end
end)
tr_word = gsub(tr_word, "%-+", "-")
tr_word = gsub(tr_word, "%-([^ⁿa-záíúéóḿńàìùèòǹâîûêôāīūēōṳA-ZÁÍÚÉÓḾŃÀÌÙÈÒǸÂÎÛÊÔĀĪŪĒŌṲ])", "%1")
tr_word = gsub(tr_word, "([^ⁿa-záíúéóḿńàìùèòǹâîûêôāīūēōoóòôōṳA-ZÁÍÚÉÓḾŃÀÌÙÈÒǸÂÎÛÊÔĀĪŪĒŌOÓÒÔŌṲ̄̀́̂̍͘])%-", "%1")
tr_word = gsub(tr_word, "<b>", "-<b>")
tr_word = gsub(tr_word, "</b>", "</b>-")
tr_word = gsub(tr_word, "%^%-<b>", "<b>^")
tr_word = gsub(tr_word, "^%-+", "")
tr_word = gsub(tr_word, "%-+$", "")
tr_word = gsub(tr_word, "%%%-?", "--")
end
if match(tr_word, "[一-鿌㐀-䶵𠀀-]") then
require("Module:debug").track("zh-usex/character without transliteration")
end
end
end
if variety_code == "nan" then
trad_word = gsub(trad_word, "%%", "")
simp_word = simp_exist and gsub(simp_word, "%%", "")
end
if display == "ruby" then
ruby_word = ruby_start .. trad_word .. (simp_exist and "<br>" .. simp_word or "") .. ruby_mid .. (real_word and tr_word or "") .. ruby_end
table.insert(ruby_words, ruby_word)
else
table.insert(trad_words, trad_word)
table.insert(simp_words, simp_word or nil)
table.insert(tr_words, tr_word or nil)
end
end
local tag_start = " <span style=\"color:darkgreen; font-size:x-small;\">[" -- HTML entity since "[[[w:MSC|MSC]]" is interpreted poorly
local tag_end = "]</span>"
if display == "ruby" then
tag = " <ruby><rb><big>" ..
tag_start .. variety_data[1] ..
(simp_exist
and ", ''[[Traditional Chinese|trad.]]''↑ + ''[[Simplified Chinese|simp.]]''↓"
or ", ''[[Traditional Chinese|trad.]]'' and ''[[Simplified Chinese|simp.]]''") .. tag_end ..
tag_start .. "''rom.'': " .. variety_data[3] .. tag_end ..
"</big></rb></ruby>"
return table.concat(ruby_words, "") .. tag .. "<dl><dd><i>" .. translation .. "</i></dd></dl>"
else
trad_text = gsub(table.concat(trad_words), "([a-zA-Z]%]%])(%[%[[a-zA-Z])", "%1 %2")
simp_text = simp_exist and gsub(table.concat(simp_words), "([a-zA-Z]%]%])(%[%[[a-zA-Z])", "%1 %2") or false
phonetic = manual_tr or (#tr_words > 0 and table.concat(tr_words, " ") or false)
-- overall transcription formatting
if phonetic then
phonetic = gsub(phonetic, " </b>", "</b> ")
phonetic = gsub(phonetic, " ", " ")
if variety_code == "yue" or variety_code == "zhx-tai" or variety_code == "zhx-teo" or variety_code == "nan-hai" or variety_code == "cmn-sze" then
phonetic = gsub(phonetic, "([a-zê]+)([1-9%-]+)", "%1<sup>%2</sup>") -- superscript tones
end
phonetic = gsub(phonetic, " ([,%.?!;:’”)])", "%1") -- remove excess spaces from punctiation
phonetic = gsub(phonetic, "([‘“(]) ", "%1")
if not manual_tr then
phonetic = gsub(phonetic, "%'([^%'])", "%1") -- allow bolding for manual translit
if variety_code == "nan" then
phonetic = gsub(phonetic, " +%-%-", "--")
end
end
-- capitalisation
if not args.tr_nocap and match(example, "[。?!]") then
phonetic = "^" .. gsub(phonetic, "([%.?!]) ", "%1 ^")
end
phonetic = gsub(phonetic, "([%.%?%!][”’]) (.)", "%1 ^%2")
phonetic = gsub(phonetic, "<br>(.)", "<br>^%1")
phonetic = gsub(phonetic, ": ([“‘])(.)", ": %1^%2")
phonetic = gsub(phonetic, "%^<b>", "<b>^")
phonetic = gsub(phonetic, "%^+.", mw.ustring.upper)
phonetic = gsub(phonetic, "%^", "")
if variety_code == "wuu" then
local wuu_pron = require("Module:wuu-pron")
phonetic = "<span class=\"IPA\">[" .. wuu_pron.ipa_conv(phonetic) .. "]</span>"
elseif variety_code == "cmn-wuh" then
phonetic = "<span class=\"IPA\">[" .. phonetic .. "]</span>"
elseif variety_code == "cdo" then
local cdo_pron = require("Module:cdo-pron")
phonetic = "<i>" .. phonetic .. "</i>" ..
(not match(phonetic, "-[^ ]+-[^ ]+-[^ ]+-")
and " / <span class=\"IPA\"><small>[" .. cdo_pron.sentence(phonetic) .. "]</small></span>"
or "")
else
phonetic = "<i>" .. phonetic .. "</i>"
end
phonetic = "<span style=\"color:#404D52\">" .. phonetic .. "</span>"
end
end
local collapse_start, collapse_end, collapse_tag, collapse_border_div, collapse_border_div_end = '', '', '', '', ''
simplified_start = '<br>'
if collapsed then
collapse_start = '<span class="vsHide">'
collapse_end = '</span>'
collapse_tag = '<span class="vsToggleElement" style="color:darkgreen; font-size:x-small;padding-left:10px"></span>'
collapse_border_div = '<div class="vsSwitcher" data-toggle-category="usage examples" style="border-left: 1px solid #930; border-left-width: 2px; padding-left: 0.8em;">'
collapse_border_div_end = '</div>'
simplified_start = '<hr>'
end
if actual_title.nsText == '' then -- fixme: probably categorize only if text contains the actual word
if reference then
cat = "[[Kategori:Kata bahasa Cina dengan petikan]]"
else
cat = "[[Kategori:Kata bahasa Cina dengan contoh penggunaan]]"
end
end
-- indentation, font and identity tags
if
((variety_code == "cmn" and original_length > 7)
or (variety_code ~= "cmn" and original_length > 5)
or reference
or (match(example, "[,。?!、:; ]") and variety_code == "wuu")
or (variety_code == "cdo" and original_length > 3)
or (inline or "" ~= "")) then
trad_text = zh_format_start_trad .. trad_text .. zh_format_end
if not phonetic then
translation = "<i>" .. translation .. "</i>"
end
if phonetic then
phonetic = "<dd>" .. collapse_start .. phonetic
translation = "<dd>" .. translation .. "</dd>"
tr_tag = tag_start .. variety_data[3] .. tag_end .. collapse_end .. "</dd>"
else
translation = "<dd>" .. translation .. "</dd>"
end
if audio_file then
audio = "<dd>[[File:" .. audio_file .. "]]</dd>"
end
trad_tag = collapse_start .. tag_start .. variety_data[1] .. ", <i>[[w:Traditional Chinese|trad.]]" ..
((simp_exist or variety_code == "vi") and "" or " and [[w:Simplified Chinese|simp.]]") .. "</i>" .. tag_end .. collapse_end .. collapse_tag
if simp_exist then
simp_text = simplified_start .. collapse_start .. zh_format_start_simp .. simp_text .. zh_format_end
simp_tag = tag_start .. variety_data[1] .. ", <i>[[w:Simplified Chinese|simp.]]</i>" .. tag_end .. collapse_end
end
if reference then
reference = "<dd>" .. collapse_start .. "<small><i>From:</i> " ..
(ref_list[reference] and ref_list[reference][2] or reference) .. "</small>" .. collapse_end .. "</dd>"
end
return collapse_border_div .. "<dl class=\"zhusex\">" .. trad_text .. trad_tag .. (simp_text or "") .. (simp_tag or "") .. (reference or "") ..
(phonetic and phonetic .. tr_tag or "") .. (audio or "") .. translation .. "</dl>" .. (cat or "") .. collapse_border_div_end
else
trad_text = zh_format_start_trad .. trad_text .. zh_format_end
divider = " ― "
if variety ~= "MSC" then
ts_tag = tag_start .. variety_data[1] .. tag_end
tr_tag = tag_start .. variety_data[3] .. tag_end
end
if not phonetic then
translation = "<i>" .. translation .. "</i>"
end
if simp_exist then
simp_text = " / " .. zh_format_start_simp .. simp_text .. zh_format_end
end
if audio_file then
audio = " [[File:" .. audio_file .. "]]"
end
return trad_text .. (simp_text or "") .. (ts_tag or "") .. divider ..
(phonetic and phonetic .. (tr_tag or "") .. (audio or "") .. divider or "") .. translation .. (literal and " (literally, “" .. literal .. "”)" or "") ..
(cat or "")
end
end
function export.migrate(text, translation, ref)
if type(text) == "table" then
if not text.args or not text.args[1] then
text = text:getParent()
end
if text.args[2] and text.args[2] ~= '' then
ref = text.args[1]
translation = text.args[3]
text = text.args[2]
else
text = text.args[1]
end
end
text = text:gsub('^[%*#: \n]+', ''):gsub('[ \n]+$', ''):gsub(' +', ' '):gsub('\n+', '<br>'):gsub('|', '\\'):gsub('\'\'\'%[%[', ' '):gsub('%]%]\'\'\'', ' '):gsub('%]%]%[%[', ' '):gsub('%]%]', ''):gsub('%[%[', '')
:gsub('\'\'\'', ''):gsub(',', ','):gsub('!', '!'):gsub('%?', '?')
if translation then
if ref and ref ~= '' then
return '{{zh-x|' .. text .. '|' .. translation .. '|ref=' .. ref .. '}}'
else
return '{{zh-x|' .. text .. '|' .. translation .. '}}'
end
else
return text
end
end
return export