มอดูล:family tree
- The following documentation is located at มอดูล:family tree/documentation. [edit]
- Useful links: subpage list • links • transclusions • testcases • sandbox
Family tree
แก้ไขThis module allows for the display of English Wiktionary's hierarchical language and family ancestry data.
{{#invoke:family tree|show|language code}}
- The first parameter is the language code.
- Add
|fam=1
(alias|2=
) to show language families as separate (often redundant) nodes from their proto-languages. Ordinarily proto-languages are shown without the families that they are the parent of. - Add
|etym=1
(alias|3=
) to show all etymology languages (as children of a "parent" language or language family). Ordinarily they are not shown. - Add
|famunderproto=1
to show families on a line below the proto-languages that belong to the family and are the common ancestor of its members, and|protounderfam=1
to do the reverse. - Add
|collapsed=1
to have the top level of the tree collapsed by default.
- เจอร์แมนิกดั้งเดิม (gem-pro)
- ├───┬ เจอร์แมนิกตะวันตก (gmw)
- │ └───┬ เจอร์แมนิกตะวันตกดั้งเดิม (gmw-pro)
- │ ├──── Low Franconian (gmw-frk)
- │ ├──── Suevic (gem-sue)
- │ ├───┬ แฟรงก์ (frk)
- │ │ └───┬ ดัตช์เก่า (odt)
- │ │ ├──── Bergish (gmw-bgh)
- │ │ └───┬ ดัตช์กลาง (dum)
- │ │ ├──── West Flemish (vls)
- │ │ ├──── Zealandic (zea)
- │ │ ├───┬ ดัตช์ (nl)
- │ │ │ ├──── Belgian Dutch (nl-BE)
- │ │ │ ├──── Berbice Creole Dutch (brc)
- │ │ │ ├──── Jersey Dutch (gmw-jdt)
- │ │ │ ├──── Skepi Creole Dutch (skw)
- │ │ │ ├──── เนเกอร์ฮอลันดส์ (dcr)
- │ │ │ └───┬ แอฟริคานส์ (af)
- │ │ │ └───┬ Tsotsitaal (fly)
- │ │ │ └──── Camtho (cmt)
- │ │ │ └───┬ Tsotsitaal (fly)
- │ │ └──── ลิมเบิร์ก (li)
- │ │ └───┬ ดัตช์เก่า (odt)
- │ ├───┬ แองโกล-ฟรีเซียน (gmw-afr)
- │ │ ├───┬ ฟรีเซียน (gmw-fri)
- │ │ │ └───┬ ฟรีเซียเก่า (ofs)
- │ │ │ ├──── Saterland Frisian (stq)
- │ │ │ ├──── ฟรีเชียตะวันตก (fy)
- │ │ │ └──── ฟรีเซียเหนือ (frr)
- │ │ │ └───┬ ฟรีเซียเก่า (ofs)
- │ │ └───┬ แองกลิก (gmw-ang)
- │ │ └───┬ อังกฤษเก่า (ang)
- │ │ ├──── Kentish Old English (ang-ken)
- │ │ ├───┬ อังกฤษกลาง (enm)
- │ │ │ ├───┬ Irish Anglo-Norman (gmw-ian)
- │ │ │ │ ├──── Fingallian (gmw-fin)
- │ │ │ │ └──── ยอลอ (yol)
- │ │ │ └───┬ อังกฤษใหม่ช่วงต้น (en-ear)
- │ │ │ └───┬ อังกฤษ (en)
- │ │ │ ├──── Afro-Seminole Creole (afs)
- │ │ │ ├──── Angloromani (rme)
- │ │ │ ├──── Antigua and Barbuda Creole English (aig)
- │ │ │ ├───┬ Aukan (djk)
- │ │ │ │ └──── Ndyuka-Trio Pidgin (njt)
- │ │ │ ├───┬ Australian Kriol (rop)
- │ │ │ │ └──── Gurindji Kriol (gjr)
- │ │ │ ├──── Bahamian Creole (bah)
- │ │ │ ├──── Bajan (bjs)
- │ │ │ ├──── Belizean Creole (bzj)
- │ │ │ ├──── Cameroon Pidgin (wes)
- │ │ │ ├──── Chinese Pidgin English (cpi)
- │ │ │ ├──── Grenadian Creole English (gcl)
- │ │ │ ├──── Gullah (gul)
- │ │ │ ├──── Guyanese Creole English (gyn)
- │ │ │ ├──── Islander Creole English (icr)
- │ │ │ ├──── Krio (kri)
- │ │ │ ├──── Kwinti (kww)
- │ │ │ ├──── Liberian Kreyol (lir)
- │ │ │ ├───┬ Maroon Spirit Language (crp-mar)
- │ │ │ │ └──── Kromanti (alv-kro)
- │ │ │ ├──── Ngatik Men's Creole (ngm)
- │ │ │ ├──── Nicaraguan Creole (bzk)
- │ │ │ ├──── Nigerian Pidgin (pcm)
- │ │ │ ├──── Pichinglis (fpe)
- │ │ │ ├──── Pijin (pis)
- │ │ │ ├──── Pitcairn-Norfolk (pih)
- │ │ │ ├──── Polari (pld)
- │ │ │ ├──── Samoan Plantation Pidgin (crp-spp)
- │ │ │ ├──── Saramaccan (srm)
- │ │ │ ├──── Shelta (sth)
- │ │ │ ├──── Solombala English (crp-slb)
- │ │ │ ├──── Tobagonian Creole English (tgh)
- │ │ │ ├──── Torres Strait Creole (tcs)
- │ │ │ ├──── Trinidadian Creole English (trf)
- │ │ │ ├──── Turks and Caicos Creole English (tch)
- │ │ │ ├──── Vincentian Creole English (svc)
- │ │ │ ├──── Virgin Islands Creole (vic)
- │ │ │ ├──── ครีโอลจาเมกา (jam)
- │ │ │ ├──── ทอกพิซิน (tpi)
- │ │ │ ├──── บิสลามา (bi)
- │ │ │ ├───┬ อังกฤษแบบบริเตน (en-GB)
- │ │ │ │ ├──── อังกฤษแบบสกอตแลนด์ (en-GB-SCT)
- │ │ │ │ ├──── อังกฤษแบบเวลส์ (en-GB-WLS)
- │ │ │ │ └──── อังกฤษแบบแมงซ์ (en-IM)
- │ │ │ ├───┬ อังกฤษแบบออสเตรเลีย (en-AU)
- │ │ │ │ └──── Australian Aboriginal English (en-aae)
- │ │ │ ├──── อังกฤษแบบอินเดีย (en-IN)
- │ │ │ ├───┬ อังกฤษแบบอเมริกาเหนือ (en-NNN)
- │ │ │ │ └───┬ อังกฤษแบบอเมริกา (en-US)
- │ │ │ │ ├──── อังกฤษแบบแคนาดา (en-CA)
- │ │ │ │ └──── อังกฤษแบบแคลิฟอร์เนีย (en-US-CA)
- │ │ │ │ └───┬ อังกฤษแบบอเมริกา (en-US)
- │ │ │ ├──── อังกฤษแบบฮ่องกง (en-HK)
- │ │ │ └───┬ อังกฤษแบบไอร์แลนด์ (en-IE)
- │ │ │ └───┬ Ulster English (en-uls)
- │ │ │ └──── อังกฤษแบบไอร์แลนด์เหนือ (en-GB-NIR)
- │ │ │ └───┬ Ulster English (en-uls)
- │ │ │ └───┬ อังกฤษ (en)
- │ │ │ ├───┬ Irish Anglo-Norman (gmw-ian)
- │ │ └───┬ อังกฤษเก่าแบบแองเกิล (ang-ang)
- │ │ ├───┬ อังกฤษเก่าแบบนอร์ธัมเบรีย (ang-nor)
- │ │ │ └───┬ Northern Middle English (enm-nor)
- │ │ │ ├───┬ Early Scots (enm-esc)
- │ │ │ │ └───┬ Middle Scots (gmw-msc)
- │ │ │ │ └───┬ สกอต (sco)
- │ │ │ │ ├──── Insular Scots (sco-ins)
- │ │ │ │ ├──── Traveller Scottish (trl)
- │ │ │ │ ├──── Ulster Scots (sco-uls)
- │ │ │ │ ├──── สกอตเหนือ (sco-nor)
- │ │ │ │ └──── สกอตใต้ (sco-sou)
- │ │ │ │ └───┬ สกอต (sco)
- │ │ │ │ └───┬ Middle Scots (gmw-msc)
- │ │ │ └──── Geordie English (en-geo)
- │ │ │ ├───┬ Early Scots (enm-esc)
- │ │ │ └───┬ Northern Middle English (enm-nor)
- │ │ └──── อังกฤษเก่าแบบเมอร์เซีย (ang-mer)
- │ │ ├───┬ อังกฤษเก่าแบบนอร์ธัมเบรีย (ang-nor)
- │ │ └───┬ อังกฤษเก่า (ang)
- │ │ ├───┬ ฟรีเซียน (gmw-fri)
- │ ├───┬ โลว์เจอร์แมน (gmw-lgm)
- │ │ └───┬ แซกซันเก่า (osx)
- │ │ └───┬ เยอรมันต่ำกลาง (gml)
- │ │ └───┬ เยอรมันต่ำ (nds)
- │ │ ├───┬ Dutch Low Saxon (nds-nl)
- │ │ │ ├──── Achterhoeks (act)
- │ │ │ ├──── Drents (drt)
- │ │ │ ├──── Gronings (gos)
- │ │ │ ├──── Sallands (sdz)
- │ │ │ ├──── Stellingwerfs (stl)
- │ │ │ ├──── Twents (twd)
- │ │ │ └──── Veluws (vel)
- │ │ └───┬ German Low German (nds-de)
- │ │ ├──── East Frisian Low German (frs)
- │ │ ├──── Low Prussian (nds-lpr)
- │ │ ├──── Westphalian (wep)
- │ │ └──── เพลาท์ดิทช์ (pdt)
- │ │ ├───┬ Dutch Low Saxon (nds-nl)
- │ │ └───┬ เยอรมันต่ำ (nds)
- │ │ └───┬ เยอรมันต่ำกลาง (gml)
- │ │ └───┬ แซกซันเก่า (osx)
- │ └───┬ ไฮเจอร์แมน (gmw-hgm)
- │ └───┬ เยอรมันสูงเก่า (goh)
- │ ├──── Lombardic (lng)
- │ └───┬ เยอรมันสูงกลาง (gmh)
- │ ├───┬ Central Franconian (gmw-cfr)
- │ │ ├──── Kölsch (ksh)
- │ │ ├──── Transylvanian Saxon (gmw-tsx)
- │ │ ├──── ลักเซมเบิร์ก (lb)
- │ │ └──── ฮุนสริก (hrx)
- │ ├───┬ East Central German (gmw-ecg)
- │ │ ├──── Silesian East Central German (sli)
- │ │ └──── Upper Saxon German (sxu)
- │ ├──── East Franconian (vmf)
- │ ├───┬ Rhine Franconian (gmw-rfr)
- │ │ ├──── เยอรมันแบบปาเลสไตน์ (pfl)
- │ │ ├──── เยอรมันแบบว็อลกา (gmw-vog)
- │ │ └──── เยอรมันแบบเพนซิลเวเนีย (pdc)
- │ ├──── Yenish (yec)
- │ ├──── Zipser German (gmw-zps)
- │ ├───┬ บาวาเรีย (bar)
- │ │ ├──── Cimbrian (cim)
- │ │ ├──── Gottscheerish (gmw-gts)
- │ │ ├──── Hutterisch (geh)
- │ │ └──── โมเชโน (mhn)
- │ ├──── ยิดดิช (yi)
- │ ├──── วีลามอวิตแซ (wym)
- │ ├───┬ เยอรมัน (de)
- │ │ ├──── Baltic German (de-bal)
- │ │ ├──── อุนเซอร์ด็อยทช์ (uln)
- │ │ ├──── เยอรมันแบบสวิตเซอร์แลนด์ (de-CH)
- │ │ └───┬ เยอรมันแบบออสเตรีย (de-AT)
- │ │ └──── เยอรมันแบบเวียนนา (de-AT-vie)
- │ └───┬ เยอรมันแบบแอเลอแมนนี (gsw)
- │ ├──── Colonia Tovar German (gct)
- │ ├──── High Alemannic German (gsw-hig)
- │ ├───┬ Highest Alemannic German (gsw-hst)
- │ │ └──── Walser German (wae)
- │ ├───┬ Low Alemannic German (gsw-low)
- │ │ └──── Alsatian Alemannic German (gsw-FR-als)
- │ └───┬ Swabian (swg)
- │ └──── Sathmar Swabian (gmw-stm)
- │ ├───┬ Central Franconian (gmw-cfr)
- │ └───┬ เยอรมันสูงเก่า (goh)
- │ └───┬ เจอร์แมนิกตะวันตกดั้งเดิม (gmw-pro)
- ├───┬ เจอร์แมนิกตะวันออก (gme)
- │ ├──── Burgundian (gme-bur)
- │ ├──── Vandalic (xvn)
- │ ├──── กอท (got)
- │ └──── กอทแบบไครเมีย (gme-cgo)
- └───┬ เจอร์แมนิกเหนือ (gmq)
- └───┬ นอร์สดั้งเดิม (gmq-pro)
- └───┬ นอร์สเก่า (non)
- ├───┬ Old East Norse (non-oen)
- │ └───┬ สแกนดิเนเวียนตะวันออก (gmq-eas)
- │ ├──── Elfdalian (ovd)
- │ ├──── Jamtish (gmq-jmk)
- │ ├──── Scanian (gmq-scy)
- │ ├───┬ สวีเดนเก่า (gmq-osw)
- │ │ └───┬ Late Old Swedish (gmq-osw-lat)
- │ │ └───┬ สวีเดน (sv)
- │ │ └──── Tavringer Romani (rmu)
- │ │ └───┬ สวีเดน (sv)
- │ │ └───┬ Late Old Swedish (gmq-osw-lat)
- │ └───┬ เดนมาร์กเก่า (gmq-oda)
- │ └───┬ เดนมาร์ก (da)
- │ ├──── Jutish (jut)
- │ ├──── Traveller Danish (rmd)
- │ └──── นอร์เวย์แบบบุ๊กมอล (nb)
- │ └───┬ เดนมาร์ก (da)
- │ └───┬ สแกนดิเนเวียนตะวันออก (gmq-eas)
- ├───┬ Old Gutnish (gmq-ogt)
- │ └──── Gutnish (gmq-gut)
- └───┬ Old West Norse (non-own)
- ├──── Greenlandic Norse (non-grn)
- └───┬ สแกนดิเนเวียนตะวันตก (gmq-wes)
- ├───┬ Insular Scandinavian (gmq-ins)
- │ ├──── Norn (nrn)
- │ ├──── แฟโร (fo)
- │ └──── ไอซ์แลนด์ (is)
- └───┬ นอร์เวย์กลาง (gmq-mno)
- ├───┬ นอร์เวย์ (no)
- │ └──── Traveller Norwegian (rmg)
- ├───┬ นอร์เวย์แบบนือนอสก์ (nn)
- │ └──── Russenorsk (crp-rsn)
- └──── นอร์เวย์แบบบุ๊กมอล (nb)
- ├───┬ นอร์เวย์ (no)
- ├───┬ Insular Scandinavian (gmq-ins)
- ├───┬ Old East Norse (non-oen)
- └───┬ นอร์สเก่า (non)
- └───┬ นอร์สดั้งเดิม (gmq-pro)
- ├───┬ เจอร์แมนิกตะวันตก (gmw)
Trees
แก้ไขThe template include limit prevents this page from showing all of Wiktionary's current language trees. Above is a sample language tree. When making changes to the Module:languages data, you may need to refresh
this page to see an update.
See also
แก้ไข--[=[
Authors: [[User:kc_kennylau]], [[User:JohnC5]], [[User:Erutuon]], [[User:Suzukaze-c]], [[User:Theknightwho]]
--]=]
local export = {}
local regular_languages = require("Module:languages/code to canonical name")
local etymology_languages = require("Module:etymology languages/code to canonical name")
local families = require("Module:families/code to canonical name")
function export.find_subtree(t, code)
for _, val in ipairs(t) do
if val.name == code then -- "name" is really code
return { val }
else
local result = export.find_subtree(val, code)
if result then
return result
end
end
end
end
local family_icon = "F"
local etymology_language_icon = "E"
local proto_language_icon = family_icon
local family_with_proto_language_icon = family_icon
local function format_node(code, is_protolanguage_or_has_protolanguage)
local canonical_name, category_name, class, icon, tooltip
if regular_languages[code] then
canonical_name = regular_languages[code]
--category_name = canonical_name .. ' language'
category_name = "ภาษา" .. canonical_name
class = "familytree-lang"
if is_protolanguage_or_has_protolanguage then
class = class .. ' familytree-protolang'
icon = proto_language_icon
end
elseif etymology_languages[code] then
canonical_name = etymology_languages[code]
category_name = "ภาษา" .. canonical_name
class = "familytree-etymlang"
icon = etymology_language_icon
tooltip = "ภาษาสำหรับอ้างอิง"
elseif families[code] then
canonical_name = families[code]
--category_name = canonical_name .. " languages"
category_name = "กลุ่มภาษา" .. canonical_name
class = "familytree-family"
if is_protolanguage_or_has_protolanguage then
class = class .. ' familytree-hasprotolang'
icon = family_with_proto_language_icon
else
icon = family_icon
end
tooltip = "กลุ่มภาษา"
end
return '<span class="' .. class .. '" '
.. (tooltip and 'title="' .. tooltip .. '"' or '') .. '>'
.. '[[:Category:' .. (category_name or canonical_name) .. '|'
.. canonical_name
.. ' <span class="familytree-code">(' .. code .. ')</span>]]'
.. (icon and ' <span class="familytree-icon">' .. icon .. '</span>' or '')
.. '</span>'
end
-- If neither options.show_all_families or options.show_etymology_languages is
-- falsy, then this function does nothing.
local function filter_nested_data(nested_data, options, protolanguage_of, is_protolanguage)
if not nested_data then -- ???
return nil
else
local name = nested_data.name
local first_child = nested_data[1]
-- This indicates that new_nested_data below should only be returned
-- if it contains non-etymology languages.
local check_for_non_etymology_children = false
-- If `show_all_families` is false and this is a family and its only
-- child is its proto-language, then replace the family with the
-- proto-language.
if options.hide_families_with_protolanguages and name and families[name]
and first_child and not nested_data[2]
and protolanguage_of[name] == first_child.name then
is_protolanguage[first_child.name] = true
return filter_nested_data(first_child, options, protolanguage_of, is_protolanguage)
elseif options.hide_etymology_languages
and etymology_languages[name] then
if nested_data[1] then
check_for_non_etymology_children = true
else
return nil
end
end
local new_nested_data = { name = name }
local i = 0
for _, subtable in ipairs(nested_data) do
subtable = filter_nested_data(subtable, options, protolanguage_of, is_protolanguage)
if subtable then
i = i + 1
new_nested_data[i] = subtable
end
end
if not check_for_non_etymology_children or new_nested_data[1] then
return new_nested_data
end
end
end
local function make_node(code, is_protolanguage, protolanguage_of)
return '</span> ' .. format_node(code,
is_protolanguage[code] or protolanguage_of[code] ~= nil)
end
local function only_child_is_protolanguage(tree, options, protolanguage_of)
return (options.family_under_protolanguage
or options.protolanguage_under_family)
and tree[1] and protolanguage_of[tree.name] == tree[1].name
end
export.are_all_children_etymology_languages = require "Module:fun".memoize(function (nested_data)
if not nested_data[1] then
return nil
end
for _, child in ipairs(nested_data) do
if not etymology_languages[child.name]
or export.are_all_children_etymology_languages(child) == false then
return false
end
end
return true
end)
local customcollapsible_number = 0
local customcollapsible_prefix = "familytree"
local function get_customcollapsible_id()
customcollapsible_number = customcollapsible_number + 1
return customcollapsible_prefix .. customcollapsible_number
end
local no_break_space = "\194\160"
local level_separator = (no_break_space):rep(3)
local expandtext, collapsetext = "[+]─", "[-]┬"
local function make_tree(data, is_protolanguage, protolanguage_of, options, prefix)
local result = {}
local function ins(val)
table.insert(result, val)
end
-- This tag is closed in the node generated by make_node.
prefix = prefix or '<span class="familytree-linedrawing">'
local branch = "├"
local next_level = prefix .. "│" .. level_separator
local length = #data
for i, val in ipairs(data) do
if i == length then
branch = "└"
next_level = prefix .. level_separator .. no_break_space
end
local code = val.name
local language_or_family_node =
make_node(code, is_protolanguage, protolanguage_of)
if not val[1] then
ins('<li>' .. prefix .. branch .. options.sterile_branch_text
.. language_or_family_node .. '</li>')
else
local customcollapsible_id = get_customcollapsible_id()
ins('<li>' .. prefix .. branch
.. '<span class="familytree-toggle mw-customtoggle-'
.. customcollapsible_id .. '">───┬</span>')
-- name me!
local flag = (options.family_under_protolanguage
or options.protolanguage_under_family)
and only_child_is_protolanguage(val, options, protolanguage_of)
local top_node
if flag then
code = val[1].name
val = val[1]
top_node = make_node(code, is_protolanguage, protolanguage_of)
if options.protolanguage_under_family then
top_node, language_or_family_node =
language_or_family_node, top_node
end
end
local all_children_are_etymology_languages =
export.are_all_children_etymology_languages(val)
local collapsible_ul = '<ul class="mw-collapsible'
.. (all_children_are_etymology_languages
and ' familytree-only-etym-children'
or '') .. '" '
.. 'id="mw-customcollapsible-' .. customcollapsible_id
.. '" data-expandtext="' .. expandtext
.. '" data-collapsetext="' .. collapsetext .. '">'
if flag then
ins(top_node
.. collapsible_ul .. '<li>' .. prefix
.. (i == length and no_break_space or "│")
.. level_separator .. "│")
end
ins(language_or_family_node)
if not flag then
ins(collapsible_ul)
end
-- Can't get default collapsibility script to apply the data-expandtext
-- and data-collapsetext attribute values to the custom toggle,
-- so have to have a custom script do it.
ins(make_tree(val, is_protolanguage, protolanguage_of, options, next_level))
ins('</ul></li>')
end
end
return table.concat(result)
end
local function get_number_parameter_in_range(args, arg, low, high)
local val = args[arg]
if val == "" or val == nil then
val = nil
else
val = tonumber(val)
if not (type(val) == "number"
and 0 <= val and val <= 6) then
error("Expected nothing or number between " .. low .. " and "
.. high .. " in parameter |" .. arg .. "=.")
end
end
return val
end
function export.show(frame)
local args = frame.args
local descendants_of = args[1]
local to_boolean = require("Module:yesno")
-- Determines whether families that have proto-languages will be shown.
local show_all_families = to_boolean(args[2] or args.fam)
-- Determines whether all etymology languages will be shown.
local show_etymology_languages = to_boolean(args[3] or args.etym)
-- help! parameter name too long!
local sterile_branch_length = get_number_parameter_in_range(args, "sterile_branch_length", 0, 6)
-- Determines whether (if all families are shown) a family will be shown
-- on a line directly under and at the same level as its proto-language,
-- or the proto-language on a line directly under and at the same level as
-- its family.
local family_under_protolanguage = to_boolean(args.famunderproto)
local protolanguage_under_family = to_boolean(args.protounderfam)
if family_under_protolanguage and protolanguage_under_family then
error("Kindly choose between proto-language under family and family under proto-language.")
end
return export.print_children(descendants_of, {
hide_families_with_protolanguages = not show_all_families,
hide_etymology_languages = not show_etymology_languages,
family_under_protolanguage = family_under_protolanguage,
protolanguage_under_family = protolanguage_under_family,
sterile_branch_length = sterile_branch_length,
collapsed = require("Module:yesno")(args.collapsed)
})
end
function export.print_children(descendants_of, options)
local m_languages = require("Module:languages")
local m_table = require("Module:table")
local make_auto_subtabler = require("Module:auto-subtable")
descendants_of = m_languages.getByCode(descendants_of, nil, true, true, true)
local names = {}
local protolanguage_of = {}
local children = make_auto_subtabler{}
local descendants = descendants_of:getDescendantCodes()
table.insert(descendants, descendants_of:getCode())
if descendants_of:hasType("family") then
protolanguage_of[descendants_of:getCode()] = descendants_of:getProtoLanguageCode()
end
local memoized = {}
local get = function(code, func, ...)
local ret = memoized[code] or func(...)
if code then
memoized[code] = ret
end
return ret
end
for _, descendant_code in ipairs(descendants) do
-- Inner "repeat until true" loop allows break to work like continue, as it will always only run once.
repeat
local descendant = get(descendant_code, m_languages.getByCode, descendant_code, nil, true, true, true)
names[descendant_code] = descendant:getCanonicalName():gsub("Proto%-", "")
if descendant:hasType("language") then
local ancestors = m_table.shallowcopy(descendant:getAncestorCodes())
local parent_code = descendant:getParentCode()
if parent_code and descendant:hasType("etymology-only") then
local parent = get(parent_code, descendant.getParent, descendant)
if m_table.deepEquals(parent:getAncestorCodes(), ancestors) and
descendant:getFamilyCode() == parent:getFamilyCode() then
table.insert(children[parent:getCode()], descendant_code)
break
end
end
if #ancestors > 0 then
for _, ancestor in ipairs(ancestors) do
table.insert(children[ancestor], descendant_code)
end
break
end
else
local protolang = descendant:getProtoLanguageCode()
protolanguage_of[descendant_code] = protolang
if protolang and descendant:hasAncestor(protolang) then
table.insert(children[protolang], descendant_code)
break
end
end
local family_code = descendant:getFamilyCode()
if family_code then
local family = get(family_code, descendant.getFamily, descendant)
local protolang = get(family:getProtoLanguageCode(), family.getProtoLanguage, family)
if not protolanguage_of[family] then
protolanguage_of[family] = protolang and protolang:getCode()
end
if protolang and protolang:inFamily(family) and protolang:getCode() ~= descendant_code then
table.insert(children[protolang:getCode()], descendant_code)
else
table.insert(children[family:getCode()], descendant_code)
end
end
until true
end
-- No more auto subtabling needed.
children = children:un_auto_subtable()
-- Copy to new table, to filter out unwanted ancestors from descendants with multiple ancestors, where some are not descendants of the target language.
local parent_to_children_map = {}
for _, code in ipairs(descendants) do
parent_to_children_map[code] = children[code]
end
local function make_nested(data, children)
local make_nil = {}
for key, val in pairs(data) do
if type(key) == "number" then
if children[val] then
data[val] = make_nested(children[val], children)
table.insert(make_nil, key)
end
else
data[key] = make_nested(val, children)
end
end
if make_nil[2] then -- Make sure larger keys are removed first.
table.sort(make_nil, function (a, b) return a > b end)
end
for _, key in ipairs(make_nil) do
table.remove(data, key)
end
return data
end
local nested = make_nested(parent_to_children_map, parent_to_children_map)
local function deep_sort(current)
local result = {}
local is_table = {}
for key, val in pairs(current) do
if type(key) == "number" then
table.insert(result, val)
else
is_table[key] = true
table.insert(result, key)
end
end
table.sort(result, function(code1, code2)
return names[code1] < names[code2]
end)
for i = 1, #result do
if is_table[result[i]] then
local name = result[i]
result[i] = deep_sort(current[result[i]])
result[i].name = name
else
result[i] = { name = result[i] }
end
end
return result
end
nested = deep_sort(nested)
data = { nested = nested, protolanguage_of = protolanguage_of }
local nested_data, protolanguage_of = data.nested, data.protolanguage_of
nested_data = export.find_subtree(nested_data, descendants_of:getCode())
-- Return nil instead of a tree with only the root node.
if options.must_have_descendants and (#nested_data == 0 or nested_data[1] and #nested_data[1] == 0) then
return nil
end
local is_protolanguage = {}
if options.hide_families_with_protolanguages or options.hide_etymology_languages then
nested_data = filter_nested_data(nested_data, {
hide_families_with_protolanguages = options.hide_families_with_protolanguages,
hide_etymology_languages = options.hide_etymology_languages,
}, protolanguage_of, is_protolanguage)
end
if not nested_data or not next(nested_data) then
return nil
end
local result = {'<div class="familytree"><ul>'}
local function ins(val)
table.insert(result, val)
end
local tree_options = {
sterile_branch_text = '<span class="familytree-branch">'
.. ("─"):rep(options.sterile_branch_length or 4)
.. '</span>',
family_under_protolanguage = options.family_under_protolanguage,
protolanguage_under_family = options.protolanguage_under_family,
}
local collapsetext, expandtext = 'ยุบ', 'ขยาย'
for i, subtable in ipairs(nested_data) do
-- top language name
ins('<li>')
-- name me!
local flag = (options.family_under_protolanguage
or options.protolanguage_under_family)
and only_child_is_protolanguage(subtable, options, protolanguage_of)
local top_node = format_node(subtable.name)
local next_node
if flag then
subtable = subtable[1]
next_node = format_node(subtable.name)
if options.family_under_protolanguage then
top_node, next_node = next_node, top_node
end
end
ins(top_node)
-- top toggle
local customcollapsible_id = get_customcollapsible_id()
ins('<span class="familytree-toptoggle mw-customtoggle-'
.. customcollapsible_id .. '" style="display: none;">')
ins(options.collapsed and expandtext or collapsetext)
ins('</span>')
if flag then
ins('<li>')
ins(next_node)
end
-- tree
ins('<ul class="mw-collapsible')
if options.collapsed then
ins(' mw-collapsed')
end
ins('" id="mw-customcollapsible-' .. customcollapsible_id)
ins('" data-expandtext="' .. expandtext)
ins('" data-collapsetext="' .. collapsetext .. '">')
ins(make_tree(subtable, is_protolanguage, protolanguage_of, tree_options, nil))
if flag then
ins('</li>')
end
ins('</ul></li>')
end
ins('</ul></div>')
ins(require("Module:TemplateStyles")("Module:family tree/style.css"))
return table.concat(result)
end
return export