Module:ko-pron
Jump to navigation
Jump to search
- The followingdocumentationis located atModule:ko-pron/documentation.[edit]Categories were auto-generated byModule:module categorization.[edit]
- Useful links:subpage list•links•transclusions•testcases•sandbox
Korean pronunciation and romanisation module. Generates Revised Romanisation (RR
), phonetic hangul (ph
), Yale romanisation (yr
), McCune-Reischauer (mr
), WT-revised Revised Romanisation (rrr
) and IPA (ipa
) for now.
Data is stored atModule:ko-pron/data.
See{{ko-IPA}}
for more examples.
localexport={}
localm_data=mw.loadData("Module:ko-pron/data")
localm_ko_utilities=require("Module:ko")
localm_str_utils=require("Module:string utilities")
localcodepoint=m_str_utils.codepoint
localconcat=table.concat
localfloor=math.floor
localgmatch=m_str_utils.gmatch
localgsub=m_str_utils.gsub
localinsert=table.insert
locallen=m_str_utils.len
localmatch=m_str_utils.match
localpattern_escape=m_str_utils.pattern_escape
localsub=m_str_utils.sub
localtoNFC=mw.ustring.toNFC
localu=m_str_utils.char
localupper=m_str_utils.upper
localPAGENAME=mw.loadData("Module:headword/data").pagename
localPAGENAME2=gsub(PAGENAME,"-","")
localsystem_lookup={
["ph"]=1,["rr"]=2,["rrr"]=3,
["mr"]=4,["yr"]=5,["ipa"]=6,
}
localquestion_mark="<sup><small>[[Wiktionary:About Korean/Romanization|?]]</small></sup>"
localsystem_list={
{
abbreviation="ph",
display="Phonetic hangul:",
separator="/",
},
{
abbreviation="rr",
display="Revised Romanization"..question_mark,
separator="/",
},
{
abbreviation="rrr",
display="Revised Romanization (translit.)"..question_mark,
separator="/"
},
{
abbreviation="mc",
display="McCune–Reischauer"..question_mark,
separator="/"
},
{
abbreviation="yr",
display="Yale Romanization"..question_mark,
separator="/"
},
{
abbreviation="ipa",
display="(<i>[[w:South Korean standard language|SK Standard]]/[[w:Seoul dialect|Seoul]]</i>) [[Wiktionary:International Phonetic Alphabet|IPA]]<sup>([[Appendix:Korean pronunciation|key]])</sup>:",
separator="~"
}
}
--[[
vowel_variation:
rules for vowel transformation.
key:
the number of a syllable's vowel (vowel_id):
floor(((codepoint('가') - 0xAC00) % 588) / 28) = 0
floor(((codepoint('개') - 0xAC00) % 588) / 28) = 1
value:
an integer that is added to the decimal codepoint of the syllable
u(codepoint('개') + 112) = '게'
allowed_vowel_scheme:
a list of which systems vowel transformation is reflected in.
key:
vowel_id.. "-".. system_index
system_index: see system_list above. IPA is #6
value:
1, representing true
]]
localfinal_syllable_conversion={[""]="Ø",["X"]=""}
localcom_mc={["g"]="k",["d"]="t",["b"]="p",["j"]="ch",["sy"]="s",["s"]="ss"}
localcom_ph={["ᄀ"]="ᄁ",["ᄃ"]="ᄄ",["ᄇ"]="ᄈ",["ᄉ"]="ᄊ",["ᄌ"]="ᄍ"}
localvowel_variation={
[1]=112,-- 개→게
[3]=112,-- 걔→계
[10]=140,-- 괘→궤
[7]=-56,-- 계→게
[11]=112,-- 괴→궤
[16]=0,-- 귀→귀
}
localallowed_vowel_scheme={
["1-1"]=1,
["1-6"]=1,
["3-1"]=1,
["3-6"]=1,
["10-1"]=1,
["10-6"]=1,
["7-1"]=1,
["7-6"]=1,
["11-1"]=1,
["11-6"]=1,
["16-6"]=1,
}
localambiguous_intersyllabic_rr={["oe"]=1,["eo"]=1,["eu"]=1,["ae"]=1,["ui"]=1}
localambiguous_intersyllabic_mr={["oe"]=1,["ae"]=1}
localambiguous_intersyllabic_yr={["ay"]=1,["ey"]=1,["oy"]=1,["uy"]=1,["̄y"]=1,["ya"]=1,["ye"]=1,["yo"]=1,["yu"]=1}
localfunctiondecompose_syllable(word)
localdecomposed_syllables={}
forsyllableinmw.text.gsplit(word,"")do
insert(decomposed_syllables,m_ko_utilities.decompose_jamo(syllable))
end
returndecomposed_syllables
end
localfunctiontidy_phonetic(original,romanised)
localj,k,w=1,1,{}
fori=1,len(romanised)do
localromanised_syllable=sub(romanised,k,k)
localoriginal_syllable=sub(original,j,j)
ifromanised_syllable~=original_syllablethen
insert(w,'<b>'..romanised_syllable..'</b>')
localoriginal_advance=match(original_syllable,"[^ː ]")
localromanised_advance=match(romanised_syllable,"[^ː ]")
iforiginal_advanceornotromanised_advancethen
k=k+1
end
ifromanised_advanceornotoriginal_advancethen
j=j+1
end
else
insert(w,'<span>'..romanised_syllable..'</span>')
j,k=j+1,k+1
end
end
returnconcat(w)
end
localfunctiontidy_ipa(ipa)
ipa=gsub(ipa,"ʌ̹%(ː%)","ɘ(ː)")-- TODO: [[멀다]] really should be [ˈmʌ̹ɭda̠] ~ [ˈmɘːɭda̠] instead of [ˈmɘ(ː)ɭda̠]
ipa=gsub(ipa,"ɭɭi","ʎʎi")
ipa=gsub(ipa,"ɭɭj","ʎʎ")
ipa=gsub(ipa,"s([ʰ͈])ɥi","ʃ%1ɥi")
ipa=gsub(ipa,"ss͈([ji])","ɕɕ͈%1")
ipa=gsub(ipa,"s([ʰ͈])([ji])","ɕ%1%2")
ipa=gsub(ipa,"nj","ɲ")
ipa=gsub(ipa,"([ʑɕ])([ʰ͈]?)j","%1%2")
ipa=gsub(ipa,"kʰ[ijɯ]",{
["kʰi"]="cçi",
["kʰj"]="cç",
["kʰɯ"]="kxɯ"}
)
ipa=gsub(ipa,"[hɦ][ijɯouw]",{
["hi"]="çi",
["hj"]="ç",
["hɯ"]="xɯ",
["ho"]="ɸʷo",
["hu"]="ɸʷu",
["hw"]="ɸw",
["ɦi"]="ʝi",
["ɦj"]="ʝ",
["ɦɯ"]="ɣɯ",
["ɦo"]="βo",
["ɦu"]="βu",
["ɦw"]="βw"}
)
ifmatch(ipa,"ɥi")then
localmidpoint=floor(len(ipa)/2)
ipa=sub(ipa,1,midpoint)..gsub(sub(ipa,midpoint+1,-1),"ɥi","y")
end
returnipa
end
functionexport.romanise(text_param,system_index,args)
iftype(text_param)=="table"then
args=text_param:getParent().args
system_index=args[2]or2
text_param=args[1]
end
localp,optional_params={},{"nn","l","com","cap","ni"}
for_,pminipairs(optional_params)do
p[pm]={}
ifargs[pm]then
forppinmw.text.gsplit(args[pm],",")dop[pm][tonumber(pp)orpp]=1end
end
end
localcategories={}
localvowel_ui_i,vowel_ui_e,no_batchim,batchim_reduce,s_variation,iotation=
args.ui,args.uie,args.nobc,args.bcred,args.svar,args.iot
system_index=system_lookup[system_index]orsystem_index
text_param=gsub(text_param,'[ "](.)',"%1")
forprimitive_wordingmatch(text_param,"[%-ᄀ-ᄒ".."ᅡ-ᅵ".."ᆨ-ᇂ".."ㄱ-ㅣ가-힣' -]+")do
localthe_original=primitive_word
primitive_word=gsub(primitive_word,"'''","ß")
localformatting_position,formatting_count={},0
primitive_word=gsub(primitive_word,"()([ß-])",function(m1,m2)
formatting_position[m1+formatting_count]=m2=="ß"and"'''"orm2
return""
end)
localhas_vowel={}
forchingmatch(primitive_word,".")do
localjungseong=floor(((codepoint(ch)-0xAC00)%588)/28)
ifnotmatch(ch,"[예옛옘례롄]")andmatch(ch,"[가-힣]")thenhas_vowel[jungseong]=trueend
end
localword_set={primitive_word}
localfunctionadd_respelling(variable,modification,modification2)
modification2=modification2orfunction(x)returnxend
ifvariableandmatch(system_index,"[16]")then
variable=tonumber(variable)
localpre_length=#word_set
fori=1,pre_lengthdo
localitem=mw.text.split(word_set[i],"")
item[variable]=modification(item[variable])
item[variable+1]=modification2(item[variable+1])
word_set[pre_length+i]=concat(item)
end
end
end
add_respelling(vowel_ui_i,function(x)return"이"end)
add_respelling(vowel_ui_e,function(x)return"에"end)
add_respelling(no_batchim,
function(x)returnu(codepoint(x)-(codepoint(x)-0xAC00)%28)end,
function(y)returnu(codepoint(y)+588)end)
add_respelling(s_variation,function(x)returnu(codepoint(x)-12)end)
add_respelling(iotation,function(x)returnu(codepoint(x)+56)end)
forvowel_id,vowel_variation_incrementinpairs(vowel_variation)do
ifhas_vowel[vowel_id]andallowed_vowel_scheme[vowel_id.."-"..system_index]then
localpre_length=#word_set
fori=1,pre_lengthdo
localitem=mw.text.split(word_set[i],"")
fornum,itinipairs(item)do
iffloor(((codepoint(it)-0xAC00)%588)/28)==vowel_idthen
item[num]=u(codepoint(it)+vowel_variation_increment)
end
end
ifvowel_id==11then
insert(word_set,i,concat(item))
else
insert(word_set,concat(item))
end
end
end
end
localword_set_romanisations={}
for_,respellinginipairs(word_set)do
localdecomposed_syllables=decompose_syllable(respelling)
localromanisation={}
localformatting_insert_count=0
forindex=0,#decomposed_syllables,1do
localthis_syllable_text=index~=0andsub(respelling,index,index)or""
ifthis_syllable_text=="-"then
-- skip it, it will be handled below
else
localsyllable=decomposed_syllables[index]or{initial="Ø",vowel="Ø",final="X"}
localnext_index=index
localnext_syllable_text
localsaw_hyphen_after=false
whiletruedo
next_index=next_index+1
next_syllable_text=next_index>#decomposed_syllablesand""orsub(respelling,next_index,next_index)
ifnext_syllable_text~="-"then
break
end
saw_hyphen_after=true
end
localnext_syllable=decomposed_syllables[next_index]or{initial="Ø",vowel="Ø",final="Ø"}
syllable.final=final_syllable_conversion[syllable.final]orsyllable.final
ifsystem_index==5andsyllable.vowel=="ᅮ"andmatch(syllable.initial,"[ᄆᄇᄈᄑ]")then
syllable.vowel="ᅳ"
end
ifmatch(system_index,"[1246]")then
ifmatch(syllable.initial,"[ᄌᄍᄎ]")then
ifsyllable.vowel=="ᅣ"then
syllable.vowel="ᅡ"
elseifsyllable.vowel=="ᅤ"then
syllable.vowel="ᅢ"
elseifsyllable.vowel=="ᅧ"then
syllable.vowel="ᅥ"
elseifsyllable.vowel=="ᅨ"then
syllable.vowel="ᅦ"
elseifsyllable.vowel=="ᅭ"then
syllable.vowel="ᅩ"
elseifsyllable.vowel=="ᅲ"then
syllable.vowel="ᅮ"
end
end
end
ifmatch(system_index,"[16]")then
ifsyllable.vowel=="ᅴ"andthis_syllable_text~="의"then
syllable.vowel="ᅵ"
end
end
ifmatch(system_index,"[1246]")then
ifthis_syllable_text=="넓"then
ifmatch(next_syllable.initial,"[ᄌᄉ]")then
syllable.final="ᆸ"
elseifnext_syllable.initial=="ᄃ"then
ifmatch(next_syllable.vowel,"[^ᅡᅵ]")then
syllable.final="ᆸ"
end
end
end
end
localvowel=m_data.vowels[syllable.vowel][system_index]
ifp.nn[next_index]andmatch(system_index,"[1246]")then
next_syllable.initial="ᄂ"
end
ifp.com[index]andmatch(system_index,"[16]")then
next_syllable.initial=com_ph[next_syllable.initial]ornext_syllable.initial
end
ifp.ni[next_index]andsystem_index~=3then
next_syllable.initial=(system_index==5andsyllable.final=="ᆯ")and"ᄅ"or"ᄂ"
end
ifmatch(system_index,"[1246]")then
iftonumber(batchim_reduceor-1)==indexthen
syllable.final=m_data.boundary[syllable.final.."-Ø"][1]
end
ifindex~=0andthis_syllable_text=="밟"andnot
match(next_syllable.initial,"[ᄋᄒ]")then
syllable.final="ᆸ"
end
ifnext_syllable_text=="없"then
ifmatch(syllable.final,"[ᆩᆪᆰᆿ]")then
syllable.final="ᆨ"
elseifmatch(syllable.final,"[ᆬᆭ]")then
syllable.final="ᆫ"
elseifmatch(syllable.final,"[ᆺᆻᆽᆾᇀ]")then
syllable.final="ᆮ"
elseifmatch(syllable.final,"[ᆲᆳᆴᆶ]")then
syllable.final="ᆯ"
elseifsyllable.final=="ᆱ"then
syllable.final="ᆷ"
elseifmatch(syllable.final,"[ᆵᆹᇁ]")then
syllable.final="ᆸ"
end
end
iftonumber(batchim_reduceor-1)~=indexthen
ifmatch(syllable.final..next_syllable.initial,"ᇀᄋ")then
ifnext_syllable.vowel=="ᅵ"then
syllable.final="ᆾ"
elseifnext_syllable.vowel=="ᅧ"then
syllable.final="ᆾ"
next_syllable.vowel="ᅥ"
end
elseifmatch(syllable.final..next_syllable.initial,"ᆴᄋ")then
ifnext_syllable.vowel=="ᅵ"then
syllable.final="ᆯ"
next_syllable.initial="ᄎ"
elseifnext_syllable.vowel=="ᅧ"then
syllable.final="ᆯ"
next_syllable.initial="ᄎ"
next_syllable.vowel="ᅥ"
end
elseifmatch(syllable.final..next_syllable.initial,"ᆮᄋ")andtonumber(s_variationor-1)~=indexthen
ifnext_syllable.vowel=="ᅵ"then
syllable.final="ᆽ"
elseifnext_syllable.vowel=="ᅧ"then
syllable.final="ᆽ"
next_syllable.vowel="ᅥ"
end
elseifmatch(syllable.final..next_syllable.initial,"ᆮᄒ")then
ifnext_syllable.vowel=="ᅵ"then
syllable.final="ᆾ"
next_syllable.initial="ᄋ"
elseifnext_syllable.vowel=="ᅧ"then
syllable.final="ᆾ"
next_syllable.initial="ᄋ"
next_syllable.vowel="ᅥ"
end
elseifmatch(syllable.final..next_syllable.initial..next_syllable.vowel,"[ᆬᆽᆾ][ᄋᄒ]ᅧ")then
next_syllable.vowel="ᅥ"
end
end
ifsyllable.final..next_syllable.initial=="ᆺᄋ"andnot
match(next_syllable_text,"[아았어었에으은을음읍의이인일임입있]")then
syllable.final="ᆮ"
end
end
localbound=syllable.final.."-"..next_syllable.initial
ifnotm_data.boundary[bound]then
require("Module:debug").track("ko-pron/no boundary data")
mw.log("No boundary data for"..bound..".")
returnnil
end
localjunction=m_data.boundary[bound][system_index]
ifsystem_index==2then
localpos_format_start=index+formatting_insert_count+1
localpos_format_end=pos_format_start
whileformatting_position[pos_format_end]do
pos_format_end=pos_format_end+1
formatting_insert_count=formatting_insert_count+1
end
ifpos_format_end>pos_format_startthen
locala,b=match(junction,"^(ng%-?)(.?)$")
ifnotaornotbthena,b=match(junction,"^(.?%-?)(.*)$")end
junction=match(syllable.final..next_syllable.initial,"^Ø?[ᄀ-ᄒ]$")
andconcat(formatting_position,"",pos_format_start,pos_format_end-1)..(aor"")..(bor"")
or(aor"")..concat(formatting_position,"",pos_format_start,pos_format_end-1)..(bor"")
end
end
ifp.l[index]or(p.l["y"]andindex==1)then
-- FIXME, verify this code still works with final/initial cons changes
ifsystem_index==1then
if#junction==0then
junction=junction.."ː"
else
junction=gsub(junction,"^(.)(.?)$",function(a,b)
returnmatch(a,"[ᆨ-ᇂ]")anda.."ː"..bor"ː"..a..bend)
end
elseifsystem_index==5then
vowel=gsub(vowel,"([aeiou])","%1̄")
elseifsystem_index==6then
vowel=vowel.."ː"
ifindex==1then
insert(categories,"Korean terms with long vowels in the first syllable")
end
end
end
if(p.l["y"]orp.l[1])andindex==0andsystem_index==6and#decomposed_syllables>1then
vowel=vowel.."ˈ"
end
ifp.com[index]then
-- FIXME, verify this code still works with final/initial cons changes
junction=gsub(junction,"(.)$",function(next_letter)
return
(system_index==5and"q"or"")..
(system_index==4
and(com_mc[next_letter..(p.cap["y"]or"")]orcom_mc[next_letter]ornext_letter)
ornext_letter)end)
end
ifp.ni[next_index]andsystem_index==5then
-- FIXME, verify this code still works with final/initial cons changes
junction=gsub(junction,"([nl])$","<sup>%1</sup>")
end
localfinal_cons,initial_cons=match(junction,"^(.*);(.*)$")
ifnotfinal_consthen
ifsystem_index==2then
error("Need a semicolon in the boundary value for"..bound)
end
-- FIXME, throw an error for all systems once we've added semicolons everywhere
final_cons=junction
initial_cons=""
end
ifsystem_index==2then
insert(romanisation,vowel..final_cons..(saw_hyphen_afterand"-"or"")..initial_cons)
else
insert(romanisation,vowel..junction)
end
end
end
localtemp_romanisation=concat(romanisation)
ifsystem_index==1then
temp_romanisation=tidy_phonetic(primitive_word,toNFC(temp_romanisation))
elseifmatch(system_index,"[23]")then
fori=1,2do
temp_romanisation=gsub(temp_romanisation,"(.)…(.)",function(a,b)
returna..(ambiguous_intersyllabic_rr[a..b]and"'"or"")..bend)
temp_romanisation=gsub(temp_romanisation,"wo'e","woe")
temp_romanisation=gsub(temp_romanisation,"yo'e","yoe")
temp_romanisation=gsub(temp_romanisation,"we'o","weo")
temp_romanisation=gsub(temp_romanisation,"we'u","weu")
temp_romanisation=gsub(temp_romanisation,"ye'u","yeu")
temp_romanisation=gsub(temp_romanisation,"yu'i","yui")
end
elseifsystem_index==4then
fori=1,2do
temp_romanisation=gsub(temp_romanisation,"(.)…(.)",function(a,b)
returna..(ambiguous_intersyllabic_mr[a..b]and"'"or"")..bend)
temp_romanisation=gsub(temp_romanisation,"yo'e","yoe")
temp_romanisation=gsub(temp_romanisation,"a'e","aë")
temp_romanisation=gsub(temp_romanisation,"o'e","oë")
temp_romanisation=gsub(temp_romanisation,"n'k","nk")
temp_romanisation=gsub(temp_romanisation,"swi","shwi")
end
elseifsystem_index==5then
fori=1,2do
temp_romanisation=gsub(temp_romanisation,"(.)…(.)",function(a,b)
returna..(ambiguous_intersyllabic_yr[a..b]and"."or"")..bend)
temp_romanisation=gsub(temp_romanisation,"[.]q","q")
end
elseifsystem_index==6then
temp_romanisation="["..temp_romanisation.."]"
end
ifmatch(system_index,"[16]")then
temp_romanisation=gsub(temp_romanisation,"ː","(ː)")
end
ifp.cap["y"]andmatch(system_index,"[234]")then
temp_romanisation=upper(sub(temp_romanisation,1,1))..sub(temp_romanisation,2,-1)
end
insert(word_set_romanisations,temp_romanisation)
end
text_param=gsub(
text_param,
pattern_escape(the_original),
concat(word_set_romanisations,system_list[system_index].separator),
1
)
end
ifsystem_index==6then
text_param=tidy_ipa(text_param)
end
if#categories>0then
text_param=text_param..require("Module:utilities").format_categories(categories,m_ko_utilities.lang)
end
returntext_param
end
functionexport.make(frame,scheme)
localparams={
[1]={default=PAGENAME2,list=true},
["a"]={},
["audio"]={alias_of="a"},
["nn"]={},
["l"]={},
["com"]={},
["cap"]={},
["ui"]={},
["uie"]={},
["nobc"]={},
["ni"]={},
["bcred"]={},
["svar"]={},
["iot"]={},
}
localargs=require("Module:parameters").process(frame:getParent().args,params)
localresults={}
for_,text_paraminipairs(args[1])do
localcurrent_word_dataset={}
forsystem_index,systeminpairs(system_list)do
localromanised=export.romanise(text_param,system_index,args)
insert(current_word_dataset,romanised)
end
insert(results,current_word_dataset)
end
localoutput_result={[1]={},[2]={},[3]={},[4]={},[5]={},[6]={}}
for_,resultinipairs(results)do
forresult_index,valueinipairs(result)do
insert(output_result[result_index],value)
end
end
localhtml_ul=mw.html.create("ul")
:done()
localhtml_li_ipa=mw.html.create("li")
:wikitext(system_list[6].display)
:tag("span")
:addClass("IPA")
:wikitext(concat(output_result[6],system_list[6].separator))
:done()
:done()
localhtml_li_ph=mw.html.create("li")
:addClass("ko-pron__ph")
:wikitext(system_list[1].display)
:tag("span")
:addClass("Kore")
:attr("lang","ko")
:wikitext("["..concat(output_result[1],system_list[1].separator).."]")
:done()
:done()
ifargs.athen
html_li_ipa
:tag("ul")
:tag("li")
:wikitext(require("Module:audio").format_audio{
lang=m_ko_utilities.lang,
file=args.a=="y"and"Ko-"..PAGENAME..".ogg"orargs.a,
})
:done()
:done()
:done()
end
ifargs.lthen
html_li_ph
:tag("ul")
:tag("li")
:addClass("ko-pron__note-vowel-length")
:wikitext('Though still prescribed in Standard Korean, most speakers in both Koreas no longer distinguish vowel length.')
:done()
:done()
:done()
end
html_ul
:node(html_li_ipa)
:node(html_li_ph)
:done()
localhtml_table=mw.html.create("table")
:addClass("ko-pron")
:addClass("mw-collapsible")
:addClass("mw-collapsed")
:tag("tr")
:tag("th")
:attr("colspan",2)
:wikitext("Romanizations")
:done()
:done()
:done()
forroman_index=2,5do
html_table
:tag("tr")
:tag("th")
:wikitext(system_list[roman_index].display)
:done()
:tag("td")
:addClass("IPA")
:wikitext(concat(output_result[roman_index],system_list[roman_index].separator))
:done()
:done()
:done()
end
returntostring(html_ul)..tostring(html_table)..require("Module:TemplateStyles")("Template:ko-IPA/style.css")
end
functionexport.make_hanja(frame,scheme)
localparams={
[1]={list=true},
["l"]={},
}
localargs=require("Module:parameters").process(frame:getParent().args,params)
localresults={
[1]={},
[6]={},
}
for_,text_paraminipairs(args[1])do
for_,system_indexinpairs({1,6})do
localromanised=export.romanise(text_param,system_index,args)
insert(results[system_index],romanised)
end
end
localhtml_ul=mw.html.create("ul")
:done()
localhtml_li_ipa=mw.html.create("li")
:wikitext(system_list[6].display)
:tag("span")
:addClass("IPA")
:wikitext(concat(results[6],system_list[6].separator))
:done()
:done()
localhtml_li_ph=mw.html.create("li")
:addClass("ko-pron__ph")
:wikitext(system_list[1].display)
:tag("span")
:addClass("Kore")
:attr("lang","ko")
:wikitext("["..concat(results[1],system_list[1].separator).."]")
:done()
:done()
ifargs.lthen
html_li_ph
:tag("ul")
:tag("li")
:addClass("ko-pron__note-vowel-length")
:wikitext('Though still prescribed in Standard Korean, most speakers in both Koreas no longer distinguish vowel length.')
:done()
:done()
:done()
end
html_ul
:node(html_li_ipa)
:node(html_li_ph)
:done()
returntostring(html_ul)..require("Module:TemplateStyles")("Template:ko-IPA/style.css")
end
returnexport