Module:kanjitab: difference between revisions
Jump to navigation
Jump to search
Content deleted Content added
Theknightwho (talk | contribs) And irregular. |
use CSS class floatright; remove unnecessary font-size:small |
||
(17 intermediate revisions by 2 users not shown) | |||
Line 25: | Line 25: | ||
local usub = m_str_utils.sub |
local usub = m_str_utils.sub |
||
local title = mw.title.getCurrentTitle() |
|||
local PAGENAME = mw.loadData("Module:headword/data").pagename |
local PAGENAME = mw.loadData("Module:headword/data").pagename |
||
local NAMESPACE = title.nsText |
local NAMESPACE = mw.title.getCurrentTitle().nsText |
||
local d_range = mw.loadData |
local d_range = mw.loadData("Module:ja/data/range") |
||
local yomi_data = mw.loadData("Module:kanjitab/data") |
|||
local kanji_grade_links = { |
local kanji_grade_links = { |
||
Line 40: | Line 40: | ||
"[[Appendix:Japanese_glossary#jōyō_kanji|Grade: S]]", -- 7 |
"[[Appendix:Japanese_glossary#jōyō_kanji|Grade: S]]", -- 7 |
||
"[[Appendix:Japanese_glossary#jinmeiyō_kanji|Jinmeiyō]]", -- 8 |
"[[Appendix:Japanese_glossary#jinmeiyō_kanji|Jinmeiyō]]", -- 8 |
||
"[[Appendix:Japanese_glossary# |
"[[Appendix:Japanese_glossary#hyōgai_kanji|Hyōgai]]" -- 9 |
||
} |
} |
||
Line 56: | Line 56: | ||
alt2 = {}, |
alt2 = {}, |
||
kyu = { list = true }, |
kyu = { list = true }, |
||
y = {alias_of = |
y = {alias_of = "yomi"}, |
||
clearright = {type = "boolean"}, |
clearright = {type = "boolean"}, |
||
pagename = {}, |
pagename = {}, |
||
Line 66: | Line 66: | ||
if args.pagename and NAMESPACE == "" then |
if args.pagename and NAMESPACE == "" then |
||
require |
require("Module:debug/track")("kanjitab/pagename param in mainspace") |
||
end |
end |
||
local pagename = args.pagename or PAGENAME |
local pagename = args.pagename or PAGENAME |
||
Line 81: | Line 81: | ||
local kanji_border = 1 |
local kanji_border = 1 |
||
ugsub(pagename, |
ugsub(pagename, "()([" .. d_range.kanji .. "々〻])()", function(p1, w1, p2) |
||
insert(non_kanji, usub(pagename, kanji_border, p1 - 1)) |
insert(non_kanji, usub(pagename, kanji_border, p1 - 1)) |
||
kanji_border = p2 |
kanji_border = p2 |
||
Line 90: | Line 90: | ||
-- kyujitai |
-- kyujitai |
||
local kyu = args.kyu |
local kyu = args.kyu |
||
if kyu[1] == |
if kyu[1] == "-" then |
||
kyu = {} |
kyu = {} |
||
elseif kyu[1] == nil then |
elseif kyu[1] == nil then |
||
local form_kyu = {non_kanji[1]} |
local form_kyu = {non_kanji[1]} |
||
local kyu_data = mw.loadData( |
local kyu_data = mw.loadData("Module:ja/data/kyu") |
||
local has_kyu, has_kyu_nonsupple, has_shin = false, false, false |
local has_kyu, has_kyu_nonsupple, has_shin = false, false, false |
||
for i, v in ipairs(kanji) do |
for i, v in ipairs(kanji) do |
||
Line 100: | Line 100: | ||
if v_kyu == nil then |
if v_kyu == nil then |
||
insert(form_kyu, v) |
insert(form_kyu, v) |
||
elseif v_kyu == |
elseif v_kyu == "" then |
||
has_shin = true |
has_shin = true |
||
break |
break |
||
elseif v_kyu:sub(1, 1) == |
elseif v_kyu:sub(1, 1) == "&" then |
||
has_kyu = true |
has_kyu = true |
||
insert(form_kyu, v_kyu) |
insert(form_kyu, v_kyu) |
||
Line 114: | Line 114: | ||
if not has_shin and has_kyu then |
if not has_shin and has_kyu then |
||
kyu[1] = (has_kyu_nonsupple and |
kyu[1] = (has_kyu_nonsupple and "" or pagename .. "|") .. concat(form_kyu) |
||
end |
end |
||
if find(pagename, "弁") then |
if find(pagename, "弁") then |
||
require |
require("Module:debug/track")("kanjitab/ambiguous kyujitai for 弁") |
||
kyu[1] = |
kyu[1] = "which 弁?" |
||
end |
end |
||
end |
end |
||
local all_yomi, missing_yomi |
|||
if args.yomi then |
|||
all_yomi = {} |
|||
local keys = split(args.yomi, ",") |
|||
for i, yomi, len in ipairs(keys) do |
|||
yomi, len = match(yomi, "^(%l*)(%d*)$") |
|||
yomi = yomi_data[yomi] or error("The yomi type \"" .. yomi .. "\" in the input \"" .. args.yomi .. "\" is not recognized.") |
|||
if len ~= "" then |
|||
-- Disallow length 0 or leading zeroes, as a sanity check. |
|||
len = match(len, "^[1-9]%d*$") and tonumber(len) or error("Cannot specify a length of " .. len .. " kanji.") |
|||
-- Only one yomi with no length given: apply to all kanji. |
|||
elseif i == 1 and #keys == 1 then |
|||
len = #kanji |
|||
else |
|||
len = 1 |
|||
end |
|||
local yomi_type = yomi.type |
|||
-- If the on'yomi is not specified as goon/kanon/toon/soon, only "on". |
|||
if yomi_type == "on'yomi" then |
|||
require("Module:debug/track")("kanjitab/unspecified on") |
|||
elseif yomi_type == "jūbakoyomi" then |
|||
require("Module:debug/track")("kanjitab/jubakoyomi") |
|||
elseif yomi_type == "yutōyomi" then |
|||
require("Module:debug/track")("kanjitab/yutoyomi") |
|||
end |
|||
-- If the yomi requires a specific number of kanji (e.g. jūbakoyomi, yutōyomi). |
|||
local req_kanji = yomi.required_kanji |
|||
if req_kanji and #kanji ~= req_kanji then |
|||
error("The yomi type \"" .. yomi.type .. "\" is only applicable to terms with " .. req_kanji .. " kanji.") |
|||
elseif yomi.type == "none" then |
|||
missing_yomi = true |
|||
end |
|||
-- Insert yomi data for each applicable kanji. Wrap in a table first, as the range for this input yomi is determined by its identity, so that (e.g.) "kun,kun" is still treated as two separate inputs. |
|||
yomi = {data = yomi} |
|||
for _ = 1, len do |
|||
insert(all_yomi, yomi) |
|||
end |
|||
end |
|||
-- If there are any yomi slots left, handle them as empty. |
|||
if #all_yomi < #kanji then |
|||
missing_yomi = true |
|||
for _ = #all_yomi + 1, #kanji do |
|||
insert(all_yomi, {data = yomi_data.none}) |
|||
end |
|||
end |
|||
elseif #kanji > 0 then |
|||
missing_yomi = true |
|||
end |
|||
if missing_yomi then |
|||
insert(categories, lang_name .. " terms with missing yomi") |
|||
end |
|||
-- process readings |
-- process readings |
||
local readings = {} |
local readings = {} |
||
Line 136: | Line 193: | ||
end |
end |
||
if reading_length_total > #kanji then |
if reading_length_total > #kanji then |
||
error( |
error("Readings for " .. reading_length_total .. " kanji are given, but this word has only " .. #kanji .. " kanji.") |
||
else |
else |
||
for _ = reading_length_total + 1, #kanji do |
for _ = reading_length_total + 1, #kanji do |
||
Line 144: | Line 201: | ||
local table_head = [=[ |
local table_head = [=[ |
||
{| class="wikitable kanji-table" style="text-align: center; |
{| class="wikitable kanji-table floatright" style="text-align: center; ]=] .. (args.clearright and " clear:right;" or "") .. [=[" |
||
! ]=] .. (#kanji > 1 and |
! ]=] .. (#kanji > 1 and "colspan=\"" .. #kanji .. "\" " or "") .. [=[style="font-weight: normal;" | [[Appendix:Japanese_glossary#kanji|Kanji]] in this term |
||
|- lang="]=] .. lang_code .. [=[" class="Jpan" style="font-size: 2em; background: white; line-height: 1em;" |
|- lang="]=] .. lang_code .. [=[" class="Jpan" style="font-size: 2em; background: white; line-height: 1em;" |
||
]=] |
]=] |
||
local yomi |
|||
-- on/kun is jūbakoyomi; NOTE: these are only applicable for two-kanji compounds |
|||
-- kun/on is yutōyomi; NOTE: these are only applicable for two-kanji compounds |
|||
if args.yomi then |
|||
yomi = {} |
|||
local extended_yomi_code = { |
|||
o = 'on', on = 'on', |
|||
kanon = 'kanon', -- kan is kan'yoon, and ko is kun+on for backward compatibility |
|||
goon = 'goon', |
|||
soon = 'soon', |
|||
toon = 'toon', |
|||
kan = 'kanyoon', kanyo = 'kanyoon', kanyoon = 'kanyoon', |
|||
k = 'kun', kun = 'kun', |
|||
juku = 'jukujikun', jukuji = 'jukujikun', jukujikun = 'jukujikun', |
|||
ok = "jūbakoyomi", j = "jūbakoyomi", |
|||
ko = "yutōyomi", y = "yutōyomi", yu = "yutōyomi", |
|||
i = 'irregular', irr = 'irregular', irreg = 'irregular', irregular = 'irregular', |
|||
n = 'nanori', nanori = 'nanori', |
|||
[''] = '', none = '', |
|||
} |
|||
for i in gsplit(args.yomi, ',') do |
|||
local a, b = match(i, "^(%l*)(%d*)$") |
|||
a = extended_yomi_code[a] or error("The yomi type “" .. args.yomi .. "” is not recognized.") |
|||
b = tonumber(b) or 1 |
|||
insert(yomi, { a, b }) |
|||
-- If the on'yomi is not specified as goon/kanon/toon/soon, only 'on' |
|||
if a == 'on' then |
|||
require'Module:debug'.track'kanjitab/unspecified on' |
|||
end |
|||
if (a == "jūbakoyomi" or a == "yutōyomi") and #kanji ~= 2 then |
|||
error'yutou or juubako is only applicable to 二字熟語' |
|||
end |
|||
end |
|||
if #yomi == 1 and #kanji > 1 then |
|||
yomi[1][2] = #kanji |
|||
end |
|||
elseif #kanji > 0 then |
|||
require'Module:debug'.track'kanjitab/no yomi' |
|||
end |
|||
if args.k.maxindex and args.k.maxindex > args[1].maxindex then |
if args.k.maxindex and args.k.maxindex > args[1].maxindex then |
||
error |
error("kanjitab/too many k") |
||
end |
end |
||
if args.o.maxindex and args.o.maxindex > args[1].maxindex then |
if args.o.maxindex and args.o.maxindex > args[1].maxindex then |
||
error |
error("kanjitab/too many o") |
||
end |
end |
||
local yomi_type_by_kanji = {} |
|||
if yomi then |
|||
for i = 1, #yomi do |
|||
for _ = 1, yomi[i][2] do |
|||
insert(yomi_type_by_kanji, yomi[i][1]) |
|||
end |
|||
end |
|||
else |
|||
for _ = 1, #kanji do |
|||
insert(yomi_type_by_kanji, '') |
|||
end |
|||
end |
|||
local is_ateji = {} |
local is_ateji = {} |
||
if args.ateji then |
if args.ateji then |
||
local ateji = args.ateji |
local ateji = args.ateji |
||
local cat_ateji = false |
local cat_ateji = false |
||
if ateji == |
if ateji == "y" then |
||
for i = 1, #kanji do |
for i = 1, #kanji do |
||
is_ateji[i] = true |
is_ateji[i] = true |
||
Line 224: | Line 225: | ||
cat_ateji = true |
cat_ateji = true |
||
else |
else |
||
for i in gsplit(ateji, |
for i in gsplit(ateji, ";") do |
||
gsub(i, |
gsub(i, "^(%d+)$", function(a) |
||
is_ateji[tonumber(a)] = true |
is_ateji[tonumber(a)] = true |
||
cat_ateji = true |
cat_ateji = true |
||
end) |
end) |
||
gsub(i, |
gsub(i, "^(%d+),(%d+)$", function (a, b) |
||
for j = tonumber(a), tonumber(b) do |
for j = tonumber(a), tonumber(b) do |
||
is_ateji[j] = true |
is_ateji[j] = true |
||
Line 251: | Line 252: | ||
if reading_length <= 1 then |
if reading_length <= 1 then |
||
insert(cell, |
insert(cell, "| rowspan=\"2\" | ") |
||
else |
else |
||
insert(cell, |
insert(cell, "| colspan =\"" .. reading_length .. "\" | ") |
||
end |
end |
||
-- display reading, actual reading and okurigana |
-- display reading, actual reading and okurigana |
||
if reading_kana then |
if reading_kana then |
||
if reading_kana ~= "" and umatch(reading_kana, "[^" .. d_range.kana .. "]") then |
if reading_kana ~= "" and reading_kana ~= "-" and umatch(reading_kana, "[^" .. d_range.kana .. "]") then |
||
error("Please remove any non-kana characters from the reading input " .. reading_kana .. ".") |
|||
require'Module:debug'.track'kanjitab/not all kana' |
|||
end |
end |
||
Line 269: | Line 270: | ||
local text = reading_kana .. okurigana_text .. actual_reading_text |
local text = reading_kana .. okurigana_text .. actual_reading_text |
||
readings_actual[i] = {(actual_reading or reading_kana) .. (okurigana or |
readings_actual[i] = {(actual_reading or reading_kana) .. (okurigana or ""), reading_length} |
||
insert(cell, |
insert(cell, "<span class=\"Jpan\" lang=\"" .. lang_code .. "\">" .. text .. "</span>") |
||
if reading_length <= 1 then insert(cell, |
if reading_length <= 1 then insert(cell, "<br/>") end |
||
else |
else |
||
readings_actual[i] = {nil, 1} |
readings_actual[i] = {nil, 1} |
||
Line 281: | Line 282: | ||
local single_kanji = kanji[j] |
local single_kanji = kanji[j] |
||
local kanji_grade = m_ja.kanji_grade(single_kanji) |
local kanji_grade = m_ja.kanji_grade(single_kanji) |
||
local ateji_text = is_ateji[j] and |
local ateji_text = is_ateji[j] and "<br/><small>([[Appendix:Japanese glossary#ateji|ateji]])</small>" or "" |
||
local type, compound |
|||
if reading_kana then |
|||
if all_yomi then |
|||
-- subcategorize by reading if this is joyo kanji, not doing that for less common kanji, with exceptions |
|||
local yomi = all_yomi[j].data |
|||
if reading_length == 1 and yomi_type_by_kanji[j] ~= "irregular" then |
|||
type, compound = yomi.type, yomi.compound_reading |
|||
insert(categories, lang_name .. " terms spelled with " .. single_kanji .. " read as " .. kata_to_hira(reading_kana)) |
|||
end |
|||
insert(categories, lang_name .. " terms spelled with " .. single_kanji) |
|||
if not reading_kana then |
|||
end |
|||
if type ~= "irregular" then |
|||
else |
|||
require("Module:debug/track")("kanjitab/no reading") |
|||
if yomi_type_by_kanji[j] ~= 'irregular' and yomi_type_by_kanji[j] ~= 'jukujikun' then |
|||
require'Module:debug'.track'kanjitab/no reading' |
|||
end |
end |
||
insert(categories, lang_name .. " terms spelled with " .. single_kanji) |
insert(categories, lang_name .. " terms spelled with " .. single_kanji) |
||
elseif reading_length ~= 1 or type == "irregular" then |
|||
insert(categories, lang_name .. " terms spelled with " .. single_kanji) |
|||
elseif compound then |
|||
-- Re-enable once all bad jukujikun calls are fixed. |
|||
-- error("The yomi type \"" .. type .. "\" is only applicable to compound character readings, so cannot apply to " .. single_kanji .. " read as " .. reading_kana .. ". If this is intended as part of a " .. type .. " reading, please enter the whole reading as one, followed by the number of kanji it applies to.") |
|||
require("Module:debug/track")("kanjitab/single kanji with jukujikun") |
|||
else -- Subcategorize by reading. |
|||
insert(categories, lang_name .. " terms spelled with " .. single_kanji .. " read as " .. kata_to_hira(reading_kana)) |
|||
end |
end |
||
Line 306: | Line 314: | ||
kanji_pos = kanji_pos + reading_length |
kanji_pos = kanji_pos + reading_length |
||
end |
end |
||
insert(cells, |
insert(cells, "|- style=\"background: white;\"") |
||
if #cells_below > 0 then |
if #cells_below > 0 then |
||
insert(cells, concat(cells_above, |
insert(cells, concat(cells_above, "\n")) |
||
insert(cells, |
insert(cells, "|- style=\"background: white;\"") |
||
insert(cells, concat(cells_below, |
insert(cells, concat(cells_below, "\n")) |
||
else |
else |
||
for i, v in ipairs(cells_above) do |
for i, v in ipairs(cells_above) do |
||
cells_above[i] = gsub(v, "| rowspan=\"2\" | ", "| ") |
cells_above[i] = gsub(v, "| rowspan=\"2\" | ", "| ") |
||
end |
end |
||
insert(cells, concat(cells_above, |
insert(cells, concat(cells_above, "\n")) |
||
end |
end |
||
local yomi_info = { |
|||
["on"] = { |
|||
text = "on’yomi", |
|||
entry = "Appendix:Japanese_glossary#on'yomi", |
|||
category = lang_name .. " terms read with on'yomi", |
|||
}, |
|||
["kanon"] = { |
|||
text = "kan’on", |
|||
entry = "Appendix:Japanese_glossary#kan'on", |
|||
category = lang_name .. " terms read with on'yomi", |
|||
}, |
|||
["goon"] = { |
|||
text = "goon", |
|||
entry = "Appendix:Japanese_glossary#goon", |
|||
category = lang_name .. " terms read with on'yomi", |
|||
}, |
|||
["soon"] = { |
|||
text = "sōon", |
|||
entry = "Appendix:Japanese_glossary#tōon", |
|||
category = lang_name .. " terms read with on'yomi", |
|||
}, |
|||
["toon"] = { |
|||
text = "tōon", |
|||
entry = "Appendix:Japanese_glossary#tōon", |
|||
category = lang_name .. " terms read with on'yomi", |
|||
}, |
|||
["kun"] = { |
|||
text = "kun’yomi", |
|||
entry = "Appendix:Japanese_glossary#kun'yomi", |
|||
category = lang_name .. " terms read with kun'yomi", |
|||
}, |
|||
["nanori"] = { |
|||
text = "nanori", |
|||
entry = "Appendix:Japanese_glossary#nanori", |
|||
category = lang_name .. " terms read with nanori", |
|||
}, |
|||
["yutōyomi"] = { |
|||
text = "yutōyomi", |
|||
entry = "Appendix:Japanese_glossary#yutōyomi", |
|||
category = lang_name .. " terms read with yutōyomi", |
|||
}, |
|||
["jūbakoyomi"] = { |
|||
text = "jūbakoyomi", |
|||
entry = "Appendix:Japanese_glossary#jūbakoyomi", |
|||
category = lang_name .. " terms read with jūbakoyomi", |
|||
}, |
|||
["jukujikun"] = { |
|||
text = "jukujikun", |
|||
entry = "Appendix:Japanese_glossary#jukujikun", |
|||
category = lang_name .. " terms read with jukujikun", |
|||
}, |
|||
["irregular"] = { |
|||
text = "''irregular''", |
|||
category = lang_name .. " terms with irregular kanji readings", |
|||
}, |
|||
["kanyoon"] = { |
|||
text = "kan’yōon", |
|||
entry = "Appendix:Japanese_glossary#kan'yoon", |
|||
category = lang_name .. " terms read with kan'yōon", |
|||
}, |
|||
} |
|||
local rendaku = args.r |
local rendaku = args.r |
||
if rendaku then |
if rendaku then |
||
insert(categories, lang_name .. " terms with rendaku") |
insert(categories, lang_name .. " terms with rendaku") |
||
end |
end |
||
if |
if all_yomi then |
||
insert(cells, "|-") |
insert(cells, "|-") |
||
local len, all_on, yomi_cat = 1, true |
|||
for _, i in ipairs(yomi) do |
|||
for i, yomi in ipairs(all_yomi) do |
|||
local yomi_info = yomi_info[i[1]] or { text = i[1] } |
|||
-- If the next kanji has the same yomi table, it's part of the same range. |
|||
local text |
|||
if |
if yomi == all_yomi[i + 1] then |
||
len = len + 1 |
|||
text = "[[" .. yomi_info.entry .. "|" .. yomi_info.text .. "]]" |
|||
else |
else |
||
yomi = yomi.data |
|||
local yomi_type = yomi.type |
|||
local display = yomi.display or yomi_type |
|||
local appendix = yomi.appendix |
|||
insert(cells, "| colspan=\"" .. len .. "\" |" .. ( |
|||
appendix == false and display or |
|||
"[[Appendix:Japanese_glossary#" .. (appendix or yomi_type) .. "|" .. display .. "]]" |
|||
)) |
|||
-- Categorise as irregular if any irregular yomi are found; otherwise, categorise if all yomi are of the same type. If yomi are of different types but are all on, on'yomi is used as a fallback. |
|||
if yomi_cat ~= "irregular" then |
|||
local cat_type = yomi_type |
|||
if cat_type == "irregular" or yomi_cat == nil then |
|||
yomi_cat = cat_type |
|||
elseif yomi_cat ~= cat_type then |
|||
yomi_cat = false |
|||
end |
|||
if not yomi.onyomi then |
|||
all_on = false |
|||
end |
|||
end |
|||
len = 1 |
|||
end |
end |
||
insert(cells, '| colspan="' .. i[2] .. '" |' .. text) |
|||
end |
end |
||
if yomi_cat then |
|||
local is_onyomi = { on = true, kanon = true, goon = true, soon = true, toon = true, kanyoon = true } |
|||
-- Check yomi_data first, in case cat_type is "irregular"; if no match, must be some other type, so get it from the first yomi in all_yomi, since not all yomi types are yomi_data keys. |
|||
-- categories |
|||
yomi_cat = yomi_data[yomi_cat] or all_yomi[1].data |
|||
local all_onyomi = true |
|||
elseif all_on then |
|||
for i = 1, #yomi do |
|||
yomi_cat = yomi_data.on |
|||
if not is_onyomi[yomi[i][1]] then all_onyomi = false; break end |
|||
elseif #all_yomi == 2 then |
|||
end |
|||
local y1, y2 = all_yomi[1].data, all_yomi[2].data |
|||
if all_onyomi then |
|||
if ulen(pagename) == 2 then |
|||
insert(categories, yomi_info.on.category) |
|||
if y1.onyomi and y2.type == "kun'yomi" then |
|||
elseif yomi[1][1] == 'jūbakoyomi' or yomi[1][1] == 'yutōyomi' then |
|||
yomi_cat = yomi_data.j -- jūbakoyomi |
|||
insert(categories, yomi_info[yomi[1][1]].category) |
|||
elseif y1.type == "kun'yomi" and y2.onyomi then |
|||
else |
|||
yomi_cat = yomi_data.y -- yutōyomi |
|||
local all_yomi_of_same_type = true |
|||
for i = 2, #yomi do |
|||
if yomi[i][1] ~= yomi[1][1] then all_yomi_of_same_type = false; break end |
|||
end |
|||
if all_yomi_of_same_type then |
|||
insert(categories, yomi_info[yomi[1][1]].category) |
|||
elseif #yomi == 2 and yomi[1][2] == 1 and yomi[2][2] == 1 and ulen(pagename) == 2 then |
|||
if is_onyomi[yomi[1][1]] and yomi[2][1] == 'kun' then |
|||
insert(categories, yomi_info["jūbakoyomi"].category) |
|||
elseif yomi[1][1] == 'kun' and is_onyomi[yomi[2][1]] then |
|||
insert(categories, yomi_info["yutōyomi"].category) |
|||
end |
end |
||
end |
|||
end |
|||
if yomi_cat then |
|||
local category = yomi_cat.reading_category |
|||
if category ~= false then |
|||
insert(categories, lang_name .. " " .. "terms read with " .. (category or yomi_cat.type)) |
|||
end |
end |
||
end |
end |
||
Line 428: | Line 389: | ||
kanji_table = table_head |
kanji_table = table_head |
||
for _, v in ipairs(kanji) do |
for _, v in ipairs(kanji) do |
||
kanji_table = kanji_table .. |
kanji_table = kanji_table .. "| style=\"padding: 0.5em;\" | [[" .. v .. "#" .. lang_name .. "|" .. v .. "]]\n" |
||
end |
end |
||
kanji_table = kanji_table .. concat(cells, |
kanji_table = kanji_table .. concat(cells, "\n") .. "\n|}" |
||
else |
else |
||
kanji_table = |
kanji_table = "" |
||
end |
end |
||
local forms_table = "" |
local forms_table = "" |
||
if args.alt == |
if args.alt == "" or args.alt == "-" then args.alt = nil end |
||
if kyu[1] or args.alt then |
if kyu[1] or args.alt then |
||
local forms = {} |
local forms = {} |
||
-- |kyu= |
-- |kyu= |
||
if kyu[1] == |
if kyu[1] == "which 弁?" then |
||
insert(forms, |
insert(forms, "<strong class=\"error\" style=\"font-size:75%;\">Please specify the correct kyujitai for 弁 with the parameter \"kyu\".</strong>[[Category:Requests for cleanup in " .. lang_name .. " entries]]") |
||
remove(kyu, 1) |
remove(kyu, 1) |
||
end |
end |
||
Line 450: | Line 411: | ||
if not form_linkto then form_linkto, form_display = form, form end |
if not form_linkto then form_linkto, form_display = form, form end |
||
insert(forms, concat{ |
insert(forms, concat{ |
||
"<span class=\"Jpan\" lang=\"" .. lang_code .. "\" style=\"font-family:游ゴシック, HanaMinA, sans-serif; font-size:140%;\">[[", |
|||
form_linkto, |
form_linkto, |
||
form_linkto == pagename and |
form_linkto == pagename and "|" or "#" .. lang_name .. "|", |
||
form_display, |
form_display, |
||
"]]</span> <small>", |
|||
show_labels {labels = { |
show_labels {labels = {"kyūjitai"}, lang = lang, nocat = true }, |
||
"</small>", |
|||
}) |
}) |
||
end |
end |
||
Line 462: | Line 423: | ||
-- |alt= |
-- |alt= |
||
if args.alt then |
if args.alt then |
||
for form in gsplit(args.alt, |
for form in gsplit(args.alt, ",") do |
||
local i_semicolon = find(form, ":") |
local i_semicolon = find(form, ":") |
||
if i_semicolon then |
if i_semicolon then |
||
local altform = sub(form, 1, i_semicolon - 1) |
local altform = sub(form, 1, i_semicolon - 1) |
||
local altlabels = split(sub(form, i_semicolon + 1), |
local altlabels = split(sub(form, i_semicolon + 1), " ") |
||
insert(forms, concat{ |
insert(forms, concat{ |
||
"<span class=\"Jpan\" lang=\"" .. lang_code .. "\" style=\"font-size:140%\">[[", |
|||
altform, |
altform, |
||
"#" .. lang_name .. "|", |
|||
altform, |
altform, |
||
"]]</span> <small>", |
|||
show_labels { labels = altlabels, lang = lang, nocat = true }, |
show_labels { labels = altlabels, lang = lang, nocat = true }, |
||
"</small>", |
|||
}) |
}) |
||
else |
else |
||
insert(forms, concat{ |
insert(forms, concat{ |
||
"<span class=\"Jpan\" lang=\"" .. lang_code .. "\" style=\"font-size:140%\">[[", |
|||
form, |
form, |
||
"#" .. lang_name .. "|", |
|||
form, |
form, |
||
"]]</span>" |
|||
}) |
}) |
||
end |
end |
||
Line 488: | Line 449: | ||
end |
end |
||
forms_table = |
forms_table = "\n" .. [[{| class="wikitable floatright" |
||
! style="font-weight:normal" | Alternative spelling]] .. (#forms == 1 and "" or "s") .. [[ |
! style="font-weight:normal" | Alternative spelling]] .. (#forms == 1 and "" or "s") .. [[ |
||
|- |
|- |
||
| style="text-align:center;font-size:108%" | ]] .. concat(forms, |
| style="text-align:center;font-size:108%" | ]] .. concat(forms, "<br>") .. "\n|}" |
||
end |
end |
||
Line 498: | Line 459: | ||
if args.alt2 and args.alt2 ~= "" and args.alt2 ~= "-" then |
if args.alt2 and args.alt2 ~= "" and args.alt2 ~= "-" then |
||
local forms2 = {} |
local forms2 = {} |
||
for form in gsplit(args.alt2, |
for form in gsplit(args.alt2, ",") do |
||
insert(forms2, |
insert(forms2, "<span class=\"Jpan\" lang=\"" .. lang_code .. "\">[[" .. form .. "#" .. lang_name .. "|" .. form .. "]]</span>") |
||
end |
end |
||
forms_table2 = |
forms_table2 = "\n" .. [[{| class="wikitable floatright" |
||
! style="font-weight:normal" | Variant form]] .. (#forms2 == 1 and "" or "s") .. |
! style="font-weight:normal" | Variant form]] .. (#forms2 == 1 and "" or "s") .. "\n" .. [[ |
||
| style="text-align:center;font-size:140%" | ]] .. concat(forms2, |
| style="text-align:center;font-size:140%" | ]] .. concat(forms2, "<br>") .. "\n|}" |
||
end |
end |
||
Line 518: | Line 479: | ||
for _, v in ipairs(readings_actual) do |
for _, v in ipairs(readings_actual) do |
||
id = id + v[2] |
id = id + v[2] |
||
insert(sortkey, (v[1] or |
insert(sortkey, (v[1] or "") .. (non_kanji[id] or "")) |
||
end |
end |
||
sortkey = concat(sortkey) |
sortkey = concat(sortkey) |
Revision as of 19:14, 17 July 2024
- The following documentation is located at Module:kanjitab/documentation. [edit]
- Useful links: subpage list • links • transclusions • testcases • sandbox
This module generates the content of {{ja-kanjitab}}
, {{ryu-kanjitab}}
etc.
Testcases
Kanji in this term |
---|
懐 |
なつ Grade: S |
kun'yomi |
Alternative spelling |
---|
懷かしい (kyūjitai) |
Kanji in this term | |
---|---|
取 | 締 |
と(り) Grade: 3 |
し(まり) Grade: S |
kun'yomi |
Kanji in this term | |
---|---|
日 | 付 |
ひ Grade: 1 |
つ(け) > づ(け) Grade: 4 |
kun'yomi |
Kanji in this term | |
---|---|
関 | 係 |
かん Grade: 4 |
けい Grade: 3 |
kan'on |
Alternative spelling |
---|
關係 (kyūjitai) |
Kanji in this term | |
---|---|
東 | 京 |
とう Grade: 2 |
きょう Grade: 2 |
kan'on | goon |
Kanji in this term | |||
---|---|---|---|
大 | 和 | 言 | 葉 |
やまと | こと Grade: 2 |
は > ば Grade: 3 | |
Grade: 1 | Grade: 3 | ||
jukujikun | kun'yomi |
Kanji in this term | |||
---|---|---|---|
滅 | 茶 | 苦 | 茶 |
め Grade: S (ateji) |
ちゃ Grade: 2 (ateji) |
く Grade: 3 (ateji) |
ちゃ Grade: 2 (ateji) |
irregular | kan'yōon | goon | kan'yōon |
Kanji in this term | |||||||||
---|---|---|---|---|---|---|---|---|---|
阿 | 弗 | 利 | 加 | 系 | 亜 | 米 | 利 | 加 | 人 |
あ Jinmeiyō (ateji) |
ふつ > ふ Hyōgai (ateji) |
り Grade: 4 (ateji) |
か Grade: 4 (ateji) |
けい Grade: 6 |
あ Grade: S (ateji) |
め Grade: 2 (ateji) |
り Grade: 4 (ateji) |
か Grade: 4 (ateji) |
じん Grade: 1 |
on'yomi | irregular | on'yomi | kan'on | kan'on | kan'on | irregular | on'yomi | kan'on | kan'on |
Alternative spelling |
---|
阿弗利加系亞米利加人 (kyūjitai) |
{{ja-kanjitab|pagename=大和言葉|||こと|は|k4=ば|yomi=juku2,k2}} {{ja-kanjitab|pagename=大和言葉|やまと2|こと|は|k3=ば|yomi=juku2,k2}} // "3" is # of argument, not # of kanji
local export = {}
local m_str_utils = require("Module:string utilities")
local m_utilities = require("Module:utilities")
local m_ja = require("Module:ja")
local show_labels = require("Module:labels").show_labels
--[=[
Other modules used: [[Module:parameters]]
]=]
local concat = table.concat
local convert_iteration_marks = require("Module:Hani").convert_iteration_marks
local find = string.find
local gsplit = m_str_utils.gsplit
local gsub = string.gsub
local kata_to_hira = m_ja.kata_to_hira
local insert = table.insert
local match = string.match
local remove = table.remove
local split = m_str_utils.split
local sub = string.sub
local ugsub = mw.ustring.gsub
local ulen = m_str_utils.len
local umatch = mw.ustring.match
local usub = m_str_utils.sub
local PAGENAME = mw.loadData("Module:headword/data").pagename
local NAMESPACE = mw.title.getCurrentTitle().nsText
local d_range = mw.loadData("Module:ja/data/range")
local yomi_data = mw.loadData("Module:kanjitab/data")
local kanji_grade_links = {
"[[Appendix:Japanese_glossary#kyōiku_kanji|Grade: 1]]",
"[[Appendix:Japanese_glossary#kyōiku_kanji|Grade: 2]]",
"[[Appendix:Japanese_glossary#kyōiku_kanji|Grade: 3]]",
"[[Appendix:Japanese_glossary#kyōiku_kanji|Grade: 4]]",
"[[Appendix:Japanese_glossary#kyōiku_kanji|Grade: 5]]",
"[[Appendix:Japanese_glossary#kyōiku_kanji|Grade: 6]]",
"[[Appendix:Japanese_glossary#jōyō_kanji|Grade: S]]", -- 7
"[[Appendix:Japanese_glossary#jinmeiyō_kanji|Jinmeiyō]]", -- 8
"[[Appendix:Japanese_glossary#hyōgai_kanji|Hyōgai]]" -- 9
}
-- this is the function that is called from templates
function export.show(frame)
local args = require("Module:parameters").process(frame:getParent().args, {
[1] = { list = true, allow_holes = true },
k = { list = true, allow_holes = true },
o = { list = true, allow_holes = true },
r = {},
sort = {},
yomi = {},
ateji = {},
alt = {},
alt2 = {},
kyu = { list = true },
y = {alias_of = "yomi"},
clearright = {type = "boolean"},
pagename = {},
})
local lang_code = frame.args[1]
local lang = require("Module:languages").getByCode(lang_code)
local lang_name = lang:getCanonicalName()
if args.pagename and NAMESPACE == "" then
require("Module:debug/track")("kanjitab/pagename param in mainspace")
end
local pagename = args.pagename or PAGENAME
local categories = {}
local cells = {}
-- extract kanji and non-kanji
local kanji = {}
local non_kanji = {}
-- 々 and 〻
pagename = convert_iteration_marks(pagename)
local kanji_border = 1
ugsub(pagename, "()([" .. d_range.kanji .. "々〻])()", function(p1, w1, p2)
insert(non_kanji, usub(pagename, kanji_border, p1 - 1))
kanji_border = p2
insert(kanji, w1)
end)
insert(non_kanji, usub(pagename, kanji_border))
-- kyujitai
local kyu = args.kyu
if kyu[1] == "-" then
kyu = {}
elseif kyu[1] == nil then
local form_kyu = {non_kanji[1]}
local kyu_data = mw.loadData("Module:ja/data/kyu")
local has_kyu, has_kyu_nonsupple, has_shin = false, false, false
for i, v in ipairs(kanji) do
local v_kyu = match(kyu_data[1], v .. "(%S*)%s")
if v_kyu == nil then
insert(form_kyu, v)
elseif v_kyu == "" then
has_shin = true
break
elseif v_kyu:sub(1, 1) == "&" then
has_kyu = true
insert(form_kyu, v_kyu)
else
has_kyu, has_kyu_nonsupple = true, true
insert(form_kyu, v_kyu)
end
insert(form_kyu, non_kanji[i + 1])
end
if not has_shin and has_kyu then
kyu[1] = (has_kyu_nonsupple and "" or pagename .. "|") .. concat(form_kyu)
end
if find(pagename, "弁") then
require("Module:debug/track")("kanjitab/ambiguous kyujitai for 弁")
kyu[1] = "which 弁?"
end
end
local all_yomi, missing_yomi
if args.yomi then
all_yomi = {}
local keys = split(args.yomi, ",")
for i, yomi, len in ipairs(keys) do
yomi, len = match(yomi, "^(%l*)(%d*)$")
yomi = yomi_data[yomi] or error("The yomi type \"" .. yomi .. "\" in the input \"" .. args.yomi .. "\" is not recognized.")
if len ~= "" then
-- Disallow length 0 or leading zeroes, as a sanity check.
len = match(len, "^[1-9]%d*$") and tonumber(len) or error("Cannot specify a length of " .. len .. " kanji.")
-- Only one yomi with no length given: apply to all kanji.
elseif i == 1 and #keys == 1 then
len = #kanji
else
len = 1
end
local yomi_type = yomi.type
-- If the on'yomi is not specified as goon/kanon/toon/soon, only "on".
if yomi_type == "on'yomi" then
require("Module:debug/track")("kanjitab/unspecified on")
elseif yomi_type == "jūbakoyomi" then
require("Module:debug/track")("kanjitab/jubakoyomi")
elseif yomi_type == "yutōyomi" then
require("Module:debug/track")("kanjitab/yutoyomi")
end
-- If the yomi requires a specific number of kanji (e.g. jūbakoyomi, yutōyomi).
local req_kanji = yomi.required_kanji
if req_kanji and #kanji ~= req_kanji then
error("The yomi type \"" .. yomi.type .. "\" is only applicable to terms with " .. req_kanji .. " kanji.")
elseif yomi.type == "none" then
missing_yomi = true
end
-- Insert yomi data for each applicable kanji. Wrap in a table first, as the range for this input yomi is determined by its identity, so that (e.g.) "kun,kun" is still treated as two separate inputs.
yomi = {data = yomi}
for _ = 1, len do
insert(all_yomi, yomi)
end
end
-- If there are any yomi slots left, handle them as empty.
if #all_yomi < #kanji then
missing_yomi = true
for _ = #all_yomi + 1, #kanji do
insert(all_yomi, {data = yomi_data.none})
end
end
elseif #kanji > 0 then
missing_yomi = true
end
if missing_yomi then
insert(categories, lang_name .. " terms with missing yomi")
end
-- process readings
local readings = {}
local readings_actual = {}
local reading_length_total = 0
for i = 1, args[1].maxindex do
local reading_kana, reading_length = match(args[1][i] or "", "^(%D*)(%d*)$")
reading_kana = reading_kana ~= "" and reading_kana or nil
reading_length = reading_kana and tonumber(reading_length) or 1
insert(readings, {reading_kana, reading_length})
reading_length_total = reading_length_total + reading_length
end
if reading_length_total > #kanji then
error("Readings for " .. reading_length_total .. " kanji are given, but this word has only " .. #kanji .. " kanji.")
else
for _ = reading_length_total + 1, #kanji do
insert(readings, {nil, 1})
end
end
local table_head = [=[
{| class="wikitable kanji-table floatright" style="text-align: center; ]=] .. (args.clearright and " clear:right;" or "") .. [=["
! ]=] .. (#kanji > 1 and "colspan=\"" .. #kanji .. "\" " or "") .. [=[style="font-weight: normal;" | [[Appendix:Japanese_glossary#kanji|Kanji]] in this term
|- lang="]=] .. lang_code .. [=[" class="Jpan" style="font-size: 2em; background: white; line-height: 1em;"
]=]
if args.k.maxindex and args.k.maxindex > args[1].maxindex then
error("kanjitab/too many k")
end
if args.o.maxindex and args.o.maxindex > args[1].maxindex then
error("kanjitab/too many o")
end
local is_ateji = {}
if args.ateji then
local ateji = args.ateji
local cat_ateji = false
if ateji == "y" then
for i = 1, #kanji do
is_ateji[i] = true
end
cat_ateji = true
else
for i in gsplit(ateji, ";") do
gsub(i, "^(%d+)$", function(a)
is_ateji[tonumber(a)] = true
cat_ateji = true
end)
gsub(i, "^(%d+),(%d+)$", function (a, b)
for j = tonumber(a), tonumber(b) do
is_ateji[j] = true
end
cat_ateji = true
end)
end
end
if cat_ateji then insert(categories, lang_name .. " terms spelled with ateji") end
end
-- if hiragana readings were passed,
-- make the "spelled with ..." categories, the readings cells on the lower level and build the sort key
-- otherwise rely on the pagename to make the original kanjitab and categories
local cells_above = {}
local cells_below = {}
local kanji_pos = 1
for i, reading in ipairs(readings) do
local reading_kana, reading_length = reading[1], reading[2]
local cell = {}
if reading_length <= 1 then
insert(cell, "| rowspan=\"2\" | ")
else
insert(cell, "| colspan =\"" .. reading_length .. "\" | ")
end
-- display reading, actual reading and okurigana
if reading_kana then
if reading_kana ~= "" and reading_kana ~= "-" and umatch(reading_kana, "[^" .. d_range.kana .. "]") then
error("Please remove any non-kana characters from the reading input " .. reading_kana .. ".")
end
local actual_reading = args.k[i]
local okurigana = args.o[i]
local okurigana_text = okurigana and "(" .. okurigana .. ")" or ""
local actual_reading_text = actual_reading and " > " .. actual_reading .. okurigana_text or ""
local text = reading_kana .. okurigana_text .. actual_reading_text
readings_actual[i] = {(actual_reading or reading_kana) .. (okurigana or ""), reading_length}
insert(cell, "<span class=\"Jpan\" lang=\"" .. lang_code .. "\">" .. text .. "</span>")
if reading_length <= 1 then insert(cell, "<br/>") end
else
readings_actual[i] = {nil, 1}
end
-- display kanji grade, categorize
for j = kanji_pos, kanji_pos + reading_length - 1 do
local single_kanji = kanji[j]
local kanji_grade = m_ja.kanji_grade(single_kanji)
local ateji_text = is_ateji[j] and "<br/><small>([[Appendix:Japanese glossary#ateji|ateji]])</small>" or ""
local type, compound
if all_yomi then
local yomi = all_yomi[j].data
type, compound = yomi.type, yomi.compound_reading
end
if not reading_kana then
if type ~= "irregular" then
require("Module:debug/track")("kanjitab/no reading")
end
insert(categories, lang_name .. " terms spelled with " .. single_kanji)
elseif reading_length ~= 1 or type == "irregular" then
insert(categories, lang_name .. " terms spelled with " .. single_kanji)
elseif compound then
-- Re-enable once all bad jukujikun calls are fixed.
-- error("The yomi type \"" .. type .. "\" is only applicable to compound character readings, so cannot apply to " .. single_kanji .. " read as " .. reading_kana .. ". If this is intended as part of a " .. type .. " reading, please enter the whole reading as one, followed by the number of kanji it applies to.")
require("Module:debug/track")("kanjitab/single kanji with jukujikun")
else -- Subcategorize by reading.
insert(categories, lang_name .. " terms spelled with " .. single_kanji .. " read as " .. kata_to_hira(reading_kana))
end
if reading_length <= 1 then
insert(cell, "<small>" .. kanji_grade_links[kanji_grade] .. "</small>" .. ateji_text)
else
insert(cells_below, "| <small>" .. kanji_grade_links[kanji_grade] .. "</small>" .. ateji_text)
end
end
insert(cells_above, concat(cell))
kanji_pos = kanji_pos + reading_length
end
insert(cells, "|- style=\"background: white;\"")
if #cells_below > 0 then
insert(cells, concat(cells_above, "\n"))
insert(cells, "|- style=\"background: white;\"")
insert(cells, concat(cells_below, "\n"))
else
for i, v in ipairs(cells_above) do
cells_above[i] = gsub(v, "| rowspan=\"2\" | ", "| ")
end
insert(cells, concat(cells_above, "\n"))
end
local rendaku = args.r
if rendaku then
insert(categories, lang_name .. " terms with rendaku")
end
if all_yomi then
insert(cells, "|-")
local len, all_on, yomi_cat = 1, true
for i, yomi in ipairs(all_yomi) do
-- If the next kanji has the same yomi table, it's part of the same range.
if yomi == all_yomi[i + 1] then
len = len + 1
else
yomi = yomi.data
local yomi_type = yomi.type
local display = yomi.display or yomi_type
local appendix = yomi.appendix
insert(cells, "| colspan=\"" .. len .. "\" |" .. (
appendix == false and display or
"[[Appendix:Japanese_glossary#" .. (appendix or yomi_type) .. "|" .. display .. "]]"
))
-- Categorise as irregular if any irregular yomi are found; otherwise, categorise if all yomi are of the same type. If yomi are of different types but are all on, on'yomi is used as a fallback.
if yomi_cat ~= "irregular" then
local cat_type = yomi_type
if cat_type == "irregular" or yomi_cat == nil then
yomi_cat = cat_type
elseif yomi_cat ~= cat_type then
yomi_cat = false
end
if not yomi.onyomi then
all_on = false
end
end
len = 1
end
end
if yomi_cat then
-- Check yomi_data first, in case cat_type is "irregular"; if no match, must be some other type, so get it from the first yomi in all_yomi, since not all yomi types are yomi_data keys.
yomi_cat = yomi_data[yomi_cat] or all_yomi[1].data
elseif all_on then
yomi_cat = yomi_data.on
elseif #all_yomi == 2 then
local y1, y2 = all_yomi[1].data, all_yomi[2].data
if ulen(pagename) == 2 then
if y1.onyomi and y2.type == "kun'yomi" then
yomi_cat = yomi_data.j -- jūbakoyomi
elseif y1.type == "kun'yomi" and y2.onyomi then
yomi_cat = yomi_data.y -- yutōyomi
end
end
end
if yomi_cat then
local category = yomi_cat.reading_category
if category ~= false then
insert(categories, lang_name .. " " .. "terms read with " .. (category or yomi_cat.type))
end
end
end
local kanji_table
if #kanji > 0 then
kanji_table = table_head
for _, v in ipairs(kanji) do
kanji_table = kanji_table .. "| style=\"padding: 0.5em;\" | [[" .. v .. "#" .. lang_name .. "|" .. v .. "]]\n"
end
kanji_table = kanji_table .. concat(cells, "\n") .. "\n|}"
else
kanji_table = ""
end
local forms_table = ""
if args.alt == "" or args.alt == "-" then args.alt = nil end
if kyu[1] or args.alt then
local forms = {}
-- |kyu=
if kyu[1] == "which 弁?" then
insert(forms, "<strong class=\"error\" style=\"font-size:75%;\">Please specify the correct kyujitai for 弁 with the parameter \"kyu\".</strong>[[Category:Requests for cleanup in " .. lang_name .. " entries]]")
remove(kyu, 1)
end
for _, form in ipairs(kyu) do
local form_linkto, form_display = match(form, "^(.+)|(.+)$")
if not form_linkto then form_linkto, form_display = form, form end
insert(forms, concat{
"<span class=\"Jpan\" lang=\"" .. lang_code .. "\" style=\"font-family:游ゴシック, HanaMinA, sans-serif; font-size:140%;\">[[",
form_linkto,
form_linkto == pagename and "|" or "#" .. lang_name .. "|",
form_display,
"]]</span> <small>",
show_labels {labels = {"kyūjitai"}, lang = lang, nocat = true },
"</small>",
})
end
-- |alt=
if args.alt then
for form in gsplit(args.alt, ",") do
local i_semicolon = find(form, ":")
if i_semicolon then
local altform = sub(form, 1, i_semicolon - 1)
local altlabels = split(sub(form, i_semicolon + 1), " ")
insert(forms, concat{
"<span class=\"Jpan\" lang=\"" .. lang_code .. "\" style=\"font-size:140%\">[[",
altform,
"#" .. lang_name .. "|",
altform,
"]]</span> <small>",
show_labels { labels = altlabels, lang = lang, nocat = true },
"</small>",
})
else
insert(forms, concat{
"<span class=\"Jpan\" lang=\"" .. lang_code .. "\" style=\"font-size:140%\">[[",
form,
"#" .. lang_name .. "|",
form,
"]]</span>"
})
end
end
end
forms_table = "\n" .. [[{| class="wikitable floatright"
! style="font-weight:normal" | Alternative spelling]] .. (#forms == 1 and "" or "s") .. [[
|-
| style="text-align:center;font-size:108%" | ]] .. concat(forms, "<br>") .. "\n|}"
end
local forms_table2 = ""
if args.alt2 and args.alt2 ~= "" and args.alt2 ~= "-" then
local forms2 = {}
for form in gsplit(args.alt2, ",") do
insert(forms2, "<span class=\"Jpan\" lang=\"" .. lang_code .. "\">[[" .. form .. "#" .. lang_name .. "|" .. form .. "]]</span>")
end
forms_table2 = "\n" .. [[{| class="wikitable floatright"
! style="font-weight:normal" | Variant form]] .. (#forms2 == 1 and "" or "s") .. "\n" .. [[
| style="text-align:center;font-size:140%" | ]] .. concat(forms2, "<br>") .. "\n|}"
end
-- use user-provided sortkey if we got one, otherwise
-- use the sortkey we've already made by combining the
-- readings if provided, if we have neither then
-- default to empty string and don't sort
local sortkey
if args.sort then
sortkey = args.sort
else
sortkey = {non_kanji[1]}
local id = 1
for _, v in ipairs(readings_actual) do
id = id + v[2]
insert(sortkey, (v[1] or "") .. (non_kanji[id] or ""))
end
sortkey = concat(sortkey)
end
if sortkey == "" then
sortkey = nil
else
sortkey = lang:makeSortKey(sortkey)
end
if sortkey ~= lang:makeSortKey(PAGENAME) then
require("Module:debug/track"){"kanjitab/nonstandard sortkey", "kanjitab/nonstandard sortkey/" .. lang_code}
end
return kanji_table .. forms_table .. forms_table2 .. m_utilities.format_categories(categories, lang, sortkey)
end
return export
Categories:
- Southern Amami Ōshima modules
- Language-specific utility modules
- Japanese modules
- Old Japanese modules
- Kunigami modules
- Kikai modules
- Okinawan modules
- Proto-Ryukyuan modules
- Miyako modules
- Yonaguni modules
- Northern Amami Ōshima modules
- Yaeyama modules
- Hachijō modules
- Proto-Japonic modules
- Tokunoshima modules
- Okinoerabu modules
- Yoron modules