본문으로 이동

모듈:zh-han

위키낱말사전, 말과 글의 누리

이 모듈에 대한 설명문서는 모듈:zh-han/설명문서에서 만들 수 있습니다

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

local codepoint = m_str_utils.codepoint
local find = m_str_utils.find
local get_section = require("Module:pages").get_section
local gsub = m_str_utils.gsub
local sub = m_str_utils.sub

local m_links = require("Module:also/link")
local m_script_utils = require("Module:script utilities")

local export = {}

local PAGENAME = mw.loadData("Module:headword/data").pagename

local cangjie = {
	A = "日", B = "月", C = "金", D = "木", E = "水", F = "火", G = "土", H = "竹", I = "戈", J = "十", K = "大", L = "中", M = "一", N = "弓", O = "人", P = "心", Q = "手", R = "口", S = "尸", T = "廿", U = "山", V = "女", W = "田", X = "難", Y = "卜", Z = "重"
}

local radicals = {
	"一","丨","丶","丿","乙","亅",
	"二","亠","人","儿","入","八","冂","冖","冫","几","凵","刀","力","勹","匕","匚","匸","十","卜","卩","厂","厶","又",
	"口","囗","土","士","夂","夊","夕","大","女","子","宀","寸","小","尢","尸","屮","山","巛","工","己","巾","干","幺","广","廴","廾","弋","弓","彐","彡","彳",
	"心","戈","戶","手","支","攴","文","斗","斤","方","无","日","曰","月","木","欠","止","歹","殳","毋","比","毛","氏","气","水","火","爪","父","爻","爿","片","牙","牛","犬",
	"玄","玉","瓜","瓦","甘","生","用","田","疋","疒","癶","白","皮","皿","目","矛","矢","石","示","禸","禾","穴","立",
	"竹","米","糸","缶","网","羊","羽","老","而","耒","耳","聿","肉","臣","自","至","臼","舌","舛","舟","艮","色","艸","虍","虫","血","行","衣","襾",
	"見","角","言","谷","豆","豕","豸","貝","赤","走","足","身","車","辛","辰","辵","邑","酉","釆","里",
	"金","長","門","阜","隶","隹","雨","靑","非",
	"面","革","韋","韭","音","頁","風","飛","食","首","香",
	"馬","骨","高","髟","鬥","鬯","鬲","鬼",
	"魚","鳥","鹵","鹿","麥","麻",
	"黃","黍","黑","黹",
	"黽","鼎","鼓","鼠",
	"鼻","齊",
	"齒",
	"龍","龜",
	"龠"
}

local simplified_radical = {
	['讠']='言',['门']='門',['饣']='食',['飞']='飛',['马']='馬',['见']='見',['贝']='貝',['纟']='糸',['车']='車',['长']='長',['韦']='韋',['风']='風',['钅']='金',['鸟']='鳥',['竜']='龍',['龙']='龍',['页']='頁',['斉']='齊',['齐']='齊',['麦']='麥',['亀']='龜',['龟']='龜',['鱼']='魚',['黾']='黽',['鼡']='鼠',['歯']='齒',['齿']='齒',['卤']='鹵',['𬺞']='龜',['丬']='爿',['黒']='黑',['黄']='黃',['𱷥']='龍',['𲋄']='風',
}

local codes = {
	c = '중국어 간체', m = '중국 대륙',
	j = '일본어', k = '한국어'
}

-- "as" 또는 "sn" 매개변수 이름의 글자에 대한 기준
-- - 글자는 1개 또는 2개여야 합니다.
-- - 글자는 c, m, j, k 중 하나여야 합니다.
-- - 글자는 [cm]jk 순서여야 합니다.
local function validate_letters(letters)
	local letter_count = #letters
	return letter_count == 3 and (letters == 'mjk' or letters == 'cjk')
		or letter_count == 2 and (letters == 'jk' or letters == 'cj' or letters == 'mj')
		or letter_count == 1 and codes[letters]
end

local function mul_link(term)
	return m_links.full_link({lang = require('Module:languages').getByCode('zh'), term = term.."//", tr="-"})
end

-- 설명:
-- 이 상자는 위키미디어 공용의 214개 부수 분류로 연결됩니다.
--
-- 목적:
-- 공용에서 각 한자 부수 분류는 해당 글자가 잘 설명된 위키낱말사전 항목으로 직접 연결됩니다.
-- 위키낱말사전의 각 부수 항목에서 해당하는 공용 분류로 다시 연결하면 한자를 탐색하기가 더 쉬워집니다.
local function radical(name,number,variant)
	number = number or 1
	local padleft = ("%03d"):format(number)
	local text = '<div class="noprint standard-box nowrap" style="margin:0;font-size:90%;width:fit-content;text-align:left;float:right"><div style="float:left; margin-right:0.5em">[[Image:Commons-logo.svg|24px|none|link=Commons:Category:Radical ' .. padleft .. ']]</div>[[Commons:Category:Radical ' .. padleft .. "-0|관련 이미지: <br />'''부수 " .. number .. "번 <big>" .. ((name and name ~= '') and PAGENAME or '※') .. "</big>''']]</div>"
	if name == PAGENAME or (variant and variant ~= '') then
		text = text .. '[[분류:한자 부수| ]]'
	else
		text = text .. '[[분류:한자 기본형 부수| ]]'
	end
	return text
end

function export.simp(frame)
	local args = frame:getParent().args
	
	local trad = args[1] or ''
	if trad == '' then
		require('Module:debug').track("zh-han-simp-no-arg1")
		trad = mw.loadData("Module:zh/data/st")[PAGENAME] or PAGENAME
	end
	
	local nocap = args['nocap'] or ''
	local alt = args['a'] or ''
	local from = {args['f'] or '',args['f2'] or ''}
	local to = {args['t'] or '',args['t2'] or ''}
	if from[1] == '' and to[1] ~= '' then from[1] = trad end
	local text = {}
	local result = ''
	result = mul_link(trad) .. '의 간체자'
	if alt ~= '' then
		result = result .. ' 및 ' .. mul_link(alt)
	end
	for i=1,2 do
		if from[i] ~= '' then
			if to[i] == '' then
				table.insert(text,mul_link(from[i]) .. " → 독립적으로 표시할 수 없는 구성 요소")
			elseif to[i] == ' ' or to[i] == '&nbsp;' then
				table.insert(text,mul_link(from[i]) .. '의 생략')
			else
				table.insert(text,mul_link(from[i]) .. ' → ' .. mul_link(to[i]))
			end
		end
	end
	if #text > 0 then
		result = result .. ' (' .. table.concat(text,' 및 ') .. ')'
	end
	return result
end

function export.cp()
	return string.format('%.4X', codepoint(PAGENAME))
end

do
	local function check_translingual_only()
		for _, sec in pairs(mw.loadData("Module:headword/data").page.L2_sections) do
			if sec ~= "범언어" then
				return
			end
		end
		require('Module:debug').track('zh-han/translingual-only character')
	end
	
	function export.character(frame)
		local args = {}
		for arg, val in pairs(frame:getParent().args) do -- 빈 인수는 nil로 설정
			if val ~= '' then
				args[arg] = val
			end
		end
		if radicals[tonumber(args['rn'])] ~= (simplified_radical[args['rad']] or args['rad']) then
			error('부수 번호(rn)와 부수(rad)가 일치하지 않습니다.')
		end
		local text = { insert = table.insert }
		local categories = { insert = table.insert }
		local as = tostring(tonumber(args['as'] or '-1'))
		if as == '0' then
			text:insert(radical(args['rad'], args['rn'], (args['var'] or '')))
		end
		
		-- [[Module:headword]]로 표제어를 생성하여 페이지 제목이 Hani(일반 한자) 스크립트로 태그되도록 함.
		-- {{Han char}}는 범언어 문단에서만 사용된다고 가정.
		local mul = require("Module:languages").getByCode("mul")
		local Hani = require("Module:scripts").getByCode("Hani")
		local sort_key = args['rad'] .. args['as'] .. PAGENAME
		text:insert(
		    require("Module:headword").full_headword{
		        lang = mul,
		        sc = Hani,
		        -- heads 테이블에 HTML 스타일을 직접 추가합니다.
		        heads = { { term = '<span style="font-size: 120%;">' .. (args['head'] or PAGENAME) .. '</span>' } },
		        categories = {},
		        pos_category = "기호",
		        sort_key = sort_key,
		    }
		)
		text:insert(" ([[강희자전 부수]] " .. (args['rn'] or '') .. "번, [[부록:한자 부수/" .. (args['rad'] or '') .. '|' .. (args['rad'] or ' ') .. ']]+' .. as)
		if args['asj'] then
			text:insert("(중국어), " .. (args['rad'] or '') .. '+' .. tonumber(args['asj']) .. "(일본어)")
		end
		if args['asc'] then
			text:insert("(정체자), " .. (args['rad'] or '') .. '+' .. tonumber(args['asc']) .. "(간체자)")
		end
		if args['ask'] then
			text:insert("(중국어), " .. (args['rad'] or '') .. '+' .. tonumber(args['ask']) .. "(한국어)")
		end
		if args['asjk'] then
			text:insert("중국어), " .. (args['rad'] or '') .. '+' .. tonumber(args['asjk']) .. "(일본어 및 한국어)")
		end
		if args['asj+'] then
			text:insert("(중국어 및 한국어), " .. (args['rad'] or '') .. '+' .. tonumber(args['asj+']) .. "(일본어)")
		end
		if args['ask+'] then
			text:insert("(중국어 및 일본어), " .. (args['rad'] or '') .. '+' .. tonumber(args['ask+']) .. "(한국어)")
		end
		if args['asc+'] then
			text:insert("(정체자 및 일본어), " .. (args['rad'] or '') .. '+' .. tonumber(args['asc+']) .. "(간체자)")
		end
		if args['asc++'] then
			text:insert("(정체자, 일본어 및 한국어), " .. (args['rad'] or '') .. '+' .. tonumber(args['asc++']) .. "(간체자)")
		end
		if args['ascj'] then
			text:insert("(정체자), " .. (args['rad'] or '') .. '+' .. tonumber(args['ascj']) .. "(간체자 및 일본어)")
		end
		if args['ascj+'] then
			text:insert("(정체자 및 한국어), " .. (args['rad'] or '') .. '+' .. tonumber(args['ascj+']) .. "(간체자 및 일본어)")
		end
		if args['asm'] then
			text:insert("(정체자), " .. (args['rad'] or '') .. '+' .. tonumber(args['asm']) .. "(중국 대륙)")
		end
		if args['asmj'] then
			text:insert("(정체자), " .. (args['rad'] or '') .. '+' .. tonumber(args['asmj']) .. "(중국 대륙 및 일본어)")
		end
		if args['asmj+'] then
			text:insert("(정체자 및 한국어), " .. (args['rad'] or '') .. '+' .. tonumber(args['asmj+']) .. "(중국 대륙 및 일본어)")
		end
		if args['asm+'] then
			text:insert("(정체자 및 일본어), " .. (args['rad'] or '') .. '+' .. tonumber(args['asm+']) .. "(중국 대륙)")
		end
		if args['asm++'] then
			text:insert("(정체자, 일본어 및 한국어), " .. (args['rad'] or '') .. '+' .. tonumber(args['asm++']) .. "(중국 대륙)")
		end
		if args['ascjk'] then
			text:insert("(정체자), " .. (args['rad'] or '') .. '+' .. tonumber(args['ascjk']) .. "(간체자, 일본어 및 한국어)")
		end
		if args['asmjk'] then
			text:insert("(정체자), " .. (args['rad'] or '') .. '+' .. tonumber(args['asmjk']) .. "(중국 대륙, 일본어 및 한국어)")
		end
		if args['asmjk+'] then
			text:insert("(정체자(대만)), " .. (args['rad'] or '') .. '+' .. tonumber(args['asmjk+']) .. "(중국(대륙, 홍콩), 일본어 및 한국어)")
		end
		text:insert("획, " .. (args['sn'] or '') .. "획")

		if args['snj'] then
			text:insert("(중국어)")
		end
		if args['snc'] then
			text:insert("(정체자)")
		end
		if args['snk'] then
			text:insert("(중국어)")
		end
		if args['snjk'] then
			text:insert("(중국어)")
		end
		if args['snj+'] then
			text:insert("(중국어 및 한국어)")
		end
		if args['snk+'] then
			text:insert("(중국어 및 일본어)")
		end
		if args['snc+'] then
			text:insert("(정체자 및 일본어)")
		end
		if args['snc++'] then
			text:insert("(정체자, 일본어 및 한국어)")
		end
		if args['sncj'] then
			text:insert("(정체자)")
		end
		if args['sncj+'] then
			text:insert("(정체자 및 한국어)")
		end
		if args['snm'] then
			text:insert("(정체자)")
		end
		if args['snmj'] then
			text:insert("(정체자)")
		end
		if args['snmj+'] then
			text:insert("(정체자 및 한국어)")
		end
		if args['snm+'] then
			text:insert("(정체자 및 일본어)")
		end
		if args['snm++'] then
			text:insert("(정체자, 일본어 및 한국어)")
		end
		if args['sncjk'] then
			text:insert("(정체자)")
		end
		if args['snmjk'] then
			text:insert("(정체자)")
		end
		if args['snmjk+'] then
			text:insert("(정체자(대만))")
		end
		
		-- Find parameters specifying additional stroke numbers and add notes for
		-- them.
		for param_name, value in pairs(args) do
			if type(param_name) == "string" then
				local letters = param_name:match("^sn(%l+)%+*$")
				if letters then
					if validate_letters(letters) then
						if value and value ~= '' then
							local label = {}
							for letter in letters:gmatch(".") do
								table.insert(label, codes[letter])
							end
							label = table.concat(label, " 및 ")
							
							text:insert(", " .. value .. "획")
							text:insert("(" .. label .. ")")
						end
					else
						require("Module:debug").track('zh-han/incorrect stroke number parameter')
						-- return error("알 수 없는 획수 매개변수 이름 " .. param_name .. "입니다.")
					end
				end
			end
		end
		
		if args['canj'] then
			local canj = args['canj']
			local canj_split = mw.text.split(canj,',')
			for i = 1, #canj_split do
				if canj_split[i]:match('^%u+$') then
					canj_split[i] = canj_split[i]:gsub('[%(%)]','')
					canj_split[i] = m_script_utils.tag_text(canj_split[i]:gsub('%u',cangjie), mul, Hani) .. ' ([[부록:창힐수입법/' .. canj_split[i]:sub(1,1):lower() .. '|' .. canj_split[i] .. ']])'
				else
					return error('"canj" 매개변수 값이 유효하지 않습니다.')
				end
			end
			text:insert(", [[부록:창힐수입법|창힐 입력]] " .. table.concat(canj_split,' 또는 '))
			if #canj_split > 1 then
				categories:insert("[[분류:창힐 코드가 여러 개인 한자]]")
			end
		end
		if args['four'] then
			local four = args['four']
			local four_split = mw.text.split(four,',')
			for i=1,#four_split do
				if not four_split[i]:match('[<>]') then
					four_split[i] = four_split[i]:gsub('(%d)(%d%d%d)%.?(%d?)','[[부록:사각호마/%1|%1%2<sub>%3</sub>]]')
				else
					return error('"four" 매개변수 값이 유효하지 않습니다.')
				end
			end
			text:insert(", [[부록:사각호마|사각호마]] " .. table.concat(four_split,' or '))
			if #four_split > 1 then
				categories:insert("[[분류:사각호마 코드가 여러 개인 한자]]")
			end
		end
		if args['ids'] then
			local ids = args['ids']
			local ids_split = mw.text.split(ids,',')
			for i=1, #ids_split do
				if not ids_split[i]:match('[%[%]]') then
					if find(ids_split[i], '^[⿲⿳](.)%1%1$') then
						categories:insert('[[분류:같은 글자를 세 개 합친 한자]]')
					end
					if find(ids_split[i], '^[⿰⿱](.)%1$') then
						categories:insert('[[분류:같은 글자를 두 개 합친 한자]]')
					end
					local before = {}
					ids_split[i] = gsub(ids_split[i], "([⺀-⻳ -〿アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヰヱヲン㇀-㇣〇一-鿿㐀-䶿﨎﨏﨑﨓﨔﨟﨡﨣﨤﨧-﨩𠀀-𪛟𪜀-𮯠𰀀-𲎯])",
						function (character)
							if not before[character] then
								before[character] = true
								return "[[" .. character .. "]]"
							else
								return character
							end
						end)
					ids_split[i] = ids_split[i]:gsub("^(.-)%f[%(%z](.*)",
						function(m1, m2)
							local m1 = m_links.embedded_language_links{term = m1, lang = mul, sc = Hani}
							m1 = m_script_utils.tag_text(m1, mul, Hani)
							local letters = {
								G = '<span class="explain" title="중국 대륙">G</span>',
								H = '<span class="explain" title="홍콩">H</span>',
								T = '<span class="explain" title="대만">T</span>',
								J = '<span class="explain" title="일본">J</span>',
								K = '<span class="explain" title="한국">K</span>',
								V = '<span class="explain" title="베트남">V</span>'
							}
							return m1 .. m2:gsub(".", letters)
						end)
				end
			end
			text:insert(", [[w:en:Chinese character description languages#Ideographic Description Sequences|자형 구조]] " .. table.concat(ids_split,' 또는 '))
			if #ids_split > 1 then
				categories:insert("[[분류:자형 구조가 여러 개인 한자]]")
			end
		end
		text:insert(')')
		if args['rad'] then
			if mw.title.getCurrentTitle().nsText == '' then
				categories:insert("[[분류:한자 글자|" .. sort_key .. "]]")
			end
		else
			if mw.title.getCurrentTitle().nsText == '' then
				categories:insert("[[분류:부수 정보가 없는 한자]]")
			end
		end
		local params_to_check = { "as", "rn", "sn", "ids", "four", "canj" }
		local sortkey = args['rad'] and "|" .. args['rad'] or ""
		for _, param in pairs(params_to_check) do
			if not args[param] or args[param] == '' then
				categories:insert("[[분류:한자 정보(" .. param .. ") 없음" .. sortkey .. "]]")
			end
		end
		
		if type(args['sn']) == "string" and sub(args['sn'],1,1) == '0' then
			return error('"sn" 매개변수에서 맨 앞의 0을 제거해주세요.')
		end
		
		check_translingual_only()
		
		if (get_section(mw.title.getCurrentTitle():getContent(), "범언어", 2) or ""):match("%f[^%z\n\r]#[ \t]*%S") then
			categories:insert("[[분류:범언어 문단에 뜻풀이가 있는 한자" .. sortkey .. "]]")
		end
		
		return table.concat(text) .. table.concat(categories)
	end
end

return export