跳转到内容

模組:Category tree/poscatboiler/data/lang-specific/jpx/sandbox

維基詞典,自由的多語言詞典
local labels = {}
local handlers = {}

local m_str_utils = require("Module:string utilities")

local concat = table.concat
local full_link = require("Module:links").full_link
local insert = table.insert
local Hani_sort = require("Module:Hani-sortkey").makeSortKey
local match = m_str_utils.match
local sort = table.sort
local tag_text = require("Module:script_utilities").tag_text
local ucfirst = m_str_utils.ucfirst

local Hira = require("Module:scripts").getByCode("Hira")
local Jpan = require("Module:scripts").getByCode("Jpan")
local kana_to_romaji = require("Module:Hrkt-translit").tr
local m_numeric = require("Module:ConvertNumeric")

local kana_capture = "([-" .. require("Module:ja/data/range").kana .. "・]+)"
local yomi_data = require("Module:kanjitab/data")

labels["連體詞"] = {
	description = "{{{langname}}}{{ja-r|連%体%詞|れん%たい%し}},即用來修飾名詞、沒有活用且不做謂語的詞類。",
	parents = {{name = "{{{langcat}}}", raw = true}},
}

labels["平假名"] = {
	description = "{{{langname}}} terms with hiragana {{mdash}} {{ja-r|平%仮%名|ひら%が%な}} {{mdash}} forms, sorted by conventional hiragana sequence. The hiragana form is a [[phonetic]] representation of that word. " ..
	"Wiktionary represents {{{langname}}}-language segments in three ways: in normal form (with [[kanji]], if appropriate), in [[hiragana]] " ..
	"form (this differs from kanji form only when the segment contains kanji), and in [[romaji]] form.",
	additional = "參見[[:Category:{{{langname}}}片假名]]",
	toc_template = "categoryTOC-hiragana",
	parents = {
		{name = "{{{langcat}}}", raw = true},
		"Category:平假名字元",
	}
}

labels["歷史平假名"] = {
	description = "在歷史上曾使用的{{{langname}}}[[平假名]]形式",
	additional = "參見[[:Category:{{{langname}}}歷史片假名]]。",
	toc_template = "categoryTOC-hiragana",
	parents = {
		"平假名",
		{name = "{{{langcat}}}", raw = true},
		"Category:平假名字元",
	}
}

labels["片假名"] = {
	description = "{{{langname}}} terms with katakana {{mdash}} {{ja-r|片%仮%名|かた%か%な}} {{mdash}} forms, sorted by conventional katakana sequence. Katakana is used primarily for transliterations of foreign words, including old Chinese hanzi not used in [[shinjitai]].",
	additional = "參見[[:Category:{{{langname}}}平假名]]",
	toc_template = "categoryTOC-katakana",
	parents = {
		{name = "{{{langcat}}}", raw = true},
		"Category:片假名字元",
	}
}

labels["歷史片假名"] = {
	description = "在歷史上曾使用的{{{langname}}}[[片假名]]形式。",
	additional = "參見[[:Category:{{{langname}}}歷史平假名]]。",
	toc_template = "categoryTOC-katakana",
	parents = {
		"片假名",
		{name = "{{{langcat}}}", raw = true},
		"Category:片假名字元",
	}
}

labels["參雜假名的用語拼寫"] = {
	description = "{{{langname}}}中同時使用[[平假名]]和[[片假名]](有時還包括[[漢字]])的詞彙。",
	parents = {
		{name = "{{{langcat}}}", raw = true},
		"平假名",
		"片假名",
	},
}

labels["敬語"] = {
	topright = "{{wp|日語敬語}}",
	description = "{{{langname}}}[[敬語]]。",
	parents = {{name = "{{{langcat}}}", raw = true}},
}

labels["謙讓語"] = {
	description = "{{{langname}}} humble terms, or {{ja-r|謙%譲%語|けん%じょう%ご}}, which is a type of honorific speech that lowers the speaker in relation to the listener.",
	parents = "敬語",
}

labels["尊敬語"] = {
	description = "{{{langname}}} respectful terms, or {{ja-r|尊%敬%語|そん%けい%ご}}, which is a type of honorific speech that elevates the listener in relation to the speaker.",
	parents = "敬語",
}

labels["漢字"] = {
	topright = "{{wp|漢字}}",
	description = "{{{langname}}} symbols of the Han logographic script, which can represent sounds or convey meanings directly.",
	toc_template = "Hani-categoryTOC",
	umbrella = "漢字",
	parents = "語素文字",
}

labels["依讀音分類的漢字"] = {
	description = "依讀音分類的{{{langname}}}漢字。",
	parents = {{name = "kanji", sort = "reading"}},
}

labels["枕詞"] = {
	topright = "{{wp|枕詞}}",
	description = "{{{langname}}}詩歌中冠於特定詞語前而用於修飾或調整句調的詞語。",
	parents = {"俗語"},
}

labels["依漢字讀音分類的詞"] = {
	description = "{{{langname}}} categories grouped with regard to the readings of the kanji with which they are spelled.",
	parents = {{name = "{{{langcat}}}", raw = true}},
}

labels["依讀音規則分類的詞"] = {
	description = "{{{langname}}} categories with terms grouped by their reading patterns.",
	parents = {{name = "{{{langcat}}}", raw = true}},
}

local function handle_onyomi_list(category, category_type, cat_yomi_type)
	local onyomi, seen = {}, {}
	for _, yomi in pairs(yomi_data) do
		if not seen[yomi] and yomi.onyomi then
			local yomi_catname = yomi[category_type]
			if yomi_catname ~= false then
				local yomi_type = yomi.type
				if yomi_type ~= "音讀" and yomi_type ~= cat_yomi_type then
					insert(onyomi, "[[:Category:{{{langname}}}" .. category:gsub("{{{yomi_catname}}}", yomi_catname) .. "]]")
				end
			end
		end
		seen[yomi] = true
	end
	sort(onyomi)
	return onyomi
end

local function add_yomi_category(category, category_type, parent, description)
	for _, yomi in pairs(yomi_data) do
		local yomi_catname = yomi[category_type]
		if yomi_catname ~= false then
			local yomi_type = yomi.type
			local yomi_desc = yomi.link or yomi_catname
			if yomi.description then
				yomi_desc = yomi_desc .. ";" .. yomi.description
			end
			local label = {
				description = description .. yomi_desc .. "。",
				breadcrumb = yomi_type,
				parents = {{name = parent, sort = yomi_catname}},
			}
			if yomi.onyomi then
				local onyomi = handle_onyomi_list(category, category_type, yomi_type)
				
				label.additional = "Categories of terms with " ..
					(yomi_type == "音讀" and "more" or "other") ..
					"特定種類的音讀可見於以下分類:\n* " .. concat(onyomi, "\n* ")
				
				if yomi_type ~= "音讀" then
					insert(label.parents, 1, {
						name = (category:gsub("{{{yomi_catname}}}", yomi_data.on[category_type])),
						sort = yomi_catname
					})
				end
			end
			labels[category:gsub("{{{yomi_catname}}}", yomi_catname)] = label
		end
	end
end

add_yomi_category(
	"使用{{{yomi_catname}}}的詞",
	"reading_category",
	"依讀音規則分類的詞",
	"{{{langname}}} terms read with"
)

add_yomi_category(
	"有漢字使用{{{yomi_catname}}}的詞",
	"kanji_category",
	"依漢字讀法分類的詞",
	"{{{langname}}} categories with terms that are spelled with one or more kanji read with"
)

labels["缺少yomi參數的詞"] = {
	description = "{{tl|{{{langcode}}}-kanjitab}}中至少缺失一個[[Appendix:日語術語表#讀音|讀音]]的{{{langname}}}詞。",
	hidden = true,
	can_be_empty = true,
	parents = {"詞條維護"},
}

labels["有國際音標而缺少音高重音的詞"] = {
	description = "{{{langname}}} terms with pronunciations that do not have a {{w|Japanese pitch accent|pitch accent}} specified.",
	additional = "Pitch accent can be specified in {{tl|{{{langcode}}}-pron}} with the {{code|=acc=}} parameter.",
	hidden = true,
	can_be_empty = true,
	parents = {"詞條維護"},
}

labels["依漢字讀法分類的詞"] = {
	description = "{{{langname}}} categories with terms grouped with regard to the types of readings of the kanji with which " ..
	"they are spelled; broadly, those of Chinese origin, {{ja-r|音|おん}} readings, and those of non-Chinese origin, {{ja-r|訓|くん}} readings.",
	parents = {{name = "{{{langcat}}}", raw = true}},
}

labels["有借字的詞"] = {
	topright = "{{wp|借字 (日語)|借字}}",
	description = "包含一個或多個[[Appendix:日語術語表#借字|借字]]({{ja-r|当て字|あてじ}})的{{{langname}}}詞。這些漢字用於表示讀音而非含義(儘管含義可能對選擇哪個漢字有一定影響)。",
	parents = {{name = "{{{langcat}}}", raw = true}},
}

labels["有代用字的詞"] = {
	description = "使用代用字的{{{langname}}}詞,依據{{temp|ja-daiyouji}}形成的分類。",
	parents = {"詞源"},
}

labels["有熟字訓的詞"] = {
	description = "包含一個或多個[[Appendix:日語術語表#熟字訓|熟字訓]]({{ja-r|熟%字%訓|じゅく%じ%くん}})的{{{langname}}}詞。這些漢字僅用於表示含義而與讀音無關。",
	parents = {{name = "{{{langcat}}}", raw = true}},
}

local function add_grade_categories(grade, desc, wp, only_one, parent, sort)
	local grade_kanji = grade .. "漢字"
	local topright = wp and ("{{wp|%s}}"):format(ucfirst(grade_kanji)) or nil
	
	labels[grade_kanji] = {
		topright = topright,
		description = "{{{langname}}}漢字 " .. desc,
		toc_template = "Hani-categoryTOC",
		parents = {{
			name = parent and (parent .. "漢字") or "漢字",
			sort = sort or grade
		}},
	}
	
	labels["有" .. grade_kanji .. "的詞"] = {
		topright = topright,
		description = "詞中有" .. (only_one and "至少一個" or "") .. desc .. "的詞",
		parents = {{
			name = parent and ("有" .. parent .. "漢字的詞") or "依正字法屬性分類的詞",
			sort = sort or grade
		}},
	}
end

for i = 1, 6 do
	local ord = m_numeric.ones_position_ord[i]
	add_grade_categories(
		ord .. " grade",
		"於小學" .. ord .. "年級教授(根據文部科學省規定的{{ja-r|教%育 漢%字|きょう%いく かん%じ}}表)的漢字",
		false,
		false,
		"教育",
		i
	)
end

add_grade_categories(
	"教育",
	"於文部科學省規定的{{ja-r|教%育 漢%字|きょう%いく かん%じ|education kanji}}表中的漢字",
	true,
	false,
	"常用"
)

add_grade_categories(
	"中學",
	"於{{ja-r|常%用 漢%字|じょう%よう かん%じ}}表中的漢字(通常於中學期間教授)",
	false,
	false,
	"常用"
)

add_grade_categories(
	"常用",
	"於{{ja-r|常%用 漢%字|じょう%よう かん%じ}}表中的漢字",
	true,
	false
)

add_grade_categories(
	"當用",
	"於{{ja-r|当%用 漢%字|とう%よう かん%じ}}表中的漢字(於1946{{ndash}}1981年使用,後為{{ja-r|常%用 漢%字|じょう%よう かん%じ}}取代)",
	true,
	false
)

add_grade_categories(
	"人名用",
	"於{{ja-r|人%名%用 漢%字|じん%めい%-よう かん%}}表中的漢字",
	true,
	true
)

add_grade_categories(
	"表外",
	"未收錄於{{ja-r|常%用 漢%字|じょう%よう かん%じ}}或{{ja-r|人%名%用 漢%字|じん%めい%-よう かん%じ}}的漢字(稱作{{ja-r|表%外 漢%字|ひょう%がい かん%じ}} 或{{ja-r|表%外%字|ひょう%がい%じ}})",
	true,
	true
)

labels["有多個讀音的詞"] = {
	description = "有多種讀音(因此有多種[[假名]]寫法)的{{{langname}}}詞。",
	parents = {{name = "{{{langcat}}}", raw = true}},
}

labels["依漢字音拍數分類的詞"] = {
	description = "依據漢字讀音中的音拍數進行分組的{{{langname}}}分類。",
	parents = {{name = "{{{langcat}}}", raw = true}},
}

labels["單漢字詞"] = {
	description = "由單個漢字組成的{{{langname}}}詞。",
	parents = {"依正字法屬性分類的詞", {name = "字符數", sort = " "}},
}

labels["有訓讀但缺少送假名的日語漢字"] = {
	breadcrumb = "缺少送假名標記的漢字",
	description = "{{tl|{{{langcode}}}-readings}}中輸入了一個或多個訓讀但未標記送假名的{{{langname}}}的漢字詞條。",
	toc_template = "Hani-categoryTOC",
	hidden = true,
	can_be_empty = true,
	parents = {"詞條維護"},
}

labels["依歷史假名遣分類的詞"] = {
	breadcrumb = "歷史假名遣",
	description = "根據{{{langname}}}{{w|歷史假名遣}}中的拼寫是否包含特定假名進行分類的{{{langname}}}詞。",
	parents = {{name = "依字元分類的詞", sort = " "}},
}

labels["未指定是否及物的動詞"] = {
	description = "在標題行模板中缺失{{code|=tr=}}參數的{{{langname}}}詞。",
	hidden = true,
	can_be_empty = true,
	parents = {"詞條維護"},
}

labels["四字熟語"] = {
	topright = "{{wp|Yojijukugo}}",
	description = "由四個漢字組成的{{{langname}}}詞語({{ja-r|四%字 熟%語|よ%じ じゅく%ご}}),屬於熟語,通常源自古典漢語、佛教經典或日本傳統諺語。",
	additional = "比較漢語{{w|成語}}和朝鮮語{{w|四字成語}}。",
	umbrella = "成語",
	parents = {"俗語"},
}

-- FIXME: Only works for 0 through 19.
local word_to_number = {}
for k, v in pairs(m_numeric.ones_position) do
	word_to_number[v] = k
end

local periods = {
	historical = true,
	ancient = true,
}

local function get_period_text_and_reading_type_link(period, reading_type)
	if period and not periods[period] then
		return nil
	end
	local period_text = period and period .. "" or nil

	-- Allow periods (historical or ancient) by themselves; they will parse as reading types.
	if not period and periods[reading_type] then
		return nil, reading_type
	end

	local reading_type_link = "[[Appendix:日語術語表#" .. reading_type .. "|" .. reading_type .. "]]"
	return period_text, reading_type_link
end

local function get_sc(str)
	return match(str:gsub("[%s%p]+", ""), "[^" .. Hira:getCharacters() .. "]") and Jpan or Hira
end
		
local function get_tagged_reading(reading, lang)
	return tag_text(reading, lang, get_sc(reading))
end

local function get_reading_link(reading, lang, period, link)
	local hist = periods[period]
	reading = reading:gsub("[%.%-%s]+", "")
	return full_link({
		lang = lang,
		sc = get_sc(reading),
		term = link or reading:gsub("・", ""),
		-- If we have okurigana, demarcate furigana.
		alt = reading:gsub("^(.-)・", "<span style=\"border-top:1px solid;position:relative;padding:1px;\">%1<span style=\"position:absolute;top:0;bottom:67%%;right:0%%;border-right:1px solid;\"></span></span>"),
		tr = kana_to_romaji((reading:gsub("・", ".")), lang:getCode(), nil, {keep_dot = true, hist = hist})
			:gsub("^(.-)%.", "<u>%1</u>"),
		pos = reading:find("・", 1, true) and get_tagged_reading((reading:gsub("^.-・", "~")), lang) or nil
	}, "term")
end

local function is_on_subtype(reading_type)
	return reading_type:find(".音$")
end

insert(handlers, function(data)
	local number = data.label:match("^有([1-9]%d*)個漢字的詞$")
	if not number then
		return
	end
	return {
		description = "有" .. number .. "個漢字的{{{langname}}}詞。",
		breadcrumb = number,
		parents = {{
			name = "字符數",
			sort = ("#%03d"):format(number)
		}}
	}
end)


insert(handlers, function(data)
	local label_pref, kana = data.label:match("^(歷史假名遣包含「)" .. kana_capture .. "」的詞$")
	
	if not kana then
		return
	end
	
	local lang = data.lang
	
	return {
		description = "{{{langname}}} terms spelled with " .. get_reading_link(kana, lang, "歷史假名遣") .. " in the {{w|historical kana orthography}}.",
		displaytitle = "{{{langname}}}" .. label_pref .. get_tagged_reading(kana, lang),
		breadcrumb = "歷史假名遣",
		parents = {
			{name = "帶「" .. kana .. "」的日語詞", sort = " "},
			{name = "依歷史假名遣分類的詞", sort = lang:makeSortKey(kana)}
		},
	}
end)


insert(handlers, function(data)
	local count = data.label:match("^讀作(.)個音拍的漢字$")
	
	-- Make sure 'one' goes with singular and other numbers with plural.
	-- if not count or (count == "one") ~= (plural == "") then
	-- 	return
	-- end
	
	local num = word_to_number[count]
	if not num then
		return nil
	end
	
	return {
		description =  "含有".. count .."個音拍的{{{langname}}}漢字讀法。",
		breadcrumb = num,
		parents = {{name = "依漢字音拍數分類的詞", sort = num}},
	}
end)


insert(handlers, function(data)
	local label_pref, period, reading_type, reading = match(data.label, "^(((歷史假名遣|古日語)?)?(訓讀|音讀|名乘)讀作「)" .. kana_capture .. "」的漢字$")
	mw.log(data.label, label_pref, period, reading_type, reading)
	local basic = data.label:match("^(.*)讀作「(.*)」的漢字$")
	mw.log("Basic match:", basic)
	
	local prefix = data.label:match("^(古日語訓讀)讀作")
	mw.log("Prefix match:", prefix)
	
	local period_test = data.label:match("^(歷史假名遣|古日語)")
	mw.log("Period match:", period_test)
	
	local type_test = data.label:match("(訓讀|音讀|名乘)讀作")
	mw.log("Type match:", type_test)
	
	local label_pref, period, reading_type, reading = match(data.label, 
    "^(((歷史假名遣|古日語)?)?(訓讀|音讀|名乘)讀作「)" .. kana_capture .. "」的漢字$")
    
	if not period then
		return
	end
	
	period = period ~= "" and period or nil
	local period_text, reading_type_link = get_period_text_and_reading_type_link(period, reading_type)
	
	if not reading_type_link then
		return
	end
	
	local lang = data.lang
	
	-- Compute parents.
	local parents, breadcrumb = {}
	if reading:find("・", 1, true) then
		local okurigana = reading:match("・(.*)")
		insert(parents, {
			name = (period_text or "") .. reading_type .. "讀作「" .. reading:match("(.-)・") .. "」的漢字",
			-- Sort by okurigana, since all coordinate categories will have the same furigana.
			sort = (lang:makeSortKey(okurigana))
		})
		breadcrumb = "~" .. okurigana
	else
		insert(parents, {
			name = "依" .. (period_text or "") .. reading_type .. "分類的漢字",
			sort = (lang:makeSortKey(reading))
		})
		breadcrumb = reading
	end
	if is_on_subtype(reading_type) then
		insert(parents, {name = (period_text or "") .. "音讀讀作「" .. reading .. "」的漢字", sort = reading_type})
	elseif period_text then
		insert(parents, {name = period_text .. "讀作「" .. reading .. "」的漢字", sort = reading_type})
	end
	if not period_text then
		insert(parents, {name = "讀作「" .. reading .. "」的漢字", sort = reading_type})
	end
	
	return {
		description = (period_text or "") .. reading_type_link .. "讀作「"
		.. get_reading_link(reading, lang, period or reading_type) .. "」的{{{langname}}}[[漢字]]。",
		displaytitle = "{{{langname}}}" .. label_pref .. get_tagged_reading(reading, lang),
		breadcrumb = get_tagged_reading(breadcrumb, lang),
		parents = parents,
	}
end)

insert(handlers, function(data)
	local period, reading_type = match(data.label, "^依([一-鿌]*)分類的漢字$")
	
	if not period then
		return
	end
	
	period = period ~= "" and period or nil
	local period_text, reading_type_link = get_period_text_and_reading_type_link(period, reading_type)
	
	if not reading_type_link then
		return nil
	end

	-- Compute parents.
	local parents = {
		is_on_subtype(reading_type) and {name = "依" .. (period_text or "") .. "音讀分類的漢字", sort = reading_type} or
		period_text and {name = "依" .. reading_type .. "分類的漢字", sort = period} or
		{name = "依讀音分類的漢字", sort = reading_type}
	}
	if period_text then
		insert(parents, {name = "依" .. period_text .. "分類的漢字", sort = reading_type})
	end

	-- Compute description.
	local description = "依照" .. (period_text or "") .. reading_type_link .. "進行分類的{{{langname}}}[[漢字]]。"
	return {
		description = description,
		breadcrumb = (period_text or "") .. reading_type,
		parents = parents,
	}
end)


insert(handlers, function(data)
	local label_pref, reading = match(data.label, "^(讀作「" .. kana_capture .. "」的漢字)$")
	
	if not reading then
		return
	end
	
	local args = require("Module:parameters").process(data.args, {
		["histconsol"] = true,
	})
	local lang = data.lang
	
	local parents, breadcrumb = {}
	if reading:find("・", 1, true) then
		local okurigana = reading:match("・(.*)")
		insert(parents, {
			name = "讀作「" .. reading:match("(.-)・" .. "」的漢字"),
			-- Sort by okurigana, since all coordinate categories will have the same furigana.
			sort = (lang:makeSortKey(okurigana))
		})
		breadcrumb = "~" .. okurigana
	else
		insert(parents, {
			name = "依讀音分類的漢字",
			sort = (lang:makeSortKey(reading))
		})
		breadcrumb = reading
	end
	
	local addl
	local period_text
	if args.histconsol then
		period_text = "歷史假名遣"
		addl = ("這是一個[[w:歷史假名遣|歷史]][[w:假名遣|假名遣]]," ..
		"已和[[w:現代假名遣|現代假名遣]]" ..
		get_reading_link(args.histconsol, lang, nil, ("Category:J讀作「%s」的日語漢字"):format(args.histconsol)) .. "合併。")
	end
	
	return {
		description = "讀作「" .. get_reading_link(reading, lang, period_text) .. "」的{{{langname}}}漢字。",
		additional = addl,
		displaytitle = "{{{langname}}} " .. label_pref .. get_tagged_reading(reading, lang),
		breadcrumb = get_tagged_reading(breadcrumb, lang),
		parents = parents,
	}, true
end)


insert(handlers, function(data)
	local label_pref, reading = match(data.label, "^(讀作「" .. kana_capture .. "」的詞)$")
	
	if not reading then
		return
	end
	
	-- Compute parents.
	local lang = data.lang
	local sort_key = (lang:makeSortKey(reading))
	local mora_count = require("Module:ja").count_morae(reading)
	local mora_count_words = m_numeric.spell_number(tostring(mora_count))
	local parents = {
		{name = "依漢字讀音分類的詞", sort = sort_key},
		{name = "讀作" .. mora_count .. "個音拍的漢字", sort = sort_key},
		{name = "讀作「" .. reading .. "」的漢字", sort = " "},
	}

	local tagged_reading = get_tagged_reading(reading, lang)
	return {
		description = "讀法為" .. get_reading_link(reading, lang) ..
				"的{{{langname}}}詞條(不考慮任何發音變化)。",
		displaytitle = "{{{langname}}} " .. label_pref .. tagged_reading,
		breadcrumb = tagged_reading,
		parents = parents,
	}
end)


insert(handlers, function(data)
	local kanji, reading = match(data.label, "^寫作「(.)」讀作「" .. kana_capture .. "」的詞$")
	
	if not kanji then
		return nil
	end
	
	local args = require("Module:parameters").process(data.args, {
		[1] = {list = true},
	})
	local lang = data.lang
	
	if #args[1] == 0 then
		error("對於形如「寫作『?』讀作『?』的" .. lang:getCanonicalName() ..
			"詞」的分類,請指明至少一種讀法(例如<code>kun</code>表示訓讀,<code>on</code>表示音讀),分別填入<code>1=</code>、<code>2=</code>、<code>3=</code>等。")
	end
	local yomi_types, parents = {}, {}
	for _, yomi, category in ipairs(args[1]) do
		local yomi_data = yomi_data[yomi]
		if not yomi_data then
			error("無法辨識讀法「" .. yomi .. "」。")
		end
		category = yomi_data.kanji_category
		if not category then
			error("讀法「" .. yomi .. "」不適用於此類分類。")
		end
		insert(yomi_types, yomi_data.link)
		insert(parents, {
			name = "有漢字使用" .. category .. "的詞",
			sort = (lang:makeSortKey(reading))
		})
	end
	
	insert(parents, 1, {name = "帶「" .. kanji.. "」的詞", sort = (lang:makeSortKey(reading))})
	insert(parents, 2, {name = "讀作「" .. reading.. "」的詞", sort = Hani_sort(kanji)})
	
	yomi_types = (#yomi_types > 1 and "one of " or "") .. "its " ..
		require("Module:table").serialCommaJoin(yomi_types, {conj = "或"}) ..
		" reading" .. (#yomi_types > 1 and "s" or "")
	
	local tagged_kanji = get_tagged_reading(kanji, lang)
	local tagged_reading = get_tagged_reading(reading, lang)
	return {
		description = "含有漢字「{{l|{{{langcode}}}|" .. kanji .. "}}」且採用" ..
			yomi_types .. "讀作「" .. get_reading_link(reading, lang) .. "」的{{{langname}}}詞語。" .. string.format("-{H|「%s」=>zh-hans:“%s”}--{H|「%s」=>zh-hant:「%s」}-", kanji, kanji, kanji, kanji),
		displaytitle = "寫作「" .. tagged_kanji .. "」讀作「" .. tagged_reading .. "」的{{{langname}}}詞",
		breadcrumb = "讀作「" .. tagged_reading .. "」",
		parents = parents,
	}, true
end)


insert(handlers, function(data)
	local kanji, daiyoji = match(data.label, "^使用「(.)」作為代用字代替「(.)」的詞$")
	
	if not kanji then
		return nil
	end
	
	local args = require("Module:parameters").process(data.args, {
		["sort"] = true,
	})
	local lang = data.lang
	
	if not args.sort then
		error("對於形如使用『?』作為代用字代替『?』的" .. data.lang:getCanonicalName() ..
			"詞」的分類,請指明至少一種代用字用法,在sort=填入代用字的發音")
	end

	local tagged_kanji = get_tagged_reading(kanji, lang)
	local tagged_daiyoji = get_tagged_reading(daiyoji, lang)
	return {
		description = "採用[[Appendix:日語術語表|代用字]]「{{l|{{{langcode}}}|" .. kanji .. "}}」以代替「{{l|{{{langcode}}}|" .. daiyoji .. "}}」的{{{langname}}}詞。",
		displaytitle = "使用「" .. tagged_kanji .. "」作為代用字代替「" .. tagged_daiyoji .. "」的{{{langname}}}詞",
		breadcrumb = "使用「" .. tagged_kanji .. "」代替「" .. tagged_daiyoji .. "」的詞",
		parents = {{name = "有代用字的詞", sort = args.sort}},
	}, true
end)

return {LABELS = labels, HANDLERS = handlers}