local export = {}
local find = mw.ustring.find
local len = mw.ustring.len
local gsub = mw.ustring.gsub
local match = mw.ustring.match
local gmatch = mw.ustring.gmatch
local split = mw.text.split
local m_ja = require('Modül:ja')
local function gmatch_array(s, pattern) local result = {} for e in gmatch(s, pattern) do table.insert(result, e) end return result end
local function map(arr, f) local result = {} for _, e in ipairs(arr) do local fe = f(e) if fe ~= nil then table.insert(result, fe) end end return result end
local function filter(arr, f) local result = {} for _, e in ipairs(arr) do if f(e) then table.insert(result, e) end end return result end
local function contains(arr, item) for _, e in ipairs(arr) do if e == item then return true end end return false end
local function set(arr) local result = {} for _, e in ipairs(arr) do if not contains(result, e) then table.insert(result, e) end end return result end
local function flatten(arrs) local result = {} for _, arr in ipairs(arrs) do for _, e in ipairs(arr) do table.insert(result, e) end end return result end
-- f should be str->str in the following functions
local function memoize(f) local results = {} return function(s) if not results then results = f(s) end return results end end
local getContent_memo = memoize(function(title) return mw.title.new(title):getContent() or '' end)
local function group(arr, f) local r = {} for _, e in ipairs(arr) do local fe = f(e) if r and r.key == fe then table.insert(r, e) else table.insert(r, { e, key = fe }) end end return r end
local function ja(text) return '<span lang="ja" class="Jpan">' .. text .. '</span>' end
local function link(lemma, display) return ja(']') end
local function link_bracket(lemma, display) return ja('【]】') end
--[[ returns an array of definitions, each having the format
{ def = <definition>,
kanji_spellings = <array of alternative kanji spellings listed in {{ja-kanjitab|alt=...}}, can be overrided with {{ja-def|...}}>,
kana_spellings = <array of alternative kana spellings listed in the headword template>,
historical_kana_spellings = <array of historical kana spellings listed in the headword template>,
header = <name of PoS header>,
headword_line = <wikicode of headword line> }
]]
local function get_definitions_from_wikicode(wikicode)
local current_kanji_spellings = {}
local current_kana_spellings = {}
local current_historical_kana_spellings = {}
local current_header
local current_headword_line
local currently_under_headword_line = false
local result = {}
for line in gmatch(match(wikicode, '==Japonca==\n(.*)') or '', '+') do
-- the following branches are ordered by frequency; read backwards
if currently_under_headword_line and find(line, '^#+') then
table.insert(result, { def = line,
kanji_spellings = find(line, '{{ja%-anlam|') and split(match(line, '{{ja%-anlam|(+)'), '|')
or find(line, '<!%-%- sadece kana %-%->') and {}
or current_kanji_spellings,
kana_spellings = current_kana_spellings,
historical_kana_spellings = current_historical_kana_spellings,
header = current_header,
headword_line = current_headword_line })
elseif find(line, '^{{ja%-ad')
or find(line, '^{{ja%-ön ad')
or find(line, '^{{ja%-söz')
or find(line, '^{{ja%-phrase')
or find(line, '^{{ja%-eylem')
or find(line, '^{{ja%-verb form')
or find(line, '^{{ja%-verb%-suru') then
local escaped_line = gsub(gsub(line, '%|]-)|(|]-)%]%]', ']'), '|hkata=', '|hhira=')
current_kana_spellings = map(gmatch_array(escaped_line, '|(+)'), m_ja.remove_ruby_markup)
current_historical_kana_spellings = gmatch_array(escaped_line, '|hhira=(+)')
current_headword_line = line
currently_under_headword_line = true
elseif find(line, '^===++===+$') then
current_header = match(line, '^===+(+)===+$')
currently_under_headword_line = false
elseif find(line, '^{{ja%-kanjitab') then
local alt_argument = match(line, '|alt=(*)')
current_kanji_spellings = alt_argument and split(gsub(alt_argument, ':*', ''), ',') or {}
elseif line == '----' then
break
end
end
return result
end
-- ditto, except that each definition also contains the title of the page it is from
local function get_definitions_from_entry(title)
local wikicode = getContent_memo(title)
local defs = get_definitions_from_wikicode(wikicode)
map(defs, function(def)
def.title = title
table.insert(({ Hira = true, Kana = true, = true }) and def.kana_spellings or def.kanji_spellings, title)
end)
return defs
end
local function get_definitions_from_entries(titles)
return flatten(map(titles, get_definitions_from_entry))
end
local function format_table_content(defs, frame)
local kanji_grade_labels = {
'<span class="explain" title="Sınıf 1 kanji" style="vertical-align: top;">1</span>',
'<span class="explain" title="Sınıf 2 kanji" style="vertical-align: top;">2</span>',
'<span class="explain" title="Sınıf 3 kanji" style="vertical-align: top;">3</span>',
'<span class="explain" title="Sınıf 4 kanji" style="vertical-align: top;">4</span>',
'<span class="explain" title="Sınıf 5 kanji" style="vertical-align: top;">5</span>',
'<span class="explain" title="Sınıf 6 kanji" style="vertical-align: top;">6</span>',
'<span class="explain" title="Jōyō kanji" style="vertical-align: top;">S</span>',
'<span class="explain" title="Jinmeiyō kanji" style="vertical-align: top;">J</span>',
'<span class="explain" title="Hyōgaiji kanji" style="vertical-align: top;">H</span>' }
local function ruby(kanji, kana) -- this function ought to be in ]
local kanji_segments = gsub(kanji, "(+)", "`%1`")
-- returns possible matches between kanji and kana
-- for example, match('`物`の`哀`れ', 'もののあわれ') returns { '(も)の(のあわ)れ', '(もの)の(あわ)れ' }
local function match(kanji_segments, kana)
if kanji_segments:find('`') then
local kana_portion, kanji_portion, rest = mw.ustring.match(kanji_segments, '(.-)`(.-)`(.*)')
_, _, kana = mw.ustring.find(kana, '^' .. kana_portion .. '(.*)')
if not kana then return {} end
local candidates = {}
for i = 1, mw.ustring.len(kana) do
for _, candidate in ipairs(match(rest, mw.ustring.sub(kana, i + 1))) do
table.insert(candidates, kana_portion .. '(' .. mw.ustring.sub(kana, 1, i) .. ')' .. candidate)
end
end
return candidates
else
return (kanji_segments == kana) and { kana } or {}
end
end
local matches = match(kanji_segments, kana)
local result = #matches == 1 and matches or ('(' .. kana .. ')')
return gsub(result, "%]+)%]%((+)%)", "<ruby><rb>%1</rb><rt>%2</rt></ruby>")
end
local function format_headword(defs)
local title = defs.title
local kana = defs.kana_spellings
local headword = link_bracket(title, mw.title.getCurrentTitle().text == kana and title or ruby(title, kana))
local kanji_grade = len(title) == 1 and m_ja.kanji_grade(title)
return '<span style="font-size:x-large">' .. headword .. '</span>' .. (kanji_grade and kanji_grade_labels or '')
end
local preprocess_memo = memoize(function (s) return frame:preprocess(s) end)
local function format_definitions(defs)
local headword_line_categories = {}
local alt_forms = {}
local function format_definition(def)
local def_text = find(def.def, '{{rfdef') and "''Bu sözcüğün Türkçe çevirisi gerekiyor.''" or preprocess_memo(gsub(def.def, '^#+ *', ''))
local def_prefix = gsub(match(def.def, '^#+'), '#', ':')
local def_pos_label = ' <span style="padding-right:.6em;color:#5A5C5A;font-size:80%"></span> '
local headword_line = gsub(def.headword_line, '%%', '')
if ({ Hira = true, Kana = true, = true }) then
headword_line = gsub(headword_line, '}}$', '|hira=' .. def.title .. '}}')
end
table.insert(headword_line_categories, table.concat(gmatch_array(preprocess_memo(headword_line), '%%]')))
map(def.kanji_spellings, function(s) if s ~= def.title and not contains(alt_forms, s) then table.insert(alt_forms, s) end end)
map(def.kana_spellings, function(s) if s ~= def.kana_spellings and s ~= mw.title.getCurrentTitle().text and not contains(alt_forms, s) then table.insert(alt_forms, s) end end)
return def_prefix .. def_pos_label .. def_text
end
local formatted_defs = table.concat(map(defs, format_definition), '\n')
if #alt_forms == 1 and alt_forms == mw.title.getCurrentTitle().text then alt_forms = {} end
return table.concat(headword_line_categories) .. '\n' .. formatted_defs
.. (#alt_forms > 0 and '\n: <div style="background:#f8f9fa"><span style="color:#5A5C5A;font-size:80%">'
.. (#alt_forms == 1 and 'Farklı yazılış' or 'Farklı yazılışlar')
.. '</span><br><span style="margin-left:.8em">'
.. table.concat(map(alt_forms, link), ', ')
.. '</span></div>' or '')
end
local is_first_row = true
local function format_row(defs)
local result = '|-\n| style="white-space:nowrap;width:15%;vertical-align:top;' .. (is_first_row and '' or 'border-top:1px solid lightgray;') .. '" | ' .. format_headword(defs)
.. '\n| style="' .. (is_first_row and '' or 'border-top:1px solid lightgray;') .. '" |\n' .. format_definitions(defs) .. '\n'
is_first_row = false
return result
end
local def_groups = group(defs, function(def) return def.title .. ',' .. def.kana_spellings end)
local rows = map(def_groups, format_row)
return '{| style="width: 100%"\n' .. table.concat(rows) .. '|}'
end
function export.show(frame, mode)
local title = mw.title.getCurrentTitle().text
local lemmas, key
if not mode or mode == 'kango' then
local params = {
= { list = true },
= {},
}
local args, unrecognized_args = require("Modül:parameters").process(frame:getParent().args, params, true)
for key, value in pairs(unrecognized_args) do error("“" .. key .. "” parametresi tanınmıyor.") end
lemmas = args
key = args.key or title
elseif mode == 'glyphvar' then
local params = {
= {},
}
local args, unrecognized_args = require("Modül:parameters").process(frame:getParent().args, params, true)
for key, value in pairs(unrecognized_args) do error("“" .. key .. "” parametresi tanınmıyor.") end
local wikicode = getContent_memo(args)
local _lemmas = flatten({ gmatch_array(wikicode, '{{ja%-bak|(+)'), gmatch_array(wikicode, '{{ja%-bak%-kango|(+)') })
_lemmas = flatten(map(_lemmas, function(arglist) return split(arglist, '|') end))
_lemmas = filter(_lemmas, function(arg) return not find(arg, '=') end)
_lemmas = set(flatten({ {args}, _lemmas }))
lemmas = _lemmas
key = args
end
local defs = get_definitions_from_entries(lemmas)
local matching_defs = filter(defs, function(def)
return contains(def.kanji_spellings, key) or contains(def.kana_spellings, key) or contains(def.historical_kana_spellings, key)
end)
local table_header = ja(title) .. ' söylenişi ve anlamları için – '
.. (#matching_defs == 0 and (table.concat(map(lemmas, function(title) return '<span style="font-size:120%">' .. link(title) .. '</span>' end), ', '))
or #group(matching_defs, function(def) return def.title end) == 1 and 'aşağıdaki maddeye'
or 'aşağıdaki maddelere')
.. ' bakınız.'
local table_content = format_table_content(matching_defs, frame)
local table_footer = '(Bu sözcük, ' .. ja(title) .. ', yukarıdaki '
.. (mode == 'kango' and 'Çin-Japon karakterli ' or '')
.. (#group(matching_defs, function(def) return def.title .. ',' .. def.kana_spellings end) == 1 and 'sözcüğün' or 'sözcüklerin')
.. (#filter(matching_defs, function(def) return contains(def.historical_kana_spellings, key) and not contains(def.kana_spellings, key) end) == 0
and ' farklı'
or ({ Hira = ' geleneksel hiragana]',
Kana = ' geleneksel katakana]',
= ' geleneksel karışık kana]' })
or ' geleneksel')
.. ' yazılışıdır.'
.. (m_ja.script(title) == 'Hira' and #filter(matching_defs, function(def) return match(def.title, '^$') end) > 0
and mw.title.new('Kategori:Japonca ' .. title .. ' okunuşlu kanjiler').exists
and ("<br><span style='font-size:85%;'>Sadece Japonca sözcüklerde kullanılanlar değil, " .. ja(title) .. ' okunuşlu tüm kanjilerin listesi için, bakınız '
.. '].)</span>')
or ')')
local result = '{| class="wikitable" style="min-width:70%"\n|-\n| <b>'
.. table_header
.. '</b>' .. (#matching_defs > 0 and ('\n|-\n| style="background-color: white" |\n'
.. table_content
.. '\n|-\n| ') or '<br>')
.. table_footer
.. '\n|}'
if mode ~= 'glyphvar' then
local created_entries = set(map(matching_defs, function(def) return def.title end))
local uncreated_entries = set(filter(lemmas, function(lemma) return not contains(created_entries, lemma) end))
if #uncreated_entries > 0 then
result = result .. '\n<small class="attentionseeking">(Şu madde' .. (#uncreated_entries == 1 and '' or 'ler')
.. ' henüz oluşturulmamış: ' .. table.concat(map(uncreated_entries, link), ", ") .. '.)</small>'
end
end
result = gsub(result, '%])', '[[Kategori:Japonca sözcükler%1')
return result
end
function export.show_kango(frame)
return export.show(frame, 'kango')
end
function export.show_gv(frame)
return export.show(frame, 'glyphvar')
end
return export