위키낱말사전 kowiktionary https://ko.wiktionary.org/wiki/%EC%9C%84%ED%82%A4%EB%82%B1%EB%A7%90%EC%82%AC%EC%A0%84:%EB%8C%80%EB%AC%B8 MediaWiki 1.47.0-wmf.4 case-sensitive 미디어 특수 토론 사용자 사용자토론 위키낱말사전 위키낱말사전토론 파일 파일토론 미디어위키 미디어위키토론 틀토론 도움말 도움말토론 분류 분류토론 부록 부록 토론 TimedText TimedText talk 모듈 모듈토론 행사 행사토론 부처 0 116671 4484375 4384016 2026-05-29T03:11:41Z Jeebeen 13056 /* 어원 1 */ 4484375 wikitext text/x-wiki == 한국어 == === 발음 === {{발음 듣기|}} {{ko-IPA}} === 어원 1 === {{etymon|ko|inh|ko-ear>부쳐|id=불교}} * {{der|ko|sa|बुद्धत्व}}에서 {{der|ko|och|佛體}}로 전래되었고, 이를 {{inh|ko|qfa-kor-pro|*pwutukye}}로, {{inh|ko|oko-lat|佛體|tr=*PWUthye?}}를 거쳤고, {{inh|ko|okm|부텨}}에서 {{pron|ko|t^h}}가 {{pron|ko|구개음화}}되면서 {{inh|ko|ko-ear|부쳐}}가 됨. ==== 명사 ==== {{한국어 명사|한자=佛體}} # [[석가모니]]의 다른 이름. # 불도를 깨달은 성인. # 부처의 형상을 표현한 상. 나무ㆍ돌ㆍ쇠ㆍ흙 따위로 만든, 부처의 소상(塑像)이나 화상(畫像)을 통틀어 이르는 말이다. #: {{예문|ko|{{l|ko|향|id=Q273131}}을 [[사르고]] '''부처''' 앞에 [[절을 올리다|절을 올렸다]].}} ==== 번역 ==== {{외국어|덧=역사적으로 불교적 배경이 있는 어휘들| * 고대 그리스어(grc) ** 코이네 그리스어: {{t|grc|Βοδδο}} * 광둥어(yue): {{t|yue|佛陀}} * 만주어(mnc): {{t|mnc|ᡶᡠᠴᡳᡥᡳ}} * 중세 몽골어(xng): {{t|xng|}} * 박트리아어(xbc): {{t|xbc|Βοδδο}} * 버마어(my): {{t|my|ဗုဒ္ဓ}}, {{t|my|ရှင်စော}}, {{t|my|မုနေ့}}, {{t|my|မာရဇိန်}}, {{t|my|ဘုရားရှင်}}, {{t|my|စိန္တေယျာ}}, {{t|my|ဘုရားမြတ်စွာ}}, {{t|my|မြတ်စွာဘုရား}}, {{t|my|ကိုယ်တော်မြတ်}} * 산스크리트어(sa): {{t|sa|बुद्धत्व}} * 여진어(juc): futuchi * 종카어(dz): {{t|dz|སངས་རྒྱས།}} * 중국어(zh): {{t|zh|成佛}} }} {{외국어|덧=불교적 배경은 없으나, 이를 설명하고 번역하기 위한 용어들| * 그리스어(el): * 러시아어(ru): {{t|ru|Будда}} * 몽골어(mn): {{t|mn|Будда}} * 아랍어(ar): * 우크라이나어(uk): {{t|uk|Будда}} * 영어(en): {{t|en|Buddhahood}}, {{t|en|Buddha}} * 카자흐어(kk): }} === 어원 2 === ==== 명사 ==== {{한국어 명사|한자=夫妻}} # 남편과 아내를 아울러 이르는 말. {{국립국어원}} [[분류:표준어 자립명사]] [[분류:표준어 단일어명사]] lwkvysy9rmr6r1pr7w2k1fqats8lts3 4484378 4484375 2026-05-29T03:17:41Z Jeebeen 13056 /* 어원 1 */ 4484378 wikitext text/x-wiki == 한국어 == === 발음 === {{발음 듣기|}} {{ko-IPA}} === 어원 1 === {{etymon|ko|inh|ko-ear>부쳐>불교|id=불교}} * {{der|ko|sa|बुद्धत्व}}에서 {{der|ko|och|佛體}}로 전래되었고, 이를 {{inh|ko|qfa-kor-pro|*pwutukye}}로, {{inh|ko|oko-lat|佛體|tr=*PWUthye?}}를 거쳤고, {{inh|ko|okm|부텨}}에서 {{pron|ko|t^h}}가 {{pron|ko|구개음화}}되면서 {{inh|ko|ko-ear|부쳐}}가 됨. ==== 명사 ==== {{한국어 명사|한자=佛體}} # [[석가모니]]의 다른 이름. # 불도를 깨달은 성인. # 부처의 형상을 표현한 상. 나무ㆍ돌ㆍ쇠ㆍ흙 따위로 만든, 부처의 소상(塑像)이나 화상(畫像)을 통틀어 이르는 말이다. #: {{예문|ko|{{l|ko|향|id=Q273131}}을 [[사르고]] '''부처''' 앞에 [[절을 올리다|절을 올렸다]].}} ==== 번역 ==== {{외국어|덧=역사적으로 불교적 배경이 있는 어휘들| * 고대 그리스어(grc) ** 코이네 그리스어: {{t|grc|Βοδδο}} * 광둥어(yue): {{t|yue|佛陀}} * 만주어(mnc): {{t|mnc|ᡶᡠᠴᡳᡥᡳ}} * 중세 몽골어(xng): {{t|xng|}} * 박트리아어(xbc): {{t|xbc|Βοδδο}} * 버마어(my): {{t|my|ဗုဒ္ဓ}}, {{t|my|ရှင်စော}}, {{t|my|မုနေ့}}, {{t|my|မာရဇိန်}}, {{t|my|ဘုရားရှင်}}, {{t|my|စိန္တေယျာ}}, {{t|my|ဘုရားမြတ်စွာ}}, {{t|my|မြတ်စွာဘုရား}}, {{t|my|ကိုယ်တော်မြတ်}} * 산스크리트어(sa): {{t|sa|बुद्धत्व}} * 여진어(juc): futuchi * 종카어(dz): {{t|dz|སངས་རྒྱས།}} * 중국어(zh): {{t|zh|成佛}} }} {{외국어|덧=불교적 배경은 없으나, 이를 설명하고 번역하기 위한 용어들| * 그리스어(el): * 러시아어(ru): {{t|ru|Будда}} * 몽골어(mn): {{t|mn|Будда}} * 아랍어(ar): * 우크라이나어(uk): {{t|uk|Будда}} * 영어(en): {{t|en|Buddhahood}}, {{t|en|Buddha}} * 카자흐어(kk): }} === 어원 2 === ==== 명사 ==== {{한국어 명사|한자=夫妻}} # 남편과 아내를 아울러 이르는 말. {{국립국어원}} [[분류:표준어 자립명사]] [[분류:표준어 단일어명사]] j5jj1yw8ewzt9tmqn5559alb6e8c71p 4484379 4484378 2026-05-29T03:18:08Z Jeebeen 13056 /* 어원 1 */ 4484379 wikitext text/x-wiki == 한국어 == === 발음 === {{발음 듣기|}} {{ko-IPA}} === 어원 1 === {{etymon|ko|inh|ko-ear>부쳐>불교|id=불교|tree=1|text=+}} * {{der|ko|sa|बुद्धत्व}}에서 {{der|ko|och|佛體}}로 전래되었고, 이를 {{inh|ko|qfa-kor-pro|*pwutukye}}로, {{inh|ko|oko-lat|佛體|tr=*PWUthye?}}를 거쳤고, {{inh|ko|okm|부텨}}에서 {{pron|ko|t^h}}가 {{pron|ko|구개음화}}되면서 {{inh|ko|ko-ear|부쳐}}가 됨. ==== 명사 ==== {{한국어 명사|한자=佛體}} # [[석가모니]]의 다른 이름. # 불도를 깨달은 성인. # 부처의 형상을 표현한 상. 나무ㆍ돌ㆍ쇠ㆍ흙 따위로 만든, 부처의 소상(塑像)이나 화상(畫像)을 통틀어 이르는 말이다. #: {{예문|ko|{{l|ko|향|id=Q273131}}을 [[사르고]] '''부처''' 앞에 [[절을 올리다|절을 올렸다]].}} ==== 번역 ==== {{외국어|덧=역사적으로 불교적 배경이 있는 어휘들| * 고대 그리스어(grc) ** 코이네 그리스어: {{t|grc|Βοδδο}} * 광둥어(yue): {{t|yue|佛陀}} * 만주어(mnc): {{t|mnc|ᡶᡠᠴᡳᡥᡳ}} * 중세 몽골어(xng): {{t|xng|}} * 박트리아어(xbc): {{t|xbc|Βοδδο}} * 버마어(my): {{t|my|ဗုဒ္ဓ}}, {{t|my|ရှင်စော}}, {{t|my|မုနေ့}}, {{t|my|မာရဇိန်}}, {{t|my|ဘုရားရှင်}}, {{t|my|စိန္တေယျာ}}, {{t|my|ဘုရားမြတ်စွာ}}, {{t|my|မြတ်စွာဘုရား}}, {{t|my|ကိုယ်တော်မြတ်}} * 산스크리트어(sa): {{t|sa|बुद्धत्व}} * 여진어(juc): futuchi * 종카어(dz): {{t|dz|སངས་རྒྱས།}} * 중국어(zh): {{t|zh|成佛}} }} {{외국어|덧=불교적 배경은 없으나, 이를 설명하고 번역하기 위한 용어들| * 그리스어(el): * 러시아어(ru): {{t|ru|Будда}} * 몽골어(mn): {{t|mn|Будда}} * 아랍어(ar): * 우크라이나어(uk): {{t|uk|Будда}} * 영어(en): {{t|en|Buddhahood}}, {{t|en|Buddha}} * 카자흐어(kk): }} === 어원 2 === ==== 명사 ==== {{한국어 명사|한자=夫妻}} # 남편과 아내를 아울러 이르는 말. {{국립국어원}} [[분류:표준어 자립명사]] [[분류:표준어 단일어명사]] cryiuer7l03y2gdnvbfbgru7mqblcwj 4484382 4484379 2026-05-29T03:45:15Z Jeebeen 13056 /* 명사 */ 4484382 wikitext text/x-wiki == 한국어 == === 발음 === {{발음 듣기|}} {{ko-IPA}} === 어원 1 === {{etymon|ko|inh|ko-ear>부쳐>불교|id=불교|tree=1|text=+}} * {{der|ko|sa|बुद्धत्व}}에서 {{der|ko|och|佛體}}로 전래되었고, 이를 {{inh|ko|qfa-kor-pro|*pwutukye}}로, {{inh|ko|oko-lat|佛體|tr=*PWUthye?}}를 거쳤고, {{inh|ko|okm|부텨}}에서 {{pron|ko|t^h}}가 {{pron|ko|구개음화}}되면서 {{inh|ko|ko-ear|부쳐}}가 됨. ==== 명사 ==== {{한국어 명사|한자=佛體}} # [[석가모니]]의 다른 이름. # 불도를 깨달은 성인. # 부처의 형상을 표현한 상. 나무ㆍ돌ㆍ쇠ㆍ흙 따위로 만든, 부처의 소상(塑像)이나 화상(畫像)을 통틀어 이르는 말이다. #: {{예문|ko|{{l|ko|향|id=Q273131}}을 [[사르다|사르고]] '''부처''' 앞에 [[절을 올리다|절을 올렸다]].}} ==== 번역 ==== {{외국어|덧=역사적으로 불교적 배경이 있는 어휘들| * 고대 그리스어(grc) ** 코이네 그리스어: {{t|grc|Βοδδο}} * 광둥어(yue): {{t|yue|佛陀}} * 만주어(mnc): {{t|mnc|ᡶᡠᠴᡳᡥᡳ}} * 중세 몽골어(xng): {{t|xng|}} * 박트리아어(xbc): {{t|xbc|Βοδδο}} * 버마어(my): {{t|my|ဗုဒ္ဓ}}, {{t|my|ရှင်စော}}, {{t|my|မုနေ့}}, {{t|my|မာရဇိန်}}, {{t|my|ဘုရားရှင်}}, {{t|my|စိန္တေယျာ}}, {{t|my|ဘုရားမြတ်စွာ}}, {{t|my|မြတ်စွာဘုရား}}, {{t|my|ကိုယ်တော်မြတ်}} * 산스크리트어(sa): {{t|sa|बुद्धत्व}} * 여진어(juc): futuchi * 종카어(dz): {{t|dz|སངས་རྒྱས།}} * 중국어(zh): {{t|zh|成佛}} }} {{외국어|덧=불교적 배경은 없으나, 이를 설명하고 번역하기 위한 용어들| * 그리스어(el): * 러시아어(ru): {{t|ru|Будда}} * 몽골어(mn): {{t|mn|Будда}} * 아랍어(ar): * 우크라이나어(uk): {{t|uk|Будда}} * 영어(en): {{t|en|Buddhahood}}, {{t|en|Buddha}} * 카자흐어(kk): }} === 어원 2 === ==== 명사 ==== {{한국어 명사|한자=夫妻}} # 남편과 아내를 아울러 이르는 말. {{국립국어원}} [[분류:표준어 자립명사]] [[분류:표준어 단일어명사]] e20jngirax3qejhpye14z9r4kkqxgsv 4484383 4484382 2026-05-29T03:58:19Z Jeebeen 13056 /* 어원 1 */ 4484383 wikitext text/x-wiki == 한국어 == === 발음 === {{발음 듣기|}} {{ko-IPA}} === 어원 1 === {{etymon|ko|inh|ko-ear>부쳐>불교|id=불교|tree=1|text=+}} * {{der|ko|sa|बुद्धत्व}}에서 {{der|ko|och|佛體}}로 전래되었고, 이를 {{inh|ko|qfa-kor-pro|*pwutukye}}로, {{inh|ko|oko-lat|佛體|tr=*PWUthye?}}를 거쳤고, {{inh|ko|okm|부텨}}에서 {{pron|ko|t^h}}가 {{pron|ko|구개음화}}되면서 {{inh|ko|ko-ear|부쳐}}가 됨. * {{cog|mnc|ᡶᡠᠴᡳᡥᡳ}}와 동계어 ==== 명사 ==== {{한국어 명사|한자=佛體}} # [[석가모니]]의 다른 이름. # 불도를 깨달은 성인. # 부처의 형상을 표현한 상. 나무ㆍ돌ㆍ쇠ㆍ흙 따위로 만든, 부처의 소상(塑像)이나 화상(畫像)을 통틀어 이르는 말이다. #: {{예문|ko|{{l|ko|향|id=Q273131}}을 [[사르다|사르고]] '''부처''' 앞에 [[절을 올리다|절을 올렸다]].}} ==== 번역 ==== {{외국어|덧=역사적으로 불교적 배경이 있는 어휘들| * 고대 그리스어(grc) ** 코이네 그리스어: {{t|grc|Βοδδο}} * 광둥어(yue): {{t|yue|佛陀}} * 만주어(mnc): {{t|mnc|ᡶᡠᠴᡳᡥᡳ}} * 중세 몽골어(xng): {{t|xng|}} * 박트리아어(xbc): {{t|xbc|Βοδδο}} * 버마어(my): {{t|my|ဗုဒ္ဓ}}, {{t|my|ရှင်စော}}, {{t|my|မုနေ့}}, {{t|my|မာရဇိန်}}, {{t|my|ဘုရားရှင်}}, {{t|my|စိန္တေယျာ}}, {{t|my|ဘုရားမြတ်စွာ}}, {{t|my|မြတ်စွာဘုရား}}, {{t|my|ကိုယ်တော်မြတ်}} * 산스크리트어(sa): {{t|sa|बुद्धत्व}} * 여진어(juc): futuchi * 종카어(dz): {{t|dz|སངས་རྒྱས།}} * 중국어(zh): {{t|zh|成佛}} }} {{외국어|덧=불교적 배경은 없으나, 이를 설명하고 번역하기 위한 용어들| * 그리스어(el): * 러시아어(ru): {{t|ru|Будда}} * 몽골어(mn): {{t|mn|Будда}} * 아랍어(ar): * 우크라이나어(uk): {{t|uk|Будда}} * 영어(en): {{t|en|Buddhahood}}, {{t|en|Buddha}} * 카자흐어(kk): }} === 어원 2 === ==== 명사 ==== {{한국어 명사|한자=夫妻}} # 남편과 아내를 아울러 이르는 말. {{국립국어원}} [[분류:표준어 자립명사]] [[분류:표준어 단일어명사]] 03bei3ac7xgf5c07omcwuhshzn10fb3 모듈:languages/data/3/x 828 446663 4484385 4393908 2026-05-29T06:13:29Z Apisite 21408 4484385 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["xaa"] = { "Andalusian Arabic", 1137945, "sem-arb", "Arab, Latn", entry_name = { Arab = { remove_diacritics = c.kashida .. c.fathatan .. c.dammatan .. c.kasratan .. c.fatha .. c.damma .. c.kasra .. c.shadda .. c.sukun .. c.superalef, from = {u(0x0671)}, to = {u(0x0627)} }, }, } m["xab"] = { "Sambe", 36265, "nic-alu", "Latn", } m["xac"] = { "Kachari", 3442442, "tbq-bdg", } m["xad"] = { "Adai", 346744, nil, "Latn", } m["xae"] = { "Aequian", 930579, "itc", "Ital, Latn", translit = { Ital = "Ital-translit", }, display_text = { Latn = s["itc-Latn-displaytext"] }, entry_name = { Latn = s["itc-Latn-entryname"] }, sort_key = { Latn = s["itc-Latn-sortkey"] }, } m["xag"] = { "Aghwan", 34931, "cau-esm", "Aghb", translit = "Aghb-translit", override_translit = true, } m["xai"] = { "Kaimbé", 6348017, } m["xaj"] = { "Ararandewára", 63339949, "tup-gua", "Latn", } m["xak"] = { "Maku", 2032882, nil, "Latn", } m["xal"] = { "Kalmyk", 33634, "xgn-cen", "Cyrl, xwo-Mong", ancestors = "xwo", translit = "xal-translit", override_translit = true, sort_key = "xal-sortkey", } m["xam"] = { "ǀXam", 2086145, "khi-tuu", "Latn", } m["xan"] = { "Xamtanga", 56527, "cus-cen", "Ethi", } m["xao"] = { "Khao", 3196077, "mkh-pal", } m["xap"] = { "Apalachee", 686501, "nai-mus", "Latn", } m["xaq"] = { "Aquitanian", 500522, "euq", "Latn", } m["xar"] = { "Karami", 11732281, } m["xas"] = { "Kamassian", 35991, translit = "xas-translit", "syd", "Cyrl", } m["xat"] = { "Katawixi", 3440512, "sai-ktk", } m["xau"] = { "Kauwera", 6378983, "paa-tkw", } m["xav"] = { "Xavante", 36962, "sai-cje", "Latn", } m["xaw"] = { "Kawaiisu", 56338, "azc-num", "Latn", } m["xay"] = { "Kayan Mahakam", 25337171, } m["xbb"] = { "Lower Burdekin", 6693353, } m["xbc"] = { "박트리아어", 756651, "ira-sbc", "Polyt, Mani", translit = { Polyt = "grc-translit", }, display_text = { Polyt = s["Polyt-displaytext"], }, entry_name = { Polyt = s["Polyt-entryname"], }, sort_key = { Polyt = s["Polyt-sortkey"], }, } m["xbd"] = { "Bindal", 4913975, } m["xbe"] = { "Bigambal", 16841801, "aus-pam", --unclassified within "Latn", } m["xbg"] = { "Bunganditj", 4997615, } m["xbi"] = { "Kombio", 6428259, "qfa-tor", "Latn", } m["xbj"] = { "Birrpayi", 63339969, "aus-yuk", "Latn", } m["xbm"] = { "Middle Breton", 787610, "cel-brs", "Latn", ancestors = "obt", } m["xbn"] = { "Kenaboi", 6388752, } m["xbo"] = { "Bulgar", 36880, "trk-ogr", "Arab, Polyt, Cyrs", ancestors = "trk-bul-pro", translit = { Cyrs = "Cyrs-translit" }, display_text = { Polyt = s["Polyt-displaytext"], }, entry_name = { Arab = "ar-entryname", Polyt = s["Polyt-entryname"], Cyrs = s["Cyrs-entryname"], }, sort_key = { Polyt = s["Polyt-sortkey"], Cyrs = s["Cyrs-sortkey"] }, } m["xbp"] = { "Bibbulman", 22918391, } m["xbr"] = { "Kambera", 3053279, "poz-cet", "Latn", } m["xbw"] = { "Kambiwá", 9006744, } m["xby"] = { "Butchulla", 31752631, } m["xcb"] = { "Cumbric", 35965, "cel-brw", } m["xcc"] = { "Camunic", 489011, nil, "Ital", translit = "Ital-translit", } m["xce"] = { "Celtiberian", 37012, "cel-his", "Latn", } m["xch"] = { "Chemakum", 56397, "chi", "Latn", } m["xcl"] = { "Old Armenian", 181074, "hyx", "Armn", translit = "Armn-translit", override_translit = true, entry_name = { remove_diacritics = "՞՜՛՟", from = {"եւ", "ՙ", "՚"}, to = {"և", "ʻ", "’"} }, } m["xcm"] = { "Comecrudo", 609808, "nai-pak", } m["xcn"] = { "Cotoname", 56889, "nai-pak", } m["xco"] = { "Khwarezmian", 33138, "ira-sbc", "Arab, Armi, Chrs, Phlv, Sogd", translit = { Chrs = "Chrs-translit" }, } m["xcr"] = { "Carian", 35929, "ine-luw", "Cari", } m["xct"] = { "Classical Tibetan", 5128314, "sit-tib", "Tibt, Hani, Marc, Mong, mnc-Mong, xwo-Mong, Phag, Tang, Zanb", translit = { Tibt = "Tibt-translit", Mong = "Mong-translit", ["mnc-Mong"] = "mnc-translit", ["xwo-Mong"] = "xwo-translit", Tang = "txg-translit", }, override_translit = true, display_text = { Tibt = s["Tibt-displaytext"], Mong = s["Mong-displaytext"], }, entry_name = { Tibt = s["Tibt-entryname"], Mong = s["Mong-entryname"], }, sort_key = { Tibt = "Tibt-sortkey", Hani = "Hani-sortkey", }, } m["xcu"] = { "Curonian", 35857, "bat", "Latn", } m["xcv"] = { "Chuvan", 3516641, "qfa-yuk", "Cyrl", translit = "xcv-translit" } m["xcw"] = { "Coahuilteco", 2008062, "nai-pak", } m["xcy"] = { "Cayuse", 2472016, } m["xda"] = { "Darkinjung", 5223660, "aus-yuk", "Latn", } m["xdc"] = { "Dacian", 682547, "ine", "Latn, Polyt", translit = { Polyt = "grc-translit", }, display_text = { Polyt = s["Polyt-displaytext"], }, entry_name = { Polyt = s["Polyt-entryname"], }, sort_key = { Polyt = s["Polyt-sortkey"], }, } m["xdk"] = { "Dharug", 1166814, "aus-yuk", "Latn", } m["xdm"] = { "Edomite", 2363529, "sem-can", "Phnx", translit = "Phnx-translit", } m["xdq"] = { "Kaitag", 1990659, "cau-drg", "Cyrl", translit = {Cyrl = "dar-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 = { "къкъ", "хьхь", -- 4 chars "гъ", "гь", "гӏ", "ё", "къ", "кь", "кӏ", "пп", "пӏ", "сс", "тт", "тӏ", "хх", "хъ", "хь", "хӏ", "цц", "цӏ", "чч", "чӏ" -- 2 chars }, to = { "к" .. p[2], "х" .. p[4], "г" .. p[1], "г" .. p[2], "г" .. p[3], "е" .. p[1], "к" .. p[1], "к" .. p[3], "к" .. p[4], "п" .. p[1], "п" .. p[2], "с" .. p[1], "т" .. p[1], "т" .. p[2], "х" .. p[1], "х" .. p[2], "х" .. p[3], "х" .. p[5], "ц" .. p[1], "ц" .. p[2], "ч" .. p[1], "ч" .. p[2] } }, }, } m["xdy"] = { "Malayic Dayak", 3514892, } m["xeb"] = { "Eblaite", 35345, "sem-eas", "Xsux", } m["xed"] = { "Hdi", 56246, "cdc-cbm", "Latn", } m["xeg"] = { "ǁXegwi", 3509732, "khi-tuu", "Latn", } m["xel"] = { "Kelo", 6386412, "sdv-eje", } m["xem"] = { "Kembayan", 6386874, } m["xep"] = { "Epi-Olmec", 124257204, } m["xer"] = { "Xerénte", 3073436, "sai-cje", "Latn", } m["xes"] = { "Kesawai", 6394907, "ngf-mad", "Latn", } m["xet"] = { "Xetá", 2980404, "tup-gua", "Latn", } m["xeu"] = { "Keoru-Ahia", 11732313, "ngf", } m["xfa"] = { "Faliscan", 35669, "itc-laf", "Ital, Latn", translit = { Ital = "Ital-translit", }, display_text = { Latn = s["itc-Latn-displaytext"] }, entry_name = { Latn = s["itc-Latn-entryname"] }, sort_key = { Latn = s["itc-Latn-sortkey"] }, } m["xga"] = { "Galatian", 27403, "cel", "Latn, Polyt", ancestors = "cel-gau", translit = { Polyt = "grc-translit", }, display_text = { Polyt = s["Polyt-displaytext"], }, entry_name = { Polyt = s["Polyt-entryname"], }, sort_key = { Polyt = s["Polyt-sortkey"], }, } m["xgb"] = { "Gbin", 16934745, "dmn-mse", "Latn", } m["xgd"] = { "Gudang", 5614528, } m["xgf"] = { "Gabrielino-Fernandeño", 56387, "azc-tak", "Latn", } m["xgg"] = { "Goreng", 50934914, } m["xgi"] = { "Garingbal", 52008172, } m["xgl"] = { "Galindian", 1190494, "bat", "Latn", } m["xgm"] = { "Darumbal", 16954400, } m["xgr"] = { "Garza", 3098656, "nai-pak", } m["xgu"] = { "Unggumi", 62000004, "aus-wor", "Latn", } m["xgw"] = { "Guwa", 5621992, } m["xha"] = { "Harami", 41506724, nil, "Sarb", translit = "Sarb-translit", } m["xhc"] = { "Hunnic", 35959, } m["xhd"] = { "Hadrami", 1032453, "sem-osa", "Sarb", translit = "Sarb-translit", } m["xhe"] = { "Khetrani", 2614111, "inc-pan", ancestors = "lah", } m["xhm"] = { "Middle Khmer", 25226861, "mkh-kmr", "Latn, Khmr", --and also Khom ancestors = "okz", } m["xhr"] = { "Hernican", 5908773, "itc-sbl", "Ital, Latn", translit = { Ital = "Ital-translit", }, display_text = { Latn = s["itc-Latn-displaytext"] }, entry_name = { Latn = s["itc-Latn-entryname"] }, sort_key = { Latn = s["itc-Latn-sortkey"] }, } m["xht"] = { "Hattic", 31107, "qfa-iso", "Xsux", } m["xhu"] = { "Hurrian", 35740, "qfa-hur", "Xsux, Ugar", } m["xhv"] = { "Khua", 22970290, "mkh-kat", } m["xib"] = { "Iberian", 855215, "qfa-iso", "Latn, Ibrnn, Ibrns", } m["xii"] = { "Xiri", 36876, } m["xin"] = { "Xinca", 1546494, "nai-xin", "Latn", } m["xil"] = { "Illyrian", 35976, "ine", type = "reconstructed", } m["xir"] = { "Xiriâna", 2028772, "awd", "Latn", } m["xis"] = { "Kisan", 63339998, "dra-kml", ancestors = "kru", } m["xiv"] = { "Harappan", 3428279, nil, "Inds", } m["xiy"] = { "Xipaya", 13226, "tup", } m["xjb"] = { "Minjungbal", 16334334, "aus-pam", "Latn", } m["xka"] = { "Kalkoti", 3877551, "inc-shn", "ur-Arab", } m["xkb"] = { "Manigri-Kambolé Ede Nago", 36042, "alv-ede", "Latn", } m["xkc"] = { "Khoini", 6401919, "xme-ttc", ancestors = "xme-ttc-wes", } m["xkd"] = { "Mendalam Kayan", 12952597, } m["xke"] = { "Kereho", 6437086, "poz", "Latn", } m["xkf"] = { "Khengkha", 3695207, "sit-ebo", "Tibt", translit = "Tibt-translit", override_translit = true, display_text = s["Tibt-displaytext"], entry_name = s["Tibt-entryname"], sort_key = "Tibt-sortkey", } m["xkg"] = { "Kagoro", 11159524, "dmn-wmn", } m["xki"] = { "Kenyan Sign Language", 6392859, "sgn", } m["xkj"] = { "Kajali", 14916876, "xme-ttc", ancestors = "xme-ttc-cen", } m["xkk"] = { "Kaco'", 6344767, "mkh", } m["xkl"] = { "Bakung", 6736761, "poz-swa", "Latn", } m["xkn"] = { "Kayan River Kayan", 12473395, "poz", "Latn", } m["xko"] = { "Kiorr", 6414519, "mkh-pal", } m["xkp"] = { "Kabatei", 34165, "xme-ttc", ancestors = "xme-ttc-cen", } m["xkq"] = { "Koroni", 3199000, "poz-btk", } m["xkr"] = { "Xakriabá", 3073441, "sai-cje", "Latn", } m["xks"] = { "Kumbewaha", 6443722, } m["xkt"] = { "Kantosi", 35651, "nic-dag", } m["xku"] = { "Kaamba", 11042324, "bnt-kng", } m["xkv"] = { "Kgalagadi", 2088743, "bnt-sts", "Latn", } m["xkw"] = { "Kembra", 12953627, "paa-pau", } m["xkx"] = { "Karore", 6373260, "poz-ocw", } m["xky"] = { "Uma' Lasan", 7881227, "poz-swa", } m["xkz"] = { "Kurtöp", 3695193, "sit-ebo", "Tibt, Latn", translit = { Tibt = "Tibt-translit" }, display_text = { Tibt = s["Tibt-displaytext"] }, entry_name = { Tibt = s["Tibt-entryname"] }, sort_key = { Tibt = "Tibt-sortkey" }, } m["xla"] = { "Kamula", 10957277, "ngf", "Latn", } m["xlb"] = { "Loup B", 13108281, "alg-eas", "Latn", } m["xlc"] = { "Lycian", 35969, "ine-luw", "Lyci", translit = "Lyci-translit", } m["xld"] = { "Lydian", 36095, "ine-ana", "Lydi", translit = "Lydi-translit", } m["xle"] = { "Lemnian", 36203, "qfa-tyn", "Ital", translit = "Ital-translit", } m["xlg"] = { "Ancient Ligurian", 36104, "ine", "Latn", } m["xli"] = { "Liburnian", 35835, "ine", } m["xln"] = { "Alanic", 3658580, "xsc-sar", "Polyt, Latn", translit = { Polyt = "grc-translit", }, display_text = { Polyt = s["Polyt-displaytext"], }, entry_name = { Polyt = s["Polyt-entryname"], }, sort_key = { Polyt = s["Polyt-sortkey"], }, } m["xlo"] = { "Loup A", 27921265, "alg-eas", "Latn", } m["xlp"] = { "Lepontic", 35993, "cel", "Ital, Latn", translit = { Ital = "Ital-translit", }, } m["xls"] = { "Lusitanian", 35960, "ine", "Latn", } m["xlu"] = { "Luwian", 12634577, "ine-luw", "Xsux, Hluw", } m["xly"] = { "Elymian", 35329, "ine", "Polyt", translit = "grc-translit", display_text = s["Polyt-displaytext"], entry_name = s["Polyt-entryname"], sort_key = s["Polyt-sortkey"], } m["xmb"] = { "Mbonga", 36064, "nic-jrn", "Latn", } m["xmc"] = { "Makhuwa-Marrevone", 11127231, "bnt-mak", ancestors = "vmw", } m["xmd"] = { "Mbudum", 6799790, "cdc-cbm", "Latn", } m["xmf"] = { "Mingrelian", 13359, "ccs-zan", "Geor", translit = "Geor-translit", override_translit = true, } m["xmg"] = { "Mengaka", 36017, "bai", "Latn", } m["xmh"] = { "Kugu-Muminh", 10549849, "aus-pmn", "Latn", } m["xmj"] = { "Majera", 6737666, "cdc-cbm", "Latn", } m["xmk"] = { "Ancient Macedonian", 35974, "grk", "Polyt", translit = "grc-translit", display_text = s["Polyt-displaytext"], entry_name = s["Polyt-entryname"], sort_key = s["Polyt-sortkey"], } m["xml"] = { "Malaysian Sign Language", 33420, "sgn", } m["xmm"] = { "Manado Malay", 1068112, "crp", "Latn", } m["xmo"] = { "Morerebi", 12953749, "tup", "Latn", } m["xmp"] = { "Kuku-Mu'inh", 10549852, nil, "Latn", } m["xmq"] = { "Kuku-Mangk", 10549851, "aus-pam", "Latn", } m["xmr"] = { "Meroitic", 13366, "afa", "Mero, Merc, Latn", -- we have entries in Latn translit = { Mero = "xmr-translit", Merc = "xmr-translit", }, } m["xms"] = { "Moroccan Sign Language", 6913107, "sgn", } m["xmt"] = { "Matbat", 6786187, "poz-hce", "Latn", } m["xmu"] = { "Kamu", 6359779, } m["xmx"] = { "Maden", 12952756, "poz-hce", } m["xmy"] = { "Mayaguduna", 3436736, } m["xmz"] = { "Mori Bawah", 3324069, "poz-btk", "Latn", } m["xna"] = { "Ancient North Arabian", 1472213, "sem-cen", "Narb", translit = "Narb-translit", } m["xnb"] = { "Kanakanabu", 172244, "map", "Latn", } m["xng"] = { "Middle Mongol", 2582455, "xgn", "Mong, Phag, Hani, Arab, Armn", translit = { Mong = "Mong-translit" }, display_text = { Mong = s["Mong-displaytext"] }, entry_name = { Mong = s["Mong-entryname"] }, sort_key = { Hani = "Hani-sortkey" }, } m["xnh"] = { "Kuanhua", 6441084, "mkh-pal", } m["xni"] = { "Ngarigu", 7022072, "aus-yuk", } m["xnk"] = { "Nganakarti", 33087049, } m["xnn"] = { "Northern Kankanay", -- use this for now; correction must be "Northern Kankanaey" 12953609, "phi", "Latn", } -- "xno" IS TREATED AS "fro", SEE WT:LT m["xnr"] = { "Kangri", 2331560, "him", "Deva, Takr, fa-Arab", ancestors = "doi", translit = { Deva = "hi-translit", }, } m["xns"] = { "Kanashi", 6360672, "sit-whm", } m["xnt"] = { "Narragansett", 3336118, "alg-eas", "Latn, Hebr", display_text = { Hebr = "Hebr-common", }, entry_name = { Latn = {remove_diacritics = c.grave .. c.acute .. c.tilde .. c.macron .. c.breve}, Hebr = "Hebr-common", }, sort_key = { Hebr = "Hebr-common", }, } m["xnu"] = { "Nukunul", 7068904, } m["xny"] = { "Nyiyaparli", 16919427, "aus-nga", "Latn", } m["xoc"] = { "O'chi'chi'", 3813833, "nic-cde", "Latn", } m["xod"] = { "Kokoda", 6426734, "ngf-sbh", } m["xog"] = { "Soga", 33784, "bnt-nyg", "Latn", } m["xoi"] = { "Kominimung", 6428352, "paa", "Latn", } m["xok"] = { "Xokleng", 3027930, "sai-sje", } m["xom"] = { "Komo", 56681, "ssa-kom", "Latn", } m["xon"] = { "Konkomba", 35674, "nic-grm", "Latn", } m["xoo"] = { -- contrast kzw, sai-kat, sai-xoc "Xukurú", 9096758, } m["xop"] = { "Kopar", 11732346, } m["xor"] = { "Korubo", 3199022, } m["xow"] = { "Kowaki", 6434920, "ngf-mad", } m["xpa"] = { "Pirriya", 16978087, } m["xpb"] = { "Pyemmairre", 7262964, nil, "Latn", } m["xpc"] = { "Pecheneg", 877881, "trk", } m["xpd"] = { "Paredarerme", 7136678, nil, "Latn", } m["xpe"] = { "Liberia Kpelle", 20527226, "dmn-msw", "Latn, Kpel", ancestors = "kpe", } m["xpf"] = { "Southeast Tasmanian", 7068421, nil, "Latn", } m["xpg"] = { "Phrygian", 36751, "ine", "Polyt", translit = "grc-translit", display_text = s["Polyt-displaytext"], entry_name = s["Polyt-entryname"], sort_key = s["Polyt-sortkey"], } m["xph"] = { "Tyerrernotepanner", 7859815, nil, "Latn", } m["xpi"] = { "Pictish", 856383, "cel-brw", "Ogam, Latn", } m["xpj"] = { "Mpalitjanh", 6928192, "aus-pam", } m["xpk"] = { "Kulina", 6443027, "sai-pan", } m["xpl"] = { "Port Sorell", 7230944, nil, "Latn", } m["xpm"] = { "Pumpokol", 2991985, "qfa-yso", "Latn, Cyrl", } m["xpn"] = { "Kapinawá", 6366667, } m["xpo"] = { "Pochutec", 2427341, "azc-nah", "Latn", } m["xpp"] = { "Puyo-Paekche", 65455887, } m["xpq"] = { "Mohegan-Pequot", 3319130, "alg-eas", "Latn", } m["xpr"] = { "Parthian", 25953, "ira-mpr", "Prti, Mani, Phlv", translit = { Prti = "Prti-translit", Mani = "Mani-translit", }, } m["xps"] = { "Pisidian", 36580, "ine-luw", } m["xpu"] = { "Punic", 535958, "sem-can", "Phnx, Latn, Polyt", ancestors = "phn", translit = { Phnx = "Phnx-translit", Polyt = "grc-translit", }, display_text = { Polyt = s["Polyt-displaytext"], }, entry_name = { Polyt = s["Polyt-entryname"], }, sort_key = { Polyt = s["Polyt-sortkey"], }, } m["xpv"] = { "Tommeginne", 7819095, nil, "Latn", } m["xpw"] = { "Peerapper", 7160431, nil, "Latn", } m["xpx"] = { "Toogee", 7824008, nil, "Latn", } m["xpy"] = { "Buyeo", 5003359, "qfa-kor", "Hani", sort_key = "Hani-sortkey", } m["xpz"] = { "Bruny Island", 4979601, nil, "Latn", } m["xqa"] = { "Karakhanid", 4494885, "trk-kar", "Arab, Ougr", entry_name = "ar-entryname", } m["xqt"] = { "Qatabanian", 384101, "sem-osa", "Sarb", translit = "Sarb-translit", } m["xra"] = { "Krahô", 3199549, "sai-nje", "Latn", } m["xrb"] = { "Eastern Karaboro", 35716, "alv-krb", "Latn", } m["xrd"] = { "Gundungurra", 60611652, nil, "Latn", } m["xre"] = { "Kreye", 3199686, "sai-nje", } m["xrg"] = { "Minang", 22893424, "aus-pam", } m["xri"] = { "Krikati-Timbira", 3199710, } m["xrm"] = { "Armazic", 7599646, } m["xrn"] = { "Arin", 34088, "qfa-yso", "Latn, Cyrl", } m["xrq"] = { "Karranga", 6373349, nil, "Latn", } m["xrr"] = { "Raetic", 36689, "qfa-tyn", "Ital", translit = "Ital-translit", } m["xrt"] = { "Aranama-Tamique", 2859505, } m["xru"] = { "Marriammu", 10577724, "aus-dal", } m["xrw"] = { "Karawa", 6368857, "paa-spk", } m["xsa"] = { "Sabaean", 1070391, "sem-osa", "Sarb", translit = "Sarb-translit", } m["xsb"] = { "Sambali", 2592378, "phi", "Latn", } m["xsd"] = { "Sidetic", 36659, "ine-luw", "Sidt", } m["xse"] = { "Sempan", 3504358, } m["xsh"] = { "Shamang", 3914876, "nic-plc", } m["xsi"] = { "Sio", 3485100, "poz-ocw", } m["xsj"] = { "Subi", 7631298, "bnt-haj", } m["xsl"] = { "South Slavey", 28552, "den", "Latn", } m["xsm"] = { "Kasem", 35552, "nic-gnn", "Latn", } m["xsn"] = { "Sanga (Nigeria)", 3915334, "nic-jer", "Latn", } m["xso"] = { "Solano", 2474492, nil, "Latn", } m["xsp"] = { "Silopi", 7515533, "ngf-mad", } m["xsq"] = { "Makhuwa-Saka", 11008159, "bnt-mak", ancestors = "vmw", } m["xsr"] = { "Sherpa", 36612, "sit-tib", "Tibt, Deva", ancestors = "xct", translit = { Tibt = "Tibt-translit", Deva = "xsr-Deva-translit", }, override_translit = true, display_text = { Tibt = s["Tibt-displaytext"] }, entry_name = { Tibt = s["Tibt-entryname"] }, sort_key = { Tibt = "Tibt-sortkey" }, } m["xss"] = { "Assan", 34089, "qfa-yso", "Latn, Cyrl", } m["xsu"] = { "Sanumá", 251728, "sai-ynm", "Latn", } m["xsv"] = { "Sudovian", 35603, "bat-wes", "Latn", } m["xsy"] = { "Saisiyat", 716695, "map", "Latn", } m["xta"] = { "Alcozauca Mixtec", 25559587, "omq-mxt", "Latn", } m["xtb"] = { "Chazumba Mixtec", 12182838, "omq-mxt", "Latn", } m["xtc"] = { "Kadugli", 3407136, "qfa-kad", "Latn", } m["xtd"] = { "Diuxi-Tilantongo Mixtec", 7802048, "omq-mxt", "Latn", } m["xte"] = { "Ketengban", 10990152, } m["xth"] = { "Yitha Yitha", 8053879, } m["xti"] = { "Sinicahua Mixtec", 12953733, "omq-mxt", "Latn", } m["xtj"] = { "San Juan Teita Mixtec", 32093049, "omq-mxt", "Latn", } m["xtl"] = { "Tijaltepec Mixtec", 12953738, "omq-mxt", "Latn", } m["xtm"] = { "Magdalena Peñasco Mixtec", 7179700, "omq-mxt", "Latn", } m["xtn"] = { "Northern Tlaxiaco Mixtec", 25559585, "omq-mxt", "Latn", } m["xto"] = { "Tocharian A", 2827041, "ine-toc", "Latn", } m["xtp"] = { "San Miguel Piedras Mixtec", 7414970, "omq-mxt", "Latn", } m["xtq"] = { "Tumshuqese", 65455890, "xsc-sak", "Brah, Khar", translit = { Brah = "Brah-translit", }, } m["xtr"] = { "Early Tripuri", 65455891, } m["xts"] = { "Sindihui Mixtec", 13583581, "omq-mxt", "Latn", } m["xtt"] = { "Tacahua Mixtec", 7673668, "omq-mxt", "Latn", } m["xtu"] = { "Cuyamecalco Mixtec", 12953726, "omq-mxt", "Latn", } m["xtv"] = { "Thawa", 7711494, } m["xtw"] = { "Tawandê", 63340139, "sai-nmk", "Latn", } m["xty"] = { "Yoloxochitl Mixtec", 8054817, "omq-mxt", "Latn", } m["xua"] = { "Alu Kurumba", 12952679, "dra-kan", "Knda", translit = "kn-translit", } m["xub"] = { "Betta Kurumba", 16841033, "dra-kan", "Knda, Mlym, Taml", translit = { Knda = "kn-translit", Taml = "ta-translit", }, } m["xud"] = { "Umiida", 61999874, "aus-wor", "Latn", } m["xug"] = { "Kunigami", 56558, "jpx-nry", "Jpan", translit = s["jpx-translit"], display_text = s["jpx-displaytext"], entry_name = s["jpx-entryname"], sort_key = s["jpx-sortkey"], } m["xuj"] = { "Jennu Kurumba", 21282543, "dra-kan", "Knda", translit = "kn-translit", } m["xul"] = { "Ngunawal", 7022712, "aus-yuk", "Latn", } m["xum"] = { "Umbrian", 36957, "itc-sbl", "Ital, Latn", translit = { Ital = "Ital-translit", }, display_text = { Latn = s["itc-Latn-displaytext"] }, entry_name = { Latn = s["itc-Latn-entryname"] }, sort_key = { Latn = s["itc-Latn-sortkey"] }, } m["xun"] = { "Unggaranggu", 61999823, "aus-wor", "Latn", } m["xuo"] = { "Kuo", 6445233, "alv-mbm", } m["xup"] = { "Upper Umpqua", 20607, "ath-pco", "Latn", } m["xur"] = { "Urartian", 36934, "qfa-hur", "Xsux", } m["xut"] = { "Kuthant", 6448417, } m["xuu"] = { "Khwe", 28305, "khi-kal", "Latn", } m["xve"] = { "Venetic", 36871, "ine", "Ital", translit = "Ital-translit", } -- m["xvi"] = { "Kamviri", 1193495, "nur-nor", Arab } moved to etym-only code m["xvn"] = { "Vandalic", 36835, "gme", "Latn", } m["xvo"] = { "Volscian", 622110, "itc-sbl", "Ital, Latn", translit = { Ital = "Ital-translit", }, display_text = { Latn = s["itc-Latn-displaytext"] }, entry_name = { Latn = s["itc-Latn-entryname"] }, sort_key = { Latn = s["itc-Latn-sortkey"] }, } m["xvs"] = { "Vestinian", 2576407, "itc", "Ital, Latn", translit = { Ital = "Ital-translit", }, display_text = { Latn = s["itc-Latn-displaytext"] }, entry_name = { Latn = s["itc-Latn-entryname"] }, sort_key = { Latn = s["itc-Latn-sortkey"] }, } m["xwa"] = { "Kwaza", 3200839, nil, "Latn", } m["xwc"] = { "Woccon", 3569569, "nai-cat", "Latn", } m["xwd"] = { "Wadi Wadi", 7959249, } m["xwe"] = { "Xwela Gbe", 36887, "alv-pph", } m["xwg"] = { "Kwegu", 56723, "sdv", } m["xwj"] = { "Wajuk", 33110188, } m["xwk"] = { "Wangkumara", 7967891, "aus-pam", "Latn", } m["xwl"] = { "Western Xwla Gbe", 36924, "alv-pph", "Latn", } m["xwo"] = { "Written Oirat", 56959, "xgn-cen", "xwo-Mong", translit = "xwo-translit", } m["xwr"] = { "Kwerba Mamberamo", 6450325, "paa-tkw", } m["xww"] = { "Wemba-Wemba", 18472819, "aus-pam", "Latn", } m["xxb"] = { "Boro", 16844787, nil, "Latn", } m["xxk"] = { "Ke'o", 3195346, } m["xxm"] = { "Minkin", 6867836, } m["xxr"] = { "Koropó", 6432560, } m["xxt"] = { "Tambora", 36711, "paa", "Latn", } m["xya"] = { "Yaygir", 8050525, "aus-pam", "Latn", } m["xyb"] = { "Yandjibara", 63340189, nil, "Latn", } m["xyl"] = { "Yalakalore", 12645352, "sai-nmk", "Latn", } m["xyt"] = { "Mayi-Thakurti", 47004719, "aus-pam", "Latn", } m["xyy"] = { "Yorta Yorta", 8055849, "aus-pam", "Latn", } m["xzh"] = { "Zhang-Zhung", 3437292, "sit-alm", "Marc, Tibt", translit = { Tibt = "Tibt-translit" }, display_text = { Tibt = s["Tibt-displaytext"] }, entry_name = { Tibt = s["Tibt-entryname"] }, sort_key = { Tibt = "Tibt-sortkey" }, } m["xzm"] = { "Semigallian", 47631, "bat-eas", } m["xzp"] = { "Ancient Zapotec", 65455892, } return require("Module:languages").finalizeData(m, "language") ndjiuf3eiubeh92sshssqygv94lqp1m 모듈:etymon 828 449271 4484380 4393697 2026-05-29T03:30:43Z Jeebeen 13056 4484380 Scribunto text/plain local export = {} local anchors_module = "Module:anchors" local etymology_module = "Module:etymology" local headword_data_module = "Module:headword/data" local languages_module = "Module:languages" local languages_errorgetby_module = "Module:languages/errorGetBy" local links_module = "Module:also/link" local pages_module = "Module:pages" local parameters_module = "Module:parameters" local parameters_data_module = "Module:parameters/data" local string_utilities_module = "Module:string utilities" local template_parser_module = "Module:template parser/sandbox" local templatestyles_module = "Module:TemplateStyles" local utilities_module = "Module:utilities" local debug_module = "Module:debug" local concat = table.concat local find = string.find local gsub = string.gsub local html_create = mw.html.create local insert = table.insert local match = string.match local max = math.max local new_title = mw.title.new local next = next local require = require local sub = string.sub local tostring = tostring local type = type local unpack = unpack or table.unpack -- Lua 5.2 compatibility local function track(page) trackfn("etymon/" .. page) return true end local unallowed_langs = { ["zh"] = { ["ref"] = "[[Wiktionary:Beer_parlour/2025/May#etymon_for_Chinese]]" } } --[==[ Loaders for functions in other modules, which overwrite themselves with the target function when called. This ensures modules are only loaded when needed, retains the speed/convenience of locally-declared pre-loaded functions, and has no overhead after the first call, since the target functions are called directly in any subsequent calls.]==] local function check_ancestor(...) check_ancestor = require(etymology_module).check_ancestor return check_ancestor(...) end local function find_templates(...) find_templates = require(template_parser_module).find_templates return find_templates(...) end local function format_categories(...) format_categories = require(utilities_module).format_categories return format_categories(...) end local function full_link(...) full_link = require(links_module).full_link return full_link(...) end local function get_lang(...) get_lang = require(languages_module).getByCode return get_lang(...) end local function get_link_page(...) get_link_page = require(links_module).get_link_page return get_link_page(...) end local function get_section(...) get_section = require(pages_module).get_section return get_section(...) end local function language_anchor(...) language_anchor = require(anchors_module).language_anchor return language_anchor(...) end local function process_params(...) process_params = require(parameters_module).process return process_params(...) end local function split(...) split = require(string_utilities_module).split return split(...) end local function templatestyles(...) templatestyles = require(templatestyles_module) return templatestyles(...) end local function trim(...) trim = require(string_utilities_module).trim return trim(...) end local function trackfn(...) trackfn = require(debug_module).track return trackfn(...) end --[==[ Loaders for objects, which load data (or some other object) into some variable, which can then be accessed as "foo or get_foo()", where the function get_foo sets the object to "foo" and then returns it. This ensures they are only loaded when needed, and avoids the need to check for the existence of the object each time, since once "foo" has been set, "get_foo" will not be called again.]==] local content_page local function is_content_page() content_page, is_content_page = require(pages_module).is_content_page(mw.title.getCurrentTitle()), nil return content_page end local page_data local function get_page_data() page_data, get_page_data = mw.loadData(headword_data_module).page, nil return page_data end local frame -- Generate an HTML link. local function makeLink(params) -- [[Wiktionary:Beer_parlour/2025/May#{{etymon}}_for_Chinese]] if params["lang"]:getCode() == "zh" then params["tr"] = "" end return full_link(params, "term") end -- Get a language object. local function getLang(code) return get_lang(code, nil, true) or require(languages_errorgetby_module).code(code, true, true) end -- Normalize the language so that special handling of Chinese is accounted for. -- This is everything in the Sinitic family which isn't a creole, pidgin or mixed language. local function getNormLang(lang) if lang:inFamily("zhx") and not lang:inFamily("qfa-cnt") then return get_lang("zh") end return lang end -- Given an etymon param, return its parts. local function getParts(templateLang, etymonParam) local etymonLang, etymonLangcode, etymonPage, etymonId local parts = split(etymonParam, ">", true) local n = #parts for i = 1, n do parts[i] = trim(parts[i]) end -- FIXME: this doesn't work properly if nested templates output HTML tags, which is likely to cause bugs that are hard for ordinary users to fix. if n == 2 then -- Assume language is the same as the template call if none is provided. etymonLang, etymonPage, etymonId = templateLang, unpack(parts) else etymonLangcode, etymonPage, etymonId = unpack(parts) etymonLang = getLang(etymonLangcode) end return etymonLang, etymonPage, etymonId end local argsOf = {} local disambiguationCount = {} local function scrapePage(etymonPage, etymonTitle, key, etymonLang, etymonId, redirectedFrom) local content = etymonTitle:getContent() if content == nil then argsOf[key] = "redlink" return end -- Search only the relevant L2 entry, unless it's a redirect, in which case search the whole page. local redirectTarget = etymonTitle.redirectTarget if not redirectTarget then content = get_section(content, etymonLang:getFullName(), 2) if content == nil then argsOf[key] = "missing" return end end local etymonLangcode = etymonLang:getFullCode() local L2_key = etymonLangcode .. ">" .. etymonPage -- Search for the template on the page (even if this is a redirect page). -- FIXME: mw.uri.anchorEncode on IDs. Not possible to implement until ">" syntax is fixed (see comment in getParts). for template in find_templates(content) do if template:get_name() == "etymon" then local templateArgs = template:get_arguments() if templateArgs[1] == etymonLangcode then argsOf[L2_key .. ">" .. templateArgs["id"]] = templateArgs disambiguationCount[L2_key] = (disambiguationCount[L2_key] or 0) + 1 end end end if redirectedFrom and disambiguationCount[L2_key] then disambiguationCount[redirectedFrom] = (disambiguationCount[redirectedFrom] or 0) + disambiguationCount[L2_key] end -- If scraping produced a result, there's nothing left to do. if argsOf[key] then return -- Else if we've already followed a redirect and still found nothing, record the template as missing. elseif redirectedFrom then argsOf[key] = "missing" return end -- Check if the page is a redirect, and if not record the template as missing. if not redirectTarget then argsOf[key] = "missing" return end -- Otherwise, try again with the redirect target. etymonPage = redirectTarget.prefixedText scrapePage(etymonPage, redirectTarget, L2_key .. ">" .. etymonId, etymonLang, etymonId, L2_key) -- Record the value as the same as the redirect's. argsOf[key] = argsOf[etymonLangcode .. ">" .. etymonPage .. ">" .. etymonId] end -- Given an etymon, scrape the page and get its parameters. -- This function returns either: a table of the params, "missing", "redlink", or "nolink" local function getArgs(templateLang, etymonParam) -- Get normalized parts of the etymon parameter. local etymonLang, etymonPage, etymonId = getParts(templateLang, etymonParam) -- "?" is a special value that unlinks the page. TODO: Figure this out... if etymonId == "?" then return "nolink" end -- If multiple terms are linked like A//B, only look at A. etymonPage = match(etymonPage, "^(.-)//") or etymonPage etymonPage = get_link_page(etymonPage, etymonLang) etymonLang = getNormLang(etymonLang) -- Find the parameters by scraping etymonPage. -- Store data in the argsOf table to save time in case the same etymon is accessed again. -- The key is a normalized version of etymonParam. local key = etymonLang:getFullCode() .. ">" .. etymonPage .. ">" .. etymonId if argsOf[key] == nil then local etymonTitle = new_title(etymonPage) if not etymonTitle then -- This shouldn't happen: all unsupported titles should be resolved at this stage. error("Invalid page title \"" .. etymonPage .. "\" encountered.") end scrapePage(etymonPage, etymonTitle, key, etymonLang, etymonId) end return argsOf[key] end -- [tag]: {abbreviation, label glossary anchor, start text, start text plus, middle text, forms groups} -- Note: the keywords `root`, `afeq`, `conf`, and `unc` are also recognized, but do not use this dictionary. -- Please do not add any new keywords without discussion or this list will get extremely unwieldy. -- If we decide to add keywords for each thing I will have to figure out a systematic way to organize them. local keywordDict = { ["from"] = {false, false, "From", "From", "from", false, false}, ["uder"] = {false, false, "From", "From", "from", false, false}, ["inh"] = {false, false, "From", "[[Appendix:Glossary#inherited|Inherited]] from", "from", false}, ["af"] = {false, false, "From", "From", "from", true}, ["blend"] = {"blend.", "blend", "Blend of", "[[Appendix:Glossary#blend|Blend]] of", "a blend of", true}, ["bor"] = {"bor.", "borrowing", "Borrowed from", "[[Appendix:Glossary#borrowing|Borrowed]] from", "borrowed from", false}, ["lbor"] = {"lbor.", "learned_borrowing", "Learned borrowing from", "[[Appendix:Glossary#learned_borrowing|Learned borrowing]] from", "borrowed from", false}, ["obor"] = {"obor.", "orthographic_borrowing", "Orthographic borrowing from", "[[Appendix:Glossary#orthographic_borrowing|Orthographic borrowing]] from", "borrowed from", false}, ["slbor"] = {"slbor.", "semi-learned_borrowing", "Semi-learned borrowing from", "[[Appendix:Glossary#semi-learned_borrowing|Semi-learned borrowing]] from", "borrowed from", false}, ["der"] = {"der.", "derived_terms", "Derived from", "[[Appendix:Glossary#derived_terms|Derived]] from", "from", false}, ["calque"] = {"calq.", "calque", "Calque of", "[[Appendix:Glossary#calque|Calque]] of", "a calque of", false}, ["sl"] = {"sl.", "semantic loan", "Semantic loan of", "[[Appendix:Glossary#semantic_loan|Semantic loan]] of", "a semantic loan of", false}, ["bf"] = {"bf.", "back-formation", "Back-formation from", "[[Appendix:Glossary#Back-formation|Back-formation]] from", "a back-formation from", false}, ["translit"] = {"translit.", "transliteration", "Transliteration of", "[[Appendix:Glossary#transliteration|Transliteration]] of", "borrowed from", false}, ["vrd"] = {"vrd.", "vṛddhi derivative", "Vṛddhi derivative of", "[[vṛddhi|Vṛddhi]] derivative of", "a vṛddhi derivative of", false}, ["aphetic"] = {"aph.", "aphesis", "Aphetic form of", "[[Appendix:Glossary#aphesis|Aphetic form]] of", "an aphetic form of", false}, ["influence"] = {"influ.", "contamination", "", "", "", false} } -- This function takes an etymon and recursively builds a tree to display in an entry. local function etyTree(currTitle, lang, args, alreadySeen, isTopLevel, isUncertain, label) local treeWidth = 0 local treeHeight = 0 local subtree, subtreeHeight, subtreeWidth, etymonLang, etymonPage, etymonArgs local subtrees = {} local currId = "" if type(args) == "table" then currId = args["id"] end local key = getNormLang(lang):getFullCode() .. ">" .. get_link_page(currTitle, lang) .. ">" .. currId local derType, confidence, ignoreEtymons = "from", "conf", false -- Only recurse when an etymon has params and was not included in the tree previously. if type(args) == "table" and alreadySeen[key] == nil then local i, templateLang = 1, getLang(args[1]) -- Add the page to alreadySeen, which keeps track of what's already been added to the tree and the depth reached. alreadySeen[key] = true -- Loop over each parameter in the current template, starting from 2. while true do i = i + 1 local param = args[i] if param == nil then break elseif find(param, ">", nil, true) and not ignoreEtymons then etymonLang, etymonPage = getParts(templateLang, param) -- Scrape the page and get the parameters. etymonArgs = getArgs(templateLang, param) -- Recurse into the etymon and append its tree to the list of subtrees. subtree, subtreeHeight, subtreeWidth = etyTree(etymonPage, etymonLang, etymonArgs, alreadySeen, false, confidence == "unc", derType) insert(subtrees, subtree) treeHeight = max(treeHeight, subtreeHeight) treeWidth = treeWidth + subtreeWidth else -- Reached a keyword. if param == "conf" or param == "unc" then confidence = param elseif keywordDict[param] ~= nil then ignoreEtymons = false confidence = "conf" derType = param else ignoreEtymons = true end end end end -- Create link. local link = "<span style=\"display:inline-block\" class=\"etyl\">" .. lang:getCanonicalName() .. "</span> <span style=\"display:inline-block\">" if isTopLevel then link = link .. makeLink({lang = lang, alt = "'''" .. currTitle .. "'''"}) elseif currId == "" then link = link .. makeLink({lang = lang, term = currTitle}) else link = link .. makeLink({lang = lang, term = currTitle, id = currId}) end link = link .. "</span>" -- Create tree. local tree = "" if #subtrees == 1 then -- Add long top connector. tree = tree .. "<span style=\"position:relative;height:20px;border-right:2px solid var(--wikt-palette-grey,#9e9e9e)\"></span>" elseif #subtrees >= 2 then --Add short top connector. tree = tree .. "<span style=\"position:relative;height:10px;border-right:2px solid var(--wikt-palette-grey,#9e9e9e)\"></span>" end --Create term block. tree = tree .. "<div style=\"position:relative;text-align:center;padding:5px 10px;background:var(--wikt-palette-beige,#fffbf2);color:inherit;border:1px solid var(--wikt-palette-lightgrey,#ccc);border-radius:4px\">" .. link -- Add derivation and uncertainty labels. -- TODO: make the CSS less horrible. if (label ~= "" and keywordDict[label][1] ~= false) or isUncertain then tree = tree .. "<span style=\"z-index:1;position:absolute;transform:translate(-50%);top:calc(100% + 5px);left:50%;border-radius:2px;background:var(--wikt-palette-cyan,#eaffff);color:inherit;font-size:12px;height:10px;line-height:10px\">" if label ~= "" and keywordDict[label][1] ~= false then tree = tree .. "[[Appendix:Glossary#" .. keywordDict[label][2] .. "|<abbr title=\"" .. gsub(keywordDict[label][2], "_", " ") .. "\" style=\"color:var(--wikt-palette-black,#202122);font-style:italic;text-decoration:none\">" .. keywordDict[label][1] .. "</abbr>]]" if isUncertain then -- Add uncertainty label next to the derivation label. tree = tree .. "<abbr title=\"uncertain\" style=\"position:absolute;top:50%;transform:translate(0,-48%);left:calc(100% + 2px);font-size:10px;border-radius:2px;background:var(--wikt-palette-pink,#ffe0f0);color:inherit;padding:1px 2px;font-weight:bold;text-decoration:none\">?</abbr>" end elseif isUncertain then -- Add uncertainty label in the middle. tree = tree .. "<abbr title=\"uncertain\" style=\"position:absolute;top:50%;left:50%;transform:translate(calc(-50% - 1px),-50%);font-size:10px;border-radius:2px;background:var(--wikt-palette-pink,#ffe0f0);color:inherit;padding:1px 2px;font-weight:bold;text-decoration:none\">?</span>" end tree = tree .. "</span>" end tree = tree .. "</div>" -- Append subtrees. local n_subtrees = #subtrees if n_subtrees == 1 then tree = subtrees[1] .. tree elseif n_subtrees >= 2 then local i, subtreeString = 0, "" while true do i = i + 1 local v = subtrees[i] if v == nil then break elseif i == 1 then -- Add left connector. v = v .. "<span style=\"align-self:start;left:50%;width:calc(50% + 0.25em);height:10px;position:relative;border-bottom:2px solid var(--wikt-palette-grey,#9e9e9e);border-left:2px solid var(--wikt-palette-grey,#9e9e9e);border-bottom-left-radius:4px\"></span>" elseif i == n_subtrees then -- Add right connector. v = v .. "<span style=\"align-self:end;right:50%;width:calc(50% + 0.25em);height:10px;position:relative;border-bottom:2px solid var(--wikt-palette-grey,#9e9e9e);border-right:2px solid var(--wikt-palette-grey,#9e9e9e);border-bottom-right-radius:4px\"></span>" else -- Add a short bottom connector and middle connector. v = v .. "<span style=\"position:relative;height:10px;border-right:2px solid var(--wikt-palette-grey,#9e9e9e)\"></span><span style=\"position:relative;width:calc(100% + 0.5em);border-bottom:2px solid var(--wikt-palette-grey,#9e9e9e)\"></span>" end -- Add column div. v = "<div style=\"display:flex;flex-direction:column;align-items:center\">" .. v .. "</div>" subtreeString = subtreeString .. v end tree = "<div style=\"position:relative;display:flex;column-gap:0.5em;align-items:end\">" .. subtreeString .. "</div>" .. tree else --Reached a leaf node. treeWidth = treeWidth + 1 end -- Add outer divs. if isTopLevel then tree = "<div style=\"width:fit-content;margin:auto;padding:0.5em;display:flex;flex-direction:column;align-items:center\">" .. tree .. "</div>" -- 한국어판에는 NavFrame 클래스가 없어 편집 2026.05.29 tree = "<div class=\"etytree\" data-etytree-height=\"" .. treeHeight + 1 .. "\" data-etytree-width=\"" .. treeWidth .. "\">" .. tree .. "</div>" end return tree, treeHeight + 1, treeWidth end -- This function takes an etymon and generates some text to display in an entry. -- Currently, it is only able to handle simple combinations of parameters. local function etyText(title, lang, args, usePlusTemplates, maxDepth) local text = "" local depth = 1 local alreadyWritten = {} local key, currLang, group, groupType, groupConfidence, confidence, derType, foundGroup, complexParams, ignoreEtymons, etymonLang, etymonTitle, etymonId, templateLang -- Loop and continuously expand the sentence until we reach the end of the chain. while not maxDepth or depth <= maxDepth do group, groupType, groupConfidence, confidence, derType, foundGroup, complexParams, ignoreEtymons, currLang = {}, "from", "conf", "conf", "from", false, false, false, lang key = getNormLang(lang):getFullCode() .. ">" .. get_link_page(title, lang) .. ">" .. args["id"] templateLang = getLang(args[1]) -- Stop if we encounter an already-seen term. if alreadyWritten[key] ~= nil then break end alreadyWritten[key] = true local i = 1 -- Iterate from 2. while true do i = i + 1 local param = args[i] if param == nil then break elseif find(param, ">", nil, true) and not ignoreEtymons then -- The text should only continue if `args` is either (not including `influence` or `afeq` etymons): -- A single etymon, or single `af` group. Otherwise the parameters are too "complex" and are rejected. -- TODO: add smarter handling for complex parameters. if foundGroup or (#group == 1 and not keywordDict[derType][6]) then complexParams = true break end groupType = derType if confidence == "unc" then groupConfidence = "unc" end insert(group, param) else -- Reached a keyword. if param == "unc" then confidence = param elseif param == "afeq" or param == "influence" or param == "root" then ignoreEtymons = true if #group == 1 then foundGroup = true end else ignoreEtymons = false confidence = "conf" derType = param if #group == 1 then foundGroup = true end end end end if complexParams or #group == 0 then break end if #group == 1 then args = getArgs(templateLang, group[1]) end if text == "" then -- Start the sentence. if groupConfidence == "conf" and not usePlusTemplates then text = keywordDict[groupType][3] elseif groupConfidence == "conf" and usePlusTemplates then text = keywordDict[groupType][4] else text = "Possibly " .. keywordDict[groupType][5] end else -- Add a phrase onto the sentence. if groupConfidence == "conf" then text = text .. ", " .. keywordDict[groupType][5] else text = text .. ", possibly " .. keywordDict[groupType][5] end end -- Add the links. for i = 1, #group do etymonLang, etymonTitle, etymonId = getParts(templateLang, group[i]) --Make sure ID exists prior to linking to it. if type(getArgs(templateLang, group[i])) ~= "table" then etymonId = nil end if etymonLang:getCanonicalName() ~= currLang:getCanonicalName() then group[i] = etymonLang:makeWikipediaLink() .. " " .. makeLink({lang = etymonLang, term = etymonTitle, id = etymonId}) currLang = etymonLang else group[i] = makeLink({lang = etymonLang, term = etymonTitle, id = etymonId}) end end text = text .. " " .. concat(group, " + ") depth = depth + 1 if #group >= 2 then break end lang = etymonLang title = etymonTitle if type(args) ~= "table" then break end end -- Add a period at the end of the sentence. if text ~= "" then text = text .. "." end return text end -- This function take an etymon and recursively generates categories to add to the entry. -- Currently the behaviour tries to emulate existing templates including {{dercat}}. -- More specific and useful categories are planned pending consensus (e.g. take confidence into account). local function etyCategories(title, langName, args, passedThroughOtherLanguage, inInhChain, categories, seen) local etymonLang, categoryEtymonTitle, etymonTitle, normTitle, etymonId, etymonLangName, etymonNormLangName, etymonArgs, key, L2_key, etymonPassedThroughOtherLanguage, etymonInInhChain, categoryName local templateLang, currGroupLength, derType, isTopLevel = getLang(args[1]), 0, "from" if categories == nil then categories, isTopLevel = {}, true end local i = 1 -- Iterate from 2. while true do i = i + 1 local param = args[i] if param == nil then break elseif find(param, ">", nil, true) then currGroupLength = currGroupLength + 1 etymonLang, etymonTitle, etymonId = getParts(templateLang, param) normTitle = get_link_page(etymonTitle, etymonLang) L2_key = getNormLang(etymonLang):getFullCode() .. ">" .. normTitle key = L2_key .. ">" .. etymonId etymonLangName = etymonLang:getCanonicalName() etymonNormLangName = getNormLang(etymonLang):getFullName() etymonInInhChain = inInhChain and (derType == "from" or derType == "inh") etymonPassedThroughOtherLanguage = passedThroughOtherLanguage or langName ~= etymonNormLangName etymonArgs = getArgs(templateLang, param) -- FIXME: this should use :getCanonicalName() for the target language name and :getDisplayForm() for the source language name. Currently uses :getCanonicalName() for both. if isTopLevel then --Add a maintenance category if an invalid ID is provided. if etymonArgs == "missing" or etymonArgs == "redlink" then if content_page == nil and is_content_page() or content_page then categories[langName .. " entries referencing etymons with invalid IDs"] = true else categories["Entries referencing etymons with invalid IDs/hidden"] = true end end -- Add borrowing categories at the top level only. if derType == "bor" or derType == "lbor" or derType == "slbor" then categories[langName .. " terms borrowed from " .. etymonLangName] = true end if derType == "uder" then categories[langName .. " undefined derivations"] = true elseif derType == "lbor" then categories[langName .. " learned borrowings from " .. etymonLangName] = true elseif derType == "calque" then categories[langName .. " terms calqued from " .. etymonLangName] = true elseif derType == "sl" then categories[langName .. " semantic loans from " .. etymonLangName] = true elseif derType == "slbor" then categories[langName .. " semi-learned borrowings from " .. etymonLangName] = true elseif derType == "translit" then categories[langName .. " transliterations of " .. etymonLangName .. " terms"] = true elseif derType == "bf" then categories[langName .. " back-formations"] = true elseif derType == "blend" then categories[langName .. " blends"] = true elseif derType == "vrd" then categories[langName .. " vrddhi derivatives"] = true elseif derType == "aphetic" then categories[langName .. " aphetic forms"] = true elseif derType == "obor" then categories[langName .. " orthographic borrowings from " .. etymonLangName] = true end end -- Add basic derivation categories. if etymonPassedThroughOtherLanguage and langName == etymonNormLangName then categories[langName .. " terms borrowed back into " .. etymonLangName] = true end if etymonNormLangName ~= langName then categories[langName .. " terms derived from " .. etymonLangName] = true end if etymonNormLangName ~= langName and etymonInInhChain then categories[langName .. " terms inherited from " .. etymonLangName] = true end categoryEtymonTitle = normTitle if sub(categoryEtymonTitle, 1, 15) == "Reconstruction:" then categoryEtymonTitle = gsub(categoryEtymonTitle, "^Reconstruction:[^/]+/", "*") end -- Add affix categories. if type(etymonArgs) == "table" and etymonArgs["pos"] ~= nil and (derType == "af" or derType == "afeq") and isTopLevel then if (etymonArgs["pos"] == "prefix" or etymonArgs["pos"] == "suffix" or etymonArgs["pos"] == "interfix" or etymonArgs["pos"] == "infix") then if etymonArgs["pos"] == "prefix" then categoryName = langName .. " terms prefixed with " .. categoryEtymonTitle elseif etymonArgs["pos"] == "suffix" then categoryName = langName .. " terms suffixed with " .. categoryEtymonTitle elseif etymonArgs["pos"] == "interfix" then categoryName = langName .. " terms interfixed with " .. categoryEtymonTitle elseif etymonArgs["pos"] == "infix" then categoryName = langName .. " terms infixed with " .. categoryEtymonTitle end -- Add ID if necessary for disambiguation. if disambiguationCount[L2_key] > 1 then categoryName = categoryName .. " (" .. etymonId .. ")" end categories[categoryName] = true end end -- Add root categories. -- TODO: there are currently two ways of specifying roots: pos=root on the etymon, -- and the special root keyword. Maybe we should clean this up. if (type(etymonArgs) == "table" and etymonArgs["pos"] == "root") or derType == "root" then if etymonPassedThroughOtherLanguage then categoryName = langName .. " terms derived from the " .. etymonLangName .. " root " .. categoryEtymonTitle else categoryName = langName .. " terms belonging to the root " .. categoryEtymonTitle end -- Add ID if necessary for disambiguation. if (disambiguationCount[L2_key] or 0) > 1 then categoryName = categoryName .. " (" .. etymonId .. ")" end categories[categoryName] = true end -- Recurse into the etymon. if ( not (derType == "afeq" or derType == "influence" or derType == "root") and (seen == nil or seen[key] == nil) and type(etymonArgs) == "table" ) then if seen == nil then seen = {} end seen[key] = true etyCategories(title, langName, etymonArgs, etymonPassedThroughOtherLanguage, etymonInInhChain, categories, seen) end elseif not (param == "unc" or param == "conf") then derType = param currGroupLength = 0 end end return categories end -- TODO: this should all be integrated into etyCategories at the top-level pass. local function paramsSanityCheck(lang, params, id, title, pos) if mw.ustring.len(id) < 2 then error("The `id` parameter must have at least two characters. See the [[Template:etymon/documentation#Parameters|documentation]] for more details.") elseif id == title or id == (page_data or get_page_data()).pagename then error("The `id` parameter must not be the same as the page title. Be more creative. See the [[Template:etymon/documentation#Parameters|documentation]] for more details.") end if pos and pos ~= "prefix" and pos ~= "suffix" and pos ~= "interfix" and pos ~= "infix" and pos ~= "root" then error("Unknown value provided for `pos`. Allowed values are: prefix, suffix, interfix, infix, root.") end local i, currKeyword, singleAfParam, paramLang = 0, "from", "not in group" while true do i = i + 1 local param = params[i] if param == nil then break elseif find(param, ">", nil, true) then --In this case, `templateLang` is the same as `lang` because we are at the top level. paramLang = getParts(lang, param) if currKeyword == "from" then if paramLang:getFullCode() ~= lang:getFullCode() then error("Error: " .. param .. " is associated with `from` (same-language derivation) but is of language `" .. paramLang:getFullCode() .. "`, which does not match the current entry language (`" .. lang:getFullCode() .. "`); see the [[Template:etymon/documentation#Derivation keywords|documentation]] for more details.") end elseif currKeyword == "inh" then check_ancestor(lang, paramLang) elseif keywordDict[currKeyword] and keywordDict[currKeyword][6] then singleAfParam = singleAfParam ~= "not in group" and "found group" or param elseif (currKeyword == "bor" or currKeyword == "lbor" or currKeyword == "obor" or currKeyword == "slbor" or currKeyword == "der" or currKeyword == "uder" or currKeyword == "calque" or currKeyword == "sl") and (paramLang:getCode() == lang:getCode()) then error("Error: " .. param .. " is associated with `" .. currKeyword .. "` but has the same language (`" .. paramLang:getCode() .. "`) as the current entry; see the [[Template:etymon/documentation#Derivation keywords|documentation]] for more details.") end elseif param ~= "unc" and param ~= "conf" and param ~= "afeq" and param ~= "root" and keywordDict[param] == nil then error("Received unknown keyword: " .. param) elseif param ~= "unc" and param ~= "conf" then currKeyword = param if singleAfParam == "found group" then singleAfParam = "not in group" end end end if singleAfParam ~= "not in group" and singleAfParam ~= "found group" then error("Detected `af` or group containing only a single etymon: `" .. singleAfParam .. "`; note that `af` and `afeq` groups must have at least two etymons. See the [[Template:etymon/documentation#Derivation keywords|documentation]] for more details.") end end function export.main(_frame) frame = _frame -- Process argument input. local args = process_params(frame:getParent().args, mw.loadData(parameters_data_module).etymon) local lang = args[1] -- Store non-numeric parameters as locals, then treat the main numeric list as `args`. local id = args["id"] local title = args["title"] local text = args["text"] local tree = args["tree"] local exnihilo = args["exnihilo"] local pos = args["pos"] args = args[2] -- The `title` parameter is used for overriding the page title. if title == nil then -- Get the canonical pagename. title = (page_data or get_page_data()).pagename -- Determine if current term is reconstructed. if page_data.namespace == "Reconstruction" then title = "*" .. title end end paramsSanityCheck(lang, args, id, title, pos) -- Add the langcode and `id`, to match the format of scraped parameters. insert(args, 1, lang:getCode()) args["id"] = id argsOf[args[1] .. ">" .. title .. ">" .. id] = args -- Add anchor to output. local output = {tostring(html_create("ul") :attr("id", language_anchor(lang, id)) :allDone() )} local langName, categories = lang:getFullName(), {} if content_page == nil and is_content_page() or content_page then local categorySet = etyCategories(title, langName, args, false, true) for category in next, categorySet do insert(categories, category) end end -- Special categories. if exnihilo then insert(categories, langName .. " terms coined ex nihilo") end -- Insert tree. if tree then if unallowed_langs[lang:getCode()] then local error_text = "etymology trees are not allowed for " .. lang:getFullName() if unallowed_langs[lang:getCode()]["ref"] then error_text = error_text .. "; see " .. unallowed_langs[lang:getCode()]["ref"] else error_text = error_text .. "." end error(error_text) end insert(output, templatestyles("Module:etymon/styles.css")) insert(output, (etyTree(title, lang, args, {}, true, false, ""))) insert(categories, langName .. " entries with etymology trees") end -- Insert text. if text then if unallowed_langs[lang:getCode()] then local error_text = "etymology texts are not allowed for " .. lang:getFullName() if unallowed_langs[lang:getCode()]["ref"] then error_text = error_text .. "; see " .. unallowed_langs[lang:getCode()]["ref"] else error_text = error_text .. "." end error(error_text) end insert(categories, langName .. " entries with etymology texts") end if text == "++" then insert(output, etyText(title, lang, args, true, false)) elseif text == "+" then insert(output, etyText(title, lang, args, true, 1)) elseif text == "-" then insert(output, etyText(title, lang, args, false, 1)) elseif text ~= nil then insert(output, etyText(title, lang, args, false, false)) end -- [[https://en.wiktionary.org/wiki/Wiktionary:Beer_parlour/2025/May#etymon_for_Chinese]] if #categories > 0 and lang:getCode() ~= "zh" then insert(output, format_categories(categories, lang)) end return concat(output) end return export 5a5krzep0ki3uwgdvjbcbdyomzshipx 4484381 4484380 2026-05-29T03:31:25Z Jeebeen 13056 4484381 Scribunto text/plain local export = {} local anchors_module = "Module:anchors" local etymology_module = "Module:etymology" local headword_data_module = "Module:headword/data" local languages_module = "Module:languages" local languages_errorgetby_module = "Module:languages/errorGetBy" local links_module = "Module:also/link" local pages_module = "Module:pages" local parameters_module = "Module:parameters" local parameters_data_module = "Module:parameters/data" local string_utilities_module = "Module:string utilities" local template_parser_module = "Module:template parser/sandbox" local templatestyles_module = "Module:TemplateStyles" local utilities_module = "Module:utilities" local debug_module = "Module:debug" local concat = table.concat local find = string.find local gsub = string.gsub local html_create = mw.html.create local insert = table.insert local match = string.match local max = math.max local new_title = mw.title.new local next = next local require = require local sub = string.sub local tostring = tostring local type = type local unpack = unpack or table.unpack -- Lua 5.2 compatibility local function track(page) trackfn("etymon/" .. page) return true end local unallowed_langs = { ["zh"] = { ["ref"] = "[[Wiktionary:Beer_parlour/2025/May#etymon_for_Chinese]]" } } --[==[ Loaders for functions in other modules, which overwrite themselves with the target function when called. This ensures modules are only loaded when needed, retains the speed/convenience of locally-declared pre-loaded functions, and has no overhead after the first call, since the target functions are called directly in any subsequent calls.]==] local function check_ancestor(...) check_ancestor = require(etymology_module).check_ancestor return check_ancestor(...) end local function find_templates(...) find_templates = require(template_parser_module).find_templates return find_templates(...) end local function format_categories(...) format_categories = require(utilities_module).format_categories return format_categories(...) end local function full_link(...) full_link = require(links_module).full_link return full_link(...) end local function get_lang(...) get_lang = require(languages_module).getByCode return get_lang(...) end local function get_link_page(...) get_link_page = require(links_module).get_link_page return get_link_page(...) end local function get_section(...) get_section = require(pages_module).get_section return get_section(...) end local function language_anchor(...) language_anchor = require(anchors_module).language_anchor return language_anchor(...) end local function process_params(...) process_params = require(parameters_module).process return process_params(...) end local function split(...) split = require(string_utilities_module).split return split(...) end local function templatestyles(...) templatestyles = require(templatestyles_module) return templatestyles(...) end local function trim(...) trim = require(string_utilities_module).trim return trim(...) end local function trackfn(...) trackfn = require(debug_module).track return trackfn(...) end --[==[ Loaders for objects, which load data (or some other object) into some variable, which can then be accessed as "foo or get_foo()", where the function get_foo sets the object to "foo" and then returns it. This ensures they are only loaded when needed, and avoids the need to check for the existence of the object each time, since once "foo" has been set, "get_foo" will not be called again.]==] local content_page local function is_content_page() content_page, is_content_page = require(pages_module).is_content_page(mw.title.getCurrentTitle()), nil return content_page end local page_data local function get_page_data() page_data, get_page_data = mw.loadData(headword_data_module).page, nil return page_data end local frame -- Generate an HTML link. local function makeLink(params) -- [[Wiktionary:Beer_parlour/2025/May#{{etymon}}_for_Chinese]] if params["lang"]:getCode() == "zh" then params["tr"] = "" end return full_link(params, "term") end -- Get a language object. local function getLang(code) return get_lang(code, nil, true) or require(languages_errorgetby_module).code(code, true, true) end -- Normalize the language so that special handling of Chinese is accounted for. -- This is everything in the Sinitic family which isn't a creole, pidgin or mixed language. local function getNormLang(lang) if lang:inFamily("zhx") and not lang:inFamily("qfa-cnt") then return get_lang("zh") end return lang end -- Given an etymon param, return its parts. local function getParts(templateLang, etymonParam) local etymonLang, etymonLangcode, etymonPage, etymonId local parts = split(etymonParam, ">", true) local n = #parts for i = 1, n do parts[i] = trim(parts[i]) end -- FIXME: this doesn't work properly if nested templates output HTML tags, which is likely to cause bugs that are hard for ordinary users to fix. if n == 2 then -- Assume language is the same as the template call if none is provided. etymonLang, etymonPage, etymonId = templateLang, unpack(parts) else etymonLangcode, etymonPage, etymonId = unpack(parts) etymonLang = getLang(etymonLangcode) end return etymonLang, etymonPage, etymonId end local argsOf = {} local disambiguationCount = {} local function scrapePage(etymonPage, etymonTitle, key, etymonLang, etymonId, redirectedFrom) local content = etymonTitle:getContent() if content == nil then argsOf[key] = "redlink" return end -- Search only the relevant L2 entry, unless it's a redirect, in which case search the whole page. local redirectTarget = etymonTitle.redirectTarget if not redirectTarget then content = get_section(content, etymonLang:getFullName(), 2) if content == nil then argsOf[key] = "missing" return end end local etymonLangcode = etymonLang:getFullCode() local L2_key = etymonLangcode .. ">" .. etymonPage -- Search for the template on the page (even if this is a redirect page). -- FIXME: mw.uri.anchorEncode on IDs. Not possible to implement until ">" syntax is fixed (see comment in getParts). for template in find_templates(content) do if template:get_name() == "etymon" then local templateArgs = template:get_arguments() if templateArgs[1] == etymonLangcode then argsOf[L2_key .. ">" .. templateArgs["id"]] = templateArgs disambiguationCount[L2_key] = (disambiguationCount[L2_key] or 0) + 1 end end end if redirectedFrom and disambiguationCount[L2_key] then disambiguationCount[redirectedFrom] = (disambiguationCount[redirectedFrom] or 0) + disambiguationCount[L2_key] end -- If scraping produced a result, there's nothing left to do. if argsOf[key] then return -- Else if we've already followed a redirect and still found nothing, record the template as missing. elseif redirectedFrom then argsOf[key] = "missing" return end -- Check if the page is a redirect, and if not record the template as missing. if not redirectTarget then argsOf[key] = "missing" return end -- Otherwise, try again with the redirect target. etymonPage = redirectTarget.prefixedText scrapePage(etymonPage, redirectTarget, L2_key .. ">" .. etymonId, etymonLang, etymonId, L2_key) -- Record the value as the same as the redirect's. argsOf[key] = argsOf[etymonLangcode .. ">" .. etymonPage .. ">" .. etymonId] end -- Given an etymon, scrape the page and get its parameters. -- This function returns either: a table of the params, "missing", "redlink", or "nolink" local function getArgs(templateLang, etymonParam) -- Get normalized parts of the etymon parameter. local etymonLang, etymonPage, etymonId = getParts(templateLang, etymonParam) -- "?" is a special value that unlinks the page. TODO: Figure this out... if etymonId == "?" then return "nolink" end -- If multiple terms are linked like A//B, only look at A. etymonPage = match(etymonPage, "^(.-)//") or etymonPage etymonPage = get_link_page(etymonPage, etymonLang) etymonLang = getNormLang(etymonLang) -- Find the parameters by scraping etymonPage. -- Store data in the argsOf table to save time in case the same etymon is accessed again. -- The key is a normalized version of etymonParam. local key = etymonLang:getFullCode() .. ">" .. etymonPage .. ">" .. etymonId if argsOf[key] == nil then local etymonTitle = new_title(etymonPage) if not etymonTitle then -- This shouldn't happen: all unsupported titles should be resolved at this stage. error("Invalid page title \"" .. etymonPage .. "\" encountered.") end scrapePage(etymonPage, etymonTitle, key, etymonLang, etymonId) end return argsOf[key] end -- [tag]: {abbreviation, label glossary anchor, start text, start text plus, middle text, forms groups} -- Note: the keywords `root`, `afeq`, `conf`, and `unc` are also recognized, but do not use this dictionary. -- Please do not add any new keywords without discussion or this list will get extremely unwieldy. -- If we decide to add keywords for each thing I will have to figure out a systematic way to organize them. local keywordDict = { ["from"] = {false, false, "From", "From", "from", false, false}, ["uder"] = {false, false, "From", "From", "from", false, false}, ["inh"] = {false, false, "From", "[[Appendix:Glossary#inherited|Inherited]] from", "from", false}, ["af"] = {false, false, "From", "From", "from", true}, ["blend"] = {"blend.", "blend", "Blend of", "[[Appendix:Glossary#blend|Blend]] of", "a blend of", true}, ["bor"] = {"bor.", "borrowing", "Borrowed from", "[[Appendix:Glossary#borrowing|Borrowed]] from", "borrowed from", false}, ["lbor"] = {"lbor.", "learned_borrowing", "Learned borrowing from", "[[Appendix:Glossary#learned_borrowing|Learned borrowing]] from", "borrowed from", false}, ["obor"] = {"obor.", "orthographic_borrowing", "Orthographic borrowing from", "[[Appendix:Glossary#orthographic_borrowing|Orthographic borrowing]] from", "borrowed from", false}, ["slbor"] = {"slbor.", "semi-learned_borrowing", "Semi-learned borrowing from", "[[Appendix:Glossary#semi-learned_borrowing|Semi-learned borrowing]] from", "borrowed from", false}, ["der"] = {"der.", "derived_terms", "Derived from", "[[Appendix:Glossary#derived_terms|Derived]] from", "from", false}, ["calque"] = {"calq.", "calque", "Calque of", "[[Appendix:Glossary#calque|Calque]] of", "a calque of", false}, ["sl"] = {"sl.", "semantic loan", "Semantic loan of", "[[Appendix:Glossary#semantic_loan|Semantic loan]] of", "a semantic loan of", false}, ["bf"] = {"bf.", "back-formation", "Back-formation from", "[[Appendix:Glossary#Back-formation|Back-formation]] from", "a back-formation from", false}, ["translit"] = {"translit.", "transliteration", "Transliteration of", "[[Appendix:Glossary#transliteration|Transliteration]] of", "borrowed from", false}, ["vrd"] = {"vrd.", "vṛddhi derivative", "Vṛddhi derivative of", "[[vṛddhi|Vṛddhi]] derivative of", "a vṛddhi derivative of", false}, ["aphetic"] = {"aph.", "aphesis", "Aphetic form of", "[[Appendix:Glossary#aphesis|Aphetic form]] of", "an aphetic form of", false}, ["influence"] = {"influ.", "contamination", "", "", "", false} } -- This function takes an etymon and recursively builds a tree to display in an entry. local function etyTree(currTitle, lang, args, alreadySeen, isTopLevel, isUncertain, label) local treeWidth = 0 local treeHeight = 0 local subtree, subtreeHeight, subtreeWidth, etymonLang, etymonPage, etymonArgs local subtrees = {} local currId = "" if type(args) == "table" then currId = args["id"] end local key = getNormLang(lang):getFullCode() .. ">" .. get_link_page(currTitle, lang) .. ">" .. currId local derType, confidence, ignoreEtymons = "from", "conf", false -- Only recurse when an etymon has params and was not included in the tree previously. if type(args) == "table" and alreadySeen[key] == nil then local i, templateLang = 1, getLang(args[1]) -- Add the page to alreadySeen, which keeps track of what's already been added to the tree and the depth reached. alreadySeen[key] = true -- Loop over each parameter in the current template, starting from 2. while true do i = i + 1 local param = args[i] if param == nil then break elseif find(param, ">", nil, true) and not ignoreEtymons then etymonLang, etymonPage = getParts(templateLang, param) -- Scrape the page and get the parameters. etymonArgs = getArgs(templateLang, param) -- Recurse into the etymon and append its tree to the list of subtrees. subtree, subtreeHeight, subtreeWidth = etyTree(etymonPage, etymonLang, etymonArgs, alreadySeen, false, confidence == "unc", derType) insert(subtrees, subtree) treeHeight = max(treeHeight, subtreeHeight) treeWidth = treeWidth + subtreeWidth else -- Reached a keyword. if param == "conf" or param == "unc" then confidence = param elseif keywordDict[param] ~= nil then ignoreEtymons = false confidence = "conf" derType = param else ignoreEtymons = true end end end end -- Create link. local link = "<span style=\"display:inline-block\" class=\"etyl\">" .. lang:getCanonicalName() .. "</span> <span style=\"display:inline-block\">" if isTopLevel then link = link .. makeLink({lang = lang, alt = "'''" .. currTitle .. "'''"}) elseif currId == "" then link = link .. makeLink({lang = lang, term = currTitle}) else link = link .. makeLink({lang = lang, term = currTitle, id = currId}) end link = link .. "</span>" -- Create tree. local tree = "" if #subtrees == 1 then -- Add long top connector. tree = tree .. "<span style=\"position:relative;height:20px;border-right:2px solid var(--wikt-palette-grey,#9e9e9e)\"></span>" elseif #subtrees >= 2 then --Add short top connector. tree = tree .. "<span style=\"position:relative;height:10px;border-right:2px solid var(--wikt-palette-grey,#9e9e9e)\"></span>" end --Create term block. tree = tree .. "<div style=\"position:relative;text-align:center;padding:5px 10px;background:var(--wikt-palette-beige,#fffbf2);color:inherit;border:1px solid var(--wikt-palette-lightgrey,#ccc);border-radius:4px\">" .. link -- Add derivation and uncertainty labels. -- TODO: make the CSS less horrible. if (label ~= "" and keywordDict[label][1] ~= false) or isUncertain then tree = tree .. "<span style=\"z-index:1;position:absolute;transform:translate(-50%);top:calc(100% + 5px);left:50%;border-radius:2px;background:var(--wikt-palette-cyan,#eaffff);color:inherit;font-size:12px;height:10px;line-height:10px\">" if label ~= "" and keywordDict[label][1] ~= false then tree = tree .. "[[Appendix:Glossary#" .. keywordDict[label][2] .. "|<abbr title=\"" .. gsub(keywordDict[label][2], "_", " ") .. "\" style=\"color:var(--wikt-palette-black,#202122);font-style:italic;text-decoration:none\">" .. keywordDict[label][1] .. "</abbr>]]" if isUncertain then -- Add uncertainty label next to the derivation label. tree = tree .. "<abbr title=\"uncertain\" style=\"position:absolute;top:50%;transform:translate(0,-48%);left:calc(100% + 2px);font-size:10px;border-radius:2px;background:var(--wikt-palette-pink,#ffe0f0);color:inherit;padding:1px 2px;font-weight:bold;text-decoration:none\">?</abbr>" end elseif isUncertain then -- Add uncertainty label in the middle. tree = tree .. "<abbr title=\"uncertain\" style=\"position:absolute;top:50%;left:50%;transform:translate(calc(-50% - 1px),-50%);font-size:10px;border-radius:2px;background:var(--wikt-palette-pink,#ffe0f0);color:inherit;padding:1px 2px;font-weight:bold;text-decoration:none\">?</span>" end tree = tree .. "</span>" end tree = tree .. "</div>" -- Append subtrees. local n_subtrees = #subtrees if n_subtrees == 1 then tree = subtrees[1] .. tree elseif n_subtrees >= 2 then local i, subtreeString = 0, "" while true do i = i + 1 local v = subtrees[i] if v == nil then break elseif i == 1 then -- Add left connector. v = v .. "<span style=\"align-self:start;left:50%;width:calc(50% + 0.25em);height:10px;position:relative;border-bottom:2px solid var(--wikt-palette-grey,#9e9e9e);border-left:2px solid var(--wikt-palette-grey,#9e9e9e);border-bottom-left-radius:4px\"></span>" elseif i == n_subtrees then -- Add right connector. v = v .. "<span style=\"align-self:end;right:50%;width:calc(50% + 0.25em);height:10px;position:relative;border-bottom:2px solid var(--wikt-palette-grey,#9e9e9e);border-right:2px solid var(--wikt-palette-grey,#9e9e9e);border-bottom-right-radius:4px\"></span>" else -- Add a short bottom connector and middle connector. v = v .. "<span style=\"position:relative;height:10px;border-right:2px solid var(--wikt-palette-grey,#9e9e9e)\"></span><span style=\"position:relative;width:calc(100% + 0.5em);border-bottom:2px solid var(--wikt-palette-grey,#9e9e9e)\"></span>" end -- Add column div. v = "<div style=\"display:flex;flex-direction:column;align-items:center\">" .. v .. "</div>" subtreeString = subtreeString .. v end tree = "<div style=\"position:relative;display:flex;column-gap:0.5em;align-items:end\">" .. subtreeString .. "</div>" .. tree else --Reached a leaf node. treeWidth = treeWidth + 1 end -- Add outer divs. if isTopLevel then tree = "<div style=\"width:fit-content;margin:auto;padding:0.5em;display:flex;flex-direction:column;align-items:center\">" .. tree .. "</div>" -- 한국어판에는 NavFrame 클래스가 없어 etymon tree가 표시되지 않는 문제로 편집 2026.05.29 tree = "<div class=\"etytree\" data-etytree-height=\"" .. treeHeight + 1 .. "\" data-etytree-width=\"" .. treeWidth .. "\">" .. tree .. "</div>" end return tree, treeHeight + 1, treeWidth end -- This function takes an etymon and generates some text to display in an entry. -- Currently, it is only able to handle simple combinations of parameters. local function etyText(title, lang, args, usePlusTemplates, maxDepth) local text = "" local depth = 1 local alreadyWritten = {} local key, currLang, group, groupType, groupConfidence, confidence, derType, foundGroup, complexParams, ignoreEtymons, etymonLang, etymonTitle, etymonId, templateLang -- Loop and continuously expand the sentence until we reach the end of the chain. while not maxDepth or depth <= maxDepth do group, groupType, groupConfidence, confidence, derType, foundGroup, complexParams, ignoreEtymons, currLang = {}, "from", "conf", "conf", "from", false, false, false, lang key = getNormLang(lang):getFullCode() .. ">" .. get_link_page(title, lang) .. ">" .. args["id"] templateLang = getLang(args[1]) -- Stop if we encounter an already-seen term. if alreadyWritten[key] ~= nil then break end alreadyWritten[key] = true local i = 1 -- Iterate from 2. while true do i = i + 1 local param = args[i] if param == nil then break elseif find(param, ">", nil, true) and not ignoreEtymons then -- The text should only continue if `args` is either (not including `influence` or `afeq` etymons): -- A single etymon, or single `af` group. Otherwise the parameters are too "complex" and are rejected. -- TODO: add smarter handling for complex parameters. if foundGroup or (#group == 1 and not keywordDict[derType][6]) then complexParams = true break end groupType = derType if confidence == "unc" then groupConfidence = "unc" end insert(group, param) else -- Reached a keyword. if param == "unc" then confidence = param elseif param == "afeq" or param == "influence" or param == "root" then ignoreEtymons = true if #group == 1 then foundGroup = true end else ignoreEtymons = false confidence = "conf" derType = param if #group == 1 then foundGroup = true end end end end if complexParams or #group == 0 then break end if #group == 1 then args = getArgs(templateLang, group[1]) end if text == "" then -- Start the sentence. if groupConfidence == "conf" and not usePlusTemplates then text = keywordDict[groupType][3] elseif groupConfidence == "conf" and usePlusTemplates then text = keywordDict[groupType][4] else text = "Possibly " .. keywordDict[groupType][5] end else -- Add a phrase onto the sentence. if groupConfidence == "conf" then text = text .. ", " .. keywordDict[groupType][5] else text = text .. ", possibly " .. keywordDict[groupType][5] end end -- Add the links. for i = 1, #group do etymonLang, etymonTitle, etymonId = getParts(templateLang, group[i]) --Make sure ID exists prior to linking to it. if type(getArgs(templateLang, group[i])) ~= "table" then etymonId = nil end if etymonLang:getCanonicalName() ~= currLang:getCanonicalName() then group[i] = etymonLang:makeWikipediaLink() .. " " .. makeLink({lang = etymonLang, term = etymonTitle, id = etymonId}) currLang = etymonLang else group[i] = makeLink({lang = etymonLang, term = etymonTitle, id = etymonId}) end end text = text .. " " .. concat(group, " + ") depth = depth + 1 if #group >= 2 then break end lang = etymonLang title = etymonTitle if type(args) ~= "table" then break end end -- Add a period at the end of the sentence. if text ~= "" then text = text .. "." end return text end -- This function take an etymon and recursively generates categories to add to the entry. -- Currently the behaviour tries to emulate existing templates including {{dercat}}. -- More specific and useful categories are planned pending consensus (e.g. take confidence into account). local function etyCategories(title, langName, args, passedThroughOtherLanguage, inInhChain, categories, seen) local etymonLang, categoryEtymonTitle, etymonTitle, normTitle, etymonId, etymonLangName, etymonNormLangName, etymonArgs, key, L2_key, etymonPassedThroughOtherLanguage, etymonInInhChain, categoryName local templateLang, currGroupLength, derType, isTopLevel = getLang(args[1]), 0, "from" if categories == nil then categories, isTopLevel = {}, true end local i = 1 -- Iterate from 2. while true do i = i + 1 local param = args[i] if param == nil then break elseif find(param, ">", nil, true) then currGroupLength = currGroupLength + 1 etymonLang, etymonTitle, etymonId = getParts(templateLang, param) normTitle = get_link_page(etymonTitle, etymonLang) L2_key = getNormLang(etymonLang):getFullCode() .. ">" .. normTitle key = L2_key .. ">" .. etymonId etymonLangName = etymonLang:getCanonicalName() etymonNormLangName = getNormLang(etymonLang):getFullName() etymonInInhChain = inInhChain and (derType == "from" or derType == "inh") etymonPassedThroughOtherLanguage = passedThroughOtherLanguage or langName ~= etymonNormLangName etymonArgs = getArgs(templateLang, param) -- FIXME: this should use :getCanonicalName() for the target language name and :getDisplayForm() for the source language name. Currently uses :getCanonicalName() for both. if isTopLevel then --Add a maintenance category if an invalid ID is provided. if etymonArgs == "missing" or etymonArgs == "redlink" then if content_page == nil and is_content_page() or content_page then categories[langName .. " entries referencing etymons with invalid IDs"] = true else categories["Entries referencing etymons with invalid IDs/hidden"] = true end end -- Add borrowing categories at the top level only. if derType == "bor" or derType == "lbor" or derType == "slbor" then categories[langName .. " terms borrowed from " .. etymonLangName] = true end if derType == "uder" then categories[langName .. " undefined derivations"] = true elseif derType == "lbor" then categories[langName .. " learned borrowings from " .. etymonLangName] = true elseif derType == "calque" then categories[langName .. " terms calqued from " .. etymonLangName] = true elseif derType == "sl" then categories[langName .. " semantic loans from " .. etymonLangName] = true elseif derType == "slbor" then categories[langName .. " semi-learned borrowings from " .. etymonLangName] = true elseif derType == "translit" then categories[langName .. " transliterations of " .. etymonLangName .. " terms"] = true elseif derType == "bf" then categories[langName .. " back-formations"] = true elseif derType == "blend" then categories[langName .. " blends"] = true elseif derType == "vrd" then categories[langName .. " vrddhi derivatives"] = true elseif derType == "aphetic" then categories[langName .. " aphetic forms"] = true elseif derType == "obor" then categories[langName .. " orthographic borrowings from " .. etymonLangName] = true end end -- Add basic derivation categories. if etymonPassedThroughOtherLanguage and langName == etymonNormLangName then categories[langName .. " terms borrowed back into " .. etymonLangName] = true end if etymonNormLangName ~= langName then categories[langName .. " terms derived from " .. etymonLangName] = true end if etymonNormLangName ~= langName and etymonInInhChain then categories[langName .. " terms inherited from " .. etymonLangName] = true end categoryEtymonTitle = normTitle if sub(categoryEtymonTitle, 1, 15) == "Reconstruction:" then categoryEtymonTitle = gsub(categoryEtymonTitle, "^Reconstruction:[^/]+/", "*") end -- Add affix categories. if type(etymonArgs) == "table" and etymonArgs["pos"] ~= nil and (derType == "af" or derType == "afeq") and isTopLevel then if (etymonArgs["pos"] == "prefix" or etymonArgs["pos"] == "suffix" or etymonArgs["pos"] == "interfix" or etymonArgs["pos"] == "infix") then if etymonArgs["pos"] == "prefix" then categoryName = langName .. " terms prefixed with " .. categoryEtymonTitle elseif etymonArgs["pos"] == "suffix" then categoryName = langName .. " terms suffixed with " .. categoryEtymonTitle elseif etymonArgs["pos"] == "interfix" then categoryName = langName .. " terms interfixed with " .. categoryEtymonTitle elseif etymonArgs["pos"] == "infix" then categoryName = langName .. " terms infixed with " .. categoryEtymonTitle end -- Add ID if necessary for disambiguation. if disambiguationCount[L2_key] > 1 then categoryName = categoryName .. " (" .. etymonId .. ")" end categories[categoryName] = true end end -- Add root categories. -- TODO: there are currently two ways of specifying roots: pos=root on the etymon, -- and the special root keyword. Maybe we should clean this up. if (type(etymonArgs) == "table" and etymonArgs["pos"] == "root") or derType == "root" then if etymonPassedThroughOtherLanguage then categoryName = langName .. " terms derived from the " .. etymonLangName .. " root " .. categoryEtymonTitle else categoryName = langName .. " terms belonging to the root " .. categoryEtymonTitle end -- Add ID if necessary for disambiguation. if (disambiguationCount[L2_key] or 0) > 1 then categoryName = categoryName .. " (" .. etymonId .. ")" end categories[categoryName] = true end -- Recurse into the etymon. if ( not (derType == "afeq" or derType == "influence" or derType == "root") and (seen == nil or seen[key] == nil) and type(etymonArgs) == "table" ) then if seen == nil then seen = {} end seen[key] = true etyCategories(title, langName, etymonArgs, etymonPassedThroughOtherLanguage, etymonInInhChain, categories, seen) end elseif not (param == "unc" or param == "conf") then derType = param currGroupLength = 0 end end return categories end -- TODO: this should all be integrated into etyCategories at the top-level pass. local function paramsSanityCheck(lang, params, id, title, pos) if mw.ustring.len(id) < 2 then error("The `id` parameter must have at least two characters. See the [[Template:etymon/documentation#Parameters|documentation]] for more details.") elseif id == title or id == (page_data or get_page_data()).pagename then error("The `id` parameter must not be the same as the page title. Be more creative. See the [[Template:etymon/documentation#Parameters|documentation]] for more details.") end if pos and pos ~= "prefix" and pos ~= "suffix" and pos ~= "interfix" and pos ~= "infix" and pos ~= "root" then error("Unknown value provided for `pos`. Allowed values are: prefix, suffix, interfix, infix, root.") end local i, currKeyword, singleAfParam, paramLang = 0, "from", "not in group" while true do i = i + 1 local param = params[i] if param == nil then break elseif find(param, ">", nil, true) then --In this case, `templateLang` is the same as `lang` because we are at the top level. paramLang = getParts(lang, param) if currKeyword == "from" then if paramLang:getFullCode() ~= lang:getFullCode() then error("Error: " .. param .. " is associated with `from` (same-language derivation) but is of language `" .. paramLang:getFullCode() .. "`, which does not match the current entry language (`" .. lang:getFullCode() .. "`); see the [[Template:etymon/documentation#Derivation keywords|documentation]] for more details.") end elseif currKeyword == "inh" then check_ancestor(lang, paramLang) elseif keywordDict[currKeyword] and keywordDict[currKeyword][6] then singleAfParam = singleAfParam ~= "not in group" and "found group" or param elseif (currKeyword == "bor" or currKeyword == "lbor" or currKeyword == "obor" or currKeyword == "slbor" or currKeyword == "der" or currKeyword == "uder" or currKeyword == "calque" or currKeyword == "sl") and (paramLang:getCode() == lang:getCode()) then error("Error: " .. param .. " is associated with `" .. currKeyword .. "` but has the same language (`" .. paramLang:getCode() .. "`) as the current entry; see the [[Template:etymon/documentation#Derivation keywords|documentation]] for more details.") end elseif param ~= "unc" and param ~= "conf" and param ~= "afeq" and param ~= "root" and keywordDict[param] == nil then error("Received unknown keyword: " .. param) elseif param ~= "unc" and param ~= "conf" then currKeyword = param if singleAfParam == "found group" then singleAfParam = "not in group" end end end if singleAfParam ~= "not in group" and singleAfParam ~= "found group" then error("Detected `af` or group containing only a single etymon: `" .. singleAfParam .. "`; note that `af` and `afeq` groups must have at least two etymons. See the [[Template:etymon/documentation#Derivation keywords|documentation]] for more details.") end end function export.main(_frame) frame = _frame -- Process argument input. local args = process_params(frame:getParent().args, mw.loadData(parameters_data_module).etymon) local lang = args[1] -- Store non-numeric parameters as locals, then treat the main numeric list as `args`. local id = args["id"] local title = args["title"] local text = args["text"] local tree = args["tree"] local exnihilo = args["exnihilo"] local pos = args["pos"] args = args[2] -- The `title` parameter is used for overriding the page title. if title == nil then -- Get the canonical pagename. title = (page_data or get_page_data()).pagename -- Determine if current term is reconstructed. if page_data.namespace == "Reconstruction" then title = "*" .. title end end paramsSanityCheck(lang, args, id, title, pos) -- Add the langcode and `id`, to match the format of scraped parameters. insert(args, 1, lang:getCode()) args["id"] = id argsOf[args[1] .. ">" .. title .. ">" .. id] = args -- Add anchor to output. local output = {tostring(html_create("ul") :attr("id", language_anchor(lang, id)) :allDone() )} local langName, categories = lang:getFullName(), {} if content_page == nil and is_content_page() or content_page then local categorySet = etyCategories(title, langName, args, false, true) for category in next, categorySet do insert(categories, category) end end -- Special categories. if exnihilo then insert(categories, langName .. " terms coined ex nihilo") end -- Insert tree. if tree then if unallowed_langs[lang:getCode()] then local error_text = "etymology trees are not allowed for " .. lang:getFullName() if unallowed_langs[lang:getCode()]["ref"] then error_text = error_text .. "; see " .. unallowed_langs[lang:getCode()]["ref"] else error_text = error_text .. "." end error(error_text) end insert(output, templatestyles("Module:etymon/styles.css")) insert(output, (etyTree(title, lang, args, {}, true, false, ""))) insert(categories, langName .. " entries with etymology trees") end -- Insert text. if text then if unallowed_langs[lang:getCode()] then local error_text = "etymology texts are not allowed for " .. lang:getFullName() if unallowed_langs[lang:getCode()]["ref"] then error_text = error_text .. "; see " .. unallowed_langs[lang:getCode()]["ref"] else error_text = error_text .. "." end error(error_text) end insert(categories, langName .. " entries with etymology texts") end if text == "++" then insert(output, etyText(title, lang, args, true, false)) elseif text == "+" then insert(output, etyText(title, lang, args, true, 1)) elseif text == "-" then insert(output, etyText(title, lang, args, false, 1)) elseif text ~= nil then insert(output, etyText(title, lang, args, false, false)) end -- [[https://en.wiktionary.org/wiki/Wiktionary:Beer_parlour/2025/May#etymon_for_Chinese]] if #categories > 0 and lang:getCode() ~= "zh" then insert(output, format_categories(categories, lang)) end return concat(output) end return export sphzupzwbq3xb2ro16109bpnucqraxv 부쳐 0 496393 4484374 2026-05-29T03:11:16Z Jeebeen 13056 새 문서: == 근대 한국어 == === 어원 === {{etymon|ko-ear|inh|okm>부텨>불교|id=불교}} === 명사 === {{head|ko-ear}} # [[부처]] 4484374 wikitext text/x-wiki == 근대 한국어 == === 어원 === {{etymon|ko-ear|inh|okm>부텨>불교|id=불교}} === 명사 === {{head|ko-ear}} # [[부처]] bjangp5lm1573k8m6avk8pehiybncde 4484377 4484374 2026-05-29T03:14:43Z Jeebeen 13056 /* 명사 */ 4484377 wikitext text/x-wiki == 근대 한국어 == === 어원 === {{etymon|ko-ear|inh|okm>부텨>불교|id=불교}} === 명사 === {{head|ko-ear|명사}} # [[부처]] a8iz3sui4cj3erx3leic466t7bcm2xy 부텨 0 496394 4484376 2026-05-29T03:13:05Z Jeebeen 13056 새 문서: == 중세 한국어 == === 어원 === {{etymon|okm|inh|oko>佛體>불교|id=불교}} === 명사 === {{head|okm|명사}} # [[부처]] 4484376 wikitext text/x-wiki == 중세 한국어 == === 어원 === {{etymon|okm|inh|oko>佛體>불교|id=불교}} === 명사 === {{head|okm|명사}} # [[부처]] nb09y4aw089a9mykr9mwgrajgit7gma 샤인머스캣 0 496395 4484384 2026-05-29T04:40:15Z Jeebeen 13056 새 문서: == 한국어 == {{위키백과}} === 어원 === * {{bor|ko|ja|シャインマスカット}}으로, {{surf|ko|샤인|머스캣|t2=포도의 품종군}}. === 발음 === {{ko-IPA|l=2}} === 명사 === {{한국어 명사}} # [[일본]]에서 개발된 [[씨없는]] [[머스캣]] [[품종]]의 [[청포도]] ==== 파생어 ==== {{col|ko|샤인모수끼|샤모끼}} 4484384 wikitext text/x-wiki == 한국어 == {{위키백과}} === 어원 === * {{bor|ko|ja|シャインマスカット}}으로, {{surf|ko|샤인|머스캣|t2=포도의 품종군}}. === 발음 === {{ko-IPA|l=2}} === 명사 === {{한국어 명사}} # [[일본]]에서 개발된 [[씨없는]] [[머스캣]] [[품종]]의 [[청포도]] ==== 파생어 ==== {{col|ko|샤인모수끼|샤모끼}} ameg7kpbu80avb4xdtj0vms722isruw