Wiktionary
viwiktionary
https://vi.wiktionary.org/wiki/Wiktionary:Trang_Ch%C3%ADnh
MediaWiki 1.46.0-wmf.23
case-sensitive
Phương tiện
Đặc biệt
Thảo luận
Thành viên
Thảo luận Thành viên
Wiktionary
Thảo luận Wiktionary
Tập tin
Thảo luận Tập tin
MediaWiki
Thảo luận MediaWiki
Bản mẫu
Thảo luận Bản mẫu
Trợ giúp
Thảo luận Trợ giúp
Thể loại
Thảo luận Thể loại
Phụ lục
Thảo luận Phụ lục
TimedText
TimedText talk
Mô đun
Thảo luận Mô đun
Event
Event talk
bệ rạc
0
27341
2344289
2223117
2026-04-11T14:13:21Z
Hiyuune
50834
2344289
wikitext
text/x-wiki
=={{langname|vi}}==
==={{section|pron}}===
{{vi-pron}}
==={{section|adj}}===
{{vie-adj}}
# [[lôi thôi|Lôi thôi]], thiếu [[quy củ]], [[nền nếp]], [[lộ]] [[rõ]] sự thiếu [[nhân cách]] trong [[lối sống]].
#: {{ux|vi|Sống '''bệ rạc'''.}}
#: {{ux|vi|Nhà cửa quá '''bệ rạc'''.}}
==={{section|ref}}===
* {{R:FVDP}}
8l47m1pxbwziny2np40l2ycgwp1zix9
kvikksølv
0
189368
2344419
1865619
2026-04-12T05:07:01Z
Kelly zhrm
58416
2344419
wikitext
text/x-wiki
=={{langname|nb}}==
{{wp|no:}}
==={{ĐM|etym}}===
Từ {{der|nb|non|kviksilfr}}.
==={{ĐM|pron}}===
* {{IPA4|nb|/kʋɪksœl/}}
* {{rhymes|nb|œl}}
==={{ĐM|n}}===
{{nb-noun-nu}}
# [[thủy ngân|Thủy ngân]] (''nguyên tố hóa học, ký hiệu'' '''[[Hg]]''')
==={{ĐM|ref}}===
* {{R:nb:OB}}
{{C|nb|Nguyên tố hóa học}}
=={{langname|nn}}==
{{wp|nn:}}
==={{ĐM|alt}}===
* {{alt|nn|kvikksylv}}
==={{ĐM|etym}}===
Từ {{der|nn|non|kviksilfr}}.
==={{ĐM|n}}===
{{nn-noun-nu}}
# [[thủy ngân|Thủy ngân]].
==={{ĐM|ref}}===
* {{R:nn:OB}}
{{C|nn|Nguyên tố hóa học}}
aya80o5xhrx9yl2w4dvnbpbf0f10rd3
từ chương
0
192509
2344404
1937144
2026-04-12T04:56:10Z
Hiyuune
50834
2344404
wikitext
text/x-wiki
{{also|từ-chương}}
=={{langname|==
==={{section|alt}}===
* {{alter|vi|từ-chương}}
==={{section|etym}}===
{{vi-etym-sino|辭章}}.
==={{section|pron}}===
{{vi-pron}}
==={{section|n}}===
{{vi-noun}}
# {{lb|vi|obsolete}} [[văn chương|Văn chương]] đẹp như [[thơ]], [[phú]] nhưng [[vô ích]] cho [[đời sống]].
#: {{ux|vi|Nạn '''từ chương''' trong nền học cũ.}}
#* {{RQ:Tran Trong Kim Nho giao|page=14|volume=I|chapter=Lời phát đoan|url=https://vi.wikisource.org/wiki/Nho_gi%C3%A1o/Quy%E1%BB%83n_I/L%E1%BB%9Di_ph%C3%A1t_%C4%91oan|passage=Cách học tập của người mình lại chỉ vụ lấy '''từ-chương''', chuyên về khoa-cử để làm cái thang lợi danh.}}
==={{section|ref}}===
* {{R:FVDP}}
isso2cdkthhv2132y4l7f253mcfllk5
2344405
2344404
2026-04-12T04:56:19Z
Hiyuune
50834
2344405
wikitext
text/x-wiki
{{also|từ-chương}}
=={{langname|vi}}==
==={{section|alt}}===
* {{alter|vi|từ-chương}}
==={{section|etym}}===
{{vi-etym-sino|辭章}}.
==={{section|pron}}===
{{vi-pron}}
==={{section|n}}===
{{vi-noun}}
# {{lb|vi|obsolete}} [[văn chương|Văn chương]] đẹp như [[thơ]], [[phú]] nhưng [[vô ích]] cho [[đời sống]].
#: {{ux|vi|Nạn '''từ chương''' trong nền học cũ.}}
#* {{RQ:Tran Trong Kim Nho giao|page=14|volume=I|chapter=Lời phát đoan|url=https://vi.wikisource.org/wiki/Nho_gi%C3%A1o/Quy%E1%BB%83n_I/L%E1%BB%9Di_ph%C3%A1t_%C4%91oan|passage=Cách học tập của người mình lại chỉ vụ lấy '''từ-chương''', chuyên về khoa-cử để làm cái thang lợi danh.}}
==={{section|ref}}===
* {{R:FVDP}}
mg7ek0js8ur8ezoub1negjqvxx03rhn
tormenta
0
243911
2344292
1931787
2026-04-11T14:30:27Z
Kelly zhrm
58416
2344292
wikitext
text/x-wiki
=={{langname|en}}==
==={{ĐM|n}}===
{{head|en|Biến thể hình thái danh từ}}
# {{plural of|en|tormentum}}
==={{ĐM|ana}}===
* {{anagrams|en|a=aemnortt|Metatron|no matter}}
=={{langname|ast}}==
==={{ĐM|etym}}===
Từ {{der|ast|la|tormenta}}, số nhiều của {{mention|la|tormentum}}.
==={{ĐM|pron}}===
{{ast-pr}}
==={{ĐM|n}}===
{{ast-noun|f|tormentes}}
# [[bão|Bão]].
==={{ĐM|further}}===
* {{R:ast:DGLA}}
* {{R:ast:DALLA}}
=={{langname|es}}==
==={{ĐM|pron}}===
{{es-pr|+<audio:LL-Q1321 (spa)-AdrianAbdulBaha-tormenta.wav<a:Colombia>>}}
==={{ĐM|n}}===
{{es-noun|f}}
# [[bão|Bão]].
#: {{syn|es|tempestad}}
# [[giông|Giông]].
#: {{syn|es|tronada}}
===={{ĐM|drv}}====
{{col|es|tormenta de arena|tormenta de citocinas|tormenta de citoquinas|tormenta de ideas|tormenta de polvo|tormenta ígnea}}
===={{ĐM|rel}}====
{{col|es|tormento}}
==={{ĐM|ref}}===
<references/>
==={{ĐM|further}}===
* {{R:es:DRAE}}
{{C|es|Thời tiết}}
5vjdl6fhm41uxmjxob0kw24n280ntwp
頭
0
245507
2344391
2335741
2026-04-12T04:38:42Z
Hiyuune
50834
/* Từ nguyên 1 */ (sử dụng [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]])
2344391
wikitext
text/x-wiki
{{also|头}}
{{character info}}
=={{langname|mul}}==
{{stroke order|strokes=16}}
==={{section|han}}===
{{Han char|rn=181|rad=頁|as=07|sn=16|four=11186|canj=MTMBC|ids=⿰豆頁}}
===={{section|drv}}====
* {{charlist|sc=Hani|䕱}}
{{col-top|1|Các ký tự dẫn xuất}}
* {{charlist|sc=Hani|𭀆𫷒𢸸𤃌𨯲𡾣𨷩}}
{{col-bottom}}
===={{section|rel}}====
* {{l-lite|mul|sc=Hans|头}} {{q-lite|{{w|chữ Hán giản thể}}}}
===={{section|ref}}====
{{Han ref|kx=1404.200|dkj=43490|dj=1921.130|hdz=74372.050|uh=982D}}
=={{langname|vi}}==
==={{section|han}}===
{{vi-readings|reading=đầu|rs=頁07}}
# {{lb|vi|anatomy}} [[đầu|Đầu]].
#: {{syn|vi|trốc}}
=={{langname|jpx-hcj}}==
==={{ĐM|Kanji}}===
{{jpx-hcj-kanji}}
==={{ĐM|etym}}===
Cùng gốc với {{cog|ja|頭|tr=tsuburi}}.
==={{ĐM|noun}}===
{{jpx-hcj-head|noun|つぶり}}
# [[đầu]].
=={{langname|ja}}==
==={{section|kanji}}===
{{ja-kanji|grade=2|rs=頁07}}
# [[trán|Trán]].
# [[đầu|Đầu]].
# [[chủ nhân|Chủ nhân]].
# Đếm số lượng gia súc lớn (trâu, bò, ngựa).
===={{section|reading}}====
{{ja-readings
|goon=ず<づ
|kanon=とう<とう
|toon=じゅう<ぢゆう
|kanyoon=と
|kun=あたま-, かしら-, かぶり-, こうべ-<かうべ-, かみ-, ほとり-
|nanori=かぶ, かぶし, かみ, ちゃん, つぶり, つむ, つむり, づ, どたま
}}
==={{section|etym}} 1===
{{etymid|ja|atama}}
{{ja-kanjitab|あたま|yomi=k}}
{{wp|ja:}}
===={{section|pron}}====
{{ja-pron|あたま|acc=3|acc_ref=DJR,NHK,<ref name="NKD2O_atama"/>|acc2=2|acc2_ref=DJR,NHK}}
{{ja-accent-dialectal|region=Kyoto|k|あ|たま|áꜜtàmà|ref=<ref name="NKD2O_atama">{{R:ja:NKD2O|あたま 【頭・天窓】|lid=2002001764183y1rk2CW|kotobank=頭-22205#w-1866565}}</ref>}}
{{ja-accent-historical|h=LLL|ref=<ref name="NKD2O_atama"/>}}
===={{section|n}}====
{{ja-noun|あたま}}
# [[đầu|Đầu]].
#: {{syn|ja|びんた|q=phương ngữ, Kagoshima}}
====={{ĐM|desc}}=====
* {{desc|ycr|atama}}
==={{section|etym}} 2===
{{etymid|ja|kashira}}
{{ja-kanjitab|yomi=k|かしら|alt=首}}
===={{section|pron}}====
{{sense|danh từ}}
{{ja-pron|かしら|acc=3|acc_ref=DJR,NHK,<ref name="NKD2O_kashira"/>}}
{{ja-accent-dialectal|region=Kyoto|k|か|しら|káꜜshìrà|ref=<ref name="NKD2O_kashira">{{R:ja:NKD2O|かしら 【頭】|lid=200200d1bce38Q12u6x6|kotobank=頭-22205#w-1915250}}</ref>}}
{{ja-accent-historical|h=LLL|k=LLL|m=HHL|e=HHL|ref=<ref name="NKD2O_kashira"/>}}
===={{section|counter}}====
{{ja-pos|counter|かしら}}
# Đếm số lượng [[gia súc]] lớn.
===={{section|n}}====
{{ja-noun|かしら}}
# {{ja-def|頭}} [[ông|Ông]] [[chủ]]; [[sếp]].
==={{section|etym}} 3===
{{etymid|ja|kaburi}}
{{ja-kanjitab|かぶり|yomi=k}}
===={{section|pron}}====
{{ja-pron|かぶり|acc=0|acc_ref=DJR,NHK|acc2=3|acc2_ref=DJR,NHK,<ref name="NKD2O_kaburi"/>|acc3=1|acc3_ref=DJR,NHK,<ref name="NKD2O_kaburi"/>}}
{{ja-accent-dialectal|region=Kyoto|k-0|かぶり|kábúrí|ref=<ref name="NKD2O_kaburi">{{R:ja:NKD2O|かぶり 【頭】|lid=200200e4a818lnZeX4f1|kotobank=頭-22205#w-1920202}}</ref>}}
===={{section|n}}====
{{ja-noun|かぶり}}
# [[đầu|Đầu]].
==={{section|etym}} 4===
{{etymid|ja|kabu}}
{{ja-kanjitab|かぶ|yomi=irr}}
===={{section|pron}}====
{{ja-pron|かぶ}}
===={{section|n}}====
{{ja-noun|かぶ}}
# {{lb|ja|obsolete|_|or|_|Yamagata|sort=かぶ}} [[đầu|Đầu]].
===={{section|ref}}====
<references/>
:* {{R:Kanjipedia Kotoba|0005233000|<sup>△</sup>頭}}
=={{langname|zh}}==
{{zh-forms|s=头|alt=䫁,𥘖}}
==={{section|glyph origin}}===
{{Han etym}}
{{Han compound|豆|頁|ls=psc|c1=p|c2=s|t2=đầu}}.
==={{section|etym}}===
Kết hợp hình-thanh ([[形聲]]): [[豆]]([[đậu]]) + [[頁]]([[hiệt]]).
==={{section|pron}} 1===
{{zh-pron
|m=tóu
|m-s=tou2
|m-x=tóu
|m-nj=tóu
|dg=ту1
|c=tau4,tau4-2
|ca=LL-Q9186-Justinrleung-頭.wav
|c_note=tau4-2
|c-dg=taau4
|c-t=heu3,heu3*
|c-t_note=heu3*
|c-yj=tau4
|g=teu2
|h=pfs=thèu;hrs=h:teu;gd=têu2
|j=tou1
|mb=tê
|md=tàu
|mn=ml,jj,tp,kh,tn,tc,hc,lk,sx,yl,km,mg,pn,ph,sg:thâu/xm,zz,yl,km,mg:thô͘/qz,jj,tp,kh,tn,lk,sx,hc:thiô
|mn_note=thâu - vernacular; thô͘/thiô - văn chương
|mn-t=tao5
|mn-l=tao5
|px=pt,xy:tao2/pt,xy:tieo2
|px_note=tao2 - vernacular; tieo2 - văn chương
|sp=dau4
|w-j=3tieu,2dieu
|x=dou2
|x-l=ddieu2
|x-h=dou2
|mc=y
|oc=y
|ma=y
|cat=n,cls,a
}}
===={{section|dfn}}====
{{head|zh|Hanzi}}
# [[đầu|Đầu]] ([[bộ phận]] trên [[chóp]] [[cơ thể]]).
# [[tóc|Tóc]]; [[kiểu]] [[tóc]].
# [[đầu|Đầu]] (phần trước nhất hoặc phần trên cùng).
# [[đầu tiên|Đầu tiên]].
# [[chủ nhân|Chủ nhân]].
====={{section|syn}}=====
{{zh-dial}}
{{zh-dial|頭-2}}
{{zh-dial|頭-3}}
{{zh-dial|口-2}}
{{zh-dial|匹}}
{{zh-dial|隻}}
{{zh-dial|條}}
{{zh-dial|朵}}
==={{section|pron}} 2===
{{zh-pron
|m=tou
|m-s=tou2
|dg=
|c=tau4,tau4-2
|c-t=heu3,heu4
|g=teu/teu2
|h=pfs=thèu;hrs=h:teu;gd=têu2
|j=tou2
|mb=tê
|md=tàu
|mn=ml,tp,kh,tn,tc,hc,lk,sx,yl,km,mg,pn,sg:thâu/xm,zz,yl,km,mg:thô͘/qz,tp,kh,tn,lk,sx,hc:thiô/tp,kh,tn,lk,sx,yl,tc:thô
|mn_note=thâu - ngôn ngữ bản địa; thô͘/thiô - văn chương; thô - chỉ dùng với {{l-lite|zh|sc=Hani|饅頭}}
|mn-t=tao5
|px=pt,xy:tao2/pt,xy:tieo2
|px_note=tao2 - ngôn ngữ bản địa; tieo2 - văn chương
|w=sh:6deu
|x=dou
|dial=n
|mc=y
|oc=y
|ma=y
|cat=suf
}}
===={{section|dfn}}====
{{head|zh|Hanzi}}
# {{gloss|[[hậu tố|Hậu tố]] của [[danh từ]]}}.
==={{section|compound}}===
{{col3|zh|一彆頭|一托頭|一踅頭|一頭|三道頭|三頭兩日|三頭兩緒|三頭兩面|三頭六臂|三頭對案|三頭臂肌|上流頭|上頭|下場頭|下溜頭|下頭|不妨頭|不律頭|不徹頭|不是頭|不防頭|並頭|丫頭|丹頭|九頭鳥|乞頭|乳頭|亂頭|事頭|二婚頭|二鍋頭|二頭股肌|二頭臂肌|五路總頭|交頭接耳|人頭|伸頭探腦|伸頭縮頸|低頭|佛頭著糞|作鼻子頭|來頭|依頭縷當|依頭順尾|俏頭|個頭|倒頭|倔頭倔腦|做頭|停頭|傲頭傲腦|傻頭傻腦|兆頭|先頭|光頭|兌頭|兜頭|入頭|兩頭|冒頭|冤頭|出人頭地|出頭|刀頭|分頭|刊頭|初頭|判官頭|刮頭|到頭|刺兒頭|剃胎頭|剃頭|前頭|剪頭|剷頭|劈頭|劍頭一吷|力巴頭|力把兒頭|勁頭|務頭|勢頭|勾頭|包葫蘆頭|包頭|匹頭|千頭橘奴|千頭百緒|千頭萬緒|占鰲頭|卸頭|原頭|參頭|口頭|叩頭|叫頭|吃回頭草|合頭|名頭|吳頭楚尾|呆腦呆頭|呆頭呆腦|呆頭木腦|和頭|咬頭|咽頭|哀江頭|品頭論足|品頭題足|唱頭|問頭|喉頭|喚頭|嘑頭|嘴頭|噴頭|噱頭|囂頭|囊頭|回頭|因頭|圓頭|團頭|土頭土腦|地頭|坐頭|垂頭|埋頭|埠頭|埤頭鄉|堂頭和尚|報頭|堵頭|堽頭|塊頭|塔頭|境頭|墳頭|壽頭|外頭|多頭|大姊頭|大姐頭|大拍頭|大頭|夫頭|奉頭鼠竄|套頭|奶頭|姘頭|媒頭|媽媽頭|字頭|孩子頭|孱頭|容頭過身|宿頭|寡頭|尋頭討腦|對頭|小頭|少頭無尾|尖頭|尺頭|屯頭|山頭|工頭|巨頭|巴頭探腦|布頭|帕頭|帩頭|帶頭|平頭|年頭|幹頭|床頭|店頭|座頭|廚頭灶腦|龐克頭|弔頭|引頭|彈頭|彩頭|後頭|得勝頭迴|從頭|德勝頭迴|徹頭徹尾|心頭|念短頭經|念頭|怪頭|怯頭怯惱|悟頭詩|悶頭|想頭|意頭|愣頭兒青|愣頭愣腦|愣頭磕腦|懸頭|戇頭戇腦|成頭|戥頭|截頭渡|戲頭|戴頭識臉|戶頭|房頭|手頭|扒頭探腦|打出頭棍|打攔頭雷|打沒頭壇|打破頭|打碗頭|打輪頭|打頭|打鼓津頭|扛頭|扣頭|扭頭折頸|扭頭暴筋|扭頭瞥項|扯頭|扳差頭|扶頭|批頭|找頭|承頭|把頭|抓頭挖耳|折頭|披頭|抬頭|抱頭|抵頭|抹頭|押頭|抽頭|抿頭|拈頭|拋頭露面|拐子頭|拔頭|拘頭|招頭|拳頭|拾頭打滾|指頭|挑頭|捉頭|捕頭|捧頭鼠竄|掉頭|掐頭去尾|排頭|掠頭|探頭|接耳交頭|接頭|推頭|提頭|插頭|換頭|搔頭|搖頭|搞頭|搭頭|摟頭|摣頭|摸頭|撐頭獲腦|撓頭|撞頭搕腦|撥頭|撲頭撲臉|撳頭低|攏頭|攬頭|改頭換面|放頭|教頭|敵頭|斧頭|斫頭|斷頭|方頭|旄頭|旗頭|日頭|昂頭挺立|昏頭|暈頭|曆頭|更頭|替頭|會頭|月頭|朋頭|木頭|本頭|朴實頭|杆子頭|杖子頭|杖頭|枋頭|枕頭|枝頭|柱頭|柴頭|根頭|案頭|梆兒頭|梢頭|梳頭|棒頭|楚尾吳頭|楞頭青|楥頭|楦頭|極頭麻化|榔頭|榫頭|槓子頭|槓頭|槽頭|樸實頭|橋頭|橫頭|歌頭|正頭|步頭|殘頭落腳|段頭|殺頭|殿頭官|毛頭|氣頭上|水頭|汕頭|沒頭仰仗|沒頭公事|沒頭告示|沒頭官司|沒頭帖子|沒頭案子|沒頭沒腦|沒頭沒臉|沒頭神|沒頭脫柄|沒頭蒼蠅|沒頭蹲|沒頭鬼|油頭|泛頭|泥頭|洗頭|派頭|浪頭|浮頭|淨頭|混頭混腦|清頭|渡頭|游頭浪子|湯頭|源頭|準頭|溪頭|滑頭|滿頭|澆頭|灘頭|火頭|灰頭土臉|灰頭土面|灰頭草面|灶頭|炕頭子貨|為頭|烏頭|無頭公案|無頭告示|無頭官事|無頭案|無頭無尾|無頭無腦|無頭罪|無頭蒼蠅|無頭願|焦頭爛額|熬頭|燈頭|燋頭爛額|爛羊頭|爛額焦頭|爭頭鼓腦|牆頭|片頭|牌頭|牛頭|牢頭|牽頭|犀頭|狀頭|狗血淋頭|狗頭軍師|狼吃幞頭|猴頭|獃頭獃腦|獅子頭|獐頭鼠目|獨占鰲頭|班頭|甕頭春|甜頭|田頭|由頭|甲頭|畏頭畏尾|留頭|當頭|疋頭|疏頭|疢頭怪腦|瘌痢頭|癩頭|癲頭癲腦|發頭|白頭|百丈竿頭|百尺竿頭|皮頭夯腦|盔頭|盡頭|盤子頭|直頭布袋|盼頭|眉頭|看頭|看香頭的|矇頭轉向|矛頭|短頭|石頭|砍頭|砧頭|破頭楔|硬頭硬腦|碰頭|磁頭|碼頭|磕素頭|磕過頭的|磕頭|磚頭|磨頭|礬頭|社頭|神頭鬼臉|神頭鬼面|禍種頭|萬丈竿頭|萬緒千頭|萬頭攢動|禿頭|科頭|空頭|窩頭|竹頭木屑|竿頭一步|笨頭笨腦|筆頭|管頭|箭頭|篙頭|篦頭|籠頭|米酒頭|粉頭|糟頭|紅頭|納頭|紙糊頭|索頭|組頭|絡頭|綃頭|綠頭鴨|綵頭|線頭|縮頭烏龜|縮頭縮腦|縮頭縮腳|纏頭|缽盂頭|缽頭|罐頭|羊胃羊頭|羊頭狗肉|老實頭|老頭|耐頭|聚頭|聳頭聳腦|聽頭|肉頭|肥頭大耳|肩頭|胖頭魚|腰頭硬|腳頭|臉紅頭脹|臘鎗頭|臨頭|臭頭|臼頭深目|興頭|舉頭|舌頭|舒頭|船頭|芋頭|芒頭|花頭|苗頭|苦頭|茶頭|草頭大王|草頭天子|草頭方兒|草頭神|草頭藥|草頭露|菜頭|菸頭|著糞佛頭|蒙頭|蒜頭|蒼頭|蓋頭|蓬頭|蔥頭|薄頭|薦頭|藏頭亢腦|藏頭漏影|藏頭露尾|藥頭|蘇頭|蘿蔔頭|虎頭|虛頭|號頭|蛇頭鼠眼|蛋頭|蠅頭|蠟槍頭|蠶頭燕尾|行頭|街頭|衲頭|袁頭|被頭|裡頭|裹頭|襆頭|角頭|解頭|討頭|訛頭|評頭品足|評頭評足|評頭論足|詞頭|話頭|認犯頭|認頭|課頭|調頭|論頭|謎頭|護頭|豬頭肥|豹頭猿臂|豹頭環眼|貓兒頭|貓頭鷹|買頭|賊頭賊腦|賊頭鼠腦|賣頭賣腳|賺頭|走頭無路|起頭|趁頭|跟頭|路頭|車頭|軍頭|轉頭|轡頭|辭頭|辮穗頭|迎頭|迭頭|迷頭|這頭|通頭|連頭帶尾|過頭|道頭會尾|道頭知尾|遨頭|邊頭|都頭|鄉頭|配頭|醜頭怪臉|采頭|重頭戲|金頭銀面|釘頭|針頭|釵頭符|釵頭鳳|鈍頭|鈿頭雲篦|銅頭鐵額|鋒頭|鋤頭|鋪頭|鎖頭|鎬頭|鏟頭|鏡頭|鐘頭|鐺頭|鑞鎗頭|鑽頭|钁頭|長頭布|門頭|開頭|關頭|陌頭|陣頭|隅頭|隱頭花序|隴頭音信|雌一頭灰|雙頭汽鍋|雙頭火杖|雙頭馬車|雞頭|雲頭|零頭|霉頭|霞頭|露尾藏頭|露面拋頭|露頭|靈頭幡|青龍頭上|鞠部頭|韻頭|響頭|頂頭|順頭順腦|領頭|頭一|頭七|頭上安頭|頭上抹下|頭上末下|頭上長角,身上長刺|頭主|頭人|頭伏|頭位|頭信|頭像|頭先|頭兒|頭到|頭前|頭功|頭勢|頭匹|頭半天|頭口|頭名|頭哨|頭回|頭囟|頭場|頭大|頭天|頭套|頭妻|頭子|頭家|頭寸|頭對|頭尾|頭屑|頭巾|頭年|頭廳|頭彩|頭影|頭役|頭懸目眩|頭房|頭手鼓|頭把兒|頭抵|頭挑|頭攔|頭敵|頭明|頭昏|頭晌|頭晚|頭暈|頭會箕斂|頭會箕賦|頭朝裡|頭板|頭條|頭梢|頭櫃|頭正|頭水|頭油|頭燈|頭版|頭牌|頭牙|頭獎|頭班車|頭球|頭由|頭當|頭疼|頭痛|頭癢搔跟|頭癬|頭皮|頭盔|頭目|頭直上|頭眩|頭眼|頭破血出|頭破血流|頭破血淋|頭稍|頭童齒豁|頭等|頭箍兒|頭管|頭籌|頭紗|頭絮兒|頭緒|頭繩|頭罩|頭翁|頭肘子|頭胎|頭胸部|頭腦|頭臉|頭茬|頭蓋|頭蓬眼瘇|頭號|頭蝨|頭行|頭裡|頭角|頭足異所|頭足異處|頭足願|頭路|頭踏|頭輕腳重|頭迓|頭道|頭達|頭遭|頭部|頭醋|頭里|頭重腳輕|頭重身輕|頭銜|頭錢|頭陀|頭陣|頭雁|頭難|頭面|頭頂|頭項|頭領|頭頭|頭頸|頭顱|頭風|頭食|頭飾|頭首|頭香|頭馬|頭骨|頭高|頭髮|頭髲|頭髻|頭鵝|頷頭|額頭|顛頭聳腦|風頭|飯頭|饃頭|饅頭|饒頭|香頭|馬快頭|馬頭|駁頭|駕頭|骨頭|骲頭|高頭|髦頭|鬅頭|鬥頭|鬼頭|魁頭|魔頭|魚頭|鰲頭獨占|鱉縮頭|鳳頭鞋|鴉頭襪|鴨頭|黃頭郎|黑頭|點頭|鼇頭|鼓腦爭頭|鼠目獐頭|鼻子頭|鼻頭|齊頭|齒豁頭童|龍頭|龜頭|廟頭|大頭菜|青字頭|南河頭|黃山頭|後頭灣|扒頭|西頭|鹿頭|髦字頭|卷字頭|竹字頭|西字頭|登字頭|虎字頭|四字頭|爪字頭|老字頭|樹頭|臺頭|魚窩頭|硬著頭皮|水龍頭|斜刀頭|負字頭|包字頭|句字頭|風字頭|六字頭|京字頭|玄字頭|蘭字頭|冒字頭|石屋頭|頭筆|火車頭|頭城|攝像頭|埤頭|頭屋|頭份|方頭括號|煙頭|回頭是岸|頭盤|蓬頭垢面|琯頭|嶼頭|虎頭蜂|捅頭|頭鬃|阿頭|nan:穡頭<tr:sit-thâu>|頭北話|nan:無頭神<tr:bô-thâu-sîn>|蠶頭雁尾|蒻頭|螭頭舫|偏頭關}}
==={{section|desc}}===
{{CJKV|頭|ず|j2=とう|두|đầu}}
''Khác'':
* {{desc|tai-pro|*truǝᴬ|t=đầu|bor=1|unc=1}}
** {{desc|aho|𑜑𑜥|𑜍𑜥|𑜍𑜤𑜈𑜫}}
** {{desc|lo|ຫົວ}}
** {{desc|khb|ᦷᦠ}}
** {{desc|nod|ᩉ᩠ᩅᩫ}}
** {{desc|shn|ႁူဝ်}}
** {{desc|blt|ꪬꪺ}}
** {{desc|th|หัว}}
** {{desc|za|hu}}
* {{desc|tai-pro|bor=1}}
** {{desc|aho|𑜄𑜥|𑜄𑜤}}
** {{desc|pcc|duez}}
** {{desc|lo|ໂຕ|ຕົວ}}
** {{desc|khb|ᦷᦎ}}
** {{desc|nod|ᨲᩫ᩠ᩅ}}
** {{desc|skb|ทั๊ว}}
** {{desc|shn|တူဝ်}}
** {{desc|blt|ꪶꪔ}}
** {{desc|th|ตัว}}
** {{desc|za|duz}}
==={{section|ref}}===
* {{R:yue:Hanzi}}
* {{R:twedu|A04555}}
mr2w4ixyw6vfcfzo8voowpcv9t9ig2q
나비
0
246296
2344291
2344265
2026-04-11T14:18:02Z
TheHighFighter2
42988
/* Danh từ */
2344291
wikitext
text/x-wiki
=={{langname|jje}}==
==={{section|pron}}===
{{jje-IPA}}
==={{section|etym}} 1===
Từ {{inh|jje|okm|나ᄇᆡ〮|tr=nàpóy}}. Cùng gốc từ {{cog|ko|나비}}.
===={{section|n}}====
{{head|jje|Danh từ}}
# Con [[bướm]].
==={{section|etym}} 2===
===={{section|n}}====
{{head|jje|noun}}
# {{alternative form of|jje|납|t=[[tiền]]}}
{{C|jje|Lớp Côn trùng}}
=={{langname|ko}}==
==={{section|etym}} 1===
[[image:C-Falter Polygonia C-album.jpg|thumb|right|{{m-self|ko|나비}}]]
{{ko-etym-native|ne|나ᄇᆡ〮|nàpóy}}
{{ko-etym-native|bdb|나뵈〮|nàpwóy|also=y}}
{{etystub|ko}}
===={{section|pron}}====
{{ko-IPA}}
* {{ko-tone|HL}}
===={{section|n}}====
{{ko-noun}}
# Con [[bướm]]
#: {{syn|ko|호접(胡蝶)|호접(蝴蝶)}}
====={{section|drv}}=====
* {{ko-l|왕나비||bướm hổ cánh nâu}}
====={{section|rel}}=====
* {{l|ko|나방}}
==={{section|etym}} 2===
===={{section|pron}}====
{{ko-IPA}}
===={{section|n}}====
{{ko-noun}}
# {{lb|ko|childish}} Con [[mèo]] con.
====={{section|see}}=====
* {{l|ko|고양이|t=mèo}}
===={{section|ref}}====
* {{cite-journal|title=ko:'원숭이'의 어휘사|trans-title=A lexical history of [words for] "monkey"|author={{lang|ko|허인영}} (Heo In-yeong)|year=2019|journal=Han'gugeohak|volume=83|pages=243–272}}
mowgdrkg5ncrb0ijaisj8hyye2f8un1
照貓畫虎
0
253994
2344379
2065346
2026-04-12T04:26:05Z
Hiyuune
50834
2344379
wikitext
text/x-wiki
=={{langname|zh}}==
{{zh-forms|s=照猫画虎}}
==={{section|pron}}===
{{zh-pron
|m=zhàomāohuàhǔ
|c=ziu3 maau1 waak6 fu2
|cat=cy
}}
==={{section|idiom}}===
{{head|zh|Thành ngữ}}
# [[chiếu|Chiếu]] [[miêu]] [[họa]] [[hổ]]: [[trông]] theo [[mèo]] [[vẽ]] hổ, [[bắt chước]] [[làm theo]].
===={{section|syn}}====
* {{zh-l|照葫蘆畫瓢}}
* {{zh-l|依樣畫葫蘆}}
517gccagn58k3zgxtzk223hre5yohal
little by little
0
254706
2344442
2002401
2026-04-12T07:26:29Z
TheHighFighter2
42988
2344442
wikitext
text/x-wiki
=={{langname|en}}==
==={{ĐM|adv}}===
{{head|en|adverb}}
# Từng [[chút]] một; [[dần dà]]; [[lần lần]].
==={{ĐM|ref}}===
* {{R:Lexico}}
{{cln|en|Cặp đẳng kết lặp|Ngữ tuyến tính khẳng định}}
p8jdbil9y0gdctjwodafger10obwbur
芒芒
0
254792
2344381
2015065
2026-04-12T04:27:28Z
Hiyuune
50834
2344381
wikitext
text/x-wiki
=={{langname|zh}}==
==={{section|pron}}===
{{zh-pron|m=mángmáng}}
==={{section|adj}}===
{{head|zh|Tính từ}}
# [[mang mang|Mang mang]].
b3aw36qhytdxgz1dvm3knvmitgxssum
Mô đun:links
828
256182
2344294
2334570
2026-04-11T15:21:43Z
TheHighFighter2
42988
2344294
Scribunto
text/plain
local export = {}
--[=[
[[Unsupported titles]], pages with high memory usage,
extraction modules and part-of-speech names are listed
at [[Module:links/data]].
Other modules used:
[[Module:script utilities]]
[[Module:scripts]]
[[Module:languages]] and its submodules
[[Module:gender and number]]
[[Module:debug/track]]
]=]
local anchors_module = "Module:anchors"
local debug_track_module = "Module:debug/track"
local gender_and_number_module = "Module:gender and number"
local languages_module = "Module:languages"
local load_module = "Module:load"
local memoize_module = "Module:memoize"
local pages_module = "Module:pages"
local pron_qualifier_module = "Module:pron qualifier"
local scripts_module = "Module:scripts"
local script_utilities_module = "Module:script utilities"
local string_encode_entities_module = "Module:string/encode entities"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local ucfirst = require("Module:string utilities").ucfirst
local concat = table.concat
local find = string.find
local get_current_title = mw.title.getCurrentTitle
local insert = table.insert
local ipairs = ipairs
local match = string.match
local new_title = mw.title.new
local pairs = pairs
local remove = table.remove
local sub = string.sub
local toNFC = mw.ustring.toNFC
local tostring = tostring
local type = type
local unstrip = mw.text.unstrip
local NAMESPACE = get_current_title().nsText
local function anchor_encode(...)
anchor_encode = require(memoize_module)(mw.uri.anchorEncode, true)
return anchor_encode(...)
end
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function decode_uri(...)
decode_uri = require(string_utilities_module).decode_uri
return decode_uri(...)
end
-- Can't yet replace, as the [[Module:string utilities]] version no longer has automatic double-encoding prevention, which requires changes here to account for.
local function encode_entities(...)
encode_entities = require(string_encode_entities_module)
return encode_entities(...)
end
local function extend(...)
extend = require(table_module).extend
return extend(...)
end
local function find_best_script_without_lang(...)
find_best_script_without_lang = require(scripts_module).findBestScriptWithoutLang
return find_best_script_without_lang(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_genders(...)
format_genders = require(gender_and_number_module).format_genders
return format_genders(...)
end
local function format_qualifiers(...)
format_qualifiers = require(pron_qualifier_module).format_qualifiers
return format_qualifiers(...)
end
local function get_current_L2(...)
get_current_L2 = require(pages_module).get_current_L2
return get_current_L2(...)
end
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
end
local function get_script(...)
get_script = require(scripts_module).getByCode
return get_script(...)
end
local function language_anchor(...)
language_anchor = require(anchors_module).language_anchor
return language_anchor(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function request_script(...)
request_script = require(script_utilities_module).request_script
return request_script(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function tag_text(...)
tag_text = require(script_utilities_module).tag_text
return tag_text(...)
end
local function tag_translit(...)
tag_translit = require(script_utilities_module).tag_translit
return tag_translit(...)
end
local function trim(...)
trim = require(string_utilities_module).trim
return trim(...)
end
local function u(...)
u = require(string_utilities_module).char
return u(...)
end
local function ulower(...)
ulower = require(string_utilities_module).lower
return ulower(...)
end
local function umatch(...)
umatch = require(string_utilities_module).match
return umatch(...)
end
local m_headword_data
local function get_headword_data()
m_headword_data = load_data("Module:headword/data")
return m_headword_data
end
local function track(page, code)
local tracking_page = "links/" .. page
debug_track(tracking_page)
if code then
debug_track(tracking_page .. "/" .. code)
end
end
local function selective_trim(...)
-- Unconditionally trimmed charset.
local always_trim =
"\194\128-\194\159" .. -- U+0080-009F (C1 control characters)
"\194\173" .. -- U+00AD (soft hyphen)
"\226\128\170-\226\128\174" .. -- U+202A-202E (directionality formatting characters)
"\226\129\166-\226\129\169" -- U+2066-2069 (directionality formatting characters)
-- Standard trimmed charset.
local standard_trim = "%s" .. -- (default whitespace charset)
"\226\128\139-\226\128\141" .. -- U+200B-200D (zero-width spaces)
always_trim
-- If there are non-whitespace characters, trim all characters in `standard_trim`.
-- Otherwise, only trim the characters in `always_trim`.
selective_trim = function(text)
if text == "" then
return text
end
local trimmed = trim(text, standard_trim)
if trimmed ~= "" then
return trimmed
end
return trim(text, always_trim)
end
return selective_trim(...)
end
local function escape(text, str)
local rep
repeat
text, rep = text:gsub("\\\\(\\*" .. str .. ")", "\5%1")
until rep == 0
return (text:gsub("\\" .. str, "\6"))
end
local function unescape(text, str)
return (text
:gsub("\5", "\\")
:gsub("\6", str))
end
-- Remove bold, italics, soft hyphens, strip markers and HTML tags.
local function remove_formatting(str)
str = str
:gsub("('*)'''(.-'*)'''", "%1%2")
:gsub("('*)''(.-'*)''", "%1%2")
:gsub("", "")
return (unstrip(str)
:gsub("<[^<>]+>", ""))
end
--[==[Takes an input and splits on a double slash (taking account of escaping backslashes).]==]
function export.split_on_slashes(text)
if text:find("\\", nil, true) then
track("escaped", "split_on_slashes")
end
text = split(escape(text, "//"), "//", true) or {}
for i, v in ipairs(text) do
text[i] = unescape(v, "//")
if v == "" then
text[i] = false
end
end
return text
end
--[==[Takes a wikilink and outputs the link target and display text. By default, the link target will be returned as a title object, but if `allow_bad_target` is set it will be returned as a string, and no check will be performed as to whether it is a valid link target.]==]
function export.get_wikilink_parts(text, allow_bad_target)
-- TODO: replace `allow_bad_target` with `allow_unsupported`, with support for links to unsupported titles, including escape sequences.
if ( -- Filters out anything but "[[...]]" with no intermediate "[[" or "]]".
not match(text, "^()%[%[") or -- Faster than sub(text, 1, 2) ~= "[[".
find(text, "[[", 3, true) or
find(text, "]]", 3, true) ~= #text - 1
) then
return nil, nil
end
local pipe, title, display = find(text, "|", 3, true)
if pipe then
title, display = sub(text, 3, pipe - 1), sub(text, pipe + 1, -3)
else
title = sub(text, 3, -3)
display = title
end
if allow_bad_target then
return title, display
end
title = new_title(title)
-- No title object means the target is invalid.
if title == nil then
return nil, nil
-- If the link target starts with "#" then mw.title.new returns a broken
-- title object, so grab the current title and give it the correct fragment.
elseif title.prefixedText == "" then
local fragment = title.fragment
if fragment == "" then -- [[#]] isn't valid
return nil, nil
end
title = get_current_title()
title.fragment = fragment
end
return title, display
end
-- Does the work of export.get_fragment, but can be called directly to avoid unnecessary checks for embedded links.
local function get_fragment(text)
text = escape(text, "#")
-- Replace numeric character references with the corresponding character (' → '),
-- as they contain #, which causes the numeric character reference to be
-- misparsed (wa'a → wa'a → pagename wa&, fragment 39;a).
text = decode_entities(text)
local target, fragment = text:match("^(.-)#(.+)$")
target = target or text
target = unescape(target, "#")
fragment = fragment and unescape(fragment, "#")
return target, fragment
end
--[==[Takes a link target and outputs the actual target and the fragment (if any).]==]
function export.get_fragment(text)
if text:find("\\", nil, true) then
track("escaped", "get_fragment")
end
-- If there are no embedded links, process input.
local open = find(text, "[[", nil, true)
if not open then
return get_fragment(text)
end
local close = find(text, "]]", open + 2, true)
if not close then
return get_fragment(text)
-- If there is one, but it's redundant (i.e. encloses everything with no pipe), remove and process.
elseif open == 1 and close == #text - 1 and not find(text, "|", 3, true) then
return get_fragment(sub(text, 3, -3))
end
-- Otherwise, return the input.
return text
end
--[==[
Given a link target as passed to `full_link()`, get the actual page that the target refers to. This removes
bold, italics, strip markets and HTML; calls `makeEntryName()` for the language in question; converts targets
beginning with `*` to the Reconstruction namespace; and converts appendix-constructed languages to the Appendix
namespace. Returns up to three values:
# the actual page to link to, or {nil} to not link to anything;
# how the target should be displayed as, if the user didn't explicitly specify any display text; generally the
same as the original target, but minus any anti-asterisk !!;
# the value `true` if the target had a backslash-escaped * in it (FIXME: explain this more clearly).
]==]
function export.get_link_page_with_auto_display(target, lang, sc, plain)
local orig_target = target
if not target then
return nil
elseif target:find("\\", nil, true) then
track("escaped", "get_link_page")
end
target = remove_formatting(target)
if target:sub(1, 1) == ":" then
track("initial colon")
-- FIXME, the auto_display (second return value) should probably remove the colon
return target:sub(2), orig_target
end
local prefix = target:match("^(.-):")
-- Convert any escaped colons
target = target:gsub("\\:", ":")
if prefix then
-- If this is an a link to another namespace or an interwiki link, ensure there's an initial colon and then
-- return what we have (so that it works as a conventional link, and doesn't do anything weird like add the term
-- to a category.)
prefix = ulower(trim(prefix))
if prefix ~= "" and (
load_data("Module:data/namespaces")[prefix] or
load_data("Module:data/interwikis")[prefix]
) then
return target, orig_target
end
end
-- Check if the term is reconstructed and remove any asterisk. Also check for anti-asterisk (!!).
-- Otherwise, handle the escapes.
local reconstructed, escaped, anti_asterisk
if not plain then
target, reconstructed = target:gsub("^%*(.)", "%1")
if reconstructed == 0 then
target, anti_asterisk = target:gsub("^!!(.)", "%1")
if anti_asterisk == 1 then
-- Remove !! from original. FIXME! We do it this way because the call to remove_formatting() above
-- may cause non-initial !! to be interpreted as anti-asterisks. We should surely move the
-- remove_formatting() call later.
orig_target = orig_target:gsub("^!!", "")
end
end
end
target, escaped = target:gsub("^(\\-)\\%*", "%1*")
if not (sc and sc:getCode() ~= "None") then
sc = lang:findBestScript(target)
end
-- Remove carets if they are used to capitalize parts of transliterations (unless they have been escaped).
if (not sc:hasCapitalization()) and sc:isTransliterated() and target:match("%^") then
target = escape(target, "^")
:gsub("%^", "")
target = unescape(target, "^")
end
-- Get the entry name for the language.
target = lang:makeEntryName(target, sc, reconstructed == 1 or lang:hasType("appendix-constructed"))
-- If the link contains unexpanded template parameters, then don't create a link.
if target:match("{{{.-}}}") then
-- FIXME: Should we return the original target as the default display value (second return value)?
return nil
end
-- Link to appendix for reconstructed terms and terms in appendix-only languages. Plain links interpret *
-- literally, however.
if reconstructed == 1 then
if lang:getFullCode() == "und" then
-- Return the original target as default display value. If we don't do this, we wrongly get
-- [Term?] displayed instead.
return nil, orig_target
end
target = "Từ tái tạo:" .. ucfirst(lang:getFullName()) .. "/" .. target
-- Reconstructed languages and substrates require an initial *.
elseif anti_asterisk ~= 1 and (lang:hasType("reconstructed") or lang:getFamilyCode() == "qfa-sub") then
error(("The specified language %s is unattested, while the term '%s' does not begin with '*' to indicate that it is reconstructed."):
format(lang:getCanonicalName(), orig_target))
elseif lang:hasType("appendix-constructed") then
target = "Phụ lục:" .. ucfirst(lang:getFullName()) .. "/" .. target
else
target = target
end
return target, orig_target, escaped > 0
end
function export.get_link_page(target, lang, sc, plain)
local target, auto_display, escaped = export.get_link_page_with_auto_display(target, lang, sc, plain)
return target, escaped
end
-- Make a link from a given link's parts
local function make_link(link, lang, sc, id, isolated, cats, no_alt_ast, plain)
-- Convert percent encoding to plaintext.
link.target = link.target and decode_uri(link.target, "PATH")
link.fragment = link.fragment and decode_uri(link.fragment, "PATH")
-- Find fragments (if one isn't already set).
-- Prevents {{l|en|word#Etymology 2|word}} from linking to [[word#Etymology 2#English]].
-- # can be escaped as \#.
if link.target and link.fragment == nil then
link.target, link.fragment = get_fragment(link.target)
end
-- Process the target
local auto_display, escaped
link.target, auto_display, escaped = export.get_link_page_with_auto_display(link.target, lang, sc, plain)
-- Create a default display form.
-- If the target is "" then it's a link like [[#English]], which refers to the current page.
if auto_display == "" then
auto_display = (m_headword_data or get_headword_data()).pagename
end
-- If the display is the target and the reconstruction * has been escaped, remove the escaping backslash.
if escaped then
auto_display = auto_display:gsub("\\([^\\]*%*)", "%1", 1)
end
-- Process the display form.
if link.display then
local orig_display = link.display
link.display = lang:makeDisplayText(link.display, sc, true)
if cats then
auto_display = lang:makeDisplayText(auto_display, sc)
-- If the alt text is the same as what would have been automatically generated, then the alt parameter is redundant (e.g. {{l|en|foo|foo}}, {{l|en|w:foo|foo}}, but not {{l|en|w:foo|w:foo}}).
-- If they're different, but the alt text could have been entered as the term parameter without it affecting the target page, then the target parameter is redundant (e.g. {{l|ru|фу|фу́}}).
-- If `no_alt_ast` is true, use pcall to catch the error which will be thrown if this is a reconstructed lang and the alt text doesn't have *.
if link.display == auto_display then
insert(cats, "Liên kết mục từ có tham số alt thừa " .. lang:getFullName())
else
local ok, check
if no_alt_ast then
ok, check = pcall(export.get_link_page, orig_display, lang, sc, plain)
else
ok = true
check = export.get_link_page(orig_display, lang, sc, plain)
end
if ok and link.target == check then
insert(cats, "Liên kết mục từ có tham số mục tiêu thừa " .. lang:getFullName())
end
end
end
else
link.display = lang:makeDisplayText(auto_display, sc)
end
if not link.target then
return link.display
end
-- If the target is the same as the current page, there is no sense id
-- and either the language code is "und" or the current L2 is the current
-- language then return a "self-link" like the software does.
if link.target == get_current_title().prefixedText then
local fragment, current_L2 = link.fragment, get_current_L2()
if (
fragment and fragment == current_L2 or
not (id or fragment) and (lang:getFullCode() == "und" or lang:getFullName() == current_L2)
) then
return tostring(mw.html.create("strong")
:addClass("selflink")
:wikitext(link.display))
end
end
-- Add fragment. Do not add a section link to "Undetermined", as such sections do not exist and are invalid.
-- TabbedLanguages handles links without a section by linking to the "last visited" section, but adding
-- "Undetermined" would break that feature. For localized prefixes that make syntax error, please use the
-- format: ["xyz"] = true.
local prefix = link.target:match("^:*([^:]+):")
prefix = prefix and ulower(prefix)
if prefix ~= "category" and not (prefix and load_data("Module:data/interwikis")[prefix]) then
if (link.fragment or link.target:sub(-1) == "#") and not plain then
track("fragment", lang:getFullCode())
if cats then
insert(cats, "Liên kết có phân mảnh thủ công " .. lang:getFullName())
end
end
if not link.fragment then
if id then
link.fragment = lang:getFullCode() == "und" and anchor_encode(id) or language_anchor(lang, id)
elseif lang:getFullCode() ~= "und" and not (link.target:match("^Phụ lục:") or link.target:match("^Từ tái tạo:")) then
link.fragment = anchor_encode(ucfirst(lang:getFullName()))
end
end
end
-- Put inward-facing square brackets around a link to isolated spacing character(s).
if isolated and #link.display > 0 and not umatch(decode_entities(link.display), "%S") then
link.display = "]" .. link.display .. "["
end
link.target = link.target:gsub("^(:?)(.*)", function(m1, m2)
return m1 .. encode_entities(m2, "#%&+/:<=>@[\\]_{|}")
end)
link.fragment = link.fragment and encode_entities(remove_formatting(link.fragment), "#%&+/:<=>@[\\]_{|}")
return "[[" .. link.target:gsub("^[^:]", ":%0") .. (link.fragment and "#" .. link.fragment or "") .. "|" .. link.display .. "]]"
end
-- Split a link into its parts
local function parse_link(linktext)
local link = {target = linktext}
local target = link.target
link.target, link.display = target:match("^(..-)|(.+)$")
if not link.target then
link.target = target
link.display = target
end
-- There's no point in processing these, as they aren't real links.
local target_lower = link.target:lower()
for _, false_positive in ipairs({"category", "cat", "file", "image"}) do
if target_lower:match("^" .. false_positive .. ":") then
return nil
end
end
link.display = decode_entities(link.display)
link.target, link.fragment = get_fragment(link.target)
-- So that make_link does not look for a fragment again.
if not link.fragment then
link.fragment = false
end
return link
end
local function check_params_ignored_when_embedded(alt, lang, id, cats)
if alt then
track("alt-ignored")
if cats then
insert(cats, "Liên kết mục từ có tham số alt bỏ qua " .. lang:getFullName())
end
end
if id then
track("id-ignored")
if cats then
insert(cats, "Liên kết mục từ có tham số id bỏ qua " .. lang:getFullName())
end
end
end
-- Find embedded links and ensure they link to the correct section.
local function process_embedded_links(text, alt, lang, sc, id, cats, no_alt_ast, plain)
-- Process the non-linked text.
text = lang:makeDisplayText(text, sc, true)
-- If the text begins with * and another character, then act as if each link begins with *. However, don't do this if the * is contained within a link at the start. E.g. `|*[[foo]]` would set all_reconstructed to true, while `|[[*foo]]` would not.
local all_reconstructed = false
if not plain then
-- anchor_encode removes links etc.
if anchor_encode(text):sub(1, 1) == "*" then
all_reconstructed = true
end
-- Otherwise, handle any escapes.
text = text:gsub("^(\\-)\\%*", "%1*")
end
check_params_ignored_when_embedded(alt, lang, id, cats)
local function process_link(space1, linktext, space2)
local capture = "[[" .. linktext .. "]]"
local link = parse_link(linktext)
-- Return unprocessed false positives untouched (e.g. categories).
if not link then
return capture
end
if all_reconstructed then
if link.target:find("^!!") then
-- Check for anti-asterisk !! at the beginning of a target, indicating that a reconstructed term
-- wants a part of the term to link to a non-reconstructed term, e.g. Old English
-- {{ang-noun|m|head=*[[!!Crist|Cristes]] [[!!mæsseǣfen]]}}.
link.target = link.target:sub(3)
-- Also remove !! from the display, which may have been copied from the target (as in mæsseǣfen in
-- the example above).
link.display = link.display:gsub("^!!", "")
elseif not link.target:match("^%*") then
link.target = "*" .. link.target
end
end
linktext = make_link(link, lang, sc, id, false, nil, no_alt_ast, plain)
:gsub("^%[%[", "\3")
:gsub("%]%]$", "\4")
return space1 .. linktext .. space2
end
-- Use chars 1 and 2 as temporary substitutions, so that we can use charsets. These are converted to chars 3 and 4 by process_link, which means we can convert any remaining chars 1 and 2 back to square brackets (i.e. those not part of a link).
text = text
:gsub("%[%[", "\1")
:gsub("%]%]", "\2")
-- If the script uses ^ to capitalize transliterations, make sure that any carets preceding links are on the inside, so that they get processed with the following text.
if (
text:find("^", nil, true) and
not sc:hasCapitalization() and
sc:isTransliterated()
) then
text = escape(text, "^")
:gsub("%^\1", "\1%^")
text = unescape(text, "^")
end
text = text:gsub("\1(%s*)([^\1\2]-)(%s*)\2", process_link)
-- Remove the extra * at the beginning of a language link if it's immediately followed by a link whose display begins with * too.
if all_reconstructed then
text = text:gsub("^%*\3([^|\1-\4]+)|%*", "\3%1|*")
end
return (text
:gsub("[\1\3]", "[[")
:gsub("[\2\4]", "]]")
)
end
local function simple_link(term, fragment, alt, lang, sc, id, cats, no_alt_ast, srwc)
local plain
if lang == nil then
lang, plain = get_lang("und"), true
end
-- Get the link target and display text. If the term is the empty string, treat the input as a link to the current page.
if term == "" then
term = get_current_title().prefixedText
elseif term then
local new_term, new_alt = export.get_wikilink_parts(term, true)
if new_term then
check_params_ignored_when_embedded(alt, lang, id, cats)
-- [[|foo]] links are treated as plaintext "[[|foo]]".
-- FIXME: Pipes should be handled via a proper escape sequence, as they can occur in unsupported titles.
if new_term == "" then
term, alt = nil, term
else
local title = new_title(new_term)
if title then
local ns = title.namespace
-- File: and Category: links should be returned as-is.
if ns == 6 or ns == 14 then
return term
end
end
term, alt = new_term, new_alt
if cats then
if not (srwc and srwc(term, alt)) then
insert(cats, "Liên kết mục từ có liên kết wiki thừa " .. lang:getFullName())
end
end
end
end
end
if alt then
alt = selective_trim(alt)
if alt == "" then
alt = nil
end
end
-- If there's nothing to process, return nil.
if not (term or alt) then
return nil
end
-- If there is no script, get one.
if not sc then
sc = lang:findBestScript(alt or term)
end
-- Embedded wikilinks need to be processed individually.
if term then
local open = find(term, "[[", nil, true)
if open and find(term, "]]", open + 2, true) then
return process_embedded_links(term, alt, lang, sc, id, cats, no_alt_ast, plain)
end
term = selective_trim(term)
end
-- If not, make a link using the parameters.
return make_link({
target = term,
display = alt,
fragment = fragment
}, lang, sc, id, true, cats, no_alt_ast, plain)
end
--[==[Creates a basic link to the given term. It links to the language section (such as <code>==English==</code>), but it does not add language and script wrappers, so any code that uses this function should call the <code class="n">[[Module:script utilities#tag_text|tag_text]]</code> from [[Module:script utilities]] to add such wrappers itself at some point.
The first argument, <code class="n">data</code>, may contain the following items, a subset of the items used in the <code class="n">data</code> argument of <code class="n">full_link</code>. If any other items are included, they are ignored.
{ {
term = entry_to_link_to,
alt = link_text_or_displayed_text,
lang = language_object,
id = sense_id,
} }
; <code class="n">term</code>
: Text to turn into a link. This is generally the name of a page. The text can contain wikilinks already embedded in it. These are processed individually just like a single link would be. The <code class="n">alt</code> argument is ignored in this case.
; <code class="n">alt</code> (''optional'')
: The alternative display for the link, if different from the linked page. If this is {{code|lua|nil}}, the <code class="n">text</code> argument is used instead (much like regular wikilinks). If <code class="n">text</code> contains wikilinks in it, this argument is ignored and has no effect. (Links in which the alt is ignored are tracked with the tracking template {{whatlinkshere|tracking=links/alt-ignored}}.)
; <code class="n">lang</code>
: The [[Module:languages#Language objects|language object]] for the term being linked. If this argument is defined, the function will determine the language's canonical name (see [[Template:language data documentation]]), and point the link or links in the <code class="n">term</code> to the language's section of an entry, or to a language-specific senseid if the <code class="n">id</code> argument is defined.
; <code class="n">id</code> (''optional'')
: Sense id string. If this argument is defined, the link will point to a language-specific sense id ({{ll|en|identifier|id=HTML}}) created by the template {{temp|senseid}}. A sense id consists of the language's canonical name, a hyphen (<code>-</code>), and the string that was supplied as the <code class="n">id</code> argument. This is useful when a term has more than one sense in a language. If the <code class="n">term</code> argument contains wikilinks, this argument is ignored. (Links in which the sense id is ignored are tracked with the tracking template {{whatlinkshere|tracking=links/id-ignored}}.)
The second argument is as follows:
; <code class="n">allow_self_link</code>
: If {{code|lua|true}}, the function will also generate links to the current page. The default ({{code|lua|false}}) will not generate a link but generate a bolded "self link" instead.
The following special options are processed for each link (both simple text and with embedded wikilinks):
* The target page name will be processed to generate the correct entry name. This is done by the [[Module:languages#makeEntryName|makeEntryName]] function in [[Module:languages]], using the <code class="n">entry_name</code> replacements in the language's data file (see [[Template:language data documentation]] for more information). This function is generally used to automatically strip dictionary-only diacritics that are not part of the normal written form of a language.
* If the text starts with <code class="n">*</code>, then the term is considered a reconstructed term, and a link to the Reconstruction: namespace will be created. If the text contains embedded wikilinks, then <code class="n">*</code> is automatically applied to each one individually, while preserving the displayed form of each link as it was given. This allows linking to phrases containing multiple reconstructed terms, while only showing the * once at the beginning.
* If the text starts with <code class="n">:</code>, then the link is treated as "raw" and the above steps are skipped. This can be used in rare cases where the page name begins with <code class="n">*</code> or if diacritics should not be stripped. For example:
** {{temp|l|en|*nix}} links to the nonexistent page [[Reconstruction:English/nix]] (<code class="n">*</code> is interpreted as a reconstruction), but {{temp|l|en|:*nix}} links to [[*nix]].
** {{temp|l|sl|Franche-Comté}} links to the nonexistent page [[Franche-Comte]] (<code>é</code> is converted to <code>e</code> by <code class="n">makeEntryName</code>), but {{temp|l|sl|:Franche-Comté}} links to [[Franche-Comté]].]==]
function export.language_link(data)
if type(data) ~= "table" then
error("The first argument to the function language_link must be a table. See Module:links/documentation for more information.")
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then
track("escaped", "language_link")
end
-- Categorize links to "und".
local lang, cats = data.lang, data.cats
if cats and lang:getCode() == "und" then
insert(cats, "Liên kết ngôn ngữ không xác định")
end
return simple_link(
data.term,
data.fragment,
data.alt,
lang,
data.sc,
data.id,
cats,
data.no_alt_ast,
data.suppress_redundant_wikilink_cat
)
end
function export.plain_link(data)
if type(data) ~= "table" then
error("The first argument to the function plain_link must be a table. See Module:links/documentation for more information.")
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then
track("escaped", "plain_link")
end
return simple_link(
data.term,
data.fragment,
data.alt,
nil,
data.sc,
data.id,
data.cats,
data.no_alt_ast,
data.suppress_redundant_wikilink_cat
)
end
--[==[Replace any links with links to the correct section, but don't link the whole text if no embedded links are found. Returns the display text form.]==]
function export.embedded_language_links(data)
if type(data) ~= "table" then
error("The first argument to the function embedded_language_links must be a table. See Module:links/documentation for more information.")
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then
track("escaped", "embedded_language_links")
end
local term, lang, sc = data.term, data.lang, data.sc
-- If we don't have a script, get one.
if not sc then
sc = lang:findBestScript(term)
end
-- Do we have embedded wikilinks? If so, they need to be processed individually.
local open = find(term, "[[", nil, true)
if open and find(term, "]]", open + 2, true) then
return process_embedded_links(term, data.alt, lang, sc, data.id, data.cats, data.no_alt_ast)
end
-- If not, return the display text.
term = selective_trim(term)
-- FIXME: Double-escape any percent-signs, because we don't want to treat non-linked text as having percent-encoded characters. This is a hack: percent-decoding should come out of [[Module:languages]] and only dealt with in this module, as it's specific to links.
term = term:gsub("%%", "%%25")
return lang:makeDisplayText(term, sc, true)
end
function export.mark(text, item_type, face, lang)
local tag = { "", "" }
if item_type == "gloss" then
tag = { '<span class="mention-gloss-double-quote">“</span><span class="mention-gloss">',
'</span><span class="mention-gloss-double-quote">”</span>' }
if type(text) == "string" and text:match("^''[^'].*''$") then
-- Temporary tracking for mention glosses that are entirely italicized or bolded, which is probably
-- wrong. (Note that this will also find bolded mention glosses since they use triple apostrophes.)
track("italicized-mention-gloss", lang and lang:getFullCode() or nil)
end
elseif item_type == "tr" then
if face == "term" then
tag = { '<span lang="' .. lang:getFullCode() .. '" class="tr mention-tr Latn">',
'</span>' }
else
tag = { '<span lang="' .. lang:getFullCode() .. '" class="tr Latn">', '</span>' }
end
elseif item_type == "ts" then
-- \226\129\160 = word joiner (zero-width non-breaking space) U+2060
tag = { '<span class="ts mention-ts Latn">/\226\129\160', '\226\129\160/</span>' }
elseif item_type == "pos" then
tag = { '<span class="ann-pos">', '</span>' }
elseif item_type == "non-gloss" then
tag = { '<span class="ann-non-gloss">', '</span>' }
elseif item_type == "annotations" then
tag = { '<span class="mention-gloss-paren annotation-paren">(</span>',
'<span class="mention-gloss-paren annotation-paren">)</span>' }
end
if type(text) == "string" then
return tag[1] .. text .. tag[2]
else
return ""
end
end
local pos_tags
--[==[Formats the annotations that are displayed with a link created by {{code|lua|full_link}}. Annotations are the extra bits of information that are displayed following the linked term, and include things such as gender, transliteration, gloss and so on.
* The first argument is a table possessing some or all of the following keys:
*:; <code class="n">genders</code>
*:: Table containing a list of gender specifications in the style of [[Module:gender and number]].
*:; <code class="n">tr</code>
*:: Transliteration.
*:; <code class="n">gloss</code>
*:: Gloss that translates the term in the link, or gives some other descriptive information.
*:; <code class="n">pos</code>
*:: Part of speech of the linked term. If the given argument matches one of the aliases in `pos_aliases` in [[Module:headword/data]], or consists of a part of speech or alias followed by `f` (for a non-lemma form), expand it appropriately. Otherwise, just show the given text as it is.
*:; <code class="n">ng</code>
*:: Arbitrary non-gloss descriptive text for the link. This should be used in preference to putting descriptive text in `gloss` or `pos`.
*:; <code class="n">lit</code>
*:: Literal meaning of the term, if the usual meaning is figurative or idiomatic.
*:Any of the above values can be omitted from the <code class="n">info</code> argument. If a completely empty table is given (with no annotations at all), then an empty string is returned.
* The second argument is a string. Valid values are listed in [[Module:script utilities/data]] "data.translit" table.]==]
function export.format_link_annotations(data, face)
local output = {}
-- Interwiki link
if data.interwiki then
insert(output, data.interwiki)
end
-- Genders
if type(data.genders) ~= "table" then
data.genders = { data.genders }
end
if data.genders and #data.genders > 0 then
local genders, gender_cats = format_genders(data.genders, data.lang)
insert(output, " " .. genders)
if gender_cats then
local cats = data.cats
if cats then
extend(cats, gender_cats)
end
end
end
local annotations = {}
-- Transliteration and transcription
if data.tr and data.tr[1] or data.ts and data.ts[1] then
local kind
if face == "term" then
kind = face
else
kind = "default"
end
if data.tr[1] and data.ts[1] then
insert(annotations, tag_translit(data.tr[1], data.lang, kind) .. " " .. export.mark(data.ts[1], "ts"))
elseif data.ts[1] then
insert(annotations, export.mark(data.ts[1], "ts"))
else
insert(annotations, tag_translit(data.tr[1], data.lang, kind))
end
end
-- Gloss/translation
if data.gloss then
insert(annotations, export.mark(data.gloss, "gloss"))
end
-- Part of speech
if data.pos then
-- debug category for pos= containing transcriptions
if data.pos:match("/[^><]-/") then
data.pos = data.pos .. "[[Category:links likely containing transcriptions in pos]]"
end
-- Canonicalize part of speech aliases as well as non-lemma aliases like 'nf' or 'nounf' for "noun form".
pos_tags = pos_tags or (m_headword_data or get_headword_data()).pos_aliases
local pos = pos_tags[data.pos]
if not pos and data.pos:find("f$") then
local pos_form = data.pos:sub(1, -2)
-- We only expand something ending in 'f' if the result is a recognized non-lemma POS.
pos_form = (pos_tags[pos_form] or pos_form) .. " form"
if (m_headword_data or get_headword_data()).nonlemmas[pos_form .. "s"] then
pos = pos_form
end
end
insert(annotations, export.mark(pos or data.pos, "pos"))
end
-- Non-gloss text
if data.ng then
insert(annotations, export.mark(data.ng, "non-gloss"))
end
-- Literal/sum-of-parts meaning
if data.lit then
insert(annotations, "nghĩa đen " .. export.mark(data.lit, "gloss"))
end
-- Provide a hook to insert additional annotations such as nested inflections.
if data.postprocess_annotations then
data.postprocess_annotations {
data = data,
annotations = annotations
}
end
if #annotations > 0 then
insert(output, " " .. export.mark(concat(annotations, ", "), "annotations"))
end
return concat(output)
end
-- Encode certain characters to avoid various delimiter-related issues at various stages. We need to encode < and >
-- because they end up forming part of CSS class names inside of <span ...> and will interfere with finding the end
-- of the HTML tag. I first tried converting them to URL encoding, i.e. %3C and %3E; they then appear in the URL as
-- %253C and %253E, which get mapped back to %3C and %3E when passed to [[Module:accel]]. But mapping them to <
-- and > somehow works magically without any further work; they appear in the URL as < and >, and get passed to
-- [[Module:accel]] as < and >. I have no idea who along the chain of calls is doing the encoding and decoding. If
-- someone knows, please modify this comment appropriately!
local accel_char_map
local function get_accel_char_map()
accel_char_map = {
["%"] = ".",
[" "] = "_",
["_"] = u(0xFFF0),
["<"] = "<",
[">"] = ">",
}
return accel_char_map
end
local function encode_accel_param_chars(param)
return (param:gsub("[% <>_]", accel_char_map or get_accel_char_map()))
end
local function encode_accel_param(prefix, param)
if not param then
return ""
end
if type(param) == "table" then
local filled_params = {}
-- There may be gaps in the sequence, especially for translit params.
local maxindex = 0
for k in pairs(param) do
if type(k) == "number" and k > maxindex then
maxindex = k
end
end
for i = 1, maxindex do
filled_params[i] = param[i] or ""
end
-- [[Module:accel]] splits these up again.
param = concat(filled_params, "*~!")
end
-- This is decoded again by [[WT:ACCEL]].
return prefix .. encode_accel_param_chars(param)
end
local function insert_if_not_blank(list, item)
if item == "" then
return
end
insert(list, item)
end
local function get_class(lang, tr, accel, nowrap)
if not accel and not nowrap then
return ""
end
local classes = {}
if accel then
insert(classes, "form-of lang-" .. lang:getFullCode())
local form = accel.form
if form then
insert(classes, encode_accel_param_chars(form) .. "-form-of")
end
insert_if_not_blank(classes, encode_accel_param("gender-", accel.gender))
insert_if_not_blank(classes, encode_accel_param("pos-", accel.pos))
insert_if_not_blank(classes, encode_accel_param("transliteration-", accel.translit or (tr ~= "-" and tr or nil)))
insert_if_not_blank(classes, encode_accel_param("target-", accel.target))
insert_if_not_blank(classes, encode_accel_param("origin-", accel.lemma))
insert_if_not_blank(classes, encode_accel_param("origin_transliteration-", accel.lemma_translit))
if accel.no_store then
insert(classes, "form-of-nostore")
end
end
if nowrap then
insert(classes, nowrap)
end
return concat(classes, " ")
end
-- Add any left or right regular or accent qualifiers, labels or references to a formatted term. `data` is the object
-- specifying the term, which should optionally contain:
-- * a language object in `lang`; required if any accent qualifiers or labels are given;
-- * left regular qualifiers in `q` (an array of strings or a single string); an empty array or blank string will be
-- ignored;
-- * right regular qualifiers in `qq` (an array of strings or a single string); an empty array or blank string will be
-- ignored;
-- * left accent qualifiers in `a` (an array of strings); an empty array will be ignored;
-- * right accent qualifiers in `aa` (an array of strings); an empty array will be ignored;
-- * left labels in `l` (an array of strings); an empty array will be ignored;
-- * right labels in `ll` (an array of strings); an empty array will be ignored;
-- * references in `refs`, an array either of strings (formatted reference text) or objects containing fields `text`
-- (formatted reference text) and optionally `name` and/or `group`.
-- `formatted` is the formatted version of the term itself.
local function add_qualifiers_and_refs_to_term(data, formatted)
local q = data.q
if type(q) == "string" then
q = {q}
end
local qq = data.qq
if type(qq) == "string" then
qq = {qq}
end
if q and q[1] or qq and qq[1] or data.a and data.a[1] or data.aa and data.aa[1] or data.l and data.l[1] or
data.ll and data.ll[1] or data.refs and data.refs[1] then
formatted = format_qualifiers{
lang = data.lang,
text = formatted,
q = q,
qq = qq,
a = data.a,
aa = data.aa,
l = data.l,
ll = data.ll,
refs = data.refs,
}
end
return formatted
end
--[==[
Creates a full link, with annotations (see `[[#format_link_annotations|format_link_annotations]]`), in the style of {{tl|l}} or {{tl|m}}.
The first argument, `data`, must be a table. It contains the various elements that can be supplied as parameters to {{tl|l}} or {{tl|m}}:
{ {
term = entry_to_link_to,
alt = link_text_or_displayed_text,
lang = language_object,
sc = script_object,
track_sc = boolean,
no_nonstandard_sc_cat = boolean,
fragment = link_fragment,
id = sense_id,
genders = { "gender1", "gender2", ... },
tr = transliteration,
respect_link_tr = boolean,
ts = transcription,
gloss = gloss,
pos = part_of_speech_tag,
ng = non-gloss text,
lit = literal_translation,
no_alt_ast = boolean,
accel = {accelerated_creation_tags},
interwiki = interwiki,
pretext = "text_at_beginning" or nil,
posttext = "text_at_end" or nil,
q = { "left_qualifier1", "left_qualifier2", ...} or "left_qualifier",
qq = { "right_qualifier1", "right_qualifier2", ...} or "right_qualifier",
l = { "left_label1", "left_label2", ...},
ll = { "right_label1", "right_label2", ...},
a = { "left_accent_qualifier1", "left_accent_qualifier2", ...},
aa = { "right_accent_qualifier1", "right_accent_qualifier2", ...},
refs = { "formatted_ref1", "formatted_ref2", ...} or { {text = "text", name = "name", group = "group"}, ... },
show_qualifiers = boolean,
} }
Any one of the items in the `data` table may be {nil}, but an error will be shown if neither `term` nor `alt` nor `tr`
is present. Thus, calling {full_link{ term = term, lang = lang, sc = sc }}, where `term` is the page to link to (which
may have diacritics that will be stripped and/or embedded bracketed links) and `lang` is a
[[Module:languages#Language objects|language object]] from [[Module:languages]], will give a plain link similar to the
one produced by the template {{tl|l}}, and calling {full_link( { term = term, lang = lang, sc = sc }, "term" )} will
give a link similar to the one produced by the template {{tl|m}}.
The function will:
* Try to determine the script, based on the characters found in the `term` or `alt` argument, if the script was not
given. If a script is given and `track_sc` is {true}, it will check whether the input script is the same as the one
which would have been automatically generated and add the category [[:Category:LANG terms with redundant script codes]]
if yes, or [[:Category:LANG terms with non-redundant manual script codes]] if no. This should be used when the input
script object is directly determined by a template's `sc` parameter.
* Call `[[#language_link|language_link]]` on the `term` or `alt` forms, to remove diacritics in the page name, process
any embedded wikilinks and create links to Reconstruction or Appendix pages when necessary.
* Call `[[Module:script utilities#tag_text]]` to add the appropriate language and script tags to the term and
italicize terms written in the Latin script if necessary. Accelerated creation tags, as used by [[WT:ACCEL]], are
included.
* Generate a transliteration, based on the `alt` or `term` arguments, if the script is not Latin, no transliteration was
provided in `tr` and the combination of the term's language and script support automatic transliteration. The
transliteration itself will be linked if both `.respect_link_tr` is specified and the language of the term has the
`link_tr` property set for the script of the term; but not otherwise.
* Add the annotations (transliteration, gender, gloss, etc.) after the link.
* If `no_alt_ast` is specified, then the `alt` text does not need to contain an asterisk if the language is
reconstructed. This should only be used by modules which really need to allow links to reconstructions that don't
display asterisks (e.g. number boxes).
* If `pretext` or `posttext` is specified, this is text to (respectively) prepend or append to the output, directly
before processing qualifiers, labels and references. This can be used to add arbitrary extra text inside of the
qualifiers, labels and references.
* If `show_qualifiers` is specified or the `show_qualifiers` argument is given, then left and right qualifiers, accent
qualifiers, labels and references will be displayed, otherwise they will be ignored. (This is because a fair amount of
code stores qualifiers, labels and/or references in these fields and displays them itself, rather than expecting
{full_link()} to display them.)]==]
function export.full_link(data, face, allow_self_link, show_qualifiers)
if type(data) ~= "table" then
error("The first argument to the function full_link must be a table. "
.. "See Module:links/documentation for more information.")
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then
track("escaped", "full_link")
end
-- Prevent data from being destructively modified.
local data = shallow_copy(data)
-- FIXME: this shouldn't be added to `data`, as that means the input table needs to be cloned.
data.cats = {}
-- Categorize links to "und".
local lang, cats = data.lang, data.cats
if cats and lang:getCode() == "und" then
insert(cats, "Liên kết ngôn ngữ không xác định")
end
local terms = {true}
-- Generate multiple forms if applicable.
for _, param in ipairs{"term", "alt"} do
if type(data[param]) == "string" and data[param]:find("//", nil, true) then
data[param] = export.split_on_slashes(data[param])
elseif type(data[param]) == "string" and not (type(data.term) == "string" and data.term:find("//", nil, true)) then
if not data.no_generate_forms then
data[param] = lang:generateForms(data[param])
else
data[param] = {data[param]}
end
else
data[param] = {}
end
end
for _, param in ipairs{"sc", "tr", "ts"} do
data[param] = {data[param]}
end
for _, param in ipairs{"term", "alt", "sc", "tr", "ts"} do
for i in pairs(data[param]) do
terms[i] = true
end
end
-- Create the link
local output = {}
local id, no_alt_ast, srwc, accel, nevercalltr = data.id, data.no_alt_ast, data.suppress_redundant_wikilink_cat,
data.accel, data.never_call_transliteration_module
local link_tr = data.respect_link_tr and lang:link_tr(data.sc[1])
for i in ipairs(terms) do
local link
-- Is there any text to show?
if (data.term[i] or data.alt[i]) then
-- Try to detect the script if it was not provided
local display_term = data.alt[i] or data.term[i]
local best = lang:findBestScript(display_term)
-- no_nonstandard_sc_cat is intended for use in [[Module:interproject]]
if (
not data.no_nonstandard_sc_cat and
best:getCode() == "None" and
find_best_script_without_lang(display_term):getCode() ~= "None"
) then
insert(cats, "Mục từ có chữ viết không chuẩn " .. lang:getFullName())
end
if not data.sc[i] then
data.sc[i] = best
-- Track uses of sc parameter.
elseif data.track_sc then
if data.sc[i]:getCode() == best:getCode() then
insert(cats, "Mục từ có mã chữ viết thừa " .. lang:getFullName())
else
insert(cats, "Mục từ có mã chữ viết thủ công không thừa " .. lang:getFullName())
end
end
-- If using a discouraged character sequence, add to maintenance category
if data.sc[i]:hasNormalizationFixes() == true then
if (data.term[i] and data.sc[i]:fixDiscouragedSequences(toNFC(data.term[i])) ~= toNFC(data.term[i])) or (data.alt[i] and data.sc[i]:fixDiscouragedSequences(toNFC(data.alt[i])) ~= toNFC(data.alt[i])) then
insert(cats, "Pages using discouraged character sequences")
end
end
link = simple_link(
data.term[i],
data.fragment,
data.alt[i],
lang,
data.sc[i],
id,
cats,
no_alt_ast,
srwc
)
end
-- simple_link can return nil, so check if a link has been generated.
if link then
-- Add "nowrap" class to prefixes in order to prevent wrapping after the hyphen
local nowrap
local display_term = data.alt[i] or data.term[i]
if display_term and (display_term:find("^%-") or display_term:find("^־")) then -- Hebrew maqqef -- FIXME, use hyphens from [[Module:affix]]
nowrap = "nowrap"
end
link = tag_text(link, lang, data.sc[i], face, get_class(lang, data.tr[i], accel, nowrap))
else
--[[ No term to show.
Is there at least a transliteration we can work from? ]]
link = request_script(lang, data.sc[i])
-- No link to show, and no transliteration either. Show a term request (unless it's a substrate, as they rarely take terms).
if (link == "" or (not data.tr[i]) or data.tr[i] == "-") and lang:getFamilyCode() ~= "qfa-sub" then
-- If there are multiple terms, break the loop instead.
if i > 1 then
remove(output)
break
elseif NAMESPACE ~= "Bản mẫu" then
insert(cats, "Yêu cầu mục từ " .. lang:getFullName())
end
link = "<small>[Mục từ gì?]</small>"
end
end
insert(output, link)
if i < #terms then insert(output, "<span class=\"Zsym mention\" style=\"font-size:100%;\"> / </span>") end
end
-- TODO: Currently only handles the first transliteration, pending consensus on how to handle multiple translits for multiple forms, as this is not always desirable (e.g. traditional/simplified Chinese).
if data.tr[1] == "" or data.tr[1] == "-" then
data.tr[1] = nil
else
local phonetic_extraction = load_data("Module:links/data").phonetic_extraction
phonetic_extraction = phonetic_extraction[lang:getCode()] or phonetic_extraction[lang:getFullCode()]
if phonetic_extraction then
data.tr[1] = data.tr[1] or require(phonetic_extraction).getTranslit(export.remove_links(data.alt[1] or data.term[1]))
elseif (data.term[1] or data.alt[1]) and data.sc[1]:isTransliterated() then
-- Track whenever there is manual translit. The categories below like 'terms with redundant transliterations'
-- aren't sufficient because they only work with reference to automatic translit and won't operate at all in
-- languages without any automatic translit, like Persian and Hebrew.
if data.tr[1] then
local full_code = lang:getFullCode()
track("manual-tr", full_code)
end
if not nevercalltr then
-- Try to generate a transliteration.
local text = data.alt[1] or data.term[1]
if not link_tr then
text = export.remove_links(text, true)
end
local automated_tr = lang:transliterate(text, data.sc[1])
if automated_tr then
local manual_tr = data.tr[1]
if manual_tr then
if export.remove_links(manual_tr) == export.remove_links(automated_tr) then
insert(cats, "Mục từ có chuyển tự thừa " .. lang:getFullName())
else
-- Prevents Arabic root categories from flooding the tracking categories.
if NAMESPACE ~= "Thể loại" then
insert(cats, "Mục từ có chuyển tự thủ công không thừa " .. lang:getFullName())
end
end
end
if not manual_tr or lang:overrideManualTranslit(data.sc[1]) then
data.tr[1] = automated_tr
end
end
end
end
end
-- Link to the transliteration entry for languages that require this
if data.tr[1] and link_tr and not data.tr[1]:match("%[%[(.-)%]%]") then
data.tr[1] = simple_link(
data.tr[1],
nil,
nil,
lang,
get_script("Latn"),
nil,
cats,
no_alt_ast,
srwc
)
elseif data.tr[1] and not link_tr then
-- Remove the pseudo-HTML tags added by remove_links.
data.tr[1] = data.tr[1]:gsub("</?link>", "")
end
if data.tr[1] and not umatch(data.tr[1], "[^%s%p]") then data.tr[1] = nil end
insert(output, export.format_link_annotations(data, face))
if data.pretext then
insert(output, 1, data.pretext)
end
if data.posttext then
insert(output, data.posttext)
end
local categories = cats[1] and format_categories(cats, lang, "-", nil, nil, data.sc) or ""
output = concat(output)
if show_qualifiers or data.show_qualifiers then
output = add_qualifiers_and_refs_to_term(data, output)
end
return output .. categories
end
--[==[Replaces all wikilinks with their displayed text, and removes any categories. This function can be invoked either from a template or from another module.
-- Strips links: deletes category links, the targets of piped links, and any double square brackets involved in links (other than file links, which are untouched). If `tag` is set, then any links removed will be given pseudo-HTML tags, which allow the substitution functions in [[Module:languages]] to properly subdivide the text in order to reduce the chance of substitution failures in modules which scrape pages like [[Module:zh-translit]].
-- FIXME: This is quite hacky. We probably want this to be integrated into [[Module:languages]], but we can't do that until we know that nothing is pushing pipe linked transliterations through it for languages which don't have link_tr set.
* <code><nowiki>[[page|displayed text]]</nowiki></code> → <code><nowiki>displayed text</nowiki></code>
* <code><nowiki>[[page and displayed text]]</nowiki></code> → <code><nowiki>page and displayed text</nowiki></code>
* <code><nowiki>[[Category:English lemmas|WORD]]</nowiki></code> → ''(nothing)'']==]
function export.remove_links(text, tag)
if type(text) == "table" then
text = text.args[1]
end
if not text or text == "" then
return ""
end
text = text
:gsub("%[%[", "\1")
:gsub("%]%]", "\2")
-- Parse internal links for the display text.
text = text:gsub("(\1)([^\1\2]-)(\2)",
function(c1, c2, c3)
-- Don't remove files.
for _, false_positive in ipairs({"file", "image"}) do
if c2:lower():match("^" .. false_positive .. ":") then return c1 .. c2 .. c3 end
end
-- Remove categories completely.
for _, false_positive in ipairs({"category", "cat"}) do
if c2:lower():match("^" .. false_positive .. ":") then return "" end
end
-- In piped links, remove all text before the pipe, unless it's the final character (i.e. the pipe trick), in which case just remove the pipe.
c2 = c2:match("^[^|]*|(.+)") or c2:match("([^|]+)|$") or c2
if tag then
return "<link>" .. c2 .. "</link>"
else
return c2
end
end)
text = text
:gsub("\1", "[[")
:gsub("\2", "]]")
return text
end
function export.section_link(link)
if type(link) ~= "string" then
error("The first argument to section_link was a " .. type(link) .. ", but it should be a string.")
elseif link:find("\\", nil, true) then
track("escaped", "section_link")
end
local target, section = get_fragment((link:gsub("_", " ")))
if not section then
error("No \"#\" delineating a section name")
end
return simple_link(
target,
section,
target .. " § " .. section
)
end
return export
3dq6a9yxp2zvi13deuk2plyhl97k8ll
2344295
2344294
2026-04-11T15:33:08Z
TheHighFighter2
42988
2344295
Scribunto
text/plain
local export = {}
--[=[
[[Unsupported titles]], pages with high memory usage,
extraction modules and part-of-speech names are listed
at [[Module:links/data]].
Other modules used:
[[Module:script utilities]]
[[Module:scripts]]
[[Module:languages]] and its submodules
[[Module:gender and number]]
[[Module:debug/track]]
]=]
local anchors_module = "Module:anchors"
local debug_track_module = "Module:debug/track"
local gender_and_number_module = "Module:gender and number"
local languages_module = "Module:languages"
local load_module = "Module:load"
local memoize_module = "Module:memoize"
local pages_module = "Module:pages"
local pron_qualifier_module = "Module:pron qualifier"
local scripts_module = "Module:scripts"
local script_utilities_module = "Module:script utilities"
local string_encode_entities_module = "Module:string/encode entities"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local ucfirst = require("Module:string utilities").ucfirst
local concat = table.concat
local find = string.find
local get_current_title = mw.title.getCurrentTitle
local insert = table.insert
local ipairs = ipairs
local match = string.match
local new_title = mw.title.new
local pairs = pairs
local remove = table.remove
local sub = string.sub
local toNFC = mw.ustring.toNFC
local tostring = tostring
local type = type
local unstrip = mw.text.unstrip
local NAMESPACE = get_current_title().nsText
local function anchor_encode(...)
anchor_encode = require(memoize_module)(mw.uri.anchorEncode, true)
return anchor_encode(...)
end
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function decode_uri(...)
decode_uri = require(string_utilities_module).decode_uri
return decode_uri(...)
end
-- Can't yet replace, as the [[Module:string utilities]] version no longer has automatic double-encoding prevention, which requires changes here to account for.
local function encode_entities(...)
encode_entities = require(string_encode_entities_module)
return encode_entities(...)
end
local function extend(...)
extend = require(table_module).extend
return extend(...)
end
local function find_best_script_without_lang(...)
find_best_script_without_lang = require(scripts_module).findBestScriptWithoutLang
return find_best_script_without_lang(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_genders(...)
format_genders = require(gender_and_number_module).format_genders
return format_genders(...)
end
local function format_qualifiers(...)
format_qualifiers = require(pron_qualifier_module).format_qualifiers
return format_qualifiers(...)
end
local function get_current_L2(...)
get_current_L2 = require(pages_module).get_current_L2
return get_current_L2(...)
end
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
end
local function get_script(...)
get_script = require(scripts_module).getByCode
return get_script(...)
end
local function language_anchor(...)
language_anchor = require(anchors_module).language_anchor
return language_anchor(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function request_script(...)
request_script = require(script_utilities_module).request_script
return request_script(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function tag_text(...)
tag_text = require(script_utilities_module).tag_text
return tag_text(...)
end
local function tag_translit(...)
tag_translit = require(script_utilities_module).tag_translit
return tag_translit(...)
end
local function trim(...)
trim = require(string_utilities_module).trim
return trim(...)
end
local function u(...)
u = require(string_utilities_module).char
return u(...)
end
local function ulower(...)
ulower = require(string_utilities_module).lower
return ulower(...)
end
local function umatch(...)
umatch = require(string_utilities_module).match
return umatch(...)
end
local m_headword_data
local function get_headword_data()
m_headword_data = load_data("Module:headword/data")
return m_headword_data
end
local function track(page, code)
local tracking_page = "links/" .. page
debug_track(tracking_page)
if code then
debug_track(tracking_page .. "/" .. code)
end
end
local function selective_trim(...)
-- Unconditionally trimmed charset.
local always_trim =
"\194\128-\194\159" .. -- U+0080-009F (C1 control characters)
"\194\173" .. -- U+00AD (soft hyphen)
"\226\128\170-\226\128\174" .. -- U+202A-202E (directionality formatting characters)
"\226\129\166-\226\129\169" -- U+2066-2069 (directionality formatting characters)
-- Standard trimmed charset.
local standard_trim = "%s" .. -- (default whitespace charset)
"\226\128\139-\226\128\141" .. -- U+200B-200D (zero-width spaces)
always_trim
-- If there are non-whitespace characters, trim all characters in `standard_trim`.
-- Otherwise, only trim the characters in `always_trim`.
selective_trim = function(text)
if text == "" then
return text
end
local trimmed = trim(text, standard_trim)
if trimmed ~= "" then
return trimmed
end
return trim(text, always_trim)
end
return selective_trim(...)
end
local function escape(text, str)
local rep
repeat
text, rep = text:gsub("\\\\(\\*" .. str .. ")", "\5%1")
until rep == 0
return (text:gsub("\\" .. str, "\6"))
end
local function unescape(text, str)
return (text
:gsub("\5", "\\")
:gsub("\6", str))
end
-- Remove bold, italics, soft hyphens, strip markers and HTML tags.
local function remove_formatting(str)
str = str
:gsub("('*)'''(.-'*)'''", "%1%2")
:gsub("('*)''(.-'*)''", "%1%2")
:gsub("", "")
return (unstrip(str)
:gsub("<[^<>]+>", ""))
end
--[==[Takes an input and splits on a double slash (taking account of escaping backslashes).]==]
function export.split_on_slashes(text)
if text:find("\\", nil, true) then
track("escaped", "split_on_slashes")
end
text = split(escape(text, "//"), "//", true) or {}
for i, v in ipairs(text) do
text[i] = unescape(v, "//")
if v == "" then
text[i] = false
end
end
return text
end
--[==[Takes a wikilink and outputs the link target and display text. By default, the link target will be returned as a title object, but if `allow_bad_target` is set it will be returned as a string, and no check will be performed as to whether it is a valid link target.]==]
function export.get_wikilink_parts(text, allow_bad_target)
-- TODO: replace `allow_bad_target` with `allow_unsupported`, with support for links to unsupported titles, including escape sequences.
if ( -- Filters out anything but "[[...]]" with no intermediate "[[" or "]]".
not match(text, "^()%[%[") or -- Faster than sub(text, 1, 2) ~= "[[".
find(text, "[[", 3, true) or
find(text, "]]", 3, true) ~= #text - 1
) then
return nil, nil
end
local pipe, title, display = find(text, "|", 3, true)
if pipe then
title, display = sub(text, 3, pipe - 1), sub(text, pipe + 1, -3)
else
title = sub(text, 3, -3)
display = title
end
if allow_bad_target then
return title, display
end
title = new_title(title)
-- No title object means the target is invalid.
if title == nil then
return nil, nil
-- If the link target starts with "#" then mw.title.new returns a broken
-- title object, so grab the current title and give it the correct fragment.
elseif title.prefixedText == "" then
local fragment = title.fragment
if fragment == "" then -- [[#]] isn't valid
return nil, nil
end
title = get_current_title()
title.fragment = fragment
end
return title, display
end
-- Does the work of export.get_fragment, but can be called directly to avoid unnecessary checks for embedded links.
local function get_fragment(text)
text = escape(text, "#")
-- Replace numeric character references with the corresponding character (' → '),
-- as they contain #, which causes the numeric character reference to be
-- misparsed (wa'a → wa'a → pagename wa&, fragment 39;a).
text = decode_entities(text)
local target, fragment = text:match("^(.-)#(.+)$")
target = target or text
target = unescape(target, "#")
fragment = fragment and unescape(fragment, "#")
return target, fragment
end
--[==[Takes a link target and outputs the actual target and the fragment (if any).]==]
function export.get_fragment(text)
if text:find("\\", nil, true) then
track("escaped", "get_fragment")
end
-- If there are no embedded links, process input.
local open = find(text, "[[", nil, true)
if not open then
return get_fragment(text)
end
local close = find(text, "]]", open + 2, true)
if not close then
return get_fragment(text)
-- If there is one, but it's redundant (i.e. encloses everything with no pipe), remove and process.
elseif open == 1 and close == #text - 1 and not find(text, "|", 3, true) then
return get_fragment(sub(text, 3, -3))
end
-- Otherwise, return the input.
return text
end
--[==[
Given a link target as passed to `full_link()`, get the actual page that the target refers to. This removes
bold, italics, strip markets and HTML; calls `makeEntryName()` for the language in question; converts targets
beginning with `*` to the Reconstruction namespace; and converts appendix-constructed languages to the Appendix
namespace. Returns up to three values:
# the actual page to link to, or {nil} to not link to anything;
# how the target should be displayed as, if the user didn't explicitly specify any display text; generally the
same as the original target, but minus any anti-asterisk !!;
# the value `true` if the target had a backslash-escaped * in it (FIXME: explain this more clearly).
]==]
function export.get_link_page_with_auto_display(target, lang, sc, plain)
local orig_target = target
if not target then
return nil
elseif target:find("\\", nil, true) then
track("escaped", "get_link_page")
end
target = remove_formatting(target)
if target:sub(1, 1) == ":" then
track("initial colon")
-- FIXME, the auto_display (second return value) should probably remove the colon
return target:sub(2), orig_target
end
local prefix = target:match("^(.-):")
-- Convert any escaped colons
target = target:gsub("\\:", ":")
if prefix then
-- If this is an a link to another namespace or an interwiki link, ensure there's an initial colon and then
-- return what we have (so that it works as a conventional link, and doesn't do anything weird like add the term
-- to a category.)
prefix = ulower(trim(prefix))
if prefix ~= "" and (
load_data("Module:data/namespaces")[prefix] or
load_data("Module:data/interwikis")[prefix]
) then
return target, orig_target
end
end
-- Check if the term is reconstructed and remove any asterisk. Also check for anti-asterisk (!!).
-- Otherwise, handle the escapes.
local reconstructed, escaped, anti_asterisk
if not plain then
target, reconstructed = target:gsub("^%*(.)", "%1")
if reconstructed == 0 then
target, anti_asterisk = target:gsub("^!!(.)", "%1")
if anti_asterisk == 1 then
-- Remove !! from original. FIXME! We do it this way because the call to remove_formatting() above
-- may cause non-initial !! to be interpreted as anti-asterisks. We should surely move the
-- remove_formatting() call later.
orig_target = orig_target:gsub("^!!", "")
end
end
end
target, escaped = target:gsub("^(\\-)\\%*", "%1*")
if not (sc and sc:getCode() ~= "None") then
sc = lang:findBestScript(target)
end
-- Remove carets if they are used to capitalize parts of transliterations (unless they have been escaped).
if (not sc:hasCapitalization()) and sc:isTransliterated() and target:match("%^") then
target = escape(target, "^")
:gsub("%^", "")
target = unescape(target, "^")
end
-- Get the entry name for the language.
target = lang:makeEntryName(target, sc, reconstructed == 1 or lang:hasType("appendix-constructed"))
-- If the link contains unexpanded template parameters, then don't create a link.
if target:match("{{{.-}}}") then
-- FIXME: Should we return the original target as the default display value (second return value)?
return nil
end
-- Link to appendix for reconstructed terms and terms in appendix-only languages. Plain links interpret *
-- literally, however.
if reconstructed == 1 then
if lang:getFullCode() == "und" then
-- Return the original target as default display value. If we don't do this, we wrongly get
-- [Term?] displayed instead.
return nil, orig_target
end
target = "Từ tái tạo:" .. ucfirst(lang:getFullName()) .. "/" .. target
-- Reconstructed languages and substrates require an initial *.
elseif anti_asterisk ~= 1 and (lang:hasType("reconstructed") or lang:getFamilyCode() == "qfa-sub") then
error(("The specified language %s is unattested, while the term '%s' does not begin with '*' to indicate that it is reconstructed."):
format(lang:getCanonicalName(), orig_target))
elseif lang:hasType("appendix-constructed") then
target = "Phụ lục:" .. ucfirst(lang:getFullName()) .. "/" .. target
else
target = target
end
return target, orig_target, escaped > 0
end
function export.get_link_page(target, lang, sc, plain)
local target, auto_display, escaped = export.get_link_page_with_auto_display(target, lang, sc, plain)
return target, escaped
end
-- Make a link from a given link's parts
local function make_link(link, lang, sc, id, isolated, cats, no_alt_ast, plain)
-- Convert percent encoding to plaintext.
link.target = link.target and decode_uri(link.target, "PATH")
link.fragment = link.fragment and decode_uri(link.fragment, "PATH")
-- Find fragments (if one isn't already set).
-- Prevents {{l|en|word#Etymology 2|word}} from linking to [[word#Etymology 2#English]].
-- # can be escaped as \#.
if link.target and link.fragment == nil then
link.target, link.fragment = get_fragment(link.target)
end
-- Process the target
local auto_display, escaped
link.target, auto_display, escaped = export.get_link_page_with_auto_display(link.target, lang, sc, plain)
-- Create a default display form.
-- If the target is "" then it's a link like [[#English]], which refers to the current page.
if auto_display == "" then
auto_display = (m_headword_data or get_headword_data()).pagename
end
-- If the display is the target and the reconstruction * has been escaped, remove the escaping backslash.
if escaped then
auto_display = auto_display:gsub("\\([^\\]*%*)", "%1", 1)
end
-- Process the display form.
if link.display then
local orig_display = link.display
link.display = lang:makeDisplayText(link.display, sc, true)
if cats then
auto_display = lang:makeDisplayText(auto_display, sc)
-- If the alt text is the same as what would have been automatically generated, then the alt parameter is redundant (e.g. {{l|en|foo|foo}}, {{l|en|w:foo|foo}}, but not {{l|en|w:foo|w:foo}}).
-- If they're different, but the alt text could have been entered as the term parameter without it affecting the target page, then the target parameter is redundant (e.g. {{l|ru|фу|фу́}}).
-- If `no_alt_ast` is true, use pcall to catch the error which will be thrown if this is a reconstructed lang and the alt text doesn't have *.
if link.display == auto_display then
insert(cats, "Liên kết mục từ có tham số alt thừa " .. lang:getFullName())
else
local ok, check
if no_alt_ast then
ok, check = pcall(export.get_link_page, orig_display, lang, sc, plain)
else
ok = true
check = export.get_link_page(orig_display, lang, sc, plain)
end
if ok and link.target == check then
insert(cats, "Liên kết mục từ có tham số mục tiêu thừa " .. lang:getFullName())
end
end
end
else
link.display = lang:makeDisplayText(auto_display, sc)
end
if not link.target then
return link.display
end
-- If the target is the same as the current page, there is no sense id
-- and either the language code is "und" or the current L2 is the current
-- language then return a "self-link" like the software does.
if link.target == get_current_title().prefixedText then
local fragment, current_L2 = link.fragment, get_current_L2()
if (
fragment and fragment == current_L2 or
not (id or fragment) and (lang:getFullCode() == "und" or ucfirst(lang:getFullName()) == current_L2)
) then
return tostring(mw.html.create("strong")
:addClass("selflink")
:wikitext(link.display))
end
end
-- Add fragment. Do not add a section link to "Undetermined", as such sections do not exist and are invalid.
-- TabbedLanguages handles links without a section by linking to the "last visited" section, but adding
-- "Undetermined" would break that feature. For localized prefixes that make syntax error, please use the
-- format: ["xyz"] = true.
local prefix = link.target:match("^:*([^:]+):")
prefix = prefix and ulower(prefix)
if prefix ~= "category" and not (prefix and load_data("Module:data/interwikis")[prefix]) then
if (link.fragment or link.target:sub(-1) == "#") and not plain then
track("fragment", lang:getFullCode())
if cats then
insert(cats, "Liên kết có phân mảnh thủ công " .. lang:getFullName())
end
end
if not link.fragment then
if id then
link.fragment = lang:getFullCode() == "und" and anchor_encode(id) or language_anchor(lang, id)
elseif lang:getFullCode() ~= "und" and not (link.target:match("^Phụ lục:") or link.target:match("^Từ tái tạo:")) then
link.fragment = anchor_encode(ucfirst(lang:getFullName()))
end
end
end
-- Put inward-facing square brackets around a link to isolated spacing character(s).
if isolated and #link.display > 0 and not umatch(decode_entities(link.display), "%S") then
link.display = "]" .. link.display .. "["
end
link.target = link.target:gsub("^(:?)(.*)", function(m1, m2)
return m1 .. encode_entities(m2, "#%&+/:<=>@[\\]_{|}")
end)
link.fragment = link.fragment and encode_entities(remove_formatting(link.fragment), "#%&+/:<=>@[\\]_{|}")
return "[[" .. link.target:gsub("^[^:]", ":%0") .. (link.fragment and "#" .. link.fragment or "") .. "|" .. link.display .. "]]"
end
-- Split a link into its parts
local function parse_link(linktext)
local link = {target = linktext}
local target = link.target
link.target, link.display = target:match("^(..-)|(.+)$")
if not link.target then
link.target = target
link.display = target
end
-- There's no point in processing these, as they aren't real links.
local target_lower = link.target:lower()
for _, false_positive in ipairs({"category", "cat", "file", "image"}) do
if target_lower:match("^" .. false_positive .. ":") then
return nil
end
end
link.display = decode_entities(link.display)
link.target, link.fragment = get_fragment(link.target)
-- So that make_link does not look for a fragment again.
if not link.fragment then
link.fragment = false
end
return link
end
local function check_params_ignored_when_embedded(alt, lang, id, cats)
if alt then
track("alt-ignored")
if cats then
insert(cats, "Liên kết mục từ có tham số alt bỏ qua " .. lang:getFullName())
end
end
if id then
track("id-ignored")
if cats then
insert(cats, "Liên kết mục từ có tham số id bỏ qua " .. lang:getFullName())
end
end
end
-- Find embedded links and ensure they link to the correct section.
local function process_embedded_links(text, alt, lang, sc, id, cats, no_alt_ast, plain)
-- Process the non-linked text.
text = lang:makeDisplayText(text, sc, true)
-- If the text begins with * and another character, then act as if each link begins with *. However, don't do this if the * is contained within a link at the start. E.g. `|*[[foo]]` would set all_reconstructed to true, while `|[[*foo]]` would not.
local all_reconstructed = false
if not plain then
-- anchor_encode removes links etc.
if anchor_encode(text):sub(1, 1) == "*" then
all_reconstructed = true
end
-- Otherwise, handle any escapes.
text = text:gsub("^(\\-)\\%*", "%1*")
end
check_params_ignored_when_embedded(alt, lang, id, cats)
local function process_link(space1, linktext, space2)
local capture = "[[" .. linktext .. "]]"
local link = parse_link(linktext)
-- Return unprocessed false positives untouched (e.g. categories).
if not link then
return capture
end
if all_reconstructed then
if link.target:find("^!!") then
-- Check for anti-asterisk !! at the beginning of a target, indicating that a reconstructed term
-- wants a part of the term to link to a non-reconstructed term, e.g. Old English
-- {{ang-noun|m|head=*[[!!Crist|Cristes]] [[!!mæsseǣfen]]}}.
link.target = link.target:sub(3)
-- Also remove !! from the display, which may have been copied from the target (as in mæsseǣfen in
-- the example above).
link.display = link.display:gsub("^!!", "")
elseif not link.target:match("^%*") then
link.target = "*" .. link.target
end
end
linktext = make_link(link, lang, sc, id, false, nil, no_alt_ast, plain)
:gsub("^%[%[", "\3")
:gsub("%]%]$", "\4")
return space1 .. linktext .. space2
end
-- Use chars 1 and 2 as temporary substitutions, so that we can use charsets. These are converted to chars 3 and 4 by process_link, which means we can convert any remaining chars 1 and 2 back to square brackets (i.e. those not part of a link).
text = text
:gsub("%[%[", "\1")
:gsub("%]%]", "\2")
-- If the script uses ^ to capitalize transliterations, make sure that any carets preceding links are on the inside, so that they get processed with the following text.
if (
text:find("^", nil, true) and
not sc:hasCapitalization() and
sc:isTransliterated()
) then
text = escape(text, "^")
:gsub("%^\1", "\1%^")
text = unescape(text, "^")
end
text = text:gsub("\1(%s*)([^\1\2]-)(%s*)\2", process_link)
-- Remove the extra * at the beginning of a language link if it's immediately followed by a link whose display begins with * too.
if all_reconstructed then
text = text:gsub("^%*\3([^|\1-\4]+)|%*", "\3%1|*")
end
return (text
:gsub("[\1\3]", "[[")
:gsub("[\2\4]", "]]")
)
end
local function simple_link(term, fragment, alt, lang, sc, id, cats, no_alt_ast, srwc)
local plain
if lang == nil then
lang, plain = get_lang("und"), true
end
-- Get the link target and display text. If the term is the empty string, treat the input as a link to the current page.
if term == "" then
term = get_current_title().prefixedText
elseif term then
local new_term, new_alt = export.get_wikilink_parts(term, true)
if new_term then
check_params_ignored_when_embedded(alt, lang, id, cats)
-- [[|foo]] links are treated as plaintext "[[|foo]]".
-- FIXME: Pipes should be handled via a proper escape sequence, as they can occur in unsupported titles.
if new_term == "" then
term, alt = nil, term
else
local title = new_title(new_term)
if title then
local ns = title.namespace
-- File: and Category: links should be returned as-is.
if ns == 6 or ns == 14 then
return term
end
end
term, alt = new_term, new_alt
if cats then
if not (srwc and srwc(term, alt)) then
insert(cats, "Liên kết mục từ có liên kết wiki thừa " .. lang:getFullName())
end
end
end
end
end
if alt then
alt = selective_trim(alt)
if alt == "" then
alt = nil
end
end
-- If there's nothing to process, return nil.
if not (term or alt) then
return nil
end
-- If there is no script, get one.
if not sc then
sc = lang:findBestScript(alt or term)
end
-- Embedded wikilinks need to be processed individually.
if term then
local open = find(term, "[[", nil, true)
if open and find(term, "]]", open + 2, true) then
return process_embedded_links(term, alt, lang, sc, id, cats, no_alt_ast, plain)
end
term = selective_trim(term)
end
-- If not, make a link using the parameters.
return make_link({
target = term,
display = alt,
fragment = fragment
}, lang, sc, id, true, cats, no_alt_ast, plain)
end
--[==[Creates a basic link to the given term. It links to the language section (such as <code>==English==</code>), but it does not add language and script wrappers, so any code that uses this function should call the <code class="n">[[Module:script utilities#tag_text|tag_text]]</code> from [[Module:script utilities]] to add such wrappers itself at some point.
The first argument, <code class="n">data</code>, may contain the following items, a subset of the items used in the <code class="n">data</code> argument of <code class="n">full_link</code>. If any other items are included, they are ignored.
{ {
term = entry_to_link_to,
alt = link_text_or_displayed_text,
lang = language_object,
id = sense_id,
} }
; <code class="n">term</code>
: Text to turn into a link. This is generally the name of a page. The text can contain wikilinks already embedded in it. These are processed individually just like a single link would be. The <code class="n">alt</code> argument is ignored in this case.
; <code class="n">alt</code> (''optional'')
: The alternative display for the link, if different from the linked page. If this is {{code|lua|nil}}, the <code class="n">text</code> argument is used instead (much like regular wikilinks). If <code class="n">text</code> contains wikilinks in it, this argument is ignored and has no effect. (Links in which the alt is ignored are tracked with the tracking template {{whatlinkshere|tracking=links/alt-ignored}}.)
; <code class="n">lang</code>
: The [[Module:languages#Language objects|language object]] for the term being linked. If this argument is defined, the function will determine the language's canonical name (see [[Template:language data documentation]]), and point the link or links in the <code class="n">term</code> to the language's section of an entry, or to a language-specific senseid if the <code class="n">id</code> argument is defined.
; <code class="n">id</code> (''optional'')
: Sense id string. If this argument is defined, the link will point to a language-specific sense id ({{ll|en|identifier|id=HTML}}) created by the template {{temp|senseid}}. A sense id consists of the language's canonical name, a hyphen (<code>-</code>), and the string that was supplied as the <code class="n">id</code> argument. This is useful when a term has more than one sense in a language. If the <code class="n">term</code> argument contains wikilinks, this argument is ignored. (Links in which the sense id is ignored are tracked with the tracking template {{whatlinkshere|tracking=links/id-ignored}}.)
The second argument is as follows:
; <code class="n">allow_self_link</code>
: If {{code|lua|true}}, the function will also generate links to the current page. The default ({{code|lua|false}}) will not generate a link but generate a bolded "self link" instead.
The following special options are processed for each link (both simple text and with embedded wikilinks):
* The target page name will be processed to generate the correct entry name. This is done by the [[Module:languages#makeEntryName|makeEntryName]] function in [[Module:languages]], using the <code class="n">entry_name</code> replacements in the language's data file (see [[Template:language data documentation]] for more information). This function is generally used to automatically strip dictionary-only diacritics that are not part of the normal written form of a language.
* If the text starts with <code class="n">*</code>, then the term is considered a reconstructed term, and a link to the Reconstruction: namespace will be created. If the text contains embedded wikilinks, then <code class="n">*</code> is automatically applied to each one individually, while preserving the displayed form of each link as it was given. This allows linking to phrases containing multiple reconstructed terms, while only showing the * once at the beginning.
* If the text starts with <code class="n">:</code>, then the link is treated as "raw" and the above steps are skipped. This can be used in rare cases where the page name begins with <code class="n">*</code> or if diacritics should not be stripped. For example:
** {{temp|l|en|*nix}} links to the nonexistent page [[Reconstruction:English/nix]] (<code class="n">*</code> is interpreted as a reconstruction), but {{temp|l|en|:*nix}} links to [[*nix]].
** {{temp|l|sl|Franche-Comté}} links to the nonexistent page [[Franche-Comte]] (<code>é</code> is converted to <code>e</code> by <code class="n">makeEntryName</code>), but {{temp|l|sl|:Franche-Comté}} links to [[Franche-Comté]].]==]
function export.language_link(data)
if type(data) ~= "table" then
error("The first argument to the function language_link must be a table. See Module:links/documentation for more information.")
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then
track("escaped", "language_link")
end
-- Categorize links to "und".
local lang, cats = data.lang, data.cats
if cats and lang:getCode() == "und" then
insert(cats, "Liên kết ngôn ngữ không xác định")
end
return simple_link(
data.term,
data.fragment,
data.alt,
lang,
data.sc,
data.id,
cats,
data.no_alt_ast,
data.suppress_redundant_wikilink_cat
)
end
function export.plain_link(data)
if type(data) ~= "table" then
error("The first argument to the function plain_link must be a table. See Module:links/documentation for more information.")
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then
track("escaped", "plain_link")
end
return simple_link(
data.term,
data.fragment,
data.alt,
nil,
data.sc,
data.id,
data.cats,
data.no_alt_ast,
data.suppress_redundant_wikilink_cat
)
end
--[==[Replace any links with links to the correct section, but don't link the whole text if no embedded links are found. Returns the display text form.]==]
function export.embedded_language_links(data)
if type(data) ~= "table" then
error("The first argument to the function embedded_language_links must be a table. See Module:links/documentation for more information.")
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then
track("escaped", "embedded_language_links")
end
local term, lang, sc = data.term, data.lang, data.sc
-- If we don't have a script, get one.
if not sc then
sc = lang:findBestScript(term)
end
-- Do we have embedded wikilinks? If so, they need to be processed individually.
local open = find(term, "[[", nil, true)
if open and find(term, "]]", open + 2, true) then
return process_embedded_links(term, data.alt, lang, sc, data.id, data.cats, data.no_alt_ast)
end
-- If not, return the display text.
term = selective_trim(term)
-- FIXME: Double-escape any percent-signs, because we don't want to treat non-linked text as having percent-encoded characters. This is a hack: percent-decoding should come out of [[Module:languages]] and only dealt with in this module, as it's specific to links.
term = term:gsub("%%", "%%25")
return lang:makeDisplayText(term, sc, true)
end
function export.mark(text, item_type, face, lang)
local tag = { "", "" }
if item_type == "gloss" then
tag = { '<span class="mention-gloss-double-quote">“</span><span class="mention-gloss">',
'</span><span class="mention-gloss-double-quote">”</span>' }
if type(text) == "string" and text:match("^''[^'].*''$") then
-- Temporary tracking for mention glosses that are entirely italicized or bolded, which is probably
-- wrong. (Note that this will also find bolded mention glosses since they use triple apostrophes.)
track("italicized-mention-gloss", lang and lang:getFullCode() or nil)
end
elseif item_type == "tr" then
if face == "term" then
tag = { '<span lang="' .. lang:getFullCode() .. '" class="tr mention-tr Latn">',
'</span>' }
else
tag = { '<span lang="' .. lang:getFullCode() .. '" class="tr Latn">', '</span>' }
end
elseif item_type == "ts" then
-- \226\129\160 = word joiner (zero-width non-breaking space) U+2060
tag = { '<span class="ts mention-ts Latn">/\226\129\160', '\226\129\160/</span>' }
elseif item_type == "pos" then
tag = { '<span class="ann-pos">', '</span>' }
elseif item_type == "non-gloss" then
tag = { '<span class="ann-non-gloss">', '</span>' }
elseif item_type == "annotations" then
tag = { '<span class="mention-gloss-paren annotation-paren">(</span>',
'<span class="mention-gloss-paren annotation-paren">)</span>' }
end
if type(text) == "string" then
return tag[1] .. text .. tag[2]
else
return ""
end
end
local pos_tags
--[==[Formats the annotations that are displayed with a link created by {{code|lua|full_link}}. Annotations are the extra bits of information that are displayed following the linked term, and include things such as gender, transliteration, gloss and so on.
* The first argument is a table possessing some or all of the following keys:
*:; <code class="n">genders</code>
*:: Table containing a list of gender specifications in the style of [[Module:gender and number]].
*:; <code class="n">tr</code>
*:: Transliteration.
*:; <code class="n">gloss</code>
*:: Gloss that translates the term in the link, or gives some other descriptive information.
*:; <code class="n">pos</code>
*:: Part of speech of the linked term. If the given argument matches one of the aliases in `pos_aliases` in [[Module:headword/data]], or consists of a part of speech or alias followed by `f` (for a non-lemma form), expand it appropriately. Otherwise, just show the given text as it is.
*:; <code class="n">ng</code>
*:: Arbitrary non-gloss descriptive text for the link. This should be used in preference to putting descriptive text in `gloss` or `pos`.
*:; <code class="n">lit</code>
*:: Literal meaning of the term, if the usual meaning is figurative or idiomatic.
*:Any of the above values can be omitted from the <code class="n">info</code> argument. If a completely empty table is given (with no annotations at all), then an empty string is returned.
* The second argument is a string. Valid values are listed in [[Module:script utilities/data]] "data.translit" table.]==]
function export.format_link_annotations(data, face)
local output = {}
-- Interwiki link
if data.interwiki then
insert(output, data.interwiki)
end
-- Genders
if type(data.genders) ~= "table" then
data.genders = { data.genders }
end
if data.genders and #data.genders > 0 then
local genders, gender_cats = format_genders(data.genders, data.lang)
insert(output, " " .. genders)
if gender_cats then
local cats = data.cats
if cats then
extend(cats, gender_cats)
end
end
end
local annotations = {}
-- Transliteration and transcription
if data.tr and data.tr[1] or data.ts and data.ts[1] then
local kind
if face == "term" then
kind = face
else
kind = "default"
end
if data.tr[1] and data.ts[1] then
insert(annotations, tag_translit(data.tr[1], data.lang, kind) .. " " .. export.mark(data.ts[1], "ts"))
elseif data.ts[1] then
insert(annotations, export.mark(data.ts[1], "ts"))
else
insert(annotations, tag_translit(data.tr[1], data.lang, kind))
end
end
-- Gloss/translation
if data.gloss then
insert(annotations, export.mark(data.gloss, "gloss"))
end
-- Part of speech
if data.pos then
-- debug category for pos= containing transcriptions
if data.pos:match("/[^><]-/") then
data.pos = data.pos .. "[[Category:links likely containing transcriptions in pos]]"
end
-- Canonicalize part of speech aliases as well as non-lemma aliases like 'nf' or 'nounf' for "noun form".
pos_tags = pos_tags or (m_headword_data or get_headword_data()).pos_aliases
local pos = pos_tags[data.pos]
if not pos and data.pos:find("f$") then
local pos_form = data.pos:sub(1, -2)
-- We only expand something ending in 'f' if the result is a recognized non-lemma POS.
pos_form = (pos_tags[pos_form] or pos_form) .. " form"
if (m_headword_data or get_headword_data()).nonlemmas[pos_form .. "s"] then
pos = pos_form
end
end
insert(annotations, export.mark(pos or data.pos, "pos"))
end
-- Non-gloss text
if data.ng then
insert(annotations, export.mark(data.ng, "non-gloss"))
end
-- Literal/sum-of-parts meaning
if data.lit then
insert(annotations, "nghĩa đen " .. export.mark(data.lit, "gloss"))
end
-- Provide a hook to insert additional annotations such as nested inflections.
if data.postprocess_annotations then
data.postprocess_annotations {
data = data,
annotations = annotations
}
end
if #annotations > 0 then
insert(output, " " .. export.mark(concat(annotations, ", "), "annotations"))
end
return concat(output)
end
-- Encode certain characters to avoid various delimiter-related issues at various stages. We need to encode < and >
-- because they end up forming part of CSS class names inside of <span ...> and will interfere with finding the end
-- of the HTML tag. I first tried converting them to URL encoding, i.e. %3C and %3E; they then appear in the URL as
-- %253C and %253E, which get mapped back to %3C and %3E when passed to [[Module:accel]]. But mapping them to <
-- and > somehow works magically without any further work; they appear in the URL as < and >, and get passed to
-- [[Module:accel]] as < and >. I have no idea who along the chain of calls is doing the encoding and decoding. If
-- someone knows, please modify this comment appropriately!
local accel_char_map
local function get_accel_char_map()
accel_char_map = {
["%"] = ".",
[" "] = "_",
["_"] = u(0xFFF0),
["<"] = "<",
[">"] = ">",
}
return accel_char_map
end
local function encode_accel_param_chars(param)
return (param:gsub("[% <>_]", accel_char_map or get_accel_char_map()))
end
local function encode_accel_param(prefix, param)
if not param then
return ""
end
if type(param) == "table" then
local filled_params = {}
-- There may be gaps in the sequence, especially for translit params.
local maxindex = 0
for k in pairs(param) do
if type(k) == "number" and k > maxindex then
maxindex = k
end
end
for i = 1, maxindex do
filled_params[i] = param[i] or ""
end
-- [[Module:accel]] splits these up again.
param = concat(filled_params, "*~!")
end
-- This is decoded again by [[WT:ACCEL]].
return prefix .. encode_accel_param_chars(param)
end
local function insert_if_not_blank(list, item)
if item == "" then
return
end
insert(list, item)
end
local function get_class(lang, tr, accel, nowrap)
if not accel and not nowrap then
return ""
end
local classes = {}
if accel then
insert(classes, "form-of lang-" .. lang:getFullCode())
local form = accel.form
if form then
insert(classes, encode_accel_param_chars(form) .. "-form-of")
end
insert_if_not_blank(classes, encode_accel_param("gender-", accel.gender))
insert_if_not_blank(classes, encode_accel_param("pos-", accel.pos))
insert_if_not_blank(classes, encode_accel_param("transliteration-", accel.translit or (tr ~= "-" and tr or nil)))
insert_if_not_blank(classes, encode_accel_param("target-", accel.target))
insert_if_not_blank(classes, encode_accel_param("origin-", accel.lemma))
insert_if_not_blank(classes, encode_accel_param("origin_transliteration-", accel.lemma_translit))
if accel.no_store then
insert(classes, "form-of-nostore")
end
end
if nowrap then
insert(classes, nowrap)
end
return concat(classes, " ")
end
-- Add any left or right regular or accent qualifiers, labels or references to a formatted term. `data` is the object
-- specifying the term, which should optionally contain:
-- * a language object in `lang`; required if any accent qualifiers or labels are given;
-- * left regular qualifiers in `q` (an array of strings or a single string); an empty array or blank string will be
-- ignored;
-- * right regular qualifiers in `qq` (an array of strings or a single string); an empty array or blank string will be
-- ignored;
-- * left accent qualifiers in `a` (an array of strings); an empty array will be ignored;
-- * right accent qualifiers in `aa` (an array of strings); an empty array will be ignored;
-- * left labels in `l` (an array of strings); an empty array will be ignored;
-- * right labels in `ll` (an array of strings); an empty array will be ignored;
-- * references in `refs`, an array either of strings (formatted reference text) or objects containing fields `text`
-- (formatted reference text) and optionally `name` and/or `group`.
-- `formatted` is the formatted version of the term itself.
local function add_qualifiers_and_refs_to_term(data, formatted)
local q = data.q
if type(q) == "string" then
q = {q}
end
local qq = data.qq
if type(qq) == "string" then
qq = {qq}
end
if q and q[1] or qq and qq[1] or data.a and data.a[1] or data.aa and data.aa[1] or data.l and data.l[1] or
data.ll and data.ll[1] or data.refs and data.refs[1] then
formatted = format_qualifiers{
lang = data.lang,
text = formatted,
q = q,
qq = qq,
a = data.a,
aa = data.aa,
l = data.l,
ll = data.ll,
refs = data.refs,
}
end
return formatted
end
--[==[
Creates a full link, with annotations (see `[[#format_link_annotations|format_link_annotations]]`), in the style of {{tl|l}} or {{tl|m}}.
The first argument, `data`, must be a table. It contains the various elements that can be supplied as parameters to {{tl|l}} or {{tl|m}}:
{ {
term = entry_to_link_to,
alt = link_text_or_displayed_text,
lang = language_object,
sc = script_object,
track_sc = boolean,
no_nonstandard_sc_cat = boolean,
fragment = link_fragment,
id = sense_id,
genders = { "gender1", "gender2", ... },
tr = transliteration,
respect_link_tr = boolean,
ts = transcription,
gloss = gloss,
pos = part_of_speech_tag,
ng = non-gloss text,
lit = literal_translation,
no_alt_ast = boolean,
accel = {accelerated_creation_tags},
interwiki = interwiki,
pretext = "text_at_beginning" or nil,
posttext = "text_at_end" or nil,
q = { "left_qualifier1", "left_qualifier2", ...} or "left_qualifier",
qq = { "right_qualifier1", "right_qualifier2", ...} or "right_qualifier",
l = { "left_label1", "left_label2", ...},
ll = { "right_label1", "right_label2", ...},
a = { "left_accent_qualifier1", "left_accent_qualifier2", ...},
aa = { "right_accent_qualifier1", "right_accent_qualifier2", ...},
refs = { "formatted_ref1", "formatted_ref2", ...} or { {text = "text", name = "name", group = "group"}, ... },
show_qualifiers = boolean,
} }
Any one of the items in the `data` table may be {nil}, but an error will be shown if neither `term` nor `alt` nor `tr`
is present. Thus, calling {full_link{ term = term, lang = lang, sc = sc }}, where `term` is the page to link to (which
may have diacritics that will be stripped and/or embedded bracketed links) and `lang` is a
[[Module:languages#Language objects|language object]] from [[Module:languages]], will give a plain link similar to the
one produced by the template {{tl|l}}, and calling {full_link( { term = term, lang = lang, sc = sc }, "term" )} will
give a link similar to the one produced by the template {{tl|m}}.
The function will:
* Try to determine the script, based on the characters found in the `term` or `alt` argument, if the script was not
given. If a script is given and `track_sc` is {true}, it will check whether the input script is the same as the one
which would have been automatically generated and add the category [[:Category:LANG terms with redundant script codes]]
if yes, or [[:Category:LANG terms with non-redundant manual script codes]] if no. This should be used when the input
script object is directly determined by a template's `sc` parameter.
* Call `[[#language_link|language_link]]` on the `term` or `alt` forms, to remove diacritics in the page name, process
any embedded wikilinks and create links to Reconstruction or Appendix pages when necessary.
* Call `[[Module:script utilities#tag_text]]` to add the appropriate language and script tags to the term and
italicize terms written in the Latin script if necessary. Accelerated creation tags, as used by [[WT:ACCEL]], are
included.
* Generate a transliteration, based on the `alt` or `term` arguments, if the script is not Latin, no transliteration was
provided in `tr` and the combination of the term's language and script support automatic transliteration. The
transliteration itself will be linked if both `.respect_link_tr` is specified and the language of the term has the
`link_tr` property set for the script of the term; but not otherwise.
* Add the annotations (transliteration, gender, gloss, etc.) after the link.
* If `no_alt_ast` is specified, then the `alt` text does not need to contain an asterisk if the language is
reconstructed. This should only be used by modules which really need to allow links to reconstructions that don't
display asterisks (e.g. number boxes).
* If `pretext` or `posttext` is specified, this is text to (respectively) prepend or append to the output, directly
before processing qualifiers, labels and references. This can be used to add arbitrary extra text inside of the
qualifiers, labels and references.
* If `show_qualifiers` is specified or the `show_qualifiers` argument is given, then left and right qualifiers, accent
qualifiers, labels and references will be displayed, otherwise they will be ignored. (This is because a fair amount of
code stores qualifiers, labels and/or references in these fields and displays them itself, rather than expecting
{full_link()} to display them.)]==]
function export.full_link(data, face, allow_self_link, show_qualifiers)
if type(data) ~= "table" then
error("The first argument to the function full_link must be a table. "
.. "See Module:links/documentation for more information.")
elseif data.term and data.term:find("\\", nil, true) or data.alt and data.alt:find("\\", nil, true) then
track("escaped", "full_link")
end
-- Prevent data from being destructively modified.
local data = shallow_copy(data)
-- FIXME: this shouldn't be added to `data`, as that means the input table needs to be cloned.
data.cats = {}
-- Categorize links to "und".
local lang, cats = data.lang, data.cats
if cats and lang:getCode() == "und" then
insert(cats, "Liên kết ngôn ngữ không xác định")
end
local terms = {true}
-- Generate multiple forms if applicable.
for _, param in ipairs{"term", "alt"} do
if type(data[param]) == "string" and data[param]:find("//", nil, true) then
data[param] = export.split_on_slashes(data[param])
elseif type(data[param]) == "string" and not (type(data.term) == "string" and data.term:find("//", nil, true)) then
if not data.no_generate_forms then
data[param] = lang:generateForms(data[param])
else
data[param] = {data[param]}
end
else
data[param] = {}
end
end
for _, param in ipairs{"sc", "tr", "ts"} do
data[param] = {data[param]}
end
for _, param in ipairs{"term", "alt", "sc", "tr", "ts"} do
for i in pairs(data[param]) do
terms[i] = true
end
end
-- Create the link
local output = {}
local id, no_alt_ast, srwc, accel, nevercalltr = data.id, data.no_alt_ast, data.suppress_redundant_wikilink_cat,
data.accel, data.never_call_transliteration_module
local link_tr = data.respect_link_tr and lang:link_tr(data.sc[1])
for i in ipairs(terms) do
local link
-- Is there any text to show?
if (data.term[i] or data.alt[i]) then
-- Try to detect the script if it was not provided
local display_term = data.alt[i] or data.term[i]
local best = lang:findBestScript(display_term)
-- no_nonstandard_sc_cat is intended for use in [[Module:interproject]]
if (
not data.no_nonstandard_sc_cat and
best:getCode() == "None" and
find_best_script_without_lang(display_term):getCode() ~= "None"
) then
insert(cats, "Mục từ có chữ viết không chuẩn " .. lang:getFullName())
end
if not data.sc[i] then
data.sc[i] = best
-- Track uses of sc parameter.
elseif data.track_sc then
if data.sc[i]:getCode() == best:getCode() then
insert(cats, "Mục từ có mã chữ viết thừa " .. lang:getFullName())
else
insert(cats, "Mục từ có mã chữ viết thủ công không thừa " .. lang:getFullName())
end
end
-- If using a discouraged character sequence, add to maintenance category
if data.sc[i]:hasNormalizationFixes() == true then
if (data.term[i] and data.sc[i]:fixDiscouragedSequences(toNFC(data.term[i])) ~= toNFC(data.term[i])) or (data.alt[i] and data.sc[i]:fixDiscouragedSequences(toNFC(data.alt[i])) ~= toNFC(data.alt[i])) then
insert(cats, "Pages using discouraged character sequences")
end
end
link = simple_link(
data.term[i],
data.fragment,
data.alt[i],
lang,
data.sc[i],
id,
cats,
no_alt_ast,
srwc
)
end
-- simple_link can return nil, so check if a link has been generated.
if link then
-- Add "nowrap" class to prefixes in order to prevent wrapping after the hyphen
local nowrap
local display_term = data.alt[i] or data.term[i]
if display_term and (display_term:find("^%-") or display_term:find("^־")) then -- Hebrew maqqef -- FIXME, use hyphens from [[Module:affix]]
nowrap = "nowrap"
end
link = tag_text(link, lang, data.sc[i], face, get_class(lang, data.tr[i], accel, nowrap))
else
--[[ No term to show.
Is there at least a transliteration we can work from? ]]
link = request_script(lang, data.sc[i])
-- No link to show, and no transliteration either. Show a term request (unless it's a substrate, as they rarely take terms).
if (link == "" or (not data.tr[i]) or data.tr[i] == "-") and lang:getFamilyCode() ~= "qfa-sub" then
-- If there are multiple terms, break the loop instead.
if i > 1 then
remove(output)
break
elseif NAMESPACE ~= "Bản mẫu" then
insert(cats, "Yêu cầu mục từ " .. lang:getFullName())
end
link = "<small>[Mục từ gì?]</small>"
end
end
insert(output, link)
if i < #terms then insert(output, "<span class=\"Zsym mention\" style=\"font-size:100%;\"> / </span>") end
end
-- TODO: Currently only handles the first transliteration, pending consensus on how to handle multiple translits for multiple forms, as this is not always desirable (e.g. traditional/simplified Chinese).
if data.tr[1] == "" or data.tr[1] == "-" then
data.tr[1] = nil
else
local phonetic_extraction = load_data("Module:links/data").phonetic_extraction
phonetic_extraction = phonetic_extraction[lang:getCode()] or phonetic_extraction[lang:getFullCode()]
if phonetic_extraction then
data.tr[1] = data.tr[1] or require(phonetic_extraction).getTranslit(export.remove_links(data.alt[1] or data.term[1]))
elseif (data.term[1] or data.alt[1]) and data.sc[1]:isTransliterated() then
-- Track whenever there is manual translit. The categories below like 'terms with redundant transliterations'
-- aren't sufficient because they only work with reference to automatic translit and won't operate at all in
-- languages without any automatic translit, like Persian and Hebrew.
if data.tr[1] then
local full_code = lang:getFullCode()
track("manual-tr", full_code)
end
if not nevercalltr then
-- Try to generate a transliteration.
local text = data.alt[1] or data.term[1]
if not link_tr then
text = export.remove_links(text, true)
end
local automated_tr = lang:transliterate(text, data.sc[1])
if automated_tr then
local manual_tr = data.tr[1]
if manual_tr then
if export.remove_links(manual_tr) == export.remove_links(automated_tr) then
insert(cats, "Mục từ có chuyển tự thừa " .. lang:getFullName())
else
-- Prevents Arabic root categories from flooding the tracking categories.
if NAMESPACE ~= "Thể loại" then
insert(cats, "Mục từ có chuyển tự thủ công không thừa " .. lang:getFullName())
end
end
end
if not manual_tr or lang:overrideManualTranslit(data.sc[1]) then
data.tr[1] = automated_tr
end
end
end
end
end
-- Link to the transliteration entry for languages that require this
if data.tr[1] and link_tr and not data.tr[1]:match("%[%[(.-)%]%]") then
data.tr[1] = simple_link(
data.tr[1],
nil,
nil,
lang,
get_script("Latn"),
nil,
cats,
no_alt_ast,
srwc
)
elseif data.tr[1] and not link_tr then
-- Remove the pseudo-HTML tags added by remove_links.
data.tr[1] = data.tr[1]:gsub("</?link>", "")
end
if data.tr[1] and not umatch(data.tr[1], "[^%s%p]") then data.tr[1] = nil end
insert(output, export.format_link_annotations(data, face))
if data.pretext then
insert(output, 1, data.pretext)
end
if data.posttext then
insert(output, data.posttext)
end
local categories = cats[1] and format_categories(cats, lang, "-", nil, nil, data.sc) or ""
output = concat(output)
if show_qualifiers or data.show_qualifiers then
output = add_qualifiers_and_refs_to_term(data, output)
end
return output .. categories
end
--[==[Replaces all wikilinks with their displayed text, and removes any categories. This function can be invoked either from a template or from another module.
-- Strips links: deletes category links, the targets of piped links, and any double square brackets involved in links (other than file links, which are untouched). If `tag` is set, then any links removed will be given pseudo-HTML tags, which allow the substitution functions in [[Module:languages]] to properly subdivide the text in order to reduce the chance of substitution failures in modules which scrape pages like [[Module:zh-translit]].
-- FIXME: This is quite hacky. We probably want this to be integrated into [[Module:languages]], but we can't do that until we know that nothing is pushing pipe linked transliterations through it for languages which don't have link_tr set.
* <code><nowiki>[[page|displayed text]]</nowiki></code> → <code><nowiki>displayed text</nowiki></code>
* <code><nowiki>[[page and displayed text]]</nowiki></code> → <code><nowiki>page and displayed text</nowiki></code>
* <code><nowiki>[[Category:English lemmas|WORD]]</nowiki></code> → ''(nothing)'']==]
function export.remove_links(text, tag)
if type(text) == "table" then
text = text.args[1]
end
if not text or text == "" then
return ""
end
text = text
:gsub("%[%[", "\1")
:gsub("%]%]", "\2")
-- Parse internal links for the display text.
text = text:gsub("(\1)([^\1\2]-)(\2)",
function(c1, c2, c3)
-- Don't remove files.
for _, false_positive in ipairs({"file", "image"}) do
if c2:lower():match("^" .. false_positive .. ":") then return c1 .. c2 .. c3 end
end
-- Remove categories completely.
for _, false_positive in ipairs({"category", "cat"}) do
if c2:lower():match("^" .. false_positive .. ":") then return "" end
end
-- In piped links, remove all text before the pipe, unless it's the final character (i.e. the pipe trick), in which case just remove the pipe.
c2 = c2:match("^[^|]*|(.+)") or c2:match("([^|]+)|$") or c2
if tag then
return "<link>" .. c2 .. "</link>"
else
return c2
end
end)
text = text
:gsub("\1", "[[")
:gsub("\2", "]]")
return text
end
function export.section_link(link)
if type(link) ~= "string" then
error("The first argument to section_link was a " .. type(link) .. ", but it should be a string.")
elseif link:find("\\", nil, true) then
track("escaped", "section_link")
end
local target, section = get_fragment((link:gsub("_", " ")))
if not section then
error("No \"#\" delineating a section name")
end
return simple_link(
target,
section,
target .. " § " .. section
)
end
return export
j65lna1gtbkxv8v8ao1y9tn092on82s
Bản mẫu:blt-pron
10
260080
2344376
2079761
2026-04-12T04:22:10Z
Higashizakura
36666
2344376
wikitext
text/x-wiki
<includeonly>{{#invoke:blt-pron|show}}</includeonly><noinclude>{{tài liệu}}{{tcat|pron}}</noinclude>
9bxj8e12arw7bpl41tapkfeuut0wzha
Phụ lục:Từ điển thuật ngữ
100
263936
2344321
2335804
2026-04-12T02:00:25Z
TheHighFighter2
42988
2344321
wikitext
text/x-wiki
Trang này chú giải [[thuật ngữ]] được sử dụng trong phần nội dung của từ điển này.
__TOC__
==B==
; '''Ban đầu [...]'''
: Một từ có nguồn gốc từ một địa phương hoặc vùng miền nào đó, mà ngày nay trở nên phổ biến gần như trở thành từ toàn dân. '''1. {{anchor|Ban đầu Miền Bắc Việt Nam}} Ban đầu Miền Bắc Việt Nam''': Một từ có chú thích “Ban đầu Miền Bắc Việt Nam” tức là từ đó bắt nguồn từ Miền Bắc Việt Nam '''2. {{anchor|Ban đầu Miền Nam Việt Nam}} Ban đầu Miền Nam Việt Nam''': Một từ có chú thích “Ban đầu Miền Nam Việt Nam” tức là từ đó bắt nguồn từ Miền Nam Việt Nam. '''3. {{anchor|Ban đầu Miền Trung Việt Nam}} Ban đầu Miền Trung Việt Nam''': Một từ có chú thích “Ban đầu Miền Trung Việt Nam” tức là từ đó bắt nguồn từ Miền Trung Việt Nam.
==C==
;{{anchor|cách}} '''cách'''
: Phạm trù ngữ pháp được sử dụng nhằm thể hiện quan hệ và vai trò giữa các từ ở trong một câu hoặc một cụm từ. Một số các cách bao gồm [[#danh cách|danh cách]], [[#sinh cách|sinh cách]], [[#dữ cách|dữ cách]],...
; {{anchor|cổ xưa}} '''cổ xưa'''
: Không còn được sử dụng rộng rãi nữa, nhưng vẫn có thể bắt gặp nó trong một số văn bản đương đại, đặc biệt là những tác phẩm muốn tạo phong cách cổ kính, chẳng hạn như các tác phẩm tiểu thuyết lịch sử. Ví dụ, trong Tiếng Anh, các đại từ [[thee]] và [[thou]] là những từ cổ xưa, giờ vẫn được dùng trong một vài văn bản đương đại, nhưng giờ đây gần như đã được thay thế hoàn toàn bằng [[you]]. ''Cổ xưa'' là một thuật ngữ mang ý nghĩa mạnh hơn [[Phụ lục:Từ điển thuật ngữ#lỗi thời|''lỗi thời'']] nhưng lại không mạnh bằng [[Phụ lục:Từ điển thuật ngữ#không còn dùng|''không còn dùng'']].
; {{anchor|CN}}'''CN'''
: Viết tắt của "[[Công Nguyên]]".
==D==
; {{anchor|dữ cách}} '''dữ cách'''
: [[#cách|Cách]] thường được sử dụng làm [[#bổ ngữ gián tiếp|bổ ngữ gián tiếp]] cho một động từ. Lấy ví dụ, trong tiếng Latinh, trong câu ''Sextus Claudiae fābulam dīxit'' (Sextus kể cho Claudia một câu chuyện), từ "Claudiae" (Claudia) được chia ở dữ cách.
==Đ==
; {{anchor|đếm được}}'''đếm được'''
:Danh từ có thể được sử dụng tự do với mạo từ không xác định (a hoặc an trong tiếng Anh) và với số, do đó có dạng [[số nhiều]].
; {{anchor|đối cách}}'''đối cách'''
: [[#cách|Cách]] thường được sử dụng làm [[#tân ngữ trực tiếp|tân ngữ trực tiếp]] cho một động từ. Lấy ví dụ, trong tiếng Latinh, trong câu ''Puella puerum amat'' (Cô bé yêu cậu bé), "puerum" (cậu bé) được chia ở đối cách.
; {{anchor|Đph}}'''Đph'''
:Viết tắt của "Từ địa phương", là những từ được sử dụng hạn chế ở một hoặc vài [[địa phương]] nào đó. Từ địa phương là một bộ phận của [[phương ngữ]].
==G==
; {{g|f}}
: ''Xem '''{{lg|giống cái}}'''.''
; {{g|c}}
: ''Xem '''{{lg|giống chung}}'''.''
; {{g|m}}
: ''Xem '''{{lg|giống đực}}'''.''
; {{g|n}}
: ''Xem '''{{lg|giống trung}}'''.''
; {{anchor|giảm nhẹ nghĩa}}'''giảm nhẹ nghĩa'''
:Hình thức giảm nhẹ nghĩa, âu yếm, trìu mến nhỏ bé thường được sử dụng để biểu đạt những mối quan hệ thân thiết, gần gũi.
; {{anchor|giống}} [[giống]]
: Cách phân loại [[#danh từ|danh từ]] trong một số ngôn ngữ. Theo đó, mỗi danh từ sẽ thuộc về một giống cụ thể (thường dựa trên nghĩa và/hoặc hình thái). Các từ loại khác (nhất là [[#tính từ|tính từ]] và [[#đại từ|đại từ]]) thường phải biến đổi hình thái để phù hợp về giống với danh từ đó. Xem thêm [[#lớp danh từ|lớp danh từ]].
; {{anchor|gc|giống cái}} [[giống cái]], {{g|f}}
: Đề cập đến một từ thuộc phạm trù ngữ pháp [[#giống|giống]] là "cái", thường tương phản với [[#giống đực|giống đực]] và đôi khi là cả [[#giống trung|giống trung]].
; {{anchor|gch|giống chung}} [[giống chung]], {{g|c}}
: Đề cập đến một từ thuộc phạm trù ngữ pháp [[#giống|giống]] là "chung giống". Trong một số ngôn ngữ, giống chung là một phạm trù ngữ pháp riêng biệt được hình thành từ sự kết hợp giữa [[#giống đực|giống đực]] và [[#giống cái|giống cái]], nhưng phân biệt với [[#giống trung|giống trung]]. Trong các ngôn ngữ khác, "danh từ giống chung" là một cặp danh từ (gồm một giống đực và một giống cái) có hình thái giống hệt nhau và tương đồng về nghĩa, nhưng khác nhau đối tượng tham chiếu (một chỉ nam giới, một chỉ nữ giới). Cần phân biệt với [[#giống đôi|giống đôi]].
; {{anchor|gđ|giống đực}} [[giống đực]], {{g|m}}
: Đề cập đến một từ thuộc phạm trù ngữ pháp [[#giống|giống]] là "đực" trong những ngôn ngữ có phân biệt giống.
; {{anchor|gt|giống trung}} [[giống trung]], {{g|n}}
: Đề cập đến một từ thuộc phạm trù ngữ pháp [[#giống|giống]] là "trung tính": có hình thái không phải [[#giống đực|giống đực]] hay là [[#giống cái|giống cái]]; hoặc có hình thái không thuộc [[#giống chung|giống chung]].
==K==
; {{anchor|kh.}}'''kh.'''
: Viết tắt của "[[khoảng]]". Một trích dẫn có ghi thông tin chẳng hạn như "kh. 1924" có nghĩa phần đó được trích dẫn từ ngữ liệu có từ khoảng những năm 1924.
; {{anchor|không còn dùng}}'''không còn dùng'''
:Không còn được sử dụng nữa. ''Không còn dùng'' là một thuật ngữ mang ý nghĩa mạnh hơn so với [[Phụ lục:Từ điển thuật ngữ#lỗi thời|''lỗi thời'']] và [[Phụ lục:Từ điển thuật ngữ#cổ xưa|''cổ xưa'']].
; {{anchor|không đếm được}}'''không đếm được'''
:Danh từ không thể được sử dụng tự do với số hoặc mạo từ không xác định, và do đó thường không có dạng số nhiều. Nhiều ngôn ngữ không phân biệt danh từ đếm được và không đếm được.
; {{anchor|Kng.}}'''Kng.'''
:Viết tắt của [[khẩu ngữ]].
==L==
; {{anchor|lẫn âm}}'''lẫn âm'''
: Từ ngữ được hình thành do hiện tượng đọc lẫn các âm gần giống, dần dà trở thành một từ mới. Nhưng ban đầu là một từ vô nghĩa hoặc có nghĩa khác. Ví dụ như từ [[mãn tính]] là một từ Hán-Việt cấu thành bởi hiện tượng lẫn âm (từ đúng là [[mạn tính]]).
; {{anchor|lóng}}{{anchor|từ lóng}}{{anchor|tiếng lóng}}'''lóng''', '''từ lóng''', '''tiếng lóng'''
: Từ ngữ riêng trong một tầng lớp hoặc một nhóm người nào đó, nhằm chỉ để cho trong nội bộ hiểu được với nhau. Các từ ngữ như vậy thường nằm ngoài cách sử dụng thông thường và hầu như không phù hợp trong bối cảnh trang trọng.
; {{anchor|lỗi thời}} '''lỗi thời'''
: Từng phổ biến trong quá khứ, đôi khi vẫn được dùng ở hiện tại nhưng bây giờ không còn hợp thời. Ví dụ, trong tiếng Anh, từ [[gay]] (theo nghĩa "sáng sủa", "hạnh phúc") là một từ lỗi thời. ''Lỗi thời'' là một thuật ngữ mang ý nghĩa yếu hơn so với [[Phụ lục: Từ điển thuật ngữ#không còn dùng|''không còn dùng'']] và [[Phụ lục: Từ điển thuật ngữ#cổ xưa|''cổ xưa'']].
; {{anchor|ly cách}} '''ly cách'''
: [[#cách|Cách]] được dùng để diễn tả sự tách biệt, sự tách ra, sự di chuyển khỏi một cái gì đó. Ly cách thường được sử dụng độc lập hoặc đi kèm với một số [[#giới từ|giới từ]] nhất định. Lấy ví dụ, trong tiếng Latinh, trong câu ''Ē Vietnamiā oriundus est Vincentius'' (Vincent đến từ Việt Nam), từ "Vietnamiā" (Việt Nam) được chia ở ly cách và đứng sau giới từ "ē". Trong một số ngôn ngữ, chẳng hạn như tiếng Latinh, ngoài để diễn tả sự tách biệt, ly cách còn có thêm nhiều cách dùng khác như: chỉ nguyên nhân, nơi chốn, thời gian,...
==N==
; {{anchor|nhạc}}'''nhạc'''
: Từ thuộc về âm nhạc.
==P==
; {{anchor|phụ tố|af}} [[phụ tố]]
: [[hình vị ràng buộc|Hình vị ràng buộc]] được thêm vào thân từ; tức [[tiền tố]], [[hậu tố]], [[trung tố]], v.v.. Theo nghĩa hẹp, đồng nghĩa với cả '''[[#hậu tố|hậu tố]]'''.
==S==
; {{g|p}}
: ''Xem '''{{lg|số nhiều}}'''.''
; {{anchor|so sánh}}'''so sánh'''
:Từ so sánh đối tượng này với một hoặc nhiều đối tượng khác nhau.
; {{anchor|so sánh được}}'''so sánh được'''
:Tính từ hoặc trạng từ: có thể so sánh, có dạng so sánh hơn và so sánh nhất kết thúc bằng -er và -est (chỉ tính từ), hoặc kết hợp với các từ ''more'' hoặc ''most'', hoặc trong một số trường hợp kết hợp với ''further'' và ''furthest''.
; {{anchor|so sánh hơn}}'''so sánh hơn'''
:Tính từ so sánh tương đối, thường biểu thị "ở mức lớn hơn" nhưng không phải "ở mức cuối cùng". Trong tiếng Anh, dạng so sánh hơn so sánh giữa 2 người hoặc 2 vật, thường được hình thành bằng cách thêm -er, hoặc sử dụng từ "more".
; {{anchor|so sánh nhất}}'''so sánh nhất'''
:Tính từ so sánh tương đối, biểu thị "ở mức cuối cùng". Trong tiếng Anh, dạng so sánh nhất so sánh giữa 3 người hoặc 3 vật trở lên, thường được hình thành bằng cách thêm -est hoặc sử dụng từ "most".
; {{anchor|số nhiều|sn}} [[số nhiều]]
: Phạm trù ngữ pháp [[#số|số]] dùng để biểu thị ý có nhiều cá thể hoặc đối tượng. Phần lớn các ngôn ngữ đặt số nhiều trong thế đối lập với [[#số ít|số ít]], và khi đó số nhiều dùng để chỉ số lượng có từ hai trở lên. Một số ngôn ngữ còn có khái niệm [[#số đôi|số đôi]] hoặc thậm chí là [[#số ba|số ba]]; trong những trường hợp này, số nhiều dùng để chỉ số lượng lớn hơn mốc cao nhất hiện có.
==T==
; {{anchor|TCN}}'''[[TCN]]'''
: Viết tắt của "[[trước]] [[Công Nguyên]]".
; {{anchor|Tech}}'''Tech'''
:Viết tắt của [[technology|Technology]], nghĩa là [[công nghệ học]] (xem thêm [[tech]] để biết thông tin chi tiết) hoặc [[công nghệ]].
; {{anchor|thô tục}}'''[[thô tục]]'''
: Từ ngữ được coi là gây khó chịu hoặc tục tĩu.
: Xem thêm: '''{{glossary|xúc phạm}}''', '''{{glossary|miệt thị}}'''.
; {{anchor|Tnd}} '''Tnd'''
: Viết tắt của "từ Toàn dân", là từ được toàn dân biết, phổ biến rộng rãi và được sử dụng trong giao tiếp hằng ngày.
; {{anchor|tôn giáo}} '''tôn giáo'''
: Từ thuộc về tôn giáo, giáo lí.
; {{anchor|tuyệt cách}} '''tuyệt cách'''
: [[#cách|Cách]] được sử dụng để chỉ bị thể hoặc nghiệm thể của hành động do một [[#động từ|động từ]] biểu thị.
; {{anchor|từ mới}}'''từ mới'''
: Từ được tạo mới hoàn toàn hay từ có thêm nét nghĩa mới trong khoảng thời gian gần đây.
; {{anchor|từ tượng hình}} '''từ tượng hình'''
: Từ mang tính biểu tượng, gợi ý hình ảnh của sự vật mà nó mô tả. Ví dụ như từ [[tẻo teo]].
; {{anchor|từ tượng thanh}}{{anchor|tượng thanh}}'''[[từ tượng thanh]]'''
: Từ có ngữ âm bắt chước, giống với, hoặc gợi ý âm thanh mà nó mô tả. Ví dụ như các từ ''{{l|vi|bùm}}'', ''{{l|vi|cúc cu}}'', ''{{l|vi|chiếp}}'', ''{{l|vi|bính boong}}'' trong tiếng Việt.
; {{anchor|từ ghép}}'''[[từ ghép]]'''
: Từ được cấu tạo bằng cách ghép những tiếng lại với nhau, các tiếng được ghép có quan hệ với nhau về nghĩa.
==V==
;{{anchor|viết tắt}} '''viết tắt'''
: Dạng rút gọn của một từ hoặc một cụm từ.
==X==
;{{anchor|xuất cách}} '''xuất cách'''
:[[#cách|Cách]] biểu thị rằng một thứ gì đó đến từ một cái gì đó, ở đâu đó hoặc ai đó.
==Khác==
; {{anchor|перен.}}'''перен.'''
:Viết tắt của [[переносное значение]], nghĩa là [[nghĩa bóng]].
; {{anchor|мед.}}'''мед.'''
:Viết tắt của [[медицинское]], nghĩa là [[Y học]].
; {{anchor|лингв.}}'''лингв.'''
:Viết tắt của [[лингвистический]], nghĩa là (thuộc về) [[ngôn ngữ học]].
; {{anchor|анат.}}'''анат.'''
:Viết tắt của [[анатомический]], nghĩa là (thuộc về) [[giải phẫu]].
; {{anchor|нескл.}}'''нескл.'''
:Viết tắt của [[несклоняемый]], nghĩa là Không biến cách.
; {{anchor|физ.}}'''физ.'''
:Viết tắt của [[физический]], nghĩa là [[vật lý]].
; {{anchor|уст.}}'''уст.'''
:Viết tắt của [[устаревший]], nghĩa là Từ cũ.
; {{anchor|тех.}}'''тех.'''
:Viết tắt của [[технический]], nghĩa là [[kỹ thuật]].
; {{anchor|хим.}}'''хим.'''
:Viết tắt của [[химический]], nghĩa là (thuộc về) [[hóa học]].
; {{anchor|воен.}}'''воен.'''
:Viết tắt của [[военный]], nghĩa là (thuộc về) [[quân sự]].
; {{anchor|мат.}}'''мат.'''
:Viết tắt của [[математический]], nghĩa là (thuộc về) [[toán học]].
; {{anchor|бот.}}'''бот.'''
:Viết tắt của [[ботанический]], nghĩa là (thuộc về) [[thực vật học]].
; {{anchor|собир.}}'''собир.'''
:Viết tắt của [[собирательный]], nghĩa là (tính chất) [[tập hợp]].
; {{anchor|спорт.}}'''спорт.'''
:Viết tắt của [[спорт]], nghĩa là (thuộc về) [[thể thao]].
[[Thể loại:Wiktionary]]
i3ku9rxip11dnloa3r7o7bcql30k3o3
asaramaab
0
267519
2344411
2063242
2026-04-12T05:01:31Z
Hiyuune
50834
2344411
wikitext
text/x-wiki
=={{langname|bej}}==
{{cardinalbox|bej|6|7|8|asagwir|asumhay}}
==={{section|etym}}===
Từ {{l|bej|maloob|t=hai}}.
==={{section|pron}}===
* {{bej-IPA}}
==={{section|num}}===
{{head|bej|Số từ|g=m|giống cái|asaramaat}}
# [[bảy|Bảy]].
==={{section|ref}}===
* {{R:bej:Reinisch|331}}
b4fqbl6mj3a9f0mgcbz7kg4yfmz5h8g
tamnagwir
0
267523
2344407
2063246
2026-04-12T04:59:22Z
Hiyuune
50834
2344407
wikitext
text/x-wiki
=={{langname|bej}}==
==={{section|num}}===
{{head|bej|Số từ|g=m}}
# [[mười một|Mười một]].
omev60b8y6m5u5rvit55rezei8xun3v
ᦀᦇᦳᧃ
0
268744
2344490
2067287
2026-04-12T11:56:01Z
Hiyuune
50834
2344490
wikitext
text/x-wiki
=={{langname|khb}}==
==={{section|etym}}===
{{bor+|khb|th|องุ่น}}, từ {{der|khb|bn|আঙ্গুর}}, từ {{der|khb|fa|انگور}}.
==={{section|pron}}===
{{khb-pron|ᦀ-ᦇᦳᧃ}}
==={{section|n}}===
{{khb-noun|ᦐᦽᧈ|l=ᩋᨦᩩᩁ}}
# [[quả|Quả]] [[nho]].
#: {{syn|khb|ᦖᦱᧅᦀᦲᧆᧈ}}
==={{section|ref}}===
* {{R:khb:Hanna}}
{{C|khb|Trái cây}}
5rt9nl46tz3816rguvhtrmjwittmk1o
ᦶᦀᧅ
0
268983
2344485
2068037
2026-04-12T11:48:25Z
Hiyuune
50834
2344485
wikitext
text/x-wiki
=={{langname|khb}}==
==={{section|etym}}===
Từ {{inh|khb|tai-pro|*ʔeːkᴰ}}, từ {{der|khb|ltc|-}} {{ltc-l|軛}}. Cùng gốc với {{cog|th|แอก}}, {{cog|tts|แอก}}, {{cog|lo|ແອກ}}, {{cog|nod|ᩋᩯ᩠ᨠ}}, {{cog|kkh|ᩋᩯ᩠ᨠ}}, {{cog|blt|ꪵꪮꪀ}}, {{cog|twh|ꪵꪮꪀ}}, {{cog|shn|ဢႅၵ်ႇ}}, {{cog|tdd|ᥟᥦᥐᥱ}}, {{cog|aho|𑜒𑜢𑜀𑜫}}, {{cog|za|ek}}.
==={{section|pron}}===
{{khb-pron}}
==={{section|n}}===
{{khb-noun|ᦀᧃ}}
# [[ách|Ách]].
==={{section|ref}}===
* {{R:khb:Hanna}}
cm1gvhlth1f1ob2xtrl95utzxpv0s62
-ꝰ
0
270158
2344429
2111793
2026-04-12T05:19:41Z
Hiyuune
50834
2344429
wikitext
text/x-wiki
{{also|ꝰ}}
=={{langname|la}}==
==={{section|suffix}}===
{{head|la|Biến thể hình thái hậu tố}} {{tlb|la|Medieval Latin}}
# {{scrib of|la|-us|addl=khác với danh từ ở dữ cách hoặc ly cách số nhiều}}
# {{scrib of|la|-ūs}}
# {{scrib of|la|-os}}
# {{scrib of|la|-ōs}}
===={{section|usage}}====
Gần như luôn luôn dùng ở cuối từ.
===={{section|rel}}====
* [[-ꝫ]]
gq4ma1bfe9anocc7mpml8zopgzr98y1
asagwir tamun
0
271106
2344406
2074155
2026-04-12T04:58:53Z
Hiyuune
50834
2344406
wikitext
text/x-wiki
=={{langname|bej}}==
==={{section|num}}===
{{head|bej|Số từ}}
# [[sáu mươi|Sáu mươi]].
lhuqthkbo0e7pp073cw8x59nrtzyiah
2344408
2344406
2026-04-12T04:59:37Z
Hiyuune
50834
/* Số từ */ (sử dụng [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]])
2344408
wikitext
text/x-wiki
=={{langname|bej}}==
==={{section|num}}===
{{head|bej|Số từ|g=m}}
# [[sáu mươi|Sáu mươi]].
9t2yfa2f2fgr82mxgp4ytsf3e779c49
asarama tamun
0
271107
2344409
2074156
2026-04-12T05:00:26Z
Hiyuune
50834
2344409
wikitext
text/x-wiki
=={{langname|bej}}==
==={{section|num}}===
{{head|bej|Số từ|g=m}}
# [[bảy mươi|Bảy mươi]].
n98ybqazptbdw07rzpird4l15upgyk9
ᦀᦞᦲᦈᦲ
0
271547
2344487
2075825
2026-04-12T11:50:29Z
Hiyuune
50834
2344487
wikitext
text/x-wiki
=={{langname|khb}}==
==={{section|etym}}===
{{etym-from|lang=sa|term=अवीचि}}
==={{section|pron}}===
{{khb-pron|ᦀ-ᦞᦲ-ᦈᦲ}}
==={{section|n}}===
{{khb-noun}}
# [[địa ngục|Địa ngục]].
43qvcir6bzbtrxubi2a7r4983vcozl3
ᦁᦳᧃᦎᦟᦻ
0
272017
2344488
2077158
2026-04-12T11:51:20Z
Hiyuune
50834
2344488
wikitext
text/x-wiki
=={{langname|khb}}==
==={{section|pron}}===
{{khb-pron|ᦁᦳᧃ-ᦎ-ᦟᦻ}}
==={{section|noun}}===
{{khb-noun}}
# [[sự|Sự]] [[nguy hiểm]], [[thiên tai]], [[tai nạn]].
sg8tq52yykztu71w77ieaq115rcpmq2
Mô đun:languages/data/3/i
828
272289
2344285
2332251
2026-04-11T13:39:24Z
Lcsnes
40261
2344285
Scribunto
text/plain
local m_langdata = require("Module:languages/data")
-- Loaded on demand, as it may not be needed (depending on the data).
local function u(...)
u = require("Module:string utilities").char
return u(...)
end
local c = m_langdata.chars
local p = m_langdata.puaChars
local s = m_langdata.shared
local m = {}
m["iai"] = {
"tiếng Iaai",
282888,
"poz-occ",
"Latn",
"Tiếng Iaai",
"Iaai",
}
m["ian"] = {
"Iatmul",
5983460,
"paa-spk",
}
m["iar"] = {
"Purari",
3499934,
"paa",
}
m["iba"] = {
"tiếng Iban",
33424,
"poz-mly",
"Latn",
"Tiếng Iban",
"Iban",
}
m["ibb"] = {
"tiếng Ibibio",
33792,
"nic-ief",
"Latn",
"Tiếng Ibibio",
"Ibibio",
}
m["ibd"] = {
"tiếng Iwaidja",
1977429,
"aus-wdj",
"Latn",
"Tiếng Iwaidja",
"Iwaidja",
}
m["ibe"] = {
"Akpes",
35457,
"alv-von",
"Latn",
}
m["ibg"] = {
"tiếng Ibanag",
1775596,
"phi",
"Latn",
"Tiếng Ibanag",
"Ibanag",
}
m["ibh"] = {
"tiếng Bih",
nil,
"cmc",
"Latn",
"Tiếng Bih",
"Bih",
}
m["ibl"] = {
"tiếng Ibaloi",
3147383,
"phi",
"Latn",
"Tiếng Ibaloi",
"Ibaloi",
}
m["ibm"] = {
"Agoi",
34727,
"nic-ucr",
"Latn",
}
m["ibn"] = {
"tiếng Ibino",
3813281,
"nic-lcr",
"Latn",
"Tiếng Ibino",
"Ibino",
}
m["ibr"] = {
"tiếng Ibuoro",
3813306,
"nic-ief",
"Latn",
"Tiếng Ibuoro",
"Ibuoro",
}
m["ibu"] = {
"Ibu",
11732235,
"paa-nha",
}
m["iby"] = {
"Ibani",
11280479,
"ijo",
}
m["ica"] = {
"tiếng Ede Ica",
12952405,
"alv-ede",
"Latn",
"Tiếng Ede Ica",
"Ede Ica",
}
m["ich"] = {
"Etkywan",
3914462,
"nic-jkn",
"Latn",
}
m["icl"] = {
"Icelandic Sign Language",
3436654,
"sgn",
"Latn", -- when documented
}
m["icr"] = {
"Islander Creole English",
2044587,
"crp",
"Latn",
ancestors = "en",
}
m["ida"] = {
"Idakho-Isukha-Tiriki",
12952512,
"bnt-lok",
}
m["idb"] = {
"tiếng Indo-Bồ Đào Nha",
6025550,
"crp",
"Latn",
"Tiếng Indo-Bồ Đào Nha",
"Indo-Bồ Đào Nha",
ancestors = "pt",
}
m["idc"] = {
"Idon",
3913366,
"nic-plc",
}
m["idd"] = {
"tiếng Ede Idaca",
13123376,
"alv-ede",
"Latn",
"Tiếng Ede Idaca",
"Ede Idaca",
}
m["ide"] = {
"Idere",
3813288,
"nic-ief",
}
m["idi"] = {
"Idi",
5988630,
"paa",
}
m["idr"] = {
"Indri",
35662,
"nic-ser",
}
m["ids"] = {
"Idesa",
3913979,
"alv-swd",
"Latn",
ancestors = "oke",
}
m["idt"] = {
"Idaté",
12952511,
"poz-tim",
"Latn",
}
m["idu"] = {
"Idoma",
35478,
"alv-ido",
"Latn",
}
m["ifa"] = {
"Amganad Ifugao",
18748222,
"phi",
}
m["ifb"] = {
"tiếng Ifugao Batad",
12953578,
"phi",
"Latn",
"Tiếng Ifugao Batad",
"Ifugao Batad",
}
m["ife"] = {
"tiếng Ifè",
33606,
"alv-ede",
"Latn",
"Tiếng Ifè",
"Ifè",
entry_name = {remove_diacritics = c.grave .. c.acute .. c.circ .. c.macron .. c.caron},
sort_key = {
remove_diacritics = c.tilde,
from = {"ɖ", "dz", "ɛ", "gb", "kp", "ny", "ŋ", "ɔ", "ts"},
to = {"d" .. p[1], "d" .. p[2], "e" .. p[1], "g" .. p[1], "k" .. p[1], "n" .. p[1], "n" .. p[2], "o" .. p[1], "t" .. p[1]}
},
}
m["iff"] = {
"Ifo",
7902545,
"poz-oce",
"Latn",
}
m["ifk"] = {
"Tuwali Ifugao",
7857158,
"phi",
}
m["ifm"] = {
"Teke-Fuumu",
36603,
"bnt-tek",
}
m["ifu"] = {
"Mayoyao Ifugao",
12953579,
"phi",
"Latn",
}
m["ify"] = {
"Keley-I Kallahan",
3192221,
"phi",
}
m["igb"] = {
"Ebira",
35363,
"alv-nup",
"Latn",
}
m["ige"] = {
"Igede",
35420,
"alv-ido",
"Latn",
}
m["igg"] = {
"Igana",
5991454,
"paa",
"Latn",
}
m["igl"] = {
"tiếng Igala",
35513,
"alv-yrd",
"Latn",
"Tiếng Igala",
"Igala",
entry_name = {remove_diacritics = c.grave .. c.acute .. c.circ .. c.macron .. c.dotabove .. c.caron .. c.lineabove},
sort_key = {
from = {
"ñm", "ñw", -- 3 chars
"ch", "ẹ", "gb", "gw", "kp", "kw", "ny", "ñ", "ọ" -- 2 chars
},
to = {
"n" .. p[3], "n" .. p[4],
"c" .. p[1], "e" .. p[1], "g" .. p[1], "g" .. p[2], "k" .. p[1], "k" .. p[2], "n" .. p[1], "n" .. p[2], "o" .. p[1]
}
},
}
m["igm"] = {
"Kanggape",
6362743,
"paa",
"Latn",
}
m["ign"] = {
"Ignaciano",
3148190,
"awd",
}
m["igo"] = {
"Isebe",
11732248,
"ngf-mad",
}
m["igs"] = {
"tiếng Glosa",
1138529,
"art",
"tiếng Glosa",
"Glosa",
type = "appendix-constructed",
}
m["igw"] = {
"Igwe",
3913985,
"alv-yek",
"Latn",
}
m["ihb"] = {
"Pidgin Iha",
12639686,
"crp",
ancestors = "ihp",
}
m["ihi"] = {
"Ihievbe",
3441193,
"alv-eeo",
"Latn",
ancestors = "ema",
}
m["ihp"] = {
"Iha",
5994495,
"ngf",
}
m["ijc"] = {
"tiếng Izon",
35483,
"ijo",
"Latn",
"Tiếng Izon",
"Izon",
}
m["ije"] = {
"Biseni",
35010,
"ijo",
}
m["ijj"] = {
"Ede Ije",
12952406,
"alv-ede",
"Latn",
}
m["ijn"] = {
"Kalabari",
35697,
"ijo",
}
m["ijs"] = {
"Southeast Ijo",
3915854,
"ijo",
"Latn",
}
m["ike"] = {
"tiếng Inuktitut Đông Canada",
4126517,
"esx-inu",
"Cans, Latn",
"Tiếng Inuktitut Đông Canada",
"Inuktitut Đông Canada",
translit = {Cans = "cr-translit"},
override_translit = true,
}
m["iki"] = {
"Iko",
3813290,
"nic-lcr",
"Latn",
}
m["ikk"] = {
"Ika",
35406,
"alv-igb",
}
m["ikl"] = {
"Ikulu",
425973,
"nic-plc",
"Latn",
}
m["iko"] = {
"Olulumo-Ikom",
3914402,
"nic-uce",
"Latn",
}
m["ikp"] = {
"Ikpeshi",
3912777,
"alv-yek",
"Latn",
}
m["ikr"] = {
"Ikaranggal",
5995402,
"aus-pam",
}
m["iks"] = {
"Inuit Sign Language",
13360244,
"sgn",
"Latn", -- when documented
}
m["ikt"] = {
"tiếng Inuvialuktun",
27990,
"esx-inu",
"Cans, Latn",
"Tiếng Inuvialuktun",
"Inuvialuktun",
translit = {Cans = "cr-translit"},
override_translit = true,
}
m["ikv"] = {
"Iku-Gora-Ankwa",
3913940,
"nic-plc",
}
m["ikw"] = {
"tiếng Ikwere",
35399,
"alv-igb",
"Latn",
"Tiếng Ikwere",
"Ikwere",
}
m["ikx"] = {
"Ik",
35472,
"ssa-klk",
"Latn",
}
m["ikz"] = {
"Ikizu",
10977626,
"bnt-lok",
"Latn",
}
m["ila"] = {
"Ile Ape",
12473380,
"poz-cet",
}
m["ilb"] = {
"Ila",
10962725,
"bnt-bot",
"Latn",
}
m["ilg"] = {
"Ilgar",
5997810,
"aus-wdj",
"Latn",
}
m["ili"] = {
"tiếng Ili Turki",
33627,
"trk-kar",
nil,
"Tiếng Ili Turki",
"Ili Turki",
}
m["ilk"] = {
"Ilongot",
3148787,
"phi",
"Latn",
}
m["ill"] = {
"Iranun",
12953581,
"phi",
"Latn, Arab",
}
m["ilo"] = {
"tiếng Ilokano",
35936,
"phi",
"Latn, Tglg",
"Tiếng Ilokano",
"Ilokano",
translit = {
Tglg = "ilo-translit",
},
override_translit = true,
entry_name = {
Latn = {
remove_diacritics = c.grave .. c.acute .. c.circ .. c.diaer,
}
},
sort_key = {
Latn = "tl-sortkey",
},
standardChars = {
Latn = "AaBbKkDdEeGgHhIiLlMmNnOoPpRrSsTtUuWwYy" .. c.punc,
},
}
m["ils"] = {
"International Sign",
35754,
"sgn",
}
m["ilu"] = {
"Ili'uun",
12632888,
"poz-tim",
}
m["ilv"] = {
"Ilue",
3813301,
"nic-lcr",
"Latn",
}
m["ima"] = {
"Mala Malasar",
6740693,
"dra-tam",
}
m["imi"] = {
"Anamgura",
3501881,
"ngf-mad",
}
m["iml"] = {
"Miluk",
3314550,
"nai-coo",
"Latn",
}
m["imn"] = {
"Imonda",
6005721,
"paa-brd",
}
m["imo"] = {
"Imbongu",
12632895,
"ngf-mad",
}
m["imr"] = {
"Imroing",
6008394,
"poz-tim",
}
m["ims"] = {
"tiếng Marsi",
1265446,
"itc-sbl",
"Latn, Ital",
"Tiếng Marsi",
"Marsi",
translit = {Ital = "Ital-translit"},
}
m["imy"] = {
"Milyan",
3832946,
"ine-luw",
"Lyci",
}
m["inb"] = {
"Inga",
35491,
"qwe",
ancestors = "qwe-kch",
}
m["ing"] = {
"tiếng Deg Xinag",
27782,
"ath-nor",
nil,
"Tiếng Deg Xinag",
"Deg Xinag",
}
m["inh"] = {
"tiếng Ingush",
33509,
"cau-vay",
"Cyrl, Latn, Arab",
"Tiếng Ingush",
"Ingush",
translit = {
Cyrl = "cau-nec-translit",
Arab = "ar-translit",
},
override_translit = true,
display_text = {Cyrl = s["cau-Cyrl-displaytext"]},
entry_name = {
Cyrl = s["cau-Cyrl-entryname"],
Latn = s["cau-Latn-entryname"],
},
sort_key = {
Cyrl = {
from = {"аь", "гӏ", "ё", "кх", "къ", "кӏ", "пӏ", "тӏ", "хь", "хӏ", "цӏ", "чӏ", "яь"},
to = {"а" .. p[1], "г" .. p[1], "е" .. p[1], "к" .. p[1], "к" .. p[2], "к" .. p[3], "п" .. p[1], "т" .. p[1], "х" .. p[1], "х" .. p[2], "ц" .. p[1], "ч" .. p[1], "я" .. p[1]}
},
},
}
m["inj"] = {
"Jungle Inga",
16115012,
"qwe",
ancestors = "qwe-kch",
}
m["inl"] = {
"Indonesian Sign Language",
3915477,
"sgn",
"Latn", -- when documented
}
m["inm"] = {
"Minaean",
737784,
"sem-osa",
"Sarb",
translit = "Sarb-translit",
}
m["inn"] = {
"Isinai",
6081098,
"phi",
}
m["ino"] = {
"Inoke-Yate",
6036531,
"paa-kag",
}
m["inp"] = {
"Iñapari",
15338035,
"awd",
"Latn",
}
m["ins"] = {
"Indian Sign Language",
12953486,
"sgn",
}
m["int"] = {
"tiếng Intha",
6057507,
"tbq-brm",
"Mymr",
"Tiếng Intha",
"Intha",
ancestors = "obr",
}
m["inz"] = {
"Ineseño",
35443,
"nai-chu",
"Latn",
}
m["ior"] = {
"tiếng Inor",
35763,
"sem-eth",
"Ethi",
"Tiếng Inor",
"Inor",
}
m["iou"] = {
"Tuma-Irumu",
7852460,
"ngf-fin",
"Latn",
}
m["iow"] = {
"tiếng Chiwere",
56737,
"sio-msv",
"Latn",
"Tiếng Chiwere",
"Chiwere",
}
m["ipi"] = {
"Ipili",
6065141,
"paa-eng",
}
m["ipo"] = {
"Ipiko",
10566515,
"ngf",
}
m["iqu"] = {
"Iquito",
2669184,
"sai-zap",
"Latn",
}
m["iqw"] = {
"Ikwo",
11926474,
"alv-igb",
"Latn",
ancestors = "izi",
}
m["ire"] = {
"Iresim",
6069398,
"poz-hce",
"Latn",
}
m["irh"] = {
"Irarutu",
3027928,
"poz-cet",
"Latn",
}
m["iri"] = {
"Rigwe",
3912756,
"nic-plc",
"Latn",
}
m["irk"] = {
"tiếng Iraqw",
33595,
"cus-sou",
"Latn",
"Tiếng Iraqw",
"Iraqw",
}
m["irn"] = {
"Irantxe",
3409301,
nil,
"Latn",
}
m["irr"] = {
"Ir",
3071880,
"mkh-kat",
}
m["iru"] = {
"tiếng Irula",
33363,
"dra-imd",
"Taml",
"Tiếng Irula",
"Irula",
translit = "ta-translit"
}
m["irx"] = {
"Kamberau",
6356317,
"ngf",
}
m["iry"] = {
"Iraya",
6068356,
"phi",
}
m["isa"] = {
"Isabi",
11732247,
"paa-kag",
}
m["isc"] = {
"Isconahua",
3052971,
"sai-pan",
"Latn",
}
m["isd"] = {
"tiếng Isnag",
6085162,
"phi",
"Latn",
"Tiếng Isnag",
"Isnag",
}
m["ise"] = {
"Italian Sign Language",
375619,
"sgn",
"Latn", -- when documented
}
m["isg"] = {
"Irish Sign Language",
14183,
"sgn",
"Latn", -- when documented
}
m["ish"] = {
"tiếng Esan",
35268,
"alv-eeo",
"Latn",
"Tiếng Esan",
"Esan",
}
m["isi"] = {
"Nkem-Nkum",
36261,
"nic-eko",
"Latn",
}
m["isk"] = {
"tiếng Ishkashim",
33419,
"ira-sgi",
"Cyrl, Latn",
"Tiếng Ishkashim",
"Ishkashim",
}
m["ism"] = {
"Masimasi",
6783273,
"poz-ocw",
"Latn",
}
m["isn"] = {
"Isanzu",
6078891,
"bnt-tkm",
"Latn",
}
m["iso"] = {
"tiếng Isoko",
35414,
"alv-swd",
"Latn",
"Tiếng Isoko",
"Isoko",
}
m["isr"] = {
"Israeli Sign Language",
2911863,
"sgn",
"Sgnw",
}
m["ist"] = {
"tiếng Istria",
35845,
"roa-itd",
"Latn",
"Tiếng Istria",
"Istria",
}
m["isu"] = {
"Isu",
6089423,
"nic-rnw",
"Latn",
}
m["itb"] = {
"Binongan Itneg",
12953584,
"phi",
}
m["itd"] = {
"Southern Tidong",
7049643,
"poz-san",
}
m["ite"] = {
"Itene",
3038640,
"sai-cpc",
"Latn",
}
m["iti"] = {
"Inlaod Itneg",
12953585,
"phi",
}
m["itk"] = {
"tiếng Ý-Do Thái",
1145414,
"roa-itd",
"Hebr, Latn",
"Tiếng Ý-Do Thái",
"Ý-Do Thái",
}
m["itl"] = {
"tiếng Itelmen",
33624,
"qfa-cka",
"Cyrl, Latn",
"Tiếng Itelmen",
"Itelmen",
entry_name = {
Cyrl = {
from = {"['’]", "[ӅԮ]", "[ӆԯ]", "Ҳ", "ҳ"},
to = {"ʼ", "Ԓ", "ԓ", "Ӽ", "ӽ"}
},
},
sort_key = {
Cyrl = {
from = {
"ӑ", "ё", "кʼ", "ӄʼ", "о̆", "пʼ", "тʼ", "ў", "чʼ", -- 2 chars
"ӄ", "љ", "ԓ", "њ", "ӈ", "ӽ", "ә" -- 1 char
},
to = {
"а" .. p[1], "е" .. p[1], "к" .. p[1], "к" .. p[3], "о" .. p[1], "п" .. p[1], "т" .. p[1], "у" .. p[1], "ч" .. p[1],
"к" .. p[2], "л" .. p[1], "л" .. p[2], "н" .. p[1], "н" .. p[2], "х" .. p[1], "ь" .. p[1]
}
},
},
}
m["itm"] = {
"tiếng Itu Mbon Uzo",
10977737,
"nic-ief",
"Latn",
ancestors = "ibr",
"Tiếng Itu Mbon Uzo",
"Itu Mbon Uzo",
}
m["ito"] = {
"tiếng Itonama",
950585,
"qfa-iso",
"Latn",
"Tiếng Itonama",
"Itonama",
}
m["itr"] = {
"Iteri",
2083185,
"paa-asa",
}
m["its"] = {
"tiếng Itsekiri",
36045,
"alv-edk",
"Latn",
"Tiếng Itsekiri",
"Itsekiri",
entry_name = {Latn = {remove_diacritics = c.grave .. c.acute .. c.macron}},
sort_key = {
remove_diacritics = c.tilde,
from = {"ẹ", "gb", "gh", "kp", "ọ", "ts", "ṣ"},
to = {"e" .. p[1], "g" .. p[1], "g" .. p[2], "k" .. p[1], "o" .. p[1], "t" .. p[1], "t" .. p[1]}
},
}
m["itt"] = {
"Maeng Itneg",
18748761,
"phi",
}
m["itv"] = {
"Itawit",
3915527,
"phi",
"Latn",
}
m["itw"] = {
"Ito",
11128810,
"nic-ief",
ancestors = "ibr",
}
m["itx"] = {
"Itik",
6094713,
"paa-tkw",
}
m["ity"] = {
"Moyadan Itneg",
12953583,
"phi",
}
m["itz"] = {
"Itzá",
35537,
"myn",
}
m["ium"] = {
"tiếng Ưu Miền",
2498808,
"hmx-mie",
nil,
"Tiếng Ưu Miền",
"Ưu Miền",
}
m["ivb"] = {
"tiếng Ibatan",
18748212,
"phi",
"Latn",
"Tiếng Ibatan",
"Ibatan",
ancestors = "phi-pro,poz-pro",
}
m["ivv"] = {
"tiếng Ivatan",
3547080,
"phi",
"Latn",
"Tiếng Ivatan",
"Ivatan",
}
m["iwk"] = {
"I-Wak",
12632789,
"phi",
}
m["iwm"] = {
"Iwam",
3915215,
"paa-spk",
}
m["iwo"] = {
"Iwur",
6101006,
"ngf-okk",
}
m["iws"] = {
"Sepik Iwam",
16893603,
"paa-spk",
}
m["ixc"] = {
"Ixcatec",
56706,
"omq",
}
m["ixl"] = {
"tiếng Ixil",
35528,
"myn",
"Latn",
"Tiếng Ixil",
"Ixil",
}
m["iya"] = {
"Iyayu",
3913390,
"alv-nwd",
"Latn",
}
m["iyo"] = {
"tiếng Mesaka",
36080,
"nic-tiv",
"Latn",
"Tiếng Mesaka",
"Mesaka",
}
m["iyx"] = {
"Yaa",
36909,
"bnt-nze",
"Latn",
}
m["izh"] = {
"tiếng Ingria",
33559,
"urj-fin",
"Latn",
"Tiếng Ingria",
"Ingria",
sort_key = {
from = {
"š", "ž",
},
to = {
"s" .. p[1], "z" .. p[1],
}
},
}
m["izi"] = {
"Izi-Ezaa-Ikwo-Mgbo",
nil,
"alv-igb",
}
m["izr"] = {
"Izere",
6101921,
"nic-plc",
"Latn",
}
m["izz"] = {
"Izi",
3914387,
"alv-igb",
"Latn",
ancestors = "izi",
}
return require("Module:languages").finalizeData(m, "language")
nl8ya3nkye0tw6c0wvybmz551n3x3f7
ᦀᦱᧃᧈᦵᦉᧂ
0
276842
2344489
2090131
2026-04-12T11:54:00Z
Hiyuune
50834
2344489
wikitext
text/x-wiki
=={{langname|khb}}==
==={{section|etym}}===
Từ {{affix|khb|ᦀᦱᧃᧈ|ᦵᦉᧂ}}.
==={{section|pron}}===
{{khb-pron|ᦀᦱᧃᧈ-ᦵᦉᧂ}}
==={{section|n}}===
{{khb-noun}}
# Cách [[phát âm]].
==={{section|ref}}===
* {{R:khb:Hanna}}
{{C|khb|Âm vị học}}
kq5g61df5a7zpipc146ij14xozs0hh9
luông
0
278750
2344467
2286155
2026-04-12T09:25:23Z
WhoAlone
40420
2344467
wikitext
text/x-wiki
=={{langname|mng}}==
==={{ĐM|noun}}===
{{head|mng|Danh từ}}
# {{label|mng|Rơlơm}} [[củi]].
==={{ĐM|ref}}===
* Blood, Evangeline; Blood, Henry (1972) ''Vietnam word list (revised): Mnong Rolom''. SIL International.
{{-aav-tam-}}
{{-noun-}}
{{head|aav-tam|Danh từ}}
# [[củi]].
{{-ref-}}
* Phan Trần Công (2017). Tương ứng từ vựng và mối quan hệ giữa các ngôn ngữ trong nhóm Bahnar Nam. Tạp chí Phát triển Khoa học và Công nghệ: Chuyên san Khoa học xã hội và Nhân văn, tập 1, số 4, 2017.
{{-tyz-}}
{{-pron-}}
{{tyz-IPA}}
{{-adj-}}
{{pn}}
# [[to lớn]].
{{-ref-}}
{{R:Lương Bèn}}
{{catname|Tính từ|tiếng Tày}}
=={{langname|tdr}}==
==={{ĐM|noun}}===
{{head|tdr|Danh từ}}
# {{label|tdr|Didrá}} [[cây]].
==={{ĐM|ref}}===
* Gregerson, Kenneth J. và Smith, Kenneth D. (1973). ''The development of Todrah register''. SIL International.
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# {{label|sed|dialectal}} [[cây]].
==={{đm|ref}}===
{{R:VOV}}
kuz7ibhe1bf85u5pgn1ynla15cqd4vq
Mô đun:languages/data/exceptional
828
279282
2344293
2343455
2026-04-11T15:00:36Z
TheHighFighter2
42988
2344293
Scribunto
text/plain
local m_langdata = require("Module:languages/data")
-- Loaded on demand, as it may not be needed (depending on the data).
local function u(...)
u = require("Module:string utilities").char
return u(...)
end
local c = m_langdata.chars
local p = m_langdata.puaChars
local s = m_langdata.shared
local m = {}
m["aav-bhu"] = {
"tiếng Bhumij",
57920059,
"mun",
nil,
"Tiếng Bhumij",
"Bhumij",
}
m["aav-khs-pro"] = {
"tiếng Khasi nguyên thủy",
nil,
"aav-khs",
"Latn",
"Tiếng Khasi nguyên thủy",
"Khasi nguyên thủy",
type = "reconstructed",
}
m["aav-nic-pro"] = {
"tiếng Nicobar nguyên thủy",
nil,
"aav-nic",
"Latn",
"Tiếng Nicobar nguyên thủy",
"Nicobar nguyên thủy",
type = "reconstructed",
}
m["aav-pkl-pro"] = {
"tiếng Pnar-Khasi-Lyngngam nguyên thủy",
nil,
"aav-pkl",
"Latn",
"Tiếng Pnar-Khasi-Lyngngam nguyên thủy",
"Pnar-Khasi-Lyngngam nguyên thủy",
type = "reconstructed",
}
m["aav-pro"] = { --The mkh-pro will merge into this.
"tiếng Nam Á nguyên thủy",
nil,
"aav",
"Latn",
"Tiếng Nam Á nguyên thủy",
"Nam Á nguyên thủy",
type = "reconstructed",
}
m["aav-tam"] = {
"tiếng Tà Mun",
130370566,
"mkh-ban",
nil,
"Tiếng Tà Mun",
"Tà Mun",
}
m["afa-pro"] = {
"tiếng Phi-Á nguyên thủy",
269125,
"afa",
"Latn",
"Tiếng Phi-Á nguyên thủy",
"Phi-Á nguyên thủy",
type = "reconstructed",
}
m["alg-aga"] = {
"tiếng Agawam",
nil,
"alg-eas",
"Latn",
"Tiếng Agawam",
"Agawam",
}
m["alg-pro"] = {
"tiếng Algonquin nguyên thủy",
7251834,
"alg",
"Latn",
"Tiếng Algonquin nguyên thủy",
"Algonquin nguyên thủy",
type = "reconstructed",
sort_key = {remove_diacritics = "·"},
}
m["alv-ama"] = {
"Amasi",
4740400,
"nic-grs",
"Latn",
entry_name = {remove_diacritics = c.grave .. c.acute .. c.circ .. c.tilde .. c.macron},
}
m["alv-bgu"] = {
"Baïnounk Gubëeher",
17002646,
"alv-bny",
"Latn",
}
m["alv-bua-pro"] = {
"Proto-Bua",
nil,
"alv-bua",
"Latn",
type = "reconstructed",
}
m["alv-cng-pro"] = {
"Proto-Cangin",
nil,
"alv-cng",
"Latn",
type = "reconstructed",
}
m["alv-edo-pro"] = {
"tiếng Edoid nguyên thủy",
nil,
"alv-edo",
"Latn",
"Tiếng Edoid nguyên thủy",
"Edoid nguyên thủy",
type = "reconstructed",
}
m["alv-fli-pro"] = {
"Proto-Fali",
nil,
"alv-fli",
"Latn",
type = "reconstructed",
}
m["alv-gbe-pro"] = {
"tiếng Gbe nguyên thủy",
nil,
"alv-gbe",
"Latn",
"Tiếng Gbe nguyên thủy",
"Gbe nguyên thủy",
type = "reconstructed",
}
m["alv-gng-pro"] = {
"Proto-Guang",
nil,
"alv-gng",
"Latn",
type = "reconstructed",
}
m["alv-gtm-pro"] = {
"Proto-Central Togo",
nil,
"alv-gtm",
"Latn",
type = "reconstructed",
}
m["alv-gwa"] = {
"Gwara",
16945580,
"nic-pla",
"Latn",
}
m["alv-hei-pro"] = {
"Proto-Heiban",
nil,
"alv-hei",
"Latn",
type = "reconstructed",
}
m["alv-ido-pro"] = {
"Proto-Idomoid",
nil,
"alv-ido",
"Latn",
type = "reconstructed",
}
m["alv-igb-pro"] = {
"Proto-Igboid",
nil,
"alv-igb",
"Latn",
type = "reconstructed",
}
m["alv-kwa-pro"] = {
"Proto-Kwa",
nil,
"alv-kwa",
"Latn",
type = "reconstructed",
}
m["alv-mum-pro"] = {
"Proto-Mumuye",
nil,
"alv-mum",
"Latn",
type = "reconstructed",
}
m["alv-nup-pro"] = {
"Proto-Nupoid",
nil,
"alv-nup",
"Latn",
type = "reconstructed",
}
m["alv-pro"] = {
"tiếng Đại Tây Dương–Congo nguyên thủy",
nil,
"alv",
"Latn",
"Tiếng Đại Tây Dương–Congo nguyên thủy",
"Đại Tây Dương–Congo nguyên thủy",
type = "reconstructed",
}
m["alv-edk-pro"] = {
"tiếng Edekiri nguyên thủy",
nil,
"alv-edk",
"Latn",
"Tiếng Edekiri nguyên thủy",
"Edekiri nguyên thủy",
type = "reconstructed",
}
m["alv-yor-pro"] = {
"tiếng Yoruba nguyên thủy",
nil,
"alv-yor",
"Latn",
"Tiếng Yoruba nguyên thủy",
"Yoruba nguyên thủy",
type = "reconstructed",
}
m["alv-yrd-pro"] = {
"tiếng Yorubo nguyên thủy",
116773824,
"alv-yrd",
"Latn",
"Tiếng Yorubo nguyên thủy",
"Yorubo nguyên thủy",
type = "reconstructed",
}
m["alv-von-pro"] = {
"tiếng Volta-Niger nguyên thủy",
nil,
"alv-von",
"Latn",
"Tiếng Volta-Niger nguyên thủy",
"Volta-Niger nguyên thủy",
type = "reconstructed",
}
m["apa-pro"] = {
"Proto-Apachean",
nil,
"apa",
"Latn",
type = "reconstructed",
}
m["aql-pro"] = {
"tiếng Algic nguyên thủy",
18389588,
"aql",
"Latn",
"Tiếng Algic nguyên thủy",
"Algic nguyên thủy",
type = "reconstructed",
sort_key = {remove_diacritics = "·"},
}
m["art-blk"] = {
"Bolak",
2909283,
"art",
"Latn",
type = "appendix-constructed",
}
m["art-bsp"] = {
"Black Speech",
686210,
"art",
"Latn, Teng",
type = "appendix-constructed",
}
m["art-com"] = {
"Communicationssprache",
35227,
"art",
"Latn",
type = "appendix-constructed",
}
m["art-dtk"] = {
"Dothraki",
2914733,
"art",
"Latn",
type = "appendix-constructed",
}
m["art-elo"] = {
"Eloi",
nil,
"art",
"Latn",
type = "appendix-constructed",
}
m["art-gld"] = {
"Goa'uld",
19823,
"art",
"Latn, Egyp, Mero",
type = "appendix-constructed",
}
m["art-lap"] = {
"Lapine",
6488195,
"art",
"Latn",
type = "appendix-constructed",
}
m["art-man"] = {
"Mandalorian",
54289,
"art",
"Latn",
type = "appendix-constructed",
}
m["art-mun"] = {
"Mundolinco",
851355,
"art",
"Latn",
type = "appendix-constructed",
}
m["art-nav"] = {
"Na'vi",
316939,
"art",
"Latn",
type = "appendix-constructed",
}
m["art-nox"] = {
"Noxilo",
nil,
"art",
"Latn",
type = "appendix-constructed",
}
m["art-una"] = {
"Unas",
nil,
"art",
"Latn",
type = "appendix-constructed",
}
m["ath-nic"] = {
"Nicola",
20609,
"ath-nor",
"Latn",
}
m["ath-pro"] = {
"tiếng Athabasca nguyên thủy",
104841722,
"ath",
"Latn",
type = "reconstructed",
"Tiếng Athabasca nguyên thủy",
"Athabasca nguyên thủy",
}
m["auf-pro"] = {
"Proto-Arawa",
nil,
"auf",
"Latn",
type = "reconstructed",
}
m["aus-alu"] = {
"Alungul",
16827670,
"aus-pmn",
"Latn",
}
m["aus-and"] = {
"Andjingith",
4754509,
"aus-pmn",
"Latn",
}
m["aus-ang"] = {
"tiếng Angkula",
16828520,
"aus-pmn",
"Latn",
"Tiếng Angkula",
"Angkula",
}
m["aus-arn-pro"] = {
"Proto-Arnhem",
nil,
"aus-arn",
"Latn",
type = "reconstructed",
}
m["aus-bra"] = {
"Barranbinya",
4863220,
"aus-pmn",
"Latn",
}
m["aus-brm"] = {
"Barunggam",
4865914,
"aus-pmn",
"Latn",
}
m["aus-cww-pro"] = {
"Proto-Central New South Wales",
nil,
"aus-cww",
"Latn",
type = "reconstructed",
}
m["aus-dal-pro"] = {
"Proto-Daly",
nil,
"aus-dal",
"Latn",
type = "reconstructed",
}
m["aus-guw"] = {
"Guwar",
6652138,
"aus-pam",
"Latn",
}
m["aus-lsw"] = {
"Little Swanport",
6652138,
nil,
"Latn",
}
m["aus-mbi"] = {
"Mbiywom",
6799701,
"aus-pmn",
"Latn",
}
m["aus-ngk"] = {
"Ngkoth",
7022405,
"aus-pmn",
"Latn",
}
m["aus-nyu-pro"] = {
"Proto-Nyulnyulan",
nil,
"aus-nyu",
"Latn",
type = "reconstructed",
}
m["aus-pam-pro"] = {
"tiếng Pama-Nyungar nguyên thủy",
33942,
"aus-pam",
"Latn",
"Tiếng Pama-Nyungar nguyên thủy",
"Pama-Nyungar nguyên thủy",
type = "reconstructed",
}
m["aus-tul"] = {
"Tulua",
16938541,
"aus-pam",
"Latn",
}
m["aus-uwi"] = {
"Uwinymil",
7903995,
"aus-arn",
"Latn",
}
m["aus-wdj-pro"] = {
"Proto-Iwaidjan",
nil,
"aus-wdj",
"Latn",
type = "reconstructed",
}
m["aus-won"] = {
"Wong-gie",
nil,
"aus-pam",
"Latn",
}
m["aus-wul"] = {
"Wulguru",
8039196,
"aus-dyb",
"Latn",
}
m["aus-ynk"] = { -- contrast nny
"Yangkaal",
3913770,
"aus-tnk",
"Latn",
}
m["awd-amc-pro"] = {
"Proto-Amuesha-Chamicuro",
nil,
"awd",
"Latn",
type = "reconstructed",
ancestors = "awd-pro",
}
m["awd-kmp-pro"] = {
"Proto-Kampa",
nil,
"awd",
"Latn",
type = "reconstructed",
ancestors = "awd-pro",
}
m["awd-prw-pro"] = {
"Proto-Paresi-Waura",
nil,
"awd",
"Latn",
type = "reconstructed",
ancestors = "awd-pro",
}
m["awd-ama"] = {
"Amarizana",
16827787,
"awd",
"Latn",
}
m["awd-ana"] = {
"tiếng Anauyá",
16828252,
"awd",
"Latn",
"Tiếng Anauyá",
"Anauyá",
}
m["awd-apo"] = {
"Apolista",
16916645,
"awd",
"Latn",
}
m["awd-cav"] = {
"Cavere",
nil,
"awd",
"Latn",
}
m["awd-gnu"] = {
"Guinau",
3504087,
"awd",
"Latn",
}
m["awd-kar"] = {
"Cariay",
16920253,
"awd",
"Latn",
}
m["awd-kaw"] = {
"Kawishana",
6379993,
"awd-nwk",
"Latn",
}
m["awd-kus"] = {
"Kustenau",
5196293,
"awd",
"Latn",
}
m["awd-man"] = {
"Manao",
6746920,
"awd",
"Latn",
}
m["awd-mar"] = {
"Marawan",
6755108,
"awd",
"Latn",
}
m["awd-mpr"] = {
"Maypure",
nil,
"awd",
"Latn",
}
m["awd-mrt"] = {
"Mariaté",
16910017,
"awd-nwk",
"Latn",
}
m["awd-nwk-pro"] = {
"Proto-Nawiki",
nil,
"awd-nwk",
"Latn",
type = "reconstructed",
}
m["awd-pai"] = {
"Paikoneka",
nil,
"awd",
"Latn",
}
m["awd-pas"] = {
"Passé",
nil,
"awd-nwk",
"Latn",
}
m["awd-pro"] = {
"tiếng Arawak nguyên thủy",
nil,
"awd",
"Latn",
"Tiếng Arawak nguyên thủy",
"Arawak nguyên thủy",
type = "reconstructed",
}
m["awd-she"] = {
"tiếng Shebayo",
7492248,
"awd",
"Latn",
"Tiếng Shebayo",
"Shebayo"
}
m["awd-taa-pro"] = {
"Proto-Ta-Arawak",
nil,
"awd-taa",
"Latn",
type = "reconstructed",
}
m["awd-wai"] = {
"Wainumá",
16910017,
"awd-nwk",
"Latn",
}
m["awd-yum"] = {
"Yumana",
8061062,
"awd-nwk",
"Latn",
}
m["azc-caz"] = {
"Cazcan",
5055514,
"azc",
"Latn",
}
m["azc-cup-pro"] = {
"Proto-Cupan",
nil,
"azc-cup",
"Latn",
type = "reconstructed",
}
m["azc-ktn"] = {
"Kitanemuk",
3197558,
"azc-tak",
"Latn",
}
m["azc-nah-pro"] = {
"tiếng Nahua nguyên thủy",
7251860,
"azc-nah",
"Latn",
"Tiếng Nahua nguyên thủy",
"Nahua nguyên thủy",
type = "reconstructed",
}
m["azc-num-pro"] = {
"Proto-Numic",
nil,
"azc-num",
"Latn",
type = "reconstructed",
}
m["azc-pro"] = {
"tiếng Ute-Aztec nguyên thủy",
96400333,
"azc",
"Latn",
"Tiếng Ute-Aztec nguyên thủy",
"Ute-Aztec nguyên thủy",
type = "reconstructed",
}
m["azc-tak-pro"] = {
"Proto-Takic",
nil,
"azc-tak",
"Latn",
type = "reconstructed",
}
m["azc-tat"] = {
"Tataviam",
743736,
"azc",
"Latn",
}
m["ber-pro"] = {
"tiếng Berber nguyên thủy",
2855698,
"ber",
"Latn",
"Tiếng Berber nguyên thủy",
"Berber nguyên thủy",
type = "reconstructed",
}
m["ber-fog"] = {
"tiếng Fogaha",
107610173,
"ber",
"Latn",
"Tiếng Fogaha",
"Fogaha",
}
m["ber-zuw"] = {
"Zuwara",
4117169,
"ber",
"Latn",
}
m["bnt-bal"] = {
"Balong",
93935237,
"bnt-bbo",
"Latn",
}
m["bnt-bon"] = {
"Boma Nkuu",
nil,
"bnt",
"Latn",
}
m["bnt-boy"] = {
"Boma Yumu",
nil,
"bnt",
"Latn",
}
m["bnt-bwa"] = {
"Bwala",
nil,
"bnt-tek",
"Latn",
}
m["bnt-cmw"] = {
"Chimwiini",
4958328,
"bnt-swh",
"Latn",
}
m["bnt-ind"] = {
"Indanga",
51412803,
"bnt",
"Latn",
}
m["bnt-lal"] = {
"Lala (South Africa)",
6480154,
"bnt-ngu",
"Latn",
}
m["bnt-lwl"] = {
"Lwel",
93936908,
"bnt-bdz",
"Latn",
}
m["bnt-mpi"] = {
"Mpiin",
93937013,
"bnt-bdz",
"Latn",
}
m["bnt-mpu"] = {
"Mpuono", --not to be confused with Mbuun zmp
36056,
"bnt",
"Latn",
}
m["bnt-ngu-pro"] = {
"tiếng Nguni nguyên thủy",
961559,
"bnt-ngu",
"Latn",
"Tiếng Nguni nguyên thủy",
"Nguni nguyên thủy",
type = "reconstructed",
sort_key = {remove_diacritics = c.grave .. c.acute .. c.circ .. c.caron},
}
m["bnt-phu"] = {
"Phuthi",
33796,
"bnt-ngu",
"Latn",
entry_name = {remove_diacritics = c.grave .. c.acute},
}
m["bnt-pro"] = {
"tiếng Bantu nguyên thủy",
3408025,
"bnt",
"Latn",
"Tiếng Bantu nguyên thủy",
"Bantu nguyên thủy",
type = "reconstructed",
sort_key = "bnt-pro-sortkey",
}
m["bnt-sbo"] = {
"South Boma",
nil,
"bnt",
"Latn",
}
m["bnt-sts-pro"] = {
"Proto-Sotho-Tswana",
nil,
"bnt-sts",
"Latn",
type = "reconstructed",
}
m["btk-pro"] = {
"Proto-Batak",
nil,
"btk",
"Latn",
type = "reconstructed",
}
m["cau-abz-pro"] = {
"tiếng Abkhaz-Abaza nguyên thủy",
7251831,
"cau-abz",
"Latn",
"Tiếng Abkhaz-Abaza nguyên thủy",
"Abkhaz-Abaza nguyên thủy",
type = "reconstructed",
}
m["cau-ava-pro"] = {
"tiếng Avar-Andic nguyên thủy",
116773187,
"cau-ava",
"Latn",
"Tiếng Avar-Andic nguyên thủy",
"Avar-Andic nguyên thủy",
type = "reconstructed",
}
m["cau-cir-pro"] = {
"tiếng Circassia nguyên thủy",
7251838,
"cau-cir",
"Latn",
"Tiếng Circassia nguyên thủy",
"Circassia nguyên thủy",
type = "reconstructed",
}
m["cau-drg-pro"] = {
"tiếng Dargwa nguyên thủy",
nil,
"cau-drg",
"Latn",
"Tiếng Dargwa nguyên thủy",
"Dargwa nguyên thủy",
type = "reconstructed",
}
m["cau-lzg-pro"] = {
"tiếng Lezghi nguyên thủy",
nil,
"cau-lzg",
"Latn",
"Tiếng Lezghi nguyên thủy",
"Lezghi nguyên thủy",
type = "reconstructed",
}
m["cau-nec-pro"] = {
"tiếng Đông Bắc Kavkaz nguyên thủy",
nil,
"cau-nec",
"Latn",
"Tiếng Đông Bắc Kavkaz nguyên thủy",
"Đông Bắc Kavkaz nguyên thủy",
type = "reconstructed",
}
m["cau-nkh-pro"] = {
"tiếng Nakh nguyên thủy",
nil,
"cau-nkh",
"Latn",
"Tiếng Nakh nguyên thủy",
"Nakh nguyên thủy",
type = "reconstructed",
}
m["cau-nwc-pro"] = {
"tiếng Tây Bắc Kavkaz nguyên thủy",
7251861,
"cau-nwc",
"Latn",
"Tiếng Tây Bắc Kavkaz nguyên thủy",
"Tây Bắc Kavkaz nguyên thủy",
type = "reconstructed",
}
m["cau-tsz-pro"] = {
"Proto-Tsezian",
nil,
"cau-tsz",
"Latn",
type = "reconstructed",
}
m["cba-ata"] = {
"Atanques",
4812783,
"cba",
"Latn",
}
m["cba-cat"] = {
"Catío Chibcha",
7083619,
"cba",
"Latn",
}
m["cba-dor"] = {
"Dorasque",
5297532,
"cba",
"Latn",
}
m["cba-dui"] = {
"Duit",
3041061,
"cba",
"Latn",
}
m["cba-hue"] = {
"Huetar",
35514,
"cba",
"Latn",
}
m["cba-nut"] = {
"Nutabe",
7070405,
"cba",
"Latn",
}
m["cba-pro"] = {
"Proto-Chibchan",
nil,
"cba",
"Latn",
type = "reconstructed",
}
m["ccn-pro"] = {
"Proto-North Caucasian",
nil,
"ccn",
"Latn",
type = "reconstructed",
}
m["ccs-pro"] = {
"tiếng Kartvelia nguyên thủy",
2608203,
"ccs",
"Latn",
type = "reconstructed",
"Tiếng Kartvelia nguyên thủy",
"Kartvelia nguyên thủy",
entry_name = {
from = {"q̣", "p̣", "ʓ", "ċ"},
to = {"q̇", "ṗ", "ʒ", "c̣"}
},
}
m["ccs-gzn-pro"] = {
"tiếng Gruzia-Zan nguyên thủy",
23808119,
"ccs-gzn",
"Latn",
"Tiếng Gruzia-Zan nguyên thủy",
"Gruzia-Zan nguyên thủy",
type = "reconstructed",
entry_name = {
from = {"q̣", "p̣", "ʓ", "ċ"},
to = {"q̇", "ṗ", "ʒ", "c̣"}
},
}
m["cdc-cbm-pro"] = {
"Proto-Central Chadic",
nil,
"cdc-cbm",
"Latn",
type = "reconstructed",
}
m["cdc-mas-pro"] = {
"Proto-Masa",
nil,
"cdc-mas",
"Latn",
type = "reconstructed",
}
m["cdc-pro"] = {
"tiếng Tchad nguyên thủy",
nil,
"cdc",
"Latn",
"Tiếng Tchad nguyên thủy",
"Tchad nguyên thủy",
type = "reconstructed",
}
m["cdd-pro"] = {
"Proto-Caddoan",
nil,
"cdd",
"Latn",
type = "reconstructed",
}
m["cel-bry-pro"] = {
"tiếng Britton nguyên thủy",
156877,
"cel-bry",
"Latn, Grek",
"Tiếng Britton nguyên thủy",
"Britton nguyên thủy",
sort_key = "cel-bry-pro-sortkey",
}
m["cel-gal"] = {
"Gallaecian",
3094789,
"cel",
}
m["cel-gau"] = {
"tiếng Gaul",
29977,
"cel",
"Latn, Grek, Ital",
"Tiếng Gaul",
"Gaul",
entry_name = {remove_diacritics = c.macron .. c.breve .. c.diaer},
}
m["cel-pro"] = {
"tiếng Celt nguyên thủy",
653649,
"cel",
"Latn",
"Tiếng Celt nguyên thủy",
"Celt nguyên thủy",
sort_key = "cel-pro-sortkey",
}
m["chi-pro"] = {
"Proto-Chimakuan",
nil,
"chi",
"Latn",
type = "reconstructed",
}
m["chm-pro"] = {
"tiếng Mari nguyên thủy",
nil,
"chm",
"Latn",
"Tiếng Mari nguyên thủy",
"Mari nguyên thủy",
type = "reconstructed",
}
m["cmc-pro"] = {
"tiếng Chăm nguyên thủy",
nil,
"cmc",
"Latn",
"Tiếng Chăm nguyên thủy",
"Chăm nguyên thủy",
type = "reconstructed",
}
m["cpe-mar"] = {
"Maroon Spirit Language",
1093206,
"crp",
"Latn",
ancestors = "en",
}
m["cpe-spp"] = {
"Samoan Plantation Pidgin",
7409948,
"crp",
"Latn",
ancestors = "en",
}
m["crp-gep"] = {
"West Greenlandic Pidgin",
17036301,
"crp",
"Latn",
ancestors = "kl",
}
m["crp-mpp"] = {
"Macau Pidgin Portuguese",
nil,
"crp",
"Hant, Latn",
ancestors = "pt",
sort_key = {Hant = "Hani-sortkey"},
}
m["crp-rsn"] = {
"Russenorsk",
505125,
"crp",
"Cyrl, Latn",
ancestors = "nn, ru",
}
m["crp-slb"] = {
"tiếng Anh Solombala",
7558525,
"crp",
"Cyrl, Latn",
"Tiếng Anh Solombala",
"Anh Solombala",
ancestors = "en, ru",
}
m["crp-tpr"] = {
"tiếng Nga bồi Taimyr",
16930506,
"crp",
"Cyrl",
"Tiếng Nga bồi Taimyr",
"Nga bồi Taimyr",
ancestors = "ru",
}
m["csu-bba-pro"] = {
"Proto-Bongo-Bagirmi",
nil,
"csu-bba",
"Latn",
type = "reconstructed",
}
m["csu-maa-pro"] = {
"Proto-Mangbetu",
nil,
"csu-maa",
"Latn",
type = "reconstructed",
}
m["csu-pro"] = {
"Proto-Central Sudanic",
nil,
"csu",
"Latn",
type = "reconstructed",
}
m["csu-sar-pro"] = {
"Proto-Sara",
nil,
"csu-sar",
"Latn",
type = "reconstructed",
}
m["ctp-san"] = {
"San Juan Quiahije Chatino",
nil,
"omq-cha",
"Latn",
}
m["cus-ash"] = {
"tiếng Ashraaf",
4805855,
"cus-eas",
"Latn",
"Tiếng Ashraaf",
"Ashraaf",
}
m["cus-hec-pro"] = {
"Proto-Highland East Cushitic",
nil,
"cus-hec",
"Latn",
type = "reconstructed",
}
m["cus-som-pro"] = {
"tiếng Somali nguyên thủy",
nil,
"cus-som",
"Latn",
"Tiếng Somali nguyên thủy",
"Somali nguyên thủy",
type = "reconstructed",
}
m["cus-sou-pro"] = {
"Proto-South Cushitic",
126081567,
"cus-sou",
"Latn",
type = "reconstructed",
}
m["cus-pro"] = {
"tiếng Cushit nguyên thủy",
nil,
"cus",
"Latn",
"Tiếng Cushit nguyên thủy",
"Cushit nguyên thủy",
type = "reconstructed",
}
m["dmn-dam"] = {
"Dama (Sierra Leone)",
19601574,
"dmn",
"Latn",
}
m["dra-mkn"] = {
"Middle Kannada",
nil,
"dra",
"Knda",
ancestors = "dra-okn",
translit = "kn-translit",
}
m["dra-okn"] = {
"tiếng Kannada cổ",
15723156,
"dra",
"Knda",
"Tiếng Kannada cổ",
"Kannada cổ",
ancestors = "dra-pro",
translit = "kn-translit",
}
m["dra-ote"] = {
"tiếng Telugu cổ",
126720868,
"dra-tel",
"Telu",
"Tiếng Telugu cổ",
"Telugu cổ",
translit = "te-translit",
}
m["dra-pro"] = {
"tiếng Dravida nguyên thủy",
1702853,
"dra",
"Latn",
"Tiếng Dravida nguyên thủy",
"Dravida nguyên thủy",
type = "reconstructed",
}
m["dra-sdo-pro"] = {
"tiếng Nam Dravida nguyên thủy I",
104847952, -- Wikipedia's "Proto-South Dravidian" is Proto-South Dravidian I in this scheme.
"dra-sdo",
"Latn",
"Tiếng Nam Dravida nguyên thủy I",
"Nam Dravida nguyên thủy I",
type = "reconstructed",
}
m["dra-sdt-pro"] = {
"tiếng Nam Dravida nguyên thủy II",
128885257,
"dra-sdt",
"Latn",
"Tiếng Nam Dravida nguyên thủy II",
"Nam Dravida nguyên thủy II",
type = "reconstructed",
}
m["dra-sou-pro"] = {
"tiếng Nam Dravida nguyên thủy",
128886121,
"dra-sou",
"Latn",
"Tiếng Nam Dravida nguyên thủy",
"Nam Dravida nguyên thủy",
type = "reconstructed",
}
m["egx-dem"] = {
"tiếng Ai Cập bình dân",
36765,
"egx",
"Latn, Egyd, Polyt",
"Tiếng Ai Cập bình dân",
"Ai Cập bình dân",
display_text = {
Polyt = s["Polyt-displaytext"],
},
entry_name = {
Polyt = s["Polyt-entryname"],
},
sort_key = {
Latn = {
remove_diacritics = "'%-%s",
from = {"ꜣ", "j", "e", "ꜥ", "y", "w", "b", "p", "f", "m", "n", "r", "l", "ḥ", "ḫ", "h̭", "ẖ", "h", "š", "s", "q", "k", "g", "ṱ", "ṯ", "t", "ḏ", "%.", "⸗"},
to = {p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[15], p[16], p[16], p[17], p[14], p[19], p[18], p[20], p[21], p[22], p[23], p[24], p[23], p[25], p[26], p[26]}
},
Polyt = s["Polyt-sortkey"],
},
}
m["elu-prk"] = {
"Helu",
15080869,
"inc-mid",
"Brah",
ancestors = "inc-pra",
translit = "Brah-translit",
}
m["dmn-pro"] = {
"tiếng Mande nguyên thủy",
nil,
"dmn",
"Latn",
"Tiếng Mande nguyên thủy",
"Mande nguyên thủy",
type = "reconstructed",
}
m["dmn-mdw-pro"] = {
"Proto-Western Mande",
nil,
"dmn-mdw",
"Latn",
type = "reconstructed",
}
m["dru-pro"] = {
"tiếng Rukai nguyên thủy",
nil,
"map",
"Latn",
"Tiếng Rukai nguyên thủy",
"Rukai nguyên thủy",
type = "reconstructed",
}
m["ero-tau"] = {
"tiếng Stau",
nil,
"ero",
"Latn",
"Tiếng Stau",
"Stau",
}
m["esx-esk-pro"] = {
"tiếng Eskimo nguyên thủy",
7251842,
"esx-esk",
"Latn",
"Tiếng Eskimo nguyên thủy",
"Eskimo nguyên thủy",
type = "reconstructed",
}
m["esx-ink"] = {
"Inuktun",
1671647,
"esx-inu",
"Latn",
}
m["esx-inq"] = {
"Inuinnaqtun",
28070,
"esx-inu",
"Latn",
}
m["esx-inu-pro"] = {
"tiếng Inuit nguyên thủy",
60785588,
"esx-inu",
"Latn",
"Tiếng Inuit nguyên thủy",
"Inuit nguyên thủy",
type = "reconstructed",
}
m["esx-pro"] = {
"tiếng Eskimo-Aleut nguyên thủy",
7251843,
"esx",
"Latn",
"Tiếng Eskimo-Aleut nguyên thủy",
"Eskimo-Aleut nguyên thủy",
type = "reconstructed",
}
m["esx-tut"] = {
"Tunumiisut",
15665389,
"esx-inu",
"Latn",
}
m["euq-pro"] = {
"tiếng Basque nguyên thủy",
938011,
"euq",
"Latn",
"Tiếng Basque nguyên thủy",
"Basque nguyên thủy",
type = "reconstructed",
}
m["gem-bur"] = {
"Burgundian",
nil,
"gme",
"Latn",
}
m["gem-pro"] = {
"tiếng German nguyên thủy",
669623,
"gem",
"Latn",
"Tiếng German nguyên thủy",
"German nguyên thủy",
type = "reconstructed",
sort_key = "gem-pro-sortkey",
}
m["gme-cgo"] = {
"Crimean Gothic",
36211,
"gme",
"Latn",
}
m["gmq-bot"] = {
"Westrobothnian",
7989641,
"gmq",
"Latn",
ancestors = "non",
}
m["gmq-gut"] = {
"tiếng Gotland",
1256646,
"gmq",
"Latn",
"Tiếng Gotland",
"Gotland",
ancestors = "non",
}
m["gmq-jmk"] = {
"Jamtish",
nil,
"gmq",
"Latn",
ancestors = "non",
}
m["gmq-mno"] = {
"Middle Norwegian",
3417070,
"gmq",
"Latn",
ancestors = "non",
}
m["gmq-oda"] = {
"tiếng Đan Mạch cổ",
nil,
"gmq-eas",
"Latn, Runr",
"Tiếng Đan Mạch cổ",
"Đan Mạch cổ",
ancestors = "non",
entry_name = {remove_diacritics = c.macron},
}
m["gmq-osw"] = {
"tiếng Thụy Điển cổ",
2417210,
"gmq",
"Latn",
"Tiếng Thụy Điển cổ",
"Thụy Điển cổ",
ancestors = "non",
entry_name = {remove_diacritics = c.macron},
}
m["gmq-pro"] = {
"Proto-Norse",
1671294,
"gmq",
"Runr",
translit = "Runr-translit",
}
m["gmq-scy"] = {
"Scanian",
768017,
"gmq",
"Latn",
ancestors = "non",
}
m["gmw-bgh"] = {
"Bergish",
329030,
"gmw",
"Latn",
ancestors = "odt",
}
m["gmw-cfr"] = {
"tiếng Franken Trung",
nil,
"gmw",
"Latn",
"Tiếng Franken Trung",
"Franken Trung",
ancestors = "gmh",
wikimedia_codes = "ksh",
}
m["gmw-ecg"] = {
"tiếng Đức Đông Trung",
499344, -- subsumes Q699284, Q152965
"gmw",
"Latn",
"Tiếng Đức Đông Trung",
"Đức Đông Trung",
ancestors = "gmh",
}
m["gmw-gts"] = {
"Gottscheerish",
533109,
"gmw",
"Latn",
ancestors = "bar",
}
m["gmw-jdt"] = {
"tiếng Hà Lan Jersey",
1687911,
"gmw",
"Latn",
"Tiếng Hà Lan Jersey",
"Hà Lan Jersey",
ancestors = "nl",
}
m["gmw-pro"] = {
"tiếng German Tây nguyên thủy",
78079021,
"gmw",
"Latn",
"Tiếng German Tây nguyên thủy",
"German Tây nguyên thủy",
type = "reconstructed",
sort_key = "gmw-pro-sortkey",
wikipedia_article = "Chi ngôn ngữ German phía Tây"
}
m["gmw-rfr"] = {
"Rhine Franconian",
707007,
"gmw",
"Latn",
ancestors = "gmh",
}
m["gmw-stm"] = {
"Sathmar Swabian",
2223059,
"gmw",
"Latn",
ancestors = "swg",
}
m["gmw-tsx"] = {
"tiếng Saxon Transylvania",
260942,
"gmw",
"Latn",
"Tiếng Saxon Transylvania",
"Saxon Transylvania",
ancestors = "gmw-cfr",
}
m["gmw-vog"] = {
"Volga German",
312574,
"gmw",
"Latn",
ancestors = "gmw-rfr",
}
m["gmw-zps"] = {
"Zipser German",
205548,
"gmw",
"Latn",
ancestors = "gmh",
}
m["gn-cls"] = {
"Classical Guaraní",
17478065,
"tup-gua",
"Latn",
ancestors = "gn",
}
m["grk-cal"] = {
"Calabrian Greek",
1146398,
"grk",
"Latn",
ancestors = "grc",
}
m["grk-ita"] = {
"tiếng Hy Lạp Italiot",
nil,
"grk",
"Latn, Grek",
"Tiếng Hy Lạp Italiot",
"Hy Lạp Italiot",
ancestors = "grc",
entry_name = {remove_diacritics = c.caron .. c.diaerbelow .. c.brevebelow},
sort_key = s["Grek-sortkey"],
}
m["grk-mar"] = {
"tiếng Hy Lạp Mariupol",
4400023,
"grk",
"Cyrl, Latn, Grek",
ancestors = "grc",
translit = "grk-mar-translit",
override_translit = true,
entry_name = "grk-mar-entryname",
sort_key = s["Grek-sortkey"],
"Tiếng Hy Lạp Mariupol",
"Hy Lạp Mariupol",
}
m["grk-pro"] = {
"tiếng Hellen nguyên thủy",
1231805,
"grk",
"Latn",
"Tiếng Hellen nguyên thủy",
"Hellen nguyên thủy",
type = "reconstructed",
sort_key = {
from = {"[áā]", "[éēḗ]", "[íī]", "[óōṓ]", "[úū]", "ď", "ľ", "ň", "ř", "ʰ", "ʷ", c.acute, c.macron},
to = {"a", "e", "i", "o", "u", "d", "l", "n", "r", "¯h", "¯w"}
},
}
m["hmn-pro"] = {
"Proto-Hmong",
nil,
"hmn",
"Latn",
type = "reconstructed",
}
m["hmx-mie-pro"] = {
"tiếng Miền nguyên thủy",
nil,
"hmx-mie",
"Latn",
"Tiếng Miền nguyên thủy",
"Miền nguyên thủy",
type = "reconstructed",
}
m["hmx-pro"] = {
"tiếng H'Mông-Miền nguyên thủy",
7251846,
"hmx",
"Latn",
"Tiếng H'Mông-Miền nguyên thủy",
"H'Mông-Miền nguyên thủy",
type = "reconstructed",
}
m["hyx-pro"] = {
"Proto-Armenian",
3848498,
"hyx",
"Latn",
type = "reconstructed",
}
m["iir-nur-pro"] = {
"tiếng Nuristan nguyên thủy",
nil,
"iir-nur",
"Latn",
"Tiếng Nuristan nguyên thủy",
"Nuristan nguyên thủy",
type = "reconstructed",
}
m["iir-pro"] = {
"tiếng Ấn-Iran nguyên thủy",
966439,
"iir",
"Latn",
"Tiếng Ấn-Iran nguyên thủy",
"Ấn-Iran nguyên thủy",
type = "reconstructed",
}
m["ijo-pro"] = {
"Proto-Ijoid",
nil,
"ijo",
"Latn",
type = "reconstructed",
}
m["inc-apa"] = {
"tiếng Apabhramsa",
616419,
"inc-mid",
"Deva, Shrd, Sidd",
"Tiếng Apabhramsa",
"Apabhramsa",
ancestors = "pra",
translit = {
Deva = "sa-translit",
Shrd = "Shrd-translit",
Sidd = "Sidd-translit",
},
}
m["inc-ash"] = {
"tiếng Prakrit Ashoka",
nil,
"inc-mid",
"Brah, Khar",
"Tiếng Prakrit Ashoka",
"Prakrit Ashoka",
ancestors = "sa",
translit = {
Brah = "Brah-translit",
Khar = "Khar-translit",
},
}
m["inc-gup"] = {
"Gurjar Apabhramsa",
nil,
"inc-mid",
"Deva",
ancestors = "psu",
}
m["inc-kam"] = {
"tiếng Kamarupi Prakrit",
6356097,
"inc-mid",
"Brah, Sidd",
"Tiếng Kamarupi Prakrit",
"Kamarupi Prakrit",
ancestors = "inc-mgd",
}
m["inc-kha"] = {
"tiếng Khasa Prakrit",
nil,
"inc-nor",
"Latn",
"Tiếng Khasa Prakrit",
"Khasa Prakrit",
ancestors = "inc-pra",
}
m["inc-kho"] = {
"tiếng Kholosi",
24952008,
"inc-snd",
"Latn",
"Tiếng Kholosi",
"Kholosi",
ancestors = "inc-vra",
}
m["inc-mas"] = {
"Middle Assamese",
nil,
"inc-eas",
"as-Beng",
ancestors = "inc-oas",
translit = "inc-mas-translit",
}
m["inc-mbn"] = {
"Middle Bengali",
nil,
"inc-eas",
"Beng",
ancestors = "inc-obn",
translit = "inc-mbn-translit",
}
m["inc-mgd"] = {
"Magadhi Prakrit",
2652214,
"inc-mid",
"Brah",
ancestors = "inc-pra",
translit = "Brah-translit",
}
m["inc-mgu"] = {
"tiếng Gujarat trung đại",
24907429,
"inc-wes",
"Deva",
"Tiếng Gujarat trung đại",
"Gujarat trung đại",
ancestors = "inc-ogu",
}
m["inc-mor"] = {
"tiếng Oriya trung đại",
128810882,
"inc-eas",
"Orya",
"Tiếng Oriya trung đại",
"Oriya trung đại",
ancestors = "inc-oor",
}
m["inc-oas"] = {
"tiếng Assam cận đại",
nil,
"inc-bas",
"as-Beng",
"Tiếng Assam cận đại",
"Assam cận đại",
ancestors = "inc-kam",
translit = "inc-oas-translit",
}
m["inc-obn"] = {
"Old Bengali",
nil,
"inc-eas",
"Beng",
ancestors = "inc-mgd",
}
m["inc-ogu"] = {
"tiếng Gujarat cổ",
24907427,
"inc-wes",
"Deva",
"Tiếng Gujarat cổ",
"Gujarat cổ",
ancestors = "inc-gup",
translit = "sa-translit",
}
m["inc-ohi"] = {
"Old Hindi",
48767781,
"inc-hiw",
"Deva",
ancestors = "inc-sap",
translit = "sa-translit",
}
m["inc-oor"] = {
"tiếng Oriya cổ",
128807801,
"inc-eas",
"Orya",
"Tiếng Oriya cổ",
"Oriya cổ",
}
m["inc-opa"] = {
"Old Punjabi",
nil,
"inc-pan",
"Guru, pa-Arab",
ancestors = "inc-tak",
translit = {
Guru = "inc-opa-Guru-translit",
["pa-Arab"] = "pa-Arab-translit",
},
entry_name = {remove_diacritics = c.fathatan .. c.dammatan .. c.kasratan .. c.fatha .. c.damma .. c.kasra .. c.shadda .. c.sukun},
}
m["inc-ork"] = {
"Old Kamta",
nil,
"inc-eas",
"as-Beng",
ancestors = "inc-kam",
translit = "as-translit",
}
m["inc-pra"] = {
"tiếng Prakrit",
192170,
"inc",
"Brah, Deva, Knda",
"Tiếng Prakrit",
"Prakrit",
ancestors = "inc-ash",
translit = {
Brah = "Brah-translit",
Deva = "inc-pra-Deva-translit",
Knda = "inc-pra-Knda-translit",
},
entry_name = {
from = {"ऎ", "ऒ", u(0x0946), u(0x094A), "य़", "ಯ಼", u(0x11071), u(0x11072), u(0x11073), u(0x11074)},
to = {"ए", "ओ", u(0x0947), u(0x094B), "य", "ಯ", "𑀏", "𑀑", u(0x11042), u(0x11044)}
} ,
}
m["inc-pro"] = {
"tiếng Ấn-Arya nguyên thủy",
23808344,
"inc",
"Latn",
"Tiếng Ấn-Arya nguyên thủy",
"Ấn-Arya nguyên thủy",
type = "reconstructed",
}
m["inc-psc"] = {
"tiếng Prakrit Paisaci",
2995607,
"inc-mid",
"Brah",
ancestors = "inc-ash",
translit = "Brah-translit",
"Tiếng Prakrit Paisaci",
"Prakrit Paisaci",
}
m["inc-sap"] = {
"Sauraseni Apabhramsa",
nil,
"inc-mid",
"Deva",
ancestors = "psu",
}
m["inc-tak"] = {
"Takka Apabhramsa",
nil,
"inc-mid",
"Deva",
ancestors = "inc-pra",
translit = "sa-translit",
}
m["inc-vra"] = {
"Vracada Apabhramsa",
nil,
"inc-mid",
"Deva",
ancestors = "inc-pra",
translit = "sa-translit",
}
m["inc-cen-pro"] = {
"Proto-Central Indo-Aryan",
nil,
"inc-cen",
"Latn",
type = "reconstructed",
ancestors = "psu",
}
m["ine-ana-pro"] = {
"Proto-Anatolian",
7251833,
"ine-ana",
"Latn",
type = "reconstructed",
}
m["ine-bsl-pro"] = {
"tiếng Balt-Slav nguyên thủy",
1703347,
"ine-bsl",
"Latn",
"Tiếng Balt-Slav nguyên thủy",
"Balt-Slav nguyên thủy",
type = "reconstructed",
sort_key = {
from = {"[áā]", "[éēḗ]", "[íī]", "[óōṓ]", "[úū]", c.acute, c.macron, "ˀ"},
to = {"a", "e", "i", "o", "u"}
},
}
m["ine-pae"] = {
"Paeonian",
2705672,
"ine",
"polytonic",
translit = "grc-translit",
entry_name = {remove_diacritics = c.macron .. c.breve},
sort_key = s["Grek-sortkey"],
}
m["ine-pro"] = {
"tiếng Ấn-Âu nguyên thủy",
37178,
"ine",
"Latn",
"Tiếng Ấn-Âu nguyên thủy",
"Ấn-Âu nguyên thủy",
type = "reconstructed",
sort_key = {
from = {"[áā]", "[éēḗ]", "[íī]", "[óōṓ]", "[úū]", "ĺ", "ḿ", "ń", "ŕ", "ǵ", "ḱ", "ʰ", "ʷ", "₁", "₂", "₃", c.ringbelow, c.acute, c.macron},
to = {"a", "e", "i", "o", "u", "l", "m", "n", "r", "g'", "k'", "¯h", "¯w", "1", "2", "3"}
},
}
m["ine-toc-pro"] = {
"tiếng Tochari nguyên thủy",
37029,
"ine-toc",
"Latn",
"Tiếng Tochari nguyên thủy",
"Tochari nguyên thủy",
type = "reconstructed",
}
m["xme-old"] = {
"tiếng Media cổ",
36461,
"xme",
"Grek, Latn",
"Tiếng Media cổ",
"Media cổ",
}
m["xme-mid"] = {
"Middle Median",
nil,
"xme",
"Latn",
ancestors = "xme-old",
}
m["xme-ker"] = {
"tiếng Kerman",
129850,
"xme",
"fa-Arab, Latn",
"Tiếng Kerman",
"Kerman",
ancestors = "xme-mid",
}
m["xme-taf"] = {
"Tafreshi",
nil,
"xme",
"fa-Arab, Latn",
ancestors = "xme-mid",
}
m["xme-ttc-pro"] = {
"Proto-Tatic",
nil,
"xme-ttc",
"Latn",
ancestors = "xme-mid",
}
m["xme-kls"] = {
"Kalasuri",
nil,
"xme-ttc",
ancestors = "xme-ttc-nor",
}
m["xme-klt"] = {
"Kilit",
3612452,
"xme-ttc",
"Cyrl", -- and fa-Arab?
ancestors = "xme-ttc-pro",
}
m["xme-ott"] = {
"Old Tati",
434697,
"xme-ttc",
"fa-Arab, Latn",
ancestors = "xme-ttc-pro",
}
m["ira-pro"] = {
"tiếng Iran nguyên thủy",
4167865,
"ira",
"Latn",
"Tiếng Iran nguyên thủy",
"Iran nguyên thủy",
type = "reconstructed",
}
m["ira-mpr-pro"] = {
"Proto-Medo-Parthian",
nil,
"ira-mpr",
"Latn",
type = "reconstructed",
}
m["ira-kms-pro"] = {
"Proto-Komisenian",
nil,
"ira-kms",
"Latn",
type = "reconstructed",
}
m["ira-zgr-pro"] = {
"tiếng Zaza-Goran nguyên thủy",
nil,
"ira-zgr",
"Latn",
"Tiếng Zaza-Goran nguyên thủy",
"Zaza-Goran nguyên thủy",
type = "reconstructed",
}
m["ira-pat-pro"] = {
"tiếng Pathan nguyên thủy",
nil,
"ira-pat",
"Latn",
"Tiếng Pathan nguyên thủy",
"Pathan nguyên thủy",
type = "reconstructed",
}
m["os-pro"] = {
"Proto-Ossetic",
nil,
"xsc",
"Latn",
type = "reconstructed",
}
m["xsc-pro"] = {
"tiếng Scythia nguyên thủy",
nil,
"xsc",
"Latn",
"Tiếng Scythia nguyên thủy",
"Scythia nguyên thủy",
type = "reconstructed",
}
m["xsc-sar-pro"] = {
"tiếng Sarmatia nguyên thủy",
116773249,
"xsc-sar",
"Latn",
"Tiếng Sarmatia nguyên thủy",
"Sarmatia nguyên thủy",
type = "reconstructed",
}
m["xsc-skw-pro"] = {
"tiếng Saka-Wakhi nguyên thủy",
nil,
"xsc-skw",
"Latn",
"Tiếng Saka-Wakhi nguyên thủy",
"Saka-Wakhi nguyên thủy",
type = "reconstructed",
ancestors = "xsc-pro",
}
m["xsc-sak-pro"] = {
"Proto-Saka",
nil,
"xsc-sak",
"Latn",
type = "reconstructed",
ancestors = "xsc-skw-pro",
}
m["ira-sym-pro"] = {
"tiếng Shughnan-Yazghulom-Munji nguyên thủy",
nil,
"ira-sym",
"Latn",
"Tiếng Shughnan-Yazghulom-Munji nguyên thủy",
"Shughnan-Yazghulom-Munji nguyên thủy",
type = "reconstructed",
}
m["ira-sgi-pro"] = {
"Proto-Sanglechi-Ishkashimi",
nil,
"ira-sgi",
"Latn",
type = "reconstructed",
}
m["ira-mny-pro"] = {
"Proto-Munji-Yidgha",
nil,
"ira-mny",
"Latn",
type = "reconstructed",
ancestors = "ira-sym-pro",
}
m["ira-shy-pro"] = {
"tiếng Shughnan-Yazghulom nguyên thủy",
nil,
"ira-shy",
"Latn",
"Tiếng Shughnan-Yazghulom nguyên thủy",
"Shughnan-Yazghulom nguyên thủy",
type = "reconstructed",
ancestors = "ira-sym-pro",
}
m["ira-shr-pro"] = {
"tiếng Shughnan-Rushan nguyên thủy",
nil,
"ira-shy",
"Latn",
"Tiếng Shughnan-Rushan nguyên thủy",
"Shughnan-Rushan nguyên thủy",
type = "reconstructed",
ancestors = "ira-shy-pro",
}
m["ira-sgc-pro"] = {
"tiếng Sogdia nguyên thủy",
nil,
"ira-sgc",
"Latn",
"Tiếng Sogdia nguyên thủy",
"Sogdia nguyên thủy",
type = "reconstructed",
}
m["ira-wnj"] = {
"Vanji",
nil,
"ira-shy",
"Latn",
ancestors = "ira-shy-pro",
}
m["iro-ere"] = {
"Erie",
5388365,
"iro-nor",
"Latn",
}
m["iro-min"] = {
"Mingo",
128531,
"iro-nor",
"Latn",
}
m["iro-nor-pro"] = {
"tiếng Bắc Iroquois nguyên thủy",
nil,
"iro-nor",
"Latn",
"Tiếng Bắc Iroquois nguyên thủy",
"Bắc Iroquois nguyên thủy",
type = "reconstructed",
}
m["iro-pro"] = {
"tiếng Iroquois nguyên thủy",
7251852,
"iro",
"Latn",
"Tiếng Iroquois nguyên thủy",
"Iroquois nguyên thủy",
type = "reconstructed",
}
m["itc-pro"] = {
"tiếng Italic nguyên thủy",
17102720,
"itc",
"Latn",
"Tiếng Italic nguyên thủy",
"Italic nguyên thủy",
type = "reconstructed",
}
m["jpx-hcj"] = {
"tiếng Hachijō",
5637049,
"jpx",
"Jpan",
"Tiếng Hachijō",
"Hachijō",
ancestors = "ojp-eas",
translit = s["jpx-translit"],
display_text = s["jpx-displaytext"],
entry_name = s["jpx-entryname"],
sort_key = s["jpx-sortkey"],
}
m["jpx-pro"] = {
"tiếng Nhật Bản nguyên thủy",
nil,
"jpx",
"Latn",
"Tiếng Nhật Bản nguyên thủy",
"Nhật Bản nguyên thủy",
type = "reconstructed",
}
m["jpx-ryu-pro"] = {
"tiếng Lưu Cầu nguyên thủy",
nil,
"jpx-ryu",
"Latn",
"Tiếng Lưu Cầu nguyên thủy",
"Lưu Cầu nguyên thủy",
type = "reconstructed",
}
m["kar-pro"] = {
"tiếng Karen nguyên thủy",
nil,
"kar",
"Latn",
"Tiếng Karen nguyên thủy",
"Karen nguyên thủy",
type = "reconstructed",
}
m["kca-eas"] = {
"tiếng Đông Khanty",
30304622,
"kca",
"Cyrl",
"Tiếng Đông Khanty",
"Đông Khanty",
translit = "kca-translit",
override_translit = true,
-- TODO temporary until MediaWiki supports Unicode 16 (probably requires a PHP update from their side)
sort_key = { Cyrl = { from = {""}, to = {""} } },
}
m["kca-nor"] = {
"tiếng Bắc Khanty",
30304527,
"kca",
"Cyrl",
"Tiếng Bắc Khanty",
"Bắc Khanty",
translit = "kca-translit",
override_translit = true,
-- TODO temporary until MediaWiki supports Unicode 16 (probably requires a PHP update from their side)
sort_key = { Cyrl = { from = {""}, to = {""} } },
}
m["kca-sou"] = {
"Southern Khanty",
30304618,
"kca",
"Cyrl",
translit = "kca-translit",
override_translit = true,
}
m["khi-kho-pro"] = {
"Proto-Khoe",
nil,
"khi-kho",
"Latn",
type = "reconstructed",
}
m["khi-kun"] = {
"ǃKung",
32904,
"khi-kxa",
"Latn",
}
m["ko-ear"] = {
"Early Modern Korean",
756014,
"qfa-kor",
"Kore",
ancestors = "okm",
translit = "okm-translit",
entry_name = s["Kore-entryname"],
}
m["kro-pro"] = {
"Proto-Kru",
nil,
"kro",
"Latn",
type = "reconstructed",
}
m["ku-pro"] = {
"Proto-Kurdish",
nil,
"ku",
"Latn",
type = "reconstructed",
}
m["map-ata-pro"] = {
"Proto-Atayalic",
nil,
"map-ata",
"Latn",
type = "reconstructed",
}
m["map-bms"] = {
"tiếng Banyumas",
33219,
"map",
"Latn",
"Tiếng Banyumas",
"Banyumas",
}
m["map-pro"] = {
"tiếng Nam Đảo nguyên thủy",
49230,
"map",
"Latn",
"Tiếng Nam Đảo nguyên thủy",
"Nam Đảo nguyên thủy",
type = "reconstructed",
}
m["mkh-asl-pro"] = {
"tiếng Asli nguyên thủy",
55630680,
"mkh-asl",
"Latn",
"Tiếng Asli nguyên thủy",
"Asli nguyên thủy",
type = "reconstructed",
}
m["mkh-ban-pro"] = {
"tiếng Bahnar nguyên thủy",
nil,
"mkh-ban",
"Latn",
"Tiếng Bahnar nguyên thủy",
"Bahnar nguyên thủy",
type = "reconstructed",
}
m["mkh-bhn"] = {
"tiếng Bhnong",
nil,
"mkh-nbn",
"Latn",
"Tiếng Bhnong",
"Bhnong",
}
m["mkh-kat-pro"] = {
"tiếng Cơ Tu nguyên thủy",
nil,
"mkh-kat",
"Latn",
"Tiếng Cơ Tu nguyên thủy",
"Cơ Tu nguyên thủy",
type = "reconstructed",
}
m["mkh-khm-pro"] = {
"tiếng Khơ Mú nguyên thủy",
nil,
"mkh-khm",
"Latn",
"Tiếng Khơ Mú nguyên thủy",
"Khơ Mú nguyên thủy",
type = "reconstructed",
}
m["mkh-kmr-pro"] = {
"tiếng Khmer nguyên thủy",
55630684,
"mkh-kmr",
"Latn",
"Tiếng Khmer nguyên thủy",
"Khmer nguyên thủy",
type = "reconstructed",
}
m["mkh-mmn"] = {
"tiếng Môn trung đại",
121337926,
"mkh-mnc",
"Latn, Mymr", --and also Pallava
"Tiếng Môn trung đại",
"Môn trung đại",
ancestors = "omx",
}
m["mkh-mnc-pro"] = {
"tiếng Môn nguyên thủy",
116773231,
"mkh-mnc",
"Latn",
"Tiếng Môn nguyên thủy",
"Môn nguyên thủy",
type = "reconstructed",
}
m["mkh-mvi"] = {
"tiếng Việt trung cổ",
9199,
"mkh-vie",
"Hani, Latn",
"Tiếng Việt trung cổ",
"Việt trung cổ",
sort_key = {Hani = "Hani-sortkey"},
}
m["mkh-pal-pro"] = {
"tiếng Palaung nguyên thủy",
nil,
"mkh-pal",
"Latn",
"Tiếng Palaung nguyên thủy",
"Palaung nguyên thủy",
type = "reconstructed",
}
m["mkh-pea-pro"] = {
"tiếng Pear nguyên thủy",
nil,
"mkh-pea",
"Latn",
"Tiếng Pear nguyên thủy",
"Pear nguyên thủy",
type = "reconstructed",
}
m["mkh-pkn-pro"] = {
"tiếng Pakan nguyên thủy",
nil,
"mkh-pkn",
"Latn",
"Tiếng Pakan nguyên thủy",
"Pakan nguyên thủy",
type = "reconstructed",
}
m["mkh-pro"] = { --This will be merged into 2015 aav-pro.
"tiếng Môn-Khmer nguyên thủy",
7251859,
"mkh",
"Latn",
"Tiếng Môn-Khmer nguyên thủy",
"Môn-Khmer nguyên thủy",
type = "reconstructed",
}
m["mkh-vie-pro"] = {
"tiếng Việt-Mường nguyên thủy",
nil,
"mkh-vie",
"Latn",
"Tiếng Việt-Mường nguyên thủy",
"Việt-Mường nguyên thủy",
type = "reconstructed",
}
m["mns-cen"] = {
"tiếng Trung Mansi",
128810384,
"mns",
"Cyrl",
"Tiếng Trung Mansi",
"Trung Mansi",
translit = "mns-translit",
override_translit = true,
}
m["mns-nor"] = {
"tiếng Bắc Mansi",
30304537,
"mns",
"Cyrl",
"Tiếng Bắc Mansi",
"Bắc Mansi",
translit = "mns-translit",
override_translit = true,
}
m["mns-pro"] = {
"tiếng Mansi nguyên thủy",
128883093,
"mns",
"Latn",
"Tiếng Mansi nguyên thủy",
"Mansi nguyên thủy",
type = "reconstructed",
}
m["mns-sou"] = {
"tiếng Nam Mansi",
30304629,
"mns",
"Cyrl",
"Tiếng Nam Mansi",
"Nam Mansi",
translit = "mns-translit",
override_translit = true,
}
m["mnw-tha"] = {
"tiếng Môn Thái",
nil,
"mkh-mnc",
"Mymr, Thai",
ancestors = "mkh-mmn",
sort_key = {
from = {"[%p]", "ျ", "ြ", "ွ", "ှ", "ၞ", "ၟ", "ၠ", "ၚ", "ဿ", "[็-๎]", "([เแโใไ])([ก-ฮ])ฺ?"},
to = {"", "္ယ", "္ရ", "္ဝ", "္ဟ", "္န", "္မ", "္လ", "င", "သ္သ", "", "%2%1"}
},
"Tiếng Môn Thái",
"Môn Thái"
}
m["mun-pro"] = {
"tiếng Munda nguyên thủy",
105102373,
"mun",
"Latn",
"Tiếng Munda nguyên thủy",
"Munda nguyên thủy",
type = "reconstructed",
}
m["myn-chl"] = { -- the stage after ''emy''
"Ch'olti'",
873995,
"myn",
"Latn",
}
m["myn-pro"] = {
"tiếng Maya nguyên thủy",
3321532,
"myn",
"Latn",
"Tiếng Maya nguyên thủy",
"Maya nguyên thủy",
type = "reconstructed",
}
m["nai-ala"] = {
"Alazapa",
nil,
nil,
"Latn",
}
m["nai-bay"] = {
"Bayogoula",
1563704,
nil,
"Latn",
}
m["nai-bvy"] = {
"Buena Vista Yokuts",
4985474,
"nai-yok",
"Latn",
}
m["nai-cal"] = {
"Calusa",
51782,
nil,
"Latn",
}
m["nai-chi"] = {
"Chiquimulilla",
25339627,
"nai-xin",
"Latn",
}
m["nai-chu-pro"] = {
"Proto-Chumash",
nil,
"nai-chu",
"Latn",
type = "reconstructed",
}
m["nai-cig"] = {
"Ciguayo",
20741700,
nil,
"Latn",
}
m["nai-ckn-pro"] = {
"Proto-Chinookan",
nil,
"nai-ckn",
"Latn",
type = "reconstructed",
}
m["nai-dly"] = {
"Delta Yokuts",
nil,
"nai-yok",
"Latn",
}
m["nai-gsy"] = {
"Gashowu",
nil,
"nai-yok",
"Latn",
}
m["nai-guz"] = {
"Guazacapán",
19572028,
"nai-xin",
"Latn",
}
m["nai-hit"] = {
"Hitchiti",
1542882,
"nai-mus",
"Latn",
}
m["nai-ipa"] = {
"Ipai",
3027474,
"nai-yuc",
"Latn",
}
m["nai-jtp"] = {
"Jutiapa",
nil,
"nai-xin",
"Latn",
}
m["nai-jum"] = {
"tiếng Jumaytepeque",
25339626,
"nai-xin",
"Latn",
"Tiếng Jumaytepeque",
"Jumaytepeque",
}
m["nai-kat"] = {
"Kathlamet",
6376639,
"nai-ckn",
"Latn",
}
m["nai-klp-pro"] = {
"Proto-Kalapuyan",
nil,
"nai-klp",
type = "reconstructed",
}
m["nai-knm"] = {
"Konomihu",
3198734,
"nai-shs",
"Latn",
}
m["nai-kry"] = {
"Kings River Yokuts",
6413014,
"nai-yok",
"Latn",
}
m["nai-kum"] = {
"tiếng Kumeyaay",
4910139,
"nai-yuc",
"Latn",
"Tiếng Kumeyaay",
"Kumeyaay",
}
m["nai-mac"] = {
"Macoris",
21070851,
nil,
"Latn",
}
m["nai-mdu-pro"] = {
"Proto-Maidun",
nil,
"nai-mdu",
"Latn",
type = "reconstructed",
}
m["nai-miz-pro"] = {
"Proto-Mixe-Zoque",
nil,
"nai-miz",
"Latn",
type = "reconstructed",
}
m["nai-mus-pro"] = {
"tiếng Muskogee nguyên thủy",
116775368,
"nai-mus",
"Latn",
"Tiếng Muskogee nguyên thủy",
"Muskogee nguyên thủy",
type = "reconstructed",
}
m["nai-nao"] = {
"Naolan",
6964594,
nil,
"Latn",
}
m["nai-nrs"] = {
"New River Shasta",
7011254,
"nai-shs",
"Latn",
}
m["nai-nvy"] = {
"Northern Valley Yokuts",
nil,
"nai-yok",
"Latn",
}
m["nai-okw"] = {
"Okwanuchu",
3350126,
"nai-shs",
"Latn",
}
m["nai-per"] = {
"Pericú",
3375369,
nil,
"Latn",
}
m["nai-pic"] = {
"Picuris",
7191257,
"nai-kta",
"Latn",
}
m["nai-plp-pro"] = {
"Proto-Plateau Penutian",
nil,
"nai-plp",
"Latn",
type = "reconstructed",
}
m["nai-ply"] = {
"Palewyami",
2387391,
"nai-yok",
"Latn",
}
m["nai-pom-pro"] = {
"Proto-Pomo",
nil,
"nai-pom",
"Latn",
type = "reconstructed",
}
m["nai-qng"] = {
"Quinigua",
36360,
nil,
"Latn",
}
m["nai-sca-pro"] = { -- NB 'sio-pro' "Proto-Siouan" which is Proto-Western Siouan
"Proto-Siouan-Catawban",
nil,
"nai-sca",
"Latn",
type = "reconstructed",
}
m["nai-sin"] = {
"Sinacantán",
24190249,
"nai-xin",
"Latn",
}
m["nai-sln"] = {
"Salvadoran Lenca",
3229434,
"nai-len",
"Latn",
}
m["nai-spt"] = {
"Sahaptin",
3833015,
"nai-shp",
"Latn",
}
m["nai-svy"] = {
"Southern Valley Yokuts",
nil,
"nai-yok",
"Latn",
}
m["nai-tap"] = {
"Tapachultec",
7684401,
"nai-miz",
"Latn",
}
m["nai-taw"] = {
"Tawasa",
7689233,
nil,
"Latn",
}
m["nai-teq"] = {
"Tequistlatec",
2964454,
"nai-tqn",
"Latn",
}
m["nai-tip"] = {
"tiếng Tipai",
3027471,
"nai-yuc",
"Latn",
"Tiếng Tipai",
"Tipai",
}
m["nai-tky"] = {
"Tule-Kaweah Yokuts",
7851988,
"nai-yok",
"Latn",
}
m["nai-tot-pro"] = {
"Proto-Totozoquean",
nil,
"nai-tot",
"Latn",
type = "reconstructed",
}
m["nai-tsi-pro"] = {
"Proto-Tsimshianic",
nil,
"nai-tsi",
"Latn",
type = "reconstructed",
}
m["nai-utn-pro"] = {
"Proto-Utian",
nil,
"nai-utn",
"Latn",
type = "reconstructed",
}
m["nai-wai"] = {
"Waikuri",
3118702,
nil,
"Latn",
}
m["nai-yup"] = {
"Yupiltepeque",
25339628,
"nai-xin",
"Latn",
}
m["nan-hbl"] = {
"tiếng Mân Tuyền Chương",
1624231,
"zhx-nan",
"Hants, Latn, Bopo, Kana",
"Tiếng Mân Tuyền Chương",
"Mân Tuyền Chương",
wikimedia_codes = "zh-min-nan",
generate_forms = "zh-generateforms",
sort_key = {
Hani = "Hani-sortkey",
Kana = "Kana-sortkey"
},
}
m["nan-tws"] = {
"tiếng Triều Châu",
36759,
"zhx-nan",
"Hants",
"Tiếng Triều Châu",
"Triều Châu",
generate_forms = "zh-generateforms",
translit = "zh-translit",
sort_key = "Hani-sortkey",
}
m["nds-de"] = {
"tiếng Hạ Đức tại Đức",
25433,
"gmw",
"Latn",
"Tiếng Hạ Đức tại Đức",
"Hạ Đức tại Đức",
ancestors = "nds",
wikimedia_codes = "nds",
}
m["nds-nl"] = {
"tiếng Hạ Saxon Hà Lan",
516137,
"gmw",
"Latn",
"Tiếng Hạ Saxon Hà Lan",
"Hạ Saxon Hà Lan",
ancestors = "nds",
}
m["ngf-pro"] = {
"Proto-Trans-New Guinea",
nil,
"ngf",
"Latn",
type = "reconstructed",
}
m["nic-bco-pro"] = {
"tiếng Benue-Congo nguyên thủy",
nil,
"nic-bco",
"Latn",
"Tiếng Benue-Congo nguyên thủy",
"Benue-Congo nguyên thủy",
type = "reconstructed",
}
m["nic-bod-pro"] = {
"Proto-Bantoid",
nil,
"nic-bod",
"Latn",
type = "reconstructed",
}
m["nic-eov-pro"] = {
"Proto-Eastern Oti-Volta",
nil,
"nic-eov",
"Latn",
type = "reconstructed",
}
m["nic-gns-pro"] = {
"Proto-Gurunsi",
nil,
"nic-gns",
"Latn",
type = "reconstructed",
}
m["nic-grf-pro"] = {
"Proto-Grassfields",
nil,
"nic-grf",
"Latn",
type = "reconstructed",
}
m["nic-gur-pro"] = {
"Proto-Gur",
nil,
"nic-gur",
"Latn",
type = "reconstructed",
}
m["nic-jkn-pro"] = {
"Proto-Jukunoid",
nil,
"nic-jkn",
"Latn",
type = "reconstructed",
}
m["nic-lcr-pro"] = {
"Proto-Lower Cross River",
nil,
"nic-lcr",
"Latn",
type = "reconstructed",
}
m["nic-ogo-pro"] = {
"Proto-Ogoni",
nil,
"nic-ogo",
"Latn",
type = "reconstructed",
}
m["nic-ovo-pro"] = {
"Proto-Oti-Volta",
nil,
"nic-ovo",
"Latn",
type = "reconstructed",
}
m["nic-plt-pro"] = {
"tiếng Plateau nguyên thủy",
nil,
"nic-plt",
"Latn",
"Tiếng Plateau nguyên thủy",
"Plateau nguyên thủy",
type = "reconstructed",
}
m["nic-pro"] = {
"tiếng Niger-Congo nguyên thủy",
nil,
"nic",
"Latn",
"Tiếng Niger-Congo nguyên thủy",
"Niger-Congo nguyên thủy",
type = "reconstructed",
}
m["nic-ubg-pro"] = {
"tiếng Ubangi nguyên thủy",
nil,
"nic-ubg",
"Latn",
"Tiếng Ubangi nguyên thủy",
type = "reconstructed",
}
m["nic-ucr-pro"] = {
"Proto-Upper Cross River",
nil,
"nic-ucr",
"Latn",
type = "reconstructed",
}
m["nic-vco-pro"] = {
"tiếng Volta-Congo nguyên thủy",
nil,
"nic-vco",
"Latn",
"Tiếng Volta-Congo nguyên thủy",
"Volta-Congo nguyên thủy",
type = "reconstructed",
}
m["nub-har"] = {
"Haraza",
19572059,
"nub",
"Arab, Latn",
}
m["nub-pro"] = {
"Proto-Nubian",
nil,
"nub",
"Latn",
type = "reconstructed",
}
m["omq-cha-pro"] = {
"Proto-Chatino",
nil,
"omq-cha",
"Latn",
type = "reconstructed",
}
m["omq-maz-pro"] = {
"Proto-Mazatec",
nil,
"omq-maz",
"Latn",
type = "reconstructed",
}
m["omq-mix-pro"] = {
"tiếng Mixtec nguyên thủy",
21573423,
"omq-mix",
"Latn",
"Tiếng Mixtec nguyên thủy",
"Mixtec nguyên thủy",
type = "reconstructed",
}
m["omq-mxt-pro"] = {
"Proto-Mixtec",
nil,
"omq-mxt",
"Latn",
type = "reconstructed",
}
m["omq-otp-pro"] = {
"Proto-Oto-Pamean",
nil,
"omq-otp",
"Latn",
type = "reconstructed",
ancestors = "omq-pro",
}
m["omq-pro"] = {
"Proto-Oto-Manguean",
33669,
"omq",
"Latn",
type = "reconstructed",
}
m["omq-tel"] = {
"Teposcolula Mixtec",
nil,
"omq-mxt",
"Latn",
}
m["omq-teo"] = {
"Teojomulco Chatino",
25340451,
"omq-cha",
"Latn",
}
m["omq-tri-pro"] = {
"tiếng Trique nguyên thủy",
nil,
"omq-tri",
"Latn",
"Tiếng Trique nguyên thủy",
"Trique nguyên thủy",
type = "reconstructed",
}
m["omq-zap-pro"] = {
"Proto-Zapotecan",
nil,
"omq-zap",
"Latn",
type = "reconstructed",
}
m["omq-zpc-pro"] = {
"tiếng Zapotec nguyên thủy",
116773296,
"omq-zpc",
"Latn",
"Tiếng Zapotec nguyên thủy",
"Zapotec nguyên thủy",
type = "reconstructed",
}
m["omv-aro-pro"] = {
"tiếng Aari nguyên thủy",
nil,
"omv-aro",
"Latn",
"Tiếng Aari nguyên thủy",
"Aari nguyên thủy",
type = "reconstructed",
}
m["omv-diz-pro"] = {
"tiếng Dizi nguyên thủy",
nil,
"omv-diz",
"Latn",
"Tiếng Dizi nguyên thủy",
"Dizi nguyên thủy",
type = "reconstructed",
}
m["omv-pro"] = {
"tiếng Omo nguyên thủy",
nil,
"omv",
"Latn",
"Tiếng Omo nguyên thủy",
"Omo nguyên thủy",
type = "reconstructed",
}
m["oto-otm-pro"] = {
"Proto-Otomi",
nil,
"oto-otm",
"Latn",
type = "reconstructed",
ancestors = "oto-pro",
}
m["oto-pro"] = {
"Proto-Otomian",
nil,
"oto",
"Latn",
type = "reconstructed",
ancestors = "omq-otp-pro",
}
m["paa-kom"] = {
"Kómnzo",
18344310,
"paa-yam",
"Latn",
}
m["paa-kwn"] = {
"Kuwani",
6449056,
"paa",
"Latn",
}
m["paa-nha-pro"] = {
"Proto-North Halmahera",
nil,
"paa-nha",
"Latn",
type = "reconstructed"
}
m["paa-nun"] = {
"Nungon",
nil,
"paa",
"Latn",
}
m["phi-din"] = {
"Dinapigue Agta",
16945774,
"phi",
"Latn",
}
m["phi-kal-pro"] = {
"Proto-Kalamian",
nil,
"phi-kal",
"Latn",
type = "reconstructed",
}
m["phi-nag"] = {
"Nagtipunan Agta",
16966111,
"phi",
"Latn",
}
m["phi-pro"] = {
"tiếng Philippines nguyên thủy",
18204898,
"phi",
"Latn",
"Tiếng Philippines nguyên thủy",
"Philippines nguyên thủy",
type = "reconstructed",
}
m["poz-abi"] = {
"tiếng Abai",
19570729,
"poz-san",
"Latn",
"Tiếng Abai",
"Abai",
}
m["poz-bal"] = {
"Baliledo",
4850912,
"poz",
"Latn",
}
m["poz-btk-pro"] = {
"Proto-Bungku-Tolaki",
nil,
"poz-btk",
"Latn",
type = "reconstructed",
}
m["poz-cet-pro"] = {
"tiếng Mã Lai-Đa Đảo Trung Đông nguyên thủy",
2269883,
"poz-cet",
"Latn",
"Tiếng Mã Lai-Đa Đảo Trung Đông nguyên thủy",
"Mã Lai-Đa Đảo Trung Đông nguyên thủy",
type = "reconstructed",
}
m["poz-hce-pro"] = {
"Proto-Halmahera-Cenderawasih",
nil,
"poz-hce",
"Latn",
type = "reconstructed",
}
m["poz-lgx-pro"] = {
"Proto-Lampungic",
nil,
"poz-lgx",
"Latn",
type = "reconstructed",
}
m["poz-mcm-pro"] = {
"tiếng Mã Lai-Chăm nguyên thủy",
nil,
"poz-mcm",
"Latn",
"Tiếng Mã Lai-Chăm nguyên thủy",
"Mã Lai-Chăm nguyên thủy",
type = "reconstructed",
}
m["poz-mly-pro"] = {
"tiếng Mã Lai nguyên thủy",
nil,
"poz-mly",
"Latn",
"Tiếng Mã Lai nguyên thủy",
"Mã Lai nguyên thủy",
type = "reconstructed",
}
m["poz-msa-pro"] = {
"tiếng Mã Lai-Sumbawa nguyên thủy",
nil,
"poz-msa",
"Latn",
"Tiếng Mã Lai-Sumbawa nguyên thủy",
"Mã Lai-Sumbawa nguyên thủy",
type = "reconstructed",
}
m["poz-oce-pro"] = {
"tiếng Châu Đại Dương nguyên thủy",
141741,
"poz-oce",
"Latn",
"Tiếng Châu Đại Dương nguyên thủy",
"Châu Đại Dương nguyên thủy",
type = "reconstructed",
}
m["poz-pep-pro"] = {
"tiếng Đa Đảo Đông nguyên thủy",
nil,
"poz-pep",
"Latn",
"Tiếng Đa Đảo Đông nguyên thủy",
"Đa Đảo Đông nguyên thủy",
type = "reconstructed",
}
m["poz-pnp-pro"] = {
"tiếng Đa Đảo hạt nhân nguyên thủy",
nil,
"poz-pnp",
"Latn",
"Tiếng Đa Đảo hạt nhân nguyên thủy",
"Đa Đảo hạt nhân nguyên thủy",
type = "reconstructed",
}
m["poz-pol-pro"] = {
"tiếng Đa Đảo nguyên thủy",
1658709,
"poz-pol",
"Latn",
"Tiếng Đa Đảo nguyên thủy",
"Đa Đảo nguyên thủy",
type = "reconstructed",
}
m["poz-pro"] = {
"tiếng Mã Lai-Đa Đảo nguyên thủy",
3832960,
"poz",
"Latn",
"Tiếng Mã Lai-Đa Đảo nguyên thủy",
"Mã Lai-Đa Đảo nguyên thủy",
type = "reconstructed",
}
m["poz-ssw-pro"] = {
"Proto-South Sulawesi",
nil,
"poz-ssw",
"Latn",
type = "reconstructed",
}
m["poz-sus-pro"] = {
"Proto-Sunda-Sulawesi",
nil,
"poz-sus",
"Latn",
type = "reconstructed",
}
m["poz-swa-pro"] = {
"Proto-North Sarawak",
nil,
"poz-swa",
"Latn",
type = "reconstructed",
}
m["pqe-pro"] = {
"tiếng Mã Lai-Đa Đảo Đông nguyên thủy",
2269883,
"pqe",
"Latn",
"Tiếng Mã Lai-Đa Đảo Đông nguyên thủy",
"Mã Lai-Đa Đảo Đông nguyên thủy",
type = "reconstructed",
}
m["pra-niy"] = {
"tiếng Prakrit Niya",
nil,
"inc-mid",
"Khar",
ancestors = "inc-ash",
translit = "Khar-translit",
"Tiếng Prakrit Niya",
"Prakrit Niya",
}
m["qfa-adm-pro"] = {
"Proto-Great Andamanese",
nil,
"qfa-adm",
"Latn",
type = "reconstructed",
}
m["qfa-bet-pro"] = {
"tiếng Bối-Thái nguyên thủy",
116773193,
"qfa-bet",
"Latn",
"Tiếng Bối-Thái nguyên thủy",
"Bối-Thái nguyên thủy",
type = "reconstructed",
}
m["qfa-cka-pro"] = {
"Proto-Chukotko-Kamchatkan",
7251837,
"qfa-cka",
"Latn",
type = "reconstructed",
}
m["qfa-hur-pro"] = {
"Proto-Hurro-Urartian",
nil,
"qfa-hur",
"Latn",
type = "reconstructed",
}
m["qfa-kad-pro"] = {
"Proto-Kadu",
nil,
"qfa-kad",
"Latn",
type = "reconstructed",
}
m["qfa-kms-pro"] = {
"tiếng Động-Thủy nguyên thủy",
nil,
"qfa-kms",
"Latn",
"Tiếng Động-Thủy nguyên thủy",
"Động-Thủy nguyên thủy",
type = "reconstructed",
}
m["qfa-kor-pro"] = {
"tiếng Triều Tiên nguyên thủy",
467883,
"qfa-kor",
"Latn",
"Tiếng Triều Tiên nguyên thủy",
"Triều Tiên nguyên thủy",
type = "reconstructed",
}
m["qfa-kra-pro"] = {
"tiếng Kra nguyên thủy",
7251854,
"qfa-kra",
"Latn",
"Tiếng Kra nguyên thủy",
"Kra nguyên thủy",
type = "reconstructed",
}
m["qfa-lic-pro"] = {
"tiếng Hlai nguyên thủy",
7251845,
"qfa-lic",
"Latn",
"Tiếng Hlai nguyên thủy",
"Hlai nguyên thủy",
type = "reconstructed",
}
m["qfa-onb-pro"] = {
"tiếng Ông Bối nguyên thủy",
nil,
"qfa-onb",
"Latn",
"Tiếng Ông Bối nguyên thủy",
"Ông Bối nguyên thủy",
type = "reconstructed",
}
m["qfa-ong-pro"] = {
"tiếng Önge nguyên thủy",
nil,
"qfa-ong",
"Latn",
"Tiếng Önge nguyên thủy",
"Önge nguyên thủy",
type = "reconstructed",
}
m["qfa-tak-pro"] = {
"tiếng Kra-Dai nguyên thủy",
nil,
"qfa-tak",
"Latn",
"Tiếng Kra-Dai nguyên thủy",
"Kra-Dai nguyên thủy",
type = "reconstructed",
}
m["qfa-xgx-rou"] = {
"tiếng Nhu Nhiên",
48816637,
"qfa-xgx",
"Hani, Latn",
"Tiếng Nhu Nhiên",
"Nhu Nhiên",
sort_key = {Hani = "Hani-sortkey"},
}
m["qfa-xgx-tuh"] = {
"tiếng Thổ Dục Hồn",
48816625,
"qfa-xgx",
"Hani, Latn",
"Tiếng Thổ Dục Hồn",
"Thổ Dục Hồn",
sort_key = {Hani = "Hani-sortkey"},
}
m["qfa-xgx-tuo"] = {
"tiếng Thác Bạt",
48816629,
"qfa-xgx",
"Hani, Latn",
"Tiếng Thác Bạt",
"Thác Bạt",
sort_key = {Hani = "Hani-sortkey"},
}
m["qfa-xgx-xbi"] = {
"tiếng Tiên Ti",
4448647,
"qfa-xgx",
"Hani, Latn",
"Tiếng Tiên Ti",
"Tiên Ti",
sort_key = {Hani = "Hani-sortkey"},
}
m["qfa-yen-pro"] = {
"tiếng Enisei nguyên thủy",
27639,
"qfa-yen",
"Latn",
"Tiếng Enisei nguyên thủy",
"Enisei nguyên thủy",
type = "reconstructed",
}
m["qfa-yuk-pro"] = {
"tiếng Yukaghir nguyên thủy",
nil,
"qfa-yuk",
"Latn",
"Tiếng Yukaghir nguyên thủy",
"Yukaghir nguyên thủy",
type = "reconstructed",
}
m["qwe-kch"] = {
"Kichwa",
1740805,
"qwe",
"Latn",
ancestors = "qu",
}
m["roa-ang"] = {
"Angevin",
56782,
"roa-oil",
"Latn",
sort_key = s["roa-oil-sortkey"],
}
m["roa-bbn"] = {
"Bourbonnais-Berrichon",
nil,
"roa-oil",
"Latn",
sort_key = s["roa-oil-sortkey"],
}
m["roa-brg"] = {
"tiếng Bourguignon",
508332,
"roa-oil",
"Latn",
"Tiếng Bourguignon",
"Bourguignon",
sort_key = s["roa-oil-sortkey"],
}
m["roa-cha"] = {
"Champenois",
430018,
"roa-oil",
"Latn",
sort_key = s["roa-oil-sortkey"],
}
m["roa-fcm"] = {
"tiếng Franche-Comté",
510561,
"roa-oil",
"Latn",
"Tiếng Franche-Comté",
"Franche-Comté",
sort_key = s["roa-oil-sortkey"],
}
m["roa-gal"] = {
"tiếng Gallo",
37300,
"roa-oil",
"Latn",
"Tiếng Gallo",
"Gallo",
sort_key = s["roa-oil-sortkey"],
}
m["roa-leo"] = {
"tiếng León",
34108,
"roa-ibe",
"Latn",
"Tiếng León",
"León",
ancestors = "roa-ole",
}
m["roa-lor"] = {
"tiếng Lorrain",
671198,
"roa-oil",
"Latn",
"Tiếng Lorrain",
"Lorrain",
sort_key = s["roa-oil-sortkey"],
}
m["roa-oan"] = {
"Navarro-Aragonese",
2736184,
"roa-ibe",
"Latn",
}
m["roa-oca"] = {
"tiếng Catalan cổ",
15478520,
"roa-ocr",
"Latn",
"Tiếng Catalan cổ",
"Catalan cổ",
sort_key = {
from = {"à", "[èé]", "[íï]", "[òó]", "[úü]", "ç", "·"},
to = {"a", "e", "i", "o", "u", "c"}
},
}
m["roa-ole"] = {
"tiếng León cổ",
125977465,
"roa-asl",
"Latn",
"Tiếng León cổ",
"León cổ",
}
m["roa-opt"] = {
"tiếng Galicia-Bồ Đào Nha",
1072111,
"roa-ibe",
"Latn",
"Tiếng Galicia-Bồ Đào Nha",
"Galicia-Bồ Đào Nha",
}
m["roa-orl"] = {
"Orléanais",
nil,
"roa-oil",
"Latn",
sort_key = s["roa-oil-sortkey"],
}
m["roa-poi"] = {
"Poitevin-Saintongeais",
514123,
"roa-oil",
"Latn",
sort_key = s["roa-oil-sortkey"],
}
m["roa-tar"] = {
"tiếng Tarantino",
695526,
"roa-itd",
"Latn",
"Tiếng Tarantino",
"Tarantino",
ancestors = "nap",
wikimedia_codes = "roa-tara",
}
m["roa-tou"] = {
"Tourangeau",
nil,
"roa-oil",
"Latn",
sort_key = s["roa-oil-sortkey"],
}
m["sai-ajg"] = {
"Ajagua",
nil,
nil,
"Latn",
}
m["sai-all"] = {
"tiếng Alyentiyak",
19570789,
"sai-hrp",
"Latn",
"Tiếng Alyentiyak",
"Alyentiyak",
}
m["sai-and"] = { -- not to be confused with 'cbc' or 'ano'
"Andoquero",
16828359,
"sai-wit",
"Latn",
}
m["sai-ayo"] = {
"Ayomán",
16937754,
"sai-jir",
"Latn",
}
m["sai-bae"] = {
"Baenan",
3401998,
nil,
"Latn",
}
m["sai-bag"] = {
"tiếng Bagua",
5390321,
nil,
"Latn",
"Tiếng Bagua",
"Bagua",
}
m["sai-bet"] = {
"Betoi",
926551,
"qfa-iso",
"Latn",
}
m["sai-bor-pro"] = {
"Proto-Boran",
nil,
"sai-bor",
"Latn",
}
m["sai-cac"] = {
"Cacán",
945482,
nil,
"Latn",
}
m["sai-caq"] = {
"Caranqui",
2937753,
"sai-bar",
"Latn",
}
m["sai-car-pro"] = {
"tiếng Carib nguyên thủy",
nil,
"sai-car",
"Latn",
"Tiếng Carib nguyên thủy",
"Carib nguyên thủy",
type = "reconstructed",
}
m["sai-cat"] = {
"Catacao",
5051136,
"sai-ctc",
"Latn",
}
m["sai-cer-pro"] = {
"tiếng Cerrado nguyên thủy",
nil,
"sai-cer",
"Latn",
"Tiếng Cerrado nguyên thủy",
"Cerrado nguyên thủy",
type = "reconstructed",
}
m["sai-chi"] = {
"Chirino",
5390321,
nil,
"Latn",
}
m["sai-chn"] = {
"Chaná",
5072718,
"sai-crn",
"Latn",
}
m["sai-chp"] = {
"Chapacura",
5072884,
"sai-cpc",
"Latn",
}
m["sai-chr"] = {
"Charrua",
5086680,
"sai-crn",
"Latn",
}
m["sai-chu"] = {
"Churuya",
5118339,
"sai-guh",
"Latn",
}
m["sai-cje-pro"] = {
"Proto-Central Jê",
nil,
"sai-cje",
"Latn",
type = "reconstructed",
}
m["sai-cmg"] = {
"Comechingon",
6644203,
nil,
"Latn",
}
m["sai-cno"] = {
"Chono",
5104704,
nil,
"Latn",
}
m["sai-cnr"] = {
"Cañari",
5055572,
nil,
"Latn",
}
m["sai-coe"] = {
"Coeruna",
6425639,
"sai-wit",
"Latn",
}
m["sai-col"] = {
"Colán",
5141893,
"sai-ctc",
"Latn",
}
m["sai-cop"] = {
"Copallén",
5390321,
nil,
"Latn",
}
m["sai-crd"] = {
"Coroado Puri",
24191321,
"sai-mje",
"Latn",
}
m["sai-ctq"] = {
"Catuquinaru",
16858455,
nil,
"Latn",
}
m["sai-cul"] = {
"Culli",
2879660,
nil,
"Latn",
}
m["sai-cva"] = {
"Cueva",
nil,
nil,
"Latn",
}
m["sai-esm"] = {
"Esmeralda",
3058083,
nil,
"Latn",
}
m["sai-ewa"] = {
"Ewarhuyana",
16898104,
nil,
"Latn",
}
m["sai-gam"] = {
"Gamela",
5403661,
nil,
"Latn",
}
m["sai-gay"] = {
"Gayón",
5528902,
"sai-jir",
"Latn",
}
m["sai-gmo"] = {
"Guamo",
5613495,
nil,
"Latn",
}
m["sai-gue"] = {
"Güenoa",
5626799,
"sai-crn",
"Latn",
}
m["sai-hau"] = {
"tiếng Haush",
3128376,
"sai-cho",
"Latn",
"Tiếng Haush",
"Haush",
}
m["sai-hoc-pro"] = {
"Proto-Huitoto-Ocaina",
nil,
"sai-hoc",
"Latn",
type = "reconstructed",
}
m["sai-jee-pro"] = {
"tiếng Jê nguyên thủy",
nil,
"sai-jee",
"Latn",
"Tiếng Jê nguyên thủy",
"Jê nguyên thủy",
type = "reconstructed",
}
m["sai-jko"] = {
"Jeikó",
6176527,
"sai-mje",
"Latn",
}
m["sai-jrj"] = {
"Jirajara",
6202966,
"sai-jir",
"Latn",
}
m["sai-kat"] = { -- contrast xoo, kzw, sai-xoc
"Katembri",
6375925,
nil,
"Latn",
}
m["sai-mal"] = {
"Malalí",
6741212,
nil,
"Latn",
}
m["sai-mar"] = {
"Maratino",
6755055,
nil,
"Latn",
}
m["sai-mat"] = {
"Matanawi",
6786047,
nil,
"Latn",
}
m["sai-mcn"] = {
"Mocana",
3402048,
nil,
"Latn",
}
m["sai-men"] = {
"Menien",
16890110,
"sai-mje",
"Latn",
}
m["sai-mil"] = {
"Millcayac",
19573012,
"sai-hrp",
"Latn",
}
m["sai-mlb"] = {
"Malibu",
3402048,
nil,
"Latn",
}
m["sai-msk"] = {
"Masakará",
6782426,
"sai-mje",
"Latn",
}
m["sai-muc"] = {
"Mucuchí",
nil,
nil,
"Latn",
}
m["sai-mue"] = {
"Muellama",
16886936,
"sai-bar",
"Latn",
}
m["sai-muz"] = {
"Muzo",
6644203,
nil,
"Latn",
}
m["sai-mys"] = {
"Maynas",
16919393,
nil,
"Latn",
}
m["sai-nat"] = {
"Natú",
9006749,
nil,
"Latn",
}
m["sai-nje-pro"] = {
"tiếng Jê Bắc nguyên thủy",
nil,
"sai-nje",
"Latn",
"Tiếng Jê Bắc nguyên thủy",
"Jê Bắc nguyên thủy",
type = "reconstructed",
}
m["sai-opo"] = {
"Opón",
7099152,
"sai-car",
"Latn",
}
m["sai-oto"] = {
"Otomaco",
16879234,
"sai-otm",
"Latn",
}
m["sai-pal"] = {
"Palta",
3042978,
nil,
"Latn",
}
m["sai-pam"] = {
"Pamigua",
5908689,
"sai-otm",
"Latn",
}
m["sai-par"] = {
"Paratió",
16890038,
nil,
"Latn",
}
m["sai-pnz"] = {
"Panzaleo",
3123275,
nil,
"Latn",
}
m["sai-prh"] = {
"Puruhá",
3410994,
nil,
"Latn",
}
m["sai-ptg"] = {
"Patagón",
nil,
nil,
"Latn",
}
m["sai-pur"] = {
"Purukotó",
7261622,
"sai-pem",
"Latn",
}
m["sai-pyg"] = {
"Payaguá",
7156643,
"sai-guc",
"Latn",
}
m["sai-pyk"] = {
"Pykobjê",
98113977,
"sai-nje",
"Latn",
}
m["sai-qmb"] = {
"Quimbaya",
7272043,
nil,
"Latn",
}
m["sai-qtm"] = {
"Quitemo",
7272651,
"sai-cpc",
"Latn",
}
m["sai-rab"] = {
"Rabona",
6644203,
nil,
"Latn",
}
m["sai-ram"] = {
"Ramanos",
16902824,
nil,
"Latn",
}
m["sai-sac"] = {
"Sácata",
5390321,
nil,
"Latn",
}
m["sai-san"] = {
"Sanaviron",
16895999,
nil,
"Latn",
}
m["sai-sap"] = {
"Sapará",
7420922,
"sai-car",
"Latn",
}
m["sai-sec"] = {
"Sechura",
7442912,
nil,
"Latn",
}
m["sai-sin"] = {
"Sinúfana",
7525275,
nil,
"Latn",
}
m["sai-sje-pro"] = {
"Proto-Southern Jê",
nil,
"sai-sje",
"Latn",
type = "reconstructed",
}
m["sai-tab"] = {
"Tabancale",
5390321,
nil,
"Latn",
}
m["sai-tal"] = {
"Tallán",
16910468,
nil,
"Latn",
}
m["sai-tap"] = {
"Tapayuna",
nil,
"sai-nje",
"Latn",
}
m["sai-tar-pro"] = {
"Proto-Taranoan",
nil,
"sai-tar",
"Latn",
type = "reconstructed",
}
m["sai-teu"] = {
"Teushen",
3519243,
nil,
"Latn",
}
m["sai-tim"] = {
"Timote",
nil,
nil,
"Latn",
}
m["sai-tpr"] = {
"Taparita",
7684460,
"sai-otm",
"Latn",
}
m["sai-trr"] = {
"Tarairiú",
7685313,
nil,
"Latn",
}
m["sai-wai"] = {
"Waitaká",
16918610,
nil,
"Latn",
}
m["sai-way"] = {
"Wayumará",
nil,
"sai-car",
"Latn",
}
m["sai-wit-pro"] = {
"Proto-Witotoan",
nil,
"sai-wit",
"Latn",
type = "reconstructed",
}
m["sai-wnm"] = {
"Wanham",
16879440,
"sai-cpc",
"Latn",
}
m["sai-xoc"] = { -- contrast xoo, kzw, sai-kat
"Xocó",
12953620,
nil,
"Latn",
}
m["sai-yao"] = {
"tiếng Yao (Nam Mĩ)",
nil,
"sai-ven",
"Latn",
"Tiếng Yao (Nam Mĩ)",
"Yao (Nam Mĩ)",
}
m["sai-yar"] = { -- not the same family as 'suy'
"Yarumá",
3505859,
"sai-pek",
"Latn",
}
m["sai-yri"] = {
"tiếng Yuri",
nil,
"sai-tyu",
"Latn",
"Tiếng Yuri",
"Yuri",
}
m["sai-yup"] = {
"Yupua",
8061430,
"sai-tuc",
"Latn",
}
m["sai-yur"] = {
"Yurumanguí",
1281291,
nil,
"Latn",
}
m["sal-pro"] = {
"tiếng Salish nguyên thủy",
nil,
"sal",
"Latn",
"Tiếng Salish nguyên thủy",
"Salish nguyên thủy",
type = "reconstructed",
}
m["sdv-daj-pro"] = {
"Proto-Daju",
nil,
"sdv-daj",
"Latn",
type = "reconstructed",
}
m["sdv-eje-pro"] = {
"Proto-Eastern Jebel",
nil,
"sdv-eje",
"Latn",
type = "reconstructed",
}
m["sdv-nil-pro"] = {
"Proto-Nilotic",
nil,
"sdv-nil",
"Latn",
type = "reconstructed",
}
m["sdv-nyi-pro"] = {
"Proto-Nyima",
nil,
"sdv-nyi",
"Latn",
type = "reconstructed",
}
m["sdv-tmn-pro"] = {
"Proto-Taman",
nil,
"sdv-tmn",
"Latn",
type = "reconstructed",
}
m["sel-nor"] = {
"tiếng Bắc Selkup",
30304565,
"sel",
"Cyrl",
"Tiếng Bắc Selkup",
"Bắc Selkup",
}
m["sel-pro"] = {
"tiếng Selkup nguyên thủy",
128884235,
"sel",
"Latn",
"Tiếng Selkup nguyên thủy",
"Selkup nguyên thủy",
type = "reconstructed",
}
m["sel-sou"] = {
"tiếng Nam Selkup",
30304639,
"sel",
"Cyrl",
"Tiếng Nam Selkup",
"Nam Selkup",
}
m["sem-amm"] = {
"Ammonite",
279181,
"sem-can",
"Phnx",
translit = "Phnx-translit",
}
m["sem-amo"] = {
"Amorite",
35941,
"sem-nwe",
"Xsux, Latn",
}
m["sem-cha"] = {
"Chaha",
nil,
"sem-eth",
"Ethi",
translit = "Ethi-translit",
ancestors = "sem-pro",
}
m["sem-dad"] = {
"Dadanitic",
21838040,
"sem-cen",
"Narb",
translit = "Narb-translit",
}
m["sem-dum"] = {
"Dumaitic",
nil,
"sem-cen",
"Narb",
translit = "Narb-translit",
}
m["sem-has"] = {
"Hasaitic",
3541433,
"sem-cen",
"Narb",
translit = "Narb-translit",
}
m["sem-him"] = {
"Himyaritic",
35604,
"sem",
"Arab, Sarb",
}
m["sem-his"] = {
"Hismaic",
22948260,
"sem-cen",
"Narb",
translit = "Narb-translit",
}
m["sem-mhr"] = {
"Muher",
33743,
"sem-eth",
"Latn",
}
m["sem-pro"] = {
"tiếng Semit nguyên thủy",
1658554,
"sem",
"Latn",
"Tiếng Semit nguyên thủy",
"Semit nguyên thủy",
type = "reconstructed",
}
m["sem-saf"] = {
"Safaitic",
472586,
"sem-cen",
"Narb",
translit = "Narb-translit",
}
m["sem-srb"] = {
"tiếng Nam Ả Rập cổ",
35025,
"sem-osa",
"Sarb",
"Tiếng Nam Ả Rập cổ",
"Nam Ả Rập cổ",
translit = "Sarb-translit",
}
m["sem-tay"] = {
"tiếng Tayma",
24912301,
"sem-cen",
"Narb",
"Tiếng Tayma",
"Tayma",
translit = "Narb-translit",
}
m["sem-tha"] = {
"Thamudic",
843030,
"sem-cen",
"Narb",
translit = "Narb-translit",
}
m["sem-wes-pro"] = {
"tiếng Semit Tây nguyên thủy",
98021726,
"sem-wes",
"Latn",
"Tiếng Semit Tây nguyên thủy",
"Semit Tây nguyên thủy",
type = "reconstructed",
}
m["sio-pro"] = { -- NB this is not Proto-Siouan-Catawban 'nai-sca-pro'
"tiếng Sioux nguyên thủy",
34181,
"sio",
"Latn",
"Tiếng Sioux nguyên thủy",
"Sioux nguyên thủy",
type = "reconstructed",
}
m["sit-aao-pro"] = {
"tiếng Naga Trung nguyên thủy",
nil,
"sit-aao",
"Latn",
"Tiếng Naga Trung nguyên thủy",
"Naga Trung nguyên thủy",
type = "reconstructed",
}
m["sit-bai-pro"] = {
"tiếng Bạch nguyên thủy",
nil,
"sit-bai",
"Latn",
"Tiếng Bạch nguyên thủy",
"Bạch nguyên thủy",
type = "reconstructed",
}
m["sit-ban"] = {
"Bangru",
56071779,
"sit-hrs",
"Latn",
}
m["sit-bdi-pro"] = {
"Proto-Bodish",
nil,
"sit-bdi",
"Latn",
type = "reconstructed",
}
m["sit-bok"] = {
"tiếng Bokar",
4938727,
"sit-tan",
"Latn, Tibt",
"Tiếng Bokar",
"Bokar",
translit = {Tibt = "Tibt-translit"},
override_translit = true,
display_text = {Tibt = s["Tibt-displaytext"]},
entry_name = {Tibt = s["Tibt-entryname"]},
sort_key = {Tibt = "Tibt-sortkey"},
}
m["sit-cha"] = {
"Chairel",
5068066,
"sit-luu",
"Latn",
}
m["sit-gkh"] = {
"Gokhy",
5578069,
"tbq-lol",
"Latn",
}
m["sit-hrs-pro"] = {
"Proto-Hrusish",
nil,
"sit-hrs",
type = "reconstructed",
}
m["sit-jap"] = {
"tiếng Japhug",
3162245,
"sit-egy",
"Latn",
"Tiếng Japhug",
"Japhug",
}
m["sit-kha-pro"] = {
"Proto-Kham",
nil,
"sit-kha",
type = "reconstructed",
}
m["sit-liz"] = {
"Lizu",
6660653,
"sit-qia",
"Latn", -- and Ersu Shaba
}
m["sit-lrn"] = {
"tiếng Lư Nhân",
6660653,
"sit-qia",
nil,
"Tiếng Lư Nhân",
"Lư Nhân",
}
m["sit-luu-pro"] = {
"Proto-Luish",
nil,
"sit-luu",
type = "reconstructed",
}
m["sit-mor"] = {
"Moran",
6909216,
"tbq-bdg",
"Latn",
}
m["sit-prn"] = {
"Puiron",
7259048,
"sit-zem",
}
m["sit-pro"] = {
"tiếng Hán-Tạng nguyên thủy",
45961,
"sit",
"Latn",
"Tiếng Hán-Tạng nguyên thủy",
"Hán-Tạng nguyên thủy",
type = "reconstructed",
}
m["sit-sit"] = {
"tiếng Tứ Thổ",
19840830,
"sit-egy",
"Latn",
"Tiếng Tứ Thổ",
"Tứ Thổ",
}
m["sit-tan-pro"] = {
"Proto-Tani",
nil,
"sit-tan",
"Latn", -- needs verification
type = "reconstructed",
}
m["sit-tgm"] = {
"Tangam",
17041370,
"sit-tan",
"Latn",
}
m["sit-tos"] = {
"Tosu",
7827899,
"sit-qia",
"Latn", -- also Ersu Shaba
}
m["sit-tsh"] = {
"Tshobdun",
19840950,
"sit-egy",
"Latn",
}
m["sit-zbu"] = {
"Zbu",
19841106,
"sit-egy",
"Latn",
}
m["sla-pro"] = {
"tiếng Slav nguyên thủy",
747537,
"sla",
"Latn",
"Tiếng Slav nguyên thủy",
"Slav nguyên thủy",
type = "reconstructed",
entry_name = {
remove_diacritics = c.grave .. c.acute .. c.tilde .. c.macron .. c.dgrave .. c.invbreve,
remove_exceptions = {'ś'},
},
sort_key = {
from = {"č", "ď", "ě", "ę", "ь", "ľ", "ň", "ǫ", "ř", "š", "ś", "ť", "ъ", "ž"},
to = {"c²", "d²", "e²", "e³", "i²", "l²", "nj", "o²", "r²", "s²", "s³", "t²", "u²", "z²"},
}
}
m["smi-pro"] = {
"tiếng Sami nguyên thủy",
7251862,
"smi",
"Latn",
"Tiếng Sami nguyên thủy",
"Sami nguyên thủy",
type = "reconstructed",
sort_key = {
from = {"ā", "č", "δ", "[ëē]", "ŋ", "ń", "ō", "š", "θ", "%([^()]+%)"},
to = {"a", "c²", "d", "e", "n²", "n³", "o", "s²", "t²"}
},
}
m["son-pro"] = {
"Proto-Songhay",
nil,
"son",
"Latn",
type = "reconstructed",
}
m["sqj-pro"] = {
"tiếng Albani nguyên thủy",
18210846,
"sqj",
"Latn",
"Tiếng Albani nguyên thủy",
"Albani nguyên thủy",
type = "reconstructed",
}
m["ssa-klk-pro"] = {
"Proto-Kuliak",
nil,
"ssa-klk",
"Latn",
type = "reconstructed",
}
m["ssa-kom-pro"] = {
"tiếng Koman nguyên thủy",
nil,
"ssa-kom",
"Latn",
"Tiếng Koman nguyên thủy",
"Koman nguyên thủy",
type = "reconstructed",
}
m["ssa-pro"] = {
"tiếng Nin-Sahara nguyên thủy",
nil,
"ssa",
"Latn",
"Tiếng Nin-Sahara nguyên thủy",
"Nin-Sahara nguyên thủy",
type = "reconstructed",
}
m["syd-fne"] = {
"Forest Nenets",
1295107,
"syd",
"Cyrl",
entry_name = {remove_diacritics = c.grave .. c.acute .. c.macron .. c.breve .. c.dotabove},
}
m["syd-pro"] = {
"tiếng Samoyed nguyên thủy",
7251863,
"syd",
"Latn",
"Tiếng Samoyed nguyên thủy",
"Samoyed nguyên thủy",
type = "reconstructed",
}
m["tai-pro"] = {
"tiếng Thái nguyên thủy",
6583709,
"tai",
"Latn",
"Tiếng Thái nguyên thủy",
"Thái nguyên thủy",
type = "reconstructed",
}
m["tai-swe-pro"] = {
"tiếng Tai Tây Nam nguyên thủy",
nil,
"tai-swe",
"Latn",
"Tiếng Tai Tây Nam nguyên thủy",
"Tai Tây Nam nguyên thủy",
type = "reconstructed",
}
m["tbq-bdg-pro"] = {
"tiếng Bodo-Garo nguyên thủy",
nil,
"tbq-bdg",
"Latn",
"Tiếng Bodo-Garo nguyên thủy",
"Bodo-Garo nguyên thủy",
type = "reconstructed",
}
m["tbq-kuk-pro"] = {
"Proto-Kuki-Chin",
nil,
"tbq-kuk",
"Latn",
type = "reconstructed",
}
m["tbq-lal-pro"] = {
"Proto-Lalo",
nil,
"tbq-lol",
"Latn",
type = "reconstructed",
}
m["tbq-laz"] = {
"Laze",
17007626,
"sit-nax",
}
m["tbq-lob-pro"] = {
"tiếng Lô Lô-Miến nguyên thủy",
116773224,
"tbq-lob",
"Latn",
"Tiếng Lô Lô-Miến nguyên thủy",
"Lô Lô-Miến nguyên thủy",
type = "reconstructed",
}
m["tbq-lol-pro"] = {
"Proto-Loloish",
7251855,
"tbq-lol",
"Latn",
type = "reconstructed",
}
m["tbq-ngo"] = {
"Ngochang",
nil,
"tbq-brm",
"Latn",
}
m["tbq-plg"] = {
"Pai-lang",
2879843,
"tbq-lob",
"Hani, Latn",
sort_key = {Hani = "Hani-sortkey"},
}
-- tbq-pro is now etymology-only
m["trk-dkh"] = {
"tiếng Dukha",
nil,
"trk-sib",
"Latn, Cyrl, Mong",
"Tiếng Dukha",
"Dukha",
translit = {Mong = "Mong-translit"},
display_text = {Mong = s["Mong-displaytext"]},
entry_name = {Mong = s["Mong-entryname"]},
}
m["trk-eog"] = {
"tiếng Oghuz cổ sơ kỳ",
nil,
"trk-ogz",
"ota-Arab",
strip_diacritics = {["ota-Arab"] = "ar-stripdiacritics"},
}
m["trk-fyk"] = {
"tiếng Kyrgyz Phú Dụ",
2598963,
nil,
"Latn",
"Tiếng Kyrgyz Phú Dụ",
"Kyrgyz Phú Dụ",
}
m["trk-oat"] = {
"tiếng Thổ Nhĩ Kỳ Anatolia cổ",
7083390,
"trk-ogz",
"ota-Arab",
strip_diacritics = {["ota-Arab"] = "ar-stripdiacritics"},
ancestors = "trk-eog",
"Tiếng Thổ Nhĩ Kỳ Anatolia cổ",
"Thổ Nhĩ Kỳ Anatolia cổ",
}
m["trk-pro"] = {
"tiếng Turk nguyên thủy",
3657773,
"trk",
"Latn",
"Tiếng Turk nguyên thủy",
"Turk nguyên thủy",
type = "reconstructed",
}
m["trk-soy"] = {
"tiếng Soyot",
4426878,
"trk",
"Cyrl",
"Tiếng Soyot",
"Soyot",
translit = "trk-soy-translit",
}
m["tup-gua-pro"] = {
"tiếng Tupi-Guarani nguyên thủy",
nil,
"tup-gua",
"Latn",
"Tiếng Tupi-Guarani nguyên thủy",
"Tupi-Guarani nguyên thủy",
type = "reconstructed",
}
m["tup-kab"] = {
"Kabishiana",
15302988,
"tup",
"Latn",
}
m["tup-pro"] = {
"tiếng Tupi nguyên thủy",
10354700,
"tup",
"Latn",
"Tiếng Tupi nguyên thủy",
"Tupi nguyên thủy",
type = "reconstructed",
}
m["tuw-alk"] = {
"tiếng Alchuka",
113553616,
"tuw-jrc",
"Latn, Hans",
"Tiếng Alchuka",
"Alchuka",
sort_key = {Hans = "Hani-sortkey"},
}
m["tuw-bal"] = {
"tiếng Bala",
86730632,
"tuw-jrc",
"Latn, Hans",
"Tiếng Bala",
"Bala",
sort_key = {Hans = "Hani-sortkey"},
}
m["tuw-kil"] = {
"tiếng Kili",
6406892,
"tuw",
nil,
"Tiếng Kili",
"Kili",
}
m["tuw-pro"] = {
"tiếng Tungus nguyên thủy",
nil,
"tuw",
"Latn",
"Tiếng Tungus nguyên thủy",
"Tungus nguyên thủy",
type = "reconstructed",
}
m["tuw-kkl"] = {
"tiếng Kyakala",
nil,
"tuw",
"Latn, Hani",
"Tiếng Kyakala",
"Kyakala",
sort_key = {Hani = "Hani-sortkey"},
}
m["tuw-sol"] = {
"tiếng Solon",
30004,
"tuw",
nil,
"Tiếng Solon",
"Solon",
}
m["und-isa"] = {
"Isaurian",
16956868,
nil,
-- "Xsux, Hluw, Latn",
}
m["und-kas"] = {
"Kassite",
35612,
nil,
"Xsux",
}
m["und-mil"] = {
"Milang",
6850761,
nil,
"Deva, Latn",
}
m["und-mmd"] = {
"Mimi of Decorse",
6862206,
nil,
"Latn",
}
m["und-mmn"] = {
"Mimi of Nachtigal",
6862207,
nil,
"Latn",
}
m["und-phi"] = {
"Philistine",
2230924,
nil,
"Phnx",
}
m["und-wji"] = {
"Western Jicaque",
3178610,
"hok",
"Latn",
}
m["urj-fin-pro"] = {
"tiếng Finn nguyên thủy",
11883720,
"urj-fin",
"Latn",
"Tiếng Finn nguyên thủy",
"Finn nguyên thủy",
type = "reconstructed",
}
m["urj-koo"] = {
"tiếng Komi cổ",
nil,
"urj-prm",
"Perm, Cyrs",
"Tiếng Komi cổ",
"Komi cổ",
translit = "urj-koo-translit",
sort_key = {Cyrs = s["Cyrs-sortkey"]},
}
m["urj-kuk"] = {
"Kukkuzi",
107410460,
"urj-fin",
"Latn",
ancestors = "vot",
}
m["urj-kya"] = {
"tiếng Komi-Yazva",
2365210,
"urj-prm",
"Cyrl",
"Tiếng Komi-Yazva",
"Komi-Yazva",
translit = "kv-translit",
override_translit = true,
entry_name = {remove_diacritics = c.acute},
}
m["urj-mdv-pro"] = {
"tiếng Mordvin nguyên thủy",
nil,
"urj-mdv",
"Latn",
"Tiếng Mordvin nguyên thủy",
"Mordvin nguyên thủy",
type = "reconstructed",
}
m["urj-prm-pro"] = {
"tiếng Perm nguyên thủy",
nil,
"urj-prm",
"Latn",
"Tiếng Perm nguyên thủy",
"Perm nguyên thủy",
type = "reconstructed",
}
m["urj-pro"] = {
"tiếng Ural nguyên thủy",
288765,
"urj",
"Latn",
"Tiếng Ural nguyên thủy",
"Ural nguyên thủy",
type = "reconstructed",
}
m["urj-ugr-pro"] = {
"tiếng Ugria nguyên thủy",
156631,
"urj-ugr",
"Latn",
"Tiếng Ugria nguyên thủy",
"Ugria nguyên thủy",
type = "reconstructed",
}
m["xnd-pro"] = {
"Proto-Na-Dene",
nil,
"xnd",
"Latn",
type = "reconstructed",
}
m["xgn-mgr"] = {
"tiếng Mangghuer",
34214,
"mjg",
"Latn", -- also Mong, Cyrl ?
"Tiếng Mangghuer",
"Mangghuer",
}
m["xgn-mgl"] = {
"tiếng Mongghul",
34214,
"mjg",
"Latn", -- also Mong, Cyrl ?
"Tiếng Mongghul",
"Mongghul",
}
m["xgn-pro"] = {
"tiếng Mông Cổ nguyên thủy",
2493677,
"xgn",
"Latn",
"Tiếng Mông Cổ nguyên thủy",
"Mông Cổ nguyên thủy",
type = "reconstructed",
}
m["ypk-pro"] = {
"Proto-Yupik",
nil,
"ypk",
"Latn",
type = "reconstructed",
}
m["zhx-min-pro"] = {
"tiếng Mân nguyên thủy",
19646347,
"zhx-min",
"Latn",
"Tiếng Mân nguyên thủy",
"Mân nguyên thủy",
type = "reconstructed",
}
m["zhx-sht"] = {
"Shaozhou Tuhua",
1920769,
"zhx",
"Nshu, Hani, Hant, Hans",
generate_forms = "zh-generateforms",
sort_key = {Hani = "Hani-sortkey"},
}
m["zhx-sic"] = {
"tiếng Tứ Xuyên",
2278732,
"zhx-man",
"Hants",
"Tiếng Tứ Xuyên",
"Tứ Xuyên",
generate_forms = "zh-generateforms",
translit = "zh-translit",
sort_key = "Hani-sortkey",
}
m["zhx-tai"] = {
"tiếng Đài Sơn",
2208940,
"zhx",
"Hani, Hant, Hans",
"Tiếng Đài Sơn",
"Đài Sơn",
ancestors = "yue",
generate_forms = "zh-generateforms",
translit = "zh-translit",
sort_key = "Hani-sortkey",
}
m["zhx-taz"] = {
"tiếng Taz",
3516511,
"zhx",
nil,
"Tiếng Taz",
"Taz",
}
m["zhx-twa"] = {
"tiếng Đường Uông",
7683179,
"zhx",
"Hani",
"Tiếng Đường Uông",
"Đường Uông",
}
m["zle-ono"] = {
"tiếng Novgorod cổ",
162013,
"zle",
"Cyrs, Glag",
"Tiếng Novgorod cổ",
"Novgorod cổ",
translit = "Cyrs-Glag-translit",
entry_name = {Cyrs = s["Cyrs-entryname"]},
sort_key = {Cyrs = s["Cyrs-sortkey"]},
}
m["zle-ort"] = {
"tiếng Ruthenia cổ",
13211,
"zle",
"Cyrs",
"Tiếng Ruthenia cổ",
"Ruthenia cổ",
ancestors = "orv",
translit = "zle-ort-translit",
entry_name = {
remove_diacritics = s["Cyrs-entryname"].remove_diacritics,
remove_exceptions = {"Ї", "ї"}
},
sort_key = s["Cyrs-sortkey"],
}
m["zls-chs"] = {
"tiếng Slav Giáo hội",
33251,
"zls",
"Cyrs, Glag, Latn",
"Tiếng Slav Giáo hội",
"Slav Giáo hội",
ancestors = "cu",
translit = {
Cyrs = "Cyrs-translit",
Glag = "Glag-translit"
},
entry_name = {
Cyrs = s["Cyrs-entryname"]
},
sort_key = {
Cyrs = s["Cyrs-sortkey"]
},
}
m["zlw-ocs"] = {
"tiếng Séc cổ",
593096,
"zlw",
"Latn",
"Tiếng Séc cổ",
"Séc cổ",
}
m["zlw-osk"] = {
"tiếng Slovak cổ",
12776676,
"zlw",
"Latn",
"Tiếng Slovak cổ",
"Slovak cổ",
}
m["zlw-opl"] = {
"tiếng Ba Lan cổ",
149838,
"zlw-lch",
"Latn",
"Tiếng Ba Lan cổ",
"Ba Lan cổ",
entry_name = {remove_diacritics = c.ringabove},
}
m["zlw-pom-pro"] = {
"Proto-Pomeranian",
149588,
"zlw-pom",
"Latn",
type = "reconstructed",
}
m["zlw-slv"] = {
"tiếng Slovincia",
36822,
"zlw-pom",
"Latn",
"Tiếng Slovincia",
"Slovincia",
ancestors = "zlw-pom-pro",
entry_name = "zlw-slv-entryname"
}
m["aav-qal"] = {
"tiếng Quảng Lâm",
19894302,
"mkh-pal",
"Latn",
"Tiếng Quảng Lâm",
"Quảng Lâm",
}
return require("Module:languages").finalizeData(m, "language")
8s1t8v06w5s74kz456bx84n431dy6bv
хирлиг
0
280304
2344420
2098370
2026-04-12T05:07:27Z
Hiyuune
50834
2344420
wikitext
text/x-wiki
=={{langname|tyv}}==
==={{section|pron}}===
* {{IPA4|tyv|/xɪrˈlɪɣ/}}
==={{section|adj}}===
{{tyv-adj}}
# [[bẩn|Bẩn]]; không [[sạch]].
===={{section|ant}}====
* {{l|tyv|арыг}}
j75oo5hdbdgv9fptmv3tlkebpy1pvj5
боктуг
0
280305
2344422
2098371
2026-04-12T05:09:24Z
Hiyuune
50834
2344422
wikitext
text/x-wiki
=={{langname|tyv}}==
==={{section|adj}}===
{{tyv-adj}}
# [[bẩn|Bẩn]].
qcg6dqfrtai9uoc1fvdhch055uh3ql4
алгыг
0
280308
2344424
2098374
2026-04-12T05:10:53Z
Hiyuune
50834
2344424
wikitext
text/x-wiki
=={{langname|tyv}}==
==={{section|adj}}===
{{tyv-noun}}
# [[rộng|Rộng]].
#: {{syn|tyv|делгем}}
hsdmf0rwl3wryl7i9sdb35831ftu5wz
2344425
2344424
2026-04-12T05:11:01Z
Hiyuune
50834
2344425
wikitext
text/x-wiki
=={{langname|tyv}}==
==={{section|adj}}===
{{tyv-adj}}
# [[rộng|Rộng]].
#: {{syn|tyv|делгем}}
nqt41gaila5hz5bzwqh7k5njf35meal
Mô đun:khb-headword
828
281409
2344395
2245017
2026-04-12T04:50:12Z
Hiyuune
50834
2344395
Scribunto
text/plain
local export = {}
local pos_functions = {}
local lang = require("Module:languages").getByCode("khb")
local PAGENAME = mw.loadData("Module:headword/data").pagename
local script = lang:findBestScript(PAGENAME) -- Talu hoặc Lana
function export.show(frame)
local args = frame:getParent().args
local poscat = frame.args[1] or error("Từ loại không được chỉ ró. Vui lòng thêm tham số đầu tiên để gọi mô đun.")
local head = args["head"]
local tr = args["tr"]
local data = {
lang = lang,
pos_category = poscat,
categories = {},
sccat = true,
heads = {head},
translits = {tr},
inflections = {}
}
local lana = {label = "chính tả Tày Lự cũ", lang = lang, sc = require("Module:scripts").getByCode("Lana")}
if args["l"] then table.insert(lana, args["l"]) end
if args["l2"] then table.insert(lana, args["l2"]) end
if args["l3"] then table.insert(lana, args["l3"]) end
if #lana > 0 then table.insert(data.inflections, lana) end
if pos_functions[poscat] then
pos_functions[poscat](args, data)
end
return require("Module:headword").full_headword(data)
end
pos_functions["Danh từ"] = function(args, data)
local classifiers = {label = "loại từ"}
if args[1] then
for _,par in ipairs(args) do
if par == "*" then
table.insert(classifiers, PAGENAME) -- shorthand
table.insert(data.categories, "Loại từ tiếng Lự")
table.insert(data.categories, "Danh từ có loại từ " .. PAGENAME .. " tiếng Lự")
else
table.insert(classifiers, par)
table.insert(data.categories, "Danh từ có loại từ " .. par .. " tiếng Lự")
end
end
table.insert(data.inflections, classifiers)
end
end
pos_functions["Động từ"] = function(args, data)
local par1 = args[1]; if par1 == "" then par1 = nil end
local par2 = args[2]; if par2 == "" then par2 = nil end
local par3 = args[3]; if par3 == "" then par3 = nil end
local abstract_forms = {label = "danh từ trừu tượng", accel = {pos = "Danh từ", form = "abstract-noun"}}
if par1 ~= "-" then
if not par1 then
table.insert(abstract_forms, (script:getCode() == "Talu" and "ᦂᦱᧃ" or "ᨠᩣ᩠ᩁ") .. PAGENAME)
else
if par1 == "~" then
table.insert(abstract_forms, (script:getCode() == "Talu" and "ᦂᦱᧃ" or "ᨠᩣ᩠ᩁ") .. PAGENAME)
table.insert(abstract_forms, (script:getCode() == "Talu" and "ᦩᦱᧄ" or "ᨤ᩠ᩅᩣ᩠ᨾ") .. PAGENAME)
else
table.insert(abstract_forms, par1)
table.insert(abstract_forms, par2)
table.insert(abstract_forms, par3)
end
end
table.insert(data.inflections, abstract_forms)
end
end
pos_functions["Tính từ"] = function(args, data)
local par1 = args[1]; if par1 == "" then par1 = nil end
local par2 = args[2]; if par2 == "" then par2 = nil end
local par3 = args[3]; if par3 == "" then par3 = nil end
local abstract_forms = {label = "danh từ trừu tượng", accel = {pos = "Danh từ", form = "abstract-noun"}}
if par1 ~= "-" then
if not par1 then
table.insert(abstract_forms, (script:getCode() == "Talu" and "ᦩᦱᧄ" or "ᨤ᩠ᩅᩣ᩠ᨾ") .. PAGENAME)
else
table.insert(abstract_forms, par1)
table.insert(abstract_forms, par2)
table.insert(abstract_forms, par3)
end
table.insert(data.inflections, abstract_forms)
end
end
-- same logic
pos_functions["Phó từ"] = pos_functions["Tính từ"]
return export
sdmksgbcwzmfrmg90int19aeptou33i
Mô đun:anchors
828
284089
2344296
2299099
2026-04-11T15:54:35Z
TheHighFighter2
42988
2344296
Scribunto
text/plain
local export = {}
local string_utilities_module = "Module:string utilities"
local ucfirst = require("Module:string utilities").ucfirst
local anchor_encode = mw.uri.anchorEncode
local concat = table.concat
local insert = table.insert
local language_anchor -- Defined below.
local function decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function encode_entities(...)
encode_entities = require(string_utilities_module).encode_entities
return encode_entities(...)
end
-- Returns the anchor text to be used as the fragment of a link to a language section.
function export.language_anchor(lang, id)
return anchor_encode(ucfirst(lang:getFullName()) .. ": " .. id)
end
language_anchor = export.language_anchor
-- Normalizes input text (removes formatting etc.), which can then be used as an anchor in an `id=` field.
function export.normalize_anchor(str)
return decode_entities(anchor_encode(str))
end
function export.make_anchors(ids)
local anchors = {}
for i = 1, #ids do
local id = ids[i]
insert(anchors, "<span class=\"template-anchor\" id=\"" .. anchor_encode(id) .. "\" data-id=\"" .. encode_entities(id) .. "\"></span>")
end
return concat(anchors)
end
function export.senseid(lang, id, tag_name)
-- The following tag is opened but never closed, where is it supposed to be closed?
-- with <li> it doesn't matter, as it is closed automatically.
-- with <p> it is a problem
return "<" .. tag_name .. " class=\"senseid\" id=\"" .. language_anchor(lang, id) .. "\" data-lang=\"" .. lang:getCode() .. "\" data-id=\"" .. encode_entities(id) .. "\">"
end
function export.etymid(lang, id)
-- Use a <ul> tag to ensure spacing doesn't get messed up.
return "<ul class=\"etymid\" id=\"" .. language_anchor(lang, id) .. "\" data-lang=\"" .. lang:getCode() .. "\" data-id=\"" .. encode_entities(id) .. "\"></ul>"
end
function export.etymonid(lang, id)
-- Use a <ul> tag to ensure spacing doesn't get messed up.
return "<ul class=\"etymonid\" id=\"" .. language_anchor(lang, id) .. "\" data-lang=\"" .. lang:getCode() .. "\" data-id=\"" .. encode_entities(id) .. "\"></ul>"
end
return export
qsl4iurtak58jv52szlqxc2g663z1by
2344304
2344296
2026-04-11T23:54:39Z
TheHighFighter2
42988
Đã lùi lại sửa đổi [[Special:Diff/2344296|2344296]] của [[Special:Contributions/TheHighFighter2|TheHighFighter2]] ([[User talk:TheHighFighter2|thảo luận]])
2344304
Scribunto
text/plain
local export = {}
local string_utilities_module = "Module:string utilities"
local anchor_encode = mw.uri.anchorEncode
local concat = table.concat
local insert = table.insert
local language_anchor -- Defined below.
local function decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function encode_entities(...)
encode_entities = require(string_utilities_module).encode_entities
return encode_entities(...)
end
-- Returns the anchor text to be used as the fragment of a link to a language section.
function export.language_anchor(lang, id)
return anchor_encode(lang:getFullName() .. ": " .. id)
end
language_anchor = export.language_anchor
-- Normalizes input text (removes formatting etc.), which can then be used as an anchor in an `id=` field.
function export.normalize_anchor(str)
return decode_entities(anchor_encode(str))
end
function export.make_anchors(ids)
local anchors = {}
for i = 1, #ids do
local id = ids[i]
insert(anchors, "<span class=\"template-anchor\" id=\"" .. anchor_encode(id) .. "\" data-id=\"" .. encode_entities(id) .. "\"></span>")
end
return concat(anchors)
end
function export.senseid(lang, id, tag_name)
-- The following tag is opened but never closed, where is it supposed to be closed?
-- with <li> it doesn't matter, as it is closed automatically.
-- with <p> it is a problem
return "<" .. tag_name .. " class=\"senseid\" id=\"" .. language_anchor(lang, id) .. "\" data-lang=\"" .. lang:getCode() .. "\" data-id=\"" .. encode_entities(id) .. "\">"
end
function export.etymid(lang, id)
-- Use a <ul> tag to ensure spacing doesn't get messed up.
return "<ul class=\"etymid\" id=\"" .. language_anchor(lang, id) .. "\" data-lang=\"" .. lang:getCode() .. "\" data-id=\"" .. encode_entities(id) .. "\"></ul>"
end
function export.etymonid(lang, id)
-- Use a <ul> tag to ensure spacing doesn't get messed up.
return "<ul class=\"etymonid\" id=\"" .. language_anchor(lang, id) .. "\" data-lang=\"" .. lang:getCode() .. "\" data-id=\"" .. encode_entities(id) .. "\"></ul>"
end
return export
buie2kpbi0kb4hc2y1x9ovsfm754yk9
2344320
2344304
2026-04-12T01:45:32Z
TheHighFighter2
42988
2344320
Scribunto
text/plain
local export = {}
local string_utilities_module = "Module:string utilities"
local anchor_encode = mw.uri.anchorEncode
local concat = table.concat
local insert = table.insert
local language_anchor -- Defined below.
local function decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function encode_entities(...)
encode_entities = require(string_utilities_module).encode_entities
return encode_entities(...)
end
-- Returns the anchor text to be used as the fragment of a link to a language section.
function export.language_anchor(lang, id)
return anchor_encode(lang:getFullName() .. ": " .. id)
end
language_anchor = export.language_anchor
-- Normalizes input text (removes formatting etc.), which can then be used as an anchor in an `id=` field.
function export.normalize_anchor(str)
return decode_entities(anchor_encode(str))
end
function export.make_anchors(ids)
local anchors = {}
for i = 1, #ids do
local id = ids[i]
local el = mw.html.create("span")
:addClass("template-anchor")
:attr("id", anchor_encode(id))
:attr("data-id", id)
insert(anchors, tostring(el))
end
return concat(anchors)
end
function export.senseid(lang, id, tag_name)
-- The following tag is opened but never closed, where is it supposed to be closed?
-- with <li> it doesn't matter, as it is closed automatically.
-- with <p> it is a problem
-- Cannot use mw.html here as it always closes tags
return "<" .. tag_name .. " class=\"senseid\" id=\"" .. language_anchor(lang, id) .. "\" data-lang=\"" .. lang:getCode() .. "\" data-id=\"" .. encode_entities(id) .. "\">"
end
function export.etymid(lang, id)
-- Use a <ul> tag to ensure spacing doesn't get messed up.
local el = mw.html.create("ul")
:addClass("etymid")
:attr("id", language_anchor(lang, id))
:attr("data-lang", lang:getCode())
:attr("data-id", id)
return tostring(el)
end
function export.etymonid(lang, id, opts)
opts = opts or {}
-- Use a <ul> tag to ensure spacing doesn't get messed up.
local el = mw.html.create("ul")
:addClass("etymonid")
:attr("data-lang", lang:getCode())
if id then
el:attr("id", language_anchor(lang, id))
el:attr("data-id", id)
end
if opts.no_tree then
el:attr("data-no-tree", "1")
end
if opts.title then
el:attr("data-title", opts.title)
end
if opts.empty_tree then
el:attr("data-empty-tree", "1")
end
return tostring(el)
end
return export
d0onsd99m5ccscopc1i38n0lhzar2z3
Bản mẫu:etymid
10
286106
2344435
2110882
2026-04-12T06:09:15Z
TheHighFighter2
42988
2344435
wikitext
text/x-wiki
<includeonly><onlyinclude>{{safesubst:<noinclude/>#invoke:anchors/templates|etymid_t}}</onlyinclude></includeonly><!--
-->{{documentation}}
sm3f1lxol1knum6i82u5texr7lxd45d
hızlı
0
289941
2344427
2122980
2026-04-12T05:14:16Z
Hiyuune
50834
2344427
wikitext
text/x-wiki
=={{langname|gag}}==
==={{section|adj}}===
{{head|gag|Tính từ}}
# [[nhanh|Nhanh]].
#: {{syn|gag|çabuk}}
=={{langname|tr}}==
==={{section|adj}}===
Từ {{inh|tr|ota|حزلو|tr=hızlı}}, tương đương từ {{suffix|tr|hız|-li|alt2=-lı}}.
==={{section|pron}}===
* {{tr-IPA}}
* {{audio|tr|LL-Q256 (tur)-ToprakM-hızlı.wav}}
* {{rhymes|tr|ɯ|s=2}}
==={{section|adj}}===
{{tr-adj}}
# [[nhanh|Nhanh]].
#: {{syn|tr|süratli}}
===={{section|decl}}====
{{tr-pred-c-adj|stem=hızlıy|ı|d}}
===={{section|ant}}====
* {{l|tr|yavaş}}
ilh1jd4jfa1v48pzp53y74piyikh7an
ōlaʻi
0
307153
2344360
2168084
2026-04-12T03:06:08Z
Kelly zhrm
58416
2344360
wikitext
text/x-wiki
=={{langname|haw}}==
==={{ĐM|pron}}===
* {{haw-IPA}}
==={{ĐM|n}}===
{{head|haw|Danh từ}}
# [[động đất|Động đất]].
0nmlyp6pirlfqj2qlrqdvwc5me73jnz
南蛮烏瓜
0
318793
2344462
2190198
2026-04-12T09:16:25Z
WhoAlone
40420
2344462
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|なん|ばん|からす|うり|yomi=o2,k2}}
{{wikipedia|lang=ja|ナンバンカラスウリ}}
==={{ĐM|etym}}===
{{compound|ja|南蛮|烏瓜|tr1=Nanban|t1={{w|Nanman}}|tr2=karasuuri|t2=[[Japanese]] [[snake gourd]]}}
==={{ĐM|noun}}===
{{ja-noun|^なんばん からす.うり|^ナンバン カラス.ウリ}}
# [[gấc|Gấc]]
==={{ĐM|synonym}}===
* {{ja-r|木%鼈%子|モク%ベツ%シ}}
{{C|ja|Họ Bầu bí|Trái cây}}
9th6coxtvpl8do9cpx06422vv14vhgz
klimaendring
0
318990
2344439
2190677
2026-04-12T06:40:27Z
Kelly zhrm
58416
2344439
wikitext
text/x-wiki
=={{langname|nb}}==
{{Wikipedia|no:}}
==={{ĐM|etym}}===
Từ {{affix|nb|klima|endring}}.
==={{ĐM|n}}===
{{nb-noun-c}}
# [[biến đổi|Biến đổi]] [[khí hậu]]
==={{ĐM|ref}}===
* {{R:NAOB}}
=={{langname|nn}}==
{{Wikipedia|lang=nn}}
==={{ĐM|etym}}===
Từ ghép giữa {{compound|nn|klima|t1=khí hậu|endring|t2=thay đổi, biến đổi}}.
==={{ĐM|pron}}===
* {{IPA4|nn|/kliːmaɛndriŋɡ/}}
==={{ĐM|n}}===
{{nn-noun-f3}}
# [[biến đổi|Biến đổi]] [[khí hậu]]
==={{ĐM|ref}}===
* {{R:The Nynorsk Dictionary}}
ez69m8ux7ro17uya73y38xb3oiq84mq
Mô đun:etymon
828
331836
2344307
2317904
2026-04-12T01:10:51Z
TheHighFighter2
42988
2344307
Scribunto
text/plain
--[=[
This module implements the {{etymon}} template for structured etymology data on Wiktionary.
It enables the creation of etymology trees and text by parsing etymon chains,
scraping linked pages for their own {{etymon}} data, and recursively building a tree
of derivational relationships.
Tác giả:
- Triển khai ban đầu: [[Thành viên:Ioaxxere]]
- Tái cấu trúc lại mô đun (tháng 9 năm 2025): [[Thành viên:Fenakhay]] ([[:en:Special:Diff/86717746]])
Modules:
- [[Module:etymon]]: main module handling parsing, validation, tree building, and page scraping
- [[Module:etymon/data]]: keyword definitions, configuration, and status constants
- [[Module:etymon/tree]]: etymology tree rendering
- [[Module:etymon/text]]: etymology text generation
- [[Module:etymon/categories]]: category generation logic
]=]
local export = {}
local etymon_data_module = "Module:etymon/data"
local etymon_text_module = "Module:etymon/text"
local etymon_tree_module = "Module:etymon/tree"
local etymon_categories_module = "Module:etymon/categories"
local etymon_descendants_module = "Module:etymon/descendants"
local __state = {
cached_etymon_args = {},
cached_etymon_pages = {},
cached_descendants_checks = {},
senseid_parent_etymon = {},
available_etymon_ids = {},
single_etymons = {},
entry_title = nil,
entry_lang_code = nil,
current_page_has_inline_etymology = false,
current_page_has_redundant_etymology = false,
used_idless_etymon = false,
toplevel_has_inline_etymology = false,
toplevel_redundant_etymology = false,
toplevel_idless_etymon = false,
has_mismatched_id = false,
max_depth_reached = 0,
total_nodes = 0,
language_count = {},
toplevel_keyword_stats = {},
warnings = {},
}
local loader = require("Module:module loader")
local M = loader.init({
require = {
data = etymon_data_module,
tree = etymon_tree_module,
text = etymon_text_module,
categories = etymon_categories_module,
descendants = etymon_descendants_module,
anchors = "Module:anchors",
etydate = "Module:etydate",
etymology = "Module:etymology",
families = "Module:families",
languages = "Module:languages",
languages_errorgetby = "Module:languages/errorGetBy",
links = "Module:links",
pages = "Module:pages",
parameters = "Module:parameters",
string_utilities = "Module:string utilities",
template_parser = "Module:template parser",
utilities = "Module:utilities",
debug = "Module:debug",
en_utilities = "Module:en-utilities",
parse_utilities = "Module:parse utilities",
references = "Module:references",
track = "Module:debug/track",
template_styles = "Module:TemplateStyles",
script_utilities = "Module:script utilities",
JSON = "Module:JSON",
yesno = "Module:yesno",
},
loadData = {
headword_data = "Module:headword/data",
parameters_data = "Module:parameters/data",
text_allowed = "Module:etymon/data/text_allowed",
},
})
local Util = {}
function Util.format_error(message, preview_only)
if preview_only and not M.pages.is_preview() then
return nil
end
return '<span class="error">' .. message .. '</span>'
end
function Util.add_warning(message, preview_only)
local formatted = Util.format_error(message, preview_only)
if formatted then
table.insert(__state.warnings, formatted)
end
end
function Util.is_text_param_allowed_for_lang(lang)
if not lang or type(lang) ~= "table" then
return false
end
local types = lang.getTypes and lang:getTypes()
if types and types.family then
local code = lang.getCode and lang:getCode()
return code and M.text_allowed.families[code] == true
end
local full_code = lang.getFullCode and lang:getFullCode()
if full_code and M.text_allowed.langs[full_code] then
return true
end
if lang.inFamily then
for family_code in pairs(M.text_allowed.families) do
if lang:inFamily(family_code) then
return true
end
end
end
return false
end
function Util.get_lang(code, no_error)
if no_error then
return M.languages.getByCode(code, nil, true)
end
return M.languages.getByCode(code, nil, true) or M.languages_errorgetby.code(code, true, true)
end
function Util.get_family(code)
return M.families.getByCode(code)
end
function Util.get_lang_exception(lang)
-- Families have no language-specific exceptions
if lang.getTypes and lang:getTypes().family then
return nil
end
local code = lang:getCode()
local lang_exceptions = M.data.config.lang_exceptions
if lang_exceptions[code] then
return lang_exceptions[code]
end
for norm_code, exc in pairs(lang_exceptions) do
if exc.normalize_to and code == exc.normalize_to then
return exc
end
if exc.normalize_from_families then
local should_normalize = false
for _, family in ipairs(exc.normalize_from_families) do
if lang:inFamily(family) then
should_normalize = true
break
end
end
if should_normalize and exc.normalize_exclude_families then
for _, family in ipairs(exc.normalize_exclude_families) do
if lang:inFamily(family) then
should_normalize = false
break
end
end
end
if should_normalize then
local ret = {}
for k, v in pairs(exc) do
ret[k] = v
end
ret.suppress_tr = nil
return ret
end
end
end
return nil
end
function Util.get_norm_lang(lang)
local exc = Util.get_lang_exception(lang)
if exc and exc.normalize_to then
return M.languages.getByCode(exc.normalize_to)
end
return lang
end
-- Add default values for boolean modifiers (e.g., <unc> becomes <unc:1>)
-- This is needed because Module:parse utilities expects boolean modifiers to have explicit values
function Util.add_boolean_defaults(str, param_mods)
local result = str
for name, spec in pairs(param_mods) do
if spec.type == "boolean" then
-- Replace <name> with <name:1> (but not <name:...> which already has a value)
result = result:gsub("<" .. name .. ">", "<" .. name .. ":1>")
end
end
return result
end
-- Centralized term formatting: handles suppress_term, unknown_term, and regular terms
function Util.format_term(term, is_toplevel, opts)
opts = opts or {}
-- suppress_term (-) returns nil
if term.suppress_term then
return nil
end
local lang = term.lang
local exc = Util.get_lang_exception(lang)
if is_toplevel then
local display_text = term.alt or term.title or ""
local sc = term.sc or lang:findBestScript(display_text)
local bold_text = tostring(mw.html.create("strong")
:addClass("selflink")
:wikitext(display_text))
return M.script_utilities.tag_text(bold_text, lang, sc, "term")
end
local link_params = { lang = lang }
link_params.term = not term.unknown_term and term.title or nil
link_params.alt = term.alt
link_params.id = (not term.unknown_term and term.id and term.id ~= "") and term.id or nil
if not (exc and exc.suppress_tr) then
link_params.tr = term.tr
link_params.ts = term.ts
else
link_params.suppress_tr = true
end
link_params.lit = (opts.lit ~= "suppress") and term.lit or nil
if opts.gloss ~= "suppress" then
link_params.gloss = term.t
end
if opts.pos ~= "suppress" then
link_params.pos = term.pos
end
if exc and exc.suppress_tr then
link_params.lit = nil
end
local show_qualifiers
if opts.tree_ql ~= "suppress" then
if term.q then
link_params.q = term.q
end
if term.qq then
link_params.qq = term.qq
end
if term.l then
link_params.l = term.l
end
if term.ll then
link_params.ll = term.ll
end
show_qualifiers = term.q or term.qq or term.l or term.ll
end
return M.links.full_link(link_params, "term", nil, show_qualifiers and true or nil)
end
local __is_content_page_cached
function Util.is_content_page()
if __is_content_page_cached == nil then
__is_content_page_cached = M.pages.is_content_page(mw.title.getCurrentTitle())
end
return __is_content_page_cached
end
local __page_data_cached
function Util.get_page_data()
if not __page_data_cached then
__page_data_cached = M.headword_data.page
end
return __page_data_cached
end
-- Extract base keyword from param (without modifiers)
local function get_keyword_base(param)
if type(param) ~= "string" then return nil end
local base = param:match("^:?([^<]+)") or param:gsub("^:", "")
return base
end
local function is_keyword(param, allow_colon_less)
if type(param) ~= "string" then return false end
local keywords = M.data.keywords
if param:sub(1, 1) == ":" then
local base = get_keyword_base(param)
return keywords[base] ~= nil
end
if allow_colon_less then
local base = get_keyword_base(param)
return keywords[base] ~= nil
end
return false
end
local function get_keyword(param, allow_colon_less)
if type(param) ~= "string" then return nil end
local keywords = M.data.keywords
if param:sub(1, 1) == ":" then
return get_keyword_base(param)
end
if allow_colon_less then
local base = get_keyword_base(param)
if keywords[base] then
return base
end
end
return nil
end
local function normalize_keyword(keyword)
if keyword:sub(1, 1) == ":" then
return keyword
end
return ":" .. keyword
end
-- Resolve keyword (possibly an alias) to its canonical form. Used only at input boundaries
local function get_canonical_keyword(keyword)
if not keyword then return keyword end
return M.data.keyword_canonical[keyword] or keyword
end
-- Build text/phrase for nominalization with <g:code> (uses data module for codes only).
local function get_nominalization_label_for_g(code)
if not code or code == "" then return nil end
local codes = M.data.nominalization_g_codes
local adj = codes[code]
if not adj and #code == 2 then
local gender_adj = codes[code:sub(1, 1)]
local number_adj = codes[code:sub(2, 2)]
if gender_adj and number_adj then
adj = gender_adj .. " " .. number_adj
end
end
if not adj then return nil end
local text = adj:gsub("^%l", function(c) return string.upper(c) end) .. " nominalization of"
local phrase = M.en_utilities.add_indefinite_article(adj .. " nominalization of", false)
return { text = text, phrase = phrase }
end
local EtymonParser = {}
-- Keyword modifier definitions
EtymonParser.keyword_param_mods = {
unc = { type = "boolean" },
ref = {},
text = { restrict = { keywords = { "from", "derived" } } },
lit = { restrict = { keywords = { "affix", "surf", "univerbation" } } },
conj = {}, -- conjunction for alternatives: "and", "or", "and/or", etc.
g = { restrict = { keywords = { "nominalization" } } },
}
-- Term modifier definitions
EtymonParser.etymon_param_mods = {
id = {},
t = {},
tr = {},
ts = {},
q = {},
qq = {},
l = {},
ll = {},
pos = {},
alt = {},
ety = {},
lit = {},
unc = { type = "boolean" },
ref = {},
aftype = { restrict = { keywords = { "affix", "surf", "afeq" } } },
postype = {},
bor = { type = "boolean", restrict = { keywords = { "affix", "surf" } } },
slbor = { type = "boolean", restrict = { keywords = { "affix", "surf" } } },
lbor = { type = "boolean", restrict = { keywords = { "affix", "surf" } } },
}
local function get_clean_param_mods(param_mods)
local clean = {}
for mod_name, mod_def in pairs(param_mods) do
clean[mod_name] = {}
for key, value in pairs(mod_def) do
if key ~= "restrict" then
clean[mod_name][key] = value
end
end
end
return clean
end
function EtymonParser.check_modifier_restrictions(modifiers, current_keyword, param_mods)
for mod_name, mod_value in pairs(modifiers) do
-- Only check restrictions if the modifier has a non-false/nil value
if mod_value then
local mod_def = param_mods[mod_name]
if mod_def and mod_def.restrict and mod_def.restrict.keywords then
local allowed_keywords = mod_def.restrict.keywords
local is_allowed = false
for _, allowed_keyword in ipairs(allowed_keywords) do
if current_keyword == allowed_keyword then
is_allowed = true
break
end
end
if not is_allowed then
local keyword_list = {}
for _, kw in ipairs(allowed_keywords) do
table.insert(keyword_list, ":" .. kw)
end
local keyword_str = table.concat(keyword_list, #keyword_list == 2 and " or " or ", ")
if #keyword_list > 2 then
-- Replace last comma with "or"
keyword_str = keyword_str:gsub(", ([^,]+)$", " or %1")
end
local mod_display = mod_value == true and "<" .. mod_name .. ">" or "<" .. mod_name .. ":" .. tostring(mod_value) .. ">"
error("The modifier `" .. mod_display .. "` is only allowed for the keyword" .. (#keyword_list > 1 and "s " or " ") .. keyword_str .. ".")
end
end
end
end
end
-- Parse keyword with modifiers (e.g., ":bor<unc>" or ":bor<ref:{{R:example}}>")
function EtymonParser.parse_keyword_modifiers(param)
if type(param) ~= "string" then return nil, {} end
local base_keyword = get_keyword_base(param)
if not base_keyword then return nil, {} end
local canonical_keyword = get_canonical_keyword(base_keyword)
-- Check if there are any modifiers
if not param:find("<", 1, true) then
return canonical_keyword, {}
end
-- Parse modifiers using the same mechanism as etymon parsing
local rest_with_defaults = Util.add_boolean_defaults(param, EtymonParser.keyword_param_mods)
local function generate_obj(ignored)
return {}
end
local parsed = M.parse_utilities.parse_inline_modifiers(rest_with_defaults:gsub("^:?[^<]+", ""),
{ param_mods = get_clean_param_mods(EtymonParser.keyword_param_mods), generate_obj = generate_obj })
local modifiers = {
unc = parsed.unc or false,
ref = parsed.ref,
text = parsed.text,
lit = parsed.lit,
conj = parsed.conj,
g = parsed.g,
}
-- Validate modifiers against restrictions
EtymonParser.check_modifier_restrictions(modifiers, canonical_keyword, EtymonParser.keyword_param_mods)
return canonical_keyword, modifiers
end
function EtymonParser.parse_balanced_segments(str)
local segments = {}
local current = ""
local depth = 0
local i = 1
while i <= #str do
local char = str:sub(i, i)
if char == "<" then
if depth == 0 and current ~= "" then
table.insert(segments, current)
current = ""
end
depth = depth + 1
current = current .. char
elseif char == ">" then
current = current .. char
depth = depth - 1
if depth == 0 then
table.insert(segments, current)
current = ""
elseif depth < 0 then
error("Unbalanced brackets in etymon: unexpected '>'")
end
else
current = current .. char
end
i = i + 1
end
if depth ~= 0 then
error("Unbalanced brackets in etymon: missing '>'")
end
if current ~= "" then
table.insert(segments, current)
end
return segments
end
function EtymonParser.parse_inline_ety(ety_string, context_lang)
local segments = EtymonParser.parse_balanced_segments(ety_string)
if #segments == 0 then
error("Empty inline etymology")
end
local keyword = M.string_utilities.trim(segments[1])
if not is_keyword(keyword, true) then
error("Invalid keyword '" .. keyword .. "' in inline etymology <ety:" .. keyword .. "...>")
end
local args = { context_lang:getCode(), normalize_keyword(get_canonical_keyword(keyword)) }
for i = 2, #segments do
local segment = segments[i]
if segment:sub(1, 1) == "<" and segment:sub(-1) == ">" then
local inner = segment:sub(2, -2)
if inner ~= "" then
table.insert(args, inner)
end
elseif is_keyword(segment, true) then
-- Handle keywords that appear between bracketed segments
table.insert(args, normalize_keyword(get_canonical_keyword(get_keyword(segment, true))))
end
end
return args
end
function EtymonParser.parse_etymon(param, context_lang)
if is_keyword(param) then
return nil
end
if type(param) ~= "string" then
return nil
end
local lang, rest
local is_family = false
local before_bracket = param:match("^([^<]*)") or param
local lang_code, rest_match = before_bracket:match("^([a-zA-Z][a-zA-Z0-9._-]*):(.*)$")
if lang_code then
local potential_lang = Util.get_lang(lang_code, true)
if potential_lang then
lang = potential_lang
rest = param:sub(#lang_code + 2)
else
local potential_family = Util.get_family(lang_code)
if potential_family then
lang = potential_family
rest = param:sub(#lang_code + 2)
is_family = true
else
lang = context_lang
rest = param
end
end
else
lang = context_lang
rest = param
end
if rest == "" then
M.track("etymon/term/empty")
elseif rest == "?" then
M.track("etymon/term/question-mark")
elseif rest == "-" then
M.track("etymon/term/hyphen")
end
if rest == "" then
return {
lang = lang,
term = nil,
unknown_term = true,
is_family = is_family,
}
end
if rest == "-" then
return {
lang = lang,
term = nil,
suppress_term = true,
is_family = is_family,
}
end
if not rest:find("<", 1, true) then
return {
lang = lang,
term = M.string_utilities.trim(rest),
is_family = is_family,
}
end
local term_text = rest:match("^([^<]*)") or ""
local is_unknown = (term_text == "")
local is_suppress = (term_text == "-")
local function generate_obj(ignored_term)
return { term = (is_unknown or is_suppress) and nil or M.string_utilities.trim(term_text) }
end
local rest_with_defaults = Util.add_boolean_defaults(rest, EtymonParser.etymon_param_mods)
local parsed_obj = M.parse_utilities.parse_inline_modifiers(rest_with_defaults,
{ param_mods = get_clean_param_mods(EtymonParser.etymon_param_mods), generate_obj = generate_obj })
if parsed_obj.id and parsed_obj.id:match("^!") then
parsed_obj.id = parsed_obj.id:sub(2)
parsed_obj.override = true
end
parsed_obj.lang = lang
parsed_obj.is_family = is_family
if is_unknown then
parsed_obj.unknown_term = true
elseif is_suppress then
parsed_obj.suppress_term = true
end
return parsed_obj
end
function EtymonParser.validate(lang, args, id, title, pos, starts_with_lang_code)
-- id is now optional, so only validate if provided
if id then
if mw.ustring.len(id) < 2 then
error("The `id` parameter must have at least two characters.")
end
if id == title or id == Util.get_page_data().pagename then
error("The `id` parameter must not be the same as the page title.")
end
end
local valid_pos = { prefix = true, suffix = true, interfix = true, infix = true, root = true, word = true }
if pos and not valid_pos[pos] then
error("Unknown value provided for `pos`. Valid values: " .. table.concat(require("Module:table").keysToList(valid_pos), ", ") .. ".")
end
local current_keyword = "from"
local etymons_in_group = {}
local keywords = M.data.keywords
local function checkGroup()
if keywords[current_keyword] and keywords[current_keyword].is_group and current_keyword ~= "affix" and current_keyword ~= "surf" and current_keyword ~= "afeq" and #etymons_in_group <= 1 then
error("Detected `:" .. current_keyword .. "` group with fewer than two etymons.")
end
etymons_in_group = {}
end
local start_index = starts_with_lang_code and 2 or 1
for i = start_index, #args do
local param = args[i]
if type(param) ~= "string" then
elseif param:sub(1, 1) == ":" and not is_keyword(param) then
error("Invalid keyword '" .. param .. "'. Did you mean a valid keyword like ':bor', ':inh', etc.?")
elseif is_keyword(param) then
checkGroup()
current_keyword = get_canonical_keyword(get_keyword(param))
else
local etymon_data = EtymonParser.parse_etymon(param, lang)
if etymon_data then
table.insert(etymons_in_group, param)
local param_lang = etymon_data.lang
if etymon_data.is_family and current_keyword == "inherited" then
error("`:inh` does not support family codes; use a specific language.")
end
if etymon_data.is_family and not etymon_data.suppress_term then
error("Family codes require suppressed term (use family:-).")
end
if current_keyword == "from" and param_lang:getFullCode() ~= lang:getFullCode() then
error("`:from` is for same-language derivation, but language does not match. " ..
"Expected '" .. lang:getFullCode() .. "', got '" .. param_lang:getFullCode() .. "'.")
elseif current_keyword == "inherited" then
M.etymology.check_ancestor(lang, param_lang)
end
-- Check modifier restrictions
EtymonParser.check_modifier_restrictions(etymon_data, current_keyword, EtymonParser.etymon_param_mods)
-- postype must be "root" or "word"
local VALID_POSTYPES = { root = true, word = true }
if etymon_data.postype and not VALID_POSTYPES[etymon_data.postype] then
error("Invalid <postype:" .. etymon_data.postype .. ">; must be \"root\" or \"word\".")
end
if etymon_data.ety then
local inline_args = EtymonParser.parse_inline_ety(etymon_data.ety, etymon_data.lang)
EtymonParser.validate(etymon_data.lang, inline_args, nil, nil, nil, true)
end
else
table.insert(etymons_in_group, param)
end
end
end
checkGroup()
end
local DataRetriever = {}
-- Given an etymon data, scrape its page and cache the result in the global state object.
function DataRetriever.cache_page_etymons(etymon_page, etymon_title, key, etymon_lang, etymon_id, redirected_from, descendants_is_toplevel)
local content = etymon_title:getContent()
if not content then
__state.cached_etymon_args[key] = M.data.STATUS.REDLINK
return
end
-- Check if the linked page is a redirect. If it is, the template parsing
-- code below will be effectively skipped, and `scrape_page` will be called
-- again on the redirect target (see the bottom of this function)
local lang_section_for_descendants = nil
local redirect_target = etymon_title.redirect_target
if not redirect_target then
content = M.pages.get_section(content, etymon_lang:getFullName(), 2)
if not content then
__state.cached_etymon_args[key] = M.data.STATUS.MISSING
return
end
lang_section_for_descendants = content
end
local etymon_lang_code = etymon_lang:getFullCode()
local lang_page_key = etymon_lang_code .. ":" .. etymon_page
local found_templates_for_lang = {}
local found_ids = {}
local has_idless_etymon = false
local get_node_class = M.template_parser.class_else_type
-- Look for all {{etymon}} templates within the page content using the template parser
-- This way the same page is never parsed more than once
-- Build a map from senseids to their parent etymonids.
local active_etymon_args = nil
for node in M.template_parser.parse(content):iterate_nodes() do
local node_class = get_node_class(node)
if node_class == "heading" then
-- A new L2 or etymology section acts as a barrier: an {{etymon}} usage
-- used previously cannot be the parent of any subsequent senseids.
-- Note that we don't have to check for L2s due to the usage of `M.pages.get_section` above.
if node:get_name():find("^Etymology") then
active_etymon_args = nil
end
elseif node_class == "template" then
local template_name = node:get_name()
if template_name == "etymon" then
local template_args = node:get_arguments()
-- Check if this etymon is for our language
if template_args[1] == etymon_lang_code then
table.insert(found_templates_for_lang, template_args)
if template_args.id then
local etymon_key = lang_page_key .. ":" .. template_args.id
__state.cached_etymon_args[etymon_key] = template_args
__state.cached_etymon_pages[etymon_key] = tostring(etymon_page)
table.insert(found_ids, template_args.id)
active_etymon_args = template_args
else
has_idless_etymon = true
-- Store idless etymon with default key
local etymon_key = lang_page_key .. ":*"
__state.cached_etymon_args[etymon_key] = template_args
__state.cached_etymon_pages[etymon_key] = tostring(etymon_page)
table.insert(found_ids, "*")
active_etymon_args = template_args
end
end
elseif active_etymon_args and template_name == "senseid" then
local template_args = node:get_arguments()
-- This should always be true for proper usages of {{senseid}}.
if template_args[1] == etymon_lang_code and template_args[2] then
local sense_id_key = lang_page_key .. ":" .. template_args[2]
__state.senseid_parent_etymon[sense_id_key] = active_etymon_args
__state.cached_etymon_pages[sense_id_key] = tostring(etymon_page)
end
end
end
end
if descendants_is_toplevel and lang_section_for_descendants and #found_templates_for_lang > 0 then
M.descendants.cache_page_checks({
lang_section = lang_section_for_descendants,
etymon_lang_code = etymon_lang_code,
found_templates_for_lang = found_templates_for_lang,
entry_title = __state.entry_title,
entry_lang_code = __state.entry_lang_code,
entry_lang = __state.entry_lang_code and Util.get_lang(__state.entry_lang_code, true) or nil,
cached_descendants_checks = __state.cached_descendants_checks,
lang_page_key = lang_page_key,
redirected_from = redirected_from,
})
end
-- Error if multiple etymons exist and at least one is missing an id
if #found_templates_for_lang > 1 and has_idless_etymon then
error("Page '[[" .. tostring(etymon_page) .. "]]' has " .. #found_templates_for_lang ..
" etymon templates for " .. etymon_lang:getCanonicalName() ..
", but at least one is missing an id. All etymons must have unique IDs when there are multiple.")
end
local id_data_list = {}
for _, args in ipairs(found_templates_for_lang) do
local id = args.id or "*"
table.insert(id_data_list, { id = id, pos = args.pos })
end
__state.available_etymon_ids[lang_page_key] = id_data_list
if #found_templates_for_lang == 1 then
__state.single_etymons[lang_page_key] = found_templates_for_lang[1]
end
if redirected_from and __state.available_etymon_ids[lang_page_key] then
__state.available_etymon_ids[redirected_from] = __state.available_etymon_ids[redirected_from] or {}
for _, id_data in ipairs(__state.available_etymon_ids[lang_page_key]) do
table.insert(__state.available_etymon_ids[redirected_from], id_data)
end
end
if __state.cached_etymon_args[key] ~= nil or __state.senseid_parent_etymon[key] ~= nil then
-- All done!
return
elseif redirect_target and not redirected_from then
-- Try scraping the redirect.
etymon_page = redirect_target.prefixedText
DataRetriever.cache_page_etymons(etymon_page, redirect_target, lang_page_key .. ":" .. etymon_id, etymon_lang, etymon_id, lang_page_key, descendants_is_toplevel)
__state.cached_etymon_args[key] = __state.cached_etymon_args[etymon_lang_code .. ":" .. etymon_page .. ":" .. etymon_id]
else
__state.cached_etymon_args[key] = M.data.STATUS.MISSING
end
end
-- Given an etymon object, scrape its page (if necessary) and return its own etymon arguments as well as the page name.
function DataRetriever.get_etymon_args(etymon_data, is_toplevel)
local page = M.links.get_link_page(etymon_data.term, etymon_data.lang)
local norm_lang = Util.get_norm_lang(etymon_data.lang)
local base_key = norm_lang:getFullCode() .. ":" .. page
if etymon_data.id then
local key = base_key .. ":" .. etymon_data.id
local cached_args = __state.cached_etymon_args[key] or __state.senseid_parent_etymon[key]
if cached_args == nil then
local title = mw.title.new(page)
if not title then error('Invalid page title "' .. page .. '" encountered.') end
DataRetriever.cache_page_etymons(page, title, key, norm_lang, etymon_data.id, nil, is_toplevel)
end
cached_args = __state.cached_etymon_args[key] or __state.senseid_parent_etymon[key] -- refresh
-- Get etymon_id from parent if this was resolved via senseid
local parent_etymon = __state.senseid_parent_etymon[key]
local resolved_etymon_id = parent_etymon and parent_etymon.id
local descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = is_toplevel,
base_key = base_key,
lookup = {
explicit_id = etymon_data.id,
parent_etymon = parent_etymon,
},
})
if is_toplevel and descendants_check == nil then
local title = mw.title.new(page)
if title then
DataRetriever.cache_page_etymons(page, title, key, norm_lang, etymon_data.id, nil, true)
descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = true,
base_key = base_key,
lookup = {
explicit_id = etymon_data.id,
parent_etymon = parent_etymon,
},
})
end
end
return cached_args, __state.cached_etymon_pages[key], resolved_etymon_id, descendants_check
else
__state.used_idless_etymon = true
if is_toplevel then
__state.toplevel_idless_etymon = true
end
if __state.available_etymon_ids[base_key] == nil then
local title = mw.title.new(page)
if not title then error('Invalid page title "' .. page .. '" encountered.') end
DataRetriever.cache_page_etymons(page, title, base_key .. ":*", norm_lang, "*", nil, is_toplevel)
end
local ids = __state.available_etymon_ids[base_key] or {}
local count = #ids
-- Try to filter by postype if available and we have multiple candidates
if count > 1 and etymon_data.postype then
local matching_ids = {}
for _, id_data in ipairs(ids) do
if id_data.pos == etymon_data.postype then
table.insert(matching_ids, id_data)
end
end
if #matching_ids == 1 then
local matched_id = matching_ids[1].id
local matched_key = base_key .. ":" .. matched_id
local descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = is_toplevel,
base_key = base_key,
lookup = { id = matched_id },
})
if is_toplevel and descendants_check == nil then
local title = mw.title.new(page)
if title then
DataRetriever.cache_page_etymons(page, title, base_key .. ":*", norm_lang, "*", nil, true)
descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = true,
base_key = base_key,
lookup = { id = matched_id },
})
end
end
return __state.cached_etymon_args[matched_key], __state.cached_etymon_pages[matched_key], nil, descendants_check
end
end
if count == 1 then
local only_id_data = ids[1]
local only_id = (type(only_id_data) == "table" and only_id_data.id) or only_id_data or "*"
local descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = is_toplevel,
base_key = base_key,
lookup = { id_data = only_id_data },
})
if is_toplevel and descendants_check == nil then
local title = mw.title.new(page)
if title then
DataRetriever.cache_page_etymons(page, title, base_key .. ":*", norm_lang, "*", nil, true)
descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = true,
base_key = base_key,
lookup = { id_data = only_id_data },
})
end
end
return __state.single_etymons[base_key], __state.cached_etymon_pages[base_key .. ":" .. only_id], nil, descendants_check
elseif count > 1 then
local id_list = {}
for _, id_data in ipairs(ids) do
local id = type(id_data) == "table" and id_data.id or id_data
if id and id ~= "" then
table.insert(id_list, "\"" .. id .. "\"")
end
end
local suggestion_text = ""
if #id_list > 0 then
suggestion_text = " Available IDs: " .. table.concat(id_list, ", ") .. "."
end
Util.add_warning("Etymology link to '[[" .. page .. "]]' is ambiguous. The page has " ..
count .. " etymon templates for " .. norm_lang:getCanonicalName() ..
". Please specify an ID." .. suggestion_text, true)
return M.data.STATUS.AMBIGUOUS, nil, nil, nil
else
return M.data.STATUS.MISSING, nil, nil, nil
end
end
end
local TreeBuilder = {}
local function parse_etymon_references(refs_text)
if not refs_text or refs_text == "" then
return ""
end
return M.references.parse_references(refs_text)
end
local function parse_tree_references(node)
if node.ref then
node.parsed_ref = parse_etymon_references(node.ref)
end
if node.children then
for _, container in ipairs(node.children) do
if container.terms then
for _, term in ipairs(container.terms) do
parse_tree_references(term)
end
end
end
end
end
-- Build a unique key for deduplication in the seen table
function TreeBuilder.build_key(lang, title, args)
local norm_lang_code = Util.get_norm_lang(lang):getFullCode()
local is_table = type(args) == "table"
local id = (is_table and args.id) or ""
if title then
return norm_lang_code .. ":" .. M.links.get_link_page(title, lang) .. ":" .. id
end
if is_table and args.status == M.data.STATUS.INLINE then
local content_parts = {}
for i = 1, #args do
content_parts[i] = tostring(args[i])
end
return norm_lang_code .. ":*:" .. id .. "\0" .. table.concat(content_parts, "\0")
end
return norm_lang_code .. ":*:" .. id
end
function TreeBuilder.build(lang, title, args, seen, depth, stop_recursion)
seen = seen or {}
depth = depth or 0
local is_toplevel = (depth == 0)
if depth > __state.max_depth_reached then
__state.max_depth_reached = depth
end
__state.total_nodes = __state.total_nodes + 1
local lang_code = lang:getCode()
__state.language_count[lang_code] = (__state.language_count[lang_code] or 0) + 1
local current_id = (type(args) == "table" and args.id) or ""
local key = TreeBuilder.build_key(lang, title, args)
local node = { lang = lang, title = title, id = current_id, args = args, children = {}, status = M.data.STATUS.OK }
if type(args) ~= "table" or seen[key] then
node.status = args or M.data.STATUS.MISSING
-- Mark as duplicate if we've seen this node before
if seen[key] then
node.is_duplicate = true
node.duplicate_key = key
local original_node = seen[key]
if type(original_node) == "table" and original_node.children and #original_node.children > 0 then
node.original_has_children = true
end
end
return node
end
node.status = args.status or M.data.STATUS.OK
seen[key] = node
-- If stop_recursion is set, skip parsing children but check for visible children
if stop_recursion then
local keywords = M.data.keywords
local has_visible_children = false
for i = 2, #args do
local param = args[i]
if type(param) == "string" then
local keyword_base = get_keyword_base(param)
if keyword_base and keywords[keyword_base] then
-- It's a keyword, check if visible in tree (invisible "all" or "tree" = hidden in tree)
local keyword_info = keywords[keyword_base]
local inv = keyword_info.invisible
if not (inv == "all" or inv == true or inv == "tree") then
has_visible_children = true
break
end
elseif param:sub(1, 1) ~= ":" then
-- It's a term (not a keyword), so there are visible children
has_visible_children = true
break
end
end
end
node.has_visible_children = has_visible_children
return node
end
-- Parse args into keyword containers
local current_keyword = "from"
local current_keyword_modifiers = {}
local current_container = nil
-- Helper to track keyword usage at top level
local function track_keyword_usage(keyword, target_lang, source_lang)
if not is_toplevel then return end
if not __state.toplevel_keyword_stats[keyword] then
__state.toplevel_keyword_stats[keyword] = {
count = 0,
target_langs = {},
source_langs = {},
}
end
local keyword_data = __state.toplevel_keyword_stats[keyword]
keyword_data.count = keyword_data.count + 1
local target_code = target_lang:getCode()
keyword_data.target_langs[target_code] = (keyword_data.target_langs[target_code] or 0) + 1
if source_lang then
local source_code = source_lang:getCode()
keyword_data.source_langs[source_code] = (keyword_data.source_langs[source_code] or 0) + 1
end
end
local function ensure_container()
if not current_container or current_container.keyword ~= current_keyword then
current_container = {
keyword = current_keyword,
keyword_info = M.data.keywords[current_keyword],
keyword_modifiers = current_keyword_modifiers,
terms = {},
}
table.insert(node.children, current_container)
-- Override keyword text/phrase for nominalization with <g:code>
if current_keyword_modifiers.g and current_keyword == "nominalization" then
local labels = get_nominalization_label_for_g(current_keyword_modifiers.g)
if not labels then
local codes = {}
for c in pairs(M.data.nominalization_g_codes) do table.insert(codes, c) end
table.sort(codes)
error("Invalid <g:" .. tostring(current_keyword_modifiers.g) .. ">. Supported codes for nominalization: " .. table.concat(codes, ", "))
end
current_container.keyword_info = {}
for k, v in pairs(M.data.keywords[current_keyword]) do current_container.keyword_info[k] = v end
current_container.keyword_info.text = labels.text
current_container.keyword_info.phrase = labels.phrase
end
end
end
for i = 2, #args do
local param = args[i]
if is_keyword(param) then
local keyword, modifiers = EtymonParser.parse_keyword_modifiers(param)
current_keyword = keyword
current_keyword_modifiers = modifiers
current_container = nil -- Force new container for new keyword
elseif type(param) == "string" and param:sub(1, 1) == ":" then
error("Invalid keyword '" .. param .. "'. Did you mean a valid keyword like ':bor', ':inh', etc.?")
elseif type(param) == "string" then
local etymon_data = EtymonParser.parse_etymon(param, lang)
if etymon_data then
-- Track keyword usage at top level
track_keyword_usage(current_keyword, lang, etymon_data.lang)
local term_node = {}
-- Handle suppress_term (-) and unknown_term (empty) directly
if etymon_data.suppress_term or etymon_data.unknown_term then
ensure_container()
if etymon_data.ety then
local inline_args = EtymonParser.parse_inline_ety(etymon_data.ety, etymon_data.lang)
inline_args.id = etymon_data.id
inline_args.status = M.data.STATUS.INLINE
term_node = TreeBuilder.build(etymon_data.lang, nil, inline_args, seen, depth + 1)
else
term_node = {
lang = etymon_data.lang,
children = {},
status = M.data.STATUS.OK,
}
end
term_node.suppress_term = etymon_data.suppress_term
term_node.unknown_term = etymon_data.unknown_term
term_node.is_family = etymon_data.is_family
term_node.is_uncertain = etymon_data.unc
term_node.ref = etymon_data.ref
term_node.t = etymon_data.t
term_node.tr = etymon_data.tr
term_node.ts = etymon_data.ts
term_node.alt = etymon_data.alt
term_node.pos = etymon_data.pos
term_node.lit = etymon_data.lit
term_node.q = etymon_data.q
term_node.qq = etymon_data.qq
term_node.l = etymon_data.l
term_node.ll = etymon_data.ll
else
-- Regular term: fetch arguments from page
local etymon_args, page_of, resolved_etymon_id, descendants_check = DataRetriever.get_etymon_args(etymon_data, is_toplevel)
if etymon_data.id and etymon_args == M.data.STATUS.MISSING and not etymon_data.ety then
local page = M.links.get_link_page(etymon_data.term, etymon_data.lang)
local norm_lang = Util.get_norm_lang(etymon_data.lang)
local base_key = norm_lang:getFullCode() .. ":" .. page
local available_ids = __state.available_etymon_ids[base_key] or {}
if #available_ids > 0 then
__state.has_mismatched_id = true
end
end
-- Check for <ety> inline parameter doesn't override the scraped arguments, unless the latter are missing
if etymon_data.ety then
if etymon_args == M.data.STATUS.REDLINK or etymon_args == M.data.STATUS.MISSING then
__state.current_page_has_inline_etymology = true
if is_toplevel then
__state.toplevel_has_inline_etymology = true
end
local inline_args = EtymonParser.parse_inline_ety(etymon_data.ety, etymon_data.lang)
-- Track inline ety keywords too
local inline_keyword = get_keyword(inline_args[2], true)
if inline_keyword and #inline_args >= 3 then
local inline_etymon = EtymonParser.parse_etymon(inline_args[3], etymon_data.lang)
if inline_etymon then
track_keyword_usage(inline_keyword, etymon_data.lang, inline_etymon.lang)
end
end
inline_args.id = etymon_data.id
inline_args.status = M.data.STATUS.INLINE
etymon_args = inline_args
term_node.page_of = __state.cached_etymon_pages[key] -- term node is on the same page as the parent
else
-- Scraped arguments exist, <ety> is redundant and ignored
__state.current_page_has_redundant_etymology = true
if is_toplevel then
__state.toplevel_redundant_etymology = true
end
end
end
-- Ensure container exists before checking keyword info
ensure_container()
-- Check if current keyword has no_child_categories - if so, stop recursion
local keyword_info = current_container.keyword_info
local should_stop_recursion = (stop_recursion or (keyword_info and keyword_info.no_child_categories))
term_node = TreeBuilder.build(etymon_data.lang, etymon_data.term, etymon_args, seen, depth + 1, should_stop_recursion)
term_node.target_key = Util.get_norm_lang(etymon_data.lang):getFullCode() ..
":" .. M.links.get_link_page(etymon_data.term, etymon_data.lang)
term_node.id = etymon_data.id
term_node.etymon_id = resolved_etymon_id -- The actual etymon id when resolved via senseid
term_node.t = etymon_data.t
term_node.tr = etymon_data.tr
term_node.ts = etymon_data.ts
term_node.pos = etymon_data.pos
term_node.alt = etymon_data.alt
term_node.ref = etymon_data.ref
term_node.is_uncertain = etymon_data.unc
term_node.override = etymon_data.override
term_node.page_of = page_of
term_node.aftype = etymon_data.aftype
term_node.postype = etymon_data.postype
term_node.bor = etymon_data.bor
term_node.lbor = etymon_data.lbor
term_node.slbor = etymon_data.slbor
term_node.lit = etymon_data.lit
term_node.is_family = etymon_data.is_family
term_node.q = etymon_data.q
term_node.qq = etymon_data.qq
term_node.l = etymon_data.l
term_node.ll = etymon_data.ll
term_node.missing_descendants_header, term_node.missing_descendants_entry =
M.descendants.get_term_sync_flags(current_keyword, term_node.status, descendants_check)
end
table.insert(current_container.terms, term_node)
end
end
end
return node
end
-- Convert etymology tree to JSON-serializable table
local function tree_to_json(node)
local obj = {
term = node.title,
lang = node.lang:getCode(),
lang_name = node.lang:getCanonicalName(),
id = (node.id and node.id ~= "") and node.id or nil,
status = node.status,
is_uncertain = node.is_uncertain or nil,
is_duplicate = node.is_duplicate or nil,
gloss = node.t,
transliteration = node.tr,
transcription = node.ts,
alt = node.alt,
pos = node.pos,
children = {},
}
for _, container in ipairs(node.children or {}) do
local keyword_info = container.keyword_info
if keyword_info then
local container_obj = {
keyword = container.keyword,
keyword_label = keyword_info.text,
keyword_abbrev = keyword_info.abbrev,
is_group = keyword_info.is_group or nil,
is_invisible = keyword_info.invisible or nil,
is_uncertain = (container.keyword_modifiers and container.keyword_modifiers.unc) or nil,
terms = {},
}
for _, term in ipairs(container.terms or {}) do
table.insert(container_obj.terms, tree_to_json(term))
end
table.insert(obj.children, container_obj)
end
end
return obj
end
local function track_ranges(base_key, value, ranges, lang_code)
M.track("etymon/" .. base_key .. "/" .. value)
if lang_code then
M.track("etymon/lang/" .. lang_code .. "/" .. base_key .. "/" .. value)
end
for _, range in ipairs(ranges) do
local matches = false
if range.min and range.max then
matches = value >= range.min and value <= range.max
elseif range.min then
matches = value >= range.min
elseif range.max then
matches = value <= range.max
elseif range.exact then
matches = value == range.exact
end
if matches then
M.track("etymon/" .. base_key .. "/" .. range.label)
if lang_code then
M.track("etymon/lang/" .. lang_code .. "/" .. base_key .. "/" .. range.label)
end
break
end
end
end
-- Build and return the etymology data tree for a given term.
function export.get_tree(lang, title, args, options)
options = options or {}
__state.entry_title = title
__state.entry_lang_code = lang:getCode()
if options.validate then
EtymonParser.validate(lang, args, options.id, title, options.pos, false)
end
local lang_code = lang:getCode()
local start_index = (args[1] == lang_code) and 2 or 1
local tree_args = { [1] = lang_code, id = options.id or args.id }
for i = start_index, #args do
table.insert(tree_args, args[i])
end
__state.cached_etymon_args[lang_code .. ":" .. title .. ":" .. (tree_args.id or "")] = tree_args
local ety_data_tree = TreeBuilder.build(lang, title, tree_args)
parse_tree_references(ety_data_tree)
if options.json then
return M.JSON.toJSON(tree_to_json(ety_data_tree))
end
return ety_data_tree
end
-- Given a language code, page name and optionally the id= parameter,
-- render the tree and only the etymology tree for the relevant page.
-- Fetches and parses the corresponding {{etymon}} from the requested page,
-- and any further pages needed to render the tree.
-- Parameters can be passed either through the #invoke or as
-- template parameters *through* an #invoke.
function export.render_tree_for_etymon_on_page(frame)
local frame_args = frame.args
local parent_args = frame:getParent().args
local langcode = frame_args[1] or parent_args[1]
local pagename = frame_args[2] or parent_args[2]
local id = frame_args["id"] or parent_args["id"]
local display_title = frame_args["title"] or parent_args["title"]
local parsed_title = mw.title.new(pagename, 0)
local title
if parsed_title.namespace == 0 then
title = M.pages.safe_page_name(parsed_title)
elseif parsed_title.namespace == 118 then
title = "*" .. M.pages.safe_page_name(parsed_title)
else
error("Unsupported namespace for render_tree_for_etymon_on_page: " .. parsed_title.namespace)
end
local lang = Util.get_lang(langcode)
-- Construct etymon_data for DataRetriever.get_args.
local etymon_data = {
lang = lang,
term = title,
id = id
}
local args, pagename = DataRetriever.get_etymon_args(etymon_data, true)
if args == M.data.STATUS.MISSING then
error("The etymon template was not found (language " ..
langcode ..
", title '" ..
title ..
"'" ..
(id and ", ID '" .. id .. "'" or ", no ID given") .. "). Page contents may have changed in the interim.")
end
local ety_data_tree = export.get_tree(lang, display_title or title, args, {
validate = true,
id = id,
})
local output = {}
table.insert(output, M.template_styles("Module:etymon/styles.css"))
table.insert(output, M.tree.render({
data_tree = ety_data_tree,
format_term_func = function(term, is_toplevel)
return Util.format_term(term, is_toplevel, {
gloss = "suppress",
pos = "suppress",
lit = "suppress",
tree_ql = "suppress",
})
end,
}))
return table.concat(output)
end
function export.main(frame)
local parent_args = frame:getParent().args
local args = M.parameters.process(parent_args, M.parameters_data.etymon)
local lang = args[1]
local etymon_args = args[2]
local id = args.id
local title = args.title
local text = args.text
local tree = args.tree
local etydate = args.etydate
local rfe = args.rfe
local page_data = Util.get_page_data()
if not title then
title = page_data.pagename
if page_data.namespace == "Từ tái tạo" then title = "*" .. title end
end
local current_L2 = M.pages.get_current_L2()
if current_L2 then
local norm_lang = Util.get_norm_lang(lang)
local norm_name = norm_lang:getCanonicalName()
if current_L2 ~= norm_name then
local lang_desc = lang:getCode() .. " (" .. lang:getCanonicalName() .. ")"
if norm_lang:getCode() ~= lang:getCode() then
lang_desc = lang_desc .. ", normalized to " .. norm_lang:getCode() .. " (" .. norm_name .. ")"
end
error("Language '" .. lang_desc .. "' does not match the L2 header (" .. current_L2 .. ").")
end
end
local ety_data_tree = export.get_tree(lang, title, etymon_args, {
validate = true,
pos = args.pos,
id = id,
json = args.json,
})
if args.json then
return ety_data_tree
end
local output = {}
local text_allowlist_mode = M.text_allowed.default_mode or "off"
if text and text_allowlist_mode ~= "off" and not Util.is_text_param_allowed_for_lang(lang) then
local msg = "Etymology texts (parameter <code>text=</code>) are not allowed for " .. lang:getFullName() ..
"; see [[Template:etymon#Text allowlist|Template:etymon § Text allowlist]] for the list of languages that may use the <code>text=</code> parameter."
if text_allowlist_mode == "error" then
error(msg)
else
Util.add_warning(msg, true)
end
end
local lang_exc = Util.get_lang_exception(lang)
if lang_exc and lang_exc.disallow then
local disallow = lang_exc.disallow
local error_text = " for " .. lang:getFullName()
if disallow.ref then
error_text = error_text .. "; see " .. disallow.ref
else
error_text = error_text .. "."
end
if tree and disallow.tree then
error("Etymology trees are not allowed" .. error_text)
end
if text and disallow.text then
error("Etymology texts are not allowed" .. error_text)
end
end
if etydate then
local etydate_param_mods = {
ref = { list = true, type = "references", allow_holes = true },
refn = { list = true, allow_holes = true },
nocap = { type = "boolean" },
}
local function generate_etydate_obj(etydate_text)
local etydate_specs = {}
for spec in etydate_text:gmatch("[^,]+") do
table.insert(etydate_specs, mw.text.trim(spec))
end
return { [1] = etydate_specs }
end
local parsed_etydate = M.parse_utilities.parse_inline_modifiers(etydate, { param_mods = etydate_param_mods, generate_obj = generate_etydate_obj })
local etydate_args = {
[1] = parsed_etydate[1],
nocap = parsed_etydate.nocap or false,
ref = parsed_etydate.ref or {},
refn = parsed_etydate.refn or { maxindex = 0 }
}
if etydate_args.refn then
local max = 0
for k, v in pairs(etydate_args.refn) do
if type(k) == "number" and k > max then
max = k
end
end
etydate_args.refn.maxindex = max
end
ety_data_tree.etydate = M.etydate.format_etydate(etydate_args)
-- Parse and store references separately for text rendering
local refs_text = ""
for _, ref in ipairs(etydate_args.ref) do
refs_text = refs_text .. (refs_text ~= "" and "" or "") .. ref
end
if refs_text ~= "" then
ety_data_tree.etydate_refs = M.references.parse_references(refs_text)
end
end
if tree then
table.insert(output, M.template_styles("Module:etymon/styles.css"))
table.insert(output, M.tree.render({
data_tree = ety_data_tree,
format_term_func = function(term, is_toplevel)
return Util.format_term(term, is_toplevel, {
gloss = "suppress",
pos = "suppress",
lit = "suppress",
tree_ql = "suppress",
})
end,
}))
end
-- Check if there are any visible children in tree (invisible "all" or "tree" = hidden in tree)
local has_visible_children = false
for _, child in ipairs(ety_data_tree.children or {}) do
local child_keyword_info = child.keyword_info
local inv = child_keyword_info and child_keyword_info.invisible
if not (inv == "all" or inv == true or inv == "tree") then
has_visible_children = true
break
end
end
local tree_disallowed = lang_exc and lang_exc.disallow and lang_exc.disallow.tree
local anchor = M.anchors.etymonid(lang, id, {
no_tree = args.notree,
title = title,
empty_tree = (not has_visible_children) or tree_disallowed
})
table.insert(output, anchor)
if text then
local max_depth, stop_at_blue_link, stop_at_lang, stop_at_lang_or_bluelink
if text == "++" then
max_depth, stop_at_blue_link = false, false
elseif text == "+" then
max_depth, stop_at_blue_link = 1, false
elseif text == "*" then
max_depth, stop_at_blue_link = false, true
elseif text:match("^:[^*]+%*$") then
-- Stop at a specific language OR first bluelink after it, e.g., ":ota*"
-- If the target language is a redlink, continue to the first bluelink
local lang_code = text:match("^:([^*]+)%*$")
if lang_code and lang_code ~= "" then
local lang_obj = Util.get_lang(lang_code, true)
if lang_obj then
stop_at_lang_or_bluelink = lang_code
else
Util.add_warning('Invalid language code "' .. lang_code .. '" in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false
end
else
Util.add_warning('Empty language code in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false
end
elseif text:sub(1, 1) == ":" then
-- Stop at a specific language, e.g., ":ar" stops at first Arabic term
local lang_code = text:sub(2)
if lang_code ~= "" then
-- Validate the language code
local lang_obj = Util.get_lang(lang_code, true)
if lang_obj then
stop_at_lang = lang_code
else
Util.add_warning('Invalid language code "' .. lang_code .. '" in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false -- default to ++
end
else
Util.add_warning('Empty language code in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false -- default to ++
end
else
local num = tonumber(text)
if num and num >= 1 then
max_depth, stop_at_blue_link = num, false
else
error('Invalid text value "' ..
text .. '". Valid values are: "++" (full chain), "+" (first step only), "*" (until first blue link), a number (max steps), ":lang" (stop at language), or ":lang*" (stop at language or first bluelink if redlink)')
end
end
table.insert(output, M.text.render({
data_tree = ety_data_tree,
format_term_func = Util.format_term,
max_depth = max_depth,
stop_at_blue_link = stop_at_blue_link,
curr_page = page_data.pagename,
nodot = args.nodot,
stop_at_lang = stop_at_lang,
stop_at_lang_or_bluelink = stop_at_lang_or_bluelink,
}))
end
if rfe then
local rfe_param_mods = {
nocat = { type = "boolean" },
sort = {},
y = {},
m = {},
fragment = {},
section = {},
box = { type = "boolean" },
noes = { type = "boolean" },
}
local function generate_rfe_obj(rfe_text)
-- Check if it's a boolean true value
if M.yesno(rfe_text, false) then
return { is_boolean = true }
else
return { text = rfe_text }
end
end
local rfe_with_defaults = Util.add_boolean_defaults(rfe, rfe_param_mods)
local parsed_rfe = M.parse_utilities.parse_inline_modifiers(rfe_with_defaults, {
param_mods = rfe_param_mods,
generate_obj = generate_rfe_obj
})
local rfe_args = {
[1] = lang:getCode(),
nocat = parsed_rfe.nocat,
sort = parsed_rfe.sort,
y = parsed_rfe.y,
m = parsed_rfe.m,
fragment = parsed_rfe.fragment,
section = parsed_rfe.section,
box = parsed_rfe.box,
noes = parsed_rfe.noes,
}
if not parsed_rfe.is_boolean then
rfe_args[2] = parsed_rfe.text
end
table.insert(output, frame:expandTemplate({
title = "rfe",
args = rfe_args
}))
end
if Util.is_content_page() and __state.max_depth_reached > 0 then
local lang_code = lang:getCode()
local depth_ranges = {
{ min = 50, label = "extremely-deep" },
{ min = 20, label = "20+" },
{ min = 10, max = 19, label = "10-19" },
{ min = 5, max = 9, label = "5-9" },
{ min = 3, max = 4, label = "3-4" },
{ max = 2, label = "1-2" }
}
local node_ranges = {
{ min = 100, label = "extremely-large" },
{ min = 50, label = "50+" },
{ min = 20, max = 49, label = "20-49" },
{ min = 10, max = 19, label = "10-19" },
{ min = 5, max = 9, label = "5-9" },
{ max = 4, label = "1-4" }
}
local language_ranges = {
{ min = 10, label = "10+" },
{ min = 5, max = 9, label = "5-9" },
{ min = 3, max = 4, label = "3-4" },
{ exact = 2, label = "2" },
{ exact = 1, label = "1" }
}
track_ranges("depth", __state.max_depth_reached, depth_ranges, lang_code)
track_ranges("nodes", __state.total_nodes, node_ranges, lang_code)
local unique_languages = 0
for _ in pairs(__state.language_count) do
unique_languages = unique_languages + 1
end
track_ranges("unique-languages", unique_languages, language_ranges, lang_code)
if __state.total_nodes == __state.max_depth_reached + 1 then
track_ranges("linear-depth", __state.max_depth_reached, depth_ranges, lang_code)
end
end
local categories = {}
if Util.is_content_page() then
local should_suppress_categories = lang_exc and lang_exc.suppress_categories
if not should_suppress_categories and not args.nocat then
categories = M.categories.render({
data_tree = ety_data_tree,
page_lang = lang,
available_etymon_ids = __state.available_etymon_ids,
senseid_parent_etymon = __state.senseid_parent_etymon,
get_norm_lang_func = Util.get_norm_lang,
lang_exc = lang_exc,
})
end
local target_lang_code = lang:getCode()
for keyword, keyword_data in pairs(__state.toplevel_keyword_stats) do
-- Track keyword globally
M.track("etymon/keyword/" .. keyword)
-- Track keyword per target language
M.track("etymon/keyword/" .. keyword .. "/target/" .. target_lang_code)
-- Track keyword per source language
for source_code, count in pairs(keyword_data.source_langs) do
M.track("etymon/keyword/" .. keyword .. "/source/" .. source_code)
-- Track keyword per target+source combination
M.track("etymon/keyword/" .. keyword .. "/target/" .. target_lang_code .. "/source/" .. source_code)
end
end
if tree then
table.insert(categories, "Trang có cây từ nguyên")
table.insert(categories, "Mục từ có cây từ nguyên " .. lang:getCanonicalName())
end
if text then table.insert(categories, lang:getCanonicalName() .. " entries with etymology texts") end
if args.exnihilo then table.insert(categories, lang:getCanonicalName() .. " terms coined ex nihilo") end
if __state.toplevel_has_inline_etymology then
table.insert(categories, "Pages with inline etymon for redlinks")
end
if __state.toplevel_redundant_etymology then
table.insert(categories, "Pages with redundant inline etymon")
end
if __state.toplevel_idless_etymon then
table.insert(categories, "Trang có cây từ nguyên thiếu ID")
end
if __state.has_mismatched_id then
table.insert(categories, lang:getCanonicalName() .. " entries referencing etymons with mismatched IDs")
end
end
if #categories > 0 then
table.insert(output, M.utilities.format_categories(categories, lang))
end
if __state.warnings then
for _, warning in ipairs(__state.warnings) do
table.insert(output, "\n" .. warning)
end
end
return table.concat(output)
end
return export
thf5x5bzfynll6hvbv1dzgwqa9fwyii
2344436
2344307
2026-04-12T06:24:54Z
TheHighFighter2
42988
2344436
Scribunto
text/plain
--[=[
This module implements the {{etymon}} template for structured etymology data on Wiktionary.
It enables the creation of etymology trees and text by parsing etymon chains,
scraping linked pages for their own {{etymon}} data, and recursively building a tree
of derivational relationships.
Tác giả:
- Triển khai ban đầu: [[Thành viên:Ioaxxere]]
- Tái cấu trúc lại mô đun (tháng 9 năm 2025): [[Thành viên:Fenakhay]] ([[:en:Special:Diff/86717746]])
Modules:
- [[Module:etymon]]: main module handling parsing, validation, tree building, and page scraping
- [[Module:etymon/data]]: keyword definitions, configuration, and status constants
- [[Module:etymon/tree]]: etymology tree rendering
- [[Module:etymon/text]]: etymology text generation
- [[Module:etymon/categories]]: category generation logic
]=]
local export = {}
local etymon_data_module = "Module:etymon/data"
local etymon_text_module = "Module:etymon/text"
local etymon_tree_module = "Module:etymon/tree"
local etymon_categories_module = "Module:etymon/categories"
local etymon_descendants_module = "Module:etymon/descendants"
local ucfirst = require("Module:string utilities").ucfirst
local __state = {
cached_etymon_args = {},
cached_etymon_pages = {},
cached_descendants_checks = {},
senseid_parent_etymon = {},
available_etymon_ids = {},
single_etymons = {},
entry_title = nil,
entry_lang_code = nil,
current_page_has_inline_etymology = false,
current_page_has_redundant_etymology = false,
used_idless_etymon = false,
toplevel_has_inline_etymology = false,
toplevel_redundant_etymology = false,
toplevel_idless_etymon = false,
has_mismatched_id = false,
max_depth_reached = 0,
total_nodes = 0,
language_count = {},
toplevel_keyword_stats = {},
warnings = {},
}
local loader = require("Module:module loader")
local M = loader.init({
require = {
data = etymon_data_module,
tree = etymon_tree_module,
text = etymon_text_module,
categories = etymon_categories_module,
descendants = etymon_descendants_module,
anchors = "Module:anchors",
etydate = "Module:etydate",
etymology = "Module:etymology",
families = "Module:families",
languages = "Module:languages",
languages_errorgetby = "Module:languages/errorGetBy",
links = "Module:links",
pages = "Module:pages",
parameters = "Module:parameters",
string_utilities = "Module:string utilities",
template_parser = "Module:template parser",
utilities = "Module:utilities",
debug = "Module:debug",
en_utilities = "Module:en-utilities",
parse_utilities = "Module:parse utilities",
references = "Module:references",
track = "Module:debug/track",
template_styles = "Module:TemplateStyles",
script_utilities = "Module:script utilities",
JSON = "Module:JSON",
yesno = "Module:yesno",
},
loadData = {
headword_data = "Module:headword/data",
parameters_data = "Module:parameters/data",
text_allowed = "Module:etymon/data/text_allowed",
},
})
local Util = {}
function Util.format_error(message, preview_only)
if preview_only and not M.pages.is_preview() then
return nil
end
return '<span class="error">' .. message .. '</span>'
end
function Util.add_warning(message, preview_only)
local formatted = Util.format_error(message, preview_only)
if formatted then
table.insert(__state.warnings, formatted)
end
end
function Util.is_text_param_allowed_for_lang(lang)
if not lang or type(lang) ~= "table" then
return false
end
local types = lang.getTypes and lang:getTypes()
if types and types.family then
local code = lang.getCode and lang:getCode()
return code and M.text_allowed.families[code] == true
end
local full_code = lang.getFullCode and lang:getFullCode()
if full_code and M.text_allowed.langs[full_code] then
return true
end
if lang.inFamily then
for family_code in pairs(M.text_allowed.families) do
if lang:inFamily(family_code) then
return true
end
end
end
return false
end
function Util.get_lang(code, no_error)
if no_error then
return M.languages.getByCode(code, nil, true)
end
return M.languages.getByCode(code, nil, true) or M.languages_errorgetby.code(code, true, true)
end
function Util.get_family(code)
return M.families.getByCode(code)
end
function Util.get_lang_exception(lang)
-- Families have no language-specific exceptions
if lang.getTypes and lang:getTypes().family then
return nil
end
local code = lang:getCode()
local lang_exceptions = M.data.config.lang_exceptions
if lang_exceptions[code] then
return lang_exceptions[code]
end
for norm_code, exc in pairs(lang_exceptions) do
if exc.normalize_to and code == exc.normalize_to then
return exc
end
if exc.normalize_from_families then
local should_normalize = false
for _, family in ipairs(exc.normalize_from_families) do
if lang:inFamily(family) then
should_normalize = true
break
end
end
if should_normalize and exc.normalize_exclude_families then
for _, family in ipairs(exc.normalize_exclude_families) do
if lang:inFamily(family) then
should_normalize = false
break
end
end
end
if should_normalize then
local ret = {}
for k, v in pairs(exc) do
ret[k] = v
end
ret.suppress_tr = nil
return ret
end
end
end
return nil
end
function Util.get_norm_lang(lang)
local exc = Util.get_lang_exception(lang)
if exc and exc.normalize_to then
return M.languages.getByCode(exc.normalize_to)
end
return lang
end
-- Add default values for boolean modifiers (e.g., <unc> becomes <unc:1>)
-- This is needed because Module:parse utilities expects boolean modifiers to have explicit values
function Util.add_boolean_defaults(str, param_mods)
local result = str
for name, spec in pairs(param_mods) do
if spec.type == "boolean" then
-- Replace <name> with <name:1> (but not <name:...> which already has a value)
result = result:gsub("<" .. name .. ">", "<" .. name .. ":1>")
end
end
return result
end
-- Centralized term formatting: handles suppress_term, unknown_term, and regular terms
function Util.format_term(term, is_toplevel, opts)
opts = opts or {}
-- suppress_term (-) returns nil
if term.suppress_term then
return nil
end
local lang = term.lang
local exc = Util.get_lang_exception(lang)
if is_toplevel then
local display_text = term.alt or term.title or ""
local sc = term.sc or lang:findBestScript(display_text)
local bold_text = tostring(mw.html.create("strong")
:addClass("selflink")
:wikitext(display_text))
return M.script_utilities.tag_text(bold_text, lang, sc, "term")
end
local link_params = { lang = lang }
link_params.term = not term.unknown_term and term.title or nil
link_params.alt = term.alt
link_params.id = (not term.unknown_term and term.id and term.id ~= "") and term.id or nil
if not (exc and exc.suppress_tr) then
link_params.tr = term.tr
link_params.ts = term.ts
else
link_params.suppress_tr = true
end
link_params.lit = (opts.lit ~= "suppress") and term.lit or nil
if opts.gloss ~= "suppress" then
link_params.gloss = term.t
end
if opts.pos ~= "suppress" then
link_params.pos = term.pos
end
if exc and exc.suppress_tr then
link_params.lit = nil
end
local show_qualifiers
if opts.tree_ql ~= "suppress" then
if term.q then
link_params.q = term.q
end
if term.qq then
link_params.qq = term.qq
end
if term.l then
link_params.l = term.l
end
if term.ll then
link_params.ll = term.ll
end
show_qualifiers = term.q or term.qq or term.l or term.ll
end
return M.links.full_link(link_params, "term", nil, show_qualifiers and true or nil)
end
local __is_content_page_cached
function Util.is_content_page()
if __is_content_page_cached == nil then
__is_content_page_cached = M.pages.is_content_page(mw.title.getCurrentTitle())
end
return __is_content_page_cached
end
local __page_data_cached
function Util.get_page_data()
if not __page_data_cached then
__page_data_cached = M.headword_data.page
end
return __page_data_cached
end
-- Extract base keyword from param (without modifiers)
local function get_keyword_base(param)
if type(param) ~= "string" then return nil end
local base = param:match("^:?([^<]+)") or param:gsub("^:", "")
return base
end
local function is_keyword(param, allow_colon_less)
if type(param) ~= "string" then return false end
local keywords = M.data.keywords
if param:sub(1, 1) == ":" then
local base = get_keyword_base(param)
return keywords[base] ~= nil
end
if allow_colon_less then
local base = get_keyword_base(param)
return keywords[base] ~= nil
end
return false
end
local function get_keyword(param, allow_colon_less)
if type(param) ~= "string" then return nil end
local keywords = M.data.keywords
if param:sub(1, 1) == ":" then
return get_keyword_base(param)
end
if allow_colon_less then
local base = get_keyword_base(param)
if keywords[base] then
return base
end
end
return nil
end
local function normalize_keyword(keyword)
if keyword:sub(1, 1) == ":" then
return keyword
end
return ":" .. keyword
end
-- Resolve keyword (possibly an alias) to its canonical form. Used only at input boundaries
local function get_canonical_keyword(keyword)
if not keyword then return keyword end
return M.data.keyword_canonical[keyword] or keyword
end
-- Build text/phrase for nominalization with <g:code> (uses data module for codes only).
local function get_nominalization_label_for_g(code)
if not code or code == "" then return nil end
local codes = M.data.nominalization_g_codes
local adj = codes[code]
if not adj and #code == 2 then
local gender_adj = codes[code:sub(1, 1)]
local number_adj = codes[code:sub(2, 2)]
if gender_adj and number_adj then
adj = gender_adj .. " " .. number_adj
end
end
if not adj then return nil end
local text = adj:gsub("^%l", function(c) return string.upper(c) end) .. " nominalization of"
local phrase = M.en_utilities.add_indefinite_article(adj .. " nominalization of", false)
return { text = text, phrase = phrase }
end
local EtymonParser = {}
-- Keyword modifier definitions
EtymonParser.keyword_param_mods = {
unc = { type = "boolean" },
ref = {},
text = { restrict = { keywords = { "from", "derived" } } },
lit = { restrict = { keywords = { "affix", "surf", "univerbation" } } },
conj = {}, -- conjunction for alternatives: "and", "or", "and/or", etc.
g = { restrict = { keywords = { "nominalization" } } },
}
-- Term modifier definitions
EtymonParser.etymon_param_mods = {
id = {},
t = {},
tr = {},
ts = {},
q = {},
qq = {},
l = {},
ll = {},
pos = {},
alt = {},
ety = {},
lit = {},
unc = { type = "boolean" },
ref = {},
aftype = { restrict = { keywords = { "affix", "surf", "afeq" } } },
postype = {},
bor = { type = "boolean", restrict = { keywords = { "affix", "surf" } } },
slbor = { type = "boolean", restrict = { keywords = { "affix", "surf" } } },
lbor = { type = "boolean", restrict = { keywords = { "affix", "surf" } } },
}
local function get_clean_param_mods(param_mods)
local clean = {}
for mod_name, mod_def in pairs(param_mods) do
clean[mod_name] = {}
for key, value in pairs(mod_def) do
if key ~= "restrict" then
clean[mod_name][key] = value
end
end
end
return clean
end
function EtymonParser.check_modifier_restrictions(modifiers, current_keyword, param_mods)
for mod_name, mod_value in pairs(modifiers) do
-- Only check restrictions if the modifier has a non-false/nil value
if mod_value then
local mod_def = param_mods[mod_name]
if mod_def and mod_def.restrict and mod_def.restrict.keywords then
local allowed_keywords = mod_def.restrict.keywords
local is_allowed = false
for _, allowed_keyword in ipairs(allowed_keywords) do
if current_keyword == allowed_keyword then
is_allowed = true
break
end
end
if not is_allowed then
local keyword_list = {}
for _, kw in ipairs(allowed_keywords) do
table.insert(keyword_list, ":" .. kw)
end
local keyword_str = table.concat(keyword_list, #keyword_list == 2 and " or " or ", ")
if #keyword_list > 2 then
-- Replace last comma with "or"
keyword_str = keyword_str:gsub(", ([^,]+)$", " or %1")
end
local mod_display = mod_value == true and "<" .. mod_name .. ">" or "<" .. mod_name .. ":" .. tostring(mod_value) .. ">"
error("The modifier `" .. mod_display .. "` is only allowed for the keyword" .. (#keyword_list > 1 and "s " or " ") .. keyword_str .. ".")
end
end
end
end
end
-- Parse keyword with modifiers (e.g., ":bor<unc>" or ":bor<ref:{{R:example}}>")
function EtymonParser.parse_keyword_modifiers(param)
if type(param) ~= "string" then return nil, {} end
local base_keyword = get_keyword_base(param)
if not base_keyword then return nil, {} end
local canonical_keyword = get_canonical_keyword(base_keyword)
-- Check if there are any modifiers
if not param:find("<", 1, true) then
return canonical_keyword, {}
end
-- Parse modifiers using the same mechanism as etymon parsing
local rest_with_defaults = Util.add_boolean_defaults(param, EtymonParser.keyword_param_mods)
local function generate_obj(ignored)
return {}
end
local parsed = M.parse_utilities.parse_inline_modifiers(rest_with_defaults:gsub("^:?[^<]+", ""),
{ param_mods = get_clean_param_mods(EtymonParser.keyword_param_mods), generate_obj = generate_obj })
local modifiers = {
unc = parsed.unc or false,
ref = parsed.ref,
text = parsed.text,
lit = parsed.lit,
conj = parsed.conj,
g = parsed.g,
}
-- Validate modifiers against restrictions
EtymonParser.check_modifier_restrictions(modifiers, canonical_keyword, EtymonParser.keyword_param_mods)
return canonical_keyword, modifiers
end
function EtymonParser.parse_balanced_segments(str)
local segments = {}
local current = ""
local depth = 0
local i = 1
while i <= #str do
local char = str:sub(i, i)
if char == "<" then
if depth == 0 and current ~= "" then
table.insert(segments, current)
current = ""
end
depth = depth + 1
current = current .. char
elseif char == ">" then
current = current .. char
depth = depth - 1
if depth == 0 then
table.insert(segments, current)
current = ""
elseif depth < 0 then
error("Unbalanced brackets in etymon: unexpected '>'")
end
else
current = current .. char
end
i = i + 1
end
if depth ~= 0 then
error("Unbalanced brackets in etymon: missing '>'")
end
if current ~= "" then
table.insert(segments, current)
end
return segments
end
function EtymonParser.parse_inline_ety(ety_string, context_lang)
local segments = EtymonParser.parse_balanced_segments(ety_string)
if #segments == 0 then
error("Empty inline etymology")
end
local keyword = M.string_utilities.trim(segments[1])
if not is_keyword(keyword, true) then
error("Invalid keyword '" .. keyword .. "' in inline etymology <ety:" .. keyword .. "...>")
end
local args = { context_lang:getCode(), normalize_keyword(get_canonical_keyword(keyword)) }
for i = 2, #segments do
local segment = segments[i]
if segment:sub(1, 1) == "<" and segment:sub(-1) == ">" then
local inner = segment:sub(2, -2)
if inner ~= "" then
table.insert(args, inner)
end
elseif is_keyword(segment, true) then
-- Handle keywords that appear between bracketed segments
table.insert(args, normalize_keyword(get_canonical_keyword(get_keyword(segment, true))))
end
end
return args
end
function EtymonParser.parse_etymon(param, context_lang)
if is_keyword(param) then
return nil
end
if type(param) ~= "string" then
return nil
end
local lang, rest
local is_family = false
local before_bracket = param:match("^([^<]*)") or param
local lang_code, rest_match = before_bracket:match("^([a-zA-Z][a-zA-Z0-9._-]*):(.*)$")
if lang_code then
local potential_lang = Util.get_lang(lang_code, true)
if potential_lang then
lang = potential_lang
rest = param:sub(#lang_code + 2)
else
local potential_family = Util.get_family(lang_code)
if potential_family then
lang = potential_family
rest = param:sub(#lang_code + 2)
is_family = true
else
lang = context_lang
rest = param
end
end
else
lang = context_lang
rest = param
end
if rest == "" then
M.track("etymon/term/empty")
elseif rest == "?" then
M.track("etymon/term/question-mark")
elseif rest == "-" then
M.track("etymon/term/hyphen")
end
if rest == "" then
return {
lang = lang,
term = nil,
unknown_term = true,
is_family = is_family,
}
end
if rest == "-" then
return {
lang = lang,
term = nil,
suppress_term = true,
is_family = is_family,
}
end
if not rest:find("<", 1, true) then
return {
lang = lang,
term = M.string_utilities.trim(rest),
is_family = is_family,
}
end
local term_text = rest:match("^([^<]*)") or ""
local is_unknown = (term_text == "")
local is_suppress = (term_text == "-")
local function generate_obj(ignored_term)
return { term = (is_unknown or is_suppress) and nil or M.string_utilities.trim(term_text) }
end
local rest_with_defaults = Util.add_boolean_defaults(rest, EtymonParser.etymon_param_mods)
local parsed_obj = M.parse_utilities.parse_inline_modifiers(rest_with_defaults,
{ param_mods = get_clean_param_mods(EtymonParser.etymon_param_mods), generate_obj = generate_obj })
if parsed_obj.id and parsed_obj.id:match("^!") then
parsed_obj.id = parsed_obj.id:sub(2)
parsed_obj.override = true
end
parsed_obj.lang = lang
parsed_obj.is_family = is_family
if is_unknown then
parsed_obj.unknown_term = true
elseif is_suppress then
parsed_obj.suppress_term = true
end
return parsed_obj
end
function EtymonParser.validate(lang, args, id, title, pos, starts_with_lang_code)
-- id is now optional, so only validate if provided
if id then
if mw.ustring.len(id) < 2 then
error("The `id` parameter must have at least two characters.")
end
if id == title or id == Util.get_page_data().pagename then
error("The `id` parameter must not be the same as the page title.")
end
end
local valid_pos = { prefix = true, suffix = true, interfix = true, infix = true, root = true, word = true }
if pos and not valid_pos[pos] then
error("Unknown value provided for `pos`. Valid values: " .. table.concat(require("Module:table").keysToList(valid_pos), ", ") .. ".")
end
local current_keyword = "from"
local etymons_in_group = {}
local keywords = M.data.keywords
local function checkGroup()
if keywords[current_keyword] and keywords[current_keyword].is_group and current_keyword ~= "affix" and current_keyword ~= "surf" and current_keyword ~= "afeq" and #etymons_in_group <= 1 then
error("Detected `:" .. current_keyword .. "` group with fewer than two etymons.")
end
etymons_in_group = {}
end
local start_index = starts_with_lang_code and 2 or 1
for i = start_index, #args do
local param = args[i]
if type(param) ~= "string" then
elseif param:sub(1, 1) == ":" and not is_keyword(param) then
error("Invalid keyword '" .. param .. "'. Did you mean a valid keyword like ':bor', ':inh', etc.?")
elseif is_keyword(param) then
checkGroup()
current_keyword = get_canonical_keyword(get_keyword(param))
else
local etymon_data = EtymonParser.parse_etymon(param, lang)
if etymon_data then
table.insert(etymons_in_group, param)
local param_lang = etymon_data.lang
if etymon_data.is_family and current_keyword == "inherited" then
error("`:inh` does not support family codes; use a specific language.")
end
if etymon_data.is_family and not etymon_data.suppress_term then
error("Family codes require suppressed term (use family:-).")
end
if current_keyword == "from" and param_lang:getFullCode() ~= lang:getFullCode() then
error("`:from` is for same-language derivation, but language does not match. " ..
"Expected '" .. lang:getFullCode() .. "', got '" .. param_lang:getFullCode() .. "'.")
elseif current_keyword == "inherited" then
M.etymology.check_ancestor(lang, param_lang)
end
-- Check modifier restrictions
EtymonParser.check_modifier_restrictions(etymon_data, current_keyword, EtymonParser.etymon_param_mods)
-- postype must be "root" or "word"
local VALID_POSTYPES = { root = true, word = true }
if etymon_data.postype and not VALID_POSTYPES[etymon_data.postype] then
error("Invalid <postype:" .. etymon_data.postype .. ">; must be \"root\" or \"word\".")
end
if etymon_data.ety then
local inline_args = EtymonParser.parse_inline_ety(etymon_data.ety, etymon_data.lang)
EtymonParser.validate(etymon_data.lang, inline_args, nil, nil, nil, true)
end
else
table.insert(etymons_in_group, param)
end
end
end
checkGroup()
end
local DataRetriever = {}
-- Given an etymon data, scrape its page and cache the result in the global state object.
function DataRetriever.cache_page_etymons(etymon_page, etymon_title, key, etymon_lang, etymon_id, redirected_from, descendants_is_toplevel)
local content = etymon_title:getContent()
if not content then
__state.cached_etymon_args[key] = M.data.STATUS.REDLINK
return
end
-- Check if the linked page is a redirect. If it is, the template parsing
-- code below will be effectively skipped, and `scrape_page` will be called
-- again on the redirect target (see the bottom of this function)
local lang_section_for_descendants = nil
local redirect_target = etymon_title.redirect_target
if not redirect_target then
content = M.pages.get_section(content, etymon_lang:getFullName(), 2)
if not content then
__state.cached_etymon_args[key] = M.data.STATUS.MISSING
return
end
lang_section_for_descendants = content
end
local etymon_lang_code = etymon_lang:getFullCode()
local lang_page_key = etymon_lang_code .. ":" .. etymon_page
local found_templates_for_lang = {}
local found_ids = {}
local has_idless_etymon = false
local get_node_class = M.template_parser.class_else_type
-- Look for all {{etymon}} templates within the page content using the template parser
-- This way the same page is never parsed more than once
-- Build a map from senseids to their parent etymonids.
local active_etymon_args = nil
for node in M.template_parser.parse(content):iterate_nodes() do
local node_class = get_node_class(node)
if node_class == "heading" then
-- A new L2 or etymology section acts as a barrier: an {{etymon}} usage
-- used previously cannot be the parent of any subsequent senseids.
-- Note that we don't have to check for L2s due to the usage of `M.pages.get_section` above.
if node:get_name():find("^Etymology") then
active_etymon_args = nil
end
elseif node_class == "template" then
local template_name = node:get_name()
if template_name == "etymon" then
local template_args = node:get_arguments()
-- Check if this etymon is for our language
if template_args[1] == etymon_lang_code then
table.insert(found_templates_for_lang, template_args)
if template_args.id then
local etymon_key = lang_page_key .. ":" .. template_args.id
__state.cached_etymon_args[etymon_key] = template_args
__state.cached_etymon_pages[etymon_key] = tostring(etymon_page)
table.insert(found_ids, template_args.id)
active_etymon_args = template_args
else
has_idless_etymon = true
-- Store idless etymon with default key
local etymon_key = lang_page_key .. ":*"
__state.cached_etymon_args[etymon_key] = template_args
__state.cached_etymon_pages[etymon_key] = tostring(etymon_page)
table.insert(found_ids, "*")
active_etymon_args = template_args
end
end
elseif active_etymon_args and template_name == "senseid" then
local template_args = node:get_arguments()
-- This should always be true for proper usages of {{senseid}}.
if template_args[1] == etymon_lang_code and template_args[2] then
local sense_id_key = lang_page_key .. ":" .. template_args[2]
__state.senseid_parent_etymon[sense_id_key] = active_etymon_args
__state.cached_etymon_pages[sense_id_key] = tostring(etymon_page)
end
end
end
end
if descendants_is_toplevel and lang_section_for_descendants and #found_templates_for_lang > 0 then
M.descendants.cache_page_checks({
lang_section = lang_section_for_descendants,
etymon_lang_code = etymon_lang_code,
found_templates_for_lang = found_templates_for_lang,
entry_title = __state.entry_title,
entry_lang_code = __state.entry_lang_code,
entry_lang = __state.entry_lang_code and Util.get_lang(__state.entry_lang_code, true) or nil,
cached_descendants_checks = __state.cached_descendants_checks,
lang_page_key = lang_page_key,
redirected_from = redirected_from,
})
end
-- Error if multiple etymons exist and at least one is missing an id
if #found_templates_for_lang > 1 and has_idless_etymon then
error("Page '[[" .. tostring(etymon_page) .. "]]' has " .. #found_templates_for_lang ..
" etymon templates for " .. etymon_lang:getCanonicalName() ..
", but at least one is missing an id. All etymons must have unique IDs when there are multiple.")
end
local id_data_list = {}
for _, args in ipairs(found_templates_for_lang) do
local id = args.id or "*"
table.insert(id_data_list, { id = id, pos = args.pos })
end
__state.available_etymon_ids[lang_page_key] = id_data_list
if #found_templates_for_lang == 1 then
__state.single_etymons[lang_page_key] = found_templates_for_lang[1]
end
if redirected_from and __state.available_etymon_ids[lang_page_key] then
__state.available_etymon_ids[redirected_from] = __state.available_etymon_ids[redirected_from] or {}
for _, id_data in ipairs(__state.available_etymon_ids[lang_page_key]) do
table.insert(__state.available_etymon_ids[redirected_from], id_data)
end
end
if __state.cached_etymon_args[key] ~= nil or __state.senseid_parent_etymon[key] ~= nil then
-- All done!
return
elseif redirect_target and not redirected_from then
-- Try scraping the redirect.
etymon_page = redirect_target.prefixedText
DataRetriever.cache_page_etymons(etymon_page, redirect_target, lang_page_key .. ":" .. etymon_id, etymon_lang, etymon_id, lang_page_key, descendants_is_toplevel)
__state.cached_etymon_args[key] = __state.cached_etymon_args[etymon_lang_code .. ":" .. etymon_page .. ":" .. etymon_id]
else
__state.cached_etymon_args[key] = M.data.STATUS.MISSING
end
end
-- Given an etymon object, scrape its page (if necessary) and return its own etymon arguments as well as the page name.
function DataRetriever.get_etymon_args(etymon_data, is_toplevel)
local page = M.links.get_link_page(etymon_data.term, etymon_data.lang)
local norm_lang = Util.get_norm_lang(etymon_data.lang)
local base_key = norm_lang:getFullCode() .. ":" .. page
if etymon_data.id then
local key = base_key .. ":" .. etymon_data.id
local cached_args = __state.cached_etymon_args[key] or __state.senseid_parent_etymon[key]
if cached_args == nil then
local title = mw.title.new(page)
if not title then error('Invalid page title "' .. page .. '" encountered.') end
DataRetriever.cache_page_etymons(page, title, key, norm_lang, etymon_data.id, nil, is_toplevel)
end
cached_args = __state.cached_etymon_args[key] or __state.senseid_parent_etymon[key] -- refresh
-- Get etymon_id from parent if this was resolved via senseid
local parent_etymon = __state.senseid_parent_etymon[key]
local resolved_etymon_id = parent_etymon and parent_etymon.id
local descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = is_toplevel,
base_key = base_key,
lookup = {
explicit_id = etymon_data.id,
parent_etymon = parent_etymon,
},
})
if is_toplevel and descendants_check == nil then
local title = mw.title.new(page)
if title then
DataRetriever.cache_page_etymons(page, title, key, norm_lang, etymon_data.id, nil, true)
descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = true,
base_key = base_key,
lookup = {
explicit_id = etymon_data.id,
parent_etymon = parent_etymon,
},
})
end
end
return cached_args, __state.cached_etymon_pages[key], resolved_etymon_id, descendants_check
else
__state.used_idless_etymon = true
if is_toplevel then
__state.toplevel_idless_etymon = true
end
if __state.available_etymon_ids[base_key] == nil then
local title = mw.title.new(page)
if not title then error('Invalid page title "' .. page .. '" encountered.') end
DataRetriever.cache_page_etymons(page, title, base_key .. ":*", norm_lang, "*", nil, is_toplevel)
end
local ids = __state.available_etymon_ids[base_key] or {}
local count = #ids
-- Try to filter by postype if available and we have multiple candidates
if count > 1 and etymon_data.postype then
local matching_ids = {}
for _, id_data in ipairs(ids) do
if id_data.pos == etymon_data.postype then
table.insert(matching_ids, id_data)
end
end
if #matching_ids == 1 then
local matched_id = matching_ids[1].id
local matched_key = base_key .. ":" .. matched_id
local descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = is_toplevel,
base_key = base_key,
lookup = { id = matched_id },
})
if is_toplevel and descendants_check == nil then
local title = mw.title.new(page)
if title then
DataRetriever.cache_page_etymons(page, title, base_key .. ":*", norm_lang, "*", nil, true)
descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = true,
base_key = base_key,
lookup = { id = matched_id },
})
end
end
return __state.cached_etymon_args[matched_key], __state.cached_etymon_pages[matched_key], nil, descendants_check
end
end
if count == 1 then
local only_id_data = ids[1]
local only_id = (type(only_id_data) == "table" and only_id_data.id) or only_id_data or "*"
local descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = is_toplevel,
base_key = base_key,
lookup = { id_data = only_id_data },
})
if is_toplevel and descendants_check == nil then
local title = mw.title.new(page)
if title then
DataRetriever.cache_page_etymons(page, title, base_key .. ":*", norm_lang, "*", nil, true)
descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = true,
base_key = base_key,
lookup = { id_data = only_id_data },
})
end
end
return __state.single_etymons[base_key], __state.cached_etymon_pages[base_key .. ":" .. only_id], nil, descendants_check
elseif count > 1 then
local id_list = {}
for _, id_data in ipairs(ids) do
local id = type(id_data) == "table" and id_data.id or id_data
if id and id ~= "" then
table.insert(id_list, "\"" .. id .. "\"")
end
end
local suggestion_text = ""
if #id_list > 0 then
suggestion_text = " Available IDs: " .. table.concat(id_list, ", ") .. "."
end
Util.add_warning("Etymology link to '[[" .. page .. "]]' is ambiguous. The page has " ..
count .. " etymon templates for " .. norm_lang:getCanonicalName() ..
". Please specify an ID." .. suggestion_text, true)
return M.data.STATUS.AMBIGUOUS, nil, nil, nil
else
return M.data.STATUS.MISSING, nil, nil, nil
end
end
end
local TreeBuilder = {}
local function parse_etymon_references(refs_text)
if not refs_text or refs_text == "" then
return ""
end
return M.references.parse_references(refs_text)
end
local function parse_tree_references(node)
if node.ref then
node.parsed_ref = parse_etymon_references(node.ref)
end
if node.children then
for _, container in ipairs(node.children) do
if container.terms then
for _, term in ipairs(container.terms) do
parse_tree_references(term)
end
end
end
end
end
-- Build a unique key for deduplication in the seen table
function TreeBuilder.build_key(lang, title, args)
local norm_lang_code = Util.get_norm_lang(lang):getFullCode()
local is_table = type(args) == "table"
local id = (is_table and args.id) or ""
if title then
return norm_lang_code .. ":" .. M.links.get_link_page(title, lang) .. ":" .. id
end
if is_table and args.status == M.data.STATUS.INLINE then
local content_parts = {}
for i = 1, #args do
content_parts[i] = tostring(args[i])
end
return norm_lang_code .. ":*:" .. id .. "\0" .. table.concat(content_parts, "\0")
end
return norm_lang_code .. ":*:" .. id
end
function TreeBuilder.build(lang, title, args, seen, depth, stop_recursion)
seen = seen or {}
depth = depth or 0
local is_toplevel = (depth == 0)
if depth > __state.max_depth_reached then
__state.max_depth_reached = depth
end
__state.total_nodes = __state.total_nodes + 1
local lang_code = lang:getCode()
__state.language_count[lang_code] = (__state.language_count[lang_code] or 0) + 1
local current_id = (type(args) == "table" and args.id) or ""
local key = TreeBuilder.build_key(lang, title, args)
local node = { lang = lang, title = title, id = current_id, args = args, children = {}, status = M.data.STATUS.OK }
if type(args) ~= "table" or seen[key] then
node.status = args or M.data.STATUS.MISSING
-- Mark as duplicate if we've seen this node before
if seen[key] then
node.is_duplicate = true
node.duplicate_key = key
local original_node = seen[key]
if type(original_node) == "table" and original_node.children and #original_node.children > 0 then
node.original_has_children = true
end
end
return node
end
node.status = args.status or M.data.STATUS.OK
seen[key] = node
-- If stop_recursion is set, skip parsing children but check for visible children
if stop_recursion then
local keywords = M.data.keywords
local has_visible_children = false
for i = 2, #args do
local param = args[i]
if type(param) == "string" then
local keyword_base = get_keyword_base(param)
if keyword_base and keywords[keyword_base] then
-- It's a keyword, check if visible in tree (invisible "all" or "tree" = hidden in tree)
local keyword_info = keywords[keyword_base]
local inv = keyword_info.invisible
if not (inv == "all" or inv == true or inv == "tree") then
has_visible_children = true
break
end
elseif param:sub(1, 1) ~= ":" then
-- It's a term (not a keyword), so there are visible children
has_visible_children = true
break
end
end
end
node.has_visible_children = has_visible_children
return node
end
-- Parse args into keyword containers
local current_keyword = "from"
local current_keyword_modifiers = {}
local current_container = nil
-- Helper to track keyword usage at top level
local function track_keyword_usage(keyword, target_lang, source_lang)
if not is_toplevel then return end
if not __state.toplevel_keyword_stats[keyword] then
__state.toplevel_keyword_stats[keyword] = {
count = 0,
target_langs = {},
source_langs = {},
}
end
local keyword_data = __state.toplevel_keyword_stats[keyword]
keyword_data.count = keyword_data.count + 1
local target_code = target_lang:getCode()
keyword_data.target_langs[target_code] = (keyword_data.target_langs[target_code] or 0) + 1
if source_lang then
local source_code = source_lang:getCode()
keyword_data.source_langs[source_code] = (keyword_data.source_langs[source_code] or 0) + 1
end
end
local function ensure_container()
if not current_container or current_container.keyword ~= current_keyword then
current_container = {
keyword = current_keyword,
keyword_info = M.data.keywords[current_keyword],
keyword_modifiers = current_keyword_modifiers,
terms = {},
}
table.insert(node.children, current_container)
-- Override keyword text/phrase for nominalization with <g:code>
if current_keyword_modifiers.g and current_keyword == "nominalization" then
local labels = get_nominalization_label_for_g(current_keyword_modifiers.g)
if not labels then
local codes = {}
for c in pairs(M.data.nominalization_g_codes) do table.insert(codes, c) end
table.sort(codes)
error("Invalid <g:" .. tostring(current_keyword_modifiers.g) .. ">. Supported codes for nominalization: " .. table.concat(codes, ", "))
end
current_container.keyword_info = {}
for k, v in pairs(M.data.keywords[current_keyword]) do current_container.keyword_info[k] = v end
current_container.keyword_info.text = labels.text
current_container.keyword_info.phrase = labels.phrase
end
end
end
for i = 2, #args do
local param = args[i]
if is_keyword(param) then
local keyword, modifiers = EtymonParser.parse_keyword_modifiers(param)
current_keyword = keyword
current_keyword_modifiers = modifiers
current_container = nil -- Force new container for new keyword
elseif type(param) == "string" and param:sub(1, 1) == ":" then
error("Invalid keyword '" .. param .. "'. Did you mean a valid keyword like ':bor', ':inh', etc.?")
elseif type(param) == "string" then
local etymon_data = EtymonParser.parse_etymon(param, lang)
if etymon_data then
-- Track keyword usage at top level
track_keyword_usage(current_keyword, lang, etymon_data.lang)
local term_node = {}
-- Handle suppress_term (-) and unknown_term (empty) directly
if etymon_data.suppress_term or etymon_data.unknown_term then
ensure_container()
if etymon_data.ety then
local inline_args = EtymonParser.parse_inline_ety(etymon_data.ety, etymon_data.lang)
inline_args.id = etymon_data.id
inline_args.status = M.data.STATUS.INLINE
term_node = TreeBuilder.build(etymon_data.lang, nil, inline_args, seen, depth + 1)
else
term_node = {
lang = etymon_data.lang,
children = {},
status = M.data.STATUS.OK,
}
end
term_node.suppress_term = etymon_data.suppress_term
term_node.unknown_term = etymon_data.unknown_term
term_node.is_family = etymon_data.is_family
term_node.is_uncertain = etymon_data.unc
term_node.ref = etymon_data.ref
term_node.t = etymon_data.t
term_node.tr = etymon_data.tr
term_node.ts = etymon_data.ts
term_node.alt = etymon_data.alt
term_node.pos = etymon_data.pos
term_node.lit = etymon_data.lit
term_node.q = etymon_data.q
term_node.qq = etymon_data.qq
term_node.l = etymon_data.l
term_node.ll = etymon_data.ll
else
-- Regular term: fetch arguments from page
local etymon_args, page_of, resolved_etymon_id, descendants_check = DataRetriever.get_etymon_args(etymon_data, is_toplevel)
if etymon_data.id and etymon_args == M.data.STATUS.MISSING and not etymon_data.ety then
local page = M.links.get_link_page(etymon_data.term, etymon_data.lang)
local norm_lang = Util.get_norm_lang(etymon_data.lang)
local base_key = norm_lang:getFullCode() .. ":" .. page
local available_ids = __state.available_etymon_ids[base_key] or {}
if #available_ids > 0 then
__state.has_mismatched_id = true
end
end
-- Check for <ety> inline parameter doesn't override the scraped arguments, unless the latter are missing
if etymon_data.ety then
if etymon_args == M.data.STATUS.REDLINK or etymon_args == M.data.STATUS.MISSING then
__state.current_page_has_inline_etymology = true
if is_toplevel then
__state.toplevel_has_inline_etymology = true
end
local inline_args = EtymonParser.parse_inline_ety(etymon_data.ety, etymon_data.lang)
-- Track inline ety keywords too
local inline_keyword = get_keyword(inline_args[2], true)
if inline_keyword and #inline_args >= 3 then
local inline_etymon = EtymonParser.parse_etymon(inline_args[3], etymon_data.lang)
if inline_etymon then
track_keyword_usage(inline_keyword, etymon_data.lang, inline_etymon.lang)
end
end
inline_args.id = etymon_data.id
inline_args.status = M.data.STATUS.INLINE
etymon_args = inline_args
term_node.page_of = __state.cached_etymon_pages[key] -- term node is on the same page as the parent
else
-- Scraped arguments exist, <ety> is redundant and ignored
__state.current_page_has_redundant_etymology = true
if is_toplevel then
__state.toplevel_redundant_etymology = true
end
end
end
-- Ensure container exists before checking keyword info
ensure_container()
-- Check if current keyword has no_child_categories - if so, stop recursion
local keyword_info = current_container.keyword_info
local should_stop_recursion = (stop_recursion or (keyword_info and keyword_info.no_child_categories))
term_node = TreeBuilder.build(etymon_data.lang, etymon_data.term, etymon_args, seen, depth + 1, should_stop_recursion)
term_node.target_key = Util.get_norm_lang(etymon_data.lang):getFullCode() ..
":" .. M.links.get_link_page(etymon_data.term, etymon_data.lang)
term_node.id = etymon_data.id
term_node.etymon_id = resolved_etymon_id -- The actual etymon id when resolved via senseid
term_node.t = etymon_data.t
term_node.tr = etymon_data.tr
term_node.ts = etymon_data.ts
term_node.pos = etymon_data.pos
term_node.alt = etymon_data.alt
term_node.ref = etymon_data.ref
term_node.is_uncertain = etymon_data.unc
term_node.override = etymon_data.override
term_node.page_of = page_of
term_node.aftype = etymon_data.aftype
term_node.postype = etymon_data.postype
term_node.bor = etymon_data.bor
term_node.lbor = etymon_data.lbor
term_node.slbor = etymon_data.slbor
term_node.lit = etymon_data.lit
term_node.is_family = etymon_data.is_family
term_node.q = etymon_data.q
term_node.qq = etymon_data.qq
term_node.l = etymon_data.l
term_node.ll = etymon_data.ll
term_node.missing_descendants_header, term_node.missing_descendants_entry =
M.descendants.get_term_sync_flags(current_keyword, term_node.status, descendants_check)
end
table.insert(current_container.terms, term_node)
end
end
end
return node
end
-- Convert etymology tree to JSON-serializable table
local function tree_to_json(node)
local obj = {
term = node.title,
lang = node.lang:getCode(),
lang_name = node.lang:getCanonicalName(),
id = (node.id and node.id ~= "") and node.id or nil,
status = node.status,
is_uncertain = node.is_uncertain or nil,
is_duplicate = node.is_duplicate or nil,
gloss = node.t,
transliteration = node.tr,
transcription = node.ts,
alt = node.alt,
pos = node.pos,
children = {},
}
for _, container in ipairs(node.children or {}) do
local keyword_info = container.keyword_info
if keyword_info then
local container_obj = {
keyword = container.keyword,
keyword_label = keyword_info.text,
keyword_abbrev = keyword_info.abbrev,
is_group = keyword_info.is_group or nil,
is_invisible = keyword_info.invisible or nil,
is_uncertain = (container.keyword_modifiers and container.keyword_modifiers.unc) or nil,
terms = {},
}
for _, term in ipairs(container.terms or {}) do
table.insert(container_obj.terms, tree_to_json(term))
end
table.insert(obj.children, container_obj)
end
end
return obj
end
local function track_ranges(base_key, value, ranges, lang_code)
M.track("etymon/" .. base_key .. "/" .. value)
if lang_code then
M.track("etymon/lang/" .. lang_code .. "/" .. base_key .. "/" .. value)
end
for _, range in ipairs(ranges) do
local matches = false
if range.min and range.max then
matches = value >= range.min and value <= range.max
elseif range.min then
matches = value >= range.min
elseif range.max then
matches = value <= range.max
elseif range.exact then
matches = value == range.exact
end
if matches then
M.track("etymon/" .. base_key .. "/" .. range.label)
if lang_code then
M.track("etymon/lang/" .. lang_code .. "/" .. base_key .. "/" .. range.label)
end
break
end
end
end
-- Build and return the etymology data tree for a given term.
function export.get_tree(lang, title, args, options)
options = options or {}
__state.entry_title = title
__state.entry_lang_code = lang:getCode()
if options.validate then
EtymonParser.validate(lang, args, options.id, title, options.pos, false)
end
local lang_code = lang:getCode()
local start_index = (args[1] == lang_code) and 2 or 1
local tree_args = { [1] = lang_code, id = options.id or args.id }
for i = start_index, #args do
table.insert(tree_args, args[i])
end
__state.cached_etymon_args[lang_code .. ":" .. title .. ":" .. (tree_args.id or "")] = tree_args
local ety_data_tree = TreeBuilder.build(lang, title, tree_args)
parse_tree_references(ety_data_tree)
if options.json then
return M.JSON.toJSON(tree_to_json(ety_data_tree))
end
return ety_data_tree
end
-- Given a language code, page name and optionally the id= parameter,
-- render the tree and only the etymology tree for the relevant page.
-- Fetches and parses the corresponding {{etymon}} from the requested page,
-- and any further pages needed to render the tree.
-- Parameters can be passed either through the #invoke or as
-- template parameters *through* an #invoke.
function export.render_tree_for_etymon_on_page(frame)
local frame_args = frame.args
local parent_args = frame:getParent().args
local langcode = frame_args[1] or parent_args[1]
local pagename = frame_args[2] or parent_args[2]
local id = frame_args["id"] or parent_args["id"]
local display_title = frame_args["title"] or parent_args["title"]
local parsed_title = mw.title.new(pagename, 0)
local title
if parsed_title.namespace == 0 then
title = M.pages.safe_page_name(parsed_title)
elseif parsed_title.namespace == 118 then
title = "*" .. M.pages.safe_page_name(parsed_title)
else
error("Unsupported namespace for render_tree_for_etymon_on_page: " .. parsed_title.namespace)
end
local lang = Util.get_lang(langcode)
-- Construct etymon_data for DataRetriever.get_args.
local etymon_data = {
lang = lang,
term = title,
id = id
}
local args, pagename = DataRetriever.get_etymon_args(etymon_data, true)
if args == M.data.STATUS.MISSING then
error("The etymon template was not found (language " ..
langcode ..
", title '" ..
title ..
"'" ..
(id and ", ID '" .. id .. "'" or ", no ID given") .. "). Page contents may have changed in the interim.")
end
local ety_data_tree = export.get_tree(lang, display_title or title, args, {
validate = true,
id = id,
})
local output = {}
table.insert(output, M.template_styles("Module:etymon/styles.css"))
table.insert(output, M.tree.render({
data_tree = ety_data_tree,
format_term_func = function(term, is_toplevel)
return Util.format_term(term, is_toplevel, {
gloss = "suppress",
pos = "suppress",
lit = "suppress",
tree_ql = "suppress",
})
end,
}))
return table.concat(output)
end
function export.main(frame)
local parent_args = frame:getParent().args
local args = M.parameters.process(parent_args, M.parameters_data.etymon)
local lang = args[1]
local etymon_args = args[2]
local id = args.id
local title = args.title
local text = args.text
local tree = args.tree
local etydate = args.etydate
local rfe = args.rfe
local page_data = Util.get_page_data()
if not title then
title = page_data.pagename
if page_data.namespace == "Từ tái tạo" then title = "*" .. title end
end
local current_L2 = M.pages.get_current_L2()
if current_L2 then
local norm_lang = Util.get_norm_lang(lang)
local norm_name = ucfirst(norm_lang:getCanonicalName())
if current_L2 ~= norm_name then
local lang_desc = lang:getCode() .. " (" .. lang:getCanonicalName() .. ")"
if norm_lang:getCode() ~= lang:getCode() then
lang_desc = lang_desc .. ", normalized to " .. norm_lang:getCode() .. " (" .. norm_name .. ")"
end
error("Ngôn ngữ '" .. lang_desc .. "' không khớp với đầu mục L2 (" .. current_L2 .. ").")
end
end
local ety_data_tree = export.get_tree(lang, title, etymon_args, {
validate = true,
pos = args.pos,
id = id,
json = args.json,
})
if args.json then
return ety_data_tree
end
local output = {}
local text_allowlist_mode = M.text_allowed.default_mode or "off"
if text and text_allowlist_mode ~= "off" and not Util.is_text_param_allowed_for_lang(lang) then
local msg = "Etymology texts (parameter <code>text=</code>) are not allowed for " .. lang:getFullName() ..
"; see [[Template:etymon#Text allowlist|Template:etymon § Text allowlist]] for the list of languages that may use the <code>text=</code> parameter."
if text_allowlist_mode == "error" then
error(msg)
else
Util.add_warning(msg, true)
end
end
local lang_exc = Util.get_lang_exception(lang)
if lang_exc and lang_exc.disallow then
local disallow = lang_exc.disallow
local error_text = " for " .. lang:getFullName()
if disallow.ref then
error_text = error_text .. "; see " .. disallow.ref
else
error_text = error_text .. "."
end
if tree and disallow.tree then
error("Etymology trees are not allowed" .. error_text)
end
if text and disallow.text then
error("Etymology texts are not allowed" .. error_text)
end
end
if etydate then
local etydate_param_mods = {
ref = { list = true, type = "references", allow_holes = true },
refn = { list = true, allow_holes = true },
nocap = { type = "boolean" },
}
local function generate_etydate_obj(etydate_text)
local etydate_specs = {}
for spec in etydate_text:gmatch("[^,]+") do
table.insert(etydate_specs, mw.text.trim(spec))
end
return { [1] = etydate_specs }
end
local parsed_etydate = M.parse_utilities.parse_inline_modifiers(etydate, { param_mods = etydate_param_mods, generate_obj = generate_etydate_obj })
local etydate_args = {
[1] = parsed_etydate[1],
nocap = parsed_etydate.nocap or false,
ref = parsed_etydate.ref or {},
refn = parsed_etydate.refn or { maxindex = 0 }
}
if etydate_args.refn then
local max = 0
for k, v in pairs(etydate_args.refn) do
if type(k) == "number" and k > max then
max = k
end
end
etydate_args.refn.maxindex = max
end
ety_data_tree.etydate = M.etydate.format_etydate(etydate_args)
-- Parse and store references separately for text rendering
local refs_text = ""
for _, ref in ipairs(etydate_args.ref) do
refs_text = refs_text .. (refs_text ~= "" and "" or "") .. ref
end
if refs_text ~= "" then
ety_data_tree.etydate_refs = M.references.parse_references(refs_text)
end
end
if tree then
table.insert(output, M.template_styles("Module:etymon/styles.css"))
table.insert(output, M.tree.render({
data_tree = ety_data_tree,
format_term_func = function(term, is_toplevel)
return Util.format_term(term, is_toplevel, {
gloss = "suppress",
pos = "suppress",
lit = "suppress",
tree_ql = "suppress",
})
end,
}))
end
-- Check if there are any visible children in tree (invisible "all" or "tree" = hidden in tree)
local has_visible_children = false
for _, child in ipairs(ety_data_tree.children or {}) do
local child_keyword_info = child.keyword_info
local inv = child_keyword_info and child_keyword_info.invisible
if not (inv == "all" or inv == true or inv == "tree") then
has_visible_children = true
break
end
end
local tree_disallowed = lang_exc and lang_exc.disallow and lang_exc.disallow.tree
local anchor = M.anchors.etymonid(lang, id, {
no_tree = args.notree,
title = title,
empty_tree = (not has_visible_children) or tree_disallowed
})
table.insert(output, anchor)
if text then
local max_depth, stop_at_blue_link, stop_at_lang, stop_at_lang_or_bluelink
if text == "++" then
max_depth, stop_at_blue_link = false, false
elseif text == "+" then
max_depth, stop_at_blue_link = 1, false
elseif text == "*" then
max_depth, stop_at_blue_link = false, true
elseif text:match("^:[^*]+%*$") then
-- Stop at a specific language OR first bluelink after it, e.g., ":ota*"
-- If the target language is a redlink, continue to the first bluelink
local lang_code = text:match("^:([^*]+)%*$")
if lang_code and lang_code ~= "" then
local lang_obj = Util.get_lang(lang_code, true)
if lang_obj then
stop_at_lang_or_bluelink = lang_code
else
Util.add_warning('Invalid language code "' .. lang_code .. '" in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false
end
else
Util.add_warning('Empty language code in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false
end
elseif text:sub(1, 1) == ":" then
-- Stop at a specific language, e.g., ":ar" stops at first Arabic term
local lang_code = text:sub(2)
if lang_code ~= "" then
-- Validate the language code
local lang_obj = Util.get_lang(lang_code, true)
if lang_obj then
stop_at_lang = lang_code
else
Util.add_warning('Invalid language code "' .. lang_code .. '" in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false -- default to ++
end
else
Util.add_warning('Empty language code in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false -- default to ++
end
else
local num = tonumber(text)
if num and num >= 1 then
max_depth, stop_at_blue_link = num, false
else
error('Invalid text value "' ..
text .. '". Valid values are: "++" (full chain), "+" (first step only), "*" (until first blue link), a number (max steps), ":lang" (stop at language), or ":lang*" (stop at language or first bluelink if redlink)')
end
end
table.insert(output, M.text.render({
data_tree = ety_data_tree,
format_term_func = Util.format_term,
max_depth = max_depth,
stop_at_blue_link = stop_at_blue_link,
curr_page = page_data.pagename,
nodot = args.nodot,
stop_at_lang = stop_at_lang,
stop_at_lang_or_bluelink = stop_at_lang_or_bluelink,
}))
end
if rfe then
local rfe_param_mods = {
nocat = { type = "boolean" },
sort = {},
y = {},
m = {},
fragment = {},
section = {},
box = { type = "boolean" },
noes = { type = "boolean" },
}
local function generate_rfe_obj(rfe_text)
-- Check if it's a boolean true value
if M.yesno(rfe_text, false) then
return { is_boolean = true }
else
return { text = rfe_text }
end
end
local rfe_with_defaults = Util.add_boolean_defaults(rfe, rfe_param_mods)
local parsed_rfe = M.parse_utilities.parse_inline_modifiers(rfe_with_defaults, {
param_mods = rfe_param_mods,
generate_obj = generate_rfe_obj
})
local rfe_args = {
[1] = lang:getCode(),
nocat = parsed_rfe.nocat,
sort = parsed_rfe.sort,
y = parsed_rfe.y,
m = parsed_rfe.m,
fragment = parsed_rfe.fragment,
section = parsed_rfe.section,
box = parsed_rfe.box,
noes = parsed_rfe.noes,
}
if not parsed_rfe.is_boolean then
rfe_args[2] = parsed_rfe.text
end
table.insert(output, frame:expandTemplate({
title = "rfe",
args = rfe_args
}))
end
if Util.is_content_page() and __state.max_depth_reached > 0 then
local lang_code = lang:getCode()
local depth_ranges = {
{ min = 50, label = "extremely-deep" },
{ min = 20, label = "20+" },
{ min = 10, max = 19, label = "10-19" },
{ min = 5, max = 9, label = "5-9" },
{ min = 3, max = 4, label = "3-4" },
{ max = 2, label = "1-2" }
}
local node_ranges = {
{ min = 100, label = "extremely-large" },
{ min = 50, label = "50+" },
{ min = 20, max = 49, label = "20-49" },
{ min = 10, max = 19, label = "10-19" },
{ min = 5, max = 9, label = "5-9" },
{ max = 4, label = "1-4" }
}
local language_ranges = {
{ min = 10, label = "10+" },
{ min = 5, max = 9, label = "5-9" },
{ min = 3, max = 4, label = "3-4" },
{ exact = 2, label = "2" },
{ exact = 1, label = "1" }
}
track_ranges("depth", __state.max_depth_reached, depth_ranges, lang_code)
track_ranges("nodes", __state.total_nodes, node_ranges, lang_code)
local unique_languages = 0
for _ in pairs(__state.language_count) do
unique_languages = unique_languages + 1
end
track_ranges("unique-languages", unique_languages, language_ranges, lang_code)
if __state.total_nodes == __state.max_depth_reached + 1 then
track_ranges("linear-depth", __state.max_depth_reached, depth_ranges, lang_code)
end
end
local categories = {}
if Util.is_content_page() then
local should_suppress_categories = lang_exc and lang_exc.suppress_categories
if not should_suppress_categories and not args.nocat then
categories = M.categories.render({
data_tree = ety_data_tree,
page_lang = lang,
available_etymon_ids = __state.available_etymon_ids,
senseid_parent_etymon = __state.senseid_parent_etymon,
get_norm_lang_func = Util.get_norm_lang,
lang_exc = lang_exc,
})
end
local target_lang_code = lang:getCode()
for keyword, keyword_data in pairs(__state.toplevel_keyword_stats) do
-- Track keyword globally
M.track("etymon/keyword/" .. keyword)
-- Track keyword per target language
M.track("etymon/keyword/" .. keyword .. "/target/" .. target_lang_code)
-- Track keyword per source language
for source_code, count in pairs(keyword_data.source_langs) do
M.track("etymon/keyword/" .. keyword .. "/source/" .. source_code)
-- Track keyword per target+source combination
M.track("etymon/keyword/" .. keyword .. "/target/" .. target_lang_code .. "/source/" .. source_code)
end
end
if tree then
table.insert(categories, "Trang có cây từ nguyên")
table.insert(categories, "Mục từ có cây từ nguyên " .. lang:getCanonicalName())
end
if text then table.insert(categories, lang:getCanonicalName() .. " entries with etymology texts") end
if args.exnihilo then table.insert(categories, lang:getCanonicalName() .. " terms coined ex nihilo") end
if __state.toplevel_has_inline_etymology then
table.insert(categories, "Pages with inline etymon for redlinks")
end
if __state.toplevel_redundant_etymology then
table.insert(categories, "Pages with redundant inline etymon")
end
if __state.toplevel_idless_etymon then
table.insert(categories, "Trang có cây từ nguyên thiếu ID")
end
if __state.has_mismatched_id then
table.insert(categories, lang:getCanonicalName() .. " entries referencing etymons with mismatched IDs")
end
end
if #categories > 0 then
table.insert(output, M.utilities.format_categories(categories, lang))
end
if __state.warnings then
for _, warning in ipairs(__state.warnings) do
table.insert(output, "\n" .. warning)
end
end
return table.concat(output)
end
return export
lmr8pgx7ykhw4tu51hga1betb67oh1q
2344440
2344436
2026-04-12T07:09:29Z
TheHighFighter2
42988
2344440
Scribunto
text/plain
--[=[
This module implements the {{etymon}} template for structured etymology data on Wiktionary.
It enables the creation of etymology trees and text by parsing etymon chains,
scraping linked pages for their own {{etymon}} data, and recursively building a tree
of derivational relationships.
Tác giả:
- Triển khai ban đầu: [[Thành viên:Ioaxxere]]
- Tái cấu trúc lại mô đun (tháng 9 năm 2025): [[Thành viên:Fenakhay]] ([[:en:Special:Diff/86717746]])
Modules:
- [[Module:etymon]]: main module handling parsing, validation, tree building, and page scraping
- [[Module:etymon/data]]: keyword definitions, configuration, and status constants
- [[Module:etymon/tree]]: etymology tree rendering
- [[Module:etymon/text]]: etymology text generation
- [[Module:etymon/categories]]: category generation logic
]=]
local export = {}
local etymon_data_module = "Module:etymon/data"
local etymon_text_module = "Module:etymon/text"
local etymon_tree_module = "Module:etymon/tree"
local etymon_categories_module = "Module:etymon/categories"
local etymon_descendants_module = "Module:etymon/descendants"
local ucfirst = require("Module:string utilities").ucfirst
local __state = {
cached_etymon_args = {},
cached_etymon_pages = {},
cached_descendants_checks = {},
senseid_parent_etymon = {},
available_etymon_ids = {},
single_etymons = {},
entry_title = nil,
entry_lang_code = nil,
current_page_has_inline_etymology = false,
current_page_has_redundant_etymology = false,
used_idless_etymon = false,
toplevel_has_inline_etymology = false,
toplevel_redundant_etymology = false,
toplevel_idless_etymon = false,
has_mismatched_id = false,
max_depth_reached = 0,
total_nodes = 0,
language_count = {},
toplevel_keyword_stats = {},
warnings = {},
}
local loader = require("Module:module loader")
local M = loader.init({
require = {
data = etymon_data_module,
tree = etymon_tree_module,
text = etymon_text_module,
categories = etymon_categories_module,
descendants = etymon_descendants_module,
anchors = "Module:anchors",
etydate = "Module:etydate",
etymology = "Module:etymology",
families = "Module:families",
languages = "Module:languages",
languages_errorgetby = "Module:languages/errorGetBy",
links = "Module:links",
pages = "Module:pages",
parameters = "Module:parameters",
string_utilities = "Module:string utilities",
template_parser = "Module:template parser",
utilities = "Module:utilities",
debug = "Module:debug",
en_utilities = "Module:en-utilities",
parse_utilities = "Module:parse utilities",
references = "Module:references",
track = "Module:debug/track",
template_styles = "Module:TemplateStyles",
script_utilities = "Module:script utilities",
JSON = "Module:JSON",
yesno = "Module:yesno",
},
loadData = {
headword_data = "Module:headword/data",
parameters_data = "Module:parameters/data",
text_allowed = "Module:etymon/data/text_allowed",
},
})
local Util = {}
function Util.format_error(message, preview_only)
if preview_only and not M.pages.is_preview() then
return nil
end
return '<span class="error">' .. message .. '</span>'
end
function Util.add_warning(message, preview_only)
local formatted = Util.format_error(message, preview_only)
if formatted then
table.insert(__state.warnings, formatted)
end
end
function Util.is_text_param_allowed_for_lang(lang)
if not lang or type(lang) ~= "table" then
return false
end
local types = lang.getTypes and lang:getTypes()
if types and types.family then
local code = lang.getCode and lang:getCode()
return code and M.text_allowed.families[code] == true
end
local full_code = lang.getFullCode and lang:getFullCode()
if full_code and M.text_allowed.langs[full_code] then
return true
end
if lang.inFamily then
for family_code in pairs(M.text_allowed.families) do
if lang:inFamily(family_code) then
return true
end
end
end
return false
end
function Util.get_lang(code, no_error)
if no_error then
return M.languages.getByCode(code, nil, true)
end
return M.languages.getByCode(code, nil, true) or M.languages_errorgetby.code(code, true, true)
end
function Util.get_family(code)
return M.families.getByCode(code)
end
function Util.get_lang_exception(lang)
-- Families have no language-specific exceptions
if lang.getTypes and lang:getTypes().family then
return nil
end
local code = lang:getCode()
local lang_exceptions = M.data.config.lang_exceptions
if lang_exceptions[code] then
return lang_exceptions[code]
end
for norm_code, exc in pairs(lang_exceptions) do
if exc.normalize_to and code == exc.normalize_to then
return exc
end
if exc.normalize_from_families then
local should_normalize = false
for _, family in ipairs(exc.normalize_from_families) do
if lang:inFamily(family) then
should_normalize = true
break
end
end
if should_normalize and exc.normalize_exclude_families then
for _, family in ipairs(exc.normalize_exclude_families) do
if lang:inFamily(family) then
should_normalize = false
break
end
end
end
if should_normalize then
local ret = {}
for k, v in pairs(exc) do
ret[k] = v
end
ret.suppress_tr = nil
return ret
end
end
end
return nil
end
function Util.get_norm_lang(lang)
local exc = Util.get_lang_exception(lang)
if exc and exc.normalize_to then
return M.languages.getByCode(exc.normalize_to)
end
return lang
end
-- Add default values for boolean modifiers (e.g., <unc> becomes <unc:1>)
-- This is needed because Module:parse utilities expects boolean modifiers to have explicit values
function Util.add_boolean_defaults(str, param_mods)
local result = str
for name, spec in pairs(param_mods) do
if spec.type == "boolean" then
-- Replace <name> with <name:1> (but not <name:...> which already has a value)
result = result:gsub("<" .. name .. ">", "<" .. name .. ":1>")
end
end
return result
end
-- Centralized term formatting: handles suppress_term, unknown_term, and regular terms
function Util.format_term(term, is_toplevel, opts)
opts = opts or {}
-- suppress_term (-) returns nil
if term.suppress_term then
return nil
end
local lang = term.lang
local exc = Util.get_lang_exception(lang)
if is_toplevel then
local display_text = term.alt or term.title or ""
local sc = term.sc or lang:findBestScript(display_text)
local bold_text = tostring(mw.html.create("strong")
:addClass("selflink")
:wikitext(display_text))
return M.script_utilities.tag_text(bold_text, lang, sc, "term")
end
local link_params = { lang = lang }
link_params.term = not term.unknown_term and term.title or nil
link_params.alt = term.alt
link_params.id = (not term.unknown_term and term.id and term.id ~= "") and term.id or nil
if not (exc and exc.suppress_tr) then
link_params.tr = term.tr
link_params.ts = term.ts
else
link_params.suppress_tr = true
end
link_params.lit = (opts.lit ~= "suppress") and term.lit or nil
if opts.gloss ~= "suppress" then
link_params.gloss = term.t
end
if opts.pos ~= "suppress" then
link_params.pos = term.pos
end
if exc and exc.suppress_tr then
link_params.lit = nil
end
local show_qualifiers
if opts.tree_ql ~= "suppress" then
if term.q then
link_params.q = term.q
end
if term.qq then
link_params.qq = term.qq
end
if term.l then
link_params.l = term.l
end
if term.ll then
link_params.ll = term.ll
end
show_qualifiers = term.q or term.qq or term.l or term.ll
end
return M.links.full_link(link_params, "term", nil, show_qualifiers and true or nil)
end
local __is_content_page_cached
function Util.is_content_page()
if __is_content_page_cached == nil then
__is_content_page_cached = M.pages.is_content_page(mw.title.getCurrentTitle())
end
return __is_content_page_cached
end
local __page_data_cached
function Util.get_page_data()
if not __page_data_cached then
__page_data_cached = M.headword_data.page
end
return __page_data_cached
end
-- Extract base keyword from param (without modifiers)
local function get_keyword_base(param)
if type(param) ~= "string" then return nil end
local base = param:match("^:?([^<]+)") or param:gsub("^:", "")
return base
end
local function is_keyword(param, allow_colon_less)
if type(param) ~= "string" then return false end
local keywords = M.data.keywords
if param:sub(1, 1) == ":" then
local base = get_keyword_base(param)
return keywords[base] ~= nil
end
if allow_colon_less then
local base = get_keyword_base(param)
return keywords[base] ~= nil
end
return false
end
local function get_keyword(param, allow_colon_less)
if type(param) ~= "string" then return nil end
local keywords = M.data.keywords
if param:sub(1, 1) == ":" then
return get_keyword_base(param)
end
if allow_colon_less then
local base = get_keyword_base(param)
if keywords[base] then
return base
end
end
return nil
end
local function normalize_keyword(keyword)
if keyword:sub(1, 1) == ":" then
return keyword
end
return ":" .. keyword
end
-- Resolve keyword (possibly an alias) to its canonical form. Used only at input boundaries
local function get_canonical_keyword(keyword)
if not keyword then return keyword end
return M.data.keyword_canonical[keyword] or keyword
end
-- Build text/phrase for nominalization with <g:code> (uses data module for codes only).
local function get_nominalization_label_for_g(code)
if not code or code == "" then return nil end
local codes = M.data.nominalization_g_codes
local adj = codes[code]
if not adj and #code == 2 then
local gender_adj = codes[code:sub(1, 1)]
local number_adj = codes[code:sub(2, 2)]
if gender_adj and number_adj then
adj = gender_adj .. " " .. number_adj
end
end
if not adj then return nil end
local text = adj:gsub("^%l", function(c) return string.upper(c) end) .. " nominalization of"
local phrase = M.en_utilities.add_indefinite_article(adj .. " nominalization of", false)
return { text = text, phrase = phrase }
end
local EtymonParser = {}
-- Keyword modifier definitions
EtymonParser.keyword_param_mods = {
unc = { type = "boolean" },
ref = {},
text = { restrict = { keywords = { "from", "derived" } } },
lit = { restrict = { keywords = { "affix", "surf", "univerbation" } } },
conj = {}, -- conjunction for alternatives: "and", "or", "and/or", etc.
g = { restrict = { keywords = { "nominalization" } } },
}
-- Term modifier definitions
EtymonParser.etymon_param_mods = {
id = {},
t = {},
tr = {},
ts = {},
q = {},
qq = {},
l = {},
ll = {},
pos = {},
alt = {},
ety = {},
lit = {},
unc = { type = "boolean" },
ref = {},
aftype = { restrict = { keywords = { "affix", "surf", "afeq" } } },
postype = {},
bor = { type = "boolean", restrict = { keywords = { "affix", "surf" } } },
slbor = { type = "boolean", restrict = { keywords = { "affix", "surf" } } },
lbor = { type = "boolean", restrict = { keywords = { "affix", "surf" } } },
}
local function get_clean_param_mods(param_mods)
local clean = {}
for mod_name, mod_def in pairs(param_mods) do
clean[mod_name] = {}
for key, value in pairs(mod_def) do
if key ~= "restrict" then
clean[mod_name][key] = value
end
end
end
return clean
end
function EtymonParser.check_modifier_restrictions(modifiers, current_keyword, param_mods)
for mod_name, mod_value in pairs(modifiers) do
-- Only check restrictions if the modifier has a non-false/nil value
if mod_value then
local mod_def = param_mods[mod_name]
if mod_def and mod_def.restrict and mod_def.restrict.keywords then
local allowed_keywords = mod_def.restrict.keywords
local is_allowed = false
for _, allowed_keyword in ipairs(allowed_keywords) do
if current_keyword == allowed_keyword then
is_allowed = true
break
end
end
if not is_allowed then
local keyword_list = {}
for _, kw in ipairs(allowed_keywords) do
table.insert(keyword_list, ":" .. kw)
end
local keyword_str = table.concat(keyword_list, #keyword_list == 2 and " or " or ", ")
if #keyword_list > 2 then
-- Replace last comma with "or"
keyword_str = keyword_str:gsub(", ([^,]+)$", " or %1")
end
local mod_display = mod_value == true and "<" .. mod_name .. ">" or "<" .. mod_name .. ":" .. tostring(mod_value) .. ">"
error("The modifier `" .. mod_display .. "` is only allowed for the keyword" .. (#keyword_list > 1 and "s " or " ") .. keyword_str .. ".")
end
end
end
end
end
-- Parse keyword with modifiers (e.g., ":bor<unc>" or ":bor<ref:{{R:example}}>")
function EtymonParser.parse_keyword_modifiers(param)
if type(param) ~= "string" then return nil, {} end
local base_keyword = get_keyword_base(param)
if not base_keyword then return nil, {} end
local canonical_keyword = get_canonical_keyword(base_keyword)
-- Check if there are any modifiers
if not param:find("<", 1, true) then
return canonical_keyword, {}
end
-- Parse modifiers using the same mechanism as etymon parsing
local rest_with_defaults = Util.add_boolean_defaults(param, EtymonParser.keyword_param_mods)
local function generate_obj(ignored)
return {}
end
local parsed = M.parse_utilities.parse_inline_modifiers(rest_with_defaults:gsub("^:?[^<]+", ""),
{ param_mods = get_clean_param_mods(EtymonParser.keyword_param_mods), generate_obj = generate_obj })
local modifiers = {
unc = parsed.unc or false,
ref = parsed.ref,
text = parsed.text,
lit = parsed.lit,
conj = parsed.conj,
g = parsed.g,
}
-- Validate modifiers against restrictions
EtymonParser.check_modifier_restrictions(modifiers, canonical_keyword, EtymonParser.keyword_param_mods)
return canonical_keyword, modifiers
end
function EtymonParser.parse_balanced_segments(str)
local segments = {}
local current = ""
local depth = 0
local i = 1
while i <= #str do
local char = str:sub(i, i)
if char == "<" then
if depth == 0 and current ~= "" then
table.insert(segments, current)
current = ""
end
depth = depth + 1
current = current .. char
elseif char == ">" then
current = current .. char
depth = depth - 1
if depth == 0 then
table.insert(segments, current)
current = ""
elseif depth < 0 then
error("Unbalanced brackets in etymon: unexpected '>'")
end
else
current = current .. char
end
i = i + 1
end
if depth ~= 0 then
error("Unbalanced brackets in etymon: missing '>'")
end
if current ~= "" then
table.insert(segments, current)
end
return segments
end
function EtymonParser.parse_inline_ety(ety_string, context_lang)
local segments = EtymonParser.parse_balanced_segments(ety_string)
if #segments == 0 then
error("Empty inline etymology")
end
local keyword = M.string_utilities.trim(segments[1])
if not is_keyword(keyword, true) then
error("Invalid keyword '" .. keyword .. "' in inline etymology <ety:" .. keyword .. "...>")
end
local args = { context_lang:getCode(), normalize_keyword(get_canonical_keyword(keyword)) }
for i = 2, #segments do
local segment = segments[i]
if segment:sub(1, 1) == "<" and segment:sub(-1) == ">" then
local inner = segment:sub(2, -2)
if inner ~= "" then
table.insert(args, inner)
end
elseif is_keyword(segment, true) then
-- Handle keywords that appear between bracketed segments
table.insert(args, normalize_keyword(get_canonical_keyword(get_keyword(segment, true))))
end
end
return args
end
function EtymonParser.parse_etymon(param, context_lang)
if is_keyword(param) then
return nil
end
if type(param) ~= "string" then
return nil
end
local lang, rest
local is_family = false
local before_bracket = param:match("^([^<]*)") or param
local lang_code, rest_match = before_bracket:match("^([a-zA-Z][a-zA-Z0-9._-]*):(.*)$")
if lang_code then
local potential_lang = Util.get_lang(lang_code, true)
if potential_lang then
lang = potential_lang
rest = param:sub(#lang_code + 2)
else
local potential_family = Util.get_family(lang_code)
if potential_family then
lang = potential_family
rest = param:sub(#lang_code + 2)
is_family = true
else
lang = context_lang
rest = param
end
end
else
lang = context_lang
rest = param
end
if rest == "" then
M.track("etymon/term/empty")
elseif rest == "?" then
M.track("etymon/term/question-mark")
elseif rest == "-" then
M.track("etymon/term/hyphen")
end
if rest == "" then
return {
lang = lang,
term = nil,
unknown_term = true,
is_family = is_family,
}
end
if rest == "-" then
return {
lang = lang,
term = nil,
suppress_term = true,
is_family = is_family,
}
end
if not rest:find("<", 1, true) then
return {
lang = lang,
term = M.string_utilities.trim(rest),
is_family = is_family,
}
end
local term_text = rest:match("^([^<]*)") or ""
local is_unknown = (term_text == "")
local is_suppress = (term_text == "-")
local function generate_obj(ignored_term)
return { term = (is_unknown or is_suppress) and nil or M.string_utilities.trim(term_text) }
end
local rest_with_defaults = Util.add_boolean_defaults(rest, EtymonParser.etymon_param_mods)
local parsed_obj = M.parse_utilities.parse_inline_modifiers(rest_with_defaults,
{ param_mods = get_clean_param_mods(EtymonParser.etymon_param_mods), generate_obj = generate_obj })
if parsed_obj.id and parsed_obj.id:match("^!") then
parsed_obj.id = parsed_obj.id:sub(2)
parsed_obj.override = true
end
parsed_obj.lang = lang
parsed_obj.is_family = is_family
if is_unknown then
parsed_obj.unknown_term = true
elseif is_suppress then
parsed_obj.suppress_term = true
end
return parsed_obj
end
function EtymonParser.validate(lang, args, id, title, pos, starts_with_lang_code)
-- id is now optional, so only validate if provided
if id then
if mw.ustring.len(id) < 2 then
error("The `id` parameter must have at least two characters.")
end
if id == title or id == Util.get_page_data().pagename then
error("The `id` parameter must not be the same as the page title.")
end
end
local valid_pos = { prefix = true, suffix = true, interfix = true, infix = true, root = true, word = true }
if pos and not valid_pos[pos] then
error("Unknown value provided for `pos`. Valid values: " .. table.concat(require("Module:table").keysToList(valid_pos), ", ") .. ".")
end
local current_keyword = "from"
local etymons_in_group = {}
local keywords = M.data.keywords
local function checkGroup()
if keywords[current_keyword] and keywords[current_keyword].is_group and current_keyword ~= "affix" and current_keyword ~= "surf" and current_keyword ~= "afeq" and #etymons_in_group <= 1 then
error("Detected `:" .. current_keyword .. "` group with fewer than two etymons.")
end
etymons_in_group = {}
end
local start_index = starts_with_lang_code and 2 or 1
for i = start_index, #args do
local param = args[i]
if type(param) ~= "string" then
elseif param:sub(1, 1) == ":" and not is_keyword(param) then
error("Invalid keyword '" .. param .. "'. Did you mean a valid keyword like ':bor', ':inh', etc.?")
elseif is_keyword(param) then
checkGroup()
current_keyword = get_canonical_keyword(get_keyword(param))
else
local etymon_data = EtymonParser.parse_etymon(param, lang)
if etymon_data then
table.insert(etymons_in_group, param)
local param_lang = etymon_data.lang
if etymon_data.is_family and current_keyword == "inherited" then
error("`:inh` does not support family codes; use a specific language.")
end
if etymon_data.is_family and not etymon_data.suppress_term then
error("Family codes require suppressed term (use family:-).")
end
if current_keyword == "from" and param_lang:getFullCode() ~= lang:getFullCode() then
error("`:from` is for same-language derivation, but language does not match. " ..
"Expected '" .. lang:getFullCode() .. "', got '" .. param_lang:getFullCode() .. "'.")
elseif current_keyword == "inherited" then
M.etymology.check_ancestor(lang, param_lang)
end
-- Check modifier restrictions
EtymonParser.check_modifier_restrictions(etymon_data, current_keyword, EtymonParser.etymon_param_mods)
-- postype must be "root" or "word"
local VALID_POSTYPES = { root = true, word = true }
if etymon_data.postype and not VALID_POSTYPES[etymon_data.postype] then
error("Invalid <postype:" .. etymon_data.postype .. ">; must be \"root\" or \"word\".")
end
if etymon_data.ety then
local inline_args = EtymonParser.parse_inline_ety(etymon_data.ety, etymon_data.lang)
EtymonParser.validate(etymon_data.lang, inline_args, nil, nil, nil, true)
end
else
table.insert(etymons_in_group, param)
end
end
end
checkGroup()
end
local DataRetriever = {}
-- Given an etymon data, scrape its page and cache the result in the global state object.
function DataRetriever.cache_page_etymons(etymon_page, etymon_title, key, etymon_lang, etymon_id, redirected_from, descendants_is_toplevel)
local content = etymon_title:getContent()
if not content then
__state.cached_etymon_args[key] = M.data.STATUS.REDLINK
return
end
-- Check if the linked page is a redirect. If it is, the template parsing
-- code below will be effectively skipped, and `scrape_page` will be called
-- again on the redirect target (see the bottom of this function)
local lang_section_for_descendants = nil
local redirect_target = etymon_title.redirect_target
if not redirect_target then
content = M.pages.get_section(content, etymon_lang:getFullName(), 2)
if not content then
__state.cached_etymon_args[key] = M.data.STATUS.MISSING
return
end
lang_section_for_descendants = content
end
local etymon_lang_code = etymon_lang:getFullCode()
local lang_page_key = etymon_lang_code .. ":" .. etymon_page
local found_templates_for_lang = {}
local found_ids = {}
local has_idless_etymon = false
local get_node_class = M.template_parser.class_else_type
-- Look for all {{etymon}} templates within the page content using the template parser
-- This way the same page is never parsed more than once
-- Build a map from senseids to their parent etymonids.
local active_etymon_args = nil
for node in M.template_parser.parse(content):iterate_nodes() do
local node_class = get_node_class(node)
if node_class == "heading" then
-- A new L2 or etymology section acts as a barrier: an {{etymon}} usage
-- used previously cannot be the parent of any subsequent senseids.
-- Note that we don't have to check for L2s due to the usage of `M.pages.get_section` above.
if node:get_name():find("^Etymology") then
active_etymon_args = nil
end
elseif node_class == "template" then
local template_name = node:get_name()
if template_name == "etymon" then
local template_args = node:get_arguments()
-- Check if this etymon is for our language
if template_args[1] == etymon_lang_code then
table.insert(found_templates_for_lang, template_args)
if template_args.id then
local etymon_key = lang_page_key .. ":" .. template_args.id
__state.cached_etymon_args[etymon_key] = template_args
__state.cached_etymon_pages[etymon_key] = tostring(etymon_page)
table.insert(found_ids, template_args.id)
active_etymon_args = template_args
else
has_idless_etymon = true
-- Store idless etymon with default key
local etymon_key = lang_page_key .. ":*"
__state.cached_etymon_args[etymon_key] = template_args
__state.cached_etymon_pages[etymon_key] = tostring(etymon_page)
table.insert(found_ids, "*")
active_etymon_args = template_args
end
end
elseif active_etymon_args and template_name == "senseid" then
local template_args = node:get_arguments()
-- This should always be true for proper usages of {{senseid}}.
if template_args[1] == etymon_lang_code and template_args[2] then
local sense_id_key = lang_page_key .. ":" .. template_args[2]
__state.senseid_parent_etymon[sense_id_key] = active_etymon_args
__state.cached_etymon_pages[sense_id_key] = tostring(etymon_page)
end
end
end
end
if descendants_is_toplevel and lang_section_for_descendants and #found_templates_for_lang > 0 then
M.descendants.cache_page_checks({
lang_section = lang_section_for_descendants,
etymon_lang_code = etymon_lang_code,
found_templates_for_lang = found_templates_for_lang,
entry_title = __state.entry_title,
entry_lang_code = __state.entry_lang_code,
entry_lang = __state.entry_lang_code and Util.get_lang(__state.entry_lang_code, true) or nil,
cached_descendants_checks = __state.cached_descendants_checks,
lang_page_key = lang_page_key,
redirected_from = redirected_from,
})
end
-- Error if multiple etymons exist and at least one is missing an id
if #found_templates_for_lang > 1 and has_idless_etymon then
error("Page '[[" .. tostring(etymon_page) .. "]]' has " .. #found_templates_for_lang ..
" etymon templates for " .. etymon_lang:getCanonicalName() ..
", but at least one is missing an id. All etymons must have unique IDs when there are multiple.")
end
local id_data_list = {}
for _, args in ipairs(found_templates_for_lang) do
local id = args.id or "*"
table.insert(id_data_list, { id = id, pos = args.pos })
end
__state.available_etymon_ids[lang_page_key] = id_data_list
if #found_templates_for_lang == 1 then
__state.single_etymons[lang_page_key] = found_templates_for_lang[1]
end
if redirected_from and __state.available_etymon_ids[lang_page_key] then
__state.available_etymon_ids[redirected_from] = __state.available_etymon_ids[redirected_from] or {}
for _, id_data in ipairs(__state.available_etymon_ids[lang_page_key]) do
table.insert(__state.available_etymon_ids[redirected_from], id_data)
end
end
if __state.cached_etymon_args[key] ~= nil or __state.senseid_parent_etymon[key] ~= nil then
-- All done!
return
elseif redirect_target and not redirected_from then
-- Try scraping the redirect.
etymon_page = redirect_target.prefixedText
DataRetriever.cache_page_etymons(etymon_page, redirect_target, lang_page_key .. ":" .. etymon_id, etymon_lang, etymon_id, lang_page_key, descendants_is_toplevel)
__state.cached_etymon_args[key] = __state.cached_etymon_args[etymon_lang_code .. ":" .. etymon_page .. ":" .. etymon_id]
else
__state.cached_etymon_args[key] = M.data.STATUS.MISSING
end
end
-- Given an etymon object, scrape its page (if necessary) and return its own etymon arguments as well as the page name.
function DataRetriever.get_etymon_args(etymon_data, is_toplevel)
local page = M.links.get_link_page(etymon_data.term, etymon_data.lang)
local norm_lang = Util.get_norm_lang(etymon_data.lang)
local base_key = norm_lang:getFullCode() .. ":" .. page
if etymon_data.id then
local key = base_key .. ":" .. etymon_data.id
local cached_args = __state.cached_etymon_args[key] or __state.senseid_parent_etymon[key]
if cached_args == nil then
local title = mw.title.new(page)
if not title then error('Invalid page title "' .. page .. '" encountered.') end
DataRetriever.cache_page_etymons(page, title, key, norm_lang, etymon_data.id, nil, is_toplevel)
end
cached_args = __state.cached_etymon_args[key] or __state.senseid_parent_etymon[key] -- refresh
-- Get etymon_id from parent if this was resolved via senseid
local parent_etymon = __state.senseid_parent_etymon[key]
local resolved_etymon_id = parent_etymon and parent_etymon.id
local descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = is_toplevel,
base_key = base_key,
lookup = {
explicit_id = etymon_data.id,
parent_etymon = parent_etymon,
},
})
if is_toplevel and descendants_check == nil then
local title = mw.title.new(page)
if title then
DataRetriever.cache_page_etymons(page, title, key, norm_lang, etymon_data.id, nil, true)
descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = true,
base_key = base_key,
lookup = {
explicit_id = etymon_data.id,
parent_etymon = parent_etymon,
},
})
end
end
return cached_args, __state.cached_etymon_pages[key], resolved_etymon_id, descendants_check
else
__state.used_idless_etymon = true
if is_toplevel then
__state.toplevel_idless_etymon = true
end
if __state.available_etymon_ids[base_key] == nil then
local title = mw.title.new(page)
if not title then error('Invalid page title "' .. page .. '" encountered.') end
DataRetriever.cache_page_etymons(page, title, base_key .. ":*", norm_lang, "*", nil, is_toplevel)
end
local ids = __state.available_etymon_ids[base_key] or {}
local count = #ids
-- Try to filter by postype if available and we have multiple candidates
if count > 1 and etymon_data.postype then
local matching_ids = {}
for _, id_data in ipairs(ids) do
if id_data.pos == etymon_data.postype then
table.insert(matching_ids, id_data)
end
end
if #matching_ids == 1 then
local matched_id = matching_ids[1].id
local matched_key = base_key .. ":" .. matched_id
local descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = is_toplevel,
base_key = base_key,
lookup = { id = matched_id },
})
if is_toplevel and descendants_check == nil then
local title = mw.title.new(page)
if title then
DataRetriever.cache_page_etymons(page, title, base_key .. ":*", norm_lang, "*", nil, true)
descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = true,
base_key = base_key,
lookup = { id = matched_id },
})
end
end
return __state.cached_etymon_args[matched_key], __state.cached_etymon_pages[matched_key], nil, descendants_check
end
end
if count == 1 then
local only_id_data = ids[1]
local only_id = (type(only_id_data) == "table" and only_id_data.id) or only_id_data or "*"
local descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = is_toplevel,
base_key = base_key,
lookup = { id_data = only_id_data },
})
if is_toplevel and descendants_check == nil then
local title = mw.title.new(page)
if title then
DataRetriever.cache_page_etymons(page, title, base_key .. ":*", norm_lang, "*", nil, true)
descendants_check = M.descendants.get_lookup_check({
cached_descendants_checks = __state.cached_descendants_checks,
is_toplevel = true,
base_key = base_key,
lookup = { id_data = only_id_data },
})
end
end
return __state.single_etymons[base_key], __state.cached_etymon_pages[base_key .. ":" .. only_id], nil, descendants_check
elseif count > 1 then
local id_list = {}
for _, id_data in ipairs(ids) do
local id = type(id_data) == "table" and id_data.id or id_data
if id and id ~= "" then
table.insert(id_list, "\"" .. id .. "\"")
end
end
local suggestion_text = ""
if #id_list > 0 then
suggestion_text = " Available IDs: " .. table.concat(id_list, ", ") .. "."
end
Util.add_warning("Etymology link to '[[" .. page .. "]]' is ambiguous. The page has " ..
count .. " etymon templates for " .. norm_lang:getCanonicalName() ..
". Please specify an ID." .. suggestion_text, true)
return M.data.STATUS.AMBIGUOUS, nil, nil, nil
else
return M.data.STATUS.MISSING, nil, nil, nil
end
end
end
local TreeBuilder = {}
local function parse_etymon_references(refs_text)
if not refs_text or refs_text == "" then
return ""
end
return M.references.parse_references(refs_text)
end
local function parse_tree_references(node)
if node.ref then
node.parsed_ref = parse_etymon_references(node.ref)
end
if node.children then
for _, container in ipairs(node.children) do
if container.terms then
for _, term in ipairs(container.terms) do
parse_tree_references(term)
end
end
end
end
end
-- Build a unique key for deduplication in the seen table
function TreeBuilder.build_key(lang, title, args)
local norm_lang_code = Util.get_norm_lang(lang):getFullCode()
local is_table = type(args) == "table"
local id = (is_table and args.id) or ""
if title then
return norm_lang_code .. ":" .. M.links.get_link_page(title, lang) .. ":" .. id
end
if is_table and args.status == M.data.STATUS.INLINE then
local content_parts = {}
for i = 1, #args do
content_parts[i] = tostring(args[i])
end
return norm_lang_code .. ":*:" .. id .. "\0" .. table.concat(content_parts, "\0")
end
return norm_lang_code .. ":*:" .. id
end
function TreeBuilder.build(lang, title, args, seen, depth, stop_recursion)
seen = seen or {}
depth = depth or 0
local is_toplevel = (depth == 0)
if depth > __state.max_depth_reached then
__state.max_depth_reached = depth
end
__state.total_nodes = __state.total_nodes + 1
local lang_code = lang:getCode()
__state.language_count[lang_code] = (__state.language_count[lang_code] or 0) + 1
local current_id = (type(args) == "table" and args.id) or ""
local key = TreeBuilder.build_key(lang, title, args)
local node = { lang = lang, title = title, id = current_id, args = args, children = {}, status = M.data.STATUS.OK }
if type(args) ~= "table" or seen[key] then
node.status = args or M.data.STATUS.MISSING
-- Mark as duplicate if we've seen this node before
if seen[key] then
node.is_duplicate = true
node.duplicate_key = key
local original_node = seen[key]
if type(original_node) == "table" and original_node.children and #original_node.children > 0 then
node.original_has_children = true
end
end
return node
end
node.status = args.status or M.data.STATUS.OK
seen[key] = node
-- If stop_recursion is set, skip parsing children but check for visible children
if stop_recursion then
local keywords = M.data.keywords
local has_visible_children = false
for i = 2, #args do
local param = args[i]
if type(param) == "string" then
local keyword_base = get_keyword_base(param)
if keyword_base and keywords[keyword_base] then
-- It's a keyword, check if visible in tree (invisible "all" or "tree" = hidden in tree)
local keyword_info = keywords[keyword_base]
local inv = keyword_info.invisible
if not (inv == "all" or inv == true or inv == "tree") then
has_visible_children = true
break
end
elseif param:sub(1, 1) ~= ":" then
-- It's a term (not a keyword), so there are visible children
has_visible_children = true
break
end
end
end
node.has_visible_children = has_visible_children
return node
end
-- Parse args into keyword containers
local current_keyword = "from"
local current_keyword_modifiers = {}
local current_container = nil
-- Helper to track keyword usage at top level
local function track_keyword_usage(keyword, target_lang, source_lang)
if not is_toplevel then return end
if not __state.toplevel_keyword_stats[keyword] then
__state.toplevel_keyword_stats[keyword] = {
count = 0,
target_langs = {},
source_langs = {},
}
end
local keyword_data = __state.toplevel_keyword_stats[keyword]
keyword_data.count = keyword_data.count + 1
local target_code = target_lang:getCode()
keyword_data.target_langs[target_code] = (keyword_data.target_langs[target_code] or 0) + 1
if source_lang then
local source_code = source_lang:getCode()
keyword_data.source_langs[source_code] = (keyword_data.source_langs[source_code] or 0) + 1
end
end
local function ensure_container()
if not current_container or current_container.keyword ~= current_keyword then
current_container = {
keyword = current_keyword,
keyword_info = M.data.keywords[current_keyword],
keyword_modifiers = current_keyword_modifiers,
terms = {},
}
table.insert(node.children, current_container)
-- Override keyword text/phrase for nominalization with <g:code>
if current_keyword_modifiers.g and current_keyword == "nominalization" then
local labels = get_nominalization_label_for_g(current_keyword_modifiers.g)
if not labels then
local codes = {}
for c in pairs(M.data.nominalization_g_codes) do table.insert(codes, c) end
table.sort(codes)
error("Invalid <g:" .. tostring(current_keyword_modifiers.g) .. ">. Supported codes for nominalization: " .. table.concat(codes, ", "))
end
current_container.keyword_info = {}
for k, v in pairs(M.data.keywords[current_keyword]) do current_container.keyword_info[k] = v end
current_container.keyword_info.text = labels.text
current_container.keyword_info.phrase = labels.phrase
end
end
end
for i = 2, #args do
local param = args[i]
if is_keyword(param) then
local keyword, modifiers = EtymonParser.parse_keyword_modifiers(param)
current_keyword = keyword
current_keyword_modifiers = modifiers
current_container = nil -- Force new container for new keyword
elseif type(param) == "string" and param:sub(1, 1) == ":" then
error("Invalid keyword '" .. param .. "'. Did you mean a valid keyword like ':bor', ':inh', etc.?")
elseif type(param) == "string" then
local etymon_data = EtymonParser.parse_etymon(param, lang)
if etymon_data then
-- Track keyword usage at top level
track_keyword_usage(current_keyword, lang, etymon_data.lang)
local term_node = {}
-- Handle suppress_term (-) and unknown_term (empty) directly
if etymon_data.suppress_term or etymon_data.unknown_term then
ensure_container()
if etymon_data.ety then
local inline_args = EtymonParser.parse_inline_ety(etymon_data.ety, etymon_data.lang)
inline_args.id = etymon_data.id
inline_args.status = M.data.STATUS.INLINE
term_node = TreeBuilder.build(etymon_data.lang, nil, inline_args, seen, depth + 1)
else
term_node = {
lang = etymon_data.lang,
children = {},
status = M.data.STATUS.OK,
}
end
term_node.suppress_term = etymon_data.suppress_term
term_node.unknown_term = etymon_data.unknown_term
term_node.is_family = etymon_data.is_family
term_node.is_uncertain = etymon_data.unc
term_node.ref = etymon_data.ref
term_node.t = etymon_data.t
term_node.tr = etymon_data.tr
term_node.ts = etymon_data.ts
term_node.alt = etymon_data.alt
term_node.pos = etymon_data.pos
term_node.lit = etymon_data.lit
term_node.q = etymon_data.q
term_node.qq = etymon_data.qq
term_node.l = etymon_data.l
term_node.ll = etymon_data.ll
else
-- Regular term: fetch arguments from page
local etymon_args, page_of, resolved_etymon_id, descendants_check = DataRetriever.get_etymon_args(etymon_data, is_toplevel)
if etymon_data.id and etymon_args == M.data.STATUS.MISSING and not etymon_data.ety then
local page = M.links.get_link_page(etymon_data.term, etymon_data.lang)
local norm_lang = Util.get_norm_lang(etymon_data.lang)
local base_key = norm_lang:getFullCode() .. ":" .. page
local available_ids = __state.available_etymon_ids[base_key] or {}
if #available_ids > 0 then
__state.has_mismatched_id = true
end
end
-- Check for <ety> inline parameter doesn't override the scraped arguments, unless the latter are missing
if etymon_data.ety then
if etymon_args == M.data.STATUS.REDLINK or etymon_args == M.data.STATUS.MISSING then
__state.current_page_has_inline_etymology = true
if is_toplevel then
__state.toplevel_has_inline_etymology = true
end
local inline_args = EtymonParser.parse_inline_ety(etymon_data.ety, etymon_data.lang)
-- Track inline ety keywords too
local inline_keyword = get_keyword(inline_args[2], true)
if inline_keyword and #inline_args >= 3 then
local inline_etymon = EtymonParser.parse_etymon(inline_args[3], etymon_data.lang)
if inline_etymon then
track_keyword_usage(inline_keyword, etymon_data.lang, inline_etymon.lang)
end
end
inline_args.id = etymon_data.id
inline_args.status = M.data.STATUS.INLINE
etymon_args = inline_args
term_node.page_of = __state.cached_etymon_pages[key] -- term node is on the same page as the parent
else
-- Scraped arguments exist, <ety> is redundant and ignored
__state.current_page_has_redundant_etymology = true
if is_toplevel then
__state.toplevel_redundant_etymology = true
end
end
end
-- Ensure container exists before checking keyword info
ensure_container()
-- Check if current keyword has no_child_categories - if so, stop recursion
local keyword_info = current_container.keyword_info
local should_stop_recursion = (stop_recursion or (keyword_info and keyword_info.no_child_categories))
term_node = TreeBuilder.build(etymon_data.lang, etymon_data.term, etymon_args, seen, depth + 1, should_stop_recursion)
term_node.target_key = Util.get_norm_lang(etymon_data.lang):getFullCode() ..
":" .. M.links.get_link_page(etymon_data.term, etymon_data.lang)
term_node.id = etymon_data.id
term_node.etymon_id = resolved_etymon_id -- The actual etymon id when resolved via senseid
term_node.t = etymon_data.t
term_node.tr = etymon_data.tr
term_node.ts = etymon_data.ts
term_node.pos = etymon_data.pos
term_node.alt = etymon_data.alt
term_node.ref = etymon_data.ref
term_node.is_uncertain = etymon_data.unc
term_node.override = etymon_data.override
term_node.page_of = page_of
term_node.aftype = etymon_data.aftype
term_node.postype = etymon_data.postype
term_node.bor = etymon_data.bor
term_node.lbor = etymon_data.lbor
term_node.slbor = etymon_data.slbor
term_node.lit = etymon_data.lit
term_node.is_family = etymon_data.is_family
term_node.q = etymon_data.q
term_node.qq = etymon_data.qq
term_node.l = etymon_data.l
term_node.ll = etymon_data.ll
term_node.missing_descendants_header, term_node.missing_descendants_entry =
M.descendants.get_term_sync_flags(current_keyword, term_node.status, descendants_check)
end
table.insert(current_container.terms, term_node)
end
end
end
return node
end
-- Convert etymology tree to JSON-serializable table
local function tree_to_json(node)
local obj = {
term = node.title,
lang = node.lang:getCode(),
lang_name = node.lang:getCanonicalName(),
id = (node.id and node.id ~= "") and node.id or nil,
status = node.status,
is_uncertain = node.is_uncertain or nil,
is_duplicate = node.is_duplicate or nil,
gloss = node.t,
transliteration = node.tr,
transcription = node.ts,
alt = node.alt,
pos = node.pos,
children = {},
}
for _, container in ipairs(node.children or {}) do
local keyword_info = container.keyword_info
if keyword_info then
local container_obj = {
keyword = container.keyword,
keyword_label = keyword_info.text,
keyword_abbrev = keyword_info.abbrev,
is_group = keyword_info.is_group or nil,
is_invisible = keyword_info.invisible or nil,
is_uncertain = (container.keyword_modifiers and container.keyword_modifiers.unc) or nil,
terms = {},
}
for _, term in ipairs(container.terms or {}) do
table.insert(container_obj.terms, tree_to_json(term))
end
table.insert(obj.children, container_obj)
end
end
return obj
end
local function track_ranges(base_key, value, ranges, lang_code)
M.track("etymon/" .. base_key .. "/" .. value)
if lang_code then
M.track("etymon/lang/" .. lang_code .. "/" .. base_key .. "/" .. value)
end
for _, range in ipairs(ranges) do
local matches = false
if range.min and range.max then
matches = value >= range.min and value <= range.max
elseif range.min then
matches = value >= range.min
elseif range.max then
matches = value <= range.max
elseif range.exact then
matches = value == range.exact
end
if matches then
M.track("etymon/" .. base_key .. "/" .. range.label)
if lang_code then
M.track("etymon/lang/" .. lang_code .. "/" .. base_key .. "/" .. range.label)
end
break
end
end
end
-- Build and return the etymology data tree for a given term.
function export.get_tree(lang, title, args, options)
options = options or {}
__state.entry_title = title
__state.entry_lang_code = lang:getCode()
if options.validate then
EtymonParser.validate(lang, args, options.id, title, options.pos, false)
end
local lang_code = lang:getCode()
local start_index = (args[1] == lang_code) and 2 or 1
local tree_args = { [1] = lang_code, id = options.id or args.id }
for i = start_index, #args do
table.insert(tree_args, args[i])
end
__state.cached_etymon_args[lang_code .. ":" .. title .. ":" .. (tree_args.id or "")] = tree_args
local ety_data_tree = TreeBuilder.build(lang, title, tree_args)
parse_tree_references(ety_data_tree)
if options.json then
return M.JSON.toJSON(tree_to_json(ety_data_tree))
end
return ety_data_tree
end
-- Given a language code, page name and optionally the id= parameter,
-- render the tree and only the etymology tree for the relevant page.
-- Fetches and parses the corresponding {{etymon}} from the requested page,
-- and any further pages needed to render the tree.
-- Parameters can be passed either through the #invoke or as
-- template parameters *through* an #invoke.
function export.render_tree_for_etymon_on_page(frame)
local frame_args = frame.args
local parent_args = frame:getParent().args
local langcode = frame_args[1] or parent_args[1]
local pagename = frame_args[2] or parent_args[2]
local id = frame_args["id"] or parent_args["id"]
local display_title = frame_args["title"] or parent_args["title"]
local parsed_title = mw.title.new(pagename, 0)
local title
if parsed_title.namespace == 0 then
title = M.pages.safe_page_name(parsed_title)
elseif parsed_title.namespace == 118 then
title = "*" .. M.pages.safe_page_name(parsed_title)
else
error("Unsupported namespace for render_tree_for_etymon_on_page: " .. parsed_title.namespace)
end
local lang = Util.get_lang(langcode)
-- Construct etymon_data for DataRetriever.get_args.
local etymon_data = {
lang = lang,
term = title,
id = id
}
local args, pagename = DataRetriever.get_etymon_args(etymon_data, true)
if args == M.data.STATUS.MISSING then
error("The etymon template was not found (language " ..
langcode ..
", title '" ..
title ..
"'" ..
(id and ", ID '" .. id .. "'" or ", no ID given") .. "). Page contents may have changed in the interim.")
end
local ety_data_tree = export.get_tree(lang, display_title or title, args, {
validate = true,
id = id,
})
local output = {}
table.insert(output, M.template_styles("Module:etymon/styles.css"))
table.insert(output, M.tree.render({
data_tree = ety_data_tree,
format_term_func = function(term, is_toplevel)
return Util.format_term(term, is_toplevel, {
gloss = "suppress",
pos = "suppress",
lit = "suppress",
tree_ql = "suppress",
})
end,
}))
return table.concat(output)
end
function export.main(frame)
local parent_args = frame:getParent().args
local args = M.parameters.process(parent_args, M.parameters_data.etymon)
local lang = args[1]
local etymon_args = args[2]
local id = args.id
local title = args.title
local text = args.text
local tree = args.tree
local etydate = args.etydate
local rfe = args.rfe
local page_data = Util.get_page_data()
if not title then
title = page_data.pagename
if page_data.namespace == "Từ tái tạo" then title = "*" .. title end
end
local current_L2 = M.pages.get_current_L2()
if current_L2 then
local norm_lang = Util.get_norm_lang(lang)
local norm_name = ucfirst(norm_lang:getCanonicalName())
if current_L2 ~= norm_name then
local lang_desc = lang:getCode() .. " (" .. lang:getCanonicalName() .. ")"
if norm_lang:getCode() ~= lang:getCode() then
lang_desc = lang_desc .. ", normalized to " .. norm_lang:getCode() .. " (" .. norm_name .. ")"
end
error("Ngôn ngữ '" .. lang_desc .. "' không khớp với đầu mục L2 (" .. current_L2 .. ").")
end
end
local ety_data_tree = export.get_tree(lang, title, etymon_args, {
validate = true,
pos = args.pos,
id = id,
json = args.json,
})
if args.json then
return ety_data_tree
end
local output = {}
local text_allowlist_mode = M.text_allowed.default_mode or "off"
if text and text_allowlist_mode ~= "off" and not Util.is_text_param_allowed_for_lang(lang) then
local msg = "Etymology texts (parameter <code>text=</code>) are not allowed for " .. lang:getFullName() ..
"; see [[Template:etymon#Text allowlist|Template:etymon § Text allowlist]] for the list of languages that may use the <code>text=</code> parameter."
if text_allowlist_mode == "error" then
error(msg)
else
Util.add_warning(msg, true)
end
end
local lang_exc = Util.get_lang_exception(lang)
if lang_exc and lang_exc.disallow then
local disallow = lang_exc.disallow
local error_text = " for " .. lang:getFullName()
if disallow.ref then
error_text = error_text .. "; see " .. disallow.ref
else
error_text = error_text .. "."
end
if tree and disallow.tree then
error("Etymology trees are not allowed" .. error_text)
end
if text and disallow.text then
error("Etymology texts are not allowed" .. error_text)
end
end
if etydate then
local etydate_param_mods = {
ref = { list = true, type = "references", allow_holes = true },
refn = { list = true, allow_holes = true },
nocap = { type = "boolean" },
}
local function generate_etydate_obj(etydate_text)
local etydate_specs = {}
for spec in etydate_text:gmatch("[^,]+") do
table.insert(etydate_specs, mw.text.trim(spec))
end
return { [1] = etydate_specs }
end
local parsed_etydate = M.parse_utilities.parse_inline_modifiers(etydate, { param_mods = etydate_param_mods, generate_obj = generate_etydate_obj })
local etydate_args = {
[1] = parsed_etydate[1],
nocap = parsed_etydate.nocap or false,
ref = parsed_etydate.ref or {},
refn = parsed_etydate.refn or { maxindex = 0 }
}
if etydate_args.refn then
local max = 0
for k, v in pairs(etydate_args.refn) do
if type(k) == "number" and k > max then
max = k
end
end
etydate_args.refn.maxindex = max
end
ety_data_tree.etydate = M.etydate.format_etydate(etydate_args)
-- Parse and store references separately for text rendering
local refs_text = ""
for _, ref in ipairs(etydate_args.ref) do
refs_text = refs_text .. (refs_text ~= "" and "" or "") .. ref
end
if refs_text ~= "" then
ety_data_tree.etydate_refs = M.references.parse_references(refs_text)
end
end
if tree then
table.insert(output, M.template_styles("Module:etymon/styles.css"))
table.insert(output, M.tree.render({
data_tree = ety_data_tree,
format_term_func = function(term, is_toplevel)
return Util.format_term(term, is_toplevel, {
gloss = "suppress",
pos = "suppress",
lit = "suppress",
tree_ql = "suppress",
})
end,
}))
end
-- Check if there are any visible children in tree (invisible "all" or "tree" = hidden in tree)
local has_visible_children = false
for _, child in ipairs(ety_data_tree.children or {}) do
local child_keyword_info = child.keyword_info
local inv = child_keyword_info and child_keyword_info.invisible
if not (inv == "all" or inv == true or inv == "tree") then
has_visible_children = true
break
end
end
local tree_disallowed = lang_exc and lang_exc.disallow and lang_exc.disallow.tree
local anchor = M.anchors.etymonid(lang, id, {
no_tree = args.notree,
title = title,
empty_tree = (not has_visible_children) or tree_disallowed
})
table.insert(output, anchor)
if text then
local max_depth, stop_at_blue_link, stop_at_lang, stop_at_lang_or_bluelink
if text == "++" then
max_depth, stop_at_blue_link = false, false
elseif text == "+" then
max_depth, stop_at_blue_link = 1, false
elseif text == "*" then
max_depth, stop_at_blue_link = false, true
elseif text:match("^:[^*]+%*$") then
-- Stop at a specific language OR first bluelink after it, e.g., ":ota*"
-- If the target language is a redlink, continue to the first bluelink
local lang_code = text:match("^:([^*]+)%*$")
if lang_code and lang_code ~= "" then
local lang_obj = Util.get_lang(lang_code, true)
if lang_obj then
stop_at_lang_or_bluelink = lang_code
else
Util.add_warning('Invalid language code "' .. lang_code .. '" in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false
end
else
Util.add_warning('Empty language code in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false
end
elseif text:sub(1, 1) == ":" then
-- Stop at a specific language, e.g., ":ar" stops at first Arabic term
local lang_code = text:sub(2)
if lang_code ~= "" then
-- Validate the language code
local lang_obj = Util.get_lang(lang_code, true)
if lang_obj then
stop_at_lang = lang_code
else
Util.add_warning('Invalid language code "' .. lang_code .. '" in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false -- default to ++
end
else
Util.add_warning('Empty language code in text parameter. Showing full chain instead.')
max_depth, stop_at_blue_link = false, false -- default to ++
end
else
local num = tonumber(text)
if num and num >= 1 then
max_depth, stop_at_blue_link = num, false
else
error('Invalid text value "' ..
text .. '". Valid values are: "++" (full chain), "+" (first step only), "*" (until first blue link), a number (max steps), ":lang" (stop at language), or ":lang*" (stop at language or first bluelink if redlink)')
end
end
table.insert(output, M.text.render({
data_tree = ety_data_tree,
format_term_func = Util.format_term,
max_depth = max_depth,
stop_at_blue_link = stop_at_blue_link,
curr_page = page_data.pagename,
nodot = args.nodot,
stop_at_lang = stop_at_lang,
stop_at_lang_or_bluelink = stop_at_lang_or_bluelink,
}))
end
if rfe then
local rfe_param_mods = {
nocat = { type = "boolean" },
sort = {},
y = {},
m = {},
fragment = {},
section = {},
box = { type = "boolean" },
noes = { type = "boolean" },
}
local function generate_rfe_obj(rfe_text)
-- Check if it's a boolean true value
if M.yesno(rfe_text, false) then
return { is_boolean = true }
else
return { text = rfe_text }
end
end
local rfe_with_defaults = Util.add_boolean_defaults(rfe, rfe_param_mods)
local parsed_rfe = M.parse_utilities.parse_inline_modifiers(rfe_with_defaults, {
param_mods = rfe_param_mods,
generate_obj = generate_rfe_obj
})
local rfe_args = {
[1] = lang:getCode(),
nocat = parsed_rfe.nocat,
sort = parsed_rfe.sort,
y = parsed_rfe.y,
m = parsed_rfe.m,
fragment = parsed_rfe.fragment,
section = parsed_rfe.section,
box = parsed_rfe.box,
noes = parsed_rfe.noes,
}
if not parsed_rfe.is_boolean then
rfe_args[2] = parsed_rfe.text
end
table.insert(output, frame:expandTemplate({
title = "rfe",
args = rfe_args
}))
end
if Util.is_content_page() and __state.max_depth_reached > 0 then
local lang_code = lang:getCode()
local depth_ranges = {
{ min = 50, label = "extremely-deep" },
{ min = 20, label = "20+" },
{ min = 10, max = 19, label = "10-19" },
{ min = 5, max = 9, label = "5-9" },
{ min = 3, max = 4, label = "3-4" },
{ max = 2, label = "1-2" }
}
local node_ranges = {
{ min = 100, label = "extremely-large" },
{ min = 50, label = "50+" },
{ min = 20, max = 49, label = "20-49" },
{ min = 10, max = 19, label = "10-19" },
{ min = 5, max = 9, label = "5-9" },
{ max = 4, label = "1-4" }
}
local language_ranges = {
{ min = 10, label = "10+" },
{ min = 5, max = 9, label = "5-9" },
{ min = 3, max = 4, label = "3-4" },
{ exact = 2, label = "2" },
{ exact = 1, label = "1" }
}
track_ranges("depth", __state.max_depth_reached, depth_ranges, lang_code)
track_ranges("nodes", __state.total_nodes, node_ranges, lang_code)
local unique_languages = 0
for _ in pairs(__state.language_count) do
unique_languages = unique_languages + 1
end
track_ranges("unique-languages", unique_languages, language_ranges, lang_code)
if __state.total_nodes == __state.max_depth_reached + 1 then
track_ranges("linear-depth", __state.max_depth_reached, depth_ranges, lang_code)
end
end
local categories = {}
if Util.is_content_page() then
local should_suppress_categories = lang_exc and lang_exc.suppress_categories
if not should_suppress_categories and not args.nocat then
categories = M.categories.render({
data_tree = ety_data_tree,
page_lang = lang,
available_etymon_ids = __state.available_etymon_ids,
senseid_parent_etymon = __state.senseid_parent_etymon,
get_norm_lang_func = Util.get_norm_lang,
lang_exc = lang_exc,
})
end
local target_lang_code = lang:getCode()
for keyword, keyword_data in pairs(__state.toplevel_keyword_stats) do
-- Track keyword globally
M.track("etymon/keyword/" .. keyword)
-- Track keyword per target language
M.track("etymon/keyword/" .. keyword .. "/target/" .. target_lang_code)
-- Track keyword per source language
for source_code, count in pairs(keyword_data.source_langs) do
M.track("etymon/keyword/" .. keyword .. "/source/" .. source_code)
-- Track keyword per target+source combination
M.track("etymon/keyword/" .. keyword .. "/target/" .. target_lang_code .. "/source/" .. source_code)
end
end
if tree then
table.insert(categories, "Trang có cây từ nguyên")
table.insert(categories, "Mục từ có cây từ nguyên " .. lang:getCanonicalName())
end
if text then table.insert(categories, "Mục từ có văn bản giải thích từ nguyên " .. lang:getCanonicalName()) end
if args.exnihilo then table.insert(categories, lang:getCanonicalName() .. " terms coined ex nihilo") end
if __state.toplevel_has_inline_etymology then
table.insert(categories, "Pages with inline etymon for redlinks")
end
if __state.toplevel_redundant_etymology then
table.insert(categories, "Pages with redundant inline etymon")
end
if __state.toplevel_idless_etymon then
table.insert(categories, "Trang có nguyên từ thiếu ID")
end
if __state.has_mismatched_id then
table.insert(categories, lang:getCanonicalName() .. " entries referencing etymons with mismatched IDs")
end
end
if #categories > 0 then
table.insert(output, M.utilities.format_categories(categories, lang))
end
if __state.warnings then
for _, warning in ipairs(__state.warnings) do
table.insert(output, "\n" .. warning)
end
end
return table.concat(output)
end
return export
dt4d8dgp6y6mfgvdwa78t9i2h34mum0
0
332695
2344298
2217736
2026-04-11T17:12:39Z
WhoAlone
40420
/* Tham khảo */
2344298
wikitext
text/x-wiki
=={{langname|aav-bhu}}==
==={{ĐM|noun}}===
{{head|aav-bhu|Danh từ|tr=kanči}}
# [[rổ]].
==={{ĐM|ref}}===
* N. Ramaswamy (1992). ''Bhumij Grammar''.
{{C|aav-bhu|Dụng cụ}}
lgsz0dm3u8q6fj153to0kk06bj9qrh6
Bản mẫu:R:blt:TĐTV
10
339078
2344374
2228345
2026-04-12T04:17:50Z
Higashizakura
36666
2344374
wikitext
text/x-wiki
{{Chú thích sách
|author1=Hoàng Trần Nghịch
|author2=Tòng Kim Ân
|title=Từ điển Thái - Việt
|url=https://nguyenvietkhoi.github.io/SinicIME/TayDamDict
|year=1991
|publisher=Nhà xuất bản Khoa học xã hội
|location=Hà Nội}}
<noinclude>{{tài liệu}}{{tcat}}</noinclude>
8fjx157jodfy0j4dg5ln40fu4xa3f14
Mô đun:etymon/data
828
378443
2344311
2317908
2026-04-12T01:20:16Z
TheHighFighter2
42988
2344311
Scribunto
text/plain
local export = {}
export.STATUS = {
OK = "ok",
INLINE = "inline",
MISSING = "missing",
REDLINK = "redlink",
AMBIGUOUS = "ambiguous",
}
export.TRANSITIVE = {
ALWAYS = "always", -- always recurse into children
NEVER = "never", -- never recurse into children
CROSS_LANG = "cross_lang", -- only recurse when source lang differs from target lang (but pos chain continues)
CROSS_LANG_NO_INTERNAL_SOURCE = "cross_lang_no_internal_source", -- like CROSS_LANG, but source breaks for internal derivations in the same language context
}
-- Deep merge tables (nested tables are merged recursively, later values override earlier)
local function deep_merge(...)
local result = {}
for _, t in ipairs({ ... }) do
for k, v in pairs(t) do
if type(v) == "table" and type(result[k]) == "table" then
result[k] = deep_merge(result[k], v)
else
result[k] = v
end
end
end
return result
end
local function make_glossary_link(term, display_text)
if not term then return display_text end
return "[[Phụ lục:Từ điển thuật ngữ#" .. term:gsub(" ", "_") .. "|" .. display_text .. "]]"
end
-- Extract base word and connector from text like "Borrowed from" or "calque of"
local function split_glossary_text(text)
for _, pattern in ipairs({ "^(.-)(%s+[Oo][Ff])$", "^(.-)(%s+[Ff][Rr][Oo][Mm])$" }) do
local base, rest = text:match(pattern)
if base then return base, rest end
end
return text, ""
end
local TRANSITIVE = export.TRANSITIVE
local function create_keyword(opts)
local entry = {
is_group = opts.is_group or false,
abbrev = opts.abbrev,
glossary = opts.glossary,
transitive = opts.transitive or TRANSITIVE.ALWAYS, -- default "always"
inherited_chain = opts.inherited_chain or false,
affix_categories = opts.affix_categories or false,
borrowing_type = opts.borrowing_type,
specialized_borrowing = opts.specialized_borrowing,
toplevel_category = opts.toplevel_category,
no_child_categories = opts.no_child_categories or false,
source_category_type = opts.source_category_type,
invisible = (opts.invisible == true and "all") or opts.invisible or false,
pos_override = opts.pos_override,
new_sentence = opts.new_sentence or false,
separate_clause = opts.separate_clause or false,
aliases = opts.aliases,
}
-- Only set text/phrase when visible in text (invisible ~= "all" and ~= "text")
local inv = entry.invisible
if inv ~= "all" and inv ~= "text" then
entry.phrase = opts.phrase
if opts.text then
if opts.glossary then
local base_word, rest = split_glossary_text(opts.text)
entry.text = make_glossary_link(opts.glossary, base_word) .. rest
else
entry.text = opts.text
end
end
end
return entry
end
-- Shared defaults for keyword groups
local DEFAULTS = {
-- Keywords that pass through inheritance chain
inheritance = {
transitive = TRANSITIVE.ALWAYS,
inherited_chain = true,
},
-- Standard transitive derivation
transitive = {
transitive = TRANSITIVE.ALWAYS,
},
-- Standard for internal derivations: transitive across languages, but not within them
internal_derivation = {
transitive = TRANSITIVE.CROSS_LANG,
},
-- Borrowing keywords
borrowing = {
transitive = TRANSITIVE.ALWAYS,
},
-- Affix group keywords (compound words, blends, etc.)
affix_group = {
is_group = true,
transitive = TRANSITIVE.CROSS_LANG,
affix_categories = true,
},
-- Calque-like keywords (calque, partial calque, semantic loan)
calque_like = {
transitive = TRANSITIVE.NEVER,
no_child_categories = true,
new_sentence = true,
},
-- Non-transitive influence
influence_like = {
transitive = TRANSITIVE.NEVER,
no_child_categories = true,
},
}
export.keywords = {
--
-- Inheritance keywords
--
["from"] = create_keyword(deep_merge(DEFAULTS.inheritance, {
text = "From", phrase = "from",
})),
["inherited"] = create_keyword(deep_merge(DEFAULTS.inheritance, {
text = "Inherited from",
phrase = "from",
glossary = "inherited",
aliases = { "inh" },
})),
--
-- Basic derivation keywords
--
["uder"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "From",
phrase = "from",
toplevel_category = "undefined derivations",
})),
["derived"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Derived from",
phrase = "from",
abbrev = "der.",
glossary = "derived terms",
aliases = { "der" },
})),
--
-- Affix/compound group keywords
--
["affix"] = create_keyword(deep_merge(DEFAULTS.affix_group, {
text = "From",
phrase = "from",
aliases = { "af" },
})),
["surf"] = create_keyword(deep_merge(DEFAULTS.affix_group, {
text = "By surface analysis,",
phrase = "by surface analysis,",
abbrev = "surf.",
glossary = "surface analysis",
new_sentence = true,
invisible = "tree",
})),
["blend"] = create_keyword(deep_merge(DEFAULTS.affix_group, {
text = "Blend of",
phrase = "a blend of",
abbrev = "blend",
glossary = "blend",
toplevel_category = "blends",
})),
["univerbation"] = create_keyword(deep_merge(DEFAULTS.affix_group, {
text = "Univerbation of",
phrase = "univerbation of",
abbrev = "univ.",
glossary = "univerbation",
toplevel_category = "univerbations",
aliases = { "univ" },
})),
--
-- Borrowing keywords
--
["bor"] = create_keyword(deep_merge(DEFAULTS.borrowing, {
text = "Borrowed from",
phrase = "borrowed from",
abbrev = "bor.",
glossary = "loanword",
borrowing_type = "borrowed",
aliases = { "borrowed" },
})),
["lbor"] = create_keyword(deep_merge(DEFAULTS.borrowing, {
text = "Learned borrowing from",
phrase = "a learned borrowing from",
abbrev = "lbor.",
glossary = "learned borrowing",
specialized_borrowing = "learned",
})),
["obor"] = create_keyword(deep_merge(DEFAULTS.borrowing, {
text = "Orthographic borrowing from",
phrase = "an orthographic borrowing from",
abbrev = "obor.",
glossary = "orthographic borrowing",
specialized_borrowing = "orthographic",
})),
["slbor"] = create_keyword(deep_merge(DEFAULTS.borrowing, {
text = "Semi-learned borrowing from",
phrase = "a semi-learned borrowing from",
abbrev = "slbor.",
glossary = "semi-learned borrowing",
specialized_borrowing = "semi-learned",
})),
["ubor"] = create_keyword(deep_merge(DEFAULTS.borrowing, {
text = "Unadapted borrowing from",
phrase = "an unadapted borrowing from",
abbrev = "ubor.",
glossary = "unadapted borrowing",
specialized_borrowing = "unadapted",
})),
--
-- Calque-like keywords (non-transitive, start new sentence)
--
["calque"] = create_keyword(deep_merge(DEFAULTS.calque_like, {
text = "Calque of",
phrase = "a calque of",
abbrev = "calq.",
glossary = "calque",
specialized_borrowing = "calque",
aliases = { "cal", "clq" },
})),
["partial calque"] = create_keyword(deep_merge(DEFAULTS.calque_like, {
text = "Partial calque of",
phrase = "a partial calque of",
abbrev = "pcalq.",
glossary = "partial calque",
specialized_borrowing = "partial-calque",
aliases = { "pcal" },
})),
["semantic loan"] = create_keyword(deep_merge(DEFAULTS.calque_like, {
text = "Semantic loan of",
phrase = "a semantic loan of",
abbrev = "sl.",
glossary = "semantic loan",
specialized_borrowing = "semantic-loan",
aliases = { "sl" },
})),
--
-- Influence keywords (non-transitive, separate clause)
--
["influence"] = create_keyword(deep_merge(DEFAULTS.influence_like, {
text = "Influenced by",
phrase = "influenced by",
abbrev = "influ.",
glossary = "contamination",
separate_clause = true,
})),
--
-- Morphological derivation keywords
--
["clipping"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Clipping of",
phrase = "clipping of",
abbrev = "clip.",
glossary = "clipping",
toplevel_category = "clippings",
aliases = { "clip" },
})),
["ellipsis"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Ellipsis of",
phrase = "ellipsis of",
abbrev = "ellip.",
glossary = "ellipsis",
toplevel_category = "ellipses",
aliases = { "ellip" },
})),
["back-formation"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Back-formation from",
phrase = "a back-formation from",
abbrev = "bf.",
glossary = "back-formation",
toplevel_category = "back-formations",
aliases = { "bf" },
})),
["nominalization"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Nominalization of",
phrase = "a nominalization of",
abbrev = "nom.",
glossary = "nominalization",
toplevel_category = "nominalizations",
aliases = { "nom" },
})),
["transliteration"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Transliteration of",
phrase = "borrowed from",
abbrev = "translit.",
glossary = "transliteration",
aliases = { "translit" },
})),
["vrd"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Vṛddhi derivative of",
phrase = "a vṛddhi derivative of",
abbrev = "vṛd.",
glossary = "vṛddhi derivative",
})),
["apheretic"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Apheretic form of",
phrase = "an apheretic form of",
abbrev = "aph.",
glossary = "apheresis",
aliases = { "apheresis", "aphetic" },
})),
["denominal"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Denominal verb from",
phrase = "denominal verb from",
abbrev = "denom.",
glossary = "denominal",
toplevel_category = "denominal verbs",
aliases = { "denom" },
})),
["deverbal"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Deverbal from",
phrase = "deverbal from",
abbrev = "deverb.",
glossary = "deverbal",
toplevel_category = "deverbals",
})),
["reduplication"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Reduplication of",
phrase = "reduplication of",
abbrev = "redup.",
glossary = "reduplication",
toplevel_category = "reduplications",
aliases = { "redup" },
})),
["abbreviation"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Abbreviation of",
phrase = "abbreviation of",
abbrev = "abbr.",
glossary = "abbreviation",
aliases = { "abbr" },
})),
["acronym"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Acronym of",
phrase = "acronym of",
abbrev = "acronym",
glossary = "acronym",
aliases = { "acro" },
})),
["initialism"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Initialism of",
phrase = "initialism of",
abbrev = "init.",
glossary = "initialism",
aliases = { "init" },
})),
["metathesis"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Metathesis of",
phrase = "metathesis of",
abbrev = "meta.",
glossary = "metathesis",
toplevel_category = "words derived through metathesis",
aliases = { "meta" },
})),
--
-- Invisible keywords (no text output)
--
["root"] = create_keyword {
transitive = TRANSITIVE.ALWAYS,
invisible = "all",
pos_override = "root",
},
["afeq"] = create_keyword(deep_merge(DEFAULTS.affix_group, {
text = "From",
phrase = "from",
transitive = TRANSITIVE.NEVER,
invisible = "all",
})),
}
local aliases_to_register = {}
local canonical_aliases = {}
-- Map every keyword (canonical or alias) to its canonical form for consistent checks and tracking.
export.keyword_canonical = {}
for name, keyword_data in pairs(export.keywords) do
export.keyword_canonical[name] = name
if keyword_data.aliases then
canonical_aliases[name] = keyword_data.aliases
for _, alias in ipairs(keyword_data.aliases) do
if export.keywords[alias] then
error("Alias '" ..
alias .. "' defined in keyword '" .. name .. "' collides with existing keyword '" .. alias .. "'.")
end
if aliases_to_register[alias] then
error("Alias '" ..
alias .. "' defined in keyword '" .. name .. "' is already claimed by another keyword.")
end
aliases_to_register[alias] = keyword_data
export.keyword_canonical[alias] = name
end
keyword_data.aliases = nil
end
end
for alias, data in pairs(aliases_to_register) do
export.keywords[alias] = data
end
--
-- Language exception presets
--
local EXCEPTION_PRESETS = {
-- Fully disallowed: no tree, no text, no categories
disallowed = {
disallow = { tree = true, text = true },
suppress_categories = true,
},
-- Suppress transliteration only
no_translit = {
suppress_tr = true,
},
-- Suppress all categories only
no_categories = {
suppress_categories = true,
},
}
--[=[
Available exception options:
disallow = { Related options for disallowing output:
tree Disallow etymology trees for this language
text Disallow etymology text generation for this language
ref Reference link shown when tree/text is disallowed
}
suppress_tr Suppress transliteration in links
suppress_categories Suppress all category generation
normalize_to Normalize language code to a different code
normalize_from_families Apply normalization to languages in these families
normalize_exclude_families Exclude these families from normalization
keyword_overrides Per-keyword categorisation overrides (e.g. { ["af"] = { transitive = TRANSITIVE.NEVER } })
]=]
local function create_exception(preset, overrides)
local base = preset and EXCEPTION_PRESETS[preset] or {}
return deep_merge(base, overrides or {})
end
export.config = {
lang_exceptions = {
["zh"] = create_exception("disallowed", {
disallow = { ref = "[[Wiktionary:Beer parlour/2025/May#Template:etymon for Chinese]]" },
suppress_tr = true,
normalize_to = "zh",
normalize_from_families = { "zhx" },
normalize_exclude_families = { "qfa-cnt" },
}),
},
}
-- Supported codes for the nominalization <g:code> modifier (subset of common gender/number-style codes)
export.nominalization_g_codes = {
["m"] = "masculine",
["f"] = "feminine",
["n"] = "neuter",
["c"] = "common",
["gneut"] = "gender-neutral",
["s"] = "singular",
["p"] = "plural",
["d"] = "dual",
["pauc"] = "paucal",
["mf"] = "masculine or feminine",
["fm"] = "masculine or feminine",
["mfn"] = "masculine, feminine or neuter",
["mnf"] = "masculine, feminine or neuter",
["fmn"] = "masculine, feminine or neuter",
["fnm"] = "masculine, feminine or neuter",
["nmf"] = "masculine, feminine or neuter",
["nfm"] = "masculine, feminine or neuter",
}
--
-- Propagate keyword overrides to aliases
--
if export.config.lang_exceptions then
for lang_code, exception in pairs(export.config.lang_exceptions) do
if exception.keyword_overrides then
for canonical, aliases in pairs(canonical_aliases) do
if exception.keyword_overrides[canonical] then
local override_data = exception.keyword_overrides[canonical]
for _, alias in ipairs(aliases) do
if not exception.keyword_overrides[alias] then
exception.keyword_overrides[alias] = override_data
end
end
end
end
end
end
end
return export
1wszme3odnt04424y6bzakrvbjay5q9
2344437
2344311
2026-04-12T06:28:33Z
TheHighFighter2
42988
2344437
Scribunto
text/plain
local export = {}
export.STATUS = {
OK = "ok",
INLINE = "inline",
MISSING = "missing",
REDLINK = "redlink",
AMBIGUOUS = "ambiguous",
}
export.TRANSITIVE = {
ALWAYS = "always", -- always recurse into children
NEVER = "never", -- never recurse into children
CROSS_LANG = "cross_lang", -- only recurse when source lang differs from target lang (but pos chain continues)
CROSS_LANG_NO_INTERNAL_SOURCE = "cross_lang_no_internal_source", -- like CROSS_LANG, but source breaks for internal derivations in the same language context
}
-- Deep merge tables (nested tables are merged recursively, later values override earlier)
local function deep_merge(...)
local result = {}
for _, t in ipairs({ ... }) do
for k, v in pairs(t) do
if type(v) == "table" and type(result[k]) == "table" then
result[k] = deep_merge(result[k], v)
else
result[k] = v
end
end
end
return result
end
local function make_glossary_link(term, display_text)
if not term then return display_text end
return "[[Phụ lục:Từ điển thuật ngữ#" .. term:gsub(" ", "_") .. "|" .. display_text .. "]]"
end
-- Extract base word and connector from text like "Borrowed from" or "calque of"
local function split_glossary_text(text)
for _, pattern in ipairs({ "^(.-)(%s+[Oo][Ff])$", "^(.-)(%s+[Ff][Rr][Oo][Mm])$" }) do
local base, rest = text:match(pattern)
if base then return base, rest end
end
return text, ""
end
local TRANSITIVE = export.TRANSITIVE
local function create_keyword(opts)
local entry = {
is_group = opts.is_group or false,
abbrev = opts.abbrev,
glossary = opts.glossary,
transitive = opts.transitive or TRANSITIVE.ALWAYS, -- default "always"
inherited_chain = opts.inherited_chain or false,
affix_categories = opts.affix_categories or false,
borrowing_type = opts.borrowing_type,
specialized_borrowing = opts.specialized_borrowing,
toplevel_category = opts.toplevel_category,
no_child_categories = opts.no_child_categories or false,
source_category_type = opts.source_category_type,
invisible = (opts.invisible == true and "all") or opts.invisible or false,
pos_override = opts.pos_override,
new_sentence = opts.new_sentence or false,
separate_clause = opts.separate_clause or false,
aliases = opts.aliases,
}
-- Only set text/phrase when visible in text (invisible ~= "all" and ~= "text")
local inv = entry.invisible
if inv ~= "all" and inv ~= "text" then
entry.phrase = opts.phrase
if opts.text then
if opts.glossary then
local base_word, rest = split_glossary_text(opts.text)
entry.text = make_glossary_link(opts.glossary, base_word) .. rest
else
entry.text = opts.text
end
end
end
return entry
end
-- Shared defaults for keyword groups
local DEFAULTS = {
-- Keywords that pass through inheritance chain
inheritance = {
transitive = TRANSITIVE.ALWAYS,
inherited_chain = true,
},
-- Standard transitive derivation
transitive = {
transitive = TRANSITIVE.ALWAYS,
},
-- Standard for internal derivations: transitive across languages, but not within them
internal_derivation = {
transitive = TRANSITIVE.CROSS_LANG,
},
-- Borrowing keywords
borrowing = {
transitive = TRANSITIVE.ALWAYS,
},
-- Affix group keywords (compound words, blends, etc.)
affix_group = {
is_group = true,
transitive = TRANSITIVE.CROSS_LANG,
affix_categories = true,
},
-- Calque-like keywords (calque, partial calque, semantic loan)
calque_like = {
transitive = TRANSITIVE.NEVER,
no_child_categories = true,
new_sentence = true,
},
-- Non-transitive influence
influence_like = {
transitive = TRANSITIVE.NEVER,
no_child_categories = true,
},
}
export.keywords = {
--
-- Inheritance keywords
--
["from"] = create_keyword(deep_merge(DEFAULTS.inheritance, {
text = "From", phrase = "from",
})),
["inherited"] = create_keyword(deep_merge(DEFAULTS.inheritance, {
text = "Inherited from",
phrase = "from",
glossary = "inherited",
aliases = { "inh" },
})),
--
-- Basic derivation keywords
--
["uder"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "From",
phrase = "from",
toplevel_category = "undefined derivations",
})),
["derived"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Derived from",
phrase = "from",
abbrev = "der.",
glossary = "derived terms",
aliases = { "der" },
})),
--
-- Affix/compound group keywords
--
["affix"] = create_keyword(deep_merge(DEFAULTS.affix_group, {
text = "Từ",
phrase = "từ",
aliases = { "af" },
})),
["surf"] = create_keyword(deep_merge(DEFAULTS.affix_group, {
text = "By surface analysis,",
phrase = "by surface analysis,",
abbrev = "surf.",
glossary = "surface analysis",
new_sentence = true,
invisible = "tree",
})),
["blend"] = create_keyword(deep_merge(DEFAULTS.affix_group, {
text = "Blend of",
phrase = "a blend of",
abbrev = "blend",
glossary = "blend",
toplevel_category = "blends",
})),
["univerbation"] = create_keyword(deep_merge(DEFAULTS.affix_group, {
text = "Univerbation of",
phrase = "univerbation of",
abbrev = "univ.",
glossary = "univerbation",
toplevel_category = "univerbations",
aliases = { "univ" },
})),
--
-- Borrowing keywords
--
["bor"] = create_keyword(deep_merge(DEFAULTS.borrowing, {
text = "Borrowed from",
phrase = "borrowed from",
abbrev = "bor.",
glossary = "loanword",
borrowing_type = "borrowed",
aliases = { "borrowed" },
})),
["lbor"] = create_keyword(deep_merge(DEFAULTS.borrowing, {
text = "Learned borrowing from",
phrase = "a learned borrowing from",
abbrev = "lbor.",
glossary = "learned borrowing",
specialized_borrowing = "learned",
})),
["obor"] = create_keyword(deep_merge(DEFAULTS.borrowing, {
text = "Orthographic borrowing from",
phrase = "an orthographic borrowing from",
abbrev = "obor.",
glossary = "orthographic borrowing",
specialized_borrowing = "orthographic",
})),
["slbor"] = create_keyword(deep_merge(DEFAULTS.borrowing, {
text = "Semi-learned borrowing from",
phrase = "a semi-learned borrowing from",
abbrev = "slbor.",
glossary = "semi-learned borrowing",
specialized_borrowing = "semi-learned",
})),
["ubor"] = create_keyword(deep_merge(DEFAULTS.borrowing, {
text = "Unadapted borrowing from",
phrase = "an unadapted borrowing from",
abbrev = "ubor.",
glossary = "unadapted borrowing",
specialized_borrowing = "unadapted",
})),
--
-- Calque-like keywords (non-transitive, start new sentence)
--
["calque"] = create_keyword(deep_merge(DEFAULTS.calque_like, {
text = "Calque of",
phrase = "a calque of",
abbrev = "calq.",
glossary = "calque",
specialized_borrowing = "calque",
aliases = { "cal", "clq" },
})),
["partial calque"] = create_keyword(deep_merge(DEFAULTS.calque_like, {
text = "Partial calque of",
phrase = "a partial calque of",
abbrev = "pcalq.",
glossary = "partial calque",
specialized_borrowing = "partial-calque",
aliases = { "pcal" },
})),
["semantic loan"] = create_keyword(deep_merge(DEFAULTS.calque_like, {
text = "Semantic loan of",
phrase = "a semantic loan of",
abbrev = "sl.",
glossary = "semantic loan",
specialized_borrowing = "semantic-loan",
aliases = { "sl" },
})),
--
-- Influence keywords (non-transitive, separate clause)
--
["influence"] = create_keyword(deep_merge(DEFAULTS.influence_like, {
text = "Influenced by",
phrase = "influenced by",
abbrev = "influ.",
glossary = "contamination",
separate_clause = true,
})),
--
-- Morphological derivation keywords
--
["clipping"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Clipping of",
phrase = "clipping of",
abbrev = "clip.",
glossary = "clipping",
toplevel_category = "clippings",
aliases = { "clip" },
})),
["ellipsis"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Ellipsis of",
phrase = "ellipsis of",
abbrev = "ellip.",
glossary = "ellipsis",
toplevel_category = "ellipses",
aliases = { "ellip" },
})),
["back-formation"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Back-formation from",
phrase = "a back-formation from",
abbrev = "bf.",
glossary = "back-formation",
toplevel_category = "back-formations",
aliases = { "bf" },
})),
["nominalization"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Nominalization of",
phrase = "a nominalization of",
abbrev = "nom.",
glossary = "nominalization",
toplevel_category = "nominalizations",
aliases = { "nom" },
})),
["transliteration"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Transliteration of",
phrase = "borrowed from",
abbrev = "translit.",
glossary = "transliteration",
aliases = { "translit" },
})),
["vrd"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Vṛddhi derivative of",
phrase = "a vṛddhi derivative of",
abbrev = "vṛd.",
glossary = "vṛddhi derivative",
})),
["apheretic"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Apheretic form of",
phrase = "an apheretic form of",
abbrev = "aph.",
glossary = "apheresis",
aliases = { "apheresis", "aphetic" },
})),
["denominal"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Denominal verb from",
phrase = "denominal verb from",
abbrev = "denom.",
glossary = "denominal",
toplevel_category = "denominal verbs",
aliases = { "denom" },
})),
["deverbal"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Deverbal from",
phrase = "deverbal from",
abbrev = "deverb.",
glossary = "deverbal",
toplevel_category = "deverbals",
})),
["reduplication"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Reduplication of",
phrase = "reduplication of",
abbrev = "redup.",
glossary = "reduplication",
toplevel_category = "reduplications",
aliases = { "redup" },
})),
["abbreviation"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Abbreviation of",
phrase = "abbreviation of",
abbrev = "abbr.",
glossary = "abbreviation",
aliases = { "abbr" },
})),
["acronym"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Acronym of",
phrase = "acronym of",
abbrev = "acronym",
glossary = "acronym",
aliases = { "acro" },
})),
["initialism"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Initialism of",
phrase = "initialism of",
abbrev = "init.",
glossary = "initialism",
aliases = { "init" },
})),
["metathesis"] = create_keyword(deep_merge(DEFAULTS.transitive, {
text = "Metathesis of",
phrase = "metathesis of",
abbrev = "meta.",
glossary = "metathesis",
toplevel_category = "words derived through metathesis",
aliases = { "meta" },
})),
--
-- Invisible keywords (no text output)
--
["root"] = create_keyword {
transitive = TRANSITIVE.ALWAYS,
invisible = "all",
pos_override = "root",
},
["afeq"] = create_keyword(deep_merge(DEFAULTS.affix_group, {
text = "From",
phrase = "from",
transitive = TRANSITIVE.NEVER,
invisible = "all",
})),
}
local aliases_to_register = {}
local canonical_aliases = {}
-- Map every keyword (canonical or alias) to its canonical form for consistent checks and tracking.
export.keyword_canonical = {}
for name, keyword_data in pairs(export.keywords) do
export.keyword_canonical[name] = name
if keyword_data.aliases then
canonical_aliases[name] = keyword_data.aliases
for _, alias in ipairs(keyword_data.aliases) do
if export.keywords[alias] then
error("Alias '" ..
alias .. "' defined in keyword '" .. name .. "' collides with existing keyword '" .. alias .. "'.")
end
if aliases_to_register[alias] then
error("Alias '" ..
alias .. "' defined in keyword '" .. name .. "' is already claimed by another keyword.")
end
aliases_to_register[alias] = keyword_data
export.keyword_canonical[alias] = name
end
keyword_data.aliases = nil
end
end
for alias, data in pairs(aliases_to_register) do
export.keywords[alias] = data
end
--
-- Language exception presets
--
local EXCEPTION_PRESETS = {
-- Fully disallowed: no tree, no text, no categories
disallowed = {
disallow = { tree = true, text = true },
suppress_categories = true,
},
-- Suppress transliteration only
no_translit = {
suppress_tr = true,
},
-- Suppress all categories only
no_categories = {
suppress_categories = true,
},
}
--[=[
Available exception options:
disallow = { Related options for disallowing output:
tree Disallow etymology trees for this language
text Disallow etymology text generation for this language
ref Reference link shown when tree/text is disallowed
}
suppress_tr Suppress transliteration in links
suppress_categories Suppress all category generation
normalize_to Normalize language code to a different code
normalize_from_families Apply normalization to languages in these families
normalize_exclude_families Exclude these families from normalization
keyword_overrides Per-keyword categorisation overrides (e.g. { ["af"] = { transitive = TRANSITIVE.NEVER } })
]=]
local function create_exception(preset, overrides)
local base = preset and EXCEPTION_PRESETS[preset] or {}
return deep_merge(base, overrides or {})
end
export.config = {
lang_exceptions = {
["zh"] = create_exception("disallowed", {
disallow = { ref = "[[Wiktionary:Beer parlour/2025/May#Template:etymon for Chinese]]" },
suppress_tr = true,
normalize_to = "zh",
normalize_from_families = { "zhx" },
normalize_exclude_families = { "qfa-cnt" },
}),
},
}
-- Supported codes for the nominalization <g:code> modifier (subset of common gender/number-style codes)
export.nominalization_g_codes = {
["m"] = "masculine",
["f"] = "feminine",
["n"] = "neuter",
["c"] = "common",
["gneut"] = "gender-neutral",
["s"] = "singular",
["p"] = "plural",
["d"] = "dual",
["pauc"] = "paucal",
["mf"] = "masculine or feminine",
["fm"] = "masculine or feminine",
["mfn"] = "masculine, feminine or neuter",
["mnf"] = "masculine, feminine or neuter",
["fmn"] = "masculine, feminine or neuter",
["fnm"] = "masculine, feminine or neuter",
["nmf"] = "masculine, feminine or neuter",
["nfm"] = "masculine, feminine or neuter",
}
--
-- Propagate keyword overrides to aliases
--
if export.config.lang_exceptions then
for lang_code, exception in pairs(export.config.lang_exceptions) do
if exception.keyword_overrides then
for canonical, aliases in pairs(canonical_aliases) do
if exception.keyword_overrides[canonical] then
local override_data = exception.keyword_overrides[canonical]
for _, alias in ipairs(aliases) do
if not exception.keyword_overrides[alias] then
exception.keyword_overrides[alias] = override_data
end
end
end
end
end
end
end
return export
gbkvnexdjv0vc2y1d7cpq96tx37mzp9
Mô đun:etymon/tree
828
378444
2344318
2342904
2026-04-12T01:36:27Z
TheHighFighter2
42988
2344318
Scribunto
text/plain
local export = {}
local html_create = mw.html.create
local max = math.max
local function create_vertical_connector()
return html_create('span'):addClass('etytree-connector-vertical')
end
local function create_abbr(text, title, glossary)
local abbr = html_create('abbr')
:attr('title', title)
:wikitext(text)
if glossary then
abbr = '[[Phụ lục:Từ điển thuật ngữ#' .. glossary .. '|' .. tostring(abbr) .. ']]'
end
return html_create('span'):addClass('etytree-label'):node(abbr)
end
local function create_uncertainty_marker()
return html_create('abbr')
:addClass('etytree-unc')
:attr('title', 'uncertain')
:wikitext('?')
end
local function create_label_container()
return html_create('span'):addClass('etytree-label-container')
end
local function invisible_in_tree(inv)
return inv == "all" or inv == true or inv == "tree"
end
local function render_label(term_block, keyword_info, keyword_modifiers, is_uncertain, is_group_child, term_labels)
-- Skip label when invisible in tree
local has_label = keyword_info and keyword_info.abbrev and not is_group_child and not invisible_in_tree(keyword_info.invisible)
-- For group children, keyword uncertainty is shown on the group label, not on individual terms
local keyword_uncertain = keyword_modifiers and keyword_modifiers.unc and not is_group_child
local show_term_uncertainty = is_uncertain
-- Check if we have term-specific labels
local has_term_labels = term_labels and #term_labels > 0
if not has_label and not show_term_uncertainty and not keyword_uncertain and not has_term_labels then
return
end
local label_span = create_label_container()
if has_label then
local glossary_title = keyword_info.glossary
and keyword_info.glossary:gsub("_", " ")
or keyword_info.abbrev
label_span:node(create_abbr(
keyword_info.abbrev,
glossary_title,
keyword_info.glossary
))
-- Show uncertainty marker if term or keyword is uncertain
if show_term_uncertainty or keyword_uncertain then
label_span:node(create_uncertainty_marker())
end
else
-- No label, but term or keyword is uncertain
if show_term_uncertainty or keyword_uncertain then
label_span:node(create_uncertainty_marker())
end
end
-- Add term-specific labels
if has_term_labels then
for _, label_info in ipairs(term_labels) do
label_span:node(create_abbr(label_info.abbrev, label_info.title, label_info.glossary))
end
end
term_block:node(label_span)
end
local function render_term_block(node_data, format_term_func, is_toplevel)
local link_content = html_create()
link_content
:tag('span')
:addClass('etyl')
:wikitext(node_data.lang:getCanonicalName())
:done()
local term_text = format_term_func(node_data, is_toplevel)
if term_text then
link_content
:wikitext(' ')
:tag('span')
:addClass('etytree-term')
:wikitext(term_text)
:done()
end
local block = html_create('div'):addClass('etytree-block'):node(link_content)
-- Add duplicate styling if this is a duplicate node
if node_data.is_duplicate then
block:addClass('etytree-duplicate')
end
return block
end
local function create_dotted_connector()
return html_create('span'):addClass('etytree-connector-dotted')
end
-- Create an L-shaped connector for nodes with hidden ancestry (duplicate or no_child_categories)
local function create_duplicate_connector()
local container = html_create('div'):addClass('etytree-duplicate-connector')
local inner_wrapper = container:tag('div')
inner_wrapper:tag('span'):addClass('etytree-dup-right')
inner_wrapper:tag('span'):addClass('etytree-dup-horiz')
inner_wrapper:tag('span'):addClass('etytree-dup-left')
inner_wrapper:tag('span'):addClass('etytree-dup-arrow'):wikitext('▲')
return container
end
local function render_group_label(connecting_line, keyword_info, keyword_modifiers)
local has_abbrev = keyword_info and keyword_info.abbrev
local keyword_uncertain = keyword_modifiers and keyword_modifiers.unc
-- Nothing to show if no abbrev and no uncertainty
if not has_abbrev and not keyword_uncertain then
return
end
local label_span = connecting_line:tag('span'):addClass('etytree-group-label')
if has_abbrev then
local glossary_title = keyword_info.glossary
and keyword_info.glossary:gsub("_", " ")
or keyword_info.abbrev
label_span:node(create_abbr(keyword_info.abbrev, glossary_title, nil))
end
-- Add uncertainty marker if keyword has <unc> modifier
if keyword_uncertain then
label_span:node(create_uncertainty_marker())
end
end
local function add_branch_connector(column, index, total)
if index == 1 then
column:tag('span'):addClass('etytree-branch-left')
elseif index == total then
column:tag('span'):addClass('etytree-branch-right')
else
column:tag('span'):addClass('etytree-connector-vertical-short')
column:tag('span'):addClass('etytree-branch-mid')
end
end
function export.render(opts)
opts = opts or {}
local data_tree = opts.data_tree
local format_term_func = opts.format_term_func
-- Forward declaration
local render_term
-- Render a container (keyword + its terms)
local function render_container(container, is_toplevel)
local keyword_info = container.keyword_info
local keyword_modifiers = container.keyword_modifiers or {}
local is_group = keyword_info and keyword_info.is_group
local terms = container.terms or {}
-- Skip container entirely only when invisible = "all" (or true)
if keyword_info and invisible_in_tree(keyword_info.invisible) then
return nil, 0, 0
end
if #terms == 0 then
return nil, 0, 0
end
-- For no_child_categories keywords (calque, semantic loan, etc.), don't render term's children
local skip_child_rendering = keyword_info and keyword_info.no_child_categories
-- Render each term in the container
local rendered_terms = {}
local container_height = 0
local container_width = 0
for _, term in ipairs(terms) do
-- Collect term-specific labels
local term_labels = {}
if term.bor then
table.insert(term_labels, { abbrev = "bor.", title = "vay mượn", glossary = "từ vay mượn" })
end
if term.slbor then
table.insert(term_labels, { abbrev = "slbor.", title = "semi-learned borrowing", glossary = "semi-learned_borrowing" })
end
if term.lbor then
table.insert(term_labels, { abbrev = "lbor.", title = "learned borrowing", glossary = "learned_borrowing" })
end
local term_tree, term_height, term_width = render_term(term, keyword_info, keyword_modifiers, is_group, false, skip_child_rendering, term_labels)
table.insert(rendered_terms, {
tree = term_tree,
height = term_height,
width = term_width,
is_uncertain = term.is_uncertain,
})
container_height = max(container_height, term_height)
container_width = container_width + term_width
end
local rendered_html
local has_connector = false
if #rendered_terms == 1 then
-- Single term: just return it directly
rendered_html = rendered_terms[1].tree
container_height = rendered_terms[1].height
container_width = rendered_terms[1].width
else
-- Multiple terms: group them together
local subtree_container = html_create('div'):addClass('etytree-branch-group')
for i, term_data in ipairs(rendered_terms) do
local column = html_create('div'):addClass('etytree-branch')
column:node(term_data.tree)
add_branch_connector(column, i, #rendered_terms)
subtree_container:node(column)
end
local connecting_line = create_vertical_connector()
-- Add group label for group keywords
if is_group and not invisible_in_tree(keyword_info.invisible) then
render_group_label(connecting_line, keyword_info, keyword_modifiers)
end
rendered_html = html_create()
:node(subtree_container)
:node(connecting_line)
has_connector = true
end
return rendered_html, container_height, container_width, has_connector
end
-- Render a term node
render_term = function(term_node, keyword_info, keyword_modifiers, is_group_child, is_toplevel_term, skip_child_rendering, term_labels)
local tree_width, tree_height = 0, 0
local subtrees = {}
-- Process term's children (which are containers)
local has_hidden_children = false
if not term_node.is_duplicate and not skip_child_rendering then
for _, container in ipairs(term_node.children or {}) do
local subtree, sub_height, sub_width, subtree_has_connector = render_container(container, is_toplevel_term)
if subtree then
table.insert(subtrees, {
tree = subtree,
height = sub_height,
width = sub_width,
has_connector = subtree_has_connector,
})
tree_height = max(tree_height, sub_height)
tree_width = tree_width + sub_width
end
end
elseif skip_child_rendering then
-- Check if there are any visible children
-- When stop_recursion is true, children aren't parsed, but has_visible_children flag is set
if term_node.has_visible_children then
has_hidden_children = true
elseif term_node.children and #term_node.children > 0 then
-- Fallback: check parsed children for visibility
for _, container in ipairs(term_node.children) do
local child_keyword_info = container.keyword_info
if not (child_keyword_info and (child_keyword_info.invisible == "all" or child_keyword_info.invisible == true)) then
has_hidden_children = true
break
end
end
end
end
local is_toplevel_node = (keyword_info == nil)
local term_block = render_term_block(term_node, format_term_func, is_toplevel_node)
render_label(term_block, keyword_info, keyword_modifiers, term_node.is_uncertain, is_group_child, term_labels or {})
local term_html = html_create()
if #subtrees == 0 then
local show_connector = (term_node.is_duplicate and term_node.original_has_children) or has_hidden_children
if show_connector then
term_html:node(create_duplicate_connector())
end
term_html:node(term_block)
tree_width = tree_width + 1
elseif #subtrees == 1 then
term_html:node(subtrees[1].tree)
if not subtrees[1].has_connector then
term_html:node(create_vertical_connector())
end
term_html:node(term_block)
else
-- Multiple containers: need to merge them
local subtree_container = html_create('div'):addClass('etytree-branch-group')
for i, subtree_data in ipairs(subtrees) do
local column = html_create('div'):addClass('etytree-branch')
column:node(subtree_data.tree)
add_branch_connector(column, i, #subtrees)
subtree_container:node(column)
end
local connecting_line = create_vertical_connector()
term_html
:node(subtree_container)
:node(connecting_line)
:node(term_block)
end
return term_html, tree_height + 1, tree_width
end
local final_tree, final_height, final_width = render_term(data_tree, nil, nil, false, true)
local container = html_create('div')
:addClass('etytree-body')
:node(final_tree)
return tostring(html_create('div')
:addClass('etytree NavFrame')
:attr('data-etytree-height', final_height)
:attr('data-etytree-width', final_width)
:tag('div')
:addClass('NavHead')
:tag('div')
:wikitext('Cây từ nguyên')
:done()
:done()
:tag('div')
:addClass('NavContent')
:node(container)
:done())
end
return export
r4bnhfn2pxf697xu38c89yyp94qikc7
Mô đun:etymon/categories
828
378445
2344314
2317910
2026-04-12T01:28:31Z
TheHighFighter2
42988
2344314
Scribunto
text/plain
local export = {}
local M = require("Module:module loader").init({
require = {
etymology = "Module:etymology",
affix = "Module:affix",
etymology_specialized = "Module:etymology/specialized",
},
loadData = {
data = "Module:etymon/data",
},
})
-- Evaluate whether a keyword is transitive for a given term
local function is_transitive(transitive_mode, page_lang, term_lang)
if transitive_mode == M.data.TRANSITIVE.ALWAYS then
return true
elseif transitive_mode == M.data.TRANSITIVE.NEVER then
return false
elseif transitive_mode == M.data.TRANSITIVE.CROSS_LANG then
return page_lang:getCode() ~= term_lang:getCode()
elseif transitive_mode == M.data.TRANSITIVE.CROSS_LANG_NO_INTERNAL_SOURCE then
return page_lang:getCode() ~= term_lang:getCode()
end
error("Unknown transitive mode: " .. tostring(transitive_mode))
end
-- Get keyword config with language-specific overrides
local function get_keyword_config(keyword, lang_exc)
local base_config = M.data.keywords[keyword]
if not base_config then
return nil -- Invalid keyword
end
local overrides = lang_exc and lang_exc.keyword_overrides and lang_exc.keyword_overrides[keyword]
if not overrides then
return base_config
end
-- Merge overrides into base config
local merged = {}
for k, v in pairs(base_config) do
merged[k] = v
end
for k, v in pairs(overrides) do
merged[k] = v
end
return merged
end
function export.get_cat_name(source)
local _, cat_name = M.etymology.get_display_and_cat_name(source, true)
return cat_name
end
-- Normalize affix type aliases
local aftype_aliases = {
["pre"] = "prefix",
["suf"] = "suffix",
["in"] = "infix",
["inter"] = "interfix",
["circum"] = "circumfix",
["naf"] = "non-affix",
["root"] = "non-affix",
}
-- Collect affix categories from top-level group containers
local function collect_affix_categories(node, page_lang, available_etymon_ids, senseid_parent_etymon, lang_exc)
local parts = {}
local part_index = 1
for _, container in ipairs(node.children or {}) do
local config = container.keyword_info
if config and config.affix_categories then
for _, term in ipairs(container.terms or {}) do
if not term.unknown_term then
local part_data = {
term = term.title,
tr = term.tr,
ts = term.ts,
alt = term.alt,
itemno = part_index,
orig_index = part_index
}
-- Determine affix type: explicit aftype > pos=root > auto-detect
local aftype = term.aftype
if aftype then
aftype = aftype_aliases[aftype] or aftype
part_data.type = aftype
elseif term.args and term.args.pos and term.args.pos == "root" then
part_data.type = "non-affix"
end
if term.lang:getCode() ~= page_lang:getCode() then
part_data.lang = term.lang
end
local target_ids = available_etymon_ids[term.target_key]
local has_multiple_ids = target_ids and #target_ids > 1
local id_exists_in_disambiguation = false
local matched_id = nil
-- Count available senseids for the target page
local senseid_count = 0
local target_prefix = term.target_key .. ":"
if senseid_parent_etymon then
for key, _ in pairs(senseid_parent_etymon) do
if key:sub(1, #target_prefix) == target_prefix then
senseid_count = senseid_count + 1
end
end
end
local has_multiple_senseids = senseid_count > 1
if term.id then
-- Check if user provided a valid senseid
local senseid_key = term.target_key .. ":" .. term.id
if senseid_parent_etymon and senseid_parent_etymon[senseid_key] then
if has_multiple_senseids then
-- Ambiguous senseid: use senseid
matched_id = term.id
id_exists_in_disambiguation = true
elseif has_multiple_ids then
-- Unique senseid but ambiguous etymon: use etymon ID
matched_id = term.etymon_id or term.id
id_exists_in_disambiguation = true
end
else
-- Check if user provided a valid etymon ID
if has_multiple_ids and target_ids then
for _, id_data in ipairs(target_ids) do
local stored_id = type(id_data) == "table" and id_data.id or id_data
if stored_id == term.id then
-- Ambiguous etymon: use etymon ID
id_exists_in_disambiguation = true
matched_id = term.id
break
end
end
end
-- Fallback: check resolved etymon_id (e.g. from previous steps)
if not id_exists_in_disambiguation and has_multiple_ids and term.etymon_id and target_ids then
for _, id_data in ipairs(target_ids) do
local stored_id = type(id_data) == "table" and id_data.id or id_data
if stored_id == term.etymon_id then
id_exists_in_disambiguation = true
matched_id = term.etymon_id
break
end
end
end
end
end
-- Use the matched ID if found
if term.override or id_exists_in_disambiguation then
part_data.id = matched_id or term.id
end
table.insert(parts, part_data)
part_index = part_index + 1
end
end
end
end
if #parts == 0 then return {} end
local affix_data = {
lang = page_lang,
parts = parts,
pos = "term",
sort_key = nil
}
local affix_categories = M.affix.get_affix_categories_only(affix_data)
local result = {}
for _, cat in ipairs(affix_categories) do
if type(cat) == "table" then
table.insert(result, cat.cat)
else
table.insert(result, cat)
end
end
return result
end
-- Add borrowing-related categories (top-level only)
local function collect_borrowing_categories(categories, page_lang, term, config)
if config.borrowing_type == "borrowed" then
local temp_categories = {}
M.etymology.insert_borrowed_cat(temp_categories, page_lang, term.lang)
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
end
if config.specialized_borrowing then
local result = M.etymology_specialized.specialized_borrowing {
bortype = config.specialized_borrowing,
lang = page_lang,
sources = { term.lang },
terms = { { lang = term.lang, term = "-" } },
notext = true,
nocat = false,
}
for cat_name in result:gmatch("%[%[Category:([^%]]+)%]%]") do
categories[cat_name] = true
end
end
end
-- Add source-based derivation categories (top-level only)
local function collect_source_derivation_categories(categories, page_lang, term, config)
if not config.source_category_type then
return
end
local temp_categories = {}
M.etymology.insert_source_cat_get_display {
lang = page_lang,
source = term.lang,
categories = temp_categories,
borrowing_type = config.source_category_type,
nocat = false,
}
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
end
-- Add source language categories
local function collect_source_categories(categories, page_lang, term, chain, get_norm_lang_func)
if page_lang:getCode() == get_norm_lang_func(term.lang):getCode() then
return
end
local temp_categories = {}
M.etymology.insert_source_cat_get_display {
lang = page_lang,
source = term.lang,
categories = temp_categories,
nocat = false,
}
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
if chain.inherited then
temp_categories = {}
M.etymology.insert_source_cat_get_display {
lang = page_lang,
source = term.lang,
categories = temp_categories,
borrowing_type = "terms inherited",
nocat = false,
}
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
end
end
-- Add root/word categories
local function collect_pos_categories(categories, page_lang, root_title, term, available_etymon_ids, chain,
get_norm_lang_func, lang_exc, keyword)
local pos_types = { root = "root", word = "word" }
-- Determine pos: from term's postype, keyword's pos_override, or args.pos
local pos
local config = get_keyword_config(keyword, lang_exc)
if term.postype then
-- Term-level postype modifier takes highest priority
pos = term.postype
elseif config and config.pos_override then
pos = config.pos_override
elseif type(term.args) == "table" and term.args.pos then
pos = term.args.pos
end
local pos_type = pos_types[pos]
if not pos_type or term.unknown_term then
return
end
-- Skip root/word categories for descendants of affix groups
-- if pos_type then
-- return
-- end
local same_language = get_norm_lang_func(page_lang):getFullCode() == get_norm_lang_func(term.lang):getFullCode()
-- Skip self-references
if same_language and root_title == term.title then
return
end
-- Use makeEntryName to strip diacritics for category names
local entry_name = term.lang:makeEntryName(term.title)
local lang_name = page_lang:getCanonicalName()
local cat_name
if chain.passed_through then
local etymon_lang_name = export.get_cat_name(term.lang)
cat_name = lang_name .. " terms derived from the " .. etymon_lang_name .. " " .. pos_type .. " " .. entry_name
else
cat_name = lang_name .. " terms belonging to the " .. pos_type .. " " .. entry_name
end
-- Add ID disambiguation if needed (for roots/words: use etymon_id if resolved via senseid, otherwise use id)
local target_ids = available_etymon_ids[term.target_key]
local effective_id = term.etymon_id or term.id -- etymon_id if senseid, otherwise id is already an etymon id
if target_ids and effective_id then
local same_pos_count = 0
for _, id_data in ipairs(target_ids) do
if type(id_data) == "table" and id_data.pos == pos then
same_pos_count = same_pos_count + 1
end
end
if same_pos_count > 1 then
cat_name = cat_name .. " (" .. effective_id .. ")"
end
end
categories[cat_name] = true
end
-- Compute chain state for a term based on parent chain and keyword config
-- Hyphen patterns for affix detection (regular hyphen + script-specific)
local AFFIX_HYPHEN_PATTERN = "[%-%־ـ᠊]" -- regular hyphen, Hebrew maqqef, Arabic tatweel, Mongolian hyphen
-- Check if a term is an actual affix (not a non-affix member of an affix group)
local function is_actual_affix(term)
-- Check explicit aftype modifier
if term.aftype then
local normalized = aftype_aliases[term.aftype] or term.aftype
return normalized ~= "non-affix"
end
-- Check if pos=root (treated as non-affix)
if term.args and term.args.pos and term.args.pos == "root" then
return false
end
-- Auto-detect by hyphen: prefix ends with -, suffix starts with -, etc.
if term.title then
local title = term.title
-- Strip leading * for reconstructed terms before checking hyphens
title = title:gsub("^%*", "")
-- Check for hyphens at start or end (handles script-specific hyphens too)
if title:match("^" .. AFFIX_HYPHEN_PATTERN) or title:match(AFFIX_HYPHEN_PATTERN .. "$") then
return true
end
end
-- Default: not an affix
return false
end
local function compute_category_chain(parent_chain, config, page_lang, term_lang, get_norm_lang_func, parent_term_lang, term)
-- Track if we're inside an actual affix (for suppressing root categories on descendants)
-- Only set if the term is an actual affix (prefix, suffix, etc.), not a non-affix member
local inside_affix = parent_chain.inside_affix
if config.affix_categories and term and is_actual_affix(term) then
inside_affix = true
end
-- If no_child_categories is set, disable everything
if config.no_child_categories then
return {
passed_through = parent_chain.passed_through or page_lang:getCode() ~= get_norm_lang_func(term_lang):getCode(),
inherited = false,
source = false,
pos = false,
recurse = false,
inside_affix = inside_affix,
}
end
local term_is_transitive = is_transitive(config.transitive, page_lang, term_lang)
local new_source = parent_chain.source and term_is_transitive
-- For CROSS_LANG_NO_INTERNAL_SOURCE: track internal derivation language context
-- Check if this term is internal relative to parent term's language (if parent_term_lang provided)
-- or relative to page language (if no parent_term_lang)
local internal_lang = parent_chain.internal_lang
local is_internal_in_context = false
if config.transitive == M.data.TRANSITIVE.CROSS_LANG_NO_INTERNAL_SOURCE then
local check_lang = parent_term_lang or page_lang
local term_lang_code = get_norm_lang_func(term_lang):getCode()
local check_lang_code = get_norm_lang_func(check_lang):getCode()
if internal_lang then
-- Already in an internal derivation context: check if this term is also internal
is_internal_in_context = term_lang_code == internal_lang
else
-- Check if this term is internal relative to parent term (or page if no parent)
is_internal_in_context = term_lang_code == check_lang_code
end
end
-- Source chain behavior for CROSS_LANG_NO_INTERNAL_SOURCE
if config.transitive == M.data.TRANSITIVE.CROSS_LANG_NO_INTERNAL_SOURCE then
if is_internal_in_context then
-- Internal derivation
new_source = false
internal_lang = get_norm_lang_func(term_lang):getCode()
else
-- Cross-language
new_source = parent_chain.source and term_is_transitive
internal_lang = nil
end
end
local new_pos = parent_chain.pos
return {
passed_through = parent_chain.passed_through or page_lang:getCode() ~= get_norm_lang_func(term_lang):getCode(),
inherited = parent_chain.inherited and config.inherited_chain,
source = new_source,
pos = new_pos,
internal_lang = internal_lang,
recurse = new_source or new_pos,
inside_affix = inside_affix,
}
end
function export.render(opts)
opts = opts or {}
local data_tree = opts.data_tree
local page_lang = opts.page_lang
local available_etymon_ids = opts.available_etymon_ids
local senseid_parent_etymon = opts.senseid_parent_etymon
local get_norm_lang_func = opts.get_norm_lang_func
local lang_exc = opts.lang_exc
local categories = {}
local seen = {}
local lang_name = page_lang:getCanonicalName()
local root_title = data_tree.title
-- Collect the tree recursively
local function collect(node, parent_chain, is_toplevel)
-- Avoid processing same node twice
if not node.unknown_term and node.title then
local key = node.lang:getFullCode() .. ":" .. (node.title or "") .. ":" .. (node.id or "")
if seen[key] then return end
seen[key] = true
end
-- Collect affix categories at top level only
if is_toplevel then
local affix_cats = collect_affix_categories(node, page_lang, available_etymon_ids, senseid_parent_etymon, lang_exc)
for _, cat in ipairs(affix_cats) do
categories[lang_name .. " " .. cat] = true
end
end
-- Process each container
for _, container in ipairs(node.children or {}) do
local keyword = container.keyword
local config = get_keyword_config(keyword, lang_exc)
-- Skip invalid keywords
if config then
-- Process each term in the container
for _, term in ipairs(container.terms or {}) do
local term_chain = compute_category_chain(parent_chain, config, page_lang, term.lang, get_norm_lang_func, node.lang, term)
local no_child_categories = config.no_child_categories == true
local term_is_transitive = is_transitive(config.transitive, page_lang, term.lang)
-- Top-level only processing
if is_toplevel then
-- Missing/ambiguous etymon tracking
if not term.unknown_term and (term.status == M.data.STATUS.MISSING or term.status == M.data.STATUS.REDLINK) then
categories[lang_name .. " entries referencing missing etymons"] = true
end
if not term.unknown_term and term.status == M.data.STATUS.AMBIGUOUS then
categories[lang_name .. " entries referencing ambiguous etymons"] = true
end
if term.missing_descendants_header then
categories[lang_name .. " entries referencing etymons without Descendants sections"] = true
end
if term.missing_descendants_entry then
categories[lang_name .. " entries referencing etymons without this term in Descendants sections"] = true
end
-- Top-level category (e.g., "undefined derivations")
if config.toplevel_category then
categories[lang_name .. " " .. config.toplevel_category] = true
end
-- Borrowing categories (bor, lbor, slbor, ubor, obor)
if config.borrowing_type or config.specialized_borrowing then
collect_borrowing_categories(categories, page_lang, term, config)
end
-- Borrowing categories from <bor>, <lbor>, or <slbor> modifiers on :af/:surf terms
if keyword == "affix" or keyword == "surf" then
if term.bor then
local bor_config = { borrowing_type = "borrowed" }
collect_borrowing_categories(categories, page_lang, term, bor_config)
elseif term.lbor then
local bor_config = { specialized_borrowing = "learned" }
collect_borrowing_categories(categories, page_lang, term, bor_config)
elseif term.slbor then
local bor_config = { specialized_borrowing = "semi-learned" }
collect_borrowing_categories(categories, page_lang, term, bor_config)
end
end
-- Source-based derivation categories (sl, calque, pcal)
if config.source_category_type then
collect_source_derivation_categories(categories, page_lang, term, config)
end
-- Skip all child categorisation if no_child_categories is set
if not no_child_categories then
-- Source categories only if transitive
if term_is_transitive then
collect_source_categories(categories, page_lang, term, term_chain, get_norm_lang_func)
end
-- Pos categories always (unless no_child_categories)
collect_pos_categories(categories, page_lang, root_title, term, available_etymon_ids, term_chain,
get_norm_lang_func, lang_exc, keyword)
end
else
-- Below top level, respect the parent chain
if parent_chain.source then
collect_source_categories(categories, page_lang, term, term_chain, get_norm_lang_func)
end
if parent_chain.pos then
collect_pos_categories(categories, page_lang, root_title, term, available_etymon_ids, term_chain,
get_norm_lang_func, lang_exc, keyword)
end
end
-- Recurse into term's children if needed and status allows
if term_chain.recurse and (term.status == M.data.STATUS.OK or term.status == M.data.STATUS.INLINE) then
collect(term, term_chain, false)
end
end
end
end
end
-- Initial chain state
local initial_chain = {
passed_through = false,
inherited = true,
source = true,
pos = true,
internal_lang = nil,
recurse = true,
inside_affix = false,
}
collect(data_tree, initial_chain, true)
local cat_list = {}
for cat in pairs(categories) do
table.insert(cat_list, cat)
end
return cat_list
end
return export
6x8tux7uka6u4jnngod6ksjr5ghck2r
2344438
2344314
2026-04-12T06:35:26Z
TheHighFighter2
42988
2344438
Scribunto
text/plain
local export = {}
local M = require("Module:module loader").init({
require = {
etymology = "Module:etymology",
affix = "Module:affix",
etymology_specialized = "Module:etymology/specialized",
},
loadData = {
data = "Module:etymon/data",
},
})
-- Evaluate whether a keyword is transitive for a given term
local function is_transitive(transitive_mode, page_lang, term_lang)
if transitive_mode == M.data.TRANSITIVE.ALWAYS then
return true
elseif transitive_mode == M.data.TRANSITIVE.NEVER then
return false
elseif transitive_mode == M.data.TRANSITIVE.CROSS_LANG then
return page_lang:getCode() ~= term_lang:getCode()
elseif transitive_mode == M.data.TRANSITIVE.CROSS_LANG_NO_INTERNAL_SOURCE then
return page_lang:getCode() ~= term_lang:getCode()
end
error("Unknown transitive mode: " .. tostring(transitive_mode))
end
-- Get keyword config with language-specific overrides
local function get_keyword_config(keyword, lang_exc)
local base_config = M.data.keywords[keyword]
if not base_config then
return nil -- Invalid keyword
end
local overrides = lang_exc and lang_exc.keyword_overrides and lang_exc.keyword_overrides[keyword]
if not overrides then
return base_config
end
-- Merge overrides into base config
local merged = {}
for k, v in pairs(base_config) do
merged[k] = v
end
for k, v in pairs(overrides) do
merged[k] = v
end
return merged
end
function export.get_cat_name(source)
local _, cat_name = M.etymology.get_display_and_cat_name(source, true)
return cat_name
end
-- Normalize affix type aliases
local aftype_aliases = {
["pre"] = "prefix",
["suf"] = "suffix",
["in"] = "infix",
["inter"] = "interfix",
["circum"] = "circumfix",
["naf"] = "non-affix",
["root"] = "non-affix",
}
-- Collect affix categories from top-level group containers
local function collect_affix_categories(node, page_lang, available_etymon_ids, senseid_parent_etymon, lang_exc)
local parts = {}
local part_index = 1
for _, container in ipairs(node.children or {}) do
local config = container.keyword_info
if config and config.affix_categories then
for _, term in ipairs(container.terms or {}) do
if not term.unknown_term then
local part_data = {
term = term.title,
tr = term.tr,
ts = term.ts,
alt = term.alt,
itemno = part_index,
orig_index = part_index
}
-- Determine affix type: explicit aftype > pos=root > auto-detect
local aftype = term.aftype
if aftype then
aftype = aftype_aliases[aftype] or aftype
part_data.type = aftype
elseif term.args and term.args.pos and term.args.pos == "root" then
part_data.type = "non-affix"
end
if term.lang:getCode() ~= page_lang:getCode() then
part_data.lang = term.lang
end
local target_ids = available_etymon_ids[term.target_key]
local has_multiple_ids = target_ids and #target_ids > 1
local id_exists_in_disambiguation = false
local matched_id = nil
-- Count available senseids for the target page
local senseid_count = 0
local target_prefix = term.target_key .. ":"
if senseid_parent_etymon then
for key, _ in pairs(senseid_parent_etymon) do
if key:sub(1, #target_prefix) == target_prefix then
senseid_count = senseid_count + 1
end
end
end
local has_multiple_senseids = senseid_count > 1
if term.id then
-- Check if user provided a valid senseid
local senseid_key = term.target_key .. ":" .. term.id
if senseid_parent_etymon and senseid_parent_etymon[senseid_key] then
if has_multiple_senseids then
-- Ambiguous senseid: use senseid
matched_id = term.id
id_exists_in_disambiguation = true
elseif has_multiple_ids then
-- Unique senseid but ambiguous etymon: use etymon ID
matched_id = term.etymon_id or term.id
id_exists_in_disambiguation = true
end
else
-- Check if user provided a valid etymon ID
if has_multiple_ids and target_ids then
for _, id_data in ipairs(target_ids) do
local stored_id = type(id_data) == "table" and id_data.id or id_data
if stored_id == term.id then
-- Ambiguous etymon: use etymon ID
id_exists_in_disambiguation = true
matched_id = term.id
break
end
end
end
-- Fallback: check resolved etymon_id (e.g. from previous steps)
if not id_exists_in_disambiguation and has_multiple_ids and term.etymon_id and target_ids then
for _, id_data in ipairs(target_ids) do
local stored_id = type(id_data) == "table" and id_data.id or id_data
if stored_id == term.etymon_id then
id_exists_in_disambiguation = true
matched_id = term.etymon_id
break
end
end
end
end
end
-- Use the matched ID if found
if term.override or id_exists_in_disambiguation then
part_data.id = matched_id or term.id
end
table.insert(parts, part_data)
part_index = part_index + 1
end
end
end
end
if #parts == 0 then return {} end
local affix_data = {
lang = page_lang,
parts = parts,
pos = "Từ",
sort_key = nil
}
local affix_categories = M.affix.get_affix_categories_only(affix_data)
local result = {}
for _, cat in ipairs(affix_categories) do
if type(cat) == "table" then
table.insert(result, cat.cat)
else
table.insert(result, cat)
end
end
return result
end
-- Add borrowing-related categories (top-level only)
local function collect_borrowing_categories(categories, page_lang, term, config)
if config.borrowing_type == "borrowed" then
local temp_categories = {}
M.etymology.insert_borrowed_cat(temp_categories, page_lang, term.lang)
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
end
if config.specialized_borrowing then
local result = M.etymology_specialized.specialized_borrowing {
bortype = config.specialized_borrowing,
lang = page_lang,
sources = { term.lang },
terms = { { lang = term.lang, term = "-" } },
notext = true,
nocat = false,
}
for cat_name in result:gmatch("%[%[Category:([^%]]+)%]%]") do
categories[cat_name] = true
end
end
end
-- Add source-based derivation categories (top-level only)
local function collect_source_derivation_categories(categories, page_lang, term, config)
if not config.source_category_type then
return
end
local temp_categories = {}
M.etymology.insert_source_cat_get_display {
lang = page_lang,
source = term.lang,
categories = temp_categories,
borrowing_type = config.source_category_type,
nocat = false,
}
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
end
-- Add source language categories
local function collect_source_categories(categories, page_lang, term, chain, get_norm_lang_func)
if page_lang:getCode() == get_norm_lang_func(term.lang):getCode() then
return
end
local temp_categories = {}
M.etymology.insert_source_cat_get_display {
lang = page_lang,
source = term.lang,
categories = temp_categories,
nocat = false,
}
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
if chain.inherited then
temp_categories = {}
M.etymology.insert_source_cat_get_display {
lang = page_lang,
source = term.lang,
categories = temp_categories,
borrowing_type = "terms inherited",
nocat = false,
}
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
end
end
-- Add root/word categories
local function collect_pos_categories(categories, page_lang, root_title, term, available_etymon_ids, chain,
get_norm_lang_func, lang_exc, keyword)
local pos_types = { root = "root", word = "word" }
-- Determine pos: from term's postype, keyword's pos_override, or args.pos
local pos
local config = get_keyword_config(keyword, lang_exc)
if term.postype then
-- Term-level postype modifier takes highest priority
pos = term.postype
elseif config and config.pos_override then
pos = config.pos_override
elseif type(term.args) == "table" and term.args.pos then
pos = term.args.pos
end
local pos_type = pos_types[pos]
if not pos_type or term.unknown_term then
return
end
-- Skip root/word categories for descendants of affix groups
-- if pos_type then
-- return
-- end
local same_language = get_norm_lang_func(page_lang):getFullCode() == get_norm_lang_func(term.lang):getFullCode()
-- Skip self-references
if same_language and root_title == term.title then
return
end
-- Use makeEntryName to strip diacritics for category names
local entry_name = term.lang:makeEntryName(term.title)
local lang_name = page_lang:getCanonicalName()
local cat_name
if chain.passed_through then
local etymon_lang_name = export.get_cat_name(term.lang)
cat_name = lang_name .. " terms derived from the " .. etymon_lang_name .. " " .. pos_type .. " " .. entry_name
else
cat_name = lang_name .. " terms belonging to the " .. pos_type .. " " .. entry_name
end
-- Add ID disambiguation if needed (for roots/words: use etymon_id if resolved via senseid, otherwise use id)
local target_ids = available_etymon_ids[term.target_key]
local effective_id = term.etymon_id or term.id -- etymon_id if senseid, otherwise id is already an etymon id
if target_ids and effective_id then
local same_pos_count = 0
for _, id_data in ipairs(target_ids) do
if type(id_data) == "table" and id_data.pos == pos then
same_pos_count = same_pos_count + 1
end
end
if same_pos_count > 1 then
cat_name = cat_name .. " (" .. effective_id .. ")"
end
end
categories[cat_name] = true
end
-- Compute chain state for a term based on parent chain and keyword config
-- Hyphen patterns for affix detection (regular hyphen + script-specific)
local AFFIX_HYPHEN_PATTERN = "[%-%־ـ᠊]" -- regular hyphen, Hebrew maqqef, Arabic tatweel, Mongolian hyphen
-- Check if a term is an actual affix (not a non-affix member of an affix group)
local function is_actual_affix(term)
-- Check explicit aftype modifier
if term.aftype then
local normalized = aftype_aliases[term.aftype] or term.aftype
return normalized ~= "non-affix"
end
-- Check if pos=root (treated as non-affix)
if term.args and term.args.pos and term.args.pos == "root" then
return false
end
-- Auto-detect by hyphen: prefix ends with -, suffix starts with -, etc.
if term.title then
local title = term.title
-- Strip leading * for reconstructed terms before checking hyphens
title = title:gsub("^%*", "")
-- Check for hyphens at start or end (handles script-specific hyphens too)
if title:match("^" .. AFFIX_HYPHEN_PATTERN) or title:match(AFFIX_HYPHEN_PATTERN .. "$") then
return true
end
end
-- Default: not an affix
return false
end
local function compute_category_chain(parent_chain, config, page_lang, term_lang, get_norm_lang_func, parent_term_lang, term)
-- Track if we're inside an actual affix (for suppressing root categories on descendants)
-- Only set if the term is an actual affix (prefix, suffix, etc.), not a non-affix member
local inside_affix = parent_chain.inside_affix
if config.affix_categories and term and is_actual_affix(term) then
inside_affix = true
end
-- If no_child_categories is set, disable everything
if config.no_child_categories then
return {
passed_through = parent_chain.passed_through or page_lang:getCode() ~= get_norm_lang_func(term_lang):getCode(),
inherited = false,
source = false,
pos = false,
recurse = false,
inside_affix = inside_affix,
}
end
local term_is_transitive = is_transitive(config.transitive, page_lang, term_lang)
local new_source = parent_chain.source and term_is_transitive
-- For CROSS_LANG_NO_INTERNAL_SOURCE: track internal derivation language context
-- Check if this term is internal relative to parent term's language (if parent_term_lang provided)
-- or relative to page language (if no parent_term_lang)
local internal_lang = parent_chain.internal_lang
local is_internal_in_context = false
if config.transitive == M.data.TRANSITIVE.CROSS_LANG_NO_INTERNAL_SOURCE then
local check_lang = parent_term_lang or page_lang
local term_lang_code = get_norm_lang_func(term_lang):getCode()
local check_lang_code = get_norm_lang_func(check_lang):getCode()
if internal_lang then
-- Already in an internal derivation context: check if this term is also internal
is_internal_in_context = term_lang_code == internal_lang
else
-- Check if this term is internal relative to parent term (or page if no parent)
is_internal_in_context = term_lang_code == check_lang_code
end
end
-- Source chain behavior for CROSS_LANG_NO_INTERNAL_SOURCE
if config.transitive == M.data.TRANSITIVE.CROSS_LANG_NO_INTERNAL_SOURCE then
if is_internal_in_context then
-- Internal derivation
new_source = false
internal_lang = get_norm_lang_func(term_lang):getCode()
else
-- Cross-language
new_source = parent_chain.source and term_is_transitive
internal_lang = nil
end
end
local new_pos = parent_chain.pos
return {
passed_through = parent_chain.passed_through or page_lang:getCode() ~= get_norm_lang_func(term_lang):getCode(),
inherited = parent_chain.inherited and config.inherited_chain,
source = new_source,
pos = new_pos,
internal_lang = internal_lang,
recurse = new_source or new_pos,
inside_affix = inside_affix,
}
end
function export.render(opts)
opts = opts or {}
local data_tree = opts.data_tree
local page_lang = opts.page_lang
local available_etymon_ids = opts.available_etymon_ids
local senseid_parent_etymon = opts.senseid_parent_etymon
local get_norm_lang_func = opts.get_norm_lang_func
local lang_exc = opts.lang_exc
local categories = {}
local seen = {}
local lang_name = page_lang:getCanonicalName()
local root_title = data_tree.title
-- Collect the tree recursively
local function collect(node, parent_chain, is_toplevel)
-- Avoid processing same node twice
if not node.unknown_term and node.title then
local key = node.lang:getFullCode() .. ":" .. (node.title or "") .. ":" .. (node.id or "")
if seen[key] then return end
seen[key] = true
end
-- Collect affix categories at top level only
if is_toplevel then
local affix_cats = collect_affix_categories(node, page_lang, available_etymon_ids, senseid_parent_etymon, lang_exc)
for _, cat in ipairs(affix_cats) do
categories[cat .. " " .. lang_name] = true
end
end
-- Process each container
for _, container in ipairs(node.children or {}) do
local keyword = container.keyword
local config = get_keyword_config(keyword, lang_exc)
-- Skip invalid keywords
if config then
-- Process each term in the container
for _, term in ipairs(container.terms or {}) do
local term_chain = compute_category_chain(parent_chain, config, page_lang, term.lang, get_norm_lang_func, node.lang, term)
local no_child_categories = config.no_child_categories == true
local term_is_transitive = is_transitive(config.transitive, page_lang, term.lang)
-- Top-level only processing
if is_toplevel then
-- Missing/ambiguous etymon tracking
if not term.unknown_term and (term.status == M.data.STATUS.MISSING or term.status == M.data.STATUS.REDLINK) then
categories[lang_name .. " entries referencing missing etymons"] = true
end
if not term.unknown_term and term.status == M.data.STATUS.AMBIGUOUS then
categories[lang_name .. " entries referencing ambiguous etymons"] = true
end
if term.missing_descendants_header then
categories[lang_name .. " entries referencing etymons without Descendants sections"] = true
end
if term.missing_descendants_entry then
categories[lang_name .. " entries referencing etymons without this term in Descendants sections"] = true
end
-- Top-level category (e.g., "undefined derivations")
if config.toplevel_category then
categories[lang_name .. " " .. config.toplevel_category] = true
end
-- Borrowing categories (bor, lbor, slbor, ubor, obor)
if config.borrowing_type or config.specialized_borrowing then
collect_borrowing_categories(categories, page_lang, term, config)
end
-- Borrowing categories from <bor>, <lbor>, or <slbor> modifiers on :af/:surf terms
if keyword == "affix" or keyword == "surf" then
if term.bor then
local bor_config = { borrowing_type = "borrowed" }
collect_borrowing_categories(categories, page_lang, term, bor_config)
elseif term.lbor then
local bor_config = { specialized_borrowing = "learned" }
collect_borrowing_categories(categories, page_lang, term, bor_config)
elseif term.slbor then
local bor_config = { specialized_borrowing = "semi-learned" }
collect_borrowing_categories(categories, page_lang, term, bor_config)
end
end
-- Source-based derivation categories (sl, calque, pcal)
if config.source_category_type then
collect_source_derivation_categories(categories, page_lang, term, config)
end
-- Skip all child categorisation if no_child_categories is set
if not no_child_categories then
-- Source categories only if transitive
if term_is_transitive then
collect_source_categories(categories, page_lang, term, term_chain, get_norm_lang_func)
end
-- Pos categories always (unless no_child_categories)
collect_pos_categories(categories, page_lang, root_title, term, available_etymon_ids, term_chain,
get_norm_lang_func, lang_exc, keyword)
end
else
-- Below top level, respect the parent chain
if parent_chain.source then
collect_source_categories(categories, page_lang, term, term_chain, get_norm_lang_func)
end
if parent_chain.pos then
collect_pos_categories(categories, page_lang, root_title, term, available_etymon_ids, term_chain,
get_norm_lang_func, lang_exc, keyword)
end
end
-- Recurse into term's children if needed and status allows
if term_chain.recurse and (term.status == M.data.STATUS.OK or term.status == M.data.STATUS.INLINE) then
collect(term, term_chain, false)
end
end
end
end
end
-- Initial chain state
local initial_chain = {
passed_through = false,
inherited = true,
source = true,
pos = true,
internal_lang = nil,
recurse = true,
inside_affix = false,
}
collect(data_tree, initial_chain, true)
local cat_list = {}
for cat in pairs(categories) do
table.insert(cat_list, cat)
end
return cat_list
end
return export
kruf33c8923wu77v66w85fp6eoujhx1
2344441
2344438
2026-04-12T07:18:32Z
TheHighFighter2
42988
2344441
Scribunto
text/plain
local export = {}
local M = require("Module:module loader").init({
require = {
etymology = "Module:etymology",
affix = "Module:affix",
etymology_specialized = "Module:etymology/specialized",
},
loadData = {
data = "Module:etymon/data",
},
})
-- Evaluate whether a keyword is transitive for a given term
local function is_transitive(transitive_mode, page_lang, term_lang)
if transitive_mode == M.data.TRANSITIVE.ALWAYS then
return true
elseif transitive_mode == M.data.TRANSITIVE.NEVER then
return false
elseif transitive_mode == M.data.TRANSITIVE.CROSS_LANG then
return page_lang:getCode() ~= term_lang:getCode()
elseif transitive_mode == M.data.TRANSITIVE.CROSS_LANG_NO_INTERNAL_SOURCE then
return page_lang:getCode() ~= term_lang:getCode()
end
error("Unknown transitive mode: " .. tostring(transitive_mode))
end
-- Get keyword config with language-specific overrides
local function get_keyword_config(keyword, lang_exc)
local base_config = M.data.keywords[keyword]
if not base_config then
return nil -- Invalid keyword
end
local overrides = lang_exc and lang_exc.keyword_overrides and lang_exc.keyword_overrides[keyword]
if not overrides then
return base_config
end
-- Merge overrides into base config
local merged = {}
for k, v in pairs(base_config) do
merged[k] = v
end
for k, v in pairs(overrides) do
merged[k] = v
end
return merged
end
function export.get_cat_name(source)
local _, cat_name = M.etymology.get_display_and_cat_name(source, true)
return cat_name
end
-- Normalize affix type aliases
local aftype_aliases = {
["pre"] = "prefix",
["suf"] = "suffix",
["in"] = "infix",
["inter"] = "interfix",
["circum"] = "circumfix",
["naf"] = "non-affix",
["root"] = "non-affix",
}
-- Collect affix categories from top-level group containers
local function collect_affix_categories(node, page_lang, available_etymon_ids, senseid_parent_etymon, lang_exc)
local parts = {}
local part_index = 1
for _, container in ipairs(node.children or {}) do
local config = container.keyword_info
if config and config.affix_categories then
for _, term in ipairs(container.terms or {}) do
if not term.unknown_term then
local part_data = {
term = term.title,
tr = term.tr,
ts = term.ts,
alt = term.alt,
itemno = part_index,
orig_index = part_index
}
-- Determine affix type: explicit aftype > pos=root > auto-detect
local aftype = term.aftype
if aftype then
aftype = aftype_aliases[aftype] or aftype
part_data.type = aftype
elseif term.args and term.args.pos and term.args.pos == "root" then
part_data.type = "non-affix"
end
if term.lang:getCode() ~= page_lang:getCode() then
part_data.lang = term.lang
end
local target_ids = available_etymon_ids[term.target_key]
local has_multiple_ids = target_ids and #target_ids > 1
local id_exists_in_disambiguation = false
local matched_id = nil
-- Count available senseids for the target page
local senseid_count = 0
local target_prefix = term.target_key .. ":"
if senseid_parent_etymon then
for key, _ in pairs(senseid_parent_etymon) do
if key:sub(1, #target_prefix) == target_prefix then
senseid_count = senseid_count + 1
end
end
end
local has_multiple_senseids = senseid_count > 1
if term.id then
-- Check if user provided a valid senseid
local senseid_key = term.target_key .. ":" .. term.id
if senseid_parent_etymon and senseid_parent_etymon[senseid_key] then
if has_multiple_senseids then
-- Ambiguous senseid: use senseid
matched_id = term.id
id_exists_in_disambiguation = true
elseif has_multiple_ids then
-- Unique senseid but ambiguous etymon: use etymon ID
matched_id = term.etymon_id or term.id
id_exists_in_disambiguation = true
end
else
-- Check if user provided a valid etymon ID
if has_multiple_ids and target_ids then
for _, id_data in ipairs(target_ids) do
local stored_id = type(id_data) == "table" and id_data.id or id_data
if stored_id == term.id then
-- Ambiguous etymon: use etymon ID
id_exists_in_disambiguation = true
matched_id = term.id
break
end
end
end
-- Fallback: check resolved etymon_id (e.g. from previous steps)
if not id_exists_in_disambiguation and has_multiple_ids and term.etymon_id and target_ids then
for _, id_data in ipairs(target_ids) do
local stored_id = type(id_data) == "table" and id_data.id or id_data
if stored_id == term.etymon_id then
id_exists_in_disambiguation = true
matched_id = term.etymon_id
break
end
end
end
end
end
-- Use the matched ID if found
if term.override or id_exists_in_disambiguation then
part_data.id = matched_id or term.id
end
table.insert(parts, part_data)
part_index = part_index + 1
end
end
end
end
if #parts == 0 then return {} end
local affix_data = {
lang = page_lang,
parts = parts,
pos = "Từ",
sort_key = nil
}
local affix_categories = M.affix.get_affix_categories_only(affix_data)
local result = {}
for _, cat in ipairs(affix_categories) do
if type(cat) == "table" then
table.insert(result, cat.cat)
else
table.insert(result, cat)
end
end
return result
end
-- Add borrowing-related categories (top-level only)
local function collect_borrowing_categories(categories, page_lang, term, config)
if config.borrowing_type == "borrowed" then
local temp_categories = {}
M.etymology.insert_borrowed_cat(temp_categories, page_lang, term.lang)
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
end
if config.specialized_borrowing then
local result = M.etymology_specialized.specialized_borrowing {
bortype = config.specialized_borrowing,
lang = page_lang,
sources = { term.lang },
terms = { { lang = term.lang, term = "-" } },
notext = true,
nocat = false,
}
for cat_name in result:gmatch("%[%[Category:([^%]]+)%]%]") do
categories[cat_name] = true
end
end
end
-- Add source-based derivation categories (top-level only)
local function collect_source_derivation_categories(categories, page_lang, term, config)
if not config.source_category_type then
return
end
local temp_categories = {}
M.etymology.insert_source_cat_get_display {
lang = page_lang,
source = term.lang,
categories = temp_categories,
borrowing_type = config.source_category_type,
nocat = false,
}
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
end
-- Add source language categories
local function collect_source_categories(categories, page_lang, term, chain, get_norm_lang_func)
if page_lang:getCode() == get_norm_lang_func(term.lang):getCode() then
return
end
local temp_categories = {}
M.etymology.insert_source_cat_get_display {
lang = page_lang,
source = term.lang,
categories = temp_categories,
nocat = false,
}
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
if chain.inherited then
temp_categories = {}
M.etymology.insert_source_cat_get_display {
lang = page_lang,
source = term.lang,
categories = temp_categories,
borrowing_type = "terms inherited",
nocat = false,
}
for _, cat in ipairs(temp_categories) do
categories[cat] = true
end
end
end
-- Add root/word categories
local function collect_pos_categories(categories, page_lang, root_title, term, available_etymon_ids, chain,
get_norm_lang_func, lang_exc, keyword)
local pos_types = { root = "root", word = "word" }
-- Determine pos: from term's postype, keyword's pos_override, or args.pos
local pos
local config = get_keyword_config(keyword, lang_exc)
if term.postype then
-- Term-level postype modifier takes highest priority
pos = term.postype
elseif config and config.pos_override then
pos = config.pos_override
elseif type(term.args) == "table" and term.args.pos then
pos = term.args.pos
end
local pos_type = pos_types[pos]
if not pos_type or term.unknown_term then
return
end
-- Skip root/word categories for descendants of affix groups
-- if pos_type then
-- return
-- end
local same_language = get_norm_lang_func(page_lang):getFullCode() == get_norm_lang_func(term.lang):getFullCode()
-- Skip self-references
if same_language and root_title == term.title then
return
end
-- Use makeEntryName to strip diacritics for category names
local entry_name = term.lang:makeEntryName(term.title)
local lang_name = page_lang:getCanonicalName()
local cat_name
if chain.passed_through then
local etymon_lang_name = export.get_cat_name(term.lang)
cat_name = lang_name .. " terms derived from the " .. etymon_lang_name .. " " .. pos_type .. " " .. entry_name
else
cat_name = lang_name .. " terms belonging to the " .. pos_type .. " " .. entry_name
end
-- Add ID disambiguation if needed (for roots/words: use etymon_id if resolved via senseid, otherwise use id)
local target_ids = available_etymon_ids[term.target_key]
local effective_id = term.etymon_id or term.id -- etymon_id if senseid, otherwise id is already an etymon id
if target_ids and effective_id then
local same_pos_count = 0
for _, id_data in ipairs(target_ids) do
if type(id_data) == "table" and id_data.pos == pos then
same_pos_count = same_pos_count + 1
end
end
if same_pos_count > 1 then
cat_name = cat_name .. " (" .. effective_id .. ")"
end
end
categories[cat_name] = true
end
-- Compute chain state for a term based on parent chain and keyword config
-- Hyphen patterns for affix detection (regular hyphen + script-specific)
local AFFIX_HYPHEN_PATTERN = "[%-%־ـ᠊]" -- regular hyphen, Hebrew maqqef, Arabic tatweel, Mongolian hyphen
-- Check if a term is an actual affix (not a non-affix member of an affix group)
local function is_actual_affix(term)
-- Check explicit aftype modifier
if term.aftype then
local normalized = aftype_aliases[term.aftype] or term.aftype
return normalized ~= "non-affix"
end
-- Check if pos=root (treated as non-affix)
if term.args and term.args.pos and term.args.pos == "root" then
return false
end
-- Auto-detect by hyphen: prefix ends with -, suffix starts with -, etc.
if term.title then
local title = term.title
-- Strip leading * for reconstructed terms before checking hyphens
title = title:gsub("^%*", "")
-- Check for hyphens at start or end (handles script-specific hyphens too)
if title:match("^" .. AFFIX_HYPHEN_PATTERN) or title:match(AFFIX_HYPHEN_PATTERN .. "$") then
return true
end
end
-- Default: not an affix
return false
end
local function compute_category_chain(parent_chain, config, page_lang, term_lang, get_norm_lang_func, parent_term_lang, term)
-- Track if we're inside an actual affix (for suppressing root categories on descendants)
-- Only set if the term is an actual affix (prefix, suffix, etc.), not a non-affix member
local inside_affix = parent_chain.inside_affix
if config.affix_categories and term and is_actual_affix(term) then
inside_affix = true
end
-- If no_child_categories is set, disable everything
if config.no_child_categories then
return {
passed_through = parent_chain.passed_through or page_lang:getCode() ~= get_norm_lang_func(term_lang):getCode(),
inherited = false,
source = false,
pos = false,
recurse = false,
inside_affix = inside_affix,
}
end
local term_is_transitive = is_transitive(config.transitive, page_lang, term_lang)
local new_source = parent_chain.source and term_is_transitive
-- For CROSS_LANG_NO_INTERNAL_SOURCE: track internal derivation language context
-- Check if this term is internal relative to parent term's language (if parent_term_lang provided)
-- or relative to page language (if no parent_term_lang)
local internal_lang = parent_chain.internal_lang
local is_internal_in_context = false
if config.transitive == M.data.TRANSITIVE.CROSS_LANG_NO_INTERNAL_SOURCE then
local check_lang = parent_term_lang or page_lang
local term_lang_code = get_norm_lang_func(term_lang):getCode()
local check_lang_code = get_norm_lang_func(check_lang):getCode()
if internal_lang then
-- Already in an internal derivation context: check if this term is also internal
is_internal_in_context = term_lang_code == internal_lang
else
-- Check if this term is internal relative to parent term (or page if no parent)
is_internal_in_context = term_lang_code == check_lang_code
end
end
-- Source chain behavior for CROSS_LANG_NO_INTERNAL_SOURCE
if config.transitive == M.data.TRANSITIVE.CROSS_LANG_NO_INTERNAL_SOURCE then
if is_internal_in_context then
-- Internal derivation
new_source = false
internal_lang = get_norm_lang_func(term_lang):getCode()
else
-- Cross-language
new_source = parent_chain.source and term_is_transitive
internal_lang = nil
end
end
local new_pos = parent_chain.pos
return {
passed_through = parent_chain.passed_through or page_lang:getCode() ~= get_norm_lang_func(term_lang):getCode(),
inherited = parent_chain.inherited and config.inherited_chain,
source = new_source,
pos = new_pos,
internal_lang = internal_lang,
recurse = new_source or new_pos,
inside_affix = inside_affix,
}
end
function export.render(opts)
opts = opts or {}
local data_tree = opts.data_tree
local page_lang = opts.page_lang
local available_etymon_ids = opts.available_etymon_ids
local senseid_parent_etymon = opts.senseid_parent_etymon
local get_norm_lang_func = opts.get_norm_lang_func
local lang_exc = opts.lang_exc
local categories = {}
local seen = {}
local lang_name = page_lang:getCanonicalName()
local root_title = data_tree.title
-- Collect the tree recursively
local function collect(node, parent_chain, is_toplevel)
-- Avoid processing same node twice
if not node.unknown_term and node.title then
local key = node.lang:getFullCode() .. ":" .. (node.title or "") .. ":" .. (node.id or "")
if seen[key] then return end
seen[key] = true
end
-- Collect affix categories at top level only
if is_toplevel then
local affix_cats = collect_affix_categories(node, page_lang, available_etymon_ids, senseid_parent_etymon, lang_exc)
for _, cat in ipairs(affix_cats) do
categories[cat .. " " .. lang_name] = true
end
end
-- Process each container
for _, container in ipairs(node.children or {}) do
local keyword = container.keyword
local config = get_keyword_config(keyword, lang_exc)
-- Skip invalid keywords
if config then
-- Process each term in the container
for _, term in ipairs(container.terms or {}) do
local term_chain = compute_category_chain(parent_chain, config, page_lang, term.lang, get_norm_lang_func, node.lang, term)
local no_child_categories = config.no_child_categories == true
local term_is_transitive = is_transitive(config.transitive, page_lang, term.lang)
-- Top-level only processing
if is_toplevel then
-- Missing/ambiguous etymon tracking
if not term.unknown_term and (term.status == M.data.STATUS.MISSING or term.status == M.data.STATUS.REDLINK) then
categories["Mục từ tham chiếu đến nguyên từ bị thiếu " .. lang_name] = true
end
if not term.unknown_term and term.status == M.data.STATUS.AMBIGUOUS then
categories[lang_name .. " entries referencing ambiguous etymons"] = true
end
if term.missing_descendants_header then
categories[lang_name .. " entries referencing etymons without Descendants sections"] = true
end
if term.missing_descendants_entry then
categories[lang_name .. " entries referencing etymons without this term in Descendants sections"] = true
end
-- Top-level category (e.g., "undefined derivations")
if config.toplevel_category then
categories[lang_name .. " " .. config.toplevel_category] = true
end
-- Borrowing categories (bor, lbor, slbor, ubor, obor)
if config.borrowing_type or config.specialized_borrowing then
collect_borrowing_categories(categories, page_lang, term, config)
end
-- Borrowing categories from <bor>, <lbor>, or <slbor> modifiers on :af/:surf terms
if keyword == "affix" or keyword == "surf" then
if term.bor then
local bor_config = { borrowing_type = "borrowed" }
collect_borrowing_categories(categories, page_lang, term, bor_config)
elseif term.lbor then
local bor_config = { specialized_borrowing = "learned" }
collect_borrowing_categories(categories, page_lang, term, bor_config)
elseif term.slbor then
local bor_config = { specialized_borrowing = "semi-learned" }
collect_borrowing_categories(categories, page_lang, term, bor_config)
end
end
-- Source-based derivation categories (sl, calque, pcal)
if config.source_category_type then
collect_source_derivation_categories(categories, page_lang, term, config)
end
-- Skip all child categorisation if no_child_categories is set
if not no_child_categories then
-- Source categories only if transitive
if term_is_transitive then
collect_source_categories(categories, page_lang, term, term_chain, get_norm_lang_func)
end
-- Pos categories always (unless no_child_categories)
collect_pos_categories(categories, page_lang, root_title, term, available_etymon_ids, term_chain,
get_norm_lang_func, lang_exc, keyword)
end
else
-- Below top level, respect the parent chain
if parent_chain.source then
collect_source_categories(categories, page_lang, term, term_chain, get_norm_lang_func)
end
if parent_chain.pos then
collect_pos_categories(categories, page_lang, root_title, term, available_etymon_ids, term_chain,
get_norm_lang_func, lang_exc, keyword)
end
end
-- Recurse into term's children if needed and status allows
if term_chain.recurse and (term.status == M.data.STATUS.OK or term.status == M.data.STATUS.INLINE) then
collect(term, term_chain, false)
end
end
end
end
end
-- Initial chain state
local initial_chain = {
passed_through = false,
inherited = true,
source = true,
pos = true,
internal_lang = nil,
recurse = true,
inside_affix = false,
}
collect(data_tree, initial_chain, true)
local cat_list = {}
for cat in pairs(categories) do
table.insert(cat_list, cat)
end
return cat_list
end
return export
qorsihbwugty14b18kb7pju5xrtdgqv
Mô đun:etymon/text
828
378446
2344317
2317912
2026-04-12T01:31:38Z
TheHighFighter2
42988
2344317
Scribunto
text/plain
local export = {}
local loader = require("Module:module loader")
local M = loader.init({
require = {
en_utilities = "Module:en-utilities",
references = "Module:references",
},
loadData = {
data = "Module:etymon/data",
},
})
function export.render(opts)
opts = opts or {}
local data_tree = opts.data_tree
local format_term_func = opts.format_term_func
local max_depth = opts.max_depth
local stop_at_blue_link = opts.stop_at_blue_link
local curr_page = opts.curr_page
local nodot = opts.nodot
local stop_at_lang = opts.stop_at_lang
local stop_at_lang_or_bluelink = opts.stop_at_lang_or_bluelink
local children = data_tree.children
if not children or #children == 0 then
return ""
end
local top_l2 = data_tree.lang:getFullCode() .. ":" .. curr_page
-- Get refs for a term
local function get_term_refs(term, term_lang, depth)
local term_l2 = term_lang:getFullCode() .. ":" .. curr_page
if term.parsed_ref and (depth == 1 or term_l2 == top_l2) then
return M.references.format_references(term.parsed_ref)
end
return ""
end
-- Build a text part for a single term
local function build_term_part(term, current_lang, depth)
local text = ""
local new_lang = current_lang
local lang_changed = term.lang:getCanonicalName() ~= current_lang:getCanonicalName()
-- Use centralized format_term (handles suppress_term, unknown_term, and regular terms)
local term_text = format_term_func(term)
if lang_changed then
new_lang = term.lang
if term_text then
text = term.lang:makeWikipediaLink() .. " " .. term_text
elseif term.is_family then
text = M.en_utilities.add_indefinite_article(term.lang:makeWikipediaLink() .. " language", false)
else
-- suppress_term with language change: show only language
text = term.lang:makeWikipediaLink()
end
else
text = term_text or ""
end
return {
type = "term",
text = text,
refs = get_term_refs(term, new_lang, depth),
lang = new_lang,
is_uncertain = term.is_uncertain or false,
}
end
-- Build text parts for a container
local function build_container_part(container, node, depth, allow_continuation, fallback_to_bluelink)
local keyword_info = container.keyword_info
local keyword_modifiers = container.keyword_modifiers or {}
local terms = container.terms or {}
if not keyword_info or #terms == 0 then
return nil
end
-- Skip building text part when invisible in text ("all", "text", or true)
local inv = keyword_info.invisible
if inv == "all" or inv == true or inv == "text" then
return nil
end
local is_group = keyword_info.is_group
local keyword_uncertain = keyword_modifiers.unc or false
-- Determine text and phrase (allowing for overrides)
local intro_text = keyword_info.text
local phrase = keyword_info.phrase
if keyword_modifiers.text then
-- User-provided override: assumed to be lowercase
phrase = keyword_modifiers.text
-- Auto-capitalize for intro text (e.g., "derived from" -> "Derived from")
intro_text = mw.ustring.upper(phrase:sub(1, 1)) .. phrase:sub(2)
end
-- Get keyword references
local keyword_refs = ""
if keyword_modifiers.ref then
local parsed_keyword_refs = M.references.parse_references(keyword_modifiers.ref)
if parsed_keyword_refs and parsed_keyword_refs ~= "" then
keyword_refs = M.references.format_references(parsed_keyword_refs)
end
end
-- Build term parts
local term_parts = {}
local current_lang = node.lang
for _, term in ipairs(terms) do
local term_part = build_term_part(term, current_lang, depth)
if term_part.text ~= "" then
table.insert(term_parts, term_part)
current_lang = term_part.lang
end
end
-- Check uncertainty distribution
local uncertain_count = 0
for _, term_part in ipairs(term_parts) do
if term_part.is_uncertain then
uncertain_count = uncertain_count + 1
end
end
-- If keyword itself is uncertain, treat all terms as uncertain
local all_uncertain = keyword_uncertain or (uncertain_count == #term_parts and #term_parts > 0)
local has_mixed_uncertainty = not keyword_uncertain and uncertain_count > 0 and uncertain_count < #term_parts
-- Check if there are more steps (only if continuation is allowed)
local has_more_steps = false
local next_node = nil
local first_term = terms[1]
-- Check if we should stop at this language
local reached_stop_lang = false
if stop_at_lang then
for _, term in ipairs(terms) do
if term.lang and term.lang:getCode() == stop_at_lang then
reached_stop_lang = true
break
end
end
elseif stop_at_lang_or_bluelink then
-- Check if we should stop at this language, or at the first bluelink if it's a redlink
for _, term in ipairs(terms) do
if term.lang and term.lang:getCode() == stop_at_lang_or_bluelink then
if first_term.status == M.data.STATUS.OK then
reached_stop_lang = true
else
fallback_to_bluelink = true
end
break
end
end
if fallback_to_bluelink and first_term.status == M.data.STATUS.OK then
reached_stop_lang = true
end
end
if allow_continuation and not is_group and #terms == 1 and not reached_stop_lang then
local first_term_children = first_term.children
if first_term_children and #first_term_children > 0 and (not max_depth or depth < max_depth) then
local next_container = first_term_children[1]
local next_keyword_info = next_container and next_container.keyword_info
if not (next_keyword_info and next_keyword_info.invisible) then
if stop_at_blue_link then
if first_term.status ~= M.data.STATUS.OK then
has_more_steps = true
next_node = first_term
end
else
has_more_steps = true
next_node = first_term
end
end
end
end
return {
type = "container",
intro_text = intro_text,
phrase = phrase,
is_uncertain = all_uncertain,
has_mixed_uncertainty = has_mixed_uncertainty,
term_parts = term_parts,
is_group = is_group,
has_more_steps = has_more_steps,
next_node = next_node,
new_sentence = keyword_info.new_sentence or false,
separate_clause = keyword_info.separate_clause or false,
conj = keyword_modifiers.conj, -- custom conjunction: "and", "or", "and/or", etc.
lit = keyword_modifiers.lit,
keyword_refs = keyword_refs,
fallback_to_bluelink = fallback_to_bluelink,
}
end
-- Build the full tree of text parts
local function build_text_tree(node, depth, allow_continuation, fallback_to_bluelink)
local containers = node.children
if not containers or #containers == 0 then
return nil
end
local container_parts = {}
-- Count containers that get a text part (invisible in text = "all", "text", or true)
local visible_container_count = 0
for _, container in ipairs(containers) do
local keyword_info = container.keyword_info
local inv = keyword_info and keyword_info.invisible
if not (inv == "all" or inv == true or inv == "text") then
visible_container_count = visible_container_count + 1
end
end
-- If there are multiple visible containers at this level, don't allow continuation for any
local has_multiple_containers = visible_container_count > 1
local should_allow_continuation = allow_continuation and not has_multiple_containers
for _, container in ipairs(containers) do
local part = build_container_part(container, node, depth, should_allow_continuation, fallback_to_bluelink)
if part then
-- Recursively build children if there are more steps
if part.has_more_steps and part.next_node then
part.continuation = build_text_tree(part.next_node, depth + 1, true, part.fallback_to_bluelink)
end
table.insert(container_parts, part)
end
end
if #container_parts == 0 then
return nil
end
return {
type = "tree",
container_parts = container_parts,
depth = depth,
}
end
-- Check if tree has mixed joining types
local function check_complexity(tree)
if not tree then return nil end
local parts = tree.container_parts
if #parts <= 1 then
-- Single container
if parts[1] and parts[1].continuation then
return check_complexity(parts[1].continuation)
end
return nil
end
-- Multiple containers
local has_or_join = false
local has_new_sentence = false
local has_separate_clause = false
for i = 2, #parts do
local part = parts[i]
-- Ignore etydate parts for complexity checks
if part.type ~= "etydate" then
if part.new_sentence then
has_new_sentence = true
elseif part.separate_clause then
has_separate_clause = true
else
has_or_join = true
end
end
end
local join_type_count = 0
if has_or_join then join_type_count = join_type_count + 1 end
if has_new_sentence then join_type_count = join_type_count + 1 end
if has_separate_clause then join_type_count = join_type_count + 1 end
if join_type_count > 1 then
error(
"Cannot generate etymology text: mixed joining styles (e.g., alternatives joined with 'or' cannot be combined with calques or influences in the same list).")
end
return nil
end
-- Analyze tree and assign punctuation
local function analyze_punctuation(tree, is_toplevel)
if not tree then return end
local parts = tree.container_parts
local num_parts = #parts
for i, part in ipairs(parts) do
local is_first = (i == 1)
local is_last = (i == num_parts)
local next_part = parts[i + 1]
-- Analyze term punctuation within container
-- Terms use Oxford comma style: "A, B, or C"
-- Custom conjunction can be specified via conj modifier (e.g., "and/or", "and")
local num_terms = #part.term_parts
local term_conj = part.conj or "or" -- default to "or"
for j, term_part in ipairs(part.term_parts) do
local is_last_term = (j == num_terms)
if part.is_group then
-- Group: terms joined with " + "
term_part.joiner = is_last_term and "" or " + "
elseif num_terms > 1 then
-- Multiple terms not in a group: Oxford comma style
if is_last_term then
term_part.joiner = ""
elseif j == num_terms - 1 then
-- Second to last term
if num_terms == 2 then
term_part.joiner = " " .. term_conj .. " "
else
term_part.joiner = ", " .. term_conj .. " "
end
else
term_part.joiner = ", "
end
else
-- Single term
term_part.joiner = ""
end
end
-- Determine container punctuation based on what comes next
if part.continuation then
-- Has continuation
part.punctuation = ","
-- Recursively analyze continuation
analyze_punctuation(part.continuation, false)
elseif is_last then
-- Last container
part.punctuation = (is_toplevel and nodot) and "" or "."
elseif next_part and next_part.new_sentence then
-- Next container starts a new sentence
part.punctuation = "."
elseif next_part and next_part.separate_clause then
-- Next container is a separate clause
part.punctuation = ","
else
-- Not last, next is joined with "or"
-- Containers use repeated "or" style: "A, or B, or C"
part.punctuation = ","
end
-- Determine joiner to next part
-- Containers use repeated "or" style: ", or" between each
-- Custom conjunction can be specified via conj modifier
local container_conj = part.conj or "or" -- default to "or"
if not is_last then
if next_part and next_part.new_sentence then
-- New sentence
part.joiner = " "
elseif next_part and next_part.separate_clause then
-- Separate clause
part.joiner = " "
else
-- Same sentence: use custom conjunction or default "or"
part.joiner = " " .. container_conj .. " "
end
else
part.joiner = ""
end
-- Determine intro formatting
-- Capitalize if first at top level, OR if this container starts a new sentence
if (is_first and is_toplevel) or part.new_sentence then
part.intro_capitalized = true
part.use_full_intro = true
else
part.intro_capitalized = false
part.use_full_intro = false
end
end
end
-- Assemble text from analyzed tree
local function assemble_text(tree)
if not tree then return "" end
local result = ""
for i, part in ipairs(tree.container_parts) do
if part.type == "etydate" then
result = result .. part.etydate_text
if part.punctuation and part.punctuation ~= "" then
result = result .. part.punctuation
end
if part.etydate_refs and part.etydate_refs ~= "" then
result = result .. M.references.format_references(part.etydate_refs)
end
if part.joiner and part.joiner ~= "" then
result = result .. part.joiner
end
else
-- Build intro
local intro
if part.use_full_intro then
if part.is_uncertain then
intro = "Possibly " .. part.phrase
else
intro = part.intro_text
end
else
if part.is_uncertain then
intro = "possibly " .. part.phrase
else
intro = part.phrase
end
end
result = result .. intro
-- Build terms
if #part.term_parts > 0 then
result = result .. " "
for j, term_part in ipairs(part.term_parts) do
-- Add "possibly" prefix for uncertain terms when there's mixed uncertainty
if part.has_mixed_uncertainty and term_part.is_uncertain then
result = result .. "possibly "
end
result = result .. term_part.text
-- Add joiner between terms
if term_part.joiner ~= "" then
-- Check if joiner contains comma (punctuation)
local comma_pos = term_part.joiner:find(",")
if comma_pos then
-- Add up to and including comma
result = result .. term_part.joiner:sub(1, comma_pos)
-- Add refs after comma
if term_part.refs ~= "" then
result = result .. term_part.refs
end
-- Add rest of joiner
result = result .. term_part.joiner:sub(comma_pos + 1)
else
-- No comma, add refs before joiner
if term_part.refs ~= "" then
result = result .. term_part.refs
end
result = result .. term_part.joiner
end
end
end
-- For the last term, add punctuation then refs
local last_term = part.term_parts[#part.term_parts]
if last_term and last_term.joiner == "" then
if part.punctuation ~= "" then
-- If we have literal text, punctuation goes AFTER it
if part.lit then
-- Add refs first (attached to term)
if last_term.refs ~= "" then
result = result .. last_term.refs
end
-- Add keyword refs
if part.keyword_refs and part.keyword_refs ~= "" then
result = result .. part.keyword_refs
end
-- Add literal text
result = result .. ", literally “" .. part.lit .. "”"
-- Add punctuation
result = result .. part.punctuation
else
-- Normal behavior: punctuation then refs
result = result .. part.punctuation
if last_term.refs ~= "" then
result = result .. last_term.refs
end
-- Add keyword refs after term refs
if part.keyword_refs and part.keyword_refs ~= "" then
result = result .. part.keyword_refs
end
end
else
-- No punctuation
if last_term.refs ~= "" then
result = result .. last_term.refs
end
-- Add keyword refs
if part.keyword_refs and part.keyword_refs ~= "" then
result = result .. part.keyword_refs
end
-- Add literal text if present (even without punctuation)
if part.lit then
result = result .. ", literally “" .. part.lit .. "”"
end
end
end
else
-- No terms, just add punctuation and keyword refs
if part.punctuation ~= "" then
result = result .. part.punctuation
end
-- Add keyword refs even when there are no terms
if part.keyword_refs and part.keyword_refs ~= "" then
result = result .. part.keyword_refs
end
end
-- Add continuation
if part.continuation then
result = result .. " " .. assemble_text(part.continuation)
end
-- Add joiner to next container
if part.joiner ~= "" then
result = result .. part.joiner
end
end
end
return result
end
local text_tree = build_text_tree(data_tree, 1, true, false)
if not text_tree then
return ""
end
-- Add etydate container
if data_tree.etydate and data_tree.etydate ~= "" then
table.insert(text_tree.container_parts, {
type = "etydate",
etydate_text = data_tree.etydate,
etydate_refs = data_tree.etydate_refs,
term_parts = {},
new_sentence = true,
})
end
check_complexity(text_tree)
analyze_punctuation(text_tree, true)
return assemble_text(text_tree)
end
return export
mscg7aggtjqgbl7hwqfxfm3rjn77i82
Bản mẫu:pl-decl-combined-forms
10
392388
2344383
2344282
2026-04-12T04:33:30Z
Hiyuune
50834
2344383
wikitext
text/x-wiki
{{inflection-table-top|title=Dạng kết hợp của {{mention|pl||{{{1|{{pagename}}}}}}}|tall=yes|palette=blue}}
! class="outer" |
! class="outer" | số ít
! class="outer" | số nhiều
|-
! ngôi thứ nhất
| {{l-self|pl|{{pagename}}m}}
| {{l-self|pl|{{pagename}}śmy}}
|-
! ngôi thứ hai
| {{l-self|pl|{{pagename}}ś}}
| {{l-self|pl|{{pagename}}ście}}
|-
! ngôi thứ ba
| {{l-self|pl|{{pagename}}}}
| {{l-self|pl|{{pagename}}}}
{{inflection-table-bottom}}<!--
--><noinclude>{{tài liệu}}</noinclude>
2hxu5hs7947e7jpy8hgd6xxehyksviu
ū
0
392390
2344286
2026-04-11T13:40:14Z
Lcsnes
40261
Trang mới: “{{minitoc}} {{-Latn-}} {{character info|image=Latin alphabet Ūū.png}} ==={{ĐM|desction}}=== {{head|mul|Chữ cái|chữ hoa|Ū}} #[[chữ cái|Chữ cái]] '''[[u]] viết thường''' với dấu phù hiệu ngang bên trên [[◌̄]] ([[macron]]). ==={{ĐM|see}}=== {{Latn-script}} =={{langname|agq}}== ==={{ĐM|pron}}=== *{{IPA4|agq|/ū/}} ==={{ĐM|letter}}=== {{head|agq|Chữ cái|chữ hoa|Ū}} #Chữ cái ''[[u]]'' viết thường với thanh trung ([[◌̄]]). #…”
2344286
wikitext
text/x-wiki
{{minitoc}}
{{-Latn-}}
{{character info|image=Latin alphabet Ūū.png}}
==={{ĐM|desction}}===
{{head|mul|Chữ cái|chữ hoa|Ū}}
#[[chữ cái|Chữ cái]] '''[[u]] viết thường''' với dấu phù hiệu ngang bên trên [[◌̄]] ([[macron]]).
==={{ĐM|see}}===
{{Latn-script}}
=={{langname|agq}}==
==={{ĐM|pron}}===
*{{IPA4|agq|/ū/}}
==={{ĐM|letter}}===
{{head|agq|Chữ cái|chữ hoa|Ū}}
#Chữ cái ''[[u]]'' viết thường với thanh trung ([[◌̄]]).
#:{{quote|agq|Zwɔ̂ŋ u wə̄n wə m fuŋ ŋgəa tsughu naʼ e Silìa e dzə̀m, ghî ghə̀ n nîi wò mbī tə aghì tə̀ dzaŋā ten tə̀ dzə̀m; ghəla ghe dzaŋā ŋgòʼ e dzàŋà tə̀n tə̀ dzə̀m àsùghò luʼ'''ū''' tə eghùe tò, ghəla ghe ki zʉ̀ ù biigh wo, ghəla ghe bvʉā bvʉ̀ kò, à ghəla ghe kpuw doʼō â luʼ'''ū''' tə ghùe tò, ù m baaŋ kɔʼɔ ghee.|Vậy, danh-tiếng Ngài đồn ra khắp cả xứ Sy-ri, người ta bèn đem cho Ngài mọi người đau-ốm, hay là mắc bịnh nọ tật kia, những kẻ bị quỉ ám, điên-cuồng, bại-xuội, thì Ngài chữa cho họ được lành cả. ([[s:Ma-thi-ơ/4#4:24|Ma-thi-ơ 4:24]])}}
==={{ĐM|see}}===
*{{letters|lang=agq|sc=Latn|qual=Bảng chữ cái Latinh tiếng Aghem|Aa|(Àà)|(Āā)|(Ââ)|(Ǎǎ)|Bb|Bv/bv|Ch/ch|Dd|Dz/dz|Ee|(Èè)|(Ēē)|(Êê)|(Ěě)|Ɛɛ|(Ɛ̀/ɛ̀)|(Ɛ̄/ɛ̄)|(Ɛ̂/ɛ̂)|(Ɛ̌/ɛ̌)|Ff|Gg|Gb/gb|Gh/gh|Hh|Ii|(Ìì)|(Īī)|(Îî)|(Ǐǐ)|Ɨɨ|(Ɨ̀/ɨ̀)|(Ɨ̄/ɨ̄)|(Ɨ̂/ɨ̂)|(Ɨ̌/ɨ̌)|Kk|Kp/kp|ʼ|Ll|Mm|(M̀/m̀)|Nn|(Ǹ/ǹ)|Ŋŋ|Oo|(Òò)|(Ōō)|(Ôô)|(Ǒǒ)|Ɔɔ|(Ɔ̀/ɔ̀)|(Ɔ̄/ɔ̄)|(Ɔ̂/ɔ̂)|(Ɔ̌/ɔ̌)|Pp|Pf/pf|Ss|Sh/sh|Tt|Ts/ts|Uu|(Ùù)|(Ūū)|(Ûû)|(Ǔǔ)|Uw/uw|Ʉʉ|(Ʉ̀/ʉ̀)|(Ʉ̄/ʉ̄)|(Ʉ̂/ʉ̂)|(Ʉ̌/ʉ̌)|Vv|Ww|Yy|Zz}}
==={{ĐM|ref}}===
*{{Chú thích web|agq|work=To kə Kəzə̀ kə̀ Fughu ko|author=Cameroon Association for Bible Translation and Literacy|year=2024|entryurl=https://www.bible.com/bible/2620/MAT.4.AGQ|entry=Matìo 4}}
=={{langname|bss}}==
==={{ĐM|symbol}}===
{{head|bss|Ký tự|chữ hoa|Ū}}
#Biến thể chữ {{l|bss|u}} viết thường với thanh ngang.
#:{{ux|bss|nkú'''ū'''sē|[[kiến]] [[trắng]] [[nhỏ]]|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=bss|sc=Latn|qual=Bảng chữ cái Latinh tiếng Akoose|Aa|(Áá)|(Ââ)|(Ǎǎ)|Bb|Ch/cc|Dd|Ee|(Éé)|(Êê)|(Ěě)|Əə|(Ə́/ə́)|(Ə̂/ə̂)|(Ə̌/ə̌)|Ɛɛ|(Ɛ́/ɛ́)|(Ɛ̂/ɛ̂)|(Ɛ̌/ɛ̌)|Ff|Gg|Hh|Ii|(Íí)|(Îî)|(Ǐǐ)|Jj|Kk|Ll|Mm|(Ḿḿ)|Nn|(Ńń)|Ny/ny|Ŋŋ|Oo|(Óó)|(Ôô)|(Ǒǒ)|Ɔɔ|(Ɔ́/ɔ́)|(Ɔ̂/ɔ̂)|(Ɔ̌/ɔ̌)|Pp|Rr|Ss|Tt|Uu|(Úú)|(Ûû)|(Ǔǔ)|Vv|Ww|Yy|ʼ}}
==={{ĐM|ref}}===
*{{Chú thích web|entry=nkúūsē|entryurl=https://www.webonary.org/akoose/gf24b52ba-6597-4653-b2d9-136270df5d41/|editor=Robert Hedinger|work=Akoose–English Dictionary|year=2020|publisher=SIL International}}
=={{langname|bax}}==
==={{ĐM|symbol}}===
{{head|bax|Ký tự|chữ hoa|Ū}}
#Chữ cái ''[[u]]'' viết thường với dấu thanh trung ([[◌̄]]).
==={{ĐM|see}}===
*{{letters|lang=bax|sc=Latn|qual=Bảng chữ cái Latinh tiếng Bamum|Aa|(Áá)|(Àà)|(Ǎǎ)|(Āā)|(Ââ)|Bb|Ɓɓ|Dd|Gb/gb|Mb/mb|Ee|(Éé)|(Èè)|(Ěě)|(Ēē)|(Êê)|Ɛɛ|(Ɛ́/ɛ́)|(Ɛ̀/ɛ̀)|(Ɛ̌/ɛ̌)|(Ɛ̄/ɛ̄)|(Ɛ̂/ɛ̂)|Əə|(Ə́/ə́)|(Ə̀/ə̀)|(Ə̌/ə̌)|(Ə̄/ə̄)|(Ə̂/ə̂)|Ff|Gg|Ɣɣ|Ii|(Íí)|(Ìì)|(Ǐǐ)|(Īī)|(Îî)|Jj|Kk|Kp/kp|Ll|Mm|Ŋŋ|Nn|Ny/ny|Oo|(Óó)|(Òò)|(Ǒǒ)|(Ōō)|(Ôô)|Ɔɔ|(Ɔ́/ɔ́)|(Ɔ̀/ɔ̀)|(Ɔ̌/ɔ̌)|(Ɔ̄/ɔ̄)|(Ɔ̂/ɔ̂)|Pp|Rr|Ss|ʃ/sh|Tt|Uu|(Úú)|(Ùù)|(Ǔǔ)|(Ūū)|(Ûû)|Üü|(Ǘǘ)|(Ǜǜ)|(Ǚǚ)|(Ǖǖ)|(Ü̂/ü̂)|Ʉʉ|(Ʉ́/ʉ́)|(Ʉ̀/ʉ̀)|(Ʉ̌/ʉ̌)|(Ʉ̄/ʉ̄)(Ʉ̂/ʉ̂)|Vv|Ww|Yy|Zz|ʼ}}
=={{langname|bcq}}==
==={{ĐM|pron}}===
*{{IPA4|bcq|[u˧]}}
==={{ĐM|letter}}===
{{head|bcq|Chữ cái|chữ hoa|Ū}}
#Chữ Latinh {{l|bcq|u}} viết thường với dấu thanh điệu ◌̄.
==={{ĐM|see}}===
*{{letters|lang=bcq|sc=Latn|qual=Bảng chữ cái Latinh tiếng Bench|Aa|(A̋/a̋)|(Áá)|(Āā)|(Àà)|(Ȁȁ)|(Ǎǎ)|Bb|Cc|Ch/ch|Cʼ/cʼ|Dd|Ee|(E̋/e̋)|(Éé)|(Ēē)|(Èè)|(Ȅȅ)|(Ěě)|Gg|Hh|Ii|Kk|Ll|Mm|Nn|Oo|(Őő)|(Óó)|(Ōō)|(Òò)|(Ȍȍ)|(Ǒǒ)|Pp|P’/p’|Qq|Rr|Ss|Sh/sh|Tt|Ts/ts|Uu|(Űű)|(Úú)|(Ūū)|(Ùù)|(Ȕȕ)|(Ǔǔ)|Vv|Ww|Xx|Xh/xh|Xs/xs|X’/x’|Yy|Zh/zh|Zz|Z’/z’}}
=={{langname|brx}}==
==={{ĐM|alt}}===
*{{alter|brx|ú}}
==={{ĐM|pron}}===
*{{IPA4|brx|[uː]}}
==={{ĐM|letter}}===
{{head|brx|Chữ cái|chữ hoa|Ū}}
#{{n-g|Chữ cái Latinh viết thường biểu thị nguyên âm '''u dài''' trong tiếng Bodo.}}
==={{ĐM|see}}===
*{{letters|lang=brx|sc=Latn|qual=Bảng chữ cái Latinh tiếng Bodo|Aa|(Åå)|(Àà)|(Áá)|(Āā)|Bb|Cc|Dd|Ee|(Êê)|(Èè)|(Éé)|(Ēē)|Gg|Hh|Ii|(Íí)|(Īī)|Kk|Kh/kh|Ll|Mm|Nn|Ṅṅ|Oo|(Ôô)|(Ōō)|Ŏŏ|Pp|Ph/ph|Rr|(Ṛṛ)|Ss|Tt|Th/th|Uu|(Ŭŭ)|(Ùù)|(Úú)|(Ūū)|Ww|Yy|Zz}}
=={{langname|ckt}}==
==={{ĐM|letter}}===
{{head|ckt|Chữ cái|chữ hoa|Ū}}
#{{label|ckt|obsolete}} Chữ cái thứ 29 viết thường trong bảng chữ cái Latinh tiếng Chukot năm 1931.
==={{ĐM|see}}===
*{{letters|lang=ckt|sc=Latn|qual=Bảng chữ cái Latinh tiếng Chukot 1931-1937|Аа|Āā|Bb|Cc|Dd|Ее|Ēē|Əə|Ə̄/ə̄|Ff|Gg|Hh|Ii|Īī|Jj|Kk|Ll|Mm|Nn|Ŋŋ|Oo|Ōō|Pp|Qq|Rr|Ss|Tt|Uu|Ūū|Vv|Ww|Zz|Ьь}}
=={{langname|fmp}}==
==={{ĐM|symbol}}===
{{head|fmp|Ký tự|chữ hoa|Ū}}
#Chữ cái {{l|fmp|u}} viết thường với dấu thanh điệu trung ◌̄.
==={{ĐM|see}}===
*{{letters|lang=fmp|sc=Latn|qual=Bảng chữ cái Latinh tiếng Feʼfeʼ|Aa|(Áá)|(Āā)|(Àà)|(Ǎǎ)|(Ââ)|Ɑɑ|(Ɑ́/ɑ́)|(Ɑ̄/ɑ̄)|(Ɑ̀/ɑ̀)|(Ɑ̌/ɑ̌)|(Ɑ̂/ɑ̂)|Bb|Cc|Dd|Ee|(Éé)|(Ēē)|(Èè)|(Ěě)|(Êê)|Əə|(Ə́/ə́)|(Ə̄/ə̄)|(Ə̀/ə̀)|(Ə̌/ə̌)|(Ə̂/ə̂)|Ff|Gg|Gh/gh|Hh|Ii|(Íí)|(Īī)|(Ìì)|(Ǐǐ)|(Îî)|Jj|Kk|Ll|Mm|Nn|Ŋŋ|Oo|(Óó)|(Ōō)|(Òò)|(Ǒǒ)|(Ôô)|Pp|Ss|Sh/sh|Tt|Uu|(Úú)|(Ūū)|(Ùù)|(Ǔǔ)|(Ûû)|Ʉʉ|(Ʉ́/ʉ́)|(Ʉ̄/ʉ̄)|(Ʉ̀/ʉ̀)|(Ʉ̌/ʉ̌)|(Ʉ̂/ʉ̂)|Vv|Ww|Yy|Zz|Zh/zh|ʼ/'}}
=={{langname|haw}}==
==={{ĐM|pron}}===
*{{IPA4|haw|/ˈuː/}}
==={{ĐM|letter}}===
{{head|haw|Chữ cái|chữ hoa|Ū}}
#Chữ cái viết thường biểu thị nguyên âm ''[[u]]'' dài.
#:{{ux|haw|hōk'''ū'''|[[sao]]|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=haw|sc=Latn|qual=Bảng chữ cái Latinh tiếng Hawaii|Aa|(Āā)|Ee|(Ēē)|Ii|(Īī)|Oo|(Ōō)|Uu|(Ūū)|Hh|Kk|Ll|Mm|Nn|Pp|Ww|ʻ}}
==={{ĐM|etym}} 1===
{{dercat|haw|poz-oce-pro|pqe-pro|poz-cet-pro|poz-pro|inh=4}}
Từ {{inherited|haw|poz-pol-pro|*susu}} (đối chiếu {{cognate|mi|ū}}, {{cognate|to|huhu}}) từ {{inherited|haw|poz-oce-pro|*susu}} (đối chiếu với {{cognate|fj|sucu}}), từ {{inherited|haw|poz-pro|*susu}} (đối chiếu với {{cognate|ms|susu}}), từ {{inherited|haw|map-pro|*susu}} (đối chiếu với {{cognate|tl|suso}}).
===={{ĐM|n}}====
{{head|haw|Danh từ}}
#[[ngực|Ngực]].
#[[vú|Vú]].
====={{ĐM|der}}=====
*{{l|haw|waiū||sữa mẹ}}
==={{ĐM|etym}} 2===
Từ {{inherited|haw|poz-pol-pro|*su}}. Đối chiếu {{cognate|to|hū}}.
==={{ĐM|v}}===
{{head|haw|Động từ}}
#{{lb|haw|stative}} [[nhỏ giọt|Nhỏ giọt]].
#{{lb|haw|stative}} [[rỉ|Rỉ]] [[nước]].
====={{ĐM|der}}=====
*{{l|haw|[[hoʻoū]], [[hoʻū]]||[[ngâm]], [[dấp]], làm [[ướt]]}}
==={{ĐM|ref}}===
*{{cite-book| author=Pukui, Mary Kawena| author2=Elbert, Samuel H.| year=1957| title=English–Hawaiian Dictionary| chapter=ū| chapterurl=https://wehewehe.org/gsdl2.85/cgi-bin/hdict?e=q-11000-00---off-0hdict--00-1----0-10-0---0---0direct-10-ED--4--textpukuielbert%2ctextmamaka-----0-1l--11-haw-Zz-1---Zz-1-home-%c5%ab--00-4-1-00-0--4----0-0-11-00-2utfZz-8-00&a=d&d=D19619#hero-bottom-banner}}. Trong {{cite-web| work=Nā Puke Wehewehe ʻŌlelo Hawaiʻi| year=2003| url=http://www.wehewehe.org}}.
=={{langname|win}}==
==={{ĐM|pron}}===
*{{IPA4|win|[uː]}}
==={{ĐM|letter}}===
{{head|win|Chữ cái|chữ hoa|Ū}}
#{{label|win|Nebraska}} Chữ cái viết thường biểu thị nguyên âm ''[[u]]'' dài, tương ứng với ''{{l|win|uu}}'' tại Wisconsin.
#:{{ux|win|'''ū'''c|tr='''uu'''k|[[rìa]], [[cạnh]]|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=win|sc=Latn|qual=Bảng chữ cái Latinh tiếng Hocak|Aa|(Āā)|Ąą|(Ą̄/ą̄)|Bb|Cc|Ee|(Ēē)|Gg|Ğğ|Hh|Ii|(Īī)|Įį|(Į̄/į̄)|Jj|Kk|Mm|Nn|Oo|(Ōō)|Pp|Rr|Ss|Šš|Tt|Uu|(Ūū)|Ųų|(Ų̄/ų̄)|Ww|Xx|Yy|Zz|Žž|'}}
==={{ĐM|ref}}===
*{{Chú thích web|en|publisher=Ho-Chunk Nation|year=2026|entry=uu|entryurl=https://dictionary.hochunk.org/#/L/uu|work=Ho-Chunk Dictionary Online}}
*{{Chú thích sách|en|title=[https://web.archive.org/web/20210710171553/https://www.christianlehmann.eu/publ/ASSidUE21.pdf Hocąk-English/English-Hocąk Learner's Dictionary]|publisher=University of Erfurt|year=2006|page=36|author=Johannes Helmbrecht & Christian Lehmann}}
=={{langname|jab}}==
==={{ĐM|letter}}===
{{head|jab|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 30 viết thường trong bảng chữ cái Latinh tiếng Hyam.
#:{{quote|jab|S'''ū'''n na̱ ka̱ gywasmen na̱ ywut di gaar Nom ma̱ dzaam ma̱ di nyi, na̱yi nga̱yi shu, ka̱ na̱yi ka̱ shu, ka̱ na̱yi ku ri bo. Ka̱ ywut di gaar mo cu-hyong yikywarfaa di nkiseny gya̱set ghyi kpyob gha.|nguyền xin ân-điển và sự bình-an ban cho anh em từ nơi Đấng hiện có, đã có, và còn đến, cùng từ nơi bảy vì thần ở trước ngôi Ngài, ([[s:Khải huyền/1#1:4|Ma-thi-ơ 1:4]])}}
==={{ĐM|see}}===
*{{letters|lang=jab|sc=Latn|qual=Bảng chữ cái Latinh tiếng Hyam|Aa|Āā|Ǎǎ|A̱/a̱|Bb|Cc|Dd|Ee|Ēē|E̱/e̱|Ff|Gg|Hh|Ii|Ǐǐ|I̱/i̱|Jj|Kk|Ll|Mm|Nn|Oo|Ōō|Ǒǒ|Pp|Rr|Ss|Tt|Uu|Ūū|Vv|Ww|Yy|Zz}}
==={{ĐM|ref}}===
*{{Chú thích web|jab|author=Nigeria Bible Translation Trust|entryurl=https://www.bible.com/bible/2521/REV.1.HYAMNT|entry=Shun-ndaa Yoh 1|year=2017|work=Mbyeny Jok Nom di ho Hyam Ham ma̱}}
=={{langname|ifb}}==
==={{ĐM|letter}}===
{{head|ifb|Chữ cái|chữ hoa|Ū}}
#Biến thể chữ {{l|ifb|u}} trong bộ chữ Latinh tiếng Ifugao Batad.
#:{{ux|ifb|'''ū'''ban|[[tóc bạc]]|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=ifb|sc=Latn|qual=Bảng chữ cái Latinh tiếng Ifugao Batad|a|(ā)|b|d|e|(ē)|g|h|i|(ī)|k|l|m|n|o|(ō)|p|s|t|u|(ū)|w|y|ꞌ}}
==={{ĐM|ref}}===
*{{Chú thích web|entry=u|entryurl=https://www.webonary.org/batad-ifugao/browse/browse-vernacular/?key=ifb&letter=u&lang=en|editor=Leonard E. Newell|work=Batad Ifugao - English Dictionary|year=1993|publisher=Linguistic Society of the Philippines |location=Manila}}
*{{Chú thích web|work=[https://www.sil.org/system/files/reapdata/95/02/13/95021351436193586802650181872024268551/Ifugao_Batad_Orthography_Fact_Sheet__ifb___ifb_.pdf Ifugao Batad Orthography FactSheet ifb]|year=2012|location=Philippines}}
=={{langname|igl}}==
==={{ĐM|letter}}===
{{head|igl|Chữ cái|chữ hoa|Ū}}
#Chữ cái ''{{l|igl|u}}'' viết thường với thanh điệu cao trung ◌̄.
#:{{ux|igl|Íchámú-ógwúmẹ́l'''ū '''|[[chín]] [[trăm]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=igl|sc=Latn|qual=Bảng chữ cái Latinh tiếng Igala|native name=àmulú-ùkọ̀là|Aa|(Áá)|(Àà)|(Āā)|Bb|Ch/ch|Dd|Ee|(Éé)|(Èè)|(Ēē)|Ẹẹ|(Ẹ́/ẹ́)|(Ẹ̀/ẹ̀)|(Ẹ̄/ẹ̄)|Ff|Gg|Gb/gb|Gw/gw|Hh|Ii|(Íí)|(Ìì)|(Īī)|Jj|Kk|Kp/kp|Kw/kw|Ll|Mm|Nn|(Ṅṅ)|Ññ|Ñm/ñm|Ñw/ñw|Ny/ny|Oo|(Óó)|(Òò)|(Ōō)|Ọọ|(Ọ́/ọ́)|(Ọ̀/ọ̀)|(Ọ̄/ọ̄)|Pp|Rr|Tt|Uu|(Úú)|(Ùù)|(Ūū)|Ww|Yy}}
==={{ĐM|ref}}===
*{{Chú thích web|author=Kigala online|title=[https://kigalaonline.wordpress.com/category/vocabulary/ Vocabulary]|work=Wordpress|year=2019}}
=={{langname|ket}}==
==={{ĐM|pron}}===
*{{IPA4|ket|[uː]}}
==={{ĐM|letter}}===
{{head|ket|Chữ cái|chữ hoa|Ū}}
#{{label|ket|obsolete}} Chữ cái thứ 31 viết thường trong bảng chữ cái Latinh tiếng Ket thập niên 1930.
==={{ĐM|see}}===
*{{letters|lang=ket|sc=Latn|qual=Bảng chữ cái Latinh tiếng Ket thập niên 1930|Aa|Āā|Ææ|Bb|Çç|Dd|Ee|Ēē|Əə|Ff|Gg|Hh|Ҕҕ|Ii|Īī|Jj|Kk|Ll|Mm|Nn|Ņņ|Ŋŋ|Oo|Ōō|Pp|Qq|Rr|Ss|Şş|Tt|Uu|Ūū|Vv|Zz|Ƶƶ|Ьь}}
==={{ĐM|ref}}===
*{{Chú thích sách|author=Kotorova, Elizaveta & Andrey Nefedov (eds.)|year=2015|title=Comprehensive Ket Dictionary / Большой словарь кетского языка (2 vols)|publisher=Lincom Europa|location=Munich}}
=={{langname|kix}}==
==={{ĐM|pron}}===
*{{IPA4|kix|/u³³/}}
==={{ĐM|letter}}===
{{head|kix|Chữ cái|chữ hoa|Ū}}
#Chữ ''{{l|kix|u}}'' viết thường với dấu thanh điệu ◌̄.
#:{{ux|kix|y'''ū'''oh|[[ủn ỉn]]|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=kix|sc=Latn|qual=Bảng chữ cái Latinh tiếng Khiamniungan|Aa|(Āā)|(Àà)|Ch/ch|Ee|(Ēē)|(Èè)|Hh|Ii|(Īī)|(Ìì)|Jj|Kk|Kh/kh|Ll|Mm|Nn|Ng/ng|Ny/ny|Oo|(Ōō)|(Òò)|Pp|Ph/ph|Ss|Sh/sh|Tt|Th/th|Ts/ts|Tsh/tsh|Uu|(Ūū)|(Ùù)|Üü|(Ǖ/ǖ)|(Ǜ/ǜ)|Vv|Ww|Yy}}
=={{langname|naq}}==
==={{ĐM|pron}}===
*{{IPA4|naq|[uː]}}
==={{ĐM|letter}}===
{{head|naq|Chữ cái|chữ hoa|Ū}}
#Chữ cái Latinh viết thường biểu thị nguyên âm ''[[u]] dài''.
#:{{quote|naq|Tsî nē ǃh'''ū'''b ǃnân ge ǃ'''ū'''mû ǃhuniǀurib, bodelium ǃgâihamx'''ū'''-i tsî oniksǀuidi tsîna gere hōhe.|Vàng xứ nầy rất cao; đó lại có nhũ-hương và bích-ngọc. ([[s:Sáng thế Ký/2#2:12|Sáng thế Ký 2:12]])}}
==={{ĐM|ref}}===
*{{Chú thích web|naq|author=Bible Society in Namibia|entryurl=https://www.bible.com/bible/548/GEN.2.KKG20|entry=Genesis 2|year=2020|work=Khoekhoegowab}}
=={{langname|kub}}==
==={{ĐM|letter}}===
{{head|kub|Chữ cái|chữ hoa|Ū}}
#Chữ cái ''[[u]]'' viết thường với dấu thanh trung ([[◌̄]]).
#:{{quote|kub|Unde w'''ū''' tī kú bá isim-m skeb pú wū ame tí r'''ū'''rōb. Ame kō-m tī ame ú t'''ū'''nn fob apwā afxen-w'''ū''' bē.|Có Đấng quyền-phép hơn ta đến sau ta; ta không đáng cúi xuống mở dây giày Ngài. ([[s:Mác/1#1:7|Mác 1:7]])}}
===={{ĐM|see}}====
*{{letters|lang=kub|sc=Latn|qual=Bảng chữ cái Latinh tiếng Kutep|Aa|(Āā)|(Áá)|(Ââ)|Bb|Cc|Dd|Ee|(Ēē)|(Éé)|(Êê)|Ff|Gg|Hh|Ii|(Īī)|(Íí)|(Îî)|Jj|Kk|Ll|Mm|Nn|Oo|Pp|Rr|Ss|Tt|Uu|(Ūū)|(Úú)|(Ûû)|Vv|Ww|Xx|Yy|Zz}}
==={{ĐM|ref}}===
*{{Chú thích web|kub|author=Wycliffe Bible Translators, Inc. & The Nigeria Bible Translation Trust|entryurl=https://live.bible.is/bible/KUBTBL/MRK/1|entry=Kucangtsi 1|year=1995|work=Bible.is}}
=={{langname|ltg}}==
==={{ĐM|pron}}===
*{{IPA4|ltg|/uː/}}
==={{ĐM|letter}}===
{{head|ltg|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 32 viết thường trong bảng chữ cái Latinh tiếng Latgale.
#:{{ux|ltg|'''ū'''ga|[[quả]] [[mọng]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=ltg|sc=Latn|qual=Bảng chữ cái Latinh tiếng Latgale|Aa|Āā|Bb|Cc|Čč|Dd|Ee|Ēē|Ff|Gg|Ģģ|Hh|Ii|Yy|Īī|Jj|Kk|Ķķ|Ll|Ļļ|Mm|Nn|Ņņ|Oo|Ōō|Pp|Rr|Ss|Šš|Tt|Uu|Ūū|Vv|Zz|Žž}}
=={{langname|lv}}==
{{wikipedia|lv:}}
==={{ĐM|etym}}===
Được đề xuất năm 1908 trong chính tả tiếng Latvia mới và đưa vào giảng dạy từ năm 1909. Trước đó, tiếng Latvia được viết bằng chữ Đức Fraktur và đôi khi bằng chữ Kirin.
==={{ĐM|pron}}===
*{{lv-IPA|uː}}
==={{ĐM|letter}}===
{{head|lv|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 30 viết thường trong bảng chữ cái Latinh tiếng Latvia, gọi là chữ '''{{l|lv|garais u}}'''.
#:{{ux|lv|[[jūra#Tiếng_Latvia|j'''ū'''ra]]|[[biển]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=lv|sc=Latn|qual=Bảng chữ cái Latinh tiếng Latvia}}
=={{langname|lt}}==
{{wikipedia|lt:}}
==={{ĐM|pron}}===
*{{IPA4|lt|/uː/}}
==={{ĐM|letter}}===
{{head|lt|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 29 viết thường trong bảng chữ cái Latinh tiếng Litva.
#:{{ux|lt|[[sūnus#Tiếng_Litva|s'''ū'''nus]]|[[con trai]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=lt|sc=Latn|qual=Bảng chữ cái Latinh tiếng Litva|Aa|Ąą|Bb|Cc|Čč|Dd|Ee|Ęę|Ėė|Ff|Gg|Hh|Ii|Įį|Yy|Jj|Kk|Ll|Mm|Nn|Oo|Pp|Rr|Ss|Šš|Tt|Uu|Ųų|Ūū|Vv|Yy|Zz|Žž}}
=={{langname|liv}}==
==={{ĐM|pron}}===
*{{qualifier|âm tiết}} {{liv-IPA|uː}}
==={{ĐM|letter}}===
{{head|liv|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 36 viết thường trong bảng chữ cái Latinh tiếng Livonia.
#:{{ux|liv|'''ū'''ļ|[[môi]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=liv|sc=Latn|qual=Bảng chữ cái Latinh tiếng Livonia}}
=={{langname|mi}}==
==={{ĐM|pron}}===
*{{IPA4|mi|/uː/|[uː]}}
==={{ĐM|letter}}===
{{head|mi|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 17 viết thường trong bảng chữ cái Latinh tiếng Maori.
#:{{ux|mi|{{l|mi|mātai mat'''ū'''}}|[[hóa học]]|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=mi|sc=Latn|qual=Bảng chữ cái Latinh tiếng Maori|Aa|Āā|Ee|Ēē|Hh|Ii|Īī|Kk|Mm|Nn|Oo|Ōō|Pp|Rr|Tt|Uu|Ūū|Ww|Ng/ng|Wh/wh}}
==={{ĐM|etym}} 1===
Từ {{inherited|mi|poz-pol-pro|*susu}} (đối chiếu {{cognate|haw|ū}}, {{cognate|to|huhu}}) từ {{inherited|mi|poz-oce-pro|*susu}} (đối chiếu với {{cognate|fj|sucu}}), từ {{inherited|mi|poz-pro|*susu}} (đối chiếu với {{cognate|ms|susu}}), từ {{inherited|mi|map-pro|*susu}} (đối chiếu với {{cog|tl|suso}}).
===={{ĐM|pron}}====
*{{mi-IPA|ū|stress='}}
===={{ĐM|n}}====
{{head|mi|Danh từ}}
#[[ngực|Ngực]].
#[[vú|Vú]].
====={{ĐM|der}}=====
*{{l|mi|waiū||sữa mẹ}}
==={{ĐM|etym}} 2===
{{rfe|mi}}
===={{ĐM|v}}====
{{head|mi|Động từ}}
#[[đánh|Đánh]] [[trúng]].
#[[cập|Cập]] [[bến]], [[lên bờ]].
#[[tuân thủ|Tuân thủ]].
#{{label|mi|stative}} [[cố định|Cố định]], [[vững chắc]].
==={{ĐM|ref}}===
*{{Chú thích web|work=Te Aka Māori Dictionary|entryurl=https://maoridictionary.co.nz/search?idiom=&phrase=&proverb=&loan=&histLoanWords=&keywords=%C5%AB|entry=ū|year=2003-2023}}
=={{langname|mh}}==
==={{ĐM|pron}}===
*{{IPA4|mh|[ʌ]}}
==={{ĐM|letter}}===
{{head|mh|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 23 viết thường bảng chữ cái Latinh tiếng Marshall.
#:{{ux|mh|'''ū'''l'''ū'''l|[[rìu]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=mh|sc=Latn|qual=Bảng chữ cái Latinh tiếng Marshall|Aa|Āā|Bb|Dd|Ee|Ii|Jj|Kk|Ll|Ļļ|Mm|M̧/m̧|Nn|Ņņ|N̄/n̄|Oo|O̧/o̧|Ōō|Pp|Rr|Tt|Uu|Ūū|Ww}}
==={{ĐM|ref}}===
*{{Chú thích web|en|work=Marshallese-English Online Dictionary|entryurl=https://www.trussel2.com/MOD/MED2U.htm|entry=u|year=2023}}
=={{langname|nan-hbl}}==
{{zh-see|有|poj}}
=={{langname|ruq}}==
==={{ĐM|pron}}===
*{{IPA4|ruq|[uː]}}
==={{ĐM|letter}}===
{{head|ruq|Chữ cái|chữ hoa|Ū}}
#Chữ cái viết thường biểu thị nguyên âm ''[[u]]'' dài.
==={{ĐM|see}}===
*{{letters|lang=ruq|sc=Latn|qual=Bảng chữ cái Latinh tiếng Moglena-Rumani|Aa|(Āā)|Ăă|Bb|Cc|Dd|(Dz/dz)|(Dž/dž)|(D̦/d̦)|Ee|(Ēē)|(Ęę)|Ff|Gg|(Ǧǧ)|Hh|i̭/i|(Īī)|Jj|Kk|Ll|(Łł)|L’/l’|Mm|Nn|Ńń|Oo|(Ōō)|(Ǫǫ)|Ọọ|Pp|Qq|Rr|Ss|Șș|Tt|(Tš/tš)|Țț|Uu|(Ūū)|Vv|Ww|Xx|Yy|Zz}}
=={{langname|ja}}==
==={{ĐM|rom}}===
{{ja-romaji}}
#{{ja-romanization of|うう}}
#{{ja-romanization of|うー}}
#{{ja-romanization of|ウー}}
=={{langname|caq}}==
==={{ĐM|pron}}===
*{{IPA4|caq|[uː]}}
==={{ĐM|letter}}===
{{head|caq|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 31 viết thường trong bảng chữ cái Latinh tiếng Nicobar Car.
#:{{ux|caq|{{l|caq|'''ū'''ch-ngö-rĕ}}|[[ngồi]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=caq|sc=Latn|qual=Bảng chữ cái Latinh tiếng Nicobar Car|Aa|Āā|Ch/ch|Ĕĕ|Ēē|Ee|Ëë|Ff|Hh|Ii|Īī|Kk|Ll|Mm|Nn|Ng/ng|Ny/ny|Ṅṅ|Oo|Ōō|Òò|Ôô|Öö|Öö/öö|Pp|Rr|Ṛṛ|Ss|Tt|Uu|Ūū|Vv|Yy}}
==={{ĐM|ref}}===
*{{Chú thích web|caq|author=Bible Society of India|entryurl=https://www.bible.com/bible/1060/RUT.1.CANIBSI|entry=RŪT 1|work=TÖHET LĪPÖRE (Re-edited) Bible (BSI)|year=2024}}
=={{langname|nik}}==
==={{ĐM|pron}}===
*{{IPA4|nik|[uː]}}
==={{ĐM|letter}}===
{{head|nik|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 31 viết thường trong bảng chữ cái Latinh tiếng Nicobar Nam.
#:{{ux|nik|[[tölūi#Tiếng_Nicobar_Nam|töl'''ū'''i]]|[[chuối]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=nik|sc=Latn|qual=Bảng chữ cái Latinh tiếng Nicobar Nam|Aa|Āā|Ch/ch|Ĕĕ|Ēē|Ee|Ëë|Ff|Hh|Ii|Īī|Kk|Ll|Mm|Nn|Ng/ng|Ny/ny|Ṅṅ|Oo|Ōō|Òò|Ôô|Öö|Öö/öö|Pp|Rr|Ṛṛ|Ss|Tt|Uu|Ūū|Vv|Yy}}
=={{langname|ncb}}==
==={{ĐM|pron}}===
*{{IPA4|ncb|[uː]}}
==={{ĐM|letter}}===
{{head|ncb|Chữ cái}}
#Chữ cái Latinh viết thường thể hiện nguyên âm thứ 9 trong tiếng Nicobar Trung.
#:{{ux|ncb|{{l|ncb|y'''ū'''e}}|[[ruồi]] [[nhà]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=ncb|sc=Latn|qual=Chữ Latinh tiếng Nicobar Trung|a/ā|e/ë|ĕ/ē|eu/eū|i/ī|o/ō|ò/ô|ö/öö|u/ū|ea|eö|euö|iö|oö|ua|uö|eaṅ|euöṅ|iöṅ|uaṅ|uöṅ|ch|f|h|k|ḵ|l|m|n|ng|ny|p|r|s|t|v|y}}
=={{langname|niu}}==
==={{ĐM|pron}}===
*{{IPA4|niu|[uː]}}
==={{ĐM|letter}}===
{{head|niu|Chữ cái|chữ hoa|Ū}}
#Chữ cái viết thường biểu thị nguyên âm ''[[u]]'' dài.
#:{{ux|niu|t'''ū'''mea|[[xám]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=niu|sc=Latn|qual=Bảng chữ cái Latinh tiếng Niue|Aa|(Āā)|Ee|(Ēē)|Ii|(Īī)|Oo|(Ōō)|Uu|(Ūū)|Ff|Gg|Hh|Kk|Ll|Mm|Nn|Pp|Tt|Vv|Rr|Ss}}
==={{ĐM|ref}}===
*{{Chú thích sách|en|author=Niue, University of Hawaii at Manoa. Dept. of Linguistics|page=[https://books.google.com/books?id=hOaGrwSRBMIC&pg=PA336 336]|title=Niue Language Dictionary|year=1997|publisher=University of Hawaii Press|isbn=9780824819330}}
=={{langname|bud}}==
==={{ĐM|symbol}}===
{{head|bud|Ký tự|chữ hoa|Ū}}
#Chữ {{l|bud|u}} viết thường với thanh bằng.
#:{{ux|bud|yùk'''ū'''|[[nhảy]]|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=bud|sc=Latn|qual=Bảng chữ cái Latinh tiếng Ntcham|Aa|(Áá)|(Àà)|Bb|(B́/b́)|Cc|Dd|Ee/ee|(Ée/ée)|Èe/èe|Ff|Gg|Gb/gb|Ii|(Íí)|(Ìì)|Jj|Kk|Kp/kp|Ll|(Ĺĺ)|Mm|(Ḿḿ)|Nn|(Ńń)|Ny/ny|Ŋŋ|Ŋm/ŋm|Oo/oo|(Óo/óo)|(Òo/òo)|Ɔɔ|(Ɔ́/ɔ́)|(Ɔ̀/ɔ̀)|Pp|Ss|Tt|Uu|(Úú)|(Ùù)|Ww|Yy}}
==={{ĐM|ref}}===
*{{Chú thích web|entry=yùkū, yùkufī, yùkū|entryurl=https://www.webonary.org/ntcham/gdbe0aacd-221e-4402-8d81-685d771d9471/?lang=en|editor=Samuel Kpagheri|work=Ntcham – English Dictionary|year=2019|publisher=SIL International}}
=={{langname|pi}}==
==={{ĐM|alt sc}}===
{{pi-alt}}
==={{ĐM|pron}}===
*{{IPA4|pi|[uː]}}
==={{ĐM|letter}}===
{{head|pi|Chữ cái|chữ hoa|Ū}}
# {{n-g|Nguyên âm thứ 6 trong tiếng Pali bằng chữ Latinh viết thường.}}
#:{{ux|pi|{{l|pi|abhir'''ū'''pa}}|[[đẹp]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=pi|sc=Latn|qual=Chữ Latinh tiếng Pali|Aa|Āā|Ii|Īī|Uu|Ūū|Ee|Oo|Ṃṃ|Kk|Kh/kh|Gg|Gh/gh|Ṅṅ|Cc|Ch/ch|Jj|Jh/jh|Ññ|Ṭṭ|Ṭh/ṭh|Ḍḍ|Ḍh/ḍh|Ṇṇ|Tt|Th/th|Dd|Dh/dh|Nn|Pp|Ph/ph|Bb|Bh/bh|Mm|Yy|Rr|Ll|Ḷḷ|Vv|Ss|Hh}}
=={{langname|prg}}==
==={{ĐM|pron}}===
*{{IPA4|prg|[uː]}}
==={{ĐM|letter}}===
{{head|prg|Chữ cái|chữ hoa|Ū}}
#Chữ cái viết thường biểu thị nguyên âm ''[[u]]'' dài và nhấn.
#:{{ux|prg|la'''ū'''ws|[[sư tử]]|inline=1}}
==={{ĐM|ref}}===
*[[b:en:Prussian/Pronunciation|Prussian/Pronunciation]]
=={{langname|rap}}==
==={{ĐM|pron}}===
*{{IPA4|rap|[uː]}}
==={{ĐM|letter}}===
{{head|rap|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 17 viết thường trong bảng chữ cái Latinh tiếng Rapa Nui.
==={{ĐM|see}}===
*{{letters|lang=rap|sc=Latn|qual=Bảng chữ Latinh tiếng Rapa Nui|Aa|Āā|Ee|Ēē|Hh|Ii|Īī|Kk|Mm|Nn|Ŋŋ|(Gg)|Oo|Ōō|Pp|Rr|Tt|Uu|Ūū|Vv|ʻ’|Ġġ}}
=={{langname|rar}}==
==={{ĐM|pron}}===
*{{IPA4|rar|[aː]}}
==={{ĐM|letter}}===
{{head|rar|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 18 viết thường trong bảng chữ cái Latinh tiếng Rarotonga.
#:{{ux|rar|{{l|rar|t'''ū'''t'''ū''' mata}}|[[mặt]]|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=rar|sc=Latn|qual=Bảng chữ cái Latinh tiếng Rarotonga|Aa|Āā|Ee|Ēē|Ng/ng|Hh|Ii|Īī|Kk|Mm|Nn|Oo|Ōō|Pp|Rr|Tt|Uu|Ūū|Vv|'}}
=={{langname|rgn}}==
==={{ĐM|pron}}===
*{{IPA4|rgn|[ˈuː]}}
==={{ĐM|letter}}===
{{head|rgn|Chữ cái|chữ hoa|Ū}}
#Chữ cái viết thường biểu thị nguyên âm ''[[u]]'' dài nhấn.
#:{{ux|rgn|dep'''ū'''|[[sau]], [[rồi]]|inline=1}}
=={{langname|sml}}==
==={{ĐM|pron}}===
*{{IPA4|sml|[uː]}}
==={{ĐM|letter}}===
{{head|sml|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 24 viết thường trong trong bảng chữ cái Latinh tiếng Sama Trung.
#:{{ux|sml|'''ū'''ng|[[mũi]]|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=sml|sc=Latn|qual=Bảng chữ cái Latinh tiếng Sama Trung|Āā|Aa|Bb|Cc|Dd|Ēē|Ee|Gg|Hh|Īī|Ii|Jj|Kk|Ll|Mm|Ng/ng|Nn|Ōō|Oo|Pp|Rr|Ss|Tt|Ūū|Uu|Ww|Yy}}
==={{ĐM|ref}}===
*{{Chú thích web|en|author=SIL Philippines|work=[https://sil-philippines-languages.org/prog/sml/dict/index-english/index.htm Central Sinama - English Dictionary]|entry=ū|year=Work in progress}}
*{{Chú thích web|sml|author=Wycliffe Bible Translators, Inc.|work=Kitab Injil and Kitab Awal-Jaman|entry=Panagna'an 2|year=2008|entryurl=https://www.bible.com/bible/2394/GEN.2.SML}}
=={{langname|sm}}==
==={{ĐM|pron}}===
*{{IPA4|sm|[uː]}}
==={{ĐM|letter}}===
{{head|sm|Chữ cái|chữ hoa|Ū}}
#Chữ cái viết thường biểu thị nguyên âm ''[[u]] dài''.
#:{{ux|sm|[[w:sm:Mūsika|m'''ū'''sika]]|[[âm nhạc]]|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=sm|sc=Latn|qual=Bảng chữ cái Latinh tiếng Samoa|Aa|(Āā)|Ee|(Ēē)|Ii|(Īī)|Oo|(Ōō)|Uu|(Ūū)|Ff|Gg|Ll|Mm|Nn|Pp|Ss|Tt|Vv|Hh|Kk|Rr|‘}}
==={{ĐM|ref}}===
*{{Chú thích sách|author=George Pratt|title=A Grammar and Dictionary of the Samoan Language|year=1878|publisher=Trübner & Company|pageurl=https://books.google.com/books?id=1vsrAAAAYAAJ&pg=PA367|page=367}}
=={{langname|sgs}}==
==={{ĐM|pron}}===
*{{IPA4|sgs|[uː]|[ʲuː]}}
==={{ĐM|letter}}===
{{head|sgs|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 29 viết thường trong bảng chữ cái Latinh tiếng Samogitia, gọi là chữ ''{{l|sgs|ėlguojė ū}}''.
#:{{ux|sgs|[[w:bat-smg:Jūra|j'''ū'''ra]]|[[biển]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=sgs|sc=Latn|qual=Bảng chữ cái Latinh tiếng Samogitia|Aa|Āā|Bb|Cc|Čč|Dd|Ee|Ēē|Ėė|Ė̄/ė̄|Ff|Gg|Hh|Ii|Īī|Jj|Kk|Ll|Mm|Nn|Oo|Ōō|Pp|Rr|Ss|Šš|Tt|Uu|Ūū|Vv|Zz|Žž}}
=={{langname|sii}}==
==={{ĐM|pron}}===
*{{IPA4|sii|[uː]}}
==={{ĐM|letter}}===
{{head|sii|Chữ cái}}
#Chữ cái Latinh viết thường thể hiện nguyên âm thứ 14 trong tiếng Shompen.
==={{ĐM|see}}===
*{{letters|lang=sii|sc=Latn|qual=Chữ Latinh tiếng Shompen|a|e|ɛ/E|i|o|ɔ/O|u|ā|ē|ɛ̄|ī|ō|ɔ̄|ū|ã|ẽ|ɛ̃|ĩ|õ|ɔ̃|ũ|ā̃|ē̃|ɛ̄̃|ī̃|ō̃|ɔ̄̃|ū̃|b|bh|c|d|ɸ|g|gh|ɣ|h|j|k|kh|l|m|n|ŋ/ṅ|ɲ/ñ|p|ph|t|th|w|x|y|ʔ/?}}
==={{ĐM|ref}}===
*{{Chú thích sách|en|author=Roger Blench|year=2007|title=The language of the Shom Pen: a language isolate in the Nicobar islands|url=https://web.archive.org/web/20241212072542/https://www.rogerblench.info/Language/Isolates/Shompen%20paper.pdf}}
=={{langname|ty}}==
==={{ĐM|pron}}===
*{{IPA4|ty|[uː]}}
==={{ĐM|letter}}===
{{head|ty|Chữ cái|chữ hoa|Ū}}
#Chữ cái viết thường biểu thị nguyên âm ''[[u]] dài''.
#:{{ux|ty|[[w:ty:Pūrau|p'''ū'''rau]]|{{w|tra làm chiếu}}|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=ty|sc=Latn|qual=Bảng chữ cái Latinh tiếng Tahiti|Aa|(Āā)|Ee|(Ēē)|Ff|Hh|Ii|(Īī)|Mm|Nn|Oo|(Ōō)|Pp|Rr|Tt|Uu|(Ūū)|Vv|ʼ}}
=={{langname|tsg}}==
==={{ĐM|pron}}===
*{{IPA4|tsg|[uː]}}
==={{ĐM|letter}}===
{{head|tsg|Chữ cái|chữ hoa|Ū}}
#Chữ cái viết thường biểu thị nguyên âm ''[[u]] dài''.
#:{{ux|tsg|'''ū'''an|[[gối]]|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=tsg|sc=Latn|qual=Bảng chữ cái Latinh tiếng Tausug|Aa|(Āā)|Bb|Dd|Gg|Hh|Ii|(Īī)|Jj|Kk|Ll|Mm|Nn|Ng/ng|Ny/ny|Pp|Rr|Ss|Tt|Uu|(Ūū)|Ww|Yy|’}}
==={{ĐM|etym}}===
===={{ĐM|n}}====
{{tsg-noun|j=+}}
#[[đầu|Đầu]].
====={{ĐM|der}}=====
{{col3|tsg|ūan|ūhan|ū bala'|ū ista'|ū-atay|mag'ūan|umūan|ūanan}}
==={{ĐM|ref}}===
*{{Chú thích web|entry=u|entryurl=https://www.webonary.org/tausug/browse/browse-vernacular/?key=tsg&letter=u&lang=en|author=Kabtangan Iban Maana|work=Tausug-English Dictionary|year=2018|publisher=SIL International}}
=={{langname|tkl}}==
==={{ĐM|pron}}===
*{{IPA4|tkl|[uː]}}
==={{ĐM|letter}}===
{{head|tkl|Chữ cái|chữ hoa|Ū}}
#Chữ cái viết thường biểu thị nguyên âm ''[[u]] dài''.
#:{{ux|tkl|fīlēm'''ū'''|[[yên tĩnh]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=tkl|sc=Latn|qual=Bảng chữ cái Latinh tiếng Tokelau|Aa|(Āā)|Ee|(Ēē)|Ii|(Īī)|Oo|(Ōō)|Uu|(Ūū)|Ff|Gg|Kk|Ll|Mm|Nn|Pp|Hh|Tt|Vv}}
=={{langname|to}}==
==={{ĐM|pron}}===
*{{IPA4|to|[uː]}}
==={{ĐM|letter}}===
{{head|to|Chữ cái|chữ hoa|Ū}}
#Chữ cái viết thường biểu thị nguyên âm ''[[u]] dài''.
#:{{ux|to|[[w:to:Lūsia|L'''ū'''sia]]|[[Nga]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=to|sc=Latn|qual=Bảng chữ cái Latinh tiếng Tonga|Aa|(Āā)|Ee|(Ēē)|Ff|Hh|Ii|(Īī)|Kk|Ll|Mm|Nn|Ng/ng|Oo|(Ōō)|Pp|Ss|Tt|Uu|(Ūū)|Vv|’}}
=={{langname|ude}}==
{| class="floatright wikitable" style="text-align:center;"
|-
! Kirin
| [[ӯ#Tiếng_Udihe|ӯ]]
|-
! Latinh
| {{pn}}
|-
|}
==={{ĐM|pron}}===
*{{IPA4|ude|[uː]}}
==={{ĐM|letter}}===
{{head|ude|Chữ cái|chữ hoa|Ū}}
#{{label|ude|obsolete}} Chữ cái thứ 30 viết thường trong bảng chữ cái Latinh tiếng Udihe năm 1931-1937.
#:{{ux|ude|s'''ū'''|tr={{l|ude|с'''ӯ'''}}|[[mặt trời]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=ude|sc=Latn|qual=Bảng chữ cái Latinh tiếng Udihe năm 1931-1937|Aa|Āā|Bв|Єє|Dd|Ʒʒ|Ee|Ēē|Ææ|Ff|Gg|Hh|Ii|Īī|Jj|Kk|Ll|Mm|Nn|Ņņ|Ŋŋ|Oo|Ōō|Өө|Pp|Rr|Ss|Tt|Uu|Ūū|Ww|Xx|Yy|Zz|’}}
==={{ĐM|ref}}===
*{{Chú thích sách|ru|author=М. Д. Симонов, В. Т. Кялундзюга|year=1998|title=Словарь удэгейского языка (хорский диалект). Препринт}}
=={{langname|yka}}==
==={{ĐM|pron}}===
*{{IPA4|yka|[uː]}}
==={{ĐM|letter}}===
{{head|yka|Chữ cái|chữ hoa|Ū}}
#Chữ cái thứ 24 viết thường trong trong bảng chữ cái Latinh tiếng Yakan.
#:{{quote|yka|'''ū'''ng-'''ū'''ng|{{w|cá cam thoi}}|inline=1}}
===={{ĐM|see}}====
*{{letters|lang=yka|sc=Latn|qual=Bảng chữ cái Latinh tiếng Yakan|Āā|Aa|Bb|Cc|Dd|Ēē|Ee|Gg|Hh|Īī|Ii|Jj|Kk|Ll|Mm|Ng/ng|Nn|Ōō|Oo|Pp|Rr|Ss|Tt|Ūū|Uu|Ww|Yy}}
==={{ĐM|n}}===
{{head|yka|Danh từ}}
#[[cán|Cán]], [[chuôi]].
==={{ĐM|v}}===
{{head|yka|Động từ}}
#[[lắp|Lắp]] [[cán]], [[chuôi]].
==={{ĐM|ref}}===
*{{Chú thích web|author=SIL Philippines|work=[https://philippines.sil.org/resources/online_resources/yka Yakan-English Dictionary]|entry=ū|year=2013}}
=={{langname|yo}}==
==={{ĐM|pron}}===
*{{yor-IPA|ū}}
==={{ĐM|letter}}===
{{head|yo|Chữ cái|chữ hoa|Ū}}
#Chữ cái ''[[U]]'' viết thường với thanh trung ([[◌̄]]).
===={{ĐM|see}}====
*{{letters|lang=yo|sc=Latn|qual=Bảng chữ cái Latinh tiếng Yoruba tại Nigeria|native name=lẹ́tà|Aa|(Áá)|(Àà)|(Āā)|Bb|Dd|Ee|(Éé)|(Èè)|(Ēē)|Ẹẹ|(Ẹ́/ẹ́)|(Ẹ̀/ẹ̀)|(Ẹ̄/ẹ̄)|Ff|Gg|Gb/gb|Hh|Ii|(Íí)|(Ìì)|(Īī)|Jj|Kk|Ll|Mm|(Ḿ/ḿ)|(M̀/m̀)|(M̄/m̄)|Nn|(Ń/ń)|(Ǹ/ǹ)|(N̄/n̄)|Oo|(Óó)|(Òò)|(Ōō)|Ọọ|(Ọ́/ọ́)|(Ọ̀/ọ̀)|(Ọ̄/ọ̄)|Pp|Rr|Ss|Ṣṣ|Tt|Uu|(Úú)|(Ùù)|(Ūū)|Ww|Yy}}
*{{letters|lang=yo|sc=Latn|qual=Bảng chữ cái Latinh tiếng Yoruba tại Benin|lɛ́tà|Aa|Bb|Dd|Ee|Ɛɛ|Ff|Gg|Gb/gb|Hh|Ii|Jj|Kk|Kp/kp|Ll|Mm|Nn|Oo|Ɔɔ|Pp|Rr|Ss|Sh/sh|Tt|Uu|Ww|Yy}}
==={{ĐM|ref}}===
*{{Chú thích sách|en|title=Dictionary of the Yoruba language|author=Thomas Jefferson Bowen|year=1858|location=Washington|publisher=Smithsonian Institution|page=[https://archive.org/details/grammardictionar00bowerich/page/89 89]|}}
[[Thể loại:Khối ký tự Latin Extended-A|6B]]
2py639ol12slj6k5mmwnnyi5q79ud06
cacahuate
0
392391
2344287
2026-04-11T14:00:06Z
Kelly zhrm
58416
Trang mới: “=={{langname|es}}== [[Image:ARS peanuts.jpg|thumb|cacahuates]] ==={{ĐM|pron}}=== {{es-pr}} ==={{ĐM|n}}=== {{es-noun|m}} # {{lb|es|Honduras|Mexico}} {{alt form|es|cacahuete|t=đậu phộng, lạc}} ===={{ĐM|drv}}==== {{col|es|cacahuatero}} ==={{ĐM|further}}=== * {{R:es:DRAE}}”
2344287
wikitext
text/x-wiki
=={{langname|es}}==
[[Image:ARS peanuts.jpg|thumb|cacahuates]]
==={{ĐM|pron}}===
{{es-pr}}
==={{ĐM|n}}===
{{es-noun|m}}
# {{lb|es|Honduras|Mexico}} {{alt form|es|cacahuete|t=đậu phộng, lạc}}
===={{ĐM|drv}}====
{{col|es|cacahuatero}}
==={{ĐM|further}}===
* {{R:es:DRAE}}
7kos0bokavx3eo1cynw4s3ok6yjhzwf
2344288
2344287
2026-04-11T14:01:21Z
Kelly zhrm
58416
2344288
wikitext
text/x-wiki
=={{langname|es}}==
[[Image:ARS peanuts.jpg|thumb|cacahuates]]
==={{ĐM|pron}}===
{{es-pr}}
==={{ĐM|n}}===
{{es-noun|m}}
# {{lb|es|Honduras|Mexico}} {{alt form|es|cacahuete|t=đậu phộng, củ lạc}}
===={{ĐM|drv}}====
{{col|es|cacahuatero}}
==={{ĐM|further}}===
* {{R:es:DRAE}}
sroq7x7hx8qm0i3puzdm710dmkwe4lk
𡬕
0
392392
2344290
2026-04-11T14:16:08Z
Hiyuune
50834
+ mul
2344290
wikitext
text/x-wiki
{{character info}}
=={{langname|mul}}==
==={{section|han}}===
{{Han char|rn=40|rad=宀|as=22|sn=25|four=|canj=|ids=⿱𫲽𦓈}}
===={{section|ref}}====
* {{Han ref|kx=0293.281|dkj=|dj=|hdz=20959.210|uh=21B15}}
egbv2z6by94e1zxqriqbeym6bivzf2e
Thể loại:Mục từ có chứa nhiều từ tiếng Bhumij
14
392393
2344297
2026-04-11T17:11:47Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344297
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:aav-bhu:Dụng cụ
14
392394
2344299
2026-04-11T17:13:01Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344299
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:aav-bhu:Danh sách chủ đề thuộc nhóm loại hình
14
392395
2344300
2026-04-11T17:13:15Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344300
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:aav-bhu:Tất cả chủ đề
14
392396
2344301
2026-04-11T17:13:32Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344301
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:aav-bhu:Công nghệ
14
392397
2344302
2026-04-11T17:14:06Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344302
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:aav-bhu:Danh sách chủ đề thuộc nhóm liên quan
14
392398
2344303
2026-04-11T17:14:58Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344303
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
廣二
0
392399
2344306
2026-04-12T01:05:47Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|こう|じ}} ==={{ĐM|pr-noun}}=== {{ja-pos|proper|こうじ}} # {{given name|ja|nam|sort=こうじ}}”
2344306
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|こう|じ}}
==={{ĐM|pr-noun}}===
{{ja-pos|proper|こうじ}}
# {{given name|ja|nam|sort=こうじ}}
tm0nxh62bca5dx24alzt5pyceh4zq7l
Mô đun:etymon/data/text allowed
828
392400
2344308
2026-04-12T01:13:21Z
TheHighFighter2
42988
Trang mới: “--[=[ Languages and families that may use the {{etymon}} `text=` parameter (language-community consensus). ]=] return { -- Mode: "off" = disabled, "warn" = warn only, "error" = enforce. default_mode = "warn", langs = { ["bg"] = true, ["bnt-sab-pro"] = true, ["cs"] = true, ["en"] = true, ["fa"] = true, ["hrx"] = true, ["hsb"] = true, ["iir-pro"] = true, ["jbo"] = true, ["jdt"] = true, ["la"] = true, ["ota"] = true, ["sk"] = true, ["sw"] = tr…”
2344308
Scribunto
text/plain
--[=[
Languages and families that may use the {{etymon}} `text=` parameter (language-community consensus).
]=]
return {
-- Mode: "off" = disabled, "warn" = warn only, "error" = enforce.
default_mode = "warn",
langs = {
["bg"] = true,
["bnt-sab-pro"] = true,
["cs"] = true,
["en"] = true,
["fa"] = true,
["hrx"] = true,
["hsb"] = true,
["iir-pro"] = true,
["jbo"] = true,
["jdt"] = true,
["la"] = true,
["ota"] = true,
["sk"] = true,
["sw"] = true,
["tg"] = true,
["tl"] = true,
["tr"] = true,
["uk"] = true,
["uz"] = true,
["zlw-ocs"] = true,
["zlw-osk"] = true,
},
families = {
["ber"] = true, -- Berber
["dra"] = true, -- Dravidian
["inc"] = true, -- Indo-Aryan
["iir-nur"] = true, -- Nuristani
["roa-gap"] = true, -- Galician-Portuguese
["sem-ara"] = true, -- Aramaic
["sem-arb"] = true, -- Arabic
["tup"] = true, -- Tupian
["zlw-lch"] = true, -- Lechitic
},
}
er27mwwc9rh50dmoqbfrik3bz7b91lb
وزير اعظم
0
392401
2344309
2026-04-12T01:17:26Z
Hiyuune
50834
+ sd
2344309
wikitext
text/x-wiki
=={{langname|sd}}==
==={{section|etym}}===
{{bor+|sd|fa-cls|وَزِیرِ اَعْظَم}}.
==={{section|pron}}===
* {{IPA4|sd|[wə.ziː.ɾeː.ə.zəm]}}
==={{section|n}}===
{{sd-noun|g=m|وَزِيرِ اَعظَم}}
# [[thủ tướng|Thủ tướng]].
#: {{syn|sd|پْرَڌانْ مَنْترِي|ll=India}}
==={{section|further}}===
* {{R:sd:SLA|Prime minister}}
{{topics|sd|Government|Leaders|Occupations|People}}
7ftudpdaykhn8nqw2j152dto1fhch08
2344310
2344309
2026-04-12T01:18:14Z
Hiyuune
50834
/* Tiếng Sindh */
2344310
wikitext
text/x-wiki
=={{langname|sd}}==
==={{section|etym}}===
{{bor+|sd|fa-cls|وَزِیرِ اَعْظَم}}.
==={{section|pron}}===
* {{IPA4|sd|[wə.ziː.ɾeː.ə.zəm]}}
==={{section|n}}===
{{sd-noun|g=m|وَزِيرِ اَعظَم}}
# [[thủ tướng|Thủ tướng]].
#: {{syn|sd|پْرَڌانْ مَنْترِي|ll=India}}
==={{section|further}}===
* {{R:sd:SLA|Prime minister}}
{{topics|sd|Chính phủ|Nhà lãnh đạo|Nghề nghiệp|Mọi người}}
ainr1bl99l6x1mces4xy305f5ha7ayt
麦蒔
0
392402
2344312
2026-04-12T01:21:11Z
Hiyuune
50834
+ ja
2344312
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|むぎ|ま|o2=き|y=k|alt=麦播き}}
{{swp|ja:ムギマキ}}
==={{section|n}}===
{{ja-noun|むぎまき|ムギマキ}}
# {{taxlink|Ficedula mugimaki|loài}}
===={{section|usage}}====
{{U:ja:biology}}
{{C|ja|Họ Đớp ruồi}}
haimsts31l3y5alwnexnlku7tnnb9j5
પછવાડું
0
392403
2344313
2026-04-12T01:24:48Z
Hiyuune
50834
+ gu
2344313
wikitext
text/x-wiki
=={{langname|gu}}==
==={{section|etym}}===
{{der+|gu|sa|*पश्चपाट}}.
==={{section|n}}===
{{gu-noun|g=n}}
# [[đằng sau|Đằng sau]].
==={{section|adj}}===
{{gu-adj}}
# [[gần đây|Gần đây]]; [[cuối cùng]].
4d31g3vxt0j9f1ipu07fbm06tzawcct
Thể loại:Từ đánh vần với 廣 là こう tiếng Nhật
14
392404
2344315
2026-04-12T01:29:12Z
WhoAlone
40420
Trang mới: “{{auto cat|goon|kanon}}”
2344315
wikitext
text/x-wiki
{{auto cat|goon|kanon}}
pcfeck6099nlm7ilmenvn80gp1r7w7f
Thể loại:Từ đánh vần với 廣 tiếng Nhật
14
392405
2344316
2026-04-12T01:29:39Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344316
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 廣 theo ngôn ngữ
14
392406
2344319
2026-04-12T01:45:14Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344319
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
晃二
0
392407
2344322
2026-04-12T02:11:59Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|こう|じ}} ==={{ĐM|pr-noun}}=== {{ja-pos|proper|こうじ}} # {{given name|ja|nam|sort=こうじ}}”
2344322
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|こう|じ}}
==={{ĐM|pr-noun}}===
{{ja-pos|proper|こうじ}}
# {{given name|ja|nam|sort=こうじ}}
tm0nxh62bca5dx24alzt5pyceh4zq7l
晃司
0
392408
2344323
2026-04-12T02:12:40Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|こう|し|k2=じ}} ==={{ĐM|pr-noun}}=== {{ja-pos|proper|こうじ}} # {{given name|ja|nam|sort=こうじ}}”
2344323
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|こう|し|k2=じ}}
==={{ĐM|pr-noun}}===
{{ja-pos|proper|こうじ}}
# {{given name|ja|nam|sort=こうじ}}
7rq8gagbbg4frk8u7gk343wf6jgicob
晃次
0
392409
2344324
2026-04-12T02:15:43Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|こう|じ}} ==={{ĐM|pr-noun}}=== {{ja-pos|proper|こうじ}} # {{given name|ja|nam|sort=こうじ}}”
2344324
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|こう|じ}}
==={{ĐM|pr-noun}}===
{{ja-pos|proper|こうじ}}
# {{given name|ja|nam|sort=こうじ}}
tm0nxh62bca5dx24alzt5pyceh4zq7l
浩二
0
392410
2344325
2026-04-12T02:16:49Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|こう|じ}} ==={{ĐM|pr-noun}}=== {{ja-pos|proper|こうじ}} # {{given name|ja|nam|sort=こうじ}}”
2344325
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|こう|じ}}
==={{ĐM|pr-noun}}===
{{ja-pos|proper|こうじ}}
# {{given name|ja|nam|sort=こうじ}}
tm0nxh62bca5dx24alzt5pyceh4zq7l
浩司
0
392411
2344326
2026-04-12T02:18:21Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|こう|し|k2=じ|r=y|y=kanon,o}} {{ja-kanjitab|ひろ|し|y=y}} ==={{ĐM|pron}}=== {{ja-pron|こうじ|ひろし}} ==={{ĐM|pr-noun}}=== {{ja-pos|proper|こうじ|ひろし}} # {{given name|ja|nam}}”
2344326
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|こう|し|k2=じ|r=y|y=kanon,o}}
{{ja-kanjitab|ひろ|し|y=y}}
==={{ĐM|pron}}===
{{ja-pron|こうじ|ひろし}}
==={{ĐM|pr-noun}}===
{{ja-pos|proper|こうじ|ひろし}}
# {{given name|ja|nam}}
ae6jebj06egeg6yvlq6xhgvuyvafcyq
浩嗣
0
392412
2344327
2026-04-12T02:20:27Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|こう|し|k2=じ|yomi=o|r=y}}{{ja-kanjitab|ひろ|し}} ==={{ĐM|pr-noun}}=== {{ja-pos|proper|こうじ|ひろし}} # {{given name|ja|nam|sort=ひろし}}”
2344327
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|こう|し|k2=じ|yomi=o|r=y}}{{ja-kanjitab|ひろ|し}}
==={{ĐM|pr-noun}}===
{{ja-pos|proper|こうじ|ひろし}}
# {{given name|ja|nam|sort=ひろし}}
gnfxbihpghoc7wmyzo8tv9ri3nrd3j7
浩次
0
392413
2344328
2026-04-12T02:21:14Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|こう|じ|yomi=o}} ==={{ĐM|pr-noun}}=== {{ja-pos|proper|こうじ}} # {{given name|ja|nam|sort=こうじ}}”
2344328
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|こう|じ|yomi=o}}
==={{ĐM|pr-noun}}===
{{ja-pos|proper|こうじ}}
# {{given name|ja|nam|sort=こうじ}}
1n2mdkhkxo3ocasatzoverehvl47dwh
四肢發達,頭腦簡單
0
392414
2344329
2026-04-12T02:23:45Z
WhoAlone
40420
Trang mới: “=={{langname|zh}}== {{zh-forms|s=四肢发达,头脑简单|type=2222|lit=Tứ chi phát đạt, đầu não giản đơn}} ==={{ĐM|pron}}=== {{zh-pron |m=sìzhī fādá, tóunǎo jiǎndān |c=sei3 zi1 faat3 daat6, tau4 nou5 gaan2 daan1 |cat=ph }} ==={{ĐM|phrase}}=== {{head|zh|Cụm từ}} # [[đầu óc ngu si, tứ chi phát triển|Đầu óc ngu si, tứ chi phát triển]]. ===={{ĐM|see also}}==== * {{langname|vi}}: {{l|vi|đầu óc ngu si, tứ chi phát tr…”
2344329
wikitext
text/x-wiki
=={{langname|zh}}==
{{zh-forms|s=四肢发达,头脑简单|type=2222|lit=Tứ chi phát đạt, đầu não giản đơn}}
==={{ĐM|pron}}===
{{zh-pron
|m=sìzhī fādá, tóunǎo jiǎndān
|c=sei3 zi1 faat3 daat6, tau4 nou5 gaan2 daan1
|cat=ph
}}
==={{ĐM|phrase}}===
{{head|zh|Cụm từ}}
# [[đầu óc ngu si, tứ chi phát triển|Đầu óc ngu si, tứ chi phát triển]].
===={{ĐM|see also}}====
* {{langname|vi}}: {{l|vi|đầu óc ngu si, tứ chi phát triển}}
tdt8tl03y91mrb78b910z3rjktbvug7
Thể loại:Cụm từ tiếng Trung Quốc
14
392415
2344330
2026-04-12T02:24:21Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344330
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Mục từ có chứa nhiều từ tiếng Trung Quốc
14
392416
2344331
2026-04-12T02:24:53Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344331
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 四 tiếng Trung Quốc
14
392417
2344332
2026-04-12T02:25:36Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344332
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 肢 tiếng Trung Quốc
14
392418
2344333
2026-04-12T02:26:38Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344333
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 肢 theo ngôn ngữ
14
392419
2344334
2026-04-12T02:26:59Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344334
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 發 tiếng Trung Quốc
14
392420
2344335
2026-04-12T02:27:48Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344335
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 發 theo ngôn ngữ
14
392421
2344336
2026-04-12T02:28:14Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344336
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 達 tiếng Trung Quốc
14
392422
2344337
2026-04-12T02:29:15Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344337
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 達 theo ngôn ngữ
14
392423
2344338
2026-04-12T02:30:09Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344338
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 頭 tiếng Trung Quốc
14
392424
2344339
2026-04-12T02:31:26Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344339
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 腦 tiếng Trung Quốc
14
392425
2344340
2026-04-12T02:31:50Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344340
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 腦 theo ngôn ngữ
14
392426
2344341
2026-04-12T02:32:14Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344341
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 簡 tiếng Trung Quốc
14
392427
2344342
2026-04-12T02:33:47Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344342
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 簡 theo ngôn ngữ
14
392428
2344343
2026-04-12T02:34:12Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344343
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 單 tiếng Trung Quốc
14
392429
2344344
2026-04-12T02:35:43Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344344
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Từ đánh vần với 單 theo ngôn ngữ
14
392430
2344345
2026-04-12T02:36:18Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344345
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
四肢发达,头脑简单
0
392431
2344346
2026-04-12T02:37:55Z
WhoAlone
40420
Trang mới: “=={{langname|zh}}== {{zh-see|四肢發達,頭腦簡單}}”
2344346
wikitext
text/x-wiki
=={{langname|zh}}==
{{zh-see|四肢發達,頭腦簡單}}
lccsdvvd59b3v2hius887qdx8bqy3r1
四肢
0
392432
2344347
2026-04-12T02:38:59Z
WhoAlone
40420
Trang mới: “=={{langname|vi}}== {{vi-hantutab}} ==={{ĐM|noun}}=== {{vi-noun|sc=Hani}} # {{vi-Han form of|tứ chi}}”
2344347
wikitext
text/x-wiki
=={{langname|vi}}==
{{vi-hantutab}}
==={{ĐM|noun}}===
{{vi-noun|sc=Hani}}
# {{vi-Han form of|tứ chi}}
k2rw61j8iubo0z0w0m01h1f9iompivu
2344348
2344347
2026-04-12T02:42:07Z
WhoAlone
40420
2344348
wikitext
text/x-wiki
=={{langname|vi}}==
{{vi-hantutab}}
==={{ĐM|noun}}===
{{vi-noun|sc=Hani}}
# {{vi-Han form of|tứ chi}}
=={{langname|ja}}==
{{ja-kanjitab|し|し|yomi=o}}
==={{ĐM|pron}}===
{{ja-pron|しし|acc=1|acc_ref=DJR}}
==={{ĐM|noun}}===
{{ja-noun|しし}}
# [[tứ chi]].
#: {{ja-usex|'''四肢'''[[切断]]|'''しし''' せつだん|cắt cụt '''tứ chi'''}}
==={{ĐM|ref}}===
<references/>
:* {{R:Kanjipedia Kotoba|0002717900}}
=={{langname|ko}}==
{{ko-hanjatab}}
==={{ĐM|noun}}===
{{ko-noun|hangeul=사지}}
# {{hanja form of|사지|[[tứ chi]]}}
=={{langname|zh}}==
{{zh-forms}}
==={{ĐM|pron}}===
{{zh-pron
|m=sìzhī
|ma=Zh-sìzhi.ogg
|c=sei3 zi1
|ca=LL-Q9186 (yue)-Luilui6666-四肢.wav
|mn=ml:sì-ki/tw:sù-ki/qz:sìr-chi/xm,zz:sù-chi
|mn-t=si3 zi1
|cat=n
}}
==={{ĐM|noun}}===
{{head|zh|Danh từ}}
# [[tứ chi]].
#: {{zh-x|四肢 無力|bị yếu ở '''tứ chi'''}}
#: {{zh-x|天生 沒有 四肢|sinh ra không có '''tứ chi'''}}
===={{ĐM|derived}}====
{{col3|zh|四肢發達,頭腦簡單}}
{{C|zh|Giải phẫu học}}
eezu04xqnxbqkn4sfy8xj3epem91dmk
sìzhī
0
392433
2344349
2026-04-12T02:42:32Z
WhoAlone
40420
Trang mới: “=={{langname|cmn}}== ==={{ĐM|rom}}=== {{cmn-pinyin}} # {{cmn-pinyin of|四肢}}”
2344349
wikitext
text/x-wiki
=={{langname|cmn}}==
==={{ĐM|rom}}===
{{cmn-pinyin}}
# {{cmn-pinyin of|四肢}}
4elro4jb4k4n06uev1a8577co5q80tg
しし
0
392434
2344350
2026-04-12T02:49:33Z
WhoAlone
40420
Trang mới: “{{also|しじ|じじ}} =={{langname|ja}}== ==={{ĐM|etym}} 1=== {{ja-see-kango|獅子|四肢|志士|嗣子|死屍|梔子}} ==={{ĐM|etym}} 2=== {{ja-see|肉}} ==={{ĐM|etym}} 3=== {{ja-see|獣}} ==={{ĐM|etym}} 4=== {{ja-see|獅子}}”
2344350
wikitext
text/x-wiki
{{also|しじ|じじ}}
=={{langname|ja}}==
==={{ĐM|etym}} 1===
{{ja-see-kango|獅子|四肢|志士|嗣子|死屍|梔子}}
==={{ĐM|etym}} 2===
{{ja-see|肉}}
==={{ĐM|etym}} 3===
{{ja-see|獣}}
==={{ĐM|etym}} 4===
{{ja-see|獅子}}
e239os81fusdaemj4nmgp6xwg2zvqau
사지
0
392435
2344351
2026-04-12T02:51:13Z
WhoAlone
40420
Trang mới: “=={{langname|ko}}== ==={{ĐM|pron}}=== {{ko-IPA|l=y}} ==={{ĐM|etym}} 1=== {{ko-etym-sino|四肢}}. ===={{ĐM|noun}}==== {{ko-noun|hanja=四肢}} # [[tứ chi]]. ==={{ĐM|etym}} 2=== {{ko-etym-sino|死地}}. ===={{ĐM|noun}}==== {{ko-noun|hanja=死地}} # [[tình huống]] [[chết người]]. {{C|ko|Giải phẫu học|Chết}}”
2344351
wikitext
text/x-wiki
=={{langname|ko}}==
==={{ĐM|pron}}===
{{ko-IPA|l=y}}
==={{ĐM|etym}} 1===
{{ko-etym-sino|四肢}}.
===={{ĐM|noun}}====
{{ko-noun|hanja=四肢}}
# [[tứ chi]].
==={{ĐM|etym}} 2===
{{ko-etym-sino|死地}}.
===={{ĐM|noun}}====
{{ko-noun|hanja=死地}}
# [[tình huống]] [[chết người]].
{{C|ko|Giải phẫu học|Chết}}
nwi5swlt497a4pjot0ayqum8wyymy7g
發達
0
392436
2344352
2026-04-12T02:55:28Z
WhoAlone
40420
Trang mới: “{{also|发达}} =={{langname|vi}}== {{vi-hantutab}} ==={{ĐM|verb}}=== {{vi-verb|sc=Hani}} # {{vi-Han form of|phát đạt}} =={{langname|ja}}== {{ja-kanjitab|はつ|k1=はっ|たつ|yomi=on}} {{ja-see|発達}} =={{langname|ko}}== {{ko-hanjatab}} ==={{ĐM|noun}}=== {{ko-noun|hangeul=발달}} # {{hanja form of|발달|sự [[phát triển]]}} =={{langname|zh}}== {{zh-forms|s=发达}} ==={{ĐM|pron}}=== {{zh-pron |m=fādá |ma=Zh-fadá.ogg |c=faat3 daat6 |c-t=fat1 at…”
2344352
wikitext
text/x-wiki
{{also|发达}}
=={{langname|vi}}==
{{vi-hantutab}}
==={{ĐM|verb}}===
{{vi-verb|sc=Hani}}
# {{vi-Han form of|phát đạt}}
=={{langname|ja}}==
{{ja-kanjitab|はつ|k1=はっ|たつ|yomi=on}}
{{ja-see|発達}}
=={{langname|ko}}==
{{ko-hanjatab}}
==={{ĐM|noun}}===
{{ko-noun|hangeul=발달}}
# {{hanja form of|발달|sự [[phát triển]]}}
=={{langname|zh}}==
{{zh-forms|s=发达}}
==={{ĐM|pron}}===
{{zh-pron
|m=fādá
|ma=Zh-fadá.ogg
|c=faat3 daat6
|c-t=fat1 at5
|h=pfs=fat-tha̍t;hrs=h:fad tadˋ
|mn=hoat-ta̍t
|mn-t=huag4 dag8
|px=pt:huah6 dah7/xy:huoh6 dah7
|w=sh:7faq daq
|mc=1,2
|cat=a,v
}}
==={{ĐM|adj}}===
{{head|zh|Tính từ}}
# [[phát triển]].
===={{ĐM|syn}}====
* {{zh-l|不發達}}
===={{ĐM|derived}}====
{{col3|zh|不發達|發達國家|四肢發達,頭腦簡單|欠發達}}
==={{ĐM|verb}}===
{{zh-verb}}
# [[phát triển]].
# trở nên [[giàu có]]; [[vươn lên]] nắm quyền và [[địa vị]].
#: {{syn|zh|發財}}
#: {{zh-x|發達 啦!|Ta giàu rồi!|C}}
===={{ĐM|desc}}====
{{CJKV||s=発達|はったつ|발달|phát đạt}}
etehqytu5axdmkp5kunkn4pw13brpx8
Thể loại:Mục từ có ví dụ cách sử dụng tiếng Quảng Đông
14
392437
2344353
2026-04-12T02:57:19Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344353
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
发达
0
392438
2344354
2026-04-12T03:00:10Z
WhoAlone
40420
Trang mới: “{{also|發達}} =={{langname|zh}}== {{zh-see|發達}}”
2344354
wikitext
text/x-wiki
{{also|發達}}
=={{langname|zh}}==
{{zh-see|發達}}
1ck6lyfyj8jlao06ld53n8zu298ben0
Thể loại:Tính từ tiếng Đài Sơn
14
392439
2344355
2026-04-12T03:00:27Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344355
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Động từ tiếng Đài Sơn
14
392440
2344356
2026-04-12T03:00:29Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344356
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
fādá
0
392441
2344357
2026-04-12T03:03:02Z
WhoAlone
40420
Trang mới: “{{also|fada}} =={{langname|cmn}}== ==={{ĐM|rom}}=== {{cmn-pinyin}} # {{cmn-pinyin of|發達}}”
2344357
wikitext
text/x-wiki
{{also|fada}}
=={{langname|cmn}}==
==={{ĐM|rom}}===
{{cmn-pinyin}}
# {{cmn-pinyin of|發達}}
ilac72lcxeytxe36n25zh13a6h6ttfa
발달
0
392442
2344358
2026-04-12T03:04:43Z
WhoAlone
40420
Trang mới: “=={{langname|ko}}== ==={{ĐM|etym}}=== {{ko-etym-Sino|發|phát|達|đạt}}. ==={{ĐM|pron}}=== {{ko-IPA|com=1}} ==={{ĐM|noun}}=== {{ko-noun|hanja=發達}} # Sự [[phát triển]]. ===={{ĐM|drv}}==== * {{ko-l|발달하다|發達—|(động từ) phát triển}} * {{ko-l|발달되다|發達—|(tính từ) phát triển}}”
2344358
wikitext
text/x-wiki
=={{langname|ko}}==
==={{ĐM|etym}}===
{{ko-etym-Sino|發|phát|達|đạt}}.
==={{ĐM|pron}}===
{{ko-IPA|com=1}}
==={{ĐM|noun}}===
{{ko-noun|hanja=發達}}
# Sự [[phát triển]].
===={{ĐM|drv}}====
* {{ko-l|발달하다|發達—|(động từ) phát triển}}
* {{ko-l|발달되다|發達—|(tính từ) phát triển}}
bhg976vicpt1a6k8tjwpzylkhgjyy1l
poloka
0
392443
2344359
2026-04-12T03:05:08Z
Kelly zhrm
58416
Trang mới: “=={{langname|haw}}== ==={{ĐM|etym}}=== {{bor+|haw|en|frog}} ==={{ĐM|pron}}=== * {{haw-IPA}} ==={{ĐM|n}}=== {{head|haw|Danh từ}} # [[ếch|Ếch]]. #: {{syn|haw|lana}} {{C|haw|Lớp Lưỡng cư}}”
2344359
wikitext
text/x-wiki
=={{langname|haw}}==
==={{ĐM|etym}}===
{{bor+|haw|en|frog}}
==={{ĐM|pron}}===
* {{haw-IPA}}
==={{ĐM|n}}===
{{head|haw|Danh từ}}
# [[ếch|Ếch]].
#: {{syn|haw|lana}}
{{C|haw|Lớp Lưỡng cư}}
stzo1s2rq067li3doakh6b5jykp2rjf
発達
0
392444
2344361
2026-04-12T03:06:49Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|はつ|k1=はっ|たつ|yomi=o}} ==={{ĐM|pron}}=== * {{ja-pron|はったつ|acc=0|acc_ref=NHK}} ==={{ĐM|noun}}=== {{ja-noun|はったつ}} # Sự [[phát triển]]. ===={{ĐM|see also}}==== * {{ja-r|発展|はってん}}, {{ja-r|開発|かいはつ}} ==={{ĐM|verb}}=== {{ja-verb-suru|はったつ|tr=intransitive}} # [[phát triển]]. #* {{quote-web|ja |work=ja:国会会議録検索システム |publisher=ja:国立国会図書館…”
2344361
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|はつ|k1=はっ|たつ|yomi=o}}
==={{ĐM|pron}}===
* {{ja-pron|はったつ|acc=0|acc_ref=NHK}}
==={{ĐM|noun}}===
{{ja-noun|はったつ}}
# Sự [[phát triển]].
===={{ĐM|see also}}====
* {{ja-r|発展|はってん}}, {{ja-r|開発|かいはつ}}
==={{ĐM|verb}}===
{{ja-verb-suru|はったつ|tr=intransitive}}
# [[phát triển]].
#* {{quote-web|ja
|work=ja:国会会議録検索システム
|publisher=ja:国立国会図書館
|title=ja:第213回国会 衆議院 内閣委員会 第11号 令和6年4月17日
|date=2024-04-17
|url=https://kokkai.ndl.go.jp/txt/121304889X01120240417/111
|quotee=ja:住吉寛紀
|text=近年では、AIツールも'''発達'''して、翻訳も簡単にできます。
|transliteration=Kinnen de wa, ē ai tsūru mo '''hattatsu''' shite, hon'yaku mo kantan ni deki-masu.
|translation=Trong những năm gần đây, các công nghệ AI đã '''phát triển''', giúp việc dịch thuật trở nên dễ dàng hơn.}}
===={{ĐM|conjugation}}====
{{ja-suru|はったつ}}
==={{ĐM|ref}}===
<references/>
:* {{R:Kanjipedia Kotoba|0005690000}}
937u2irk17i2q7dmn21vn28ni669x57
hattatsu
0
392445
2344362
2026-04-12T03:07:22Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== ==={{ĐM|rom}}=== {{ja-romaji}} # {{ja-romanization of|はったつ}}”
2344362
wikitext
text/x-wiki
=={{langname|ja}}==
==={{ĐM|rom}}===
{{ja-romaji}}
# {{ja-romanization of|はったつ}}
lvdent2q1ux5fj9amwd14qn6fi0slq8
はったつ
0
392446
2344363
2026-04-12T03:07:40Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-see-kango|発達|八達}}”
2344363
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see-kango|発達|八達}}
5q9gtnxr6jq3v85f3s48ja6rk3hrw5w
aloha ahiahi
0
392447
2344364
2026-04-12T03:13:07Z
Kelly zhrm
58416
Trang mới: “=={{langname|haw}}== ==={{ĐM|pron}}=== * {{haw-IPA|aloha ahi+ahi}} ==={{ĐM|interj}}=== {{head|haw|Thán từ}} # [[chào|Chào]] [[buổi tối]].”
2344364
wikitext
text/x-wiki
=={{langname|haw}}==
==={{ĐM|pron}}===
* {{haw-IPA|aloha ahi+ahi}}
==={{ĐM|interj}}===
{{head|haw|Thán từ}}
# [[chào|Chào]] [[buổi tối]].
kmzzy0s41xbz2h8wlgmd4w71gsu5tzr
2344370
2344364
2026-04-12T03:22:13Z
Kelly zhrm
58416
2344370
wikitext
text/x-wiki
=={{langname|haw}}==
==={{ĐM|pron}}===
* {{haw-IPA|aloha ahi+ahi}}
==={{ĐM|interj}}===
{{head|haw|Thán từ}}
# [[chào|Chào]] [[buổi tối]].
{{cln|haw|Từ điển đàm thoại}}
lwdwfgzc3829oezcqs416pyu7a19a04
aloha kakahiaka
0
392448
2344365
2026-04-12T03:16:38Z
Kelly zhrm
58416
Trang mới: “=={{langname|haw}}== ==={{ĐM|etym}}=== Tiếng Hawaii {{mention|haw|aloha}} + {{mention|haw|kakahiaka||buổi sáng}}. ==={{ĐM|pron}}=== * {{haw-IPA|aloha kaka+hiaka}} {{rfap|haw|}} ==={{ĐM|phrase}}=== {{head|haw|Cụm từ}} # [[chào|Chào]] [[buổi sáng]]. {{cln|haw|Từ điển đàm thoại}}”
2344365
wikitext
text/x-wiki
=={{langname|haw}}==
==={{ĐM|etym}}===
Tiếng Hawaii {{mention|haw|aloha}} + {{mention|haw|kakahiaka||buổi sáng}}.
==={{ĐM|pron}}===
* {{haw-IPA|aloha kaka+hiaka}}
{{rfap|haw|}}
==={{ĐM|phrase}}===
{{head|haw|Cụm từ}}
# [[chào|Chào]] [[buổi sáng]].
{{cln|haw|Từ điển đàm thoại}}
g6y6sjb5sqa7amq178ayx7io8chldqk
2344366
2344365
2026-04-12T03:17:20Z
Kelly zhrm
58416
2344366
wikitext
text/x-wiki
=={{langname|haw}}==
==={{ĐM|etym}}===
Tiếng Hawaii {{mention|haw|aloha}} + {{mention|haw|kakahiaka||buổi sáng}}.
==={{ĐM|pron}}===
* {{haw-IPA|aloha kaka+hiaka}}
{{rfap|haw|}}
==={{ĐM|interj}}===
{{head|haw|Thán từ}}
# [[chào|Chào]] [[buổi sáng]].
{{cln|haw|Từ điển đàm thoại}}
2j9sgzef244slh5fl66ybv0etr1iaae
Thể loại:Mục từ có chứa nhiều từ tiếng Hawaii
14
392449
2344367
2026-04-12T03:18:19Z
Kelly zhrm
58416
Trang mới: “{{auto cat}}”
2344367
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Thán từ tiếng Hawaii
14
392450
2344368
2026-04-12T03:19:37Z
Kelly zhrm
58416
Trang mới: “{{auto cat}}”
2344368
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Bảo trì mục từ tiếng Hawaii
14
392451
2344369
2026-04-12T03:20:49Z
Kelly zhrm
58416
Trang mới: “{{auto cat}}”
2344369
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
మొసలి
0
392452
2344371
2026-04-12T03:27:09Z
Kelly zhrm
58416
Trang mới: “=={{langname|te}}== [[Image:NileCrocodile.jpg|thumb|right|మొసలి.]] ==={{ĐM|etym}}=== {{inh+|te|dra-pro|*mocVḷ}}. Cùng gốc với {{cog|iru|மொஜலெ}}. ==={{ĐM|n}}=== {{te-noun}} # [[cá sấu|Cá sấu]]. ===={{ĐM|quot}}==== {{seeCites|te}} ===={{ĐM|syn}}==== * {{l|te|మకరము}} ==={{ĐM|ref}}=== * {{R:te:CPB|head=మొసలి|1043}} {{topics|te|Bộ Cá sấu}}”
2344371
wikitext
text/x-wiki
=={{langname|te}}==
[[Image:NileCrocodile.jpg|thumb|right|మొసలి.]]
==={{ĐM|etym}}===
{{inh+|te|dra-pro|*mocVḷ}}. Cùng gốc với {{cog|iru|மொஜலெ}}.
==={{ĐM|n}}===
{{te-noun}}
# [[cá sấu|Cá sấu]].
===={{ĐM|quot}}====
{{seeCites|te}}
===={{ĐM|syn}}====
* {{l|te|మకరము}}
==={{ĐM|ref}}===
* {{R:te:CPB|head=మొసలి|1043}}
{{topics|te|Bộ Cá sấu}}
q6euuo4agjktr4rj3iwnigxgaldmer5
Thể loại:Từ kế thừa từ tiếng Dravida nguyên thủy tiếng Telugu
14
392453
2344372
2026-04-12T03:28:00Z
Kelly zhrm
58416
Trang mới: “{{auto cat}}”
2344372
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
ꪹꪖꪷꪨꪀ
0
392454
2344373
2026-04-12T04:14:35Z
Higashizakura
36666
Trang mới
2344373
wikitext
text/x-wiki
=={{langname|blt}}==
==={{đm|pron}}===
{{blt-pron|ꪖꪰ-ꪹꪨꪷꪀ}}
==={{đm|v}}===
{{head|blt|Động từ|tr=thlớk}}
# [[trầy|Trầy]].
==={{đm|ref}}===
* {{R:blt:TĐTV}}
9nqb0yok6d5v9xlfddg12qcb08r73y0
Thể loại:Bản mẫu tham khảo tiếng Thái Đen
14
392455
2344375
2026-04-12T04:18:27Z
Higashizakura
36666
Trang mới: “{{auto cat}}”
2344375
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Bản mẫu cách phát âm tiếng Thái Đen
14
392456
2344377
2026-04-12T04:22:23Z
Higashizakura
36666
Trang mới: “{{auto cat}}”
2344377
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Bản mẫu tiếng Thái Đen
14
392457
2344378
2026-04-12T04:23:13Z
Higashizakura
36666
Trang mới: “{{auto cat}}”
2344378
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
照猫画虎
0
392458
2344380
2026-04-12T04:26:25Z
Hiyuune
50834
Trang mới: “=={{langname|zh}}== {{zh-see|照貓畫虎}}”
2344380
wikitext
text/x-wiki
=={{langname|zh}}==
{{zh-see|照貓畫虎}}
9swa3zdnhiqmcl9ij5bso1x8ej986yp
Thể loại:Bản mẫu liên kết tiếng Thái Đen
14
392459
2344382
2026-04-12T04:29:24Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2344382
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
頭腦
0
392460
2344384
2026-04-12T04:35:13Z
WhoAlone
40420
Trang mới: “{{also|头脑}} =={{langname|vi}}== {{vi-hantutab}} ==={{ĐM|noun}}=== {{vi-noun|sc=Hani}} # {{vi-Han form of|đầu não}} =={{langname|ko}}== {{ko-hanjatab}} ==={{ĐM|noun}}=== {{ko-noun|hangeul=두뇌}} # {{hanja form of|두뇌|[[não]]}} =={{langname|zh}}== {{zh-forms|s=头脑|lit=đầu não}} ==={{ĐM|pron}}=== {{zh-pron |m=tóunǎo |c=tau4 nou5 |h=pfs=thèu-nó;hrs=h:teu noˊ |mb=tê-nǎu |md=tàu-nō̤ |mn=xm,zz,kh,tn,lk,yl,km,mg,pn,sg:thâu-náu/qz,hc,tc,j…”
2344384
wikitext
text/x-wiki
{{also|头脑}}
=={{langname|vi}}==
{{vi-hantutab}}
==={{ĐM|noun}}===
{{vi-noun|sc=Hani}}
# {{vi-Han form of|đầu não}}
=={{langname|ko}}==
{{ko-hanjatab}}
==={{ĐM|noun}}===
{{ko-noun|hangeul=두뇌}}
# {{hanja form of|두뇌|[[não]]}}
=={{langname|zh}}==
{{zh-forms|s=头脑|lit=đầu não}}
==={{ĐM|pron}}===
{{zh-pron
|m=tóunǎo
|c=tau4 nou5
|h=pfs=thèu-nó;hrs=h:teu noˊ
|mb=tê-nǎu
|md=tàu-nō̤
|mn=xm,zz,kh,tn,lk,yl,km,mg,pn,sg:thâu-náu/qz,hc,tc,jj,ph:thâu-ló/tp,sx:thâu-nó͘
|mn-t=tao5 nao2
|px=pt,xy:tao2 nor3
|w=sh:6deu nau
|mc=y
|cat=n
}}
==={{ĐM|noun}}===
{{head|zh|Danh từ}}
# {{lb|zh|literary}} [[đầu]].
# [[trí não]].
# [[trí tuệ]], [[trí]] [[thông minh]].
# [[lãnh đạo]].
# {{lb|zh|obsolete}} [[thông tin]] [[nội bộ]].
# {{lb|zh|obsolete}} [[lý do]]; [[nguyên nhân]].
===={{ĐM|syn}}====
{{zh-dial|頭}}
* {{s|trí não}}
{{syn-saurus|zh|腦力}}
* {{s|thông tin nội bộ}}
{{syn-saurus|zh|內情}}
===={{ĐM|derived}}====
{{col3|zh|大頭腦|不知一個頭腦|好頭腦|不知頭腦|摸不著頭腦//摸不着头脑|打大頭腦|沒頭腦官司|沒頭腦的事|沒頭腦|有頭腦|頭腦派|頭腦體操|頭腦湯|頭腦酒|頭腦簡單|頭腦風暴|丈二金剛——摸不著頭腦|丈二和尚——摸不著頭腦|頭腦發熱|四肢發達,頭腦簡單}}
===={{ĐM|desc}}====
{{CJKV||s=頭%脳|ず%のう|두뇌|đầu não}}
ppmrc83e4arj588q1hm14iulc83bgra
2344392
2344384
2026-04-12T04:39:01Z
WhoAlone
40420
2344392
wikitext
text/x-wiki
{{also|头脑}}
=={{langname|vi}}==
{{vi-hantutab}}
==={{ĐM|noun}}===
{{vi-noun|sc=Hani}}
# {{vi-Han form of|đầu não}}
=={{langname|ja}}==
{{ja-see|頭脳}}
=={{langname|ko}}==
{{ko-hanjatab}}
==={{ĐM|noun}}===
{{ko-noun|hangeul=두뇌}}
# {{hanja form of|두뇌|[[não]]}}
=={{langname|zh}}==
{{zh-forms|s=头脑|lit=đầu não}}
==={{ĐM|pron}}===
{{zh-pron
|m=tóunǎo
|c=tau4 nou5
|h=pfs=thèu-nó;hrs=h:teu noˊ
|mb=tê-nǎu
|md=tàu-nō̤
|mn=xm,zz,kh,tn,lk,yl,km,mg,pn,sg:thâu-náu/qz,hc,tc,jj,ph:thâu-ló/tp,sx:thâu-nó͘
|mn-t=tao5 nao2
|px=pt,xy:tao2 nor3
|w=sh:6deu nau
|mc=y
|cat=n
}}
==={{ĐM|noun}}===
{{head|zh|Danh từ}}
# {{lb|zh|literary}} [[đầu]].
# [[trí não]].
# [[trí tuệ]], [[trí]] [[thông minh]].
# [[lãnh đạo]].
# {{lb|zh|obsolete}} [[thông tin]] [[nội bộ]].
# {{lb|zh|obsolete}} [[lý do]]; [[nguyên nhân]].
===={{ĐM|syn}}====
{{zh-dial|頭}}
* {{s|trí não}}
{{syn-saurus|zh|腦力}}
* {{s|thông tin nội bộ}}
{{syn-saurus|zh|內情}}
===={{ĐM|derived}}====
{{col3|zh|大頭腦|不知一個頭腦|好頭腦|不知頭腦|摸不著頭腦//摸不着头脑|打大頭腦|沒頭腦官司|沒頭腦的事|沒頭腦|有頭腦|頭腦派|頭腦體操|頭腦湯|頭腦酒|頭腦簡單|頭腦風暴|丈二金剛——摸不著頭腦|丈二和尚——摸不著頭腦|頭腦發熱|四肢發達,頭腦簡單}}
===={{ĐM|desc}}====
{{CJKV||s=頭%脳|ず%のう|두뇌|đầu não}}
0dstpn9dtxjvb16g20bij91trygf1g3
头脑
0
392461
2344385
2026-04-12T04:35:38Z
WhoAlone
40420
Trang mới: “{{also|頭腦}} =={{langname|zh}}== {{zh-see|頭腦}}”
2344385
wikitext
text/x-wiki
{{also|頭腦}}
=={{langname|zh}}==
{{zh-see|頭腦}}
gghdub8o8srfluwotqtqoobumcx661c
tóunǎo
0
392462
2344386
2026-04-12T04:36:21Z
WhoAlone
40420
Trang mới: “=={{langname|cmn}}== ==={{ĐM|rom}}=== {{cmn-pinyin}} # {{cmn-pinyin of|頭腦}}”
2344386
wikitext
text/x-wiki
=={{langname|cmn}}==
==={{ĐM|rom}}===
{{cmn-pinyin}}
# {{cmn-pinyin of|頭腦}}
nw7123cpu50v08h2pi2j90gf3nx6oi6
Bản mẫu:list:Ngày trong tuần/blt
10
392463
2344387
2026-04-12T04:37:19Z
Higashizakura
36666
Trang mới: “{{#invoke:topic list|show |([[ꪫꪽ]]) [[ꪊꪽ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪎꪮꪉ]] |([[ꪫꪽ]]) [[ꪮꪰꪉ ꪅꪱꪙ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪎꪱꪣ]] |([[ꪫꪽ]]) [[ꪡꪴꪒ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪎꪲ꪿]] |([[ꪫꪽ]]) [[ꪡꪱꪀ ꪬꪰꪒ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪬ꫁ꪱ]] |([[ꪫꪽ]]) [[ꪎꪴꪀ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪶꪬ꪿ꪀ]] |([[ꪫꪽ]]) [[ꪹꪎꪱ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪹꪊꪸꪒ]] |(ꪫ…”
2344387
wikitext
text/x-wiki
{{#invoke:topic list|show
|([[ꪫꪽ]]) [[ꪊꪽ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪎꪮꪉ]]
|([[ꪫꪽ]]) [[ꪮꪰꪉ ꪅꪱꪙ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪎꪱꪣ]]
|([[ꪫꪽ]]) [[ꪡꪴꪒ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪎꪲ꪿]]
|([[ꪫꪽ]]) [[ꪡꪱꪀ ꪬꪰꪒ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪬ꫁ꪱ]]
|([[ꪫꪽ]]) [[ꪎꪴꪀ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪶꪬ꪿ꪀ]]
|([[ꪫꪽ]]) [[ꪹꪎꪱ]] / ([[ꪣꪳ꫁]]) [[ꪖꪳ꪿ ꪹꪊꪸꪒ]]
|([[ꪫꪽ]]) [[ꪗꪲꪒ]] / ([[ꪣꪳ꫁]]) [[ꪊꪴ꫁ ꪹꪑꪷꪒ]]
}}<noinclude>{{list doc}}</noinclude>
qvlqxuvp3ndpnipu1mcwo48yxadbk0y
頭脳
0
392464
2344388
2026-04-12T04:37:25Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|ず|のう|yomi=o}} ==={{ĐM|pron}}=== {{ja-pron|ずのう|acc=1|acc_ref=NHK}} ==={{ĐM|noun}}=== {{ja-noun|ずのう}} # [[trí tuệ]]. ==={{ĐM|ref}}=== <references/> :* {{R:Kanjipedia Kotoba|0005234100}}”
2344388
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|ず|のう|yomi=o}}
==={{ĐM|pron}}===
{{ja-pron|ずのう|acc=1|acc_ref=NHK}}
==={{ĐM|noun}}===
{{ja-noun|ずのう}}
# [[trí tuệ]].
==={{ĐM|ref}}===
<references/>
:* {{R:Kanjipedia Kotoba|0005234100}}
3ujroed0h49y4lg7g23j42jstv715kt
zunō
0
392465
2344389
2026-04-12T04:37:55Z
WhoAlone
40420
Trang mới: “{{also|zuno|Zuno|žuno}} =={{langname|ja}}== ==={{ĐM|rom}}=== {{ja-romaji}} # {{ja-romanization of|ずのう}}”
2344389
wikitext
text/x-wiki
{{also|zuno|Zuno|žuno}}
=={{langname|ja}}==
==={{ĐM|rom}}===
{{ja-romaji}}
# {{ja-romanization of|ずのう}}
3zew72rlkksaaodgt17c1co8xmbhwjx
ずのう
0
392466
2344390
2026-04-12T04:38:16Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-see|頭脳}}”
2344390
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see|頭脳}}
rs4aqb9v0voapnkgyqzkbnrhc7ld44u
𑜑𑜥
0
392467
2344393
2026-04-12T04:41:25Z
Hiyuune
50834
+ aho
2344393
wikitext
text/x-wiki
=={{langname|aho}}==
==={{section|etym}}===
So sánh với {{cog|och|-}} {{och-l|牛}}. Cùng gốc với {{cog|khb|ᦷᦣ}}. So sánh với {{cog|khb|ᦷᦇ}}, {{cog|th|วัว}} hoặc {{mention|th|งัว}}, {{cog|nod|ᨦ᩠ᩅᩫ}}, {{cog|tts|งัว}}, {{cog|lo|ງົວ}}, {{cog|blt|ꪉꪺ}}.
==={{section|n}}===
{{head|aho|Danh từ}}
# Con [[bò]].
{{C|aho|Động vật|Lớp Thú}}
4397q9k9iac8l5larva8dkzobmsjvru
ᦷᦣ
0
392468
2344394
2026-04-12T04:43:34Z
Hiyuune
50834
Trang mới: “=={{langname|khb}}== ==={{section|etym}}=== * {{alt|khb|ᦷᦇ|ᦷᦞ}} ==={{section|etym}}=== {{inh+|khb|tai-swe-pro|*ŋuəᴬ⁴||bò}} (Jonsson, 1991). So sánh với {{cog|och|-}} {{och-l|牛}}. Cùng gốc với {{cog|th|วัว}} hoặc {{mention|th|งัว}}, {{cog|nod|ᨦ᩠ᩅᩫ}}, {{cog|tts|งัว}}, {{cog|lo|ງົວ}}, {{cog|blt|ꪉꪺ}}, {{cog|twh|ꪉꪺ}}, {{cog|shn|ငူဝ်း}} hoặc {{mention|shn|ဝူဝ်း}}, {{cog|tdd|ᥒᥨᥝᥰ}}…”
2344394
wikitext
text/x-wiki
=={{langname|khb}}==
==={{section|etym}}===
* {{alt|khb|ᦷᦇ|ᦷᦞ}}
==={{section|etym}}===
{{inh+|khb|tai-swe-pro|*ŋuəᴬ⁴||bò}} (Jonsson, 1991). So sánh với {{cog|och|-}} {{och-l|牛}}. Cùng gốc với {{cog|th|วัว}} hoặc {{mention|th|งัว}}, {{cog|nod|ᨦ᩠ᩅᩫ}}, {{cog|tts|งัว}}, {{cog|lo|ງົວ}}, {{cog|blt|ꪉꪺ}}, {{cog|twh|ꪉꪺ}}, {{cog|shn|ငူဝ်း}} hoặc {{mention|shn|ဝူဝ်း}}, {{cog|tdd|ᥒᥨᥝᥰ}} hoặc {{mention|tdd|ᥝᥨᥝᥰ}}, {{cog|aho|𑜆𑜥}} hoặc {{mention|aho|𑜑𑜥}}.
==={{section|pron}}===
{{khb-pron}}
==={{section|n}}===
{{khb-noun|ᦷᦎ}}
# Con [[bò]].
==={{section|ref}}===
* {{R:khb:Hanna}}
jwv4v1f2j5opvrubiciymudp36ktk04
2344396
2344394
2026-04-12T04:50:41Z
Hiyuune
50834
/* Tiếng Lự */ (sử dụng [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]])
2344396
wikitext
text/x-wiki
=={{langname|khb}}==
==={{section|etym}}===
* {{alt|khb|ᦷᦇ|ᦷᦞ}}
==={{section|etym}}===
{{inh+|khb|tai-swe-pro|*ŋuəᴬ⁴||bò}} (Jonsson, 1991). So sánh với {{cog|och|-}} {{och-l|牛}}. Cùng gốc với {{cog|th|วัว}} hoặc {{mention|th|งัว}}, {{cog|nod|ᨦ᩠ᩅᩫ}}, {{cog|tts|งัว}}, {{cog|lo|ງົວ}}, {{cog|blt|ꪉꪺ}}, {{cog|twh|ꪉꪺ}}, {{cog|shn|ငူဝ်း}} hoặc {{mention|shn|ဝူဝ်း}}, {{cog|tdd|ᥒᥨᥝᥰ}} hoặc {{mention|tdd|ᥝᥨᥝᥰ}}, {{cog|aho|𑜆𑜥}} hoặc {{mention|aho|𑜑𑜥}}.
==={{section|pron}}===
{{khb-pron}}
==={{section|n}}===
{{khb-noun|ᦷᦎ}}
# Con [[bò]].
==={{section|ref}}===
* {{R:khb:Hanna}}
{{C|khb|Động vật|Lớp Thú}}
nlcy0cjmlc4o5g2fxckl3shyzkrspjx
2344443
2344396
2026-04-12T07:50:41Z
Hiyuune
50834
/* Tiếng Lự */
2344443
wikitext
text/x-wiki
=={{langname|khb}}==
==={{section|alt}}===
* {{alt|khb|ᦷᦇ|ᦷᦞ}}
==={{section|etym}}===
{{inh+|khb|tai-swe-pro|*ŋuəᴬ⁴||bò}} (Jonsson, 1991). So sánh với {{cog|och|-}} {{och-l|牛}}. Cùng gốc với {{cog|th|วัว}} hoặc {{mention|th|งัว}}, {{cog|nod|ᨦ᩠ᩅᩫ}}, {{cog|tts|งัว}}, {{cog|lo|ງົວ}}, {{cog|blt|ꪉꪺ}}, {{cog|twh|ꪉꪺ}}, {{cog|shn|ငူဝ်း}} hoặc {{mention|shn|ဝူဝ်း}}, {{cog|tdd|ᥒᥨᥝᥰ}} hoặc {{mention|tdd|ᥝᥨᥝᥰ}}, {{cog|aho|𑜆𑜥}} hoặc {{mention|aho|𑜑𑜥}}.
==={{section|pron}}===
{{khb-pron}}
==={{section|n}}===
{{khb-noun|ᦷᦎ}}
# Con [[bò]].
==={{section|ref}}===
* {{R:khb:Hanna}}
{{C|khb|Động vật|Lớp Thú}}
0ogg02r9fdbwha9tu8ldcrcqk2v2m3v
Thể loại:Danh từ có loại từ ᦷᦎ tiếng Lự
14
392469
2344397
2026-04-12T04:51:12Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2344397
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
簡單
0
392470
2344398
2026-04-12T04:51:59Z
WhoAlone
40420
Trang mới: “{{also|簡単|简单}} =={{langname|vi}}== {{vi-hantutab}} ==={{ĐM|adj}}=== {{vi-adj|sc=Hani}} # {{vi-Han form of|giản đơn}} =={{langname|ja}}== {{ja-kanjitab|かん|たん|yomi=o}} {{ja-gv|簡単}} =={{langname|ko}}== {{ko-hanjatab}} ==={{ĐM|root}}=== {{ko-pos|root|hangeul=간단}} # {{hanja form of|간단}} =={{langname|zh}}== {{zh-forms|s=简单}} ==={{ĐM|pron}}=== {{zh-pron |m=jiǎndān |ma=Zh-jiǎndān.ogg |c=gaan2 daan1 |ca=LL-Q9186-Luilui6666-简单.…”
2344398
wikitext
text/x-wiki
{{also|簡単|简单}}
=={{langname|vi}}==
{{vi-hantutab}}
==={{ĐM|adj}}===
{{vi-adj|sc=Hani}}
# {{vi-Han form of|giản đơn}}
=={{langname|ja}}==
{{ja-kanjitab|かん|たん|yomi=o}}
{{ja-gv|簡単}}
=={{langname|ko}}==
{{ko-hanjatab}}
==={{ĐM|root}}===
{{ko-pos|root|hangeul=간단}}
# {{hanja form of|간단}}
=={{langname|zh}}==
{{zh-forms|s=简单}}
==={{ĐM|pron}}===
{{zh-pron
|m=jiǎndān
|ma=Zh-jiǎndān.ogg
|c=gaan2 daan1
|ca=LL-Q9186-Luilui6666-简单.wav
|h=pfs=kién-tân;hrs=h:gienˊ danˋ
|j=jie2 dan1
|md=gāng-dăng
|mn=kán-tan
|mn-t=gang2 duan1
|px=pt,xy:gang3 *dang1
|w=sh:5ci te
|cat=a
}}
==={{ĐM|adj}}===
{{head|zh|Tính từ}}
# [[đơn giản]], [[dễ dàng]].
#: {{zh-x|簡單 碳水.化合物|'''simple''' carbohydrate}}
#: {{zh-x|簡單 易用|'''đơn giản''', tiện dụng}}
#: {{zh-x|這 道 題 太 簡單 了。|Câu hỏi này '''dễ''' quá.}}
# {{lb|zh|chủ yếu ở dạng phủ định}} [[thông thường]]; [[bình thường]].
# [[cẩu thả]]; [[bất cẩn]]; [[sơ sài]]; [[tùy tiện]]; [[đơn giản]] hóa quá mức.
===={{ĐM|syn}}====
* {{s|đơn giản}}
{{syn-saurus|zh|不複雜}}
* {{s|thông thường}}
{{syn-saurus|zh|正常}}
* {{s|cẩu thả}}
{{syn-saurus|zh|粗心}}
===={{ĐM|antonym}}====
* {{as|simple}} {{zh-l|複雜}}
===={{ĐM|drv}}====
{{col3|zh|簡單機械|簡單明瞭|頭腦簡單|簡單粗暴|四肢發達,頭腦簡單}}
===={{ĐM|desc}}====
{{CJKV|j=簡%単||かん%たん|간단|giản đơn}}
f08g2j2l7ch46mt9k8dehclr1dxj8j8
2344410
2344398
2026-04-12T05:01:25Z
WhoAlone
40420
/* {{ĐM|antonym}} */
2344410
wikitext
text/x-wiki
{{also|簡単|简单}}
=={{langname|vi}}==
{{vi-hantutab}}
==={{ĐM|adj}}===
{{vi-adj|sc=Hani}}
# {{vi-Han form of|giản đơn}}
=={{langname|ja}}==
{{ja-kanjitab|かん|たん|yomi=o}}
{{ja-gv|簡単}}
=={{langname|ko}}==
{{ko-hanjatab}}
==={{ĐM|root}}===
{{ko-pos|root|hangeul=간단}}
# {{hanja form of|간단}}
=={{langname|zh}}==
{{zh-forms|s=简单}}
==={{ĐM|pron}}===
{{zh-pron
|m=jiǎndān
|ma=Zh-jiǎndān.ogg
|c=gaan2 daan1
|ca=LL-Q9186-Luilui6666-简单.wav
|h=pfs=kién-tân;hrs=h:gienˊ danˋ
|j=jie2 dan1
|md=gāng-dăng
|mn=kán-tan
|mn-t=gang2 duan1
|px=pt,xy:gang3 *dang1
|w=sh:5ci te
|cat=a
}}
==={{ĐM|adj}}===
{{head|zh|Tính từ}}
# [[đơn giản]], [[dễ dàng]].
#: {{zh-x|簡單 碳水.化合物|'''simple''' carbohydrate}}
#: {{zh-x|簡單 易用|'''đơn giản''', tiện dụng}}
#: {{zh-x|這 道 題 太 簡單 了。|Câu hỏi này '''dễ''' quá.}}
# {{lb|zh|chủ yếu ở dạng phủ định}} [[thông thường]]; [[bình thường]].
# [[cẩu thả]]; [[bất cẩn]]; [[sơ sài]]; [[tùy tiện]]; [[đơn giản]] hóa quá mức.
===={{ĐM|syn}}====
* {{s|đơn giản}}
{{syn-saurus|zh|不複雜}}
* {{s|thông thường}}
{{syn-saurus|zh|正常}}
* {{s|cẩu thả}}
{{syn-saurus|zh|粗心}}
===={{ĐM|antonym}}====
* {{label|zh|giản thể}} {{zh-l|複雜}}
===={{ĐM|drv}}====
{{col3|zh|簡單機械|簡單明瞭|頭腦簡單|簡單粗暴|四肢發達,頭腦簡單}}
===={{ĐM|desc}}====
{{CJKV|j=簡%単||かん%たん|간단|giản đơn}}
4h9monncq056aa0ytvoafuq04xioox4
2344412
2344410
2026-04-12T05:01:35Z
WhoAlone
40420
/* {{ĐM|antonym}} */
2344412
wikitext
text/x-wiki
{{also|簡単|简单}}
=={{langname|vi}}==
{{vi-hantutab}}
==={{ĐM|adj}}===
{{vi-adj|sc=Hani}}
# {{vi-Han form of|giản đơn}}
=={{langname|ja}}==
{{ja-kanjitab|かん|たん|yomi=o}}
{{ja-gv|簡単}}
=={{langname|ko}}==
{{ko-hanjatab}}
==={{ĐM|root}}===
{{ko-pos|root|hangeul=간단}}
# {{hanja form of|간단}}
=={{langname|zh}}==
{{zh-forms|s=简单}}
==={{ĐM|pron}}===
{{zh-pron
|m=jiǎndān
|ma=Zh-jiǎndān.ogg
|c=gaan2 daan1
|ca=LL-Q9186-Luilui6666-简单.wav
|h=pfs=kién-tân;hrs=h:gienˊ danˋ
|j=jie2 dan1
|md=gāng-dăng
|mn=kán-tan
|mn-t=gang2 duan1
|px=pt,xy:gang3 *dang1
|w=sh:5ci te
|cat=a
}}
==={{ĐM|adj}}===
{{head|zh|Tính từ}}
# [[đơn giản]], [[dễ dàng]].
#: {{zh-x|簡單 碳水.化合物|'''simple''' carbohydrate}}
#: {{zh-x|簡單 易用|'''đơn giản''', tiện dụng}}
#: {{zh-x|這 道 題 太 簡單 了。|Câu hỏi này '''dễ''' quá.}}
# {{lb|zh|chủ yếu ở dạng phủ định}} [[thông thường]]; [[bình thường]].
# [[cẩu thả]]; [[bất cẩn]]; [[sơ sài]]; [[tùy tiện]]; [[đơn giản]] hóa quá mức.
===={{ĐM|syn}}====
* {{s|đơn giản}}
{{syn-saurus|zh|不複雜}}
* {{s|thông thường}}
{{syn-saurus|zh|正常}}
* {{s|cẩu thả}}
{{syn-saurus|zh|粗心}}
===={{ĐM|antonym}}====
* {{label|zh|đơn giản}} {{zh-l|複雜}}
===={{ĐM|drv}}====
{{col3|zh|簡單機械|簡單明瞭|頭腦簡單|簡單粗暴|四肢發達,頭腦簡單}}
===={{ĐM|desc}}====
{{CJKV|j=簡%単||かん%たん|간단|giản đơn}}
natjnnfolpmu9w0of0jbvgdce0tgt4g
Thể loại:Gốc từ tiếng Triều Tiên
14
392471
2344399
2026-04-12T04:52:24Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344399
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Danh từ có loại từ tiếng Lự
14
392472
2344400
2026-04-12T04:52:33Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2344400
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Tính từ tiếng Tấn
14
392473
2344401
2026-04-12T04:52:49Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344401
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
简单
0
392474
2344402
2026-04-12T04:53:44Z
WhoAlone
40420
Trang mới: “{{also|簡單|簡単}} =={{langname|zh}}== {{zh-see|簡單}}”
2344402
wikitext
text/x-wiki
{{also|簡單|簡単}}
=={{langname|zh}}==
{{zh-see|簡單}}
j1pwmtjjmmj3mr5wzl18161dpp6xzk8
간단
0
392475
2344403
2026-04-12T04:55:57Z
WhoAlone
40420
Trang mới: “=={{langname|ko}}== ==={{ĐM|etym}} 1=== {{ko-etym-Sino|間斷}}. ===={{ĐM|pron}}==== {{ko-IPA|l=y}} ===={{ĐM|noun}}==== {{ko-noun|hanja=間斷}} # {{lb|ko|formal}} Một khoảng [[dừng]] ngắn. ====={{ĐM|derived}}===== {{col3|ko|간단(間斷)하다}} ==={{ĐM|etym}} 2=== {{ko-etym-Sino|簡單}}. ===={{ĐM|pron}}==== {{ko-IPA}} ===={{ĐM|root}}==== {{ko-root|hanja=簡單}} # {{ko-root of|[[간단하다]]/[[간단히]]}}”
2344403
wikitext
text/x-wiki
=={{langname|ko}}==
==={{ĐM|etym}} 1===
{{ko-etym-Sino|間斷}}.
===={{ĐM|pron}}====
{{ko-IPA|l=y}}
===={{ĐM|noun}}====
{{ko-noun|hanja=間斷}}
# {{lb|ko|formal}} Một khoảng [[dừng]] ngắn.
====={{ĐM|derived}}=====
{{col3|ko|간단(間斷)하다}}
==={{ĐM|etym}} 2===
{{ko-etym-Sino|簡單}}.
===={{ĐM|pron}}====
{{ko-IPA}}
===={{ĐM|root}}====
{{ko-root|hanja=簡單}}
# {{ko-root of|[[간단하다]]/[[간단히]]}}
2uleaxjuvyndgi982qbnz71kc9x8z4y
Mô đun:bej-pronunciation
828
392476
2344413
2026-04-12T05:02:23Z
Hiyuune
50834
Trang mới: “local export = {} local m_IPA = require("Module:IPA") local m_table = require("Module:table") local lang = require("Module:languages").getByCode("bej") local U = mw.ustring.char local rsub = mw.ustring.gsub local rlower = mw.ustring.lower local rfind = mw.ustring.find local raised = U(0x031D) local consonants = "bpmwfdtɖʈznɲŋɳrlkɡhxjsvʃʷɣʤʔ̠" local C = "[" .. consonants .. "]" local vowels = "aeiou" local V = "[" .. vowels .. "]" local function track(page)…”
2344413
Scribunto
text/plain
local export = {}
local m_IPA = require("Module:IPA")
local m_table = require("Module:table")
local lang = require("Module:languages").getByCode("bej")
local U = mw.ustring.char
local rsub = mw.ustring.gsub
local rlower = mw.ustring.lower
local rfind = mw.ustring.find
local raised = U(0x031D)
local consonants = "bpmwfdtɖʈznɲŋɳrlkɡhxjsvʃʷɣʤʔ̠"
local C = "[" .. consonants .. "]"
local vowels = "aeiou"
local V = "[" .. vowels .. "]"
local function track(page)
require("Module:debug").track("bej-IPA/" .. page)
return true
end
local function rsub_repeatedly(term, foo, bar)
while true do
local new_term = rsub(term, foo, bar)
if new_term == term then
return term
end
term = new_term
end
end
local trigraphs = {
["nth"] = "ɳʈ",
["ndh"] = "ɳɖ",
}
local digraphs = {
["aa"] = "aː",
["ee"] = "eː",
["ii"] = "iː",
["oo"] = "oː",
["uu"] = "uː",
["áá"] = "áː",
["éé"] = "éː",
["íí"] = "íː",
["óó"] = "óː",
["úú"] = "úː",
["áa"] = "áː",
["ée"] = "éː",
["íi"] = "íː",
["óo"] = "óː",
["úu"] = "úː",
["aá"] = "áː",
["eé"] = "éː",
["ií"] = "íː",
["oó"] = "óː",
["uú"] = "úː",
["dh"] = "ɖ",
["gh"] = "ɣ",
["gw"] = "ɡʷ",
["nj"] = "ɲd͡ʒ",
["nk"] = "ŋk",
["ng"] = "ŋɡ",
["kw"] = "kʷ",
["sh"] = "ʃ",
["th"] = "ʈ",
["kh"] = "x",
}
local function flatmap(items, fun)
local new = {}
for _, item in ipairs(items) do
local results = fun(item)
mw.logObject(results, "results")
for _, result in ipairs(results) do
table.insert(new, result)
end
mw.logObject(new, "new")
end
return new
end
local phon = {
["'"] = "ʔ",
["a"] = "a",
["i"] = "i",
["u"] = "u",
["b"] = "b",
["d"] = "d",
["f"] = "f",
["g"] = "ɡ",
["h"] = "h",
["j"] = "d͡ʒ",
["k"] = "k",
["l"] = "l",
["m"] = "m",
["n"] = "n",
["r"] = "r",
["s"] = "s",
["t"] = "t",
["w"] = "w",
["y"] = "j",
[":"] = "ː",
["?"] = "ʔ"
}
function export.phonemic(text, post)
text = rlower(text)
text = rsub(text, " | ", "# | #")
text = "##" .. rsub(text, " ", "# #") .. "##"
-- basic phonology
for digraph, replacement in pairs(digraphs) do
text = rsub(text, digraph, replacement)
end
text = rsub(text, ".", phon)
text = rsub(text, "^ˈ%-", "-")
text = rsub(text, "(" .. C .. "*[áéíóú])", "ˈ%1")
if not rfind(text, "ˈ") then
text = rsub(text, text, "ˈ" .. text)
end
text = rsub(text, "á", "a")
text = rsub(text, "é", "e")
text = rsub(text, "í", "i")
text = rsub(text, "ó", "o")
text = rsub(text, "ú", "u")
text = rsub(text, "'", "ˈ")
text = rsub(text, "-", "")
local variants = {text}
local function flatmap_and_sub_pre(from, to1, to2)
variants =
flatmap(
variants,
function(item)
if rfind(item, from) then
local retval = {rsub_repeatedly(item, from, to1)}
if to2 then
m_table.insertIfNot(retval, rsub_repeatedly(item, from, to2))
end
return retval
else
return {item}
end
end
)
end
flatmap_and_sub_pre("#", "")
return variants
end
function export.IPA(frame)
local terms = {}
args = frame:getParent().args
local currentTitle = mw.loadData("Module:headword/data").pagename
for _, term in ipairs(args) do
if term == currentTitle then track("redundant") end
table.insert(terms, term)
end
if #terms == 0 then
terms = {currentTitle}
end
local results = {}
for _, term in ipairs(terms) do
local phonemic = export.phonemic(term)
for _, variant in ipairs(phonemic) do
table.insert(results, {pron = "/" .. variant .. "/"})
end
end
return "*" .. m_IPA.format_IPA_full { lang = lang, items = results }
end
return export
is07mbtm9m98v02rkmuxbtmi5ms0mvb
簡単
0
392477
2344414
2026-04-12T05:03:02Z
WhoAlone
40420
Trang mới: “{{also|簡單|简单}} =={{langname|ja}}== {{ja-kanjitab|かん|たん|yomi=on}} ==={{ĐM|etym}}=== Từ {{der|ja|ltc|-}} {{ltc-l|簡單|id=1,1}}. So sánh {{cog|nan-hbl|簡單|tr=kán-tan}} và {{cog|yue|簡單}}. ==={{ĐM|pron}}=== {{ja-pron|かんたん|acc=0|acc_ref=DJR,NHK,SMK5}} ==={{ĐM|adj}}=== {{ja-adj|infl=な|かんたん}} # [[dễ dàng]]. # [[đơn giản]]. # [[ngắn ngủi]]. ===={{ĐM|inflection}}==== {{ja-na|かんたん}} ===={{ĐM|antonym}}====…”
2344414
wikitext
text/x-wiki
{{also|簡單|简单}}
=={{langname|ja}}==
{{ja-kanjitab|かん|たん|yomi=on}}
==={{ĐM|etym}}===
Từ {{der|ja|ltc|-}} {{ltc-l|簡單|id=1,1}}. So sánh {{cog|nan-hbl|簡單|tr=kán-tan}} và {{cog|yue|簡單}}.
==={{ĐM|pron}}===
{{ja-pron|かんたん|acc=0|acc_ref=DJR,NHK,SMK5}}
==={{ĐM|adj}}===
{{ja-adj|infl=な|かんたん}}
# [[dễ dàng]].
# [[đơn giản]].
# [[ngắn ngủi]].
===={{ĐM|inflection}}====
{{ja-na|かんたん}}
===={{ĐM|antonym}}====
* {{antsense|đơn giản}} {{ja-r|複%雑|ふく%ざつ}}
==={{ĐM|noun}}===
{{ja-noun|かんたん}}
# Sự [[dễ dàng]].
# Sự [[đơn giản]].
# Sự [[ngắn ngủi]].
==={{ĐM|ref}}===
<references/>
:* {{R:Kanjipedia Kotoba|0001136200}}
:* {{R:Shogakukan}}
cnv01o93xjt0e01odv2nr7v7otepyqs
Bản mẫu:bej-IPA
10
392478
2344415
2026-04-12T05:03:36Z
Hiyuune
50834
Trang mới: “{{#invoke:bej-pronunciation|IPA}}<noinclude>{{tài liệu}}{{tcat|pron}}</noinclude>”
2344415
wikitext
text/x-wiki
{{#invoke:bej-pronunciation|IPA}}<noinclude>{{tài liệu}}{{tcat|pron}}</noinclude>
bdcrdk2d5ql8lb4qrhry9gudpks16xk
かんたん
0
392479
2344416
2026-04-12T05:04:02Z
WhoAlone
40420
Trang mới: “{{also|がんたん|かんだん}} =={{langname|ja}}== {{ja-see|簡単|感嘆|肝胆|邯鄲|管端}}”
2344416
wikitext
text/x-wiki
{{also|がんたん|かんだん}}
=={{langname|ja}}==
{{ja-see|簡単|感嘆|肝胆|邯鄲|管端}}
1bzo2dmx91j96qk14p96ndk71a85s94
Thể loại:Bản mẫu cách phát âm tiếng Beja
14
392480
2344417
2026-04-12T05:05:39Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344417
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Bản mẫu tiếng Beja
14
392481
2344418
2026-04-12T05:05:46Z
WhoAlone
40420
Trang mới: “{{auto cat}}”
2344418
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Mục từ có cách phát âm IPA tiếng Na Uy (Bokmål)
14
392482
2344421
2026-04-12T05:09:03Z
Kelly zhrm
58416
Trang mới: “{{auto cat}}”
2344421
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Bảo trì mục từ tiếng Na Uy (Bokmål)
14
392483
2344423
2026-04-12T05:09:55Z
Kelly zhrm
58416
Trang mới: “{{auto cat}}”
2344423
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
ひろい
0
392484
2344426
2026-04-12T05:13:25Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|alt=広い,弘い,宏い,博い,裕い:hiếm}} ==={{ĐM|etym}} 1=== {{ja-adj-ku|広し|firo}} Từ {{inh|ja|ojp|-}}, từ {{inh|ja|jpx-pro|*pirə}}. ===={{ĐM|pron}}==== {{ja-pron|acc=2}} {{ja-acc-table|adj-i|ひろい|acc=2|くて-form-acc=2,1|lemma=広い}} ===={{ĐM|adj}}==== {{ja-adj|infl=i}} # {{ja-def|広い|弘い|宏い}} [[rộng]] (bề ngang). #: {{ja-usex|[[その]][[川]]は'''広い'''。|その かわ は '''ひろい'…”
2344426
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|alt=広い,弘い,宏い,博い,裕い:hiếm}}
==={{ĐM|etym}} 1===
{{ja-adj-ku|広し|firo}} Từ {{inh|ja|ojp|-}}, từ {{inh|ja|jpx-pro|*pirə}}.
===={{ĐM|pron}}====
{{ja-pron|acc=2}}
{{ja-acc-table|adj-i|ひろい|acc=2|くて-form-acc=2,1|lemma=広い}}
===={{ĐM|adj}}====
{{ja-adj|infl=i}}
# {{ja-def|広い|弘い|宏い}} [[rộng]] (bề ngang).
#: {{ja-usex|[[その]][[川]]は'''広い'''。|その かわ は '''ひろい'''。|Dòng sông đó '''rộng'''.}}
# {{ja-def|広い|弘い|宏い}} [[rộng]] (diện tích).
#: {{ja-usex|[[一%番]]'''広い'''[[都%道%府%県]]|いち%ばん '''ひろい''' と%どう%ふ%けん|tỉnh '''lớn nhất''' của Nhật Bản}}
#* {{RQ:Botchan}}
#*: {{ja-usex|'''広い'''[[細%長い]][[部%屋]]の[[周%囲]]に[[机]]を[[並べる|並べて]][[みんな]][[腰]]を[[かける|かけて]][[いる]]。|'''ひろい''' ほそ%ながい へ%や の しゅう%い に つくえ を ならべて みんな こし を かけて いる。|Trong một căn phòng hình chữ nhật '''rộng rãi''', mỗi người ngồi trước một chiếc bàn được kê dọc theo các bức tường.}}
# {{ja-def|広い|弘い|宏い}} [[lớn]], [[rộng rãi]].
# {{ja-def|広い|弘い|宏い|博い}} [[rộng]].
====={{ĐM|inflection}}=====
{{ja-i}}
====={{ĐM|antonym}}=====
* {{antsense|rộng}} {{ja-r|狭い|せまい}}
====={{ĐM|derived}}=====
{{col|ja
|{{ja-r|だだっ広い|だだっぴろい}}, {{ja-r|徒広い|だだっぴろい}}
|{{ja-r|世%間は広い様で狭い|せ%けん は ひろい よう で せまい}}
|{{ja-r|幅の広い|はば の ひろい}}
|{{ja-r|幅%広い|はば%ひろい}}
|{{ja-r|広い支%持|ひろい し%じ}}
|{{ja-r|広い額|ひろい ひたい}}
|{{ja-r|心が広い|こころ が ひろい}}
|{{ja-r|心の広い|こころ の ひろい}}
|{{ja-r|手%広い|て%びろい}}
|{{ja-r|用%途が広い|よう%と が ひろい}}
|{{ja-r|用%途の広い|よう%と の ひろい}}
|{{ja-r|肩%身が広い|かた%み が ひろい}}
|{{ja-r|顔が広い|かお が ひろい}}
|{{ja-r|顔の広い|かお の ひろい}}
}}
===={{ĐM|ref}}====
* {{R:Shogakukan}}
==={{ĐM|etym}} 2===
{{ja-see|広井}}
dr635ndwux1jxd83snxbv4smg3l9d6a
2344430
2344426
2026-04-12T05:19:49Z
WhoAlone
40420
2344430
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|alt=広い,弘い,宏い,博い,裕い:hiếm}}
==={{ĐM|etym}} 1===
{{ja-adj-ku|広し|firo}} Từ {{inh|ja|ojp|-}}, từ {{inh|ja|jpx-pro|*pirə}}.
===={{ĐM|pron}}====
{{ja-pron|acc=2}}
{{ja-acc-table|adj-i|ひろい|acc=2|くて-form-acc=2,1|lemma=広い}}
===={{ĐM|adj}}====
{{ja-adj|infl=i}}
# {{ja-def|広い|弘い|宏い}} [[rộng]] (bề ngang).
#: {{ja-usex|[[その]][[川]]は'''広い'''。|その かわ は '''ひろい'''。|Dòng sông đó '''rộng'''.}}
# {{ja-def|広い|弘い|宏い}} [[rộng]] (diện tích).
#: {{ja-usex|[[一%番]]'''広い'''[[都%道%府%県]]|いち%ばん '''ひろい''' と%どう%ふ%けん|tỉnh '''lớn nhất''' của Nhật Bản}}
#* {{RQ:Botchan}}
#*: {{ja-usex|'''広い'''[[細%長い]][[部%屋]]の[[周%囲]]に[[机]]を[[並べる|並べて]][[みんな]][[腰]]を[[かける|かけて]][[いる]]。|'''ひろい''' ほそ%ながい へ%や の しゅう%い に つくえ を ならべて みんな こし を かけて いる。|Trong một căn phòng hình chữ nhật '''rộng rãi''', mỗi người ngồi trước một chiếc bàn được kê dọc theo các bức tường.}}
# {{ja-def|広い|弘い|宏い}} [[lớn]], [[rộng rãi]].
# {{ja-def|広い|弘い|宏い|博い}} [[rộng]].
====={{ĐM|inflection}}=====
{{ja-i}}
====={{ĐM|antonym}}=====
* {{antsense|rộng}} {{ja-r|狭い|せまい}}
====={{ĐM|derived}}=====
{{col|ja
|{{ja-r|だだっ広い|だだっぴろい}}, {{ja-r|徒広い|だだっぴろい}}
|{{ja-r|世%間は広い様で狭い|せ%けん は ひろい よう で せまい}}
|{{ja-r|幅の広い|はば の ひろい}}
|{{ja-r|幅%広い|はば%ひろい}}
|{{ja-r|広い支%持|ひろい し%じ}}
|{{ja-r|広い額|ひろい ひたい}}
|{{ja-r|心が広い|こころ が ひろい}}
|{{ja-r|心の広い|こころ の ひろい}}
|{{ja-r|手%広い|て%びろい}}
|{{ja-r|用%途が広い|よう%と が ひろい}}
|{{ja-r|用%途の広い|よう%と の ひろい}}
|{{ja-r|肩%身が広い|かた%み が ひろい}}
|{{ja-r|顔が広い|かお が ひろい}}
|{{ja-r|顔の広い|かお の ひろい}}
}}
====={{ĐM|desc}}=====
* {{desc|ycr|hiroy}}
===={{ĐM|ref}}====
* {{R:Shogakukan}}
==={{ĐM|etym}} 2===
{{ja-see|広井}}
an5pks9odxu6ubdbyduxrphmghjxnn4
Bản mẫu:scribal abbreviation of
10
392485
2344428
2026-04-12T05:18:26Z
Hiyuune
50834
Trang mới: “{{ {{#if:{{{lang|}}}|check deprecated lang param usage|no deprecated lang param usage}}|lang={{{lang|}}}|<!-- -->{{#invoke:form of/templates|form_of_t|chữ viết tắt thời trung đại của|cat=Chữ viết tắt thời trung đại|withencap=1}}<!-- -->}}<!-- --><noinclude>{{documentation}}</noinclude>”
2344428
wikitext
text/x-wiki
{{ {{#if:{{{lang|}}}|check deprecated lang param usage|no deprecated lang param usage}}|lang={{{lang|}}}|<!--
-->{{#invoke:form of/templates|form_of_t|chữ viết tắt thời trung đại của|cat=Chữ viết tắt thời trung đại|withencap=1}}<!--
-->}}<!--
--><noinclude>{{documentation}}</noinclude>
36s3hah63i0igbtlcp32y6hy6dhxto6
Bản mẫu:scrib of
10
392486
2344431
2026-04-12T05:20:04Z
Hiyuune
50834
Đổi hướng đến [[Bản mẫu:scribal abbreviation of]]
2344431
wikitext
text/x-wiki
#redirect [[Bản mẫu:scribal abbreviation of]]
j3j8uoz619dzn88ppnl533dcmph21fj
広い
0
392487
2344432
2026-04-12T05:20:18Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|ひろ|sort=ひろい|yomi=kun}} {{ja-see|ひろい}} ==={{ĐM|ref}}=== * {{R:Kanjipedia Kotoba|0002145900}}”
2344432
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|ひろ|sort=ひろい|yomi=kun}}
{{ja-see|ひろい}}
==={{ĐM|ref}}===
* {{R:Kanjipedia Kotoba|0002145900}}
mu51bc4gizguhjhuk1jxceb231y1mei
廣い
0
392488
2344433
2026-04-12T05:20:57Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-see|廣い}}”
2344433
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see|廣い}}
ei8z6354l46822ltotbvqs5uqemi6nr
2344434
2344433
2026-04-12T05:21:38Z
WhoAlone
40420
2344434
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab}}
{{ja-gv|ひろい}}
f5jekxnbrtl9xmejco9xx9rth3d5pm4
弘い
0
392489
2344444
2026-04-12T08:46:59Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|yomi=k|ひろ}} {{ja-see|ひろい}} ==={{ĐM|ref}}=== * {{R:Kanjipedia Kotoba|0002147900|<sup>▲</sup>弘い}}”
2344444
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|yomi=k|ひろ}}
{{ja-see|ひろい}}
==={{ĐM|ref}}===
* {{R:Kanjipedia Kotoba|0002147900|<sup>▲</sup>弘い}}
p8lfclnl2iduf8fppf25l52atg1ike4
宏い
0
392490
2344445
2026-04-12T08:48:57Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|yomi=k|ひろ}} {{ja-see|ひろい}} ==={{ĐM|ref}}=== * {{R:Kanjipedia Kotoba|0002182200|<sup>▲</sup>宏い}}”
2344445
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|yomi=k|ひろ}}
{{ja-see|ひろい}}
==={{ĐM|ref}}===
* {{R:Kanjipedia Kotoba|0002182200|<sup>▲</sup>宏い}}
1xkgt9jafbax6wv65xsyvxoymi8d2wa
博い
0
392491
2344446
2026-04-12T08:49:20Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|ひろ|yomi=k}} {{ja-see|ひろい}} ==={{ĐM|ref}}=== * {{R:Kanjipedia Kotoba|0005636600|<sup>△</sup>博い}}”
2344446
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|ひろ|yomi=k}}
{{ja-see|ひろい}}
==={{ĐM|ref}}===
* {{R:Kanjipedia Kotoba|0005636600|<sup>△</sup>博い}}
264ckw4zwigzh3mwfu6480ncxdub5sq
裕い
0
392492
2344447
2026-04-12T08:51:03Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|ひろ|yomi=k}} {{ja-gv|ひろい}}”
2344447
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|ひろ|yomi=k}}
{{ja-gv|ひろい}}
l8q6aczo85vylwvezeofxaqvmko9d5v
ひろく
0
392493
2344448
2026-04-12T08:54:43Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|alt=広く,廣く}} ==={{ĐM|etym}}=== [[連用形|Ren'yōkei]] của {{ja-r|ひろい|gloss=[[rộng]]}}. ==={{ĐM|adv}}=== {{ja-pos|adv}} # Một cách [[rộng rãi]]. #: {{ja-usex|'''広く'''[[知る|知ら]]れている|'''ひろく''' しられている|được biết đến '''rộng rãi'''}} # Một cách [[phổ biến]]. ==={{ĐM|see also}}=== * {{ja-r|あまねく}}”
2344448
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|alt=広く,廣く}}
==={{ĐM|etym}}===
[[連用形|Ren'yōkei]] của {{ja-r|ひろい|gloss=[[rộng]]}}.
==={{ĐM|adv}}===
{{ja-pos|adv}}
# Một cách [[rộng rãi]].
#: {{ja-usex|'''広く'''[[知る|知ら]]れている|'''ひろく''' しられている|được biết đến '''rộng rãi'''}}
# Một cách [[phổ biến]].
==={{ĐM|see also}}===
* {{ja-r|あまねく}}
qlvwk9s82dkucp5enw3i2r472yxgmq5
hiroi
0
392494
2344449
2026-04-12T08:55:12Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== ==={{ĐM|pron}}=== {{ja-romaji}} # {{ja-romanization of|ひろい}}”
2344449
wikitext
text/x-wiki
=={{langname|ja}}==
==={{ĐM|pron}}===
{{ja-romaji}}
# {{ja-romanization of|ひろい}}
e8l3ijzweoyei9x00f1xxjxvxzns86h
hiroku
0
392495
2344450
2026-04-12T08:56:57Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== ==={{ĐM|rom}}=== {{ja-rom}} # {{ja-rom of|ひろく}}”
2344450
wikitext
text/x-wiki
=={{langname|ja}}==
==={{ĐM|rom}}===
{{ja-rom}}
# {{ja-rom of|ひろく}}
4hb0ygs60p3pnzjt8j30o3u3dxtlt7k
広く
0
392496
2344451
2026-04-12T08:57:22Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|ひろ|yomi=k}} {{ja-see|ひろく}}”
2344451
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|ひろ|yomi=k}}
{{ja-see|ひろく}}
bvckj40ggpgnbrdlwd84ubwm6j6586v
廣く
0
392497
2344452
2026-04-12T08:58:04Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|ひろ|yomi=k}} {{ja-see|ひろく}}”
2344452
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|ひろ|yomi=k}}
{{ja-see|ひろく}}
bvckj40ggpgnbrdlwd84ubwm6j6586v
あまねく
0
392498
2344453
2026-04-12T09:03:06Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|alt=遍く,普く,洽く,汎く}} ==={{ĐM|etym}}=== Từ dạng tính từ {{mention|ja|あまねし|tr=amaneshi}}. Xem mục từ này để biết thêm từ nguyên. ==={{ĐM|pron}}=== {{ja-pron|acc=3|acc_ref=DJR}} ==={{ĐM|adv}}=== {{ja-pos|adverb}} # Một cách [[rộng rãi]]; [[khắp nơi]]. ===={{ĐM|see also}}==== * {{ja-r|ひろく}} ==={{ĐM|ref}}=== <references />”
2344453
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|alt=遍く,普く,洽く,汎く}}
==={{ĐM|etym}}===
Từ dạng tính từ {{mention|ja|あまねし|tr=amaneshi}}. Xem mục từ này để biết thêm từ nguyên.
==={{ĐM|pron}}===
{{ja-pron|acc=3|acc_ref=DJR}}
==={{ĐM|adv}}===
{{ja-pos|adverb}}
# Một cách [[rộng rãi]]; [[khắp nơi]].
===={{ĐM|see also}}====
* {{ja-r|ひろく}}
==={{ĐM|ref}}===
<references />
s932opq5w3uy7v6a93ym7q8c5w7kgst
amaneku
0
392499
2344454
2026-04-12T09:03:32Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== ==={{ĐM|rom}}=== {{ja-rom}} # {{ja-rom of|あまねく}}”
2344454
wikitext
text/x-wiki
=={{langname|ja}}==
==={{ĐM|rom}}===
{{ja-rom}}
# {{ja-rom of|あまねく}}
hznksuco1mt0svzxi8jpds5qsicx1l9
遍く
0
392500
2344455
2026-04-12T09:05:07Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|あまね|yomi=k}} {{ja-see|あまねく}} ==={{ĐM|ref}}=== * {{R:Kanjipedia Kotoba|0006273100|<sup>△</sup>遍く}}”
2344455
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|あまね|yomi=k}}
{{ja-see|あまねく}}
==={{ĐM|ref}}===
* {{R:Kanjipedia Kotoba|0006273100|<sup>△</sup>遍く}}
k0n9vrzj2k0xh8eqcocb6f2ba773hx7
普く
0
392501
2344456
2026-04-12T09:05:35Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|あまね|yomi=k}} {{ja-see|あまねく}} ==={{ĐM|ref}}=== * {{R:Kanjipedia Kotoba|0006056700|<sup>△</sup>普く}}”
2344456
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|あまね|yomi=k}}
{{ja-see|あまねく}}
==={{ĐM|ref}}===
* {{R:Kanjipedia Kotoba|0006056700|<sup>△</sup>普く}}
pp05j3m4fzlv10hc6undumuipzjw9w1
洽く
0
392502
2344457
2026-04-12T09:08:16Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|あまね|yomi=k}} {{ja-see|あまねく}}”
2344457
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|あまね|yomi=k}}
{{ja-see|あまねく}}
8scl2xj7aplgzh97e468yavuyszv0kv
汎く
0
392503
2344458
2026-04-12T09:08:35Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|あまね|yomi=k}} {{ja-see|あまねく}}”
2344458
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|あまね|yomi=k}}
{{ja-see|あまねく}}
8scl2xj7aplgzh97e468yavuyszv0kv
テレビばんぐみ
0
392504
2344459
2026-04-12T09:13:23Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-see|テレビ番組}}”
2344459
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see|テレビ番組}}
16jt6z72n54dyrdx84e7p65kaul6krg
テレビンゆ
0
392505
2344460
2026-04-12T09:14:44Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-see|テレビン油}}”
2344460
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see|テレビン油}}
iv73nsjkzav7d1piuxnod7p0fbmw6d0
なんかいじしん
0
392506
2344461
2026-04-12T09:15:12Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-see|南海地震}}”
2344461
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see|南海地震}}
6s7fqohlgxzk18y0phbxtmu71743psi
南蠻烏瓜
0
392507
2344463
2026-04-12T09:16:43Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-see|南蛮烏瓜}}”
2344463
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see|南蛮烏瓜}}
3wv71n9fovimj6u1syclndo1be4fpdf
ナンバンカラスウリ
0
392508
2344464
2026-04-12T09:16:57Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-see|南蛮烏瓜}}”
2344464
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see|南蛮烏瓜}}
3wv71n9fovimj6u1syclndo1be4fpdf
なんばんからすうり
0
392509
2344465
2026-04-12T09:17:00Z
WhoAlone
40420
Trang mới: “=={{langname|ja}}== {{ja-see|南蛮烏瓜}}”
2344465
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see|南蛮烏瓜}}
3wv71n9fovimj6u1syclndo1be4fpdf
loăng
0
392510
2344466
2026-04-12T09:18:40Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # [[cây]]. #:{{ux|sed|'''loăng '''pơlái|'''cây '''cối}} ==={{đm|ref}}=== {{R:VOV}}”
2344466
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# [[cây]].
#:{{ux|sed|'''loăng '''pơlái|'''cây '''cối}}
==={{đm|ref}}===
{{R:VOV}}
28vj5gnxqrfy386vf5lylwi2y2zxku0
loăng plâi kâ
0
392511
2344468
2026-04-12T09:26:06Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # [[cây ăn trái]]. #:{{ux|sed|'''loăng plâi kâ''' hên hěng tung kơdrum|'''cây ăn trái''' đầy vườn}} ==={{đm|ref}}=== {{R:VOV}}”
2344468
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# [[cây ăn trái]].
#:{{ux|sed|'''loăng plâi kâ''' hên hěng tung kơdrum|'''cây ăn trái''' đầy vườn}}
==={{đm|ref}}===
{{R:VOV}}
3ean8fbolzkyuar1xt3z5aldtwaxx6s
loăng tróu
0
392512
2344469
2026-04-12T09:27:28Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # [[cây]] [[bằng lăng]]. #:{{ux|sed|'''loăng tróu''' hngêi ai reăng lěm ó|'''Cây bằng lăng''' có hoa rất đẹp}} ==={{đm|ref}}=== {{R:VOV}} {{c|sed|Cây}}”
2344469
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# [[cây]] [[bằng lăng]].
#:{{ux|sed|'''loăng tróu''' hngêi ai reăng lěm ó|'''Cây bằng lăng''' có hoa rất đẹp}}
==={{đm|ref}}===
{{R:VOV}}
{{c|sed|Cây}}
abo93fg1ony1qgp8pki1yfeu1sjazk6
loăng plâi ƀơr
0
392513
2344470
2026-04-12T09:29:13Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # [[cây]] [[bơ]]. #:{{ux|sed|'''loăng plâi ƀơr''' pêt pa ngiâ hngêi|'''cây bơ''' trồng trước nhà}} ==={{đm|ref}}=== {{R:VOV}} {{c|sed|Cây}}”
2344470
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# [[cây]] [[bơ]].
#:{{ux|sed|'''loăng plâi ƀơr''' pêt pa ngiâ hngêi|'''cây bơ''' trồng trước nhà}}
==={{đm|ref}}===
{{R:VOV}}
{{c|sed|Cây}}
i4wbp10j5sf480zrwukcng28uvtyfg8
loăng chêh
0
392514
2344471
2026-04-12T09:31:17Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # [[cây]] [[bút]]. #:{{ux|sed|nôu rôe '''loăng chêh''' ăm o mơhriâm|Mẹ mua '''bút '''cho em đi học}} ==={{đm|ref}}=== {{R:VOV}}”
2344471
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# [[cây]] [[bút]].
#:{{ux|sed|nôu rôe '''loăng chêh''' ăm o mơhriâm|Mẹ mua '''bút '''cho em đi học}}
==={{đm|ref}}===
{{R:VOV}}
7botoxfj6i1ndu7nluxtvzxxg2sncgr
loăng ka te
0
392515
2344472
2026-04-12T09:32:42Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # [[cây]] [[cà te]]. #:{{ux|sed|ai môi xiâm '''loăng ka te'''|Có một '''cây cà te'''}} ==={{đm|ref}}=== {{R:VOV}} {{c|sed|Cây}}”
2344472
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# [[cây]] [[cà te]].
#:{{ux|sed|ai môi xiâm '''loăng ka te'''|Có một '''cây cà te'''}}
==={{đm|ref}}===
{{R:VOV}}
{{c|sed|Cây}}
dyw78uj8e5tucupazcnb31amaccpjow
nhâ chó đẻ
0
392516
2344473
2026-04-12T09:34:39Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # [[cây]] [[chó đẻ]]. #:{{ux|sed|'''nhâ chó đẻ''' huăn xêh lâp lu|'''Cây chó đẻ''' mọc hoang khắp nơi}} ==={{đm|ref}}=== {{R:VOV}}”
2344473
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# [[cây]] [[chó đẻ]].
#:{{ux|sed|'''nhâ chó đẻ''' huăn xêh lâp lu|'''Cây chó đẻ''' mọc hoang khắp nơi}}
==={{đm|ref}}===
{{R:VOV}}
tn19z99avsxxs6fhuzwkkj9oocftua3
loăng nhâ
0
392517
2344474
2026-04-12T10:24:18Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # [[cây cỏ]]. #:{{ux|sed|'''loăng nhâ''' amê tiah lâi?|'''Cây cỏ''' ở đó thế nào?}} ==={{đm|ref}}=== {{R:VOV}} {{c|sed|Cây}}”
2344474
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# [[cây cỏ]].
#:{{ux|sed|'''loăng nhâ''' amê tiah lâi?|'''Cây cỏ''' ở đó thế nào?}}
==={{đm|ref}}===
{{R:VOV}}
{{c|sed|Cây}}
n2q8ln99mjoiwd1ddtud9wsr7q8l33d
nhâ loăng
0
392518
2344475
2026-04-12T10:28:07Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # {{alt form of|sed|loăng nhâ}} ==={{đm|ref}}=== {{R:VOV}} {{c|sed|Cây}}”
2344475
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# {{alt form of|sed|loăng nhâ}}
==={{đm|ref}}===
{{R:VOV}}
{{c|sed|Cây}}
kb0474dco78ngl5simanxhfs65em2r7
loăng rơxế
0
392519
2344476
2026-04-12T10:29:09Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # [[cây]] [[cọ]]. #:{{ux|sed|văng ki kố ai hên '''loăng rơxế'''|Đồi này có nhiều '''cây cọ'''}} ==={{đm|ref}}=== {{R:VOV}} {{c|sed|Cây}}”
2344476
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# [[cây]] [[cọ]].
#:{{ux|sed|văng ki kố ai hên '''loăng rơxế'''|Đồi này có nhiều '''cây cọ'''}}
==={{đm|ref}}===
{{R:VOV}}
{{c|sed|Cây}}
syjobkhf7vvl8c94v3dc1ssrjsowezp
loăng plâi kơchâi nhâ
0
392520
2344477
2026-04-12T10:36:51Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # [[cây cối]]. #:{{ux|sed|rak ngăn '''loăng plâi kơchâi nhâ''' tung kơdrum|Bảo vệ '''cây cối''' trong vườn}} ==={{đm|ref}}=== {{R:VOV}} {{c|sed|Cây}}”
2344477
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# [[cây cối]].
#:{{ux|sed|rak ngăn '''loăng plâi kơchâi nhâ''' tung kơdrum|Bảo vệ '''cây cối''' trong vườn}}
==={{đm|ref}}===
{{R:VOV}}
{{c|sed|Cây}}
flobzo3w6djuriqjkslerk1ob6e20ta
loăng plâi cơm nguội
0
392521
2344478
2026-04-12T10:37:37Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # [[cây]] [[cơm]] [[nguội]]. #:{{ux|sed|'''loăng plâi cơm nguội''' a Việt Nam|'''Cây cơm nguội''' ở Việt Nam}} ==={{đm|ref}}=== {{R:VOV}} {{c|sed|Cây}}”
2344478
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# [[cây]] [[cơm]] [[nguội]].
#:{{ux|sed|'''loăng plâi cơm nguội''' a Việt Nam|'''Cây cơm nguội''' ở Việt Nam}}
==={{đm|ref}}===
{{R:VOV}}
{{c|sed|Cây}}
5eyh656wvfg5hqywjqa94uklwt5z975
luông pli kă
0
392522
2344479
2026-04-12T10:42:12Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # {{label|sed|dialectal}} [[cây ăn trái]]. ==={{đm|ref}}=== {{R:VOV}}”
2344479
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# {{label|sed|dialectal}} [[cây ăn trái]].
==={{đm|ref}}===
{{R:VOV}}
5b54ifjvqhyll3rphgzzz5q6zx82d2g
luông trol
0
392523
2344480
2026-04-12T10:43:10Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # {{label|sed|dialectal}} [[cây]] [[bằng lăng]]. ==={{đm|ref}}=== {{R:VOV}}”
2344480
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# {{label|sed|dialectal}} [[cây]] [[bằng lăng]].
==={{đm|ref}}===
{{R:VOV}}
iy2b8z387h3ug2vwr9zd1caibofnwlx
luông jêh
0
392524
2344481
2026-04-12T10:43:38Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # {{label|sed|dialectal}} [[cây]] [[bút]]. ==={{đm|ref}}=== {{R:VOV}}”
2344481
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# {{label|sed|dialectal}} [[cây]] [[bút]].
==={{đm|ref}}===
{{R:VOV}}
jwgi54tltyj04owfd0dhwa0baznpfyc
luông nhă
0
392525
2344482
2026-04-12T10:48:36Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # {{label|sed|dialectal}} [[cây cỏ]]. ==={{đm|ref}}=== {{R:VOV}}”
2344482
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# {{label|sed|dialectal}} [[cây cỏ]].
==={{đm|ref}}===
{{R:VOV}}
i58ev03gbunudzol7364afcwh1tcs0s
luông rơxế
0
392526
2344483
2026-04-12T10:48:57Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # {{label|sed|dialectal}} [[cây]] [[cọ]]. ==={{đm|ref}}=== {{R:VOV}}”
2344483
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# {{label|sed|dialectal}} [[cây]] [[cọ]].
==={{đm|ref}}===
{{R:VOV}}
bdcw0v76amiriweewk8umz4hcpbsx1p
long rơxai
0
392527
2344484
2026-04-12T10:49:35Z
WhoAlone
40420
Trang mới: “=={{langname|sed}}== ==={{ĐM|noun}}=== {{head|sed|Danh từ}} # {{label|sed|dialectal}} [[cây]] [[cọ]]. ==={{đm|ref}}=== {{R:VOV}}”
2344484
wikitext
text/x-wiki
=={{langname|sed}}==
==={{ĐM|noun}}===
{{head|sed|Danh từ}}
# {{label|sed|dialectal}} [[cây]] [[cọ]].
==={{đm|ref}}===
{{R:VOV}}
bdcw0v76amiriweewk8umz4hcpbsx1p
Thể loại:Danh từ có loại từ ᦀᧃ tiếng Lự
14
392528
2344486
2026-04-12T11:49:01Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2344486
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Danh từ có loại từ ᦐᦽᧈ tiếng Lự
14
392529
2344491
2026-04-12T11:56:43Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2344491
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
ᦷᦂᧅᧈᦟᦻ
0
392530
2344492
2026-04-12T11:58:07Z
Hiyuune
50834
+ khb
2344492
wikitext
text/x-wiki
=={{langname|khb}}==
==={{section|etym}}===
{{affix|khb|ᦷᦂᧅᧈ|ᦟᦻ}}
==={{section|pron}}===
{{khb-pron|ᦷᦂᧅᧈ-ᦟᦻ}}
==={{section|n}}===
{{khb-noun|ᦐᦽᧈ}}
# [[thùng thư|Thùng thư]], [[hòm thư]].
==={{section|ref}}===
* {{R:khb:Hanna}}
6f8q4zwqnl3kjmqvkij209yheey2b4p