Wiktionary
bjnwiktionary
https://bjn.wiktionary.org/wiki/Laman_Tatambaian
MediaWiki 1.47.0-wmf.9
case-sensitive
Media
Istimiwa
Pamandiran
Pamakai
Pamandiran Pamakai
Wikikamus
Pamandiran Wikikamus
Barakas
Pamandiran Barakas
MediaWiki
Pamandiran MediaWiki
Citakan
Pamandiran Citakan
Patulung
Pamandiran Patulung
Tumbung
Pamandiran Tumbung
TimedText
TimedText talk
Modul
Pembicaraan Modul
Acara
Pembicaraan Acara
Modul:languages
828
2497
26493
23969
2026-04-10T18:45:19Z
id>Swarabakti
0
26493
Scribunto
text/plain
--[==[ intro:
This module implements fetching of language-specific information and processing text in a given language.
===Types of languages===
There are two types of languages: full languages and etymology-only languages. The essential difference is that only
full languages appear in L2 headings in vocabulary entries, and hence categories like [[:Category:French nouns]] exist
only for full languages. Etymology-only languages have either a full language or another etymology-only language as
their parent (in the parent-child inheritance sense), and for etymology-only languages with another etymology-only
language as their parent, a full language can always be derived by following the parent links upwards. For example,
"Canadian French", code `fr-CA`, is an etymology-only language whose parent is the full language "French", code `fr`.
An example of an etymology-only language with another etymology-only parent is "Northumbrian Old English", code
`ang-nor`, which has "Anglian Old English", code `ang-ang` as its parent; this is an etymology-only language whose
parent is "Old English", code `ang`, which is a full language. (This is because Northumbrian Old English is considered
a variety of Anglian Old English.) Sometimes the parent is the "Undetermined" language, code `und`; this is the case,
for example, for "substrate" languages such as "Pre-Greek", code `qsb-grc`, and "the BMAC substrate", code `qsb-bma`.
It is important to distinguish language ''parents'' from language ''ancestors''. The parent-child relationship is one
of containment, i.e. if X is a child of Y, X is considered a variety of Y. On the other hand, the ancestor-descendant
relationship is one of descent in time. For example, "Classical Latin", code `la-cla`, and "Late Latin", code `la-lat`,
are both etymology-only languages with "Latin", code `la`, as their parents, because both of the former are varieties
of Latin. However, Late Latin does *NOT* have Classical Latin as its parent because Late Latin is *not* a variety of
Classical Latin; rather, it is a descendant. There is in fact a separate `ancestors` field that is used to express the
ancestor-descendant relationship, and Late Latin's ancestor is given as Classical Latin. It is also important to note
that sometimes an etymology-only language is actually the conceptual ancestor of its parent language. This happens,
for example, with "Old Italian" (code `roa-oit`), which is an etymology-only variant of full language "Italian" (code
`it`), and with "Old Latin" (code `itc-ola`), which is an etymology-only variant of Latin. In both cases, the full
language has the etymology-only variant listed as an ancestor. This allows a Latin term to inherit from Old Latin
using the {{tl|inh}} template (where in this template, "inheritance" refers to ancestral inheritance, i.e. inheritance
in time, rather than in the parent-child sense); likewise for Italian and Old Italian.
Full languages come in three subtypes:
* {regular}: This indicates a full language that is attested according to [[WT:CFI]] and therefore permitted in the
main namespace. There may also be reconstructed terms for the language, which are placed in the
{Reconstruction} namespace and must be prefixed with * to indicate a reconstruction. Most full languages
are natural (not constructed) languages, but a few constructed languages (e.g. Esperanto and Volapük,
among others) are also allowed in the mainspace and considered regular languages.
* {reconstructed}: This language is not attested according to [[WT:CFI]], and therefore is allowed only in the
{Reconstruction} namespace. All terms in this language are reconstructed, and must be prefixed with
*. Languages such as Proto-Indo-European and Proto-Germanic are in this category.
* {appendix-constructed}: This language is attested but does not meet the additional requirements set out for
constructed languages ([[WT:CFI#Constructed languages]]). Its entries must therefore be in
the Appendix namespace, but they are not reconstructed and therefore should not have *
prefixed in links. Most constructed languages are of this subtype.
Both full languages and etymology-only languages have a {Language} object associated with them, which is fetched using
the {getByCode} function in [[Module:languages]] to convert a language code to a {Language} object. Depending on the
options supplied to this function, etymology-only languages may or may not be accepted, and family codes may be
accepted (returning a {Family} object as described in [[Module:families]]). There are also separate {getByCanonicalName}
functions in [[Module:languages]] and [[Module:etymology languages]] to convert a language's canonical name to a
{Language} object (depending on whether the canonical name refers to a full or etymology-only language).
===Textual representations===
Textual strings belonging to a given language come in several different ''text variants'':
# The ''input text'' is what the user supplies in wikitext, in the parameters to {{tl|m}}, {{tl|l}}, {{tl|ux}},
{{tl|t}}, {{tl|lang}} and the like.
# The ''corrected input text'' is the input text with some corrections and/or normalizations applied, such as
bad-character replacements for certain languages, like replacing `l` or `1` to [[palochka]] in some languages written
in Cyrillic. (FIXME: This currently goes under the name ''display text'' but that will be repurposed below. Also,
[[User:Surjection]] suggests renaming this to ''normalized input text'', but "normalized" is used in a different sense
in [[Module:usex]].)
# The ''display text'' is the text in the form as it will be displayed to the user. This is what appears in headwords,
in usexes, in displayed internal links, etc. This can include accent marks that are removed to form the stripped
display text (see below), as well as embedded bracketed links that are variously processed further. The display text
is generated from the corrected input text by applying language-specific transformations; for most languages, there
will be no such transformations. The general reason for having a difference between input and display text is to allow
for extra information in the input text that is not displayed to the user but is sent to the transliteration module.
Note that having different display and input text is only supported currently through special-casing but will be
generalized. Examples of transformations are: (1) Removing the {{cd|^}} that is used in certain East Asian (and
possibly other unicameral) languages to indicate capitalization of the transliteration (which is currently
special-cased); (2) for Korean, removing or otherwise processing hyphens (which is currently special-cased); (3) for
Arabic, removing a ''sukūn'' diacritic placed over a ''tāʔ marbūṭa'' (like this: ةْ) to indicate that the
''tāʔ marbūṭa'' is pronounced and transliterated as /t/ instead of being silent [NOTE, NOT IMPLEMENTED YET]; (4) for
Thai and Khmer, converting space-separated words to bracketed words and resolving respelling substitutions such as
`[กรีน/กฺรีน]`, which indicate how to transliterate given words [NOTE, NOT IMPLEMENTED YET except in language-specific
templates like {{tl|th-usex}}].
## The ''right-resolved display text'' is the result of removing brackets around one-part embedded links and resolving
two-part embedded links into their right-hand components (i.e. converting two-part links into the displayed form).
The process of right-resolution is what happens when you call {{cd|remove_links()}} in [[Module:links]] on some text.
When applied to the display text, it produces exactly what the user sees, without any link markup.
# The ''stripped display text'' is the result of applying diacritic-stripping to the display text.
## The ''left-resolved stripped display text'' [NEED BETTER NAME] is the result of applying left-resolution to the
stripped display text, i.e. similar to right-resolution but resolving two-part embedded links into their left-hand
components (i.e. the linked-to page). If the display text refers to a single page, the resulting of applying
diacritic stripping and left-resolution produces the ''logical pagename''.
# The ''physical pagename text'' is the result of converting the stripped display text into physical page links. If the
stripped display text contains embedded links, the left side of those links is converted into physical page links;
otherwise, the entire text is considered a pagename and converted in the same fashion. The conversion does three
things: (1) converts characters not allowed in pagenames into their "unsupported title" representation, e.g.
{{cd|Unsupported titles/`gt`}} in place of the logical name {{cd|>}}; (2) handles certain special-cased
unsupported-title logical pagenames, such as {{cd|Unsupported titles/Space}} in place of {{cd|[space]}} and
{{cd|Unsupported titles/Ancient Greek dish}} in place of a very long Greek name for a gourmet dish as found in
Aristophanes; (3) converts "mammoth" pagenames such as [[a]] into their appropriate split component, e.g.
[[a/languages A to L]].
# The ''source translit text'' is the text as supplied to the language-specific {{cd|transliterate()}} method. The form
of the source translit text may need to be language-specific, e.g Thai and Khmer will need the corrected input text,
whereas other languages may need to work off the display text. [FIXME: It's still unclear to me how embedded bracketed
links are handled in the existing code.] In general, embedded links need to be right-resolved (see above), but when
this happens is unclear to me [FIXME]. Some languages have a chop-up-and-paste-together scheme that sends parts of the
text through the transliterate mechanism, and for others (those listed with "cont" in {{cd|substitution}} in
[[Module:languages/data]]) they receive the full input text, but preprocessed in certain ways. (The wisdom of this is
still unclear to me.)
# The ''transliterated text'' (or ''transliteration'') is the result of transliterating the source translit text. Unlike
for all the other text variants except the transcribed text, it is always in the Latin script.
# The ''transcribed text'' (or ''transcription'') is the result of transcribing the source translit text, where
"transcription" here means a close approximation to the phonetic form of the language in languages (e.g. Akkadian,
Sumerian, Ancient Egyptian, maybe Tibetan) that have a wide difference between the written letters and spoken form.
Unlike for all the other text variants other than the transliterated text, it is always in the Latin script.
Currently, the transcribed text is always supplied manually be the user; there is no such thing as a
{{cd|transcribe()}} method on language objects.
# The ''sort key'' is the text used in sort keys for determining the placing of pages in categories they belong to. The
sort key is generated from the pagename or a specified ''sort base'' by lowercasing, doing language-specific
transformations and then uppercasing the result. If the sort base is supplied and is generated from input text, it
needs to be converted to display text, have embedded links removed through right-resolution and have
diacritic-stripping applied.
# There are other text variants that occur in usexes (specifically, there are normalized variants of several of the
above text variants), but we can skip them for now.
The following methods exist on {Language} objects to convert between different text variants:
# {correctInputText} (currently called {makeDisplayText}): This converts input text to corrected input text.
# {stripDiacritics}: This converts to stripped display text. [FIXME: This needs some rethinking. In particular,
{stripDiacritics} is sometimes called on input text, corrected input text or display text (in various paths inside of
[[Module:links]], and, in the case of input text, usually from other modules). We need to make sure we don't try to
convert input text to display text twice, but at the same time we need to support calling it directly on input text
since so many modules do this. This means we need to add a parameter indicating whether the passed-in text is input,
corrected input, or display text; if the former two, we call {correctInputText} ourselves.]
# {logicalToPhysical}: This converts logical pagenames to physical pagenames.
# {transliterate}: This appears to convert input text with embedded brackets removed into a transliteration.
[FIXME: This needs some rethinking. In particular, it calls {processDisplayText} on its input, which won't work
for Thai and Khmer, so we may need language-specific flags indicating whether to pass the input text directly to the
language transliterate method. In addition, I'm not sure how embedded links are handled in the existing translit code;
a lot of callers remove the links themselves before calling {transliterate()}, which I assume is wrong.]
# {makeSortKey}: This converts display text (?) to a sort key. [FIXME: Clarify this.]
]==]
local export = {}
local debug_track_module = "Module:debug/track"
local etymology_languages_data_module = "Module:etymology languages/data"
local families_module = "Module:families"
local headword_page_module = "Module:headword/page"
local json_module = "Module:JSON"
local language_like_module = "Module:language-like"
local languages_data_module = "Module:languages/data"
local languages_data_patterns_module = "Module:languages/data/patterns"
local links_data_module = "Module:links/data"
local load_module = "Module:load"
local scripts_module = "Module:scripts"
local scripts_data_module = "Module:scripts/data"
local string_encode_entities_module = "Module:string/encode entities"
local string_pattern_escape_module = "Module:string/patternEscape"
local string_replacement_escape_module = "Module:string/replacementEscape"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local wikimedia_languages_module = "Module:wikimedia languages"
local mw = mw
local string = string
local table = table
local char = string.char
local concat = table.concat
local find = string.find
local floor = math.floor
local get_by_code -- Defined below.
local get_data_module_name -- Defined below.
local get_extra_data_module_name -- Defined below.
local getmetatable = getmetatable
local gmatch = string.gmatch
local gsub = string.gsub
local insert = table.insert
local ipairs = ipairs
local is_known_language_tag = mw.language.isKnownLanguageTag
local make_object -- Defined below.
local match = string.match
local next = next
local pairs = pairs
local remove = table.remove
local require = require
local select = select
local setmetatable = setmetatable
local sub = string.sub
local type = type
local unstrip = mw.text.unstrip
-- Loaded as needed by findBestScript.
local Hans_chars
local Hant_chars
local function check_object(...)
check_object = require(utilities_module).check_object
return check_object(...)
end
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function decode_uri(...)
decode_uri = require(string_utilities_module).decode_uri
return decode_uri(...)
end
local function deep_copy(...)
deep_copy = require(table_module).deepCopy
return deep_copy(...)
end
local function encode_entities(...)
encode_entities = require(string_encode_entities_module)
return encode_entities(...)
end
local function get_L2_sort_key(...)
get_L2_sort_key = require(headword_page_module).get_L2_sort_key
return get_L2_sort_key(...)
end
local function get_script(...)
get_script = require(scripts_module).getByCode
return get_script(...)
end
local function find_best_script_without_lang(...)
find_best_script_without_lang = require(scripts_module).findBestScriptWithoutLang
return find_best_script_without_lang(...)
end
local function get_family(...)
get_family = require(families_module).getByCode
return get_family(...)
end
local function get_plaintext(...)
get_plaintext = require(utilities_module).get_plaintext
return get_plaintext(...)
end
local function get_wikimedia_lang(...)
get_wikimedia_lang = require(wikimedia_languages_module).getByCode
return get_wikimedia_lang(...)
end
local function keys_to_list(...)
keys_to_list = require(table_module).keysToList
return keys_to_list(...)
end
local function list_to_set(...)
list_to_set = require(table_module).listToSet
return list_to_set(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function make_family_object(...)
make_family_object = require(families_module).makeObject
return make_family_object(...)
end
local function pattern_escape(...)
pattern_escape = require(string_pattern_escape_module)
return pattern_escape(...)
end
local function replacement_escape(...)
replacement_escape = require(string_replacement_escape_module)
return replacement_escape(...)
end
local function safe_require(...)
safe_require = require(load_module).safe_require
return safe_require(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function to_json(...)
to_json = require(json_module).toJSON
return to_json(...)
end
local function u(...)
u = require(string_utilities_module).char
return u(...)
end
local function ugsub(...)
ugsub = require(string_utilities_module).gsub
return ugsub(...)
end
local function ulen(...)
ulen = require(string_utilities_module).len
return ulen(...)
end
local function ulower(...)
ulower = require(string_utilities_module).lower
return ulower(...)
end
local function umatch(...)
umatch = require(string_utilities_module).match
return umatch(...)
end
local function uupper(...)
uupper = require(string_utilities_module).upper
return uupper(...)
end
local function track(page)
debug_track("languages/" .. page)
return true
end
local function normalize_code(code)
return load_data(languages_data_module).aliases[code] or code
end
local function check_inputs(self, check, default, ...)
local n = select("#", ...)
if n == 0 then
return false
end
local ret = check(self, (...))
if ret ~= nil then
return ret
elseif n > 1 then
local inputs = {...}
for i = 2, n do
ret = check(self, inputs[i])
if ret ~= nil then
return ret
end
end
end
return default
end
local function make_link(self, target, display)
local prefix, main
if self:getFamilyCode() == "qfa-sub" then
prefix, main = display:match("^(the )(.*)")
if not prefix then
prefix, main = display:match("^(a )(.*)")
end
end
return (prefix or "") .. "[[" .. target .. "|" .. (main or display) .. "]]"
end
-- Convert risky characters to HTML entities, which minimizes interference once returned (e.g. for "sms:a", "<!-- -->" etc.).
local function escape_risky_characters(text)
-- Spacing characters in isolation generally need to be escaped in order to be properly processed by the MediaWiki software.
if umatch(text, "^%s*$") then
return encode_entities(text, text)
end
return encode_entities(text, "!#%&*+/:;<=>?@[\\]_{|}")
end
-- Temporarily convert various formatting characters to PUA to prevent them from being disrupted by the substitution process.
local function doTempSubstitutions(text, subbedChars, keepCarets, noTrim)
-- Clone so that we don't insert any extra patterns into the table in package.loaded. For some reason, using require seems to keep memory use down; probably because the table is always cloned.
local patterns = shallow_copy(require(languages_data_patterns_module))
if keepCarets then
insert(patterns, "((\\+)%^)")
insert(patterns, "((%^))")
end
-- Ensure any whitespace at the beginning and end is temp substituted, to prevent it from being accidentally trimmed. We only want to trim any final spaces added during the substitution process (e.g. by a module), which means we only do this during the first round of temp substitutions.
if not noTrim then
insert(patterns, "^([\128-\191\244]*(%s+))")
insert(patterns, "((%s+)[\128-\191\244]*)$")
end
-- Pre-substitution, of "[[" and "]]", which makes pattern matching more accurate.
text = gsub(text, "%f[%[]%[%[", "\1"):gsub("%f[%]]%]%]", "\2")
local i = #subbedChars
for _, pattern in ipairs(patterns) do
-- Patterns ending in \0 stand are for things like "[[" or "]]"), so the inserted PUA are treated as breaks between terms by modules that scrape info from pages.
local term_divider
pattern = gsub(pattern, "%z$", function(divider)
term_divider = divider == "\0"
return ""
end)
text = gsub(text, pattern, function(...)
local m = {...}
local m1New = m[1]
for k = 2, #m do
local n = i + k - 1
subbedChars[n] = m[k]
local byte2 = floor(n / 4096) % 64 + (term_divider and 128 or 136)
local byte3 = floor(n / 64) % 64 + 128
local byte4 = n % 64 + 128
m1New = gsub(m1New, pattern_escape(m[k]), "\244" .. char(byte2) .. char(byte3) .. char(byte4), 1)
end
i = i + #m - 1
return m1New
end)
end
text = gsub(text, "\1", "%[%["):gsub("\2", "%]%]")
return text, subbedChars
end
-- Reinsert any formatting that was temporarily substituted.
local function undoTempSubstitutions(text, subbedChars)
for i = 1, #subbedChars do
local byte2 = floor(i / 4096) % 64 + 128
local byte3 = floor(i / 64) % 64 + 128
local byte4 = i % 64 + 128
text = gsub(text, "\244[" .. char(byte2) .. char(byte2+8) .. "]" .. char(byte3) .. char(byte4),
replacement_escape(subbedChars[i]))
end
text = gsub(text, "\1", "%[%["):gsub("\2", "%]%]")
return text
end
-- Check if the raw text is an unsupported title, and if so return that. Otherwise, remove HTML entities. We do the pre-conversion to avoid loading the unsupported title list unnecessarily.
local function checkNoEntities(self, text)
local textNoEnc = decode_entities(text)
if textNoEnc ~= text and load_data(links_data_module).unsupported_titles[text] then
return text
else
return textNoEnc
end
end
-- If no script object is provided (or if it's invalid or None), get one.
local function checkScript(text, self, sc)
if not check_object("script", true, sc) or sc:getCode() == "None" then
return self:findBestScript(text)
end
return sc
end
local function normalize(text, sc)
text = sc:fixDiscouragedSequences(text)
return sc:toFixedNFD(text)
end
-- Subfunction of iterateSectionSubstitutions(). Process an individual chunk of text according to the specifications in
-- `substitution_data`. The input parameters are all as in the documentation of iterateSectionSubstitutions() except for
-- `recursed`, which is set to true if we called ourselves recursively to process a script-specific setting or
-- script-wide fallback. Returns two values: the processed text and the actual substitution data used to do the
-- substitutions (same as the `actual_substitution_data` return value to iterateSectionSubstitutions()).
local function doSubstitutions(self, text, sc, substitution_data, data_field, function_name, recursed)
-- BE CAREFUL in this function because the value at any level can be `false`, which causes no processing to be done
-- and blocks any further fallback processing.
local actual_substitution_data = substitution_data
-- If there are language-specific substitutes given in the data module, use those.
if type(substitution_data) == "table" then
-- If a script is specified, run this function with the script-specific data before continuing.
local sc_code = sc:getCode()
local has_substitution_data = false
if substitution_data[sc_code] ~= nil then
has_substitution_data = true
if substitution_data[sc_code] then
text, actual_substitution_data = doSubstitutions(self, text, sc, substitution_data[sc_code], data_field,
function_name, true)
end
-- Hant, Hans and Hani are usually treated the same, so add a special case to avoid having to specify each one
-- separately.
elseif sc_code:match("^Han") and substitution_data.Hani ~= nil then
has_substitution_data = true
if substitution_data.Hani then
text, actual_substitution_data = doSubstitutions(self, text, sc, substitution_data.Hani, data_field,
function_name, true)
end
-- Substitution data with key 1 in the outer table may be given as a fallback.
elseif substitution_data[1] ~= nil then
has_substitution_data = true
if substitution_data[1] then
text, actual_substitution_data = doSubstitutions(self, text, sc, substitution_data[1], data_field,
function_name, true)
end
end
-- Iterate over all strings in the "from" subtable, and gsub with the corresponding string in "to". We work with
-- the NFD decomposed forms, as this simplifies many substitutions.
if substitution_data.from then
has_substitution_data = true
for i, from in ipairs(substitution_data.from) do
-- Normalize each loop, to ensure multi-stage substitutions work correctly.
text = sc:toFixedNFD(text)
text = ugsub(text, sc:toFixedNFD(from), substitution_data.to[i] or "")
end
end
if substitution_data.remove_diacritics then
has_substitution_data = true
text = sc:toFixedNFD(text)
-- Convert exceptions to PUA.
local remove_exceptions, substitutes = substitution_data.remove_exceptions
if remove_exceptions then
substitutes = {}
local i = 0
for _, exception in ipairs(remove_exceptions) do
exception = sc:toFixedNFD(exception)
text = ugsub(text, exception, function(m)
i = i + 1
local subst = u(0x80000 + i)
substitutes[subst] = m
return subst
end)
end
end
-- Strip diacritics.
text = ugsub(text, "[" .. substitution_data.remove_diacritics .. "]", "")
-- Convert exceptions back.
if remove_exceptions then
text = text:gsub("\242[\128-\191]*", substitutes)
end
end
if not has_substitution_data and sc._data[data_field] then
-- If language-specific sort key (etc.) is nil, fall back to script-wide sort key (etc.).
text, actual_substitution_data = doSubstitutions(self, text, sc, sc._data[data_field], data_field,
function_name, true)
end
elseif type(substitution_data) == "string" then
-- If there is a dedicated function module, use that.
local module = safe_require("Module:" .. substitution_data)
if module then
-- TODO: translit functions should take objects, not codes.
-- TODO: translit functions should be called with form NFD.
if function_name == "tr" then
if not module[function_name] then
error(("Internal error: Module [[%s]] has no function named 'tr'"):format(substitution_data))
end
text = module[function_name](text, self._code, sc:getCode())
elseif function_name == "stripDiacritics" then
-- FIXME, get rid of this arm after renaming makeEntryName -> stripDiacritics.
if module[function_name] then
text = module[function_name](sc:toFixedNFD(text), self, sc)
elseif module.makeEntryName then
text = module.makeEntryName(sc:toFixedNFD(text), self, sc)
else
error(("Internal error: Module [[%s]] has no function named 'stripDiacritics' or 'makeEntryName'"
):format(substitution_data))
end
else
if not module[function_name] then
error(("Internal error: Module [[%s]] has no function named '%s'"):format(
substitution_data, function_name))
end
text = module[function_name](sc:toFixedNFD(text), self, sc)
end
else
error("Substitution data '" .. substitution_data .. "' does not match an existing module.")
end
elseif substitution_data == nil and sc._data[data_field] then
-- If language-specific sort key (etc.) is nil, fall back to script-wide sort key (etc.).
text, actual_substitution_data = doSubstitutions(self, text, sc, sc._data[data_field], data_field,
function_name, true)
end
-- Don't normalize to NFC if this is the inner loop or if a module returned nil.
if recursed or not text then
return text, actual_substitution_data
end
-- Fix any discouraged sequences created during the substitution process, and normalize into the final form.
return sc:toFixedNFC(sc:fixDiscouragedSequences(text)), actual_substitution_data
end
-- Split the text into sections, based on the presence of temporarily substituted formatting characters, then iterate
-- over each section to apply substitutions (e.g. transliteration or diacritic stripping). This avoids putting PUA
-- characters through language-specific modules, which may be unequipped for them. This function is passed the following
-- values:
-- * `self` (the Language object);
-- * `text` (the text to process);
-- * `sc` (the script of the text, which must be specified; callers should call checkScript() as needed to autodetect the
-- script of the text if not given explicitly by the user);
-- * `subbedChars` (an array of the same length as the text, indicating which characters have been substituted and by
-- what, or {nil} if no substitutions are to happen);
-- * `keepCarets` (DOCUMENT ME);
-- * `substitution_data` (the data indicating which substitutions to apply, taken directly from `data_field` in the
-- language's data structure in a submodule of [[Module:languages/data]]);
-- * `data_field` (the data field from which `substitution_data` was fetched, such as "sort_key" or "strip_diacritics");
-- * `function_name` (the name of the function to call to do the substitution, in case `substitution_data` specifies a
-- module to do the substitution);
-- * `notrim` (don't trim whitespace at the edges of `text`; set when computing the sort key, because whitespace at the
-- beginning of a sort key is significant and causes the resulting page to be sorted at the beginning of the category
-- it's in).
-- Returns three values:
-- (1) the processed text;
-- (2) the value of `subbedChars` that was passed in, possibly modified with additional character substitutions; will be
-- {nil} if {nil} was passed in;
-- (3) the actual substitution data that was used to apply substitutions to `text`; this may be different from the value
-- of `substitution_data` passed in if that value recursively specified script-specific substitutions or if no
-- substitution data could be found in the language-specific data (e.g. {nil} was passed in or a structure was passed
-- in that had no setting for the script given in `sc`), but a script-wide fallback value was set; currently it is
-- only used by makeSortKey().
local function iterateSectionSubstitutions(self, text, sc, subbedChars, keepCarets, substitution_data, data_field,
function_name, notrim)
local sections
-- See [[Module:languages/data]].
if not find(text, "\244") or load_data(languages_data_module).substitution[self._code] == "cont" then
sections = {text}
else
sections = split(text, "\244[\128-\143][\128-\191]*", true)
end
local actual_substitution_data
for _, section in ipairs(sections) do
-- Don't bother processing empty strings or whitespace (which may also not be handled well by dedicated
-- modules).
if gsub(section, "%s+", "") ~= "" then
local sub, this_actual_substitution_data = doSubstitutions(self, section, sc, substitution_data, data_field,
function_name)
actual_substitution_data = this_actual_substitution_data
-- Second round of temporary substitutions, in case any formatting was added by the main substitution
-- process. However, don't do this if the section contains formatting already (as it would have had to have
-- been escaped to reach this stage, and therefore should be given as raw text).
if sub and subbedChars then
local noSub
for _, pattern in ipairs(require(languages_data_patterns_module)) do
if match(section, pattern .. "%z?") then
noSub = true
end
end
if not noSub then
sub, subbedChars = doTempSubstitutions(sub, subbedChars, keepCarets, true)
end
end
if not sub then
text = sub
break
end
text = sub and gsub(text, pattern_escape(section), replacement_escape(sub), 1) or text
end
end
if not notrim then
-- Trim, unless there are only spacing characters, while ignoring any final formatting characters.
-- Do not trim sort keys because spaces at the beginning are significant.
text = text and text:gsub("^([\128-\191\244]*)%s+(%S)", "%1%2"):gsub("(%S)%s+([\128-\191\244]*)$", "%1%2") or
nil
end
return text, subbedChars, actual_substitution_data
end
-- Process carets (and any escapes). Default to simple removal, if no pattern/replacement is given.
local function processCarets(text, pattern, repl)
local rep
repeat
text, rep = gsub(text, "\\\\(\\*^)", "\3%1")
until rep == 0
return (text:gsub("\\^", "\4")
:gsub(pattern or "%^", repl or "")
:gsub("\3", "\\")
:gsub("\4", "^"))
end
-- Remove carets if they are used to capitalize parts of transliterations (unless they have been escaped).
local function removeCarets(text, sc)
if not sc:hasCapitalization() and sc:isTransliterated() and text:find("^", 1, true) then
return processCarets(text)
else
return text
end
end
local Language = {}
local Bahasa = require("Module:bahasa")
--[==[Returns the language code of the language. Example: {{code|lua|"fr"}} for French.]==]
function Language:getCode()
return Bahasa.getLangCodeByCode(self._code) or self._code
end
--[==[Returns the canonical name of the language. This is the name used to represent that language on Wiktionary, and is guaranteed to be unique to that language alone. Example: {{code|lua|"French"}} for French.]==]
function Language:getCanonicalName()
local canonical = Bahasa.getLangNameByCode(self._code)
if canonical then
self._name = canonical
return canonical
end
local name = self._name
if name == nil then
name = self._data[1]
self._name = name
end
return name
end
--lowercase version
function Language:getCanonicalNameLower()
local name = self:getCanonicalName()
local first = mw.ustring.sub(name, 1, 1)
local rest = mw.ustring.sub(name, 2)
return mw.ustring.lower(first) .. rest
end
--[==[
Return the display form of the language. The display form of a language, family or script is the form it takes when
appearing as the <code><var>source</var></code> in categories such as <code>English terms derived from
<var>source</var></code> or <code>English given names from <var>source</var></code>, and is also the displayed text
in {makeCategoryLink()} links. For full and etymology-only languages, this is the same as the canonical name, but
for families, it reads <code>"<var>name</var> languages"</code> (e.g. {"Indo-Iranian languages"}), and for scripts,
it reads <code>"<var>name</var> script"</code> (e.g. {"Arabic script"}).
]==]
function Language:getDisplayForm()
local form = self._displayForm
if form == nil then
form = self:getCanonicalNameLower()
-- Add article and " substrate" to substrates that lack them.
if self:getFamilyCode() == "qfa-sub" then
if not (sub(form, 1, 4) == "the " or sub(form, 1, 2) == "a ") then
form = "a " .. form
end
if not match(form, " [Ss]ubstrate") then
form = form .. " substrate"
end
end
self._displayForm = form
end
return form
end
--[==[Returns the value which should be used in the HTML lang= attribute for tagged text in the language.]==]
function Language:getHTMLAttribute(sc, region)
local code = self._code
if not find(code, "-", 1, true) then
return code .. "-" .. sc:getCode() .. (region and "-" .. region or "")
end
local parent = self:getParent()
region = region or match(code, "%f[%u][%u-]+%f[%U]")
if parent then
return parent:getHTMLAttribute(sc, region)
end
-- TODO: ISO family codes can also be used.
return "mis-" .. sc:getCode() .. (region and "-" .. region or "")
end
--[==[Returns a table of the aliases that the language is known by, excluding the canonical name. Aliases are synonyms for the language in question. The names are not guaranteed to be unique, in that sometimes more than one language is known by the same name. Example: {{code|lua|{"High German", "New High German", "Deutsch"} }} for [[:Category:German language|German]].]==]
function Language:getAliases()
self:loadInExtraData()
return require(language_like_module).getAliases(self)
end
--[==[
Return a table of the known subvarieties of a given language, excluding subvarieties that have been given
explicit etymology-only language codes. The names are not guaranteed to be unique, in that sometimes a given name
refers to a subvariety of more than one language. Example: {{code|lua|{"Southern Aymara", "Central Aymara"} }} for
[[:Category:Aymara language|Aymara]]. Note that the returned value can have nested tables in it, when a subvariety
goes by more than one name. Example: {{code|lua|{"North Azerbaijani", "South Azerbaijani", {"Afshar", "Afshari",
"Afshar Azerbaijani", "Afchar"}, {"Qashqa'i", "Qashqai", "Kashkay"}, "Sonqor"} }} for
[[:Category:Azerbaijani language|Azerbaijani]]. Here, for example, Afshar, Afshari, Afshar Azerbaijani and Afchar
all refer to the same subvariety, whose preferred name is Afshar (the one listed first). To avoid a return value
with nested tables in it, specify a non-{{code|lua|nil}} value for the <code>flatten</code> parameter; in that case,
the return value would be {{code|lua|{"North Azerbaijani", "South Azerbaijani", "Afshar", "Afshari",
"Afshar Azerbaijani", "Afchar", "Qashqa'i", "Qashqai", "Kashkay", "Sonqor"} }}.
]==]
function Language:getVarieties(flatten)
self:loadInExtraData()
return require(language_like_module).getVarieties(self, flatten)
end
--[==[Returns a table of the "other names" that the language is known by, which are listed in the <code>otherNames</code> field. It should be noted that the <code>otherNames</code> field itself is deprecated, and entries listed there should eventually be moved to either <code>aliases</code> or <code>varieties</code>.]==]
function Language:getOtherNames() -- To be eventually removed, once there are no more uses of the `otherNames` field.
self:loadInExtraData()
return require(language_like_module).getOtherNames(self)
end
--[==[
Return a combined table of the canonical name, aliases, varieties and other names of a given language.]==]
function Language:getAllNames()
self:loadInExtraData()
return require(language_like_module).getAllNames(self)
end
--[==[Returns a table of types as a lookup table (with the types as keys).
The possible types are
* {language}: This is a language, either full or etymology-only.
* {full}: This is a "full" (not etymology-only) language, i.e. the union of {regular}, {reconstructed} and
{appendix-constructed}. Note that the types {full} and {etymology-only} also exist for families, so if you
want to check specifically for a full language and you have an object that might be a family, you should
use {{lua|hasType("language", "full")}} and not simply {{lua|hasType("full")}}.
* {etymology-only}: This is an etymology-only (not full) language, whose parent is another etymology-only
language or a full language. Note that the types {full} and {etymology-only} also exist for
families, so if you want to check specifically for an etymology-only language and you have an
object that might be a family, you should use {{lua|hasType("language", "etymology-only")}}
and not simply {{lua|hasType("etymology-only")}}.
* {regular}: This indicates a full language that is attested according to [[WT:CFI]] and therefore permitted
in the main namespace. There may also be reconstructed terms for the language, which are placed in
the {Reconstruction} namespace and must be prefixed with * to indicate a reconstruction. Most full
languages are natural (not constructed) languages, but a few constructed languages (e.g. Esperanto
and Volapük, among others) are also allowed in the mainspace and considered regular languages.
* {reconstructed}: This language is not attested according to [[WT:CFI]], and therefore is allowed only in the
{Reconstruction} namespace. All terms in this language are reconstructed, and must be prefixed
with *. Languages such as Proto-Indo-European and Proto-Germanic are in this category.
* {appendix-constructed}: This language is attested but does not meet the additional requirements set out for
constructed languages ([[WT:CFI#Constructed languages]]). Its entries must therefore
be in the Appendix namespace, but they are not reconstructed and therefore should
not have * prefixed in links.
]==]
function Language:getTypes()
local types = self._types
if types == nil then
types = {language = true}
if self:getFullCode() == self._code then
types.full = true
else
types["etymology-only"] = true
end
for t in gmatch(self._data.type, "[^,]+") do
types[t] = true
end
self._types = types
end
return types
end
--[==[Given a list of types as strings, returns true if the language has all of them.]==]
function Language:hasType(...)
Language.hasType = require(language_like_module).hasType
return self:hasType(...)
end
--[==[Returns a table containing <code>WikimediaLanguage</code> objects (see [[Module:wikimedia languages]]), which represent languages and their codes as they are used in Wikimedia projects for interwiki linking and such. More than one object may be returned, as a single Wiktionary language may correspond to multiple Wikimedia languages. For example, Wiktionary's single code <code>sh</code> (Serbo-Croatian) maps to four Wikimedia codes: <code>sh</code> (Serbo-Croatian), <code>bs</code> (Bosnian), <code>hr</code> (Croatian) and <code>sr</code> (Serbian).
The code for the Wikimedia language is retrieved from the <code>wikimedia_codes</code> property in the data modules. If that property is not present, the code of the current language is used. If none of the available codes is actually a valid Wikimedia code, an empty table is returned.]==]
function Language:getWikimediaLanguages()
local wm_langs = self._wikimediaLanguageObjects
if wm_langs == nil then
local codes = self:getWikimediaLanguageCodes()
wm_langs = {}
for i = 1, #codes do
wm_langs[i] = get_wikimedia_lang(codes[i])
end
self._wikimediaLanguageObjects = wm_langs
end
return wm_langs
end
function Language:getWikimediaLanguageCodes()
local wm_langs = self._wikimediaLanguageCodes
if wm_langs == nil then
wm_langs = self._data.wikimedia_codes
if wm_langs then
wm_langs = split(wm_langs, ",", true, true)
else
local code = self._code
if is_known_language_tag(code) then
wm_langs = {code}
else
-- Inherit, but only if no codes are specified in the data *and*
-- the language code isn't a valid Wikimedia language code.
local parent = self:getParent()
wm_langs = parent and parent:getWikimediaLanguageCodes() or {}
end
end
self._wikimediaLanguageCodes = wm_langs
end
return wm_langs
end
--[==[
Returns the name of the Wikipedia article for the language. `project` specifies the language and project to retrieve
the article from, defaulting to {"enwiki"} for the English Wikipedia. Normally if specified it should be the project
code for a specific-language Wikipedia e.g. "zhwiki" for the Chinese Wikipedia, but it can be any project, including
non-Wikipedia ones. If the project is the English Wikipedia and the property {wikipedia_article} is present in the data
module it will be used first. In all other cases, a sitelink will be generated from {:getWikidataItem} (if set). The
resulting value (or lack of value) is cached so that subsequent calls are fast. If no value could be determined, and
`noCategoryFallback` is {false}, {:getCategoryName} is used as fallback; otherwise, {nil} is returned. Note that if
`noCategoryFallback` is {nil} or omitted, it defaults to {false} if the project is the English Wikipedia, otherwise
to {true}. In other words, under normal circumstances, if the English Wikipedia article couldn't be retrieved, the
return value will fall back to a link to the language's category, but this won't normally happen for any other project.
]==]
function Language:getWikipediaArticle(noCategoryFallback, project)
Language.getWikipediaArticle = require(language_like_module).getWikipediaArticle
return self:getWikipediaArticle(noCategoryFallback, project)
end
function Language:makeWikipediaLink()
return make_link(self, "w:id:" .. self:getWikipediaArticle(), self:getCanonicalNameLower())
end
--[==[Returns the name of the Wikimedia Commons category page for the language.]==]
function Language:getCommonsCategory()
Language.getCommonsCategory = require(language_like_module).getCommonsCategory
return self:getCommonsCategory()
end
--[==[Returns the Wikidata item id for the language or <code>nil</code>. This corresponds to the the second field in the data modules.]==]
function Language:getWikidataItem()
Language.getWikidataItem = require(language_like_module).getWikidataItem
return self:getWikidataItem()
end
--[==[Returns a table of <code>Script</code> objects for all scripts that the language is written in. See [[Module:scripts]].]==]
function Language:getScripts()
local scripts = self._scriptObjects
if scripts == nil then
local codes = self:getScriptCodes()
if codes[1] == "All" then
scripts = load_data(scripts_data_module)
else
scripts = {}
for i = 1, #codes do
scripts[i] = get_script(codes[i])
end
end
self._scriptObjects = scripts
end
return scripts
end
--[==[Returns the table of script codes in the language's data file.]==]
function Language:getScriptCodes()
local scripts = self._scriptCodes
if scripts == nil then
scripts = self._data[4]
if scripts then
local codes, n = {}, 0
for code in gmatch(scripts, "[^,]+") do
n = n + 1
-- Special handling of "Hants", which represents "Hani", "Hant" and "Hans" collectively.
if code == "Hants" then
codes[n] = "Hani"
codes[n + 1] = "Hant"
codes[n + 2] = "Hans"
n = n + 2
else
codes[n] = code
end
end
scripts = codes
else
scripts = {"None"}
end
self._scriptCodes = scripts
end
return scripts
end
--[==[Given some text, this function iterates through the scripts of a given language and tries to find the script that best matches the text. It returns a {{code|lua|Script}} object representing the script. If no match is found at all, it returns the {{code|lua|None}} script object.]==]
function Language:findBestScript(text, forceDetect)
if not text or text == "" or text == "-" then
return get_script("None")
end
-- Differs from table returned by getScriptCodes, as Hants is not normalized into its constituents.
local codes = self._bestScriptCodes
if codes == nil then
codes = self._data[4]
codes = codes and split(codes, ",", true, true) or {"None"}
self._bestScriptCodes = codes
end
local first_sc = codes[1]
if first_sc == "All" then
return find_best_script_without_lang(text)
end
local codes_len = #codes
if not (forceDetect or first_sc == "Hants" or codes_len > 1) then
first_sc = get_script(first_sc)
local charset = first_sc.characters
return charset and umatch(text, "[" .. charset .. "]") and first_sc or get_script("None")
end
-- Remove all formatting characters.
text = get_plaintext(text)
-- Remove all spaces and any ASCII punctuation. Some non-ASCII punctuation is script-specific, so can't be removed.
text = ugsub(text, "[%s!\"#%%&'()*,%-./:;?@[\\%]_{}]+", "")
if #text == 0 then
return get_script("None")
end
-- Try to match every script against the text,
-- and return the one with the most matching characters.
local bestcount, bestscript, length = 0
for i = 1, codes_len do
local sc = codes[i]
-- Special case for "Hants", which is a special code that represents whichever of "Hant" or "Hans" best matches, or "Hani" if they match equally. This avoids having to list all three. In addition, "Hants" will be treated as the best match if there is at least one matching character, under the assumption that a Han script is desirable in terms that contain a mix of Han and other scripts (not counting those which use Jpan or Kore).
if sc == "Hants" then
local Hani = get_script("Hani")
if not Hant_chars then
Hant_chars = load_data("Module:zh/data/ts")
Hans_chars = load_data("Module:zh/data/st")
end
local t, s, found = 0, 0
-- This is faster than using mw.ustring.gmatch directly.
for ch in gmatch((ugsub(text, "[" .. Hani.characters .. "]", "\255%0")), "\255(.[\128-\191]*)") do
found = true
if Hant_chars[ch] then
t = t + 1
if Hans_chars[ch] then
s = s + 1
end
elseif Hans_chars[ch] then
s = s + 1
else
t, s = t + 1, s + 1
end
end
if found then
if t == s then
return Hani
end
return get_script(t > s and "Hant" or "Hans")
end
else
sc = get_script(sc)
if not length then
length = ulen(text)
end
-- Count characters by removing everything in the script's charset and comparing to the original length.
local charset = sc.characters
local count = charset and length - ulen((ugsub(text, "[" .. charset .. "]+", ""))) or 0
if count >= length then
return sc
elseif count > bestcount then
bestcount = count
bestscript = sc
end
end
end
-- Return best matching script, or otherwise None.
return bestscript or get_script("None")
end
--[==[Returns a <code>Family</code> object for the language family that the language belongs to. See [[Module:families]].]==]
function Language:getFamily()
local family = self._familyObject
if family == nil then
family = self:getFamilyCode()
-- If the value is nil, it's cached as false.
family = family and get_family(family) or false
self._familyObject = family
end
return family or nil
end
--[==[Returns the family code in the language's data file.]==]
function Language:getFamilyCode()
local family = self._familyCode
if family == nil then
-- If the value is nil, it's cached as false.
family = self._data[3] or false
self._familyCode = family
end
return family or nil
end
function Language:getFamilyName()
local family = self._familyName
if family == nil then
family = self:getFamily()
-- If the value is nil, it's cached as false.
family = family and family:getCanonicalName() or false
self._familyName = family
end
return family or nil
end
do
local function check_family(self, family)
if type(family) == "table" then
family = family:getCode()
end
if self:getFamilyCode() == family then
return true
end
local self_family = self:getFamily()
if self_family:inFamily(family) then
return true
-- If the family isn't a real family (e.g. creoles) check any ancestors.
elseif self_family:inFamily("qfa-not") then
local ancestors = self:getAncestors()
for _, ancestor in ipairs(ancestors) do
if ancestor:inFamily(family) then
return true
end
end
end
end
--[==[Check whether the language belongs to `family` (which can be a family code or object). A list of objects can be given in place of `family`; in that case, return true if the language belongs to any of the specified families. Note that some languages (in particular, certain creoles) can have multiple immediate ancestors potentially belonging to different families; in that case, return true if the language belongs to any of the specified families.]==]
function Language:inFamily(...)
if self:getFamilyCode() == nil then
return false
end
return check_inputs(self, check_family, false, ...)
end
end
function Language:getParent()
local parent = self._parentObject
if parent == nil then
parent = self:getParentCode()
-- If the value is nil, it's cached as false.
parent = parent and get_by_code(parent, nil, true, true) or false
self._parentObject = parent
end
return parent or nil
end
function Language:getParentCode()
local parent = self._parentCode
if parent == nil then
-- If the value is nil, it's cached as false.
parent = self._data.parent or false
self._parentCode = parent
end
return parent or nil
end
function Language:getParentName()
local parent = self._parentName
if parent == nil then
parent = self:getParent()
-- If the value is nil, it's cached as false.
parent = parent and parent:getCanonicalName() or false
self._parentName = parent
end
return parent or nil
end
function Language:getParentChain()
local chain = self._parentChain
if chain == nil then
chain = {}
local parent, n = self:getParent(), 0
while parent do
n = n + 1
chain[n] = parent
parent = parent:getParent()
end
self._parentChain = chain
end
return chain
end
do
local function check_lang(self, lang)
for _, parent in ipairs(self:getParentChain()) do
if (type(lang) == "string" and lang or lang:getCode()) == parent:getCode() then
return true
end
end
end
function Language:hasParent(...)
return check_inputs(self, check_lang, false, ...)
end
end
--[==[
If the language is etymology-only, this iterates through parents until a full language or family is found, and the
corresponding object is returned. If the language is a full language, then it simply returns itself.
]==]
function Language:getFull()
local full = self._fullObject
if full == nil then
full = self:getFullCode()
full = full == self._code and self or get_by_code(full)
self._fullObject = full
end
return full
end
--[==[
If the language is an etymology-only language, this iterates through parents until a full language or family is
found, and the corresponding code is returned. If the language is a full language, then it simply returns the
language code.
]==]
function Language:getFullCode()
return self._fullCode or self._code
end
--[==[
If the language is an etymology-only language, this iterates through parents until a full language or family is
found, and the corresponding canonical name is returned. If the language is a full language, then it simply returns
the canonical name of the language.
]==]
function Language:getFullName()
local full = self._fullName
if full == nil then
full = self:getFull():getCanonicalName()
self._fullName = full
end
return full
end
--[==[Returns a table of <code class="nf">Language</code> objects for all languages that this language is directly descended from. Generally this is only a single language, but creoles, pidgins and mixed languages can have multiple ancestors.]==]
function Language:getAncestors()
local ancestors = self._ancestorObjects
if ancestors == nil then
ancestors = {}
local ancestor_codes = self:getAncestorCodes()
if #ancestor_codes > 0 then
for _, ancestor in ipairs(ancestor_codes) do
insert(ancestors, get_by_code(ancestor, nil, true))
end
else
local fam = self:getFamily()
local protoLang = fam and fam:getProtoLanguage() or nil
-- For the cases where the current language is the proto-language
-- of its family, or an etymology-only language that is ancestral to that
-- proto-language, we need to step up a level higher right from the
-- start.
if protoLang and (
protoLang:getCode() == self._code or
(self:hasType("etymology-only") and protoLang:hasAncestor(self))
) then
fam = fam:getFamily()
protoLang = fam and fam:getProtoLanguage() or nil
end
while not protoLang and not (not fam or fam:getCode() == "qfa-not") do
fam = fam:getFamily()
protoLang = fam and fam:getProtoLanguage() or nil
end
insert(ancestors, protoLang)
end
self._ancestorObjects = ancestors
end
return ancestors
end
do
-- Avoid a language being its own ancestor via class inheritance. We only need to check for this if the language has inherited an ancestor table from its parent, because we never want to drop ancestors that have been explicitly set in the data.
-- Recursively iterate over ancestors until we either find self or run out. If self is found, return true.
local function check_ancestor(self, lang)
local codes = lang:getAncestorCodes()
if not codes then
return nil
end
for i = 1, #codes do
local code = codes[i]
if code == self._code then
return true
end
local anc = get_by_code(code, nil, true)
if check_ancestor(self, anc) then
return true
end
end
end
--[==[Returns a table of <code class="nf">Language</code> codes for all languages that this language is directly descended from. Generally this is only a single language, but creoles, pidgins and mixed languages can have multiple ancestors.]==]
function Language:getAncestorCodes()
if self._ancestorCodes then
return self._ancestorCodes
end
local data = self._data
local codes = data.ancestors
if codes == nil then
codes = {}
self._ancestorCodes = codes
return codes
end
codes = split(codes, ",", true, true)
self._ancestorCodes = codes
-- If there are no codes or the ancestors weren't inherited data, there's nothing left to check.
if #codes == 0 or self:getData(false, "raw").ancestors ~= nil then
return codes
end
local i, code = 1
while i <= #codes do
code = codes[i]
if check_ancestor(self, self) then
remove(codes, i)
else
i = i + 1
end
end
return codes
end
end
--[==[Given a list of language objects or codes, returns true if at least one of them is an ancestor. This includes any etymology-only children of that ancestor. If the language's ancestor(s) are etymology-only languages, it will also return true for those language parent(s) (e.g. if Vulgar Latin is the ancestor, it will also return true for its parent, Latin). However, a parent is excluded from this if the ancestor is also ancestral to that parent (e.g. if Classical Persian is the ancestor, Persian would return false, because Classical Persian is also ancestral to Persian).]==]
function Language:hasAncestor(...)
local function iterateOverAncestorTree(node, func, parent_check)
local ancestors = node:getAncestors()
local ancestorsParents = {}
for _, ancestor in ipairs(ancestors) do
-- When checking the parents of the other language, and the ancestor is also a parent, skip to the next ancestor, so that we exclude any etymology-only children of that parent that are not directly related (see below).
local ret = (parent_check or not node:hasParent(ancestor)) and
func(ancestor) or iterateOverAncestorTree(ancestor, func, parent_check)
if ret then
return ret
end
end
-- Check the parents of any ancestors. We don't do this if checking the parents of the other language, so that we exclude any etymology-only children of those parents that are not directly related (e.g. if the ancestor is Vulgar Latin and we are checking New Latin, we want it to return false because they are on different ancestral branches. As such, if we're already checking the parent of New Latin (Latin) we don't want to compare it to the parent of the ancestor (Latin), as this would be a false positive; it should be one or the other).
if not parent_check then
return nil
end
for _, ancestor in ipairs(ancestors) do
local ancestorParents = ancestor:getParentChain()
for _, ancestorParent in ipairs(ancestorParents) do
if ancestorParent:getCode() == self._code or ancestorParent:hasAncestor(ancestor) then
break
else
insert(ancestorsParents, ancestorParent)
end
end
end
for _, ancestorParent in ipairs(ancestorsParents) do
local ret = func(ancestorParent)
if ret then
return ret
end
end
end
local function do_iteration(otherlang, parent_check)
-- otherlang can't be self
if (type(otherlang) == "string" and otherlang or otherlang:getCode()) == self._code then
return false
end
repeat
if iterateOverAncestorTree(
self,
function(ancestor)
return ancestor:getCode() == (type(otherlang) == "string" and otherlang or otherlang:getCode())
end,
parent_check
) then
return true
elseif type(otherlang) == "string" then
otherlang = get_by_code(otherlang, nil, true)
end
otherlang = otherlang:getParent()
parent_check = false
until not otherlang
end
local parent_check = true
for _, otherlang in ipairs{...} do
local ret = do_iteration(otherlang, parent_check)
if ret then
return true
end
end
return false
end
do
local function construct_node(lang, memo)
local branch, ancestors = {lang = lang:getCode()}
memo[lang:getCode()] = branch
for _, ancestor in ipairs(lang:getAncestors()) do
if ancestors == nil then
ancestors = {}
end
insert(ancestors, memo[ancestor:getCode()] or construct_node(ancestor, memo))
end
branch.ancestors = ancestors
return branch
end
function Language:getAncestorChain()
local chain = self._ancestorChain
if chain == nil then
chain = construct_node(self, {})
self._ancestorChain = chain
end
return chain
end
end
function Language:getAncestorChainOld()
local chain = self._ancestorChain
if chain == nil then
chain = {}
local step = self
while true do
local ancestors = step:getAncestors()
step = #ancestors == 1 and ancestors[1] or nil
if not step then
break
end
insert(chain, step)
end
self._ancestorChain = chain
end
return chain
end
local function fetch_descendants(self, fmt)
local descendants, family = {}, self:getFamily()
-- Iterate over all three datasets.
for _, data in ipairs{
require("Module:languages/code to canonical name"),
require("Module:etymology languages/code to canonical name"),
require("Module:families/code to canonical name"),
} do
for code in pairs(data) do
local lang = get_by_code(code, nil, true, true)
-- Test for a descendant. Earlier tests weed out most candidates, while the more intensive tests are only used sparingly.
if (
code ~= self._code and -- Not self.
lang:inFamily(family) and -- In the same family.
(
family:getProtoLanguageCode() == self._code or -- Self is the protolanguage.
self:hasDescendant(lang) or -- Full hasDescendant check.
(lang:getFullCode() == self._code and not self:hasAncestor(lang)) -- Etymology-only child which isn't an ancestor.
)
) then
if fmt == "object" then
insert(descendants, lang)
elseif fmt == "code" then
insert(descendants, code)
elseif fmt == "name" then
insert(descendants, lang:getCanonicalName())
end
end
end
end
return descendants
end
function Language:getDescendants()
local descendants = self._descendantObjects
if descendants == nil then
descendants = fetch_descendants(self, "object")
self._descendantObjects = descendants
end
return descendants
end
function Language:getDescendantCodes()
local descendants = self._descendantCodes
if descendants == nil then
descendants = fetch_descendants(self, "code")
self._descendantCodes = descendants
end
return descendants
end
function Language:getDescendantNames()
local descendants = self._descendantNames
if descendants == nil then
descendants = fetch_descendants(self, "name")
self._descendantNames = descendants
end
return descendants
end
do
local function check_lang(self, lang)
if type(lang) == "string" then
lang = get_by_code(lang, nil, true)
end
if lang:hasAncestor(self) then
return true
end
end
function Language:hasDescendant(...)
return check_inputs(self, check_lang, false, ...)
end
end
local function fetch_children(self, fmt)
local m_etym_data = require(etymology_languages_data_module)
local self_code, children = self._code, {}
for code, lang in pairs(m_etym_data) do
local _lang = lang
repeat
local parent = _lang.parent
if parent == self_code then
if fmt == "object" then
insert(children, get_by_code(code, nil, true))
elseif fmt == "code" then
insert(children, code)
elseif fmt == "name" then
insert(children, lang[1])
end
break
end
_lang = m_etym_data[parent]
until not _lang
end
return children
end
function Language:getChildren()
local children = self._childObjects
if children == nil then
children = fetch_children(self, "object")
self._childObjects = children
end
return children
end
function Language:getChildrenCodes()
local children = self._childCodes
if children == nil then
children = fetch_children(self, "code")
self._childCodes = children
end
return children
end
function Language:getChildrenNames()
local children = self._childNames
if children == nil then
children = fetch_children(self, "name")
self._childNames = children
end
return children
end
function Language:hasChild(...)
local lang = ...
if not lang then
return false
elseif type(lang) == "string" then
lang = get_by_code(lang, nil, true)
end
if lang:hasParent(self) then
return true
end
return self:hasChild(select(2, ...))
end
--[==[Returns the name of the main category of that language. Example: {{code|lua|"French language"}} for French, whose category is at [[:Category:French language]]. Unless optional argument <code>nocap</code> is given, the language name at the beginning of the returned value will be capitalized. This capitalization is correct for category names, but not if the language name is lowercase and the returned value of this function is used in the middle of a sentence.]==]
function Language:getCategoryName(nocap)
local name = self._categoryName
if name == nil then
name = self:getCanonicalNameLower()
-- If a substrate, omit any leading article.
if self:getFamilyCode() == "qfa-sub" then
name = name:gsub("^the ", ""):gsub("^a ", "")
end
-- Only add " language" if a full language.
if self:hasType("full") then
-- Unless the canonical name already ends with "language", "lect" or their derivatives, add " language".
if not (match(name, "[Ll]anguage$") or match(name, "[Ll]ect$")) then
name = name .. " language"
end
end
self._categoryName = name
end
if nocap then
return name
end
return mw.getContentLanguage():ucfirst(name)
end
--[==[Creates a link to the category; the link text is the canonical name.]==]
function Language:makeCategoryLink()
return make_link(self, ":Category:" .. self:getCategoryName(), self:getDisplayForm())
end
function Language:getStandardCharacters(sc)
local standard_chars = self._data.standard_chars
if type(standard_chars) ~= "table" then
return standard_chars
elseif sc and type(sc) ~= "string" then
check_object("script", nil, sc)
sc = sc:getCode()
end
if (not sc) or sc == "None" then
local scripts = {}
for _, script in pairs(standard_chars) do
insert(scripts, script)
end
return concat(scripts)
end
if standard_chars[sc] then
return standard_chars[sc] .. (standard_chars[1] or "")
end
end
--[==[
Strip diacritics from display text `text` (in a language-specific fashion), which is in the script `sc`. If `sc` is
omitted or {nil}, the script is autodetected. This also strips certain punctuation characters from the end and (in the
case of Spanish upside-down question mark and exclamation points) from the beginning; strips any whitespace at the
end of the text or between the text and final stripped punctuation characters; and applies some language-specific
Unicode normalizations to replace discouraged characters with their prescribed alternatives. Return the stripped text.
]==]
function Language:stripDiacritics(text, sc)
if (not text) or text == "" then
return text
end
sc = checkScript(text, self, sc)
text = normalize(text, sc)
-- FIXME, rename makeEntryName to stripDiacritics and get rid of second and third return values
-- everywhere
text, _, _ = iterateSectionSubstitutions(self, text, sc, nil, nil,
self._data.strip_diacritics or self._data.entry_name, "strip_diacritics", "stripDiacritics")
text = umatch(text, "^[¿¡]?(.-[^%s%p].-)%s*[؟?!;՛՜ ՞ ՟?!︖︕।॥။၊་།]?$") or text
return text
end
--[==[
Convert a ''logical'' pagename (the pagename as it appears to the user, after diacritics and punctuation have been
stripped) to a ''physical'' pagename (the pagename as it appears in the MediaWiki database). Reasons for a difference
between the two are (a) unsupported titles such as `[ ]` (with square brackets in them), `#` (pound/hash sign) and
`¯\_(ツ)_/¯` (with underscores), as well as overly long titles of various sorts; (b) "mammoth" pages that are split into
parts (e.g. `a`, which is split into physical pagenames `a/languages A to L` and `a/languages M to Z`). For almost all
purposes, you should work with logical and not physical pagenames. But there are certain use cases that require physical
pagenames, such as checking the existence of a page or retrieving a page's contents.
`pagename` is the logical pagename to be converted. `is_reconstructed_or_appendix` indicates whether the page is in the
`Reconstruction` or `Appendix` namespaces. If it is omitted or has the value {nil}, the pagename is checked for an
initial asterisk, and if found, the page is assumed to be a `Reconstruction` page. Setting a value of `false` or `true`
to `is_reconstructed_or_appendix` disables this check and allows for mainspace pagenames that begin with an asterisk.
]==]
function Language:logicalToPhysical(pagename, is_reconstructed_or_appendix)
-- FIXME: This probably shouldn't happen but it happens when makeEntryName() receives nil.
if pagename == nil then
track("nil-passed-to-logicalToPhysical")
return nil
end
local initial_asterisk
if is_reconstructed_or_appendix == nil then
local pagename_minus_initial_asterisk
initial_asterisk, pagename_minus_initial_asterisk = pagename:match("^(%*)(.*)$")
if pagename_minus_initial_asterisk then
is_reconstructed_or_appendix = true
pagename = pagename_minus_initial_asterisk
elseif self:hasType("appendix-constructed") then
is_reconstructed_or_appendix = true
end
end
if not is_reconstructed_or_appendix then
-- Check if the pagename is a listed unsupported title.
local unsupportedTitles = load_data(links_data_module).unsupported_titles
if unsupportedTitles[pagename] then
return "Unsupported titles/" .. unsupportedTitles[pagename]
end
end
-- Set `unsupported` as true if certain conditions are met.
local unsupported
-- Check if there's an unsupported character. \239\191\189 is the replacement character U+FFFD, which can't be typed
-- directly here due to an abuse filter. Unix-style dot-slash notation is also unsupported, as it is used for
-- relative paths in links, as are 3 or more consecutive tildes. Note: match is faster with magic
-- characters/charsets; find is faster with plaintext.
if (
match(pagename, "[#<>%[%]_{|}]") or
find(pagename, "\239\191\189") or
match(pagename, "%f[^%z/]%.%.?%f[%z/]") or
find(pagename, "~~~")
) then
unsupported = true
-- If it looks like an interwiki link.
elseif find(pagename, ":") then
local prefix = gsub(pagename, "^:*(.-):.*", ulower)
if (
load_data("Module:data/namespaces")[prefix] or
load_data("Module:data/interwikis")[prefix]
) then
unsupported = true
end
end
-- Escape unsupported characters so they can be used in titles. ` is used as a delimiter for this, so a raw use of
-- it in an unsupported title is also escaped here to prevent interference; this is only done with unsupported
-- titles, though, so inclusion won't in itself mean a title is treated as unsupported (which is why it's excluded
-- from the earlier test).
if unsupported then
-- FIXME: This conversion needs to be different for reconstructed pages with unsupported characters. There
-- aren't any currently, but if there ever are, we need to fix this e.g. to put them in something like
-- Reconstruction:Proto-Indo-European/Unsupported titles/`lowbar``num`.
local unsupported_characters = load_data(links_data_module).unsupported_characters
pagename = pagename:gsub("[#<>%[%]_`{|}\239]\191?\189?", unsupported_characters)
:gsub("%f[^%z/]%.%.?%f[%z/]", function(m)
return (gsub(m, "%.", "`period`"))
end)
:gsub("~~~+", function(m)
return (gsub(m, "~", "`tilde`"))
end)
pagename = "Unsupported titles/" .. pagename
elseif not is_reconstructed_or_appendix then
-- Check if this is a mammoth page. If so, which subpage should we link to?
local m_links_data = load_data(links_data_module)
local mammoth_page_type = m_links_data.mammoth_pages[pagename]
if mammoth_page_type then
local canonical_name = self:getFullName()
if canonical_name ~= "Translingual" and canonical_name ~= "English" then
local this_subpage
local L2_sort_key = get_L2_sort_key(canonical_name)
for _, subpage_spec in ipairs(m_links_data.mammoth_page_subpage_types[mammoth_page_type]) do
-- unpack() fails utterly on data loaded using mw.loadData() even if offsets are given
local subpage, pattern = subpage_spec[1], subpage_spec[2]
if pattern == true or L2_sort_key:match(pattern) then
this_subpage = subpage
break
end
end
if not this_subpage then
error(("Internal error: Bad data in mammoth_page_subpage_pages in [[Module:links/data]] for mammoth page %s, type %s; last entry didn't have 'true' in it"):format(
pagename, mammoth_page_type))
end
pagename = pagename .. "/" .. this_subpage
end
end
end
return (initial_asterisk or "") .. pagename
end
--[==[
Strip the diacritics from a display pagename and convert the resulting logical pagename into a physical pagename.
This allows you, for example, to retrieve the contents of the page or check its existence. WARNING: This is deprecated
and will be going away. It is a simple composition of `self:stripDiacritics` and `self:logicalToPhysical`; most callers
only want the former, and if you need both, call them both yourself.
`text` and `sc` are as in `self:stripDiacritics`, and `is_reconstructed_or_appendix` is as in `self:logicalToPhysical`.
]==]
function Language:makeEntryName(text, sc, is_reconstructed_or_appendix)
return self:logicalToPhysical(self:stripDiacritics(text, sc), is_reconstructed_or_appendix)
end
--[==[Generates alternative forms using a specified method, and returns them as a table. If no method is specified, returns a table containing only the input term.]==]
function Language:generateForms(text, sc)
local generate_forms = self._data.generate_forms
if generate_forms == nil then
return {text}
end
sc = checkScript(text, self, sc)
return require("Module:" .. self._data.generate_forms).generateForms(text, self, sc)
end
--[==[Creates a sort key for the given stripped text, following the rules appropriate for the language. This removes
diacritical marks from the stripped text if they are not considered significant for sorting, and may perform some other
changes. Any initial hyphen is also removed, and anything in parentheses is removed as well.
The <code>sort_key</code> setting for each language in the data modules defines the replacements made by this function, or it gives the name of the module that takes the stripped text and returns a sortkey.]==]
function Language:makeSortKey(text, sc)
if (not text) or text == "" then
return text
end
if match(text, "<[^<>]+>") then
track("track HTML tag")
end
-- Remove directional characters, bold, italics, soft hyphens, strip markers and HTML tags.
-- FIXME: Partly duplicated with remove_formatting() in [[Module:links]].
text = ugsub(text, "[\194\173\226\128\170-\226\128\174\226\129\166-\226\129\169]", "")
text = text:gsub("('*)'''(.-'*)'''", "%1%2"):gsub("('*)''(.-'*)''", "%1%2")
text = gsub(unstrip(text), "<[^<>]+>", "")
text = decode_uri(text, "PATH")
text = checkNoEntities(self, text)
-- Remove initial hyphens and * unless the term only consists of spacing + punctuation characters.
text = ugsub(text, "^([-]*)[-־ـ᠊*]+([-]*)(.*[^%s%p].*)", "%1%2%3")
sc = checkScript(text, self, sc)
text = normalize(text, sc)
text = removeCarets(text, sc)
-- For languages with dotted dotless i, ensure that "İ" is sorted as "i", and "I" is sorted as "ı".
if self:hasDottedDotlessI() then
text = gsub(text, "I\204\135", "i") -- decomposed "İ"
:gsub("I", "ı")
text = sc:toFixedNFD(text)
end
-- Convert to lowercase, make the sortkey, then convert to uppercase. Where the language has dotted dotless i, it is
-- usually not necessary to convert "i" to "İ" and "ı" to "I" first, because "I" will always be interpreted as
-- conventional "I" (not dotless "İ") by any sorting algorithms, which will have been taken into account by the
-- sortkey substitutions themselves. However, if no sortkey substitutions have been specified, then conversion is
-- necessary so as to prevent "i" and "ı" both being sorted as "I".
--
-- An exception is made for scripts that (sometimes) sort by scraping page content, as that means they are sensitive
-- to changes in capitalization (as it changes the target page).
if not sc:sortByScraping() then
text = ulower(text)
end
local actual_substitution_data
-- Don't trim whitespace here because it's significant at the beginning of a sort key or sort base.
text, _, actual_substitution_data = iterateSectionSubstitutions(self, text, sc, nil, nil, self._data.sort_key,
"sort_key", "makeSortKey", "notrim")
if not sc:sortByScraping() then
if self:hasDottedDotlessI() and not actual_substitution_data then
text = text:gsub("ı", "I"):gsub("i", "İ")
text = sc:toFixedNFC(text)
end
text = uupper(text)
end
-- Remove parentheses, as long as they are either preceded or followed by something.
text = gsub(text, "(.)[()]+", "%1"):gsub("[()]+(.)", "%1")
text = escape_risky_characters(text)
return text
end
--[==[Create the form used as as a basis for display text and transliteration. FIXME: Rename to correctInputText().]==]
local function processDisplayText(text, self, sc, keepCarets, keepPrefixes)
local subbedChars = {}
text, subbedChars = doTempSubstitutions(text, subbedChars, keepCarets)
text = decode_uri(text, "PATH")
text = checkNoEntities(self, text)
sc = checkScript(text, self, sc)
text = normalize(text, sc)
text, subbedChars = iterateSectionSubstitutions(self, text, sc, subbedChars, keepCarets, self._data.display_text,
"display_text", "makeDisplayText")
text = removeCarets(text, sc)
-- Remove any interwiki link prefixes (unless they have been escaped or this has been disabled).
if find(text, ":") and not keepPrefixes then
local rep
repeat
text, rep = gsub(text, "\\\\(\\*:)", "\3%1")
until rep == 0
text = gsub(text, "\\:", "\4")
while true do
local prefix = gsub(text, "^(.-):.+", function(m1)
return (gsub(m1, "\244[\128-\191]*", ""))
end)
-- Check if the prefix is an interwiki, though ignore capitalised Wiktionary:, which is a namespace.
if not prefix or prefix == text or prefix == "Wiktionary"
or not (load_data("Module:data/interwikis")[ulower(prefix)] or prefix == "") then
break
end
text = gsub(text, "^(.-):(.*)", function(m1, m2)
local ret = {}
for subbedChar in gmatch(m1, "\244[\128-\191]*") do
insert(ret, subbedChar)
end
return concat(ret) .. m2
end)
end
text = gsub(text, "\3", "\\"):gsub("\4", ":")
end
return text, subbedChars
end
--[==[Make the display text (i.e. what is displayed on the page).]==]
function Language:makeDisplayText(text, sc, keepPrefixes)
if not text or text == "" then
return text
end
local subbedChars
text, subbedChars = processDisplayText(text, self, sc, nil, keepPrefixes)
text = escape_risky_characters(text)
return undoTempSubstitutions(text, subbedChars)
end
--[==[Transliterates the text from the given script into the Latin script (see
[[Wiktionary:Transliteration and romanization]]). The language must have the <code>translit</code> property for this to
work; if it is not present, {{code|lua|nil}} is returned.
The <code>sc</code> parameter is handled by the transliteration module, and how it is handled is specific to that
module. Some transliteration modules may tolerate {{code|lua|nil}} as the script, others require it to be one of the
possible scripts that the module can transliterate, and will throw an error if it's not one of them. For this reason,
the <code>sc</code> parameter should always be provided when writing non-language-specific code.
The <code>module_override</code> parameter is used to override the default module that is used to provide the
transliteration. This is useful in cases where you need to demonstrate a particular module in use, but there is no
default module yet, or you want to demonstrate an alternative version of a transliteration module before making it
official. It should not be used in real modules or templates, only for testing. All uses of this parameter are tracked
by [[Wiktionary:Tracking/languages/module_override]].
'''Known bugs''':
* This function assumes {tr(s1) .. tr(s2) == tr(s1 .. s2)}. When this assertion fails, wikitext markups like <nowiki>'''</nowiki> can cause wrong transliterations.
* HTML entities like <code>&apos;</code>, often used to escape wikitext markups, do not work.
]==]
function Language:transliterate(text, sc, module_override)
-- If there is no text, or the language doesn't have transliteration data and there's no override, return nil.
if not text or text == "" or text == "-" then
return text
end
-- If the script is not transliteratable (and no override is given), return nil.
sc = checkScript(text, self, sc)
if not (sc:isTransliterated() or module_override) then
-- temporary tracking to see if/when this gets triggered
track("non-transliterable")
track("non-transliterable/" .. self._code)
track("non-transliterable/" .. sc:getCode())
track("non-transliterable/" .. sc:getCode() .. "/" .. self._code)
return nil
end
-- Remove any strip markers.
text = unstrip(text)
-- Do not process the formatting into PUA characters for certain languages.
local processed = load_data(languages_data_module).substitution[self._code] ~= "none"
-- Get the display text with the keepCarets flag set.
local subbedChars
if processed then
text, subbedChars = processDisplayText(text, self, sc, true)
end
-- Transliterate (using the module override if applicable).
text, subbedChars = iterateSectionSubstitutions(self, text, sc, subbedChars, true, module_override or
self._data.translit, "translit", "tr")
if not text then
return nil
end
-- Incomplete transliterations return nil.
local charset = sc.characters
if charset and umatch(text, "[" .. charset .. "]") then
-- Remove any characters in Latin, which includes Latin characters also included in other scripts (as these are
-- false positives), as well as any PUA substitutions. Anything remaining should only be script code "None"
-- (e.g. numerals).
local check_text = ugsub(text, "[" .. get_script("Latn").characters .. "-]+", "")
-- Set none_is_last_resort_only flag, so that any non-None chars will cause a script other than "None" to be
-- returned.
if find_best_script_without_lang(check_text, true):getCode() ~= "None" then
return nil
end
end
if processed then
text = escape_risky_characters(text)
text = undoTempSubstitutions(text, subbedChars)
end
-- If the script does not use capitalization, then capitalize any letters of the transliteration which are
-- immediately preceded by a caret (and remove the caret).
if text and not sc:hasCapitalization() and text:find("^", 1, true) then
text = processCarets(text, "%^([\128-\191\244]*%*?)([^\128-\191\244][\128-\191]*)", function(m1, m2)
return m1 .. uupper(m2)
end)
end
-- Track module overrides.
if module_override ~= nil then
track("module_override")
end
return text
end
do
local function handle_language_spec(self, spec, sc)
local ret = self["_" .. spec]
if ret == nil then
ret = self._data[spec]
if type(ret) == "string" then
ret = list_to_set(split(ret, ",", true, true))
end
self["_" .. spec] = ret
end
if type(ret) == "table" then
ret = ret[sc:getCode()]
end
return not not ret
end
function Language:overrideManualTranslit(sc)
return handle_language_spec(self, "override_translit", sc)
end
function Language:link_tr(sc)
return handle_language_spec(self, "link_tr", sc)
end
end
--[==[Returns {{code|lua|true}} if the language has a transliteration module, or {{code|lua|false}} if it doesn't.]==]
function Language:hasTranslit()
return not not self._data.translit
end
--[==[Returns {{code|lua|true}} if the language uses the letters I/ı and İ/i, or {{code|lua|false}} if it doesn't.]==]
function Language:hasDottedDotlessI()
return not not self._data.dotted_dotless_i
end
function Language:toJSON(opts)
local strip_diacritics, strip_diacritics_patterns, strip_diacritics_remove_diacritics = self._data.strip_diacritics
if strip_diacritics then
if strip_diacritics.from then
strip_diacritics_patterns = {}
for i, from in ipairs(strip_diacritics.from) do
insert(strip_diacritics_patterns, {from = from, to = strip_diacritics.to[i] or ""})
end
end
strip_diacritics_remove_diacritics = strip_diacritics.remove_diacritics
end
-- mainCode should only end up non-nil if dontCanonicalizeAliases is passed to make_object().
-- props should either contain zero-argument functions to compute the value, or the value itself.
local props = {
ancestors = function() return self:getAncestorCodes() end,
canonicalName = function() return self:getCanonicalName() end,
categoryName = function() return self:getCategoryName("nocap") end,
code = self._code,
mainCode = self._mainCode,
parent = function() return self:getParentCode() end,
full = function() return self:getFullCode() end,
stripDiacriticsPatterns = strip_diacritics_patterns,
stripDiacriticsRemoveDiacritics = strip_diacritics_remove_diacritics,
family = function() return self:getFamilyCode() end,
aliases = function() return self:getAliases() end,
varieties = function() return self:getVarieties() end,
otherNames = function() return self:getOtherNames() end,
scripts = function() return self:getScriptCodes() end,
type = function() return keys_to_list(self:getTypes()) end,
wikimediaLanguages = function() return self:getWikimediaLanguageCodes() end,
wikidataItem = function() return self:getWikidataItem() end,
wikipediaArticle = function() return self:getWikipediaArticle(true) end,
}
local ret = {}
for prop, val in pairs(props) do
if not opts.skip_fields or not opts.skip_fields[prop] then
if type(val) == "function" then
ret[prop] = val()
else
ret[prop] = val
end
end
end
-- Use `deep_copy` when returning a table, so that there are no editing restrictions imposed by `mw.loadData`.
return opts and opts.lua_table and deep_copy(ret) or to_json(ret, opts)
end
function export.getDataModuleName(code)
local letter = match(code, "^(%l)%l%l?$")
return "Module:" .. (
letter == nil and "languages/data/exceptional" or
#code == 2 and "languages/data/2" or
"languages/data/3/" .. letter
)
end
get_data_module_name = export.getDataModuleName
function export.getExtraDataModuleName(code)
return get_data_module_name(code) .. "/extra"
end
get_extra_data_module_name = export.getExtraDataModuleName
do
local function make_stack(data)
local key_types = {
[2] = "unique",
aliases = "unique",
otherNames = "unique",
type = "append",
varieties = "unique",
wikipedia_article = "unique",
wikimedia_codes = "unique"
}
local function __index(self, k)
local stack, key_type = getmetatable(self), key_types[k]
-- Data that isn't inherited from the parent.
if key_type == "unique" then
local v = stack[stack[make_stack]][k]
if v == nil then
local layer = stack[0]
if layer then -- Could be false if there's no extra data.
v = layer[k]
end
end
return v
-- Data that is appended by each generation.
elseif key_type == "append" then
local parts, offset, n = {}, 0, stack[make_stack]
for i = 1, n do
local part = stack[i][k]
if part == nil then
offset = offset + 1
else
parts[i - offset] = part
end
end
return offset ~= n and concat(parts, ",") or nil
end
local n = stack[make_stack]
while true do
local layer = stack[n]
if not layer then -- Could be false if there's no extra data.
return nil
end
local v = layer[k]
if v ~= nil then
return v
end
n = n - 1
end
end
local function __newindex()
error("table is read-only")
end
local function __pairs(self)
-- Iterate down the stack, caching keys to avoid duplicate returns.
local stack, seen = getmetatable(self), {}
local n = stack[make_stack]
local iter, state, k, v = pairs(stack[n])
return function()
repeat
repeat
k = iter(state, k)
if k == nil then
n = n - 1
local layer = stack[n]
if not layer then -- Could be false if there's no extra data.
return nil
end
iter, state, k = pairs(layer)
end
until not (k == nil or seen[k])
-- Get the value via a lookup, as the one returned by the
-- iterator will be the raw value from the current layer,
-- which may not be the one __index will return for that
-- key. Also memoize the key in `seen` (even if the lookup
-- returns nil) so that it doesn't get looked up again.
-- TODO: store values in `self`, avoiding the need to create
-- the `seen` table. The iterator will need to iterate over
-- `self` with `next` first to find these on future loops.
v, seen[k] = self[k], true
until v ~= nil
return k, v
end
end
local __ipairs = require(table_module).indexIpairs
function make_stack(data)
local stack = {
data,
[make_stack] = 1, -- stores the length and acts as a sentinel to confirm a given metatable is a stack.
__index = __index,
__newindex = __newindex,
__pairs = __pairs,
__ipairs = __ipairs,
}
stack.__metatable = stack
return setmetatable({}, stack), stack
end
return make_stack(data)
end
local function get_stack(data)
local stack = getmetatable(data)
return stack and type(stack) == "table" and stack[make_stack] and stack or nil
end
--[==[
<span style="color: var(--wikt-palette-red,#BA0000)">This function is not for use in entries or other content pages.</span>
Returns a blob of data about the language. The format of this blob is undocumented, and perhaps unstable; it's intended for things like the module's own unit-tests, which are "close friends" with the module and will be kept up-to-date as the format changes. If `extra` is set, any extra data in the relevant `/extra` module will be included. (Note that it will be included anyway if it has already been loaded into the language object.) If `raw` is set, then the returned data will not contain any data inherited from parent objects.
-- Do NOT use these methods!
-- All uses should be pre-approved on the talk page!
]==]
function Language:getData(extra, raw)
if extra then
self:loadInExtraData()
end
local data = self._data
-- If raw is not set, just return the data.
if not raw then
return data
end
local stack = get_stack(data)
-- If there isn't a stack or its length is 1, return the data. Extra data (if any) will be included, as it's stored at key 0 and doesn't affect the reported length.
if stack == nil then
return data
end
local n = stack[make_stack]
if n == 1 then
return data
end
local extra = stack[0]
-- If there isn't any extra data, return the top layer of the stack.
if extra == nil then
return stack[n]
end
-- If there is, return a new stack which has the top layer at key 1 and the extra data at key 0.
data, stack = make_stack(stack[n])
stack[0] = extra
return data
end
function Language:loadInExtraData()
-- Only full languages have extra data.
if not self:hasType("language", "full") then
return
end
local data = self._data
-- If there's no stack, create one.
local stack = get_stack(self._data)
if stack == nil then
data, stack = make_stack(data)
-- If already loaded, return.
elseif stack[0] ~= nil then
return
end
self._data = data
-- Load extra data from the relevant module and add it to the stack at key 0, so that the __index and __pairs metamethods will pick it up, since they iterate down the stack until they run out of layers.
local code = self._code
local modulename = get_extra_data_module_name(code)
-- No data cached as false.
stack[0] = modulename and load_data(modulename)[code] or false
end
--[==[Returns the name of the module containing the language's data. Currently, this is always [[Module:scripts/data]].]==]
function Language:getDataModuleName()
local name = self._dataModuleName
if name == nil then
name = self:hasType("etymology-only") and etymology_languages_data_module or
get_data_module_name(self._mainCode or self._code)
self._dataModuleName = name
end
return name
end
--[==[Returns the name of the module containing the language's data. Currently, this is always [[Module:scripts/data]].]==]
function Language:getExtraDataModuleName()
local name = self._extraDataModuleName
if name == nil then
name = not self:hasType("etymology-only") and get_extra_data_module_name(self._mainCode or self._code) or false
self._extraDataModuleName = name
end
return name or nil
end
function export.makeObject(code, data, dontCanonicalizeAliases)
local data_type = type(data)
if data_type ~= "table" then
error(("bad argument #2 to 'makeObject' (table expected, got %s)"):format(data_type))
end
-- Convert any aliases.
local input_code = code
code = normalize_code(code)
input_code = dontCanonicalizeAliases and input_code or code
local parent
if data.parent then
parent = get_by_code(data.parent, nil, true, true)
else
parent = Language
end
parent.__index = parent
local lang = {_code = input_code}
-- This can only happen if dontCanonicalizeAliases is passed to make_object().
if code ~= input_code then
lang._mainCode = code
end
local parent_data = parent._data
if parent_data == nil then
-- Full code is the same as the code.
lang._fullCode = parent._code or code
else
-- Copy full code.
lang._fullCode = parent._fullCode
local stack = get_stack(parent_data)
if stack == nil then
parent_data, stack = make_stack(parent_data)
end
-- Insert the input data as the new top layer of the stack.
local n = stack[make_stack] + 1
data, stack[n], stack[make_stack] = parent_data, data, n
end
lang._data = data
return setmetatable(lang, parent)
end
make_object = export.makeObject
end
--[==[Finds the language whose code matches the one provided. If it exists, it returns a <code class="nf">Language</code> object representing the language. Otherwise, it returns {{code|lua|nil}}, unless <code class="n">paramForError</code> is given, in which case an error is generated. If <code class="n">paramForError</code> is {{code|lua|true}}, a generic error message mentioning the bad code is generated; otherwise <code class="n">paramForError</code> should be a string or number specifying the parameter that the code came from, and this parameter will be mentioned in the error message along with the bad code. If <code class="n">allowEtymLang</code> is specified, etymology-only language codes are allowed and looked up along with normal language codes. If <code class="n">allowFamily</code> is specified, language family codes are allowed and looked up along with normal language codes.]==]
function export.getByCode(code, paramForError, allowEtymLang, allowFamily)
-- Track uses of paramForError, ultimately so it can be removed, as error-handling should be done by [[Module:parameters]], not here.
if paramForError ~= nil then
track("paramForError")
end
if type(code) ~= "string" then
local typ
if not code then
typ = "nil"
elseif check_object("language", true, code) then
typ = "a language object"
elseif check_object("family", true, code) then
typ = "a family object"
else
typ = "a " .. type(code)
end
error("The function getByCode expects a string as its first argument, but received " .. typ .. ".")
end
local m_data = load_data(languages_data_module)
if m_data.aliases[code] or m_data.track[code] then
track(code)
end
local norm_code = normalize_code(code)
-- Get the data, checking for etymology-only languages if allowEtymLang is set.
local data = load_data(get_data_module_name(norm_code))[norm_code] or
allowEtymLang and load_data(etymology_languages_data_module)[norm_code]
-- If no data was found and allowFamily is set, check the family data. If the main family data was found, make the object with [[Module:families]] instead, as family objects have different methods. However, if it's an etymology-only family, use make_object in this module (which handles object inheritance), and the family-specific methods will be inherited from the parent object.
if data == nil and allowFamily then
data = load_data("Module:families/data")[norm_code]
if data ~= nil then
if data.parent == nil then
return make_family_object(norm_code, data)
elseif not allowEtymLang then
data = nil
end
end
end
local retval = code and data and make_object(code, data)
if not retval and paramForError then
require("Module:languages/errorGetBy").code(code, paramForError, allowEtymLang, allowFamily)
end
return retval
end
get_by_code = export.getByCode
--[==[Finds the language whose canonical name (the name used to represent that language on Wiktionary) or other name matches the one provided. If it exists, it returns a <code class="nf">Language</code> object representing the language. Otherwise, it returns {{code|lua|nil}}, unless <code class="n">paramForError</code> is given, in which case an error is generated. If <code class="n">allowEtymLang</code> is specified, etymology-only language codes are allowed and looked up along with normal language codes. If <code class="n">allowFamily</code> is specified, language family codes are allowed and looked up along with normal language codes.
The canonical name of languages should always be unique (it is an error for two languages on Wiktionary to share the same canonical name), so this is guaranteed to give at most one result.
This function is powered by [[Module:languages/canonical names]], which contains a pre-generated mapping of full-language canonical names to codes. It is generated by going through the [[:Category:Language data modules]] for full languages. When <code class="n">allowEtymLang</code> is specified for the above function, [[Module:etymology languages/canonical names]] may also be used, and when <code class="n">allowFamily</code> is specified for the above function, [[Module:families/canonical names]] may also be used.]==]
function export.getByCanonicalName(name, errorIfInvalid, allowEtymLang, allowFamily)
local byName = load_data("Module:languages/canonical names")
local code = byName and byName[name]
if not code and allowEtymLang then
byName = load_data("Module:etymology languages/canonical names")
code = byName and byName[name] or
byName[gsub(name, " [Ss]ubstrate$", "")] or
byName[gsub(name, "^a ", "")] or
byName[gsub(name, "^a ", ""):gsub(" [Ss]ubstrate$", "")] or
-- For etymology families like "ira-pro".
-- FIXME: This is not ideal, as it allows " languages" to be appended to any etymology-only language, too.
byName[match(name, "^(.*) languages$")]
end
if not code and allowFamily then
byName = load_data("Module:families/canonical names")
code = byName[name] or byName[match(name, "^(.*) languages$")]
end
local retval = code and get_by_code(code, errorIfInvalid, allowEtymLang, allowFamily)
if not retval and errorIfInvalid then
require("Module:languages/errorGetBy").canonicalName(name, allowEtymLang, allowFamily)
end
return retval
end
--[==[Used by [[Module:languages/data/2]] (et al.) and [[Module:etymology languages/data]], [[Module:families/data]], [[Module:scripts/data]] and [[Module:writing systems/data]] to finalize the data into the format that is actually returned.]==]
function export.finalizeData(data, main_type, variety)
local fields = {"type"}
if main_type == "language" then
insert(fields, 4) -- script codes
insert(fields, "ancestors")
insert(fields, "link_tr")
insert(fields, "override_translit")
insert(fields, "wikimedia_codes")
elseif main_type == "script" then
insert(fields, 3) -- writing system codes
end -- Families and writing systems have no extra fields to process.
local fields_len = #fields
for _, entity in next, data do
if variety then
-- Move parent from 3 to "parent" and family from "family" to 3. These are different for the sake of convenience, since very few varieties have the family specified, whereas all of them have a parent.
entity.parent, entity[3], entity.family = entity[3], entity.family
-- Give the type "regular" iff not a variety and no other types are assigned.
elseif not (entity.type or entity.parent) then
entity.type = "regular"
end
for i = 1, fields_len do
local key = fields[i]
local field = entity[key]
if field and type(field) == "string" then
entity[key] = gsub(field, "%s*,%s*", ",")
end
end
end
return data
end
--[==[For backwards compatibility only; modules should require the error themselves.]==]
function export.err(lang_code, param, code_desc, template_tag, not_real_lang)
return require("Module:languages/error")(lang_code, param, code_desc, template_tag, not_real_lang)
end
return export
278qio2ki35dtgm22th3ft9t3fyumb7
26494
26493
2026-07-07T09:55:56Z
Sibiru45
115
1 ralatan matan [[:id:Modul:languages]]
26493
Scribunto
text/plain
--[==[ intro:
This module implements fetching of language-specific information and processing text in a given language.
===Types of languages===
There are two types of languages: full languages and etymology-only languages. The essential difference is that only
full languages appear in L2 headings in vocabulary entries, and hence categories like [[:Category:French nouns]] exist
only for full languages. Etymology-only languages have either a full language or another etymology-only language as
their parent (in the parent-child inheritance sense), and for etymology-only languages with another etymology-only
language as their parent, a full language can always be derived by following the parent links upwards. For example,
"Canadian French", code `fr-CA`, is an etymology-only language whose parent is the full language "French", code `fr`.
An example of an etymology-only language with another etymology-only parent is "Northumbrian Old English", code
`ang-nor`, which has "Anglian Old English", code `ang-ang` as its parent; this is an etymology-only language whose
parent is "Old English", code `ang`, which is a full language. (This is because Northumbrian Old English is considered
a variety of Anglian Old English.) Sometimes the parent is the "Undetermined" language, code `und`; this is the case,
for example, for "substrate" languages such as "Pre-Greek", code `qsb-grc`, and "the BMAC substrate", code `qsb-bma`.
It is important to distinguish language ''parents'' from language ''ancestors''. The parent-child relationship is one
of containment, i.e. if X is a child of Y, X is considered a variety of Y. On the other hand, the ancestor-descendant
relationship is one of descent in time. For example, "Classical Latin", code `la-cla`, and "Late Latin", code `la-lat`,
are both etymology-only languages with "Latin", code `la`, as their parents, because both of the former are varieties
of Latin. However, Late Latin does *NOT* have Classical Latin as its parent because Late Latin is *not* a variety of
Classical Latin; rather, it is a descendant. There is in fact a separate `ancestors` field that is used to express the
ancestor-descendant relationship, and Late Latin's ancestor is given as Classical Latin. It is also important to note
that sometimes an etymology-only language is actually the conceptual ancestor of its parent language. This happens,
for example, with "Old Italian" (code `roa-oit`), which is an etymology-only variant of full language "Italian" (code
`it`), and with "Old Latin" (code `itc-ola`), which is an etymology-only variant of Latin. In both cases, the full
language has the etymology-only variant listed as an ancestor. This allows a Latin term to inherit from Old Latin
using the {{tl|inh}} template (where in this template, "inheritance" refers to ancestral inheritance, i.e. inheritance
in time, rather than in the parent-child sense); likewise for Italian and Old Italian.
Full languages come in three subtypes:
* {regular}: This indicates a full language that is attested according to [[WT:CFI]] and therefore permitted in the
main namespace. There may also be reconstructed terms for the language, which are placed in the
{Reconstruction} namespace and must be prefixed with * to indicate a reconstruction. Most full languages
are natural (not constructed) languages, but a few constructed languages (e.g. Esperanto and Volapük,
among others) are also allowed in the mainspace and considered regular languages.
* {reconstructed}: This language is not attested according to [[WT:CFI]], and therefore is allowed only in the
{Reconstruction} namespace. All terms in this language are reconstructed, and must be prefixed with
*. Languages such as Proto-Indo-European and Proto-Germanic are in this category.
* {appendix-constructed}: This language is attested but does not meet the additional requirements set out for
constructed languages ([[WT:CFI#Constructed languages]]). Its entries must therefore be in
the Appendix namespace, but they are not reconstructed and therefore should not have *
prefixed in links. Most constructed languages are of this subtype.
Both full languages and etymology-only languages have a {Language} object associated with them, which is fetched using
the {getByCode} function in [[Module:languages]] to convert a language code to a {Language} object. Depending on the
options supplied to this function, etymology-only languages may or may not be accepted, and family codes may be
accepted (returning a {Family} object as described in [[Module:families]]). There are also separate {getByCanonicalName}
functions in [[Module:languages]] and [[Module:etymology languages]] to convert a language's canonical name to a
{Language} object (depending on whether the canonical name refers to a full or etymology-only language).
===Textual representations===
Textual strings belonging to a given language come in several different ''text variants'':
# The ''input text'' is what the user supplies in wikitext, in the parameters to {{tl|m}}, {{tl|l}}, {{tl|ux}},
{{tl|t}}, {{tl|lang}} and the like.
# The ''corrected input text'' is the input text with some corrections and/or normalizations applied, such as
bad-character replacements for certain languages, like replacing `l` or `1` to [[palochka]] in some languages written
in Cyrillic. (FIXME: This currently goes under the name ''display text'' but that will be repurposed below. Also,
[[User:Surjection]] suggests renaming this to ''normalized input text'', but "normalized" is used in a different sense
in [[Module:usex]].)
# The ''display text'' is the text in the form as it will be displayed to the user. This is what appears in headwords,
in usexes, in displayed internal links, etc. This can include accent marks that are removed to form the stripped
display text (see below), as well as embedded bracketed links that are variously processed further. The display text
is generated from the corrected input text by applying language-specific transformations; for most languages, there
will be no such transformations. The general reason for having a difference between input and display text is to allow
for extra information in the input text that is not displayed to the user but is sent to the transliteration module.
Note that having different display and input text is only supported currently through special-casing but will be
generalized. Examples of transformations are: (1) Removing the {{cd|^}} that is used in certain East Asian (and
possibly other unicameral) languages to indicate capitalization of the transliteration (which is currently
special-cased); (2) for Korean, removing or otherwise processing hyphens (which is currently special-cased); (3) for
Arabic, removing a ''sukūn'' diacritic placed over a ''tāʔ marbūṭa'' (like this: ةْ) to indicate that the
''tāʔ marbūṭa'' is pronounced and transliterated as /t/ instead of being silent [NOTE, NOT IMPLEMENTED YET]; (4) for
Thai and Khmer, converting space-separated words to bracketed words and resolving respelling substitutions such as
`[กรีน/กฺรีน]`, which indicate how to transliterate given words [NOTE, NOT IMPLEMENTED YET except in language-specific
templates like {{tl|th-usex}}].
## The ''right-resolved display text'' is the result of removing brackets around one-part embedded links and resolving
two-part embedded links into their right-hand components (i.e. converting two-part links into the displayed form).
The process of right-resolution is what happens when you call {{cd|remove_links()}} in [[Module:links]] on some text.
When applied to the display text, it produces exactly what the user sees, without any link markup.
# The ''stripped display text'' is the result of applying diacritic-stripping to the display text.
## The ''left-resolved stripped display text'' [NEED BETTER NAME] is the result of applying left-resolution to the
stripped display text, i.e. similar to right-resolution but resolving two-part embedded links into their left-hand
components (i.e. the linked-to page). If the display text refers to a single page, the resulting of applying
diacritic stripping and left-resolution produces the ''logical pagename''.
# The ''physical pagename text'' is the result of converting the stripped display text into physical page links. If the
stripped display text contains embedded links, the left side of those links is converted into physical page links;
otherwise, the entire text is considered a pagename and converted in the same fashion. The conversion does three
things: (1) converts characters not allowed in pagenames into their "unsupported title" representation, e.g.
{{cd|Unsupported titles/`gt`}} in place of the logical name {{cd|>}}; (2) handles certain special-cased
unsupported-title logical pagenames, such as {{cd|Unsupported titles/Space}} in place of {{cd|[space]}} and
{{cd|Unsupported titles/Ancient Greek dish}} in place of a very long Greek name for a gourmet dish as found in
Aristophanes; (3) converts "mammoth" pagenames such as [[a]] into their appropriate split component, e.g.
[[a/languages A to L]].
# The ''source translit text'' is the text as supplied to the language-specific {{cd|transliterate()}} method. The form
of the source translit text may need to be language-specific, e.g Thai and Khmer will need the corrected input text,
whereas other languages may need to work off the display text. [FIXME: It's still unclear to me how embedded bracketed
links are handled in the existing code.] In general, embedded links need to be right-resolved (see above), but when
this happens is unclear to me [FIXME]. Some languages have a chop-up-and-paste-together scheme that sends parts of the
text through the transliterate mechanism, and for others (those listed with "cont" in {{cd|substitution}} in
[[Module:languages/data]]) they receive the full input text, but preprocessed in certain ways. (The wisdom of this is
still unclear to me.)
# The ''transliterated text'' (or ''transliteration'') is the result of transliterating the source translit text. Unlike
for all the other text variants except the transcribed text, it is always in the Latin script.
# The ''transcribed text'' (or ''transcription'') is the result of transcribing the source translit text, where
"transcription" here means a close approximation to the phonetic form of the language in languages (e.g. Akkadian,
Sumerian, Ancient Egyptian, maybe Tibetan) that have a wide difference between the written letters and spoken form.
Unlike for all the other text variants other than the transliterated text, it is always in the Latin script.
Currently, the transcribed text is always supplied manually be the user; there is no such thing as a
{{cd|transcribe()}} method on language objects.
# The ''sort key'' is the text used in sort keys for determining the placing of pages in categories they belong to. The
sort key is generated from the pagename or a specified ''sort base'' by lowercasing, doing language-specific
transformations and then uppercasing the result. If the sort base is supplied and is generated from input text, it
needs to be converted to display text, have embedded links removed through right-resolution and have
diacritic-stripping applied.
# There are other text variants that occur in usexes (specifically, there are normalized variants of several of the
above text variants), but we can skip them for now.
The following methods exist on {Language} objects to convert between different text variants:
# {correctInputText} (currently called {makeDisplayText}): This converts input text to corrected input text.
# {stripDiacritics}: This converts to stripped display text. [FIXME: This needs some rethinking. In particular,
{stripDiacritics} is sometimes called on input text, corrected input text or display text (in various paths inside of
[[Module:links]], and, in the case of input text, usually from other modules). We need to make sure we don't try to
convert input text to display text twice, but at the same time we need to support calling it directly on input text
since so many modules do this. This means we need to add a parameter indicating whether the passed-in text is input,
corrected input, or display text; if the former two, we call {correctInputText} ourselves.]
# {logicalToPhysical}: This converts logical pagenames to physical pagenames.
# {transliterate}: This appears to convert input text with embedded brackets removed into a transliteration.
[FIXME: This needs some rethinking. In particular, it calls {processDisplayText} on its input, which won't work
for Thai and Khmer, so we may need language-specific flags indicating whether to pass the input text directly to the
language transliterate method. In addition, I'm not sure how embedded links are handled in the existing translit code;
a lot of callers remove the links themselves before calling {transliterate()}, which I assume is wrong.]
# {makeSortKey}: This converts display text (?) to a sort key. [FIXME: Clarify this.]
]==]
local export = {}
local debug_track_module = "Module:debug/track"
local etymology_languages_data_module = "Module:etymology languages/data"
local families_module = "Module:families"
local headword_page_module = "Module:headword/page"
local json_module = "Module:JSON"
local language_like_module = "Module:language-like"
local languages_data_module = "Module:languages/data"
local languages_data_patterns_module = "Module:languages/data/patterns"
local links_data_module = "Module:links/data"
local load_module = "Module:load"
local scripts_module = "Module:scripts"
local scripts_data_module = "Module:scripts/data"
local string_encode_entities_module = "Module:string/encode entities"
local string_pattern_escape_module = "Module:string/patternEscape"
local string_replacement_escape_module = "Module:string/replacementEscape"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local wikimedia_languages_module = "Module:wikimedia languages"
local mw = mw
local string = string
local table = table
local char = string.char
local concat = table.concat
local find = string.find
local floor = math.floor
local get_by_code -- Defined below.
local get_data_module_name -- Defined below.
local get_extra_data_module_name -- Defined below.
local getmetatable = getmetatable
local gmatch = string.gmatch
local gsub = string.gsub
local insert = table.insert
local ipairs = ipairs
local is_known_language_tag = mw.language.isKnownLanguageTag
local make_object -- Defined below.
local match = string.match
local next = next
local pairs = pairs
local remove = table.remove
local require = require
local select = select
local setmetatable = setmetatable
local sub = string.sub
local type = type
local unstrip = mw.text.unstrip
-- Loaded as needed by findBestScript.
local Hans_chars
local Hant_chars
local function check_object(...)
check_object = require(utilities_module).check_object
return check_object(...)
end
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function decode_uri(...)
decode_uri = require(string_utilities_module).decode_uri
return decode_uri(...)
end
local function deep_copy(...)
deep_copy = require(table_module).deepCopy
return deep_copy(...)
end
local function encode_entities(...)
encode_entities = require(string_encode_entities_module)
return encode_entities(...)
end
local function get_L2_sort_key(...)
get_L2_sort_key = require(headword_page_module).get_L2_sort_key
return get_L2_sort_key(...)
end
local function get_script(...)
get_script = require(scripts_module).getByCode
return get_script(...)
end
local function find_best_script_without_lang(...)
find_best_script_without_lang = require(scripts_module).findBestScriptWithoutLang
return find_best_script_without_lang(...)
end
local function get_family(...)
get_family = require(families_module).getByCode
return get_family(...)
end
local function get_plaintext(...)
get_plaintext = require(utilities_module).get_plaintext
return get_plaintext(...)
end
local function get_wikimedia_lang(...)
get_wikimedia_lang = require(wikimedia_languages_module).getByCode
return get_wikimedia_lang(...)
end
local function keys_to_list(...)
keys_to_list = require(table_module).keysToList
return keys_to_list(...)
end
local function list_to_set(...)
list_to_set = require(table_module).listToSet
return list_to_set(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function make_family_object(...)
make_family_object = require(families_module).makeObject
return make_family_object(...)
end
local function pattern_escape(...)
pattern_escape = require(string_pattern_escape_module)
return pattern_escape(...)
end
local function replacement_escape(...)
replacement_escape = require(string_replacement_escape_module)
return replacement_escape(...)
end
local function safe_require(...)
safe_require = require(load_module).safe_require
return safe_require(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function to_json(...)
to_json = require(json_module).toJSON
return to_json(...)
end
local function u(...)
u = require(string_utilities_module).char
return u(...)
end
local function ugsub(...)
ugsub = require(string_utilities_module).gsub
return ugsub(...)
end
local function ulen(...)
ulen = require(string_utilities_module).len
return ulen(...)
end
local function ulower(...)
ulower = require(string_utilities_module).lower
return ulower(...)
end
local function umatch(...)
umatch = require(string_utilities_module).match
return umatch(...)
end
local function uupper(...)
uupper = require(string_utilities_module).upper
return uupper(...)
end
local function track(page)
debug_track("languages/" .. page)
return true
end
local function normalize_code(code)
return load_data(languages_data_module).aliases[code] or code
end
local function check_inputs(self, check, default, ...)
local n = select("#", ...)
if n == 0 then
return false
end
local ret = check(self, (...))
if ret ~= nil then
return ret
elseif n > 1 then
local inputs = {...}
for i = 2, n do
ret = check(self, inputs[i])
if ret ~= nil then
return ret
end
end
end
return default
end
local function make_link(self, target, display)
local prefix, main
if self:getFamilyCode() == "qfa-sub" then
prefix, main = display:match("^(the )(.*)")
if not prefix then
prefix, main = display:match("^(a )(.*)")
end
end
return (prefix or "") .. "[[" .. target .. "|" .. (main or display) .. "]]"
end
-- Convert risky characters to HTML entities, which minimizes interference once returned (e.g. for "sms:a", "<!-- -->" etc.).
local function escape_risky_characters(text)
-- Spacing characters in isolation generally need to be escaped in order to be properly processed by the MediaWiki software.
if umatch(text, "^%s*$") then
return encode_entities(text, text)
end
return encode_entities(text, "!#%&*+/:;<=>?@[\\]_{|}")
end
-- Temporarily convert various formatting characters to PUA to prevent them from being disrupted by the substitution process.
local function doTempSubstitutions(text, subbedChars, keepCarets, noTrim)
-- Clone so that we don't insert any extra patterns into the table in package.loaded. For some reason, using require seems to keep memory use down; probably because the table is always cloned.
local patterns = shallow_copy(require(languages_data_patterns_module))
if keepCarets then
insert(patterns, "((\\+)%^)")
insert(patterns, "((%^))")
end
-- Ensure any whitespace at the beginning and end is temp substituted, to prevent it from being accidentally trimmed. We only want to trim any final spaces added during the substitution process (e.g. by a module), which means we only do this during the first round of temp substitutions.
if not noTrim then
insert(patterns, "^([\128-\191\244]*(%s+))")
insert(patterns, "((%s+)[\128-\191\244]*)$")
end
-- Pre-substitution, of "[[" and "]]", which makes pattern matching more accurate.
text = gsub(text, "%f[%[]%[%[", "\1"):gsub("%f[%]]%]%]", "\2")
local i = #subbedChars
for _, pattern in ipairs(patterns) do
-- Patterns ending in \0 stand are for things like "[[" or "]]"), so the inserted PUA are treated as breaks between terms by modules that scrape info from pages.
local term_divider
pattern = gsub(pattern, "%z$", function(divider)
term_divider = divider == "\0"
return ""
end)
text = gsub(text, pattern, function(...)
local m = {...}
local m1New = m[1]
for k = 2, #m do
local n = i + k - 1
subbedChars[n] = m[k]
local byte2 = floor(n / 4096) % 64 + (term_divider and 128 or 136)
local byte3 = floor(n / 64) % 64 + 128
local byte4 = n % 64 + 128
m1New = gsub(m1New, pattern_escape(m[k]), "\244" .. char(byte2) .. char(byte3) .. char(byte4), 1)
end
i = i + #m - 1
return m1New
end)
end
text = gsub(text, "\1", "%[%["):gsub("\2", "%]%]")
return text, subbedChars
end
-- Reinsert any formatting that was temporarily substituted.
local function undoTempSubstitutions(text, subbedChars)
for i = 1, #subbedChars do
local byte2 = floor(i / 4096) % 64 + 128
local byte3 = floor(i / 64) % 64 + 128
local byte4 = i % 64 + 128
text = gsub(text, "\244[" .. char(byte2) .. char(byte2+8) .. "]" .. char(byte3) .. char(byte4),
replacement_escape(subbedChars[i]))
end
text = gsub(text, "\1", "%[%["):gsub("\2", "%]%]")
return text
end
-- Check if the raw text is an unsupported title, and if so return that. Otherwise, remove HTML entities. We do the pre-conversion to avoid loading the unsupported title list unnecessarily.
local function checkNoEntities(self, text)
local textNoEnc = decode_entities(text)
if textNoEnc ~= text and load_data(links_data_module).unsupported_titles[text] then
return text
else
return textNoEnc
end
end
-- If no script object is provided (or if it's invalid or None), get one.
local function checkScript(text, self, sc)
if not check_object("script", true, sc) or sc:getCode() == "None" then
return self:findBestScript(text)
end
return sc
end
local function normalize(text, sc)
text = sc:fixDiscouragedSequences(text)
return sc:toFixedNFD(text)
end
-- Subfunction of iterateSectionSubstitutions(). Process an individual chunk of text according to the specifications in
-- `substitution_data`. The input parameters are all as in the documentation of iterateSectionSubstitutions() except for
-- `recursed`, which is set to true if we called ourselves recursively to process a script-specific setting or
-- script-wide fallback. Returns two values: the processed text and the actual substitution data used to do the
-- substitutions (same as the `actual_substitution_data` return value to iterateSectionSubstitutions()).
local function doSubstitutions(self, text, sc, substitution_data, data_field, function_name, recursed)
-- BE CAREFUL in this function because the value at any level can be `false`, which causes no processing to be done
-- and blocks any further fallback processing.
local actual_substitution_data = substitution_data
-- If there are language-specific substitutes given in the data module, use those.
if type(substitution_data) == "table" then
-- If a script is specified, run this function with the script-specific data before continuing.
local sc_code = sc:getCode()
local has_substitution_data = false
if substitution_data[sc_code] ~= nil then
has_substitution_data = true
if substitution_data[sc_code] then
text, actual_substitution_data = doSubstitutions(self, text, sc, substitution_data[sc_code], data_field,
function_name, true)
end
-- Hant, Hans and Hani are usually treated the same, so add a special case to avoid having to specify each one
-- separately.
elseif sc_code:match("^Han") and substitution_data.Hani ~= nil then
has_substitution_data = true
if substitution_data.Hani then
text, actual_substitution_data = doSubstitutions(self, text, sc, substitution_data.Hani, data_field,
function_name, true)
end
-- Substitution data with key 1 in the outer table may be given as a fallback.
elseif substitution_data[1] ~= nil then
has_substitution_data = true
if substitution_data[1] then
text, actual_substitution_data = doSubstitutions(self, text, sc, substitution_data[1], data_field,
function_name, true)
end
end
-- Iterate over all strings in the "from" subtable, and gsub with the corresponding string in "to". We work with
-- the NFD decomposed forms, as this simplifies many substitutions.
if substitution_data.from then
has_substitution_data = true
for i, from in ipairs(substitution_data.from) do
-- Normalize each loop, to ensure multi-stage substitutions work correctly.
text = sc:toFixedNFD(text)
text = ugsub(text, sc:toFixedNFD(from), substitution_data.to[i] or "")
end
end
if substitution_data.remove_diacritics then
has_substitution_data = true
text = sc:toFixedNFD(text)
-- Convert exceptions to PUA.
local remove_exceptions, substitutes = substitution_data.remove_exceptions
if remove_exceptions then
substitutes = {}
local i = 0
for _, exception in ipairs(remove_exceptions) do
exception = sc:toFixedNFD(exception)
text = ugsub(text, exception, function(m)
i = i + 1
local subst = u(0x80000 + i)
substitutes[subst] = m
return subst
end)
end
end
-- Strip diacritics.
text = ugsub(text, "[" .. substitution_data.remove_diacritics .. "]", "")
-- Convert exceptions back.
if remove_exceptions then
text = text:gsub("\242[\128-\191]*", substitutes)
end
end
if not has_substitution_data and sc._data[data_field] then
-- If language-specific sort key (etc.) is nil, fall back to script-wide sort key (etc.).
text, actual_substitution_data = doSubstitutions(self, text, sc, sc._data[data_field], data_field,
function_name, true)
end
elseif type(substitution_data) == "string" then
-- If there is a dedicated function module, use that.
local module = safe_require("Module:" .. substitution_data)
if module then
-- TODO: translit functions should take objects, not codes.
-- TODO: translit functions should be called with form NFD.
if function_name == "tr" then
if not module[function_name] then
error(("Internal error: Module [[%s]] has no function named 'tr'"):format(substitution_data))
end
text = module[function_name](text, self._code, sc:getCode())
elseif function_name == "stripDiacritics" then
-- FIXME, get rid of this arm after renaming makeEntryName -> stripDiacritics.
if module[function_name] then
text = module[function_name](sc:toFixedNFD(text), self, sc)
elseif module.makeEntryName then
text = module.makeEntryName(sc:toFixedNFD(text), self, sc)
else
error(("Internal error: Module [[%s]] has no function named 'stripDiacritics' or 'makeEntryName'"
):format(substitution_data))
end
else
if not module[function_name] then
error(("Internal error: Module [[%s]] has no function named '%s'"):format(
substitution_data, function_name))
end
text = module[function_name](sc:toFixedNFD(text), self, sc)
end
else
error("Substitution data '" .. substitution_data .. "' does not match an existing module.")
end
elseif substitution_data == nil and sc._data[data_field] then
-- If language-specific sort key (etc.) is nil, fall back to script-wide sort key (etc.).
text, actual_substitution_data = doSubstitutions(self, text, sc, sc._data[data_field], data_field,
function_name, true)
end
-- Don't normalize to NFC if this is the inner loop or if a module returned nil.
if recursed or not text then
return text, actual_substitution_data
end
-- Fix any discouraged sequences created during the substitution process, and normalize into the final form.
return sc:toFixedNFC(sc:fixDiscouragedSequences(text)), actual_substitution_data
end
-- Split the text into sections, based on the presence of temporarily substituted formatting characters, then iterate
-- over each section to apply substitutions (e.g. transliteration or diacritic stripping). This avoids putting PUA
-- characters through language-specific modules, which may be unequipped for them. This function is passed the following
-- values:
-- * `self` (the Language object);
-- * `text` (the text to process);
-- * `sc` (the script of the text, which must be specified; callers should call checkScript() as needed to autodetect the
-- script of the text if not given explicitly by the user);
-- * `subbedChars` (an array of the same length as the text, indicating which characters have been substituted and by
-- what, or {nil} if no substitutions are to happen);
-- * `keepCarets` (DOCUMENT ME);
-- * `substitution_data` (the data indicating which substitutions to apply, taken directly from `data_field` in the
-- language's data structure in a submodule of [[Module:languages/data]]);
-- * `data_field` (the data field from which `substitution_data` was fetched, such as "sort_key" or "strip_diacritics");
-- * `function_name` (the name of the function to call to do the substitution, in case `substitution_data` specifies a
-- module to do the substitution);
-- * `notrim` (don't trim whitespace at the edges of `text`; set when computing the sort key, because whitespace at the
-- beginning of a sort key is significant and causes the resulting page to be sorted at the beginning of the category
-- it's in).
-- Returns three values:
-- (1) the processed text;
-- (2) the value of `subbedChars` that was passed in, possibly modified with additional character substitutions; will be
-- {nil} if {nil} was passed in;
-- (3) the actual substitution data that was used to apply substitutions to `text`; this may be different from the value
-- of `substitution_data` passed in if that value recursively specified script-specific substitutions or if no
-- substitution data could be found in the language-specific data (e.g. {nil} was passed in or a structure was passed
-- in that had no setting for the script given in `sc`), but a script-wide fallback value was set; currently it is
-- only used by makeSortKey().
local function iterateSectionSubstitutions(self, text, sc, subbedChars, keepCarets, substitution_data, data_field,
function_name, notrim)
local sections
-- See [[Module:languages/data]].
if not find(text, "\244") or load_data(languages_data_module).substitution[self._code] == "cont" then
sections = {text}
else
sections = split(text, "\244[\128-\143][\128-\191]*", true)
end
local actual_substitution_data
for _, section in ipairs(sections) do
-- Don't bother processing empty strings or whitespace (which may also not be handled well by dedicated
-- modules).
if gsub(section, "%s+", "") ~= "" then
local sub, this_actual_substitution_data = doSubstitutions(self, section, sc, substitution_data, data_field,
function_name)
actual_substitution_data = this_actual_substitution_data
-- Second round of temporary substitutions, in case any formatting was added by the main substitution
-- process. However, don't do this if the section contains formatting already (as it would have had to have
-- been escaped to reach this stage, and therefore should be given as raw text).
if sub and subbedChars then
local noSub
for _, pattern in ipairs(require(languages_data_patterns_module)) do
if match(section, pattern .. "%z?") then
noSub = true
end
end
if not noSub then
sub, subbedChars = doTempSubstitutions(sub, subbedChars, keepCarets, true)
end
end
if not sub then
text = sub
break
end
text = sub and gsub(text, pattern_escape(section), replacement_escape(sub), 1) or text
end
end
if not notrim then
-- Trim, unless there are only spacing characters, while ignoring any final formatting characters.
-- Do not trim sort keys because spaces at the beginning are significant.
text = text and text:gsub("^([\128-\191\244]*)%s+(%S)", "%1%2"):gsub("(%S)%s+([\128-\191\244]*)$", "%1%2") or
nil
end
return text, subbedChars, actual_substitution_data
end
-- Process carets (and any escapes). Default to simple removal, if no pattern/replacement is given.
local function processCarets(text, pattern, repl)
local rep
repeat
text, rep = gsub(text, "\\\\(\\*^)", "\3%1")
until rep == 0
return (text:gsub("\\^", "\4")
:gsub(pattern or "%^", repl or "")
:gsub("\3", "\\")
:gsub("\4", "^"))
end
-- Remove carets if they are used to capitalize parts of transliterations (unless they have been escaped).
local function removeCarets(text, sc)
if not sc:hasCapitalization() and sc:isTransliterated() and text:find("^", 1, true) then
return processCarets(text)
else
return text
end
end
local Language = {}
local Bahasa = require("Module:bahasa")
--[==[Returns the language code of the language. Example: {{code|lua|"fr"}} for French.]==]
function Language:getCode()
return Bahasa.getLangCodeByCode(self._code) or self._code
end
--[==[Returns the canonical name of the language. This is the name used to represent that language on Wiktionary, and is guaranteed to be unique to that language alone. Example: {{code|lua|"French"}} for French.]==]
function Language:getCanonicalName()
local canonical = Bahasa.getLangNameByCode(self._code)
if canonical then
self._name = canonical
return canonical
end
local name = self._name
if name == nil then
name = self._data[1]
self._name = name
end
return name
end
--lowercase version
function Language:getCanonicalNameLower()
local name = self:getCanonicalName()
local first = mw.ustring.sub(name, 1, 1)
local rest = mw.ustring.sub(name, 2)
return mw.ustring.lower(first) .. rest
end
--[==[
Return the display form of the language. The display form of a language, family or script is the form it takes when
appearing as the <code><var>source</var></code> in categories such as <code>English terms derived from
<var>source</var></code> or <code>English given names from <var>source</var></code>, and is also the displayed text
in {makeCategoryLink()} links. For full and etymology-only languages, this is the same as the canonical name, but
for families, it reads <code>"<var>name</var> languages"</code> (e.g. {"Indo-Iranian languages"}), and for scripts,
it reads <code>"<var>name</var> script"</code> (e.g. {"Arabic script"}).
]==]
function Language:getDisplayForm()
local form = self._displayForm
if form == nil then
form = self:getCanonicalNameLower()
-- Add article and " substrate" to substrates that lack them.
if self:getFamilyCode() == "qfa-sub" then
if not (sub(form, 1, 4) == "the " or sub(form, 1, 2) == "a ") then
form = "a " .. form
end
if not match(form, " [Ss]ubstrate") then
form = form .. " substrate"
end
end
self._displayForm = form
end
return form
end
--[==[Returns the value which should be used in the HTML lang= attribute for tagged text in the language.]==]
function Language:getHTMLAttribute(sc, region)
local code = self._code
if not find(code, "-", 1, true) then
return code .. "-" .. sc:getCode() .. (region and "-" .. region or "")
end
local parent = self:getParent()
region = region or match(code, "%f[%u][%u-]+%f[%U]")
if parent then
return parent:getHTMLAttribute(sc, region)
end
-- TODO: ISO family codes can also be used.
return "mis-" .. sc:getCode() .. (region and "-" .. region or "")
end
--[==[Returns a table of the aliases that the language is known by, excluding the canonical name. Aliases are synonyms for the language in question. The names are not guaranteed to be unique, in that sometimes more than one language is known by the same name. Example: {{code|lua|{"High German", "New High German", "Deutsch"} }} for [[:Category:German language|German]].]==]
function Language:getAliases()
self:loadInExtraData()
return require(language_like_module).getAliases(self)
end
--[==[
Return a table of the known subvarieties of a given language, excluding subvarieties that have been given
explicit etymology-only language codes. The names are not guaranteed to be unique, in that sometimes a given name
refers to a subvariety of more than one language. Example: {{code|lua|{"Southern Aymara", "Central Aymara"} }} for
[[:Category:Aymara language|Aymara]]. Note that the returned value can have nested tables in it, when a subvariety
goes by more than one name. Example: {{code|lua|{"North Azerbaijani", "South Azerbaijani", {"Afshar", "Afshari",
"Afshar Azerbaijani", "Afchar"}, {"Qashqa'i", "Qashqai", "Kashkay"}, "Sonqor"} }} for
[[:Category:Azerbaijani language|Azerbaijani]]. Here, for example, Afshar, Afshari, Afshar Azerbaijani and Afchar
all refer to the same subvariety, whose preferred name is Afshar (the one listed first). To avoid a return value
with nested tables in it, specify a non-{{code|lua|nil}} value for the <code>flatten</code> parameter; in that case,
the return value would be {{code|lua|{"North Azerbaijani", "South Azerbaijani", "Afshar", "Afshari",
"Afshar Azerbaijani", "Afchar", "Qashqa'i", "Qashqai", "Kashkay", "Sonqor"} }}.
]==]
function Language:getVarieties(flatten)
self:loadInExtraData()
return require(language_like_module).getVarieties(self, flatten)
end
--[==[Returns a table of the "other names" that the language is known by, which are listed in the <code>otherNames</code> field. It should be noted that the <code>otherNames</code> field itself is deprecated, and entries listed there should eventually be moved to either <code>aliases</code> or <code>varieties</code>.]==]
function Language:getOtherNames() -- To be eventually removed, once there are no more uses of the `otherNames` field.
self:loadInExtraData()
return require(language_like_module).getOtherNames(self)
end
--[==[
Return a combined table of the canonical name, aliases, varieties and other names of a given language.]==]
function Language:getAllNames()
self:loadInExtraData()
return require(language_like_module).getAllNames(self)
end
--[==[Returns a table of types as a lookup table (with the types as keys).
The possible types are
* {language}: This is a language, either full or etymology-only.
* {full}: This is a "full" (not etymology-only) language, i.e. the union of {regular}, {reconstructed} and
{appendix-constructed}. Note that the types {full} and {etymology-only} also exist for families, so if you
want to check specifically for a full language and you have an object that might be a family, you should
use {{lua|hasType("language", "full")}} and not simply {{lua|hasType("full")}}.
* {etymology-only}: This is an etymology-only (not full) language, whose parent is another etymology-only
language or a full language. Note that the types {full} and {etymology-only} also exist for
families, so if you want to check specifically for an etymology-only language and you have an
object that might be a family, you should use {{lua|hasType("language", "etymology-only")}}
and not simply {{lua|hasType("etymology-only")}}.
* {regular}: This indicates a full language that is attested according to [[WT:CFI]] and therefore permitted
in the main namespace. There may also be reconstructed terms for the language, which are placed in
the {Reconstruction} namespace and must be prefixed with * to indicate a reconstruction. Most full
languages are natural (not constructed) languages, but a few constructed languages (e.g. Esperanto
and Volapük, among others) are also allowed in the mainspace and considered regular languages.
* {reconstructed}: This language is not attested according to [[WT:CFI]], and therefore is allowed only in the
{Reconstruction} namespace. All terms in this language are reconstructed, and must be prefixed
with *. Languages such as Proto-Indo-European and Proto-Germanic are in this category.
* {appendix-constructed}: This language is attested but does not meet the additional requirements set out for
constructed languages ([[WT:CFI#Constructed languages]]). Its entries must therefore
be in the Appendix namespace, but they are not reconstructed and therefore should
not have * prefixed in links.
]==]
function Language:getTypes()
local types = self._types
if types == nil then
types = {language = true}
if self:getFullCode() == self._code then
types.full = true
else
types["etymology-only"] = true
end
for t in gmatch(self._data.type, "[^,]+") do
types[t] = true
end
self._types = types
end
return types
end
--[==[Given a list of types as strings, returns true if the language has all of them.]==]
function Language:hasType(...)
Language.hasType = require(language_like_module).hasType
return self:hasType(...)
end
--[==[Returns a table containing <code>WikimediaLanguage</code> objects (see [[Module:wikimedia languages]]), which represent languages and their codes as they are used in Wikimedia projects for interwiki linking and such. More than one object may be returned, as a single Wiktionary language may correspond to multiple Wikimedia languages. For example, Wiktionary's single code <code>sh</code> (Serbo-Croatian) maps to four Wikimedia codes: <code>sh</code> (Serbo-Croatian), <code>bs</code> (Bosnian), <code>hr</code> (Croatian) and <code>sr</code> (Serbian).
The code for the Wikimedia language is retrieved from the <code>wikimedia_codes</code> property in the data modules. If that property is not present, the code of the current language is used. If none of the available codes is actually a valid Wikimedia code, an empty table is returned.]==]
function Language:getWikimediaLanguages()
local wm_langs = self._wikimediaLanguageObjects
if wm_langs == nil then
local codes = self:getWikimediaLanguageCodes()
wm_langs = {}
for i = 1, #codes do
wm_langs[i] = get_wikimedia_lang(codes[i])
end
self._wikimediaLanguageObjects = wm_langs
end
return wm_langs
end
function Language:getWikimediaLanguageCodes()
local wm_langs = self._wikimediaLanguageCodes
if wm_langs == nil then
wm_langs = self._data.wikimedia_codes
if wm_langs then
wm_langs = split(wm_langs, ",", true, true)
else
local code = self._code
if is_known_language_tag(code) then
wm_langs = {code}
else
-- Inherit, but only if no codes are specified in the data *and*
-- the language code isn't a valid Wikimedia language code.
local parent = self:getParent()
wm_langs = parent and parent:getWikimediaLanguageCodes() or {}
end
end
self._wikimediaLanguageCodes = wm_langs
end
return wm_langs
end
--[==[
Returns the name of the Wikipedia article for the language. `project` specifies the language and project to retrieve
the article from, defaulting to {"enwiki"} for the English Wikipedia. Normally if specified it should be the project
code for a specific-language Wikipedia e.g. "zhwiki" for the Chinese Wikipedia, but it can be any project, including
non-Wikipedia ones. If the project is the English Wikipedia and the property {wikipedia_article} is present in the data
module it will be used first. In all other cases, a sitelink will be generated from {:getWikidataItem} (if set). The
resulting value (or lack of value) is cached so that subsequent calls are fast. If no value could be determined, and
`noCategoryFallback` is {false}, {:getCategoryName} is used as fallback; otherwise, {nil} is returned. Note that if
`noCategoryFallback` is {nil} or omitted, it defaults to {false} if the project is the English Wikipedia, otherwise
to {true}. In other words, under normal circumstances, if the English Wikipedia article couldn't be retrieved, the
return value will fall back to a link to the language's category, but this won't normally happen for any other project.
]==]
function Language:getWikipediaArticle(noCategoryFallback, project)
Language.getWikipediaArticle = require(language_like_module).getWikipediaArticle
return self:getWikipediaArticle(noCategoryFallback, project)
end
function Language:makeWikipediaLink()
return make_link(self, "w:id:" .. self:getWikipediaArticle(), self:getCanonicalNameLower())
end
--[==[Returns the name of the Wikimedia Commons category page for the language.]==]
function Language:getCommonsCategory()
Language.getCommonsCategory = require(language_like_module).getCommonsCategory
return self:getCommonsCategory()
end
--[==[Returns the Wikidata item id for the language or <code>nil</code>. This corresponds to the the second field in the data modules.]==]
function Language:getWikidataItem()
Language.getWikidataItem = require(language_like_module).getWikidataItem
return self:getWikidataItem()
end
--[==[Returns a table of <code>Script</code> objects for all scripts that the language is written in. See [[Module:scripts]].]==]
function Language:getScripts()
local scripts = self._scriptObjects
if scripts == nil then
local codes = self:getScriptCodes()
if codes[1] == "All" then
scripts = load_data(scripts_data_module)
else
scripts = {}
for i = 1, #codes do
scripts[i] = get_script(codes[i])
end
end
self._scriptObjects = scripts
end
return scripts
end
--[==[Returns the table of script codes in the language's data file.]==]
function Language:getScriptCodes()
local scripts = self._scriptCodes
if scripts == nil then
scripts = self._data[4]
if scripts then
local codes, n = {}, 0
for code in gmatch(scripts, "[^,]+") do
n = n + 1
-- Special handling of "Hants", which represents "Hani", "Hant" and "Hans" collectively.
if code == "Hants" then
codes[n] = "Hani"
codes[n + 1] = "Hant"
codes[n + 2] = "Hans"
n = n + 2
else
codes[n] = code
end
end
scripts = codes
else
scripts = {"None"}
end
self._scriptCodes = scripts
end
return scripts
end
--[==[Given some text, this function iterates through the scripts of a given language and tries to find the script that best matches the text. It returns a {{code|lua|Script}} object representing the script. If no match is found at all, it returns the {{code|lua|None}} script object.]==]
function Language:findBestScript(text, forceDetect)
if not text or text == "" or text == "-" then
return get_script("None")
end
-- Differs from table returned by getScriptCodes, as Hants is not normalized into its constituents.
local codes = self._bestScriptCodes
if codes == nil then
codes = self._data[4]
codes = codes and split(codes, ",", true, true) or {"None"}
self._bestScriptCodes = codes
end
local first_sc = codes[1]
if first_sc == "All" then
return find_best_script_without_lang(text)
end
local codes_len = #codes
if not (forceDetect or first_sc == "Hants" or codes_len > 1) then
first_sc = get_script(first_sc)
local charset = first_sc.characters
return charset and umatch(text, "[" .. charset .. "]") and first_sc or get_script("None")
end
-- Remove all formatting characters.
text = get_plaintext(text)
-- Remove all spaces and any ASCII punctuation. Some non-ASCII punctuation is script-specific, so can't be removed.
text = ugsub(text, "[%s!\"#%%&'()*,%-./:;?@[\\%]_{}]+", "")
if #text == 0 then
return get_script("None")
end
-- Try to match every script against the text,
-- and return the one with the most matching characters.
local bestcount, bestscript, length = 0
for i = 1, codes_len do
local sc = codes[i]
-- Special case for "Hants", which is a special code that represents whichever of "Hant" or "Hans" best matches, or "Hani" if they match equally. This avoids having to list all three. In addition, "Hants" will be treated as the best match if there is at least one matching character, under the assumption that a Han script is desirable in terms that contain a mix of Han and other scripts (not counting those which use Jpan or Kore).
if sc == "Hants" then
local Hani = get_script("Hani")
if not Hant_chars then
Hant_chars = load_data("Module:zh/data/ts")
Hans_chars = load_data("Module:zh/data/st")
end
local t, s, found = 0, 0
-- This is faster than using mw.ustring.gmatch directly.
for ch in gmatch((ugsub(text, "[" .. Hani.characters .. "]", "\255%0")), "\255(.[\128-\191]*)") do
found = true
if Hant_chars[ch] then
t = t + 1
if Hans_chars[ch] then
s = s + 1
end
elseif Hans_chars[ch] then
s = s + 1
else
t, s = t + 1, s + 1
end
end
if found then
if t == s then
return Hani
end
return get_script(t > s and "Hant" or "Hans")
end
else
sc = get_script(sc)
if not length then
length = ulen(text)
end
-- Count characters by removing everything in the script's charset and comparing to the original length.
local charset = sc.characters
local count = charset and length - ulen((ugsub(text, "[" .. charset .. "]+", ""))) or 0
if count >= length then
return sc
elseif count > bestcount then
bestcount = count
bestscript = sc
end
end
end
-- Return best matching script, or otherwise None.
return bestscript or get_script("None")
end
--[==[Returns a <code>Family</code> object for the language family that the language belongs to. See [[Module:families]].]==]
function Language:getFamily()
local family = self._familyObject
if family == nil then
family = self:getFamilyCode()
-- If the value is nil, it's cached as false.
family = family and get_family(family) or false
self._familyObject = family
end
return family or nil
end
--[==[Returns the family code in the language's data file.]==]
function Language:getFamilyCode()
local family = self._familyCode
if family == nil then
-- If the value is nil, it's cached as false.
family = self._data[3] or false
self._familyCode = family
end
return family or nil
end
function Language:getFamilyName()
local family = self._familyName
if family == nil then
family = self:getFamily()
-- If the value is nil, it's cached as false.
family = family and family:getCanonicalName() or false
self._familyName = family
end
return family or nil
end
do
local function check_family(self, family)
if type(family) == "table" then
family = family:getCode()
end
if self:getFamilyCode() == family then
return true
end
local self_family = self:getFamily()
if self_family:inFamily(family) then
return true
-- If the family isn't a real family (e.g. creoles) check any ancestors.
elseif self_family:inFamily("qfa-not") then
local ancestors = self:getAncestors()
for _, ancestor in ipairs(ancestors) do
if ancestor:inFamily(family) then
return true
end
end
end
end
--[==[Check whether the language belongs to `family` (which can be a family code or object). A list of objects can be given in place of `family`; in that case, return true if the language belongs to any of the specified families. Note that some languages (in particular, certain creoles) can have multiple immediate ancestors potentially belonging to different families; in that case, return true if the language belongs to any of the specified families.]==]
function Language:inFamily(...)
if self:getFamilyCode() == nil then
return false
end
return check_inputs(self, check_family, false, ...)
end
end
function Language:getParent()
local parent = self._parentObject
if parent == nil then
parent = self:getParentCode()
-- If the value is nil, it's cached as false.
parent = parent and get_by_code(parent, nil, true, true) or false
self._parentObject = parent
end
return parent or nil
end
function Language:getParentCode()
local parent = self._parentCode
if parent == nil then
-- If the value is nil, it's cached as false.
parent = self._data.parent or false
self._parentCode = parent
end
return parent or nil
end
function Language:getParentName()
local parent = self._parentName
if parent == nil then
parent = self:getParent()
-- If the value is nil, it's cached as false.
parent = parent and parent:getCanonicalName() or false
self._parentName = parent
end
return parent or nil
end
function Language:getParentChain()
local chain = self._parentChain
if chain == nil then
chain = {}
local parent, n = self:getParent(), 0
while parent do
n = n + 1
chain[n] = parent
parent = parent:getParent()
end
self._parentChain = chain
end
return chain
end
do
local function check_lang(self, lang)
for _, parent in ipairs(self:getParentChain()) do
if (type(lang) == "string" and lang or lang:getCode()) == parent:getCode() then
return true
end
end
end
function Language:hasParent(...)
return check_inputs(self, check_lang, false, ...)
end
end
--[==[
If the language is etymology-only, this iterates through parents until a full language or family is found, and the
corresponding object is returned. If the language is a full language, then it simply returns itself.
]==]
function Language:getFull()
local full = self._fullObject
if full == nil then
full = self:getFullCode()
full = full == self._code and self or get_by_code(full)
self._fullObject = full
end
return full
end
--[==[
If the language is an etymology-only language, this iterates through parents until a full language or family is
found, and the corresponding code is returned. If the language is a full language, then it simply returns the
language code.
]==]
function Language:getFullCode()
return self._fullCode or self._code
end
--[==[
If the language is an etymology-only language, this iterates through parents until a full language or family is
found, and the corresponding canonical name is returned. If the language is a full language, then it simply returns
the canonical name of the language.
]==]
function Language:getFullName()
local full = self._fullName
if full == nil then
full = self:getFull():getCanonicalName()
self._fullName = full
end
return full
end
--[==[Returns a table of <code class="nf">Language</code> objects for all languages that this language is directly descended from. Generally this is only a single language, but creoles, pidgins and mixed languages can have multiple ancestors.]==]
function Language:getAncestors()
local ancestors = self._ancestorObjects
if ancestors == nil then
ancestors = {}
local ancestor_codes = self:getAncestorCodes()
if #ancestor_codes > 0 then
for _, ancestor in ipairs(ancestor_codes) do
insert(ancestors, get_by_code(ancestor, nil, true))
end
else
local fam = self:getFamily()
local protoLang = fam and fam:getProtoLanguage() or nil
-- For the cases where the current language is the proto-language
-- of its family, or an etymology-only language that is ancestral to that
-- proto-language, we need to step up a level higher right from the
-- start.
if protoLang and (
protoLang:getCode() == self._code or
(self:hasType("etymology-only") and protoLang:hasAncestor(self))
) then
fam = fam:getFamily()
protoLang = fam and fam:getProtoLanguage() or nil
end
while not protoLang and not (not fam or fam:getCode() == "qfa-not") do
fam = fam:getFamily()
protoLang = fam and fam:getProtoLanguage() or nil
end
insert(ancestors, protoLang)
end
self._ancestorObjects = ancestors
end
return ancestors
end
do
-- Avoid a language being its own ancestor via class inheritance. We only need to check for this if the language has inherited an ancestor table from its parent, because we never want to drop ancestors that have been explicitly set in the data.
-- Recursively iterate over ancestors until we either find self or run out. If self is found, return true.
local function check_ancestor(self, lang)
local codes = lang:getAncestorCodes()
if not codes then
return nil
end
for i = 1, #codes do
local code = codes[i]
if code == self._code then
return true
end
local anc = get_by_code(code, nil, true)
if check_ancestor(self, anc) then
return true
end
end
end
--[==[Returns a table of <code class="nf">Language</code> codes for all languages that this language is directly descended from. Generally this is only a single language, but creoles, pidgins and mixed languages can have multiple ancestors.]==]
function Language:getAncestorCodes()
if self._ancestorCodes then
return self._ancestorCodes
end
local data = self._data
local codes = data.ancestors
if codes == nil then
codes = {}
self._ancestorCodes = codes
return codes
end
codes = split(codes, ",", true, true)
self._ancestorCodes = codes
-- If there are no codes or the ancestors weren't inherited data, there's nothing left to check.
if #codes == 0 or self:getData(false, "raw").ancestors ~= nil then
return codes
end
local i, code = 1
while i <= #codes do
code = codes[i]
if check_ancestor(self, self) then
remove(codes, i)
else
i = i + 1
end
end
return codes
end
end
--[==[Given a list of language objects or codes, returns true if at least one of them is an ancestor. This includes any etymology-only children of that ancestor. If the language's ancestor(s) are etymology-only languages, it will also return true for those language parent(s) (e.g. if Vulgar Latin is the ancestor, it will also return true for its parent, Latin). However, a parent is excluded from this if the ancestor is also ancestral to that parent (e.g. if Classical Persian is the ancestor, Persian would return false, because Classical Persian is also ancestral to Persian).]==]
function Language:hasAncestor(...)
local function iterateOverAncestorTree(node, func, parent_check)
local ancestors = node:getAncestors()
local ancestorsParents = {}
for _, ancestor in ipairs(ancestors) do
-- When checking the parents of the other language, and the ancestor is also a parent, skip to the next ancestor, so that we exclude any etymology-only children of that parent that are not directly related (see below).
local ret = (parent_check or not node:hasParent(ancestor)) and
func(ancestor) or iterateOverAncestorTree(ancestor, func, parent_check)
if ret then
return ret
end
end
-- Check the parents of any ancestors. We don't do this if checking the parents of the other language, so that we exclude any etymology-only children of those parents that are not directly related (e.g. if the ancestor is Vulgar Latin and we are checking New Latin, we want it to return false because they are on different ancestral branches. As such, if we're already checking the parent of New Latin (Latin) we don't want to compare it to the parent of the ancestor (Latin), as this would be a false positive; it should be one or the other).
if not parent_check then
return nil
end
for _, ancestor in ipairs(ancestors) do
local ancestorParents = ancestor:getParentChain()
for _, ancestorParent in ipairs(ancestorParents) do
if ancestorParent:getCode() == self._code or ancestorParent:hasAncestor(ancestor) then
break
else
insert(ancestorsParents, ancestorParent)
end
end
end
for _, ancestorParent in ipairs(ancestorsParents) do
local ret = func(ancestorParent)
if ret then
return ret
end
end
end
local function do_iteration(otherlang, parent_check)
-- otherlang can't be self
if (type(otherlang) == "string" and otherlang or otherlang:getCode()) == self._code then
return false
end
repeat
if iterateOverAncestorTree(
self,
function(ancestor)
return ancestor:getCode() == (type(otherlang) == "string" and otherlang or otherlang:getCode())
end,
parent_check
) then
return true
elseif type(otherlang) == "string" then
otherlang = get_by_code(otherlang, nil, true)
end
otherlang = otherlang:getParent()
parent_check = false
until not otherlang
end
local parent_check = true
for _, otherlang in ipairs{...} do
local ret = do_iteration(otherlang, parent_check)
if ret then
return true
end
end
return false
end
do
local function construct_node(lang, memo)
local branch, ancestors = {lang = lang:getCode()}
memo[lang:getCode()] = branch
for _, ancestor in ipairs(lang:getAncestors()) do
if ancestors == nil then
ancestors = {}
end
insert(ancestors, memo[ancestor:getCode()] or construct_node(ancestor, memo))
end
branch.ancestors = ancestors
return branch
end
function Language:getAncestorChain()
local chain = self._ancestorChain
if chain == nil then
chain = construct_node(self, {})
self._ancestorChain = chain
end
return chain
end
end
function Language:getAncestorChainOld()
local chain = self._ancestorChain
if chain == nil then
chain = {}
local step = self
while true do
local ancestors = step:getAncestors()
step = #ancestors == 1 and ancestors[1] or nil
if not step then
break
end
insert(chain, step)
end
self._ancestorChain = chain
end
return chain
end
local function fetch_descendants(self, fmt)
local descendants, family = {}, self:getFamily()
-- Iterate over all three datasets.
for _, data in ipairs{
require("Module:languages/code to canonical name"),
require("Module:etymology languages/code to canonical name"),
require("Module:families/code to canonical name"),
} do
for code in pairs(data) do
local lang = get_by_code(code, nil, true, true)
-- Test for a descendant. Earlier tests weed out most candidates, while the more intensive tests are only used sparingly.
if (
code ~= self._code and -- Not self.
lang:inFamily(family) and -- In the same family.
(
family:getProtoLanguageCode() == self._code or -- Self is the protolanguage.
self:hasDescendant(lang) or -- Full hasDescendant check.
(lang:getFullCode() == self._code and not self:hasAncestor(lang)) -- Etymology-only child which isn't an ancestor.
)
) then
if fmt == "object" then
insert(descendants, lang)
elseif fmt == "code" then
insert(descendants, code)
elseif fmt == "name" then
insert(descendants, lang:getCanonicalName())
end
end
end
end
return descendants
end
function Language:getDescendants()
local descendants = self._descendantObjects
if descendants == nil then
descendants = fetch_descendants(self, "object")
self._descendantObjects = descendants
end
return descendants
end
function Language:getDescendantCodes()
local descendants = self._descendantCodes
if descendants == nil then
descendants = fetch_descendants(self, "code")
self._descendantCodes = descendants
end
return descendants
end
function Language:getDescendantNames()
local descendants = self._descendantNames
if descendants == nil then
descendants = fetch_descendants(self, "name")
self._descendantNames = descendants
end
return descendants
end
do
local function check_lang(self, lang)
if type(lang) == "string" then
lang = get_by_code(lang, nil, true)
end
if lang:hasAncestor(self) then
return true
end
end
function Language:hasDescendant(...)
return check_inputs(self, check_lang, false, ...)
end
end
local function fetch_children(self, fmt)
local m_etym_data = require(etymology_languages_data_module)
local self_code, children = self._code, {}
for code, lang in pairs(m_etym_data) do
local _lang = lang
repeat
local parent = _lang.parent
if parent == self_code then
if fmt == "object" then
insert(children, get_by_code(code, nil, true))
elseif fmt == "code" then
insert(children, code)
elseif fmt == "name" then
insert(children, lang[1])
end
break
end
_lang = m_etym_data[parent]
until not _lang
end
return children
end
function Language:getChildren()
local children = self._childObjects
if children == nil then
children = fetch_children(self, "object")
self._childObjects = children
end
return children
end
function Language:getChildrenCodes()
local children = self._childCodes
if children == nil then
children = fetch_children(self, "code")
self._childCodes = children
end
return children
end
function Language:getChildrenNames()
local children = self._childNames
if children == nil then
children = fetch_children(self, "name")
self._childNames = children
end
return children
end
function Language:hasChild(...)
local lang = ...
if not lang then
return false
elseif type(lang) == "string" then
lang = get_by_code(lang, nil, true)
end
if lang:hasParent(self) then
return true
end
return self:hasChild(select(2, ...))
end
--[==[Returns the name of the main category of that language. Example: {{code|lua|"French language"}} for French, whose category is at [[:Category:French language]]. Unless optional argument <code>nocap</code> is given, the language name at the beginning of the returned value will be capitalized. This capitalization is correct for category names, but not if the language name is lowercase and the returned value of this function is used in the middle of a sentence.]==]
function Language:getCategoryName(nocap)
local name = self._categoryName
if name == nil then
name = self:getCanonicalNameLower()
-- If a substrate, omit any leading article.
if self:getFamilyCode() == "qfa-sub" then
name = name:gsub("^the ", ""):gsub("^a ", "")
end
-- Only add " language" if a full language.
if self:hasType("full") then
-- Unless the canonical name already ends with "language", "lect" or their derivatives, add " language".
if not (match(name, "[Ll]anguage$") or match(name, "[Ll]ect$")) then
name = name .. " language"
end
end
self._categoryName = name
end
if nocap then
return name
end
return mw.getContentLanguage():ucfirst(name)
end
--[==[Creates a link to the category; the link text is the canonical name.]==]
function Language:makeCategoryLink()
return make_link(self, ":Category:" .. self:getCategoryName(), self:getDisplayForm())
end
function Language:getStandardCharacters(sc)
local standard_chars = self._data.standard_chars
if type(standard_chars) ~= "table" then
return standard_chars
elseif sc and type(sc) ~= "string" then
check_object("script", nil, sc)
sc = sc:getCode()
end
if (not sc) or sc == "None" then
local scripts = {}
for _, script in pairs(standard_chars) do
insert(scripts, script)
end
return concat(scripts)
end
if standard_chars[sc] then
return standard_chars[sc] .. (standard_chars[1] or "")
end
end
--[==[
Strip diacritics from display text `text` (in a language-specific fashion), which is in the script `sc`. If `sc` is
omitted or {nil}, the script is autodetected. This also strips certain punctuation characters from the end and (in the
case of Spanish upside-down question mark and exclamation points) from the beginning; strips any whitespace at the
end of the text or between the text and final stripped punctuation characters; and applies some language-specific
Unicode normalizations to replace discouraged characters with their prescribed alternatives. Return the stripped text.
]==]
function Language:stripDiacritics(text, sc)
if (not text) or text == "" then
return text
end
sc = checkScript(text, self, sc)
text = normalize(text, sc)
-- FIXME, rename makeEntryName to stripDiacritics and get rid of second and third return values
-- everywhere
text, _, _ = iterateSectionSubstitutions(self, text, sc, nil, nil,
self._data.strip_diacritics or self._data.entry_name, "strip_diacritics", "stripDiacritics")
text = umatch(text, "^[¿¡]?(.-[^%s%p].-)%s*[؟?!;՛՜ ՞ ՟?!︖︕।॥။၊་།]?$") or text
return text
end
--[==[
Convert a ''logical'' pagename (the pagename as it appears to the user, after diacritics and punctuation have been
stripped) to a ''physical'' pagename (the pagename as it appears in the MediaWiki database). Reasons for a difference
between the two are (a) unsupported titles such as `[ ]` (with square brackets in them), `#` (pound/hash sign) and
`¯\_(ツ)_/¯` (with underscores), as well as overly long titles of various sorts; (b) "mammoth" pages that are split into
parts (e.g. `a`, which is split into physical pagenames `a/languages A to L` and `a/languages M to Z`). For almost all
purposes, you should work with logical and not physical pagenames. But there are certain use cases that require physical
pagenames, such as checking the existence of a page or retrieving a page's contents.
`pagename` is the logical pagename to be converted. `is_reconstructed_or_appendix` indicates whether the page is in the
`Reconstruction` or `Appendix` namespaces. If it is omitted or has the value {nil}, the pagename is checked for an
initial asterisk, and if found, the page is assumed to be a `Reconstruction` page. Setting a value of `false` or `true`
to `is_reconstructed_or_appendix` disables this check and allows for mainspace pagenames that begin with an asterisk.
]==]
function Language:logicalToPhysical(pagename, is_reconstructed_or_appendix)
-- FIXME: This probably shouldn't happen but it happens when makeEntryName() receives nil.
if pagename == nil then
track("nil-passed-to-logicalToPhysical")
return nil
end
local initial_asterisk
if is_reconstructed_or_appendix == nil then
local pagename_minus_initial_asterisk
initial_asterisk, pagename_minus_initial_asterisk = pagename:match("^(%*)(.*)$")
if pagename_minus_initial_asterisk then
is_reconstructed_or_appendix = true
pagename = pagename_minus_initial_asterisk
elseif self:hasType("appendix-constructed") then
is_reconstructed_or_appendix = true
end
end
if not is_reconstructed_or_appendix then
-- Check if the pagename is a listed unsupported title.
local unsupportedTitles = load_data(links_data_module).unsupported_titles
if unsupportedTitles[pagename] then
return "Unsupported titles/" .. unsupportedTitles[pagename]
end
end
-- Set `unsupported` as true if certain conditions are met.
local unsupported
-- Check if there's an unsupported character. \239\191\189 is the replacement character U+FFFD, which can't be typed
-- directly here due to an abuse filter. Unix-style dot-slash notation is also unsupported, as it is used for
-- relative paths in links, as are 3 or more consecutive tildes. Note: match is faster with magic
-- characters/charsets; find is faster with plaintext.
if (
match(pagename, "[#<>%[%]_{|}]") or
find(pagename, "\239\191\189") or
match(pagename, "%f[^%z/]%.%.?%f[%z/]") or
find(pagename, "~~~")
) then
unsupported = true
-- If it looks like an interwiki link.
elseif find(pagename, ":") then
local prefix = gsub(pagename, "^:*(.-):.*", ulower)
if (
load_data("Module:data/namespaces")[prefix] or
load_data("Module:data/interwikis")[prefix]
) then
unsupported = true
end
end
-- Escape unsupported characters so they can be used in titles. ` is used as a delimiter for this, so a raw use of
-- it in an unsupported title is also escaped here to prevent interference; this is only done with unsupported
-- titles, though, so inclusion won't in itself mean a title is treated as unsupported (which is why it's excluded
-- from the earlier test).
if unsupported then
-- FIXME: This conversion needs to be different for reconstructed pages with unsupported characters. There
-- aren't any currently, but if there ever are, we need to fix this e.g. to put them in something like
-- Reconstruction:Proto-Indo-European/Unsupported titles/`lowbar``num`.
local unsupported_characters = load_data(links_data_module).unsupported_characters
pagename = pagename:gsub("[#<>%[%]_`{|}\239]\191?\189?", unsupported_characters)
:gsub("%f[^%z/]%.%.?%f[%z/]", function(m)
return (gsub(m, "%.", "`period`"))
end)
:gsub("~~~+", function(m)
return (gsub(m, "~", "`tilde`"))
end)
pagename = "Unsupported titles/" .. pagename
elseif not is_reconstructed_or_appendix then
-- Check if this is a mammoth page. If so, which subpage should we link to?
local m_links_data = load_data(links_data_module)
local mammoth_page_type = m_links_data.mammoth_pages[pagename]
if mammoth_page_type then
local canonical_name = self:getFullName()
if canonical_name ~= "Translingual" and canonical_name ~= "English" then
local this_subpage
local L2_sort_key = get_L2_sort_key(canonical_name)
for _, subpage_spec in ipairs(m_links_data.mammoth_page_subpage_types[mammoth_page_type]) do
-- unpack() fails utterly on data loaded using mw.loadData() even if offsets are given
local subpage, pattern = subpage_spec[1], subpage_spec[2]
if pattern == true or L2_sort_key:match(pattern) then
this_subpage = subpage
break
end
end
if not this_subpage then
error(("Internal error: Bad data in mammoth_page_subpage_pages in [[Module:links/data]] for mammoth page %s, type %s; last entry didn't have 'true' in it"):format(
pagename, mammoth_page_type))
end
pagename = pagename .. "/" .. this_subpage
end
end
end
return (initial_asterisk or "") .. pagename
end
--[==[
Strip the diacritics from a display pagename and convert the resulting logical pagename into a physical pagename.
This allows you, for example, to retrieve the contents of the page or check its existence. WARNING: This is deprecated
and will be going away. It is a simple composition of `self:stripDiacritics` and `self:logicalToPhysical`; most callers
only want the former, and if you need both, call them both yourself.
`text` and `sc` are as in `self:stripDiacritics`, and `is_reconstructed_or_appendix` is as in `self:logicalToPhysical`.
]==]
function Language:makeEntryName(text, sc, is_reconstructed_or_appendix)
return self:logicalToPhysical(self:stripDiacritics(text, sc), is_reconstructed_or_appendix)
end
--[==[Generates alternative forms using a specified method, and returns them as a table. If no method is specified, returns a table containing only the input term.]==]
function Language:generateForms(text, sc)
local generate_forms = self._data.generate_forms
if generate_forms == nil then
return {text}
end
sc = checkScript(text, self, sc)
return require("Module:" .. self._data.generate_forms).generateForms(text, self, sc)
end
--[==[Creates a sort key for the given stripped text, following the rules appropriate for the language. This removes
diacritical marks from the stripped text if they are not considered significant for sorting, and may perform some other
changes. Any initial hyphen is also removed, and anything in parentheses is removed as well.
The <code>sort_key</code> setting for each language in the data modules defines the replacements made by this function, or it gives the name of the module that takes the stripped text and returns a sortkey.]==]
function Language:makeSortKey(text, sc)
if (not text) or text == "" then
return text
end
if match(text, "<[^<>]+>") then
track("track HTML tag")
end
-- Remove directional characters, bold, italics, soft hyphens, strip markers and HTML tags.
-- FIXME: Partly duplicated with remove_formatting() in [[Module:links]].
text = ugsub(text, "[\194\173\226\128\170-\226\128\174\226\129\166-\226\129\169]", "")
text = text:gsub("('*)'''(.-'*)'''", "%1%2"):gsub("('*)''(.-'*)''", "%1%2")
text = gsub(unstrip(text), "<[^<>]+>", "")
text = decode_uri(text, "PATH")
text = checkNoEntities(self, text)
-- Remove initial hyphens and * unless the term only consists of spacing + punctuation characters.
text = ugsub(text, "^([-]*)[-־ـ᠊*]+([-]*)(.*[^%s%p].*)", "%1%2%3")
sc = checkScript(text, self, sc)
text = normalize(text, sc)
text = removeCarets(text, sc)
-- For languages with dotted dotless i, ensure that "İ" is sorted as "i", and "I" is sorted as "ı".
if self:hasDottedDotlessI() then
text = gsub(text, "I\204\135", "i") -- decomposed "İ"
:gsub("I", "ı")
text = sc:toFixedNFD(text)
end
-- Convert to lowercase, make the sortkey, then convert to uppercase. Where the language has dotted dotless i, it is
-- usually not necessary to convert "i" to "İ" and "ı" to "I" first, because "I" will always be interpreted as
-- conventional "I" (not dotless "İ") by any sorting algorithms, which will have been taken into account by the
-- sortkey substitutions themselves. However, if no sortkey substitutions have been specified, then conversion is
-- necessary so as to prevent "i" and "ı" both being sorted as "I".
--
-- An exception is made for scripts that (sometimes) sort by scraping page content, as that means they are sensitive
-- to changes in capitalization (as it changes the target page).
if not sc:sortByScraping() then
text = ulower(text)
end
local actual_substitution_data
-- Don't trim whitespace here because it's significant at the beginning of a sort key or sort base.
text, _, actual_substitution_data = iterateSectionSubstitutions(self, text, sc, nil, nil, self._data.sort_key,
"sort_key", "makeSortKey", "notrim")
if not sc:sortByScraping() then
if self:hasDottedDotlessI() and not actual_substitution_data then
text = text:gsub("ı", "I"):gsub("i", "İ")
text = sc:toFixedNFC(text)
end
text = uupper(text)
end
-- Remove parentheses, as long as they are either preceded or followed by something.
text = gsub(text, "(.)[()]+", "%1"):gsub("[()]+(.)", "%1")
text = escape_risky_characters(text)
return text
end
--[==[Create the form used as as a basis for display text and transliteration. FIXME: Rename to correctInputText().]==]
local function processDisplayText(text, self, sc, keepCarets, keepPrefixes)
local subbedChars = {}
text, subbedChars = doTempSubstitutions(text, subbedChars, keepCarets)
text = decode_uri(text, "PATH")
text = checkNoEntities(self, text)
sc = checkScript(text, self, sc)
text = normalize(text, sc)
text, subbedChars = iterateSectionSubstitutions(self, text, sc, subbedChars, keepCarets, self._data.display_text,
"display_text", "makeDisplayText")
text = removeCarets(text, sc)
-- Remove any interwiki link prefixes (unless they have been escaped or this has been disabled).
if find(text, ":") and not keepPrefixes then
local rep
repeat
text, rep = gsub(text, "\\\\(\\*:)", "\3%1")
until rep == 0
text = gsub(text, "\\:", "\4")
while true do
local prefix = gsub(text, "^(.-):.+", function(m1)
return (gsub(m1, "\244[\128-\191]*", ""))
end)
-- Check if the prefix is an interwiki, though ignore capitalised Wiktionary:, which is a namespace.
if not prefix or prefix == text or prefix == "Wiktionary"
or not (load_data("Module:data/interwikis")[ulower(prefix)] or prefix == "") then
break
end
text = gsub(text, "^(.-):(.*)", function(m1, m2)
local ret = {}
for subbedChar in gmatch(m1, "\244[\128-\191]*") do
insert(ret, subbedChar)
end
return concat(ret) .. m2
end)
end
text = gsub(text, "\3", "\\"):gsub("\4", ":")
end
return text, subbedChars
end
--[==[Make the display text (i.e. what is displayed on the page).]==]
function Language:makeDisplayText(text, sc, keepPrefixes)
if not text or text == "" then
return text
end
local subbedChars
text, subbedChars = processDisplayText(text, self, sc, nil, keepPrefixes)
text = escape_risky_characters(text)
return undoTempSubstitutions(text, subbedChars)
end
--[==[Transliterates the text from the given script into the Latin script (see
[[Wiktionary:Transliteration and romanization]]). The language must have the <code>translit</code> property for this to
work; if it is not present, {{code|lua|nil}} is returned.
The <code>sc</code> parameter is handled by the transliteration module, and how it is handled is specific to that
module. Some transliteration modules may tolerate {{code|lua|nil}} as the script, others require it to be one of the
possible scripts that the module can transliterate, and will throw an error if it's not one of them. For this reason,
the <code>sc</code> parameter should always be provided when writing non-language-specific code.
The <code>module_override</code> parameter is used to override the default module that is used to provide the
transliteration. This is useful in cases where you need to demonstrate a particular module in use, but there is no
default module yet, or you want to demonstrate an alternative version of a transliteration module before making it
official. It should not be used in real modules or templates, only for testing. All uses of this parameter are tracked
by [[Wiktionary:Tracking/languages/module_override]].
'''Known bugs''':
* This function assumes {tr(s1) .. tr(s2) == tr(s1 .. s2)}. When this assertion fails, wikitext markups like <nowiki>'''</nowiki> can cause wrong transliterations.
* HTML entities like <code>&apos;</code>, often used to escape wikitext markups, do not work.
]==]
function Language:transliterate(text, sc, module_override)
-- If there is no text, or the language doesn't have transliteration data and there's no override, return nil.
if not text or text == "" or text == "-" then
return text
end
-- If the script is not transliteratable (and no override is given), return nil.
sc = checkScript(text, self, sc)
if not (sc:isTransliterated() or module_override) then
-- temporary tracking to see if/when this gets triggered
track("non-transliterable")
track("non-transliterable/" .. self._code)
track("non-transliterable/" .. sc:getCode())
track("non-transliterable/" .. sc:getCode() .. "/" .. self._code)
return nil
end
-- Remove any strip markers.
text = unstrip(text)
-- Do not process the formatting into PUA characters for certain languages.
local processed = load_data(languages_data_module).substitution[self._code] ~= "none"
-- Get the display text with the keepCarets flag set.
local subbedChars
if processed then
text, subbedChars = processDisplayText(text, self, sc, true)
end
-- Transliterate (using the module override if applicable).
text, subbedChars = iterateSectionSubstitutions(self, text, sc, subbedChars, true, module_override or
self._data.translit, "translit", "tr")
if not text then
return nil
end
-- Incomplete transliterations return nil.
local charset = sc.characters
if charset and umatch(text, "[" .. charset .. "]") then
-- Remove any characters in Latin, which includes Latin characters also included in other scripts (as these are
-- false positives), as well as any PUA substitutions. Anything remaining should only be script code "None"
-- (e.g. numerals).
local check_text = ugsub(text, "[" .. get_script("Latn").characters .. "-]+", "")
-- Set none_is_last_resort_only flag, so that any non-None chars will cause a script other than "None" to be
-- returned.
if find_best_script_without_lang(check_text, true):getCode() ~= "None" then
return nil
end
end
if processed then
text = escape_risky_characters(text)
text = undoTempSubstitutions(text, subbedChars)
end
-- If the script does not use capitalization, then capitalize any letters of the transliteration which are
-- immediately preceded by a caret (and remove the caret).
if text and not sc:hasCapitalization() and text:find("^", 1, true) then
text = processCarets(text, "%^([\128-\191\244]*%*?)([^\128-\191\244][\128-\191]*)", function(m1, m2)
return m1 .. uupper(m2)
end)
end
-- Track module overrides.
if module_override ~= nil then
track("module_override")
end
return text
end
do
local function handle_language_spec(self, spec, sc)
local ret = self["_" .. spec]
if ret == nil then
ret = self._data[spec]
if type(ret) == "string" then
ret = list_to_set(split(ret, ",", true, true))
end
self["_" .. spec] = ret
end
if type(ret) == "table" then
ret = ret[sc:getCode()]
end
return not not ret
end
function Language:overrideManualTranslit(sc)
return handle_language_spec(self, "override_translit", sc)
end
function Language:link_tr(sc)
return handle_language_spec(self, "link_tr", sc)
end
end
--[==[Returns {{code|lua|true}} if the language has a transliteration module, or {{code|lua|false}} if it doesn't.]==]
function Language:hasTranslit()
return not not self._data.translit
end
--[==[Returns {{code|lua|true}} if the language uses the letters I/ı and İ/i, or {{code|lua|false}} if it doesn't.]==]
function Language:hasDottedDotlessI()
return not not self._data.dotted_dotless_i
end
function Language:toJSON(opts)
local strip_diacritics, strip_diacritics_patterns, strip_diacritics_remove_diacritics = self._data.strip_diacritics
if strip_diacritics then
if strip_diacritics.from then
strip_diacritics_patterns = {}
for i, from in ipairs(strip_diacritics.from) do
insert(strip_diacritics_patterns, {from = from, to = strip_diacritics.to[i] or ""})
end
end
strip_diacritics_remove_diacritics = strip_diacritics.remove_diacritics
end
-- mainCode should only end up non-nil if dontCanonicalizeAliases is passed to make_object().
-- props should either contain zero-argument functions to compute the value, or the value itself.
local props = {
ancestors = function() return self:getAncestorCodes() end,
canonicalName = function() return self:getCanonicalName() end,
categoryName = function() return self:getCategoryName("nocap") end,
code = self._code,
mainCode = self._mainCode,
parent = function() return self:getParentCode() end,
full = function() return self:getFullCode() end,
stripDiacriticsPatterns = strip_diacritics_patterns,
stripDiacriticsRemoveDiacritics = strip_diacritics_remove_diacritics,
family = function() return self:getFamilyCode() end,
aliases = function() return self:getAliases() end,
varieties = function() return self:getVarieties() end,
otherNames = function() return self:getOtherNames() end,
scripts = function() return self:getScriptCodes() end,
type = function() return keys_to_list(self:getTypes()) end,
wikimediaLanguages = function() return self:getWikimediaLanguageCodes() end,
wikidataItem = function() return self:getWikidataItem() end,
wikipediaArticle = function() return self:getWikipediaArticle(true) end,
}
local ret = {}
for prop, val in pairs(props) do
if not opts.skip_fields or not opts.skip_fields[prop] then
if type(val) == "function" then
ret[prop] = val()
else
ret[prop] = val
end
end
end
-- Use `deep_copy` when returning a table, so that there are no editing restrictions imposed by `mw.loadData`.
return opts and opts.lua_table and deep_copy(ret) or to_json(ret, opts)
end
function export.getDataModuleName(code)
local letter = match(code, "^(%l)%l%l?$")
return "Module:" .. (
letter == nil and "languages/data/exceptional" or
#code == 2 and "languages/data/2" or
"languages/data/3/" .. letter
)
end
get_data_module_name = export.getDataModuleName
function export.getExtraDataModuleName(code)
return get_data_module_name(code) .. "/extra"
end
get_extra_data_module_name = export.getExtraDataModuleName
do
local function make_stack(data)
local key_types = {
[2] = "unique",
aliases = "unique",
otherNames = "unique",
type = "append",
varieties = "unique",
wikipedia_article = "unique",
wikimedia_codes = "unique"
}
local function __index(self, k)
local stack, key_type = getmetatable(self), key_types[k]
-- Data that isn't inherited from the parent.
if key_type == "unique" then
local v = stack[stack[make_stack]][k]
if v == nil then
local layer = stack[0]
if layer then -- Could be false if there's no extra data.
v = layer[k]
end
end
return v
-- Data that is appended by each generation.
elseif key_type == "append" then
local parts, offset, n = {}, 0, stack[make_stack]
for i = 1, n do
local part = stack[i][k]
if part == nil then
offset = offset + 1
else
parts[i - offset] = part
end
end
return offset ~= n and concat(parts, ",") or nil
end
local n = stack[make_stack]
while true do
local layer = stack[n]
if not layer then -- Could be false if there's no extra data.
return nil
end
local v = layer[k]
if v ~= nil then
return v
end
n = n - 1
end
end
local function __newindex()
error("table is read-only")
end
local function __pairs(self)
-- Iterate down the stack, caching keys to avoid duplicate returns.
local stack, seen = getmetatable(self), {}
local n = stack[make_stack]
local iter, state, k, v = pairs(stack[n])
return function()
repeat
repeat
k = iter(state, k)
if k == nil then
n = n - 1
local layer = stack[n]
if not layer then -- Could be false if there's no extra data.
return nil
end
iter, state, k = pairs(layer)
end
until not (k == nil or seen[k])
-- Get the value via a lookup, as the one returned by the
-- iterator will be the raw value from the current layer,
-- which may not be the one __index will return for that
-- key. Also memoize the key in `seen` (even if the lookup
-- returns nil) so that it doesn't get looked up again.
-- TODO: store values in `self`, avoiding the need to create
-- the `seen` table. The iterator will need to iterate over
-- `self` with `next` first to find these on future loops.
v, seen[k] = self[k], true
until v ~= nil
return k, v
end
end
local __ipairs = require(table_module).indexIpairs
function make_stack(data)
local stack = {
data,
[make_stack] = 1, -- stores the length and acts as a sentinel to confirm a given metatable is a stack.
__index = __index,
__newindex = __newindex,
__pairs = __pairs,
__ipairs = __ipairs,
}
stack.__metatable = stack
return setmetatable({}, stack), stack
end
return make_stack(data)
end
local function get_stack(data)
local stack = getmetatable(data)
return stack and type(stack) == "table" and stack[make_stack] and stack or nil
end
--[==[
<span style="color: var(--wikt-palette-red,#BA0000)">This function is not for use in entries or other content pages.</span>
Returns a blob of data about the language. The format of this blob is undocumented, and perhaps unstable; it's intended for things like the module's own unit-tests, which are "close friends" with the module and will be kept up-to-date as the format changes. If `extra` is set, any extra data in the relevant `/extra` module will be included. (Note that it will be included anyway if it has already been loaded into the language object.) If `raw` is set, then the returned data will not contain any data inherited from parent objects.
-- Do NOT use these methods!
-- All uses should be pre-approved on the talk page!
]==]
function Language:getData(extra, raw)
if extra then
self:loadInExtraData()
end
local data = self._data
-- If raw is not set, just return the data.
if not raw then
return data
end
local stack = get_stack(data)
-- If there isn't a stack or its length is 1, return the data. Extra data (if any) will be included, as it's stored at key 0 and doesn't affect the reported length.
if stack == nil then
return data
end
local n = stack[make_stack]
if n == 1 then
return data
end
local extra = stack[0]
-- If there isn't any extra data, return the top layer of the stack.
if extra == nil then
return stack[n]
end
-- If there is, return a new stack which has the top layer at key 1 and the extra data at key 0.
data, stack = make_stack(stack[n])
stack[0] = extra
return data
end
function Language:loadInExtraData()
-- Only full languages have extra data.
if not self:hasType("language", "full") then
return
end
local data = self._data
-- If there's no stack, create one.
local stack = get_stack(self._data)
if stack == nil then
data, stack = make_stack(data)
-- If already loaded, return.
elseif stack[0] ~= nil then
return
end
self._data = data
-- Load extra data from the relevant module and add it to the stack at key 0, so that the __index and __pairs metamethods will pick it up, since they iterate down the stack until they run out of layers.
local code = self._code
local modulename = get_extra_data_module_name(code)
-- No data cached as false.
stack[0] = modulename and load_data(modulename)[code] or false
end
--[==[Returns the name of the module containing the language's data. Currently, this is always [[Module:scripts/data]].]==]
function Language:getDataModuleName()
local name = self._dataModuleName
if name == nil then
name = self:hasType("etymology-only") and etymology_languages_data_module or
get_data_module_name(self._mainCode or self._code)
self._dataModuleName = name
end
return name
end
--[==[Returns the name of the module containing the language's data. Currently, this is always [[Module:scripts/data]].]==]
function Language:getExtraDataModuleName()
local name = self._extraDataModuleName
if name == nil then
name = not self:hasType("etymology-only") and get_extra_data_module_name(self._mainCode or self._code) or false
self._extraDataModuleName = name
end
return name or nil
end
function export.makeObject(code, data, dontCanonicalizeAliases)
local data_type = type(data)
if data_type ~= "table" then
error(("bad argument #2 to 'makeObject' (table expected, got %s)"):format(data_type))
end
-- Convert any aliases.
local input_code = code
code = normalize_code(code)
input_code = dontCanonicalizeAliases and input_code or code
local parent
if data.parent then
parent = get_by_code(data.parent, nil, true, true)
else
parent = Language
end
parent.__index = parent
local lang = {_code = input_code}
-- This can only happen if dontCanonicalizeAliases is passed to make_object().
if code ~= input_code then
lang._mainCode = code
end
local parent_data = parent._data
if parent_data == nil then
-- Full code is the same as the code.
lang._fullCode = parent._code or code
else
-- Copy full code.
lang._fullCode = parent._fullCode
local stack = get_stack(parent_data)
if stack == nil then
parent_data, stack = make_stack(parent_data)
end
-- Insert the input data as the new top layer of the stack.
local n = stack[make_stack] + 1
data, stack[n], stack[make_stack] = parent_data, data, n
end
lang._data = data
return setmetatable(lang, parent)
end
make_object = export.makeObject
end
--[==[Finds the language whose code matches the one provided. If it exists, it returns a <code class="nf">Language</code> object representing the language. Otherwise, it returns {{code|lua|nil}}, unless <code class="n">paramForError</code> is given, in which case an error is generated. If <code class="n">paramForError</code> is {{code|lua|true}}, a generic error message mentioning the bad code is generated; otherwise <code class="n">paramForError</code> should be a string or number specifying the parameter that the code came from, and this parameter will be mentioned in the error message along with the bad code. If <code class="n">allowEtymLang</code> is specified, etymology-only language codes are allowed and looked up along with normal language codes. If <code class="n">allowFamily</code> is specified, language family codes are allowed and looked up along with normal language codes.]==]
function export.getByCode(code, paramForError, allowEtymLang, allowFamily)
-- Track uses of paramForError, ultimately so it can be removed, as error-handling should be done by [[Module:parameters]], not here.
if paramForError ~= nil then
track("paramForError")
end
if type(code) ~= "string" then
local typ
if not code then
typ = "nil"
elseif check_object("language", true, code) then
typ = "a language object"
elseif check_object("family", true, code) then
typ = "a family object"
else
typ = "a " .. type(code)
end
error("The function getByCode expects a string as its first argument, but received " .. typ .. ".")
end
local m_data = load_data(languages_data_module)
if m_data.aliases[code] or m_data.track[code] then
track(code)
end
local norm_code = normalize_code(code)
-- Get the data, checking for etymology-only languages if allowEtymLang is set.
local data = load_data(get_data_module_name(norm_code))[norm_code] or
allowEtymLang and load_data(etymology_languages_data_module)[norm_code]
-- If no data was found and allowFamily is set, check the family data. If the main family data was found, make the object with [[Module:families]] instead, as family objects have different methods. However, if it's an etymology-only family, use make_object in this module (which handles object inheritance), and the family-specific methods will be inherited from the parent object.
if data == nil and allowFamily then
data = load_data("Module:families/data")[norm_code]
if data ~= nil then
if data.parent == nil then
return make_family_object(norm_code, data)
elseif not allowEtymLang then
data = nil
end
end
end
local retval = code and data and make_object(code, data)
if not retval and paramForError then
require("Module:languages/errorGetBy").code(code, paramForError, allowEtymLang, allowFamily)
end
return retval
end
get_by_code = export.getByCode
--[==[Finds the language whose canonical name (the name used to represent that language on Wiktionary) or other name matches the one provided. If it exists, it returns a <code class="nf">Language</code> object representing the language. Otherwise, it returns {{code|lua|nil}}, unless <code class="n">paramForError</code> is given, in which case an error is generated. If <code class="n">allowEtymLang</code> is specified, etymology-only language codes are allowed and looked up along with normal language codes. If <code class="n">allowFamily</code> is specified, language family codes are allowed and looked up along with normal language codes.
The canonical name of languages should always be unique (it is an error for two languages on Wiktionary to share the same canonical name), so this is guaranteed to give at most one result.
This function is powered by [[Module:languages/canonical names]], which contains a pre-generated mapping of full-language canonical names to codes. It is generated by going through the [[:Category:Language data modules]] for full languages. When <code class="n">allowEtymLang</code> is specified for the above function, [[Module:etymology languages/canonical names]] may also be used, and when <code class="n">allowFamily</code> is specified for the above function, [[Module:families/canonical names]] may also be used.]==]
function export.getByCanonicalName(name, errorIfInvalid, allowEtymLang, allowFamily)
local byName = load_data("Module:languages/canonical names")
local code = byName and byName[name]
if not code and allowEtymLang then
byName = load_data("Module:etymology languages/canonical names")
code = byName and byName[name] or
byName[gsub(name, " [Ss]ubstrate$", "")] or
byName[gsub(name, "^a ", "")] or
byName[gsub(name, "^a ", ""):gsub(" [Ss]ubstrate$", "")] or
-- For etymology families like "ira-pro".
-- FIXME: This is not ideal, as it allows " languages" to be appended to any etymology-only language, too.
byName[match(name, "^(.*) languages$")]
end
if not code and allowFamily then
byName = load_data("Module:families/canonical names")
code = byName[name] or byName[match(name, "^(.*) languages$")]
end
local retval = code and get_by_code(code, errorIfInvalid, allowEtymLang, allowFamily)
if not retval and errorIfInvalid then
require("Module:languages/errorGetBy").canonicalName(name, allowEtymLang, allowFamily)
end
return retval
end
--[==[Used by [[Module:languages/data/2]] (et al.) and [[Module:etymology languages/data]], [[Module:families/data]], [[Module:scripts/data]] and [[Module:writing systems/data]] to finalize the data into the format that is actually returned.]==]
function export.finalizeData(data, main_type, variety)
local fields = {"type"}
if main_type == "language" then
insert(fields, 4) -- script codes
insert(fields, "ancestors")
insert(fields, "link_tr")
insert(fields, "override_translit")
insert(fields, "wikimedia_codes")
elseif main_type == "script" then
insert(fields, 3) -- writing system codes
end -- Families and writing systems have no extra fields to process.
local fields_len = #fields
for _, entity in next, data do
if variety then
-- Move parent from 3 to "parent" and family from "family" to 3. These are different for the sake of convenience, since very few varieties have the family specified, whereas all of them have a parent.
entity.parent, entity[3], entity.family = entity[3], entity.family
-- Give the type "regular" iff not a variety and no other types are assigned.
elseif not (entity.type or entity.parent) then
entity.type = "regular"
end
for i = 1, fields_len do
local key = fields[i]
local field = entity[key]
if field and type(field) == "string" then
entity[key] = gsub(field, "%s*,%s*", ",")
end
end
end
return data
end
--[==[For backwards compatibility only; modules should require the error themselves.]==]
function export.err(lang_code, param, code_desc, template_tag, not_real_lang)
return require("Module:languages/error")(lang_code, param, code_desc, template_tag, not_real_lang)
end
return export
278qio2ki35dtgm22th3ft9t3fyumb7
gasan
0
3059
26488
19531
2026-07-07T01:00:24Z
Ezagren
26
26488
wikitext
text/x-wiki
=={{basa|bjn}}==
{{kapala|bjn}}
: {{suara|bjn|LL-Q33151 (bjn)-Volstand-asan.wav|q=Banjar Hulu}}
: {{suara|bjn|LL-Q33151 (bjn)-Muhammad Faisal Ansari-gasan.wav|q=Banjar Kuala}}
: {{punggalan|bjn|ga|san}}
{{-ragam-}}
* [[asan]] (''Banjar Hulu'')
{{-pron-|bjn}}
# kata muka nang batujuan gasan manyataakan urang tu mambaari, manjulung, wan nang lainnya
#: ''yang ngini '''gasan''' ikam''.
# tujuan atawa maksud
#: ''Ulun datang ka sini '''gasan''' malamar Pian''.
# sawagai gagantian
#: ''dijulung lading '''gasan''' sanjata''.
{{-terjemahan-}}
* Basa Indunisia: [[untuk]]; [[demi]] (p)
[[Tumbung:WikiPandir]]
[[Tumbung:Lema Banjar Kuala]]
3qpfxilxxqormzpmmezc4h9tki5xnek
Modul:array
828
3564
26495
7645
2025-11-23T11:58:51Z
id>Swarabakti
0
26495
Scribunto
text/plain
local export = {}
local debug_track_module = "Modul:debug/track"
local function_module = "Modul:fun"
local table_module = "Modul:table"
local get_array_mt -- Defined below.
local getmetatable = getmetatable
local ipairs = ipairs
local pairs = pairs
local rawget = rawget
local rawset = rawset
local require = require
local select = select
local setmetatable = setmetatable
local sort = table.sort
local type = type
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local upper = string.upper
local array_mt -- Defined below.
--[==[
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 append(...)
append = require(table_module).append
return append(...)
end
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function deep_copy(...)
deep_copy = require(table_module).deepCopy
return deep_copy(...)
end
local function list_to_set(...)
list_to_set = require(table_module).listToSet
return list_to_set(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
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 m_function
local function get_m_function()
m_function, get_m_function = require(function_module), nil
return m_function
end
local m_table
local function get_m_table()
m_table, get_m_table = require(table_module), nil
return m_table
end
-- Functions from [[Module:table]] that operate on arrays or sparse arrays.
-- List copied from [[Module:table/documentation]].
local m_table_array_funcs
local function get_m_table_array_funcs()
m_table_array_funcs = list_to_set{
-- non-sparse
"signedIndex", "append", "extend", "extendIfNot", "slice", "removeDuplicates", "length",
"size", "contains", "serialCommaJoin", "reverseIpairs", "reverse",
"invert", "listToSet", "flatten", "isArray",
-- sparse
"numKeys", "maxIndex", "compressSparseArray", "indexPairs", "indexIpairs",
"sparseIpairs",
-- tables in general
"shallowCopy", "deepCopy"
}
get_m_table_array_funcs = nil
return m_table_array_funcs
end
-- Functions from [[Module:fun]] that take an array in the second argument.
-- They just have to have the argument order reversed to work as methods of the
-- array object.
local m_function_array_funcs
local function get_m_function_array_funcs()
m_function_array_funcs = list_to_set{
"map", "some", "all", "filter", "fold"
}
get_m_function_array_funcs = nil
return m_function_array_funcs
end
-- Functions from [[Module:table]] that create an array or table.
-- Not all of these operate on arrays.
local m_table_new_array_funcs
local function get_m_table_new_array_funcs()
m_table_new_array_funcs = list_to_set{
-- Array.
"append", "slice", "removeDuplicates", "numKeys", "compressSparseArray",
"keysToList", "reverse", "flatten",
-- Array or table.
"shallowCopy", "deepCopy"
}
get_m_table_new_array_funcs = nil
return m_table_new_array_funcs
end
-- Functions from [[Module:fun]] that create an array or table.
-- Not all of these operate on arrays.
local m_function_new_array_funcs
local function get_m_function_new_array_funcs()
m_function_new_array_funcs = list_to_set{
"map", "filter",
}
get_m_function_new_array_funcs = nil
return m_function_new_array_funcs
end
-- Add aliases for the functions from [[Module:table]] whose names
-- contain "array" or "list", which is redundant.
-- The key redirects to the value.
local alias_of = {
compress = "compressSparseArray",
keys = "keysToList",
toSet = "listToSet",
}
local function underscore_to_camel_case(str)
if type(str) ~= "string" then
return str
end
local ret = str:gsub("_(.)", upper)
if ret ~= str then
debug_track("array/underscore to camel case")
end
return ret
end
local function get_module_function(key, module, module_name)
return module[key] or
error(("Cannot find %s in [[Module:%s]]"):format(mw.dumpObject(key), module_name))
end
local function wrap_in_array_constructor(func)
return function (...)
return setmetatable(func(...), array_mt or get_array_mt())
end
end
function get_array_mt()
-- Copy table library so as not to unexpectedly change the behavior of code that
-- uses it.
local Array = deep_copy(table)
Array.ipairs = ipairs
Array.pairs = pairs
Array.unpack = unpack
Array.listToText = mw.text.listToText
-- Create version of table.sort that returns the table.
function Array:sort(comp)
sort(self, comp)
return self
end
function Array:type()
local mt = getmetatable(self)
return mt and type(mt) == "table" and rawget(mt, "__type") or nil
end
local Array_mt = {}
setmetatable(Array, Array_mt)
function Array_mt:__index(key)
if type(key) ~= "string" then
return nil
end
-- Convert underscores to camel case: num_keys -> numKeys.
-- FIXME: this is pointless overhead: remove once nothing relies on it.
key = underscore_to_camel_case(key)
key = alias_of[key] or key
local func = rawget(self, key)
if func ~= nil then
return func
elseif (m_table_array_funcs or get_m_table_array_funcs())[key] then
func = get_module_function(key, m_table or get_m_table(), "table")
if (m_table_new_array_funcs or get_m_table_new_array_funcs())[key] then
func = wrap_in_array_constructor(func)
end
elseif (m_function_array_funcs or get_m_function_array_funcs())[key] then
local raw_func = get_module_function(key, m_function or get_m_function(), "fun")
--[==[ Once isArray is no longer used:
function func(a, b, ...)
return raw_func(b, a, ...)
end
]==]
if key == "fold" then
function func(t, f, accum)
return raw_func(f, t, accum)
end
else
function func(a, b) -- TODO: isArray parameter is probably unnecessary, and doesn't work with sparse arrays anyway.
debug_track("array/isArray")
return raw_func(b, a, "isArray")
end
end
if (m_function_new_array_funcs or get_m_function_new_array_funcs())[key] then
func = wrap_in_array_constructor(func)
end
else
return nil
end
rawset(Array, key, func)
return func
end
array_mt = {
__index = Array,
__type = "array",
}
function array_mt:__add(v)
return setmetatable(append(self, v), array_mt or get_array_mt())
end
get_array_mt = nil
return array_mt
end
-- A function to convert string key-table modules such
-- as [[Module:languages/data/2]] into arrays.
-- "from" is a bad name.
-- field_for_key supplies the field name in which the
-- key will be stored.
function export.from(map, field_for_key)
local arr, i = {}, 0
for key, val in pairs(map) do
i = i + 1
local new_val = shallow_copy(val)
if field_for_key then
new_val[field_for_key] = key
end
arr[i] = new_val
end
return setmetatable(arr, array_mt or get_array_mt())
end
local export_mt = {}
function export_mt:__call(...)
local arr
if select("#", ...) == 1 and type((...)) == "table" then
arr = ...
local mt = getmetatable(arr)
-- If table has been loaded with mw.loadData, copy it to avoid the
-- limitations of it being a virtual table.
if mt and type(mt) == "table" and rawget(mt, "mw_loadData") == true then
arr = shallow_copy(arr)
end
else
arr = {...}
end
return setmetatable(arr, array_mt or get_array_mt())
end
function export_mt:__index(key)
-- Convert underscores to camel case: num_keys -> numKeys.
-- FIXME: this is pointless overhead: remove once nothing relies on it.
key = underscore_to_camel_case(key)
key = alias_of[key] or key
local func = rawget(self, key)
if func ~= nil then
return func
elseif (m_table_new_array_funcs or get_m_table_new_array_funcs())[key] then
func = get_module_function(key, m_table or get_m_table(), "table")
elseif (m_function_new_array_funcs or get_m_function_new_array_funcs())[key] then
func = get_module_function(key, m_function or get_m_function(), "fun")
else
return nil
end
func = wrap_in_array_constructor(func)
rawset(export, key, func)
return func
end
return setmetatable(export, export_mt)
l9c1qufi64pu4wnsf0xz5l9yayed5ja
26496
26495
2026-07-07T09:55:56Z
Sibiru45
115
1 ralatan matan [[:id:Modul:array]]
26495
Scribunto
text/plain
local export = {}
local debug_track_module = "Modul:debug/track"
local function_module = "Modul:fun"
local table_module = "Modul:table"
local get_array_mt -- Defined below.
local getmetatable = getmetatable
local ipairs = ipairs
local pairs = pairs
local rawget = rawget
local rawset = rawset
local require = require
local select = select
local setmetatable = setmetatable
local sort = table.sort
local type = type
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local upper = string.upper
local array_mt -- Defined below.
--[==[
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 append(...)
append = require(table_module).append
return append(...)
end
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function deep_copy(...)
deep_copy = require(table_module).deepCopy
return deep_copy(...)
end
local function list_to_set(...)
list_to_set = require(table_module).listToSet
return list_to_set(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
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 m_function
local function get_m_function()
m_function, get_m_function = require(function_module), nil
return m_function
end
local m_table
local function get_m_table()
m_table, get_m_table = require(table_module), nil
return m_table
end
-- Functions from [[Module:table]] that operate on arrays or sparse arrays.
-- List copied from [[Module:table/documentation]].
local m_table_array_funcs
local function get_m_table_array_funcs()
m_table_array_funcs = list_to_set{
-- non-sparse
"signedIndex", "append", "extend", "extendIfNot", "slice", "removeDuplicates", "length",
"size", "contains", "serialCommaJoin", "reverseIpairs", "reverse",
"invert", "listToSet", "flatten", "isArray",
-- sparse
"numKeys", "maxIndex", "compressSparseArray", "indexPairs", "indexIpairs",
"sparseIpairs",
-- tables in general
"shallowCopy", "deepCopy"
}
get_m_table_array_funcs = nil
return m_table_array_funcs
end
-- Functions from [[Module:fun]] that take an array in the second argument.
-- They just have to have the argument order reversed to work as methods of the
-- array object.
local m_function_array_funcs
local function get_m_function_array_funcs()
m_function_array_funcs = list_to_set{
"map", "some", "all", "filter", "fold"
}
get_m_function_array_funcs = nil
return m_function_array_funcs
end
-- Functions from [[Module:table]] that create an array or table.
-- Not all of these operate on arrays.
local m_table_new_array_funcs
local function get_m_table_new_array_funcs()
m_table_new_array_funcs = list_to_set{
-- Array.
"append", "slice", "removeDuplicates", "numKeys", "compressSparseArray",
"keysToList", "reverse", "flatten",
-- Array or table.
"shallowCopy", "deepCopy"
}
get_m_table_new_array_funcs = nil
return m_table_new_array_funcs
end
-- Functions from [[Module:fun]] that create an array or table.
-- Not all of these operate on arrays.
local m_function_new_array_funcs
local function get_m_function_new_array_funcs()
m_function_new_array_funcs = list_to_set{
"map", "filter",
}
get_m_function_new_array_funcs = nil
return m_function_new_array_funcs
end
-- Add aliases for the functions from [[Module:table]] whose names
-- contain "array" or "list", which is redundant.
-- The key redirects to the value.
local alias_of = {
compress = "compressSparseArray",
keys = "keysToList",
toSet = "listToSet",
}
local function underscore_to_camel_case(str)
if type(str) ~= "string" then
return str
end
local ret = str:gsub("_(.)", upper)
if ret ~= str then
debug_track("array/underscore to camel case")
end
return ret
end
local function get_module_function(key, module, module_name)
return module[key] or
error(("Cannot find %s in [[Module:%s]]"):format(mw.dumpObject(key), module_name))
end
local function wrap_in_array_constructor(func)
return function (...)
return setmetatable(func(...), array_mt or get_array_mt())
end
end
function get_array_mt()
-- Copy table library so as not to unexpectedly change the behavior of code that
-- uses it.
local Array = deep_copy(table)
Array.ipairs = ipairs
Array.pairs = pairs
Array.unpack = unpack
Array.listToText = mw.text.listToText
-- Create version of table.sort that returns the table.
function Array:sort(comp)
sort(self, comp)
return self
end
function Array:type()
local mt = getmetatable(self)
return mt and type(mt) == "table" and rawget(mt, "__type") or nil
end
local Array_mt = {}
setmetatable(Array, Array_mt)
function Array_mt:__index(key)
if type(key) ~= "string" then
return nil
end
-- Convert underscores to camel case: num_keys -> numKeys.
-- FIXME: this is pointless overhead: remove once nothing relies on it.
key = underscore_to_camel_case(key)
key = alias_of[key] or key
local func = rawget(self, key)
if func ~= nil then
return func
elseif (m_table_array_funcs or get_m_table_array_funcs())[key] then
func = get_module_function(key, m_table or get_m_table(), "table")
if (m_table_new_array_funcs or get_m_table_new_array_funcs())[key] then
func = wrap_in_array_constructor(func)
end
elseif (m_function_array_funcs or get_m_function_array_funcs())[key] then
local raw_func = get_module_function(key, m_function or get_m_function(), "fun")
--[==[ Once isArray is no longer used:
function func(a, b, ...)
return raw_func(b, a, ...)
end
]==]
if key == "fold" then
function func(t, f, accum)
return raw_func(f, t, accum)
end
else
function func(a, b) -- TODO: isArray parameter is probably unnecessary, and doesn't work with sparse arrays anyway.
debug_track("array/isArray")
return raw_func(b, a, "isArray")
end
end
if (m_function_new_array_funcs or get_m_function_new_array_funcs())[key] then
func = wrap_in_array_constructor(func)
end
else
return nil
end
rawset(Array, key, func)
return func
end
array_mt = {
__index = Array,
__type = "array",
}
function array_mt:__add(v)
return setmetatable(append(self, v), array_mt or get_array_mt())
end
get_array_mt = nil
return array_mt
end
-- A function to convert string key-table modules such
-- as [[Module:languages/data/2]] into arrays.
-- "from" is a bad name.
-- field_for_key supplies the field name in which the
-- key will be stored.
function export.from(map, field_for_key)
local arr, i = {}, 0
for key, val in pairs(map) do
i = i + 1
local new_val = shallow_copy(val)
if field_for_key then
new_val[field_for_key] = key
end
arr[i] = new_val
end
return setmetatable(arr, array_mt or get_array_mt())
end
local export_mt = {}
function export_mt:__call(...)
local arr
if select("#", ...) == 1 and type((...)) == "table" then
arr = ...
local mt = getmetatable(arr)
-- If table has been loaded with mw.loadData, copy it to avoid the
-- limitations of it being a virtual table.
if mt and type(mt) == "table" and rawget(mt, "mw_loadData") == true then
arr = shallow_copy(arr)
end
else
arr = {...}
end
return setmetatable(arr, array_mt or get_array_mt())
end
function export_mt:__index(key)
-- Convert underscores to camel case: num_keys -> numKeys.
-- FIXME: this is pointless overhead: remove once nothing relies on it.
key = underscore_to_camel_case(key)
key = alias_of[key] or key
local func = rawget(self, key)
if func ~= nil then
return func
elseif (m_table_new_array_funcs or get_m_table_new_array_funcs())[key] then
func = get_module_function(key, m_table or get_m_table(), "table")
elseif (m_function_new_array_funcs or get_m_function_new_array_funcs())[key] then
func = get_module_function(key, m_function or get_m_function(), "fun")
else
return nil
end
func = wrap_in_array_constructor(func)
rawset(export, key, func)
return func
end
return setmetatable(export, export_mt)
l9c1qufi64pu4wnsf0xz5l9yayed5ja
Modul:parameters
828
3568
26501
23985
2026-04-28T15:13:10Z
id>Swarabakti
0
26501
Scribunto
text/plain
--[==[TODO:
* Change certain flag names, as some are misnomers:
* Change `allow_holes` to `keep_holes`, because it's not the inverse of `disallow_holes`.
* Change `allow_empty` to `keep_empty`, as it causes them to be kept as "" instead of deleted.
* Sort out all the internal error calls. Manual error(format()) calls are used when certain parameters shouldn't be dumped, so find a way to avoid that.
]==]
local export = {}
local collation_module = "Module:collation"
local families_module = "Module:families"
local functions_module = "Module:fun"
local gender_and_number_utilities_module = "Module:gender and number utilities"
local labels_module = "Module:labels"
local languages_module = "Module:languages"
local math_module = "Module:math"
local pages_module = "Module:pages"
local parameters_finalize_set_module = "Module:parameters/finalizeSet"
local parameters_track_module = "Module:parameters/track"
local parse_utilities_module = "Module:parse utilities"
local references_module = "Module:references"
local scribunto_module = "Module:Scribunto"
local scripts_module = "Module:scripts"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local wikimedia_languages_module = "Module:wikimedia languages"
local yesno_module = "Module:yesno"
local mw = mw
local mw_title = mw.title
local string = string
local table = table
local dump = mw.dumpObject
local find = string.find
local format = string.format
local gsub = string.gsub
local insert = table.insert
local ipairs = ipairs
local list_to_text = mw.text.listToText
local make_title = mw_title.makeTitle
local match = string.match
local max = math.max
local new_title = mw_title.new
local next = next
local pairs = pairs
local pcall = pcall
local require = require
local sub = string.sub
local tonumber = tonumber
local type = type
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local current_title_text, current_namespace, sets -- Defined when needed.
local namespaces = mw.site.namespaces
--[==[
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 decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function extend(...)
extend = require(table_module).extend
return extend(...)
end
local function finalize_set(...)
finalize_set = require(parameters_finalize_set_module)
return finalize_set(...)
end
local function get_family_by_code(...)
get_family_by_code = require(families_module).getByCode
return get_family_by_code(...)
end
local function get_family_by_name(...)
get_family_by_name = require(families_module).getByCanonicalName
return get_family_by_name(...)
end
local function get_language_by_code(...)
get_language_by_code = require(languages_module).getByCode
return get_language_by_code(...)
end
local function get_language_by_name(...)
get_language_by_name = require(languages_module).getByCanonicalName
return get_language_by_name(...)
end
local function get_script_by_code(...)
get_script_by_code = require(scripts_module).getByCode
return get_script_by_code(...)
end
local function get_script_by_name(...)
get_script_by_name = require(scripts_module).getByCanonicalName
return get_script_by_name(...)
end
local function get_wm_lang_by_code(...)
get_wm_lang_by_code = require(wikimedia_languages_module).getByCode
return get_wm_lang_by_code(...)
end
local function get_wm_lang_by_code_with_fallback(...)
get_wm_lang_by_code_with_fallback = require(wikimedia_languages_module).getByCodeWithFallback
return get_wm_lang_by_code_with_fallback(...)
end
local function gsplit(...)
gsplit = require(string_utilities_module).gsplit
return gsplit(...)
end
local function is_callable(...)
is_callable = require(functions_module).is_callable
return is_callable(...)
end
local function is_integer(...)
is_integer = require(math_module).is_integer
return is_integer(...)
end
local function is_internal_title(...)
is_internal_title = require(pages_module).is_internal_title
return is_internal_title(...)
end
local function is_positive_integer(...)
is_positive_integer = require(math_module).is_positive_integer
return is_positive_integer(...)
end
local function iterate_list(...)
iterate_list = require(table_module).iterateList
return iterate_list(...)
end
local function num_keys(...)
num_keys = require(table_module).numKeys
return num_keys(...)
end
local function parse_gender_and_number_spec(...)
parse_gender_and_number_spec = require(gender_and_number_utilities_module).parse_gender_and_number_spec
return parse_gender_and_number_spec(...)
end
local function parse_references(...)
parse_references = require(references_module).parse_references
return parse_references(...)
end
local function pattern_escape(...)
pattern_escape = require(string_utilities_module).pattern_escape
return pattern_escape(...)
end
local function php_trim(...)
php_trim = require(scribunto_module).php_trim
return php_trim(...)
end
local function scribunto_parameter_key(...)
scribunto_parameter_key = require(scribunto_module).scribunto_parameter_key
return scribunto_parameter_key(...)
end
local function sort(...)
sort = require(collation_module).sort
return sort(...)
end
local function sorted_pairs(...)
sorted_pairs = require(table_module).sortedPairs
return sorted_pairs(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function split_labels_on_comma(...)
split_labels_on_comma = require(labels_module).split_labels_on_comma
return split_labels_on_comma(...)
end
local function split_on_comma(...)
split_on_comma = require(parse_utilities_module).split_on_comma
return split_on_comma(...)
end
local function tonumber_extended(...)
tonumber_extended = require(math_module).tonumber_extended
return tonumber_extended(...)
end
local function track(...)
track = require(parameters_track_module)
return track(...)
end
local function yesno(...)
yesno = require(yesno_module)
return yesno(...)
end
--[==[ intro:
This module is used to standardize template argument processing and checking. A typical workflow is as follows (based
on [[Module:translations]]):
{
...
local parent_args = frame:getParent().args
local params = {
[1] = {required = true, type = "language", default = "und"},
[2] = true,
[3] = {list = true},
["alt"] = true,
["id"] = true,
["sc"] = {type = "script"},
["tr"] = true,
["ts"] = true,
["lit"] = true,
}
local args = require("Module:parameters").process(parent_args, params)
-- Do further processing of the parsed arguments in `args`.
...
}
The `params` table should have the parameter names as the keys, and a (possibly empty) table of parameter tags as the
value. An empty table as the value merely states that the parameter exists, but should not receive any special
treatment; if desired, empty tables can be replaced with the value `true` as a perforamnce optimization.
Possible parameter tags are listed below:
; {required = true}
: The parameter is required; an error is shown if it is not present. The template's page itself is an exception; no
error is shown there.
; {default =}
: Specifies a default input value for the parameter, if it is absent or empty. This will be processed as though it were
the input instead, so (for example) {default = "und"} with the type {"language"} will return a language object for
[[:Category:Undetermined language|Undetermined language]] if no language code is provided. When used on list
parameters, this specifies a default value for the first item in the list only. Note that it is not possible to
generate a default that depends on the value of other parameters. If used together with {required = true}, the default
applies only to template pages (see the following entry), as a side effect of the fact that "required" parameters
aren't actually required on template pages. This can be used to show an example of the template in action when the
template page is visited; however, it is preferred to use `template_default` for this purpose, for clarity.
; {template_default =}
: Specifies a default input value for absent or empty parameters only on the template demo invocation (the invocation of
the template that is displayed when the template page that implements the template is viewed). Template pages are
pages in template space that invoke (through {{tl|#invoke:}}) the module that implements the template and calls
[[Module:parameters]]. For example, the page [[Template:en-noun]] implements the {{tl|en-noun}} template, which in
turn invokes [[Module:en-headword]], and is a template page for [[Module:en-headword]]. When the template page
[[Template:en-noun]] is visited, the {{tl|#invoke:}} of the template's module is expanded as if the template were
called without arguments, and the output is inserted at that point into the processed page. This output serves as a
sort of demo of the template's functionality. `template_default` can be used to supply default values for use only in
this demo. Since the template page may also contain other invocations of the same template (e.g. on the template's
documentation page, which is typically transcluded into the template page itself), `template_default` does not apply
if there are any arguments passed to the template or if the template is invoked on any other page but its own template
page (which is checked by comparing the name of the invoking template to the current pagename). Both
`template_default` and `default` can be specified for the same parameter. If this is done, `template_default` applies
for the argumentless template invocation on the template page, and `default` in all other circumstances As an example,
{{tl|cs-IPA}} uses the equivalent of {[1] = {default = "+", template_default = "příklad"}} to supply a default of
{"+"} for mainspace and documentation pages (which tells the module to use the value of the {{para|pagename}}
parameter, falling back to the actual pagename), but {"příklad"} (which means "example"), on [[Template:cs-IPA]].
; {alias_of =}
: Treat the parameter as an alias of another. When arguments are specified for this parameter, they will automatically
be renamed and stored under the alias name. This allows for parameters with multiple alternative names, while still
treating them as if they had only one name. The conversion-related properties of an aliased parameter (e.g. `type`,
`set`, `convert`, `sublist`) are taken from the aliasee, and the corrresponding properties set on the alias itself
are ignored; but other properties on the alias are taken from the alias's spec and not from the aliasee's spec. This
means, for example, that if you create an alias of a list parameter, the alias must also specify the `list` property
or it is not a list. (In such a case, a value specified for the alias goes into the first item of the aliasee's list.
You cannot make a list alias of a non-list parameter; this causes an error to be thrown.) Similarly, if you specify
`separate_no_index` on an aliasee but not on the alias, uses of the unindexed aliasee parameter are stored into the
`.default` key, but uses of the unindexed alias are stored into the first numbered key of the aliasee's list.
Aliases cannot be required, as this prevents the other name or names of the parameter from being used. Parameters
that are aliases and required at the same time cause an error to be thrown.
; {allow_empty = true}
: If the argument is an empty string value, it is not converted to {nil}, but kept as-is. The use of `allow_empty` is
disallowed if a type has been specified, and causes an error to be thrown.
; {no_trim = true}
: Spacing characters such as spaces and newlines at the beginning and end of a positional parameter are not removed.
(MediaWiki itself automatically trims spaces and newlines at the edge of named parameters.) The use of `no_trim` is
disallowed if a type has been specified, and causes an error to be thrown.
; {type =}
: Specifies what value type to convert the argument into. The default is to leave it as a text string. Alternatives are:
:; {type = "boolean"}
:: The value is treated as a boolean value, either true or false. No value, the empty string, and the strings {"0"},
{"no"}, {"n"}, {"false"}, {"f"} and {"off"} are treated as {false}, all other values are considered {true}.
:; {type = "number"}
:: The value is converted into a number, and throws an error if the value is not parsable as a number. Input values may
be signed (`+` or `-`), and may contain decimal points and leading zeroes. If {allow_hex = true}, then hexadecimal
values in the form {"0x100"} may optionally be used instead, which otherwise have the same syntax restrictions
(including signs, decimal digits, and leading zeroes after {"0x"}). Hexadecimal inputs are not case-sensitive. Lua's
special number values (`inf` and `nan`) are not possible inputs.
:; {type = "range"}
:: The value is interpreted as a hyphen-separated range of two numbers (e.g. {"2-4"} is interpreted as the range from
{2} to {4}). A number input without a hyphen is interpreted as a range from that number to itself (e.g. the input {"1"} is interpreted as the range from {1} to {1}). Any optional flags which are available for numbers will also work for ranges.
:; {type = "language"}
:: The value is interpreted as a full or [[Wiktionary:Languages#Etymology-only languages|etymology-only language]] code
language code (or name, if {method = "name"}) and converted into the corresponding object (see [[Module:languages]]).
If the code or name is invalid, then an error is thrown. The additional setting {family = true} can be given to allow
[[Wiktionary:Language families|language family codes]] to be considered valid and the corresponding object returned.
Note that to distinguish an etymology-only language object from a full language object, use
{object:hasType("language", "etymology-only")}.
:; {type = "full language"}
:: The value is interpreted as a full language code (or name, if {method = "name"}) and converted into the corresponding
object (see [[Module:languages]]). If the code or name is invalid, then an error is thrown. Etymology-only languages
are not allowed. The additional setting {family = true} can be given to allow
[[Wiktionary:Language families|language family codes]] to be considered valid and the corresponding object returned.
:; {type = "Wikimedia language"}
:: The value is interpreted as a code and converted into a Wikimedia language object. If the code is invalid, then an
error is thrown. If {fallback = true} is specified, conventional language codes which are different from their
Wikimedia equivalent will also be accepted as a fallback.
:; {type = "family"}
:: The value is interpreted as a language family code (or name, if {method = "name"}) and converted into the
corresponding object (see [[Module:families]]). If the code or name is invalid, then an error is thrown.
:; {type = "script"}
:: The value is interpreted as a script code (or name, if {method = "name"}) and converted into the corresponding object
(see [[Module:scripts]]). If the code or name is invalid, then an error is thrown.
:; {type = "title"}
:: The value is interpreted as a page title and converted into the corresponding object (see the
[[mw:Extension:Scribunto/Lua_reference_manual#Title_library|Title library]]). If the page title is invalid, then an
error is thrown; by default, external titles (i.e. those on other wikis) are not treated as valid. Options are:
::; {namespace = n}
::: The default namespace, where {n} is a namespace number; this is treated as {0} (the mainspace) if not specified.
::; {allow_external = true}
::: External titles are treated as valid.
::; {prefix = "namespace override"} (default)
::: The default namespace prefix will be prefixed to the value is already prefixed by a namespace prefix. For instance,
the input {"Foo"} with namespace {10} returns {"Template:Foo"}, {"Wiktionary:Foo"} returns {"Wiktionary:Foo"}, and
{"Template:Foo"} returns {"Template:Foo"}. Interwiki prefixes cannot act as overrides, however: the input {"fr:Foo"}
returns {"Template:fr:Foo"}.
::; {prefix = "force"}
::: The default namespace prefix will be prefixed unconditionally, even if the value already appears to be prefixed.
This is the way that {{tl|#invoke:}} works when calling modules from the module namespace ({828}): the input {"Foo"}
returns {"Module:Foo"}, {"Wiktionary:Foo"} returns {"Module:Wiktionary:Foo"}, and {"Module:Foo"} returns
{"Module:Module:Foo"}.
::; {prefix = "full override"}
::: The same as {prefix = "namespace override"}, except that interwiki prefixes can also act as overrides. For instance,
{"el:All topics"} with namespace {14} returns {"el:Category:All topics"}. Due to the limitations of MediaWiki, only
the first prefix in the value may act as an override, so the namespace cannot be overridden if the first prefix is
an interwiki prefix: e.g. {"el:Template:All topics"} with namespace {14} returns {"el:Category:Template:All topics"}.
:; {type = "parameter"}
:: The value is interpreted as the name of a parameter, and will be normalized using the method that Scribunto uses when
constructing a {frame.args} table of arguments. This means that integers will be converted to numbers, but all other
arguments will remain as strings (e.g. {"1"} will be normalized to {1}, but {"foo"} and {"1.5"} will remain
unchanged). Note that Scribunto also trims parameter names, following the same trimming method that this module
applies by default to all parameter types.
:: This type is useful when one set of input arguments is used to construct a {params} table for use in a subsequent
{export.process()} call with another set of input arguments; for instance, the set of valid parameters for a template
might be defined as {{tl|#invoke:[some module]|args=}} in the template, where {args} is a sublist of valid parameters
for the template.
:; {type = "qualifier"}
:: The value is interpreted as a qualifier and converted into the correct format for passing into `format_qualifiers()`
in [[Module:qualifier]] (which currently just means converting it to a one-item list).
:; {type = "labels"}
:: The value is interpreted as a comma-separated list of labels and converted into the correct format for passing into
`show_labels()` in [[Module:labels]] (which is currently a list of strings). Splitting is done on commas not followed
by whitespace, except that commas inside of double angle brackets do not count even if not followed by whitespace.
This type should be used by for normal labels (typically specified using {{para|l}} or {{para|ll}}) and accent
qualifiers (typically specified using {{para|a}} and {{para|aa}}).
:; {type = "references"}
:: The value is interpreted as one or more references, in the format prescribed by `parse_references()` in
[[Module:references]], and converted into a list of objects of the form accepted by `format_references()` in the same
module. If a syntax error is found in the reference format, an error is thrown.
:; {type = "genders"}
:: The value is interpreted as one or more comma-separated gender/number specs, in the format prescribed by
[[Module:gender and number]]. Inline modifiers (`<q:...>`, `<qq:...>`, `<l:...>`, `<ll:...>` or `<ref:...>`) may be
attached to a gender/number spec.
:; {type = "form of tags"}
:: The value is interpreted as an ampersand-separated list of grammar tags and converted into the correct format
for passing as `tags` into `tagged_inflections()` in [[Module:form of]] (which is currently a list of strings).
Splitting is always done by ampersands. This type should be used by for inflection qualifiers that act as
grammar tags (typically specified using {{para|infl}}).
:; {type = function(val) ... end}
:: `type` may be set to a function (or callable table), which must take the argument value as its sole argument, and must
output one of the other recognized types. This is particularly useful for lists (see below), where certain values need
to be interpreted differently to others.
; {list =}
: Treat the parameter as a list of values, each having its own parameter name, rather than a single value. The
parameters will have a number at the end, except optionally for the first (but see also {require_index = true}). For
example, {list = true} on a parameter named "head" will include the parameters {{para|head}} (or {{para|head1}}),
{{para|head2}}, {{para|head3}} and so on. If the parameter name is a number, another number doesn't get appended, but
the counting simply continues, e.g. for parameter {3} the sequence is {{para|3}}, {{para|4}}, {{para|5}} etc. List
parameters are returned as numbered lists, so for a template that is given the parameters `|head=a|head2=b|head3=c`,
the processed value of the parameter {"head"} will be { { "a", "b", "c" }}}.
: The value for {list =} can also be a string. This tells the module that parameters other than the first should have a
different name, which is useful when the first parameter in a list is a number, but the remainder is named. An example
would be for genders: {list = "g"} on a parameter named {1} would have parameters {{para|1}}, {{para|g2}}, {{para|g3}}
etc.
: If the number is not located at the end, it can be specified by putting {"\1"} at the number position. For example,
parameters {{para|f1accel}}, {{para|f2accel}}, ... can be captured by using the parameter name {"f\1accel"}, as is
done in [[Module:headword/templates]].
; {set =}
: Require that the value of the parameter be one of the specified values (or omitted, if {required = true} isn't given).
Two formats are allowed; either a list of possible values can be supplied, or a table can be supplied where the keys
are allowed values and the values are either `true` or a string naming a value found elsewhere in the table as a key.
In the latter case, the key is an alias and the value is the canonical value, and if the user uses the alias, it will
automatically be mapped to the canonical value. In such a case, the canonical value cannot itself be an alias. The use
of `set` is disallowed if {type = "boolean"} and causes an error to be thrown.
; {sublist =}
: The value of the parameter is a delimiter-separated list of individual raw values. The resulting field in `args` will
be a Lua list (i.e. a table with numeric indices) of the converted values. If {sublist = true} is given, the values
will be split on commas (possibly with whitespace on one or both sides of the comma, which is ignored). If
{sublist = "comma without whitespace"} is given, the values will be split on commas which are not followed by whitespace,
and which aren't preceded by an escaping backslash. Otherwise, the value of `sublist` should be either a Lua pattern
specifying the delimiter(s) to split on or a function (or callable table) to do the splitting, which is passed two values
(the value to split and a function to signal an error) and should return a list of the split values.
; {convert =}
: If given, this specifies a function (or callable table) to convert the raw parameter value into the Lua object used
during further processing. The function is passed two arguments, the raw parameter value itself and a function used to
signal an error during parsing or conversion, and should return one value, the converted parameter. The error-signaling
function contains the name and raw value of the parameter embedded into the message it generates, so these do not need to
specified in the message passed into it. If `type` is specified in conjunction with `convert`, the processing by
`type` happens first. If `sublist` is given in conjunction with `convert`, the raw parameter value will be split
appropriately and `convert` called on each resulting item.
; {allow_hex = true}
: When used in conjunction with {type = "number"}, allows hexadecimal numbers as inputs, in the format {"0x100"} (which is
not case-sensitive).
; {family = true}
: When used in conjunction with {type = "language"}, allows [[Wiktionary:Language families|language family codes]] to be
returned. To check if a given object refers to a language family, use {object:hasType("family")}.
; {method = "name"}
: When used in conjunction with {type = "language"}, {type = "family"} or {type = "script"}, checks for and parses a
language, family or script name instead of a code.
; {allow_holes = true}
: This is used in conjunction with list-type parameters. By default, the values are tightly packed in the resulting
list. This means that if, for example, an entry specified `head=a|head3=c` but not {{para|head2}}, the returned list
will be { {"a", "c"}}}, with the values stored at the indices {1} and {2}, not {1} and {3}. If it is desirable to keep
the numbering intact, for example if the numbers of several list parameters correlate with each other (like those of
{{tl|affix}}), then this tag should be specified.
: If {allow_holes = true} is given, there may be {nil} values in between two real values, which makes many of Lua's
table processing functions no longer work, like {#} or {ipairs()}. To remedy this, the resulting table will contain an
additional named value, `maxindex`, which tells you the highest numeric index that is present in the table. In the
example above, the resulting table will now be { { "a", nil, "c", maxindex = 3}}}. That way, you can iterate over the
values from {1} to `maxindex`, while skipping {nil} values in between.
; {disallow_holes = true}
: This is used in conjunction with list-type parameters. As mentioned above, normally if there is a hole in the source
arguments, e.g. `head=a|head3=c` but not {{para|head2}}, it will be removed in the returned list. If
{disallow_holes = true} is specified, however, an error is thrown in such a case. This should be used whenever there
are multiple list-type parameters that need to line up (e.g. both {{para|head}} and {{para|tr}} are available and
{{para|head3}} lines up with {{para|tr3}}), unless {allow_holes = true} is given and you are prepared to handle the
holes in the returned lists.
; {disallow_missing = true}
: This is similar to {disallow_holes = true}, but an error will not be thrown if an argument is blank, rather than
completely missing. This may be used to tolerate intermediate blank numerical parameters, which sometimes occur in list
templates. For instance, `head=a|head2=|head3=c` will not throw an error, but `head=a|head3=c` will.
; {require_index = true}
: This is used in conjunction with list-type parameters. By default, the first parameter can have its index omitted.
For example, a list parameter named `head` can have its first parameter specified as either {{para|head}} or
{{para|head1}}. If {require_index = true} is specified, however, only {{para|head1}} is recognized, and {{para|head}}
will be treated as an unknown parameter. {{tl|affixusex}} (and variants {{tl|suffixusex}}, {{tl|prefixusex}}) use
this, for example, on all list parameters.
; {separate_no_index = true}
: This is used to distinguish between {{para|head}} and {{para|head1}} as different parameters. For example, in
{{tl|affixusex}}, to distinguish between {{para|sc}} (a script code for all elements in the usex's language) and
{{para|sc1}} (the script code of the first element, used when the first element is prefixed with a language code to
indicate that it is in a different language). When this is used, the resulting table will contain an additional named
value, `default`, which contains the value for the indexless argument.
; {flatten = true}
: This is used in conjunction with list-type parameters when `sublist` or a list-generating type such as {"labels"} or
{"genders"} is also specified, and causes the resulting list to be flattened. Not currently compatible with
{allow_holes = true}.
; {replaced_by =}
: Specifies that the parameter is no longer valid, and has been replaced by some other mechanism. If the value of
`replaced_by` is a string, it is the name of the new parameter to use instead. Use the `reason` tag to specify the
reason why this change has been made, e.g.
{reason = "for consistency with the corresponding parameter in other Romance-language headword templates"}. If the
value of `replaced_by` is {false}, there is no replacement parameter. In this case, `instead` should be supplied
with a description of what to do instead, e.g.
{instead = "use an inline modifier on |2= such as <q:...>, <qq:...>, <l:...> or <ll:...>"}. You can also supply a
justification in `reason` if you feel it is appropriate or necessary to do so.
; {reason =}
: When used in conjunction with `replaced_by`, specifies the reason for the parameter replacement.
; {instead =}
: When used in conjunction with {replaced_by = false}, specifies what to do instead of using the removed parameter.
; {demo = true}
: This is used as a way to ensure that the parameter is only enabled on the template's own page (and its documentation
page), and in the User: namespace; otherwise, it will be treated as an unknown parameter. This should only be used if
special settings are required to showcase a template in its documentation (e.g. adjusting the pagename or disabling
categorization). In most cases, it should be possible to do this without using demo parameters, but they may be
required if a template/documentation page also contains real uses of the same template as well (e.g. {{tl|shortcut}}),
as a way to distinguish them.
; {deprecated = true}
: This is for tracking the use of deprecated parameters, including any aliases that are being brought out of use. See
[[Wiktionary:Tracking]] for more information.
]==]
-- Returns true if the current page is a template or module containing the current {{#invoke}}.
-- If the include_documentation argument is given, also returns true if the current page is either page's documentation page.
local own_page, own_page_or_documentation
local function is_own_page(include_documentation)
if own_page == nil then
if current_namespace == nil then
local current_title = mw_title.getCurrentTitle()
current_title_text, current_namespace = current_title.prefixedText, current_title.namespace
end
local frame = current_namespace == 828 and mw.getCurrentFrame() or
current_namespace == 10 and mw.getCurrentFrame():getParent()
if frame then
local frame_title_text = frame:getTitle()
own_page = current_title_text == frame_title_text
own_page_or_documentation = own_page or current_title_text == frame_title_text .. "/documentation"
else
own_page, own_page_or_documentation = false, false
end
end
return include_documentation and own_page_or_documentation or own_page
end
-------------------------------------- Some helper functions -----------------------------
-- Convert a list in `list` to a string, separating the final element from the preceding one(s) by `conjunction`. If
-- `dump_vals` is given, pass all values in `list` through mw.dumpObject() (WARNING: this destructively modifies
-- `list`). This is similar to serialCommaJoin() in [[Module:table]] when used with the `dontTag = true` option, but
-- internally uses mw.text.listToText().
local function concat_list(list, conjunction, dump_vals)
if dump_vals then
for k, v in pairs(list) do
list[k] = dump(v)
end
end
return list_to_text(list, nil, conjunction)
end
-- A helper function for use with generating error-signaling functions in the presence of raw value conversion. Format a
-- message `msg`, including the processed value `processed` if it is different from the raw value `rawval`; otherwise,
-- just return `msg`.
local function msg_with_processed(msg, rawval, processed)
if rawval == processed then
return msg
end
local processed_type = type(processed)
return format("%s (processed value %s)",
msg, (processed_type == "string" or processed_type == "number") and processed or dump(processed)
)
end
-- Separate form of tags with ampersand (&).
local function split_tags_on_ampersand(tags)
return split(tags, "&")
end
-------------------------------------- Error handling -----------------------------
local function process_error(fmt, ...)
local args = {...}
for i, val in ipairs(args) do
args[i] = dump(val)
end
if type(fmt) == "table" then
-- hacky signal that we're called from internal_process_error(), and not to omit stack frames
return error(format(fmt[1], unpack(args)))
end
return error(format(fmt, unpack(args)), 3)
end
local function internal_process_error(fmt, ...)
process_error({"Internal error in `params` table: " .. fmt}, ...)
end
-- Check that a parameter or argument is in the form form Scribunto normalizes input argument keys into (e.g. 1 not "1", "foo" not " foo "). Otherwise, it won't be possible to normalize inputs in the expected way. Unless is_argument is set, also check that the name only contains one placeholder at most, and that strings don't resolve to numeric keys once the placeholder has been substituted.
local function validate_name(name, desc, extra_name, is_argument)
local normalized = scribunto_parameter_key(name)
if name and name == normalized then
if is_argument or type(name) ~= "string" then
return
end
local placeholder = find(name, "\1", nil, true)
if not placeholder then
return
elseif find(name, "\1", placeholder + 1, true) then
error(format(
"Internal error: expected %s to only contain one placeholder, but saw %s",
extra_name and (desc .. dump(extra_name)) or desc, dump(name)
))
end
local first_name = gsub(name, "\1", "1")
normalized = scribunto_parameter_key(first_name)
if first_name == normalized then
return
end
error(format(
"Internal error: %s cannot resolve to numeric parameters once any placeholder has been substituted, but %s resolves to %s",
extra_name and (desc .. dump(extra_name)) or desc, dump(name), dump(normalized)
))
elseif normalized == nil then
error(format(
"Internal error: expected %s to be of type string or number, but saw %s",
extra_name and (desc .. dump(extra_name)) or desc, type(name)
))
end
error(format(
"Internal error: expected %s to be Scribunto-compatible: %s (a %s) should be %s (a %s)",
extra_name and (desc .. dump(extra_name)) or desc, dump(name), type(name), dump(normalized), type(normalized)
))
end
local function validate_alias_options(...)
local invalid = {
required = true,
default = true,
template_default = true,
allow_holes = true,
disallow_holes = true,
disallow_missing = true,
}
function validate_alias_options(param, name, main_param, alias_of)
for k in pairs(param) do
if invalid[k] then
track("bad alias option")
-- internal_process_error(
-- "parameter %s cannot have the option %s, as it is an alias of parameter %s.",
-- name, option, alias_of
-- )
end
end
-- Soon, aliases will inherit options from the main parameter via __index. Track cases where this would happen.
if main_param ~= true then
for k in pairs(main_param) do
if param[k] == nil and not invalid[k] then
if k == "list" then -- these need to be changed to list = false to retain current behaviour
track("mismatched list alias option")
elseif not (k == "type" or k == "set" or k == "sublist") then -- rarely specified on aliases, as they're effectively inherited already
track("mismatched alias option")
end
end
end
end
end
validate_alias_options(...)
end
-- TODO: give ranges instead of long lists, if possible.
--[==[ func: export.params_list_error(params, msg)
Given a key-value table of raw parameters `params`, display an error message about all the parameters seen in the table.
The parameter names are displayed in sorted order. `msg` should be e.g. {"required"} or {"not used by this template"}.
This is used internally to display error messages about required or invalid parameters, and can be used for the same
purpose by code that processes its own parameters (e.g. if the `return_unknown` flag is specified to `process`).
]==]
local function params_list_error(params, msg)
local list, n = {}, 0
for name in sorted_pairs(params) do
n = n + 1
list[n] = name
end
error(format(
"Parameter%s %s.",
format(n == 1 and " %s is" or "s %s are", concat_list(list, " and ", true)),
msg
), 3)
end
export.params_list_error = params_list_error
-- Helper function for use with convert_val_error(). Format a list of possible choices using `concat_list` and
-- conjunction "or", displaying "either " before the choices if there's more than one.
local function format_choice_list(valid)
return (#valid > 1 and "either " or "") .. concat_list(valid, " or ")
end
-- Signal an error for a value `val` that is not of the right type `valid` (which is either a string specifying a type, or
-- a list of possible values, in the case where `set` was used). `name` is the name of the parameter and can be a
-- function to signal an error (which is assumed to automatically display the parameter's name and value). `seetext` is
-- an optional additional explanatory link to display (e.g. [[WT:LOL]], the list of possible languages and codes).
local function convert_val_error(val, name, valid, seetext)
if is_callable(name) then
if type(valid) == "table" then
valid = "choice, must be " .. format_choice_list(valid)
end
name(format("Invalid %s; the value %s is not valid%s", valid, val, seetext and "; see " .. seetext or ""))
else
if type(valid) == "table" then
valid = format_choice_list(valid)
else
valid = "a valid " .. valid
end
error(format("Parameter %s must be %s; the value %s is not valid.%s", dump(name), valid, dump(val),
seetext and " See " .. seetext .. "." or ""))
end
end
-- Generate the appropriate error-signaling function given parameter value `val` and name `name`. If `name` is already
-- a function, it is just returned; otherwise a function is generated and returned that displays the passed-in messaeg
-- along with the parameter's name and value.
local function make_parse_err(val, name)
if is_callable(name) then
return name
end
return function(msg)
error(format("%s: parameter %s=%s", msg, name, val))
end
end
-------------------------------------- Value conversion -----------------------------
-- For a list parameter `name` and corresponding value `list_name` of the `list` field (which should have the same value
-- as `name` if `list = true` was given), generate a pattern to match parameters of the list and store the pattern as a
-- key in `patterns`, with corresponding value set to `name`. For example, if `list_name` is "tr", the pattern will
-- match "tr" as well as "tr1", "tr2", ..., "tr10", "tr11", etc. If the `list_name` contains a \1 in it, the numeric
-- portion goes in place of the \1. For example, if `list_name` is "f\1accel", the pattern will match "faccel",
-- "f1accel", "f2accel", etc. Any \1 in `name` is removed before storing into `patterns`.
local function save_pattern(name, list_name, patterns)
name = type(name) == "string" and gsub(name, "\1", "") or name
if find(list_name, "\1", nil, true) then
patterns["^" .. gsub(pattern_escape(list_name), "\1", "([1-9]%%d*)") .. "$"] = name
else
patterns["^" .. pattern_escape(list_name) .. "([1-9]%d*)$"] = name
list_name = list_name .. "\1"
end
validate_name(list_name, "the list field of parameter ", name)
return patterns
end
-- A helper function for use with `sublist`. It is an iterator function for use in a for-loop that returns split
-- elements of `val` using `sublist` (a Lua split pattern; boolean `true` to split on commas optionally surrounded by
-- whitespace; "comma without whitespace" to split only on commas not followed by whitespace which have not been escaped
-- by a backslash; or a function to do the splitting, which is passed two values, the value to split and a function to
-- signal an error, and should return a list of the split elements). `name` is the parameter name or error-signaling
-- function passed into convert_val().
local function split_sublist(val, name, sublist)
if sublist == true then
return gsplit(val, "%s*,%s*")
-- Split an argument on comma, but not comma followed by whitespace.
elseif sublist == "comma without whitespace" then
-- If difficult cases, use split_on_comma.
if find(val, "\\", nil, true) or match(val, ",%s") then
return iterate_list(split_on_comma(val))
end
-- Otherwise, use gsplit.
return gsplit(val, ",")
elseif type(sublist) == "string" then
return gsplit(val, sublist)
elseif not is_callable(sublist) then
error(format('Internal error: expected `sublist` to be of type "string" or "function" or boolean `true`, but saw %s', dump(sublist)))
end
return iterate_list(sublist(val, make_parse_err(val, name)))
end
-- For parameter named `name` with value `val` and param spec `param`, if the `set` field is specified, verify that the
-- value is one of the one specified in `set`, and throw an error otherwise. `name` is taken directly from the
-- corresponding parameter passed into convert_val() and may be a function to signal an error. Optional `param_type` is
-- a string specifying the conversion type of `val` and is used for special-casing: If `param_type` is "boolean", an
-- internal error is thrown (since `set` cannot be used in conjunction with booleans) and if `param_type` is "number",
-- no checking happens because in this case `set` contains numbers and is checked inside the number conversion function
-- itself, after converting `val` to a number. Return the canonical value of `val` (which may be different from `val`
-- if an alias map is given).
local function check_set(val, name, param, param_type)
if param_type == "boolean" then
error(format('Internal error: cannot use `set` with `type = "%s"`', param_type))
-- Needs to be special cased because the check happens after conversion to numbers.
elseif param_type == "number" then
return val
end
local set, map = param.set
if sets == nil then
map = finalize_set(set, name)
sets = {[set] = map}
else
map = sets[set]
if map == nil then
map = finalize_set(set, name)
sets[set] = map
end
end
local newval = map[val]
if newval == true then
return val
elseif newval ~= nil then
return newval
end
local list = {}
for k, v in sorted_pairs(map) do
if v == true then
insert(list, dump(k))
else
insert(list, ("%s (alias of %s)"):format(dump(k), dump(v)))
end
end
-- If the parameter is not required then put "or empty" at the end of the list, to avoid implying the parameter is actually required.
if not param.required then
insert(list, "empty")
end
convert_val_error(val, name, list)
end
local function convert_language(val, name, param, allow_etym)
local method, func = param.method
if method == nil or method == "code" then
func, method = get_language_by_code, "code"
elseif method == "name" then
func, method = get_language_by_name, "name"
else
error(format('Internal error: expected `method` for type `language` to be "code", "name" or undefined, but saw %s', dump(method)))
end
local lang = func(val, nil, allow_etym, param.family)
if lang then
return lang
end
local list, links = {"language"}, {"[[WT:LOL]]"}
if allow_etym then
insert(list, "etymology language")
insert(links, "[[WT:LOL/E]]")
end
if param.family then
insert(list, "family")
insert(links, "[[WT:LOF]]")
end
convert_val_error(val, name, concat_list(list, " or ") .. " " .. (method == "name" and "name" or "code"), concat_list(links, " and "))
end
local function convert_number(val, allow_hex)
-- Call tonumber_extended with the `real_finite` flag, which filters out ±infinity and NaN.
-- By default, specify base 10, which prevents 0x hex inputs from being converted.
-- If `allow_hex` is set, then don't give a base, which means 0x hex inputs will work.
local num = tonumber_extended(val, not allow_hex and 10 or nil, "finite_real")
if not num then
return num
end
if match(val, "[eEpP.]") then -- float
track("number not an integer")
end
if find(val, "+", nil, true) then
track("number with +")
end
-- Track various unusual number inputs to determine if it should be restricted to positive integers by default (possibly including 0).
if not is_positive_integer(num) then
track("number not a positive integer")
if num == 0 then
track("number is 0")
elseif not is_integer(num) then
track("number not an integer")
end
end
return num
end
-- TODO: validate parameter specs separately, as it's making the handler code really messy at the moment.
local type_handlers = setmetatable({
["boolean"] = function(val)
return yesno(val, true)
end,
["family"] = function(val, name, param)
local method, func = param.method
if method == nil or method == "code" then
func, method = get_family_by_code, "code"
elseif method == "name" then
func, method = get_family_by_name, "name"
else
error(format('Internal error: expected `method` for type `family` to be "code", "name" or undefined, but saw %s', dump(method)))
end
return func(val) or convert_val_error(val, name, "family " .. method, "[[WT:LOF]]")
end,
["labels"] = function(val, name, param)
-- FIXME: Should be able to pass in a parse_err function.
return split_labels_on_comma(val)
end,
["form of tags"] = function(val, name, param)
return split_tags_on_ampersand(val)
end,
["language"] = function(val, name, param)
return convert_language(val, name, param, true)
end,
["full language"] = convert_language,
["number"] = function(val, name, param)
local allow_hex = param.allow_hex
if allow_hex and allow_hex ~= true then
error(format(
'Internal error: expected `allow_hex` for type `number` to be of type "boolean" or undefined, but saw %s',
dump(allow_hex)
))
end
local num = convert_number(val, allow_hex)
if param.set then
-- Don't pass in "number" here; otherwise no checking will happen.
num = check_set(num, name, param)
end
if num then
return num
end
convert_val_error(val, name, (allow_hex and "decimal or hexadecimal " or "") .. "number")
end,
["range"] = function(val, name, param)
local allow_hex = param.allow_hex
if allow_hex and allow_hex ~= true then
error(format(
'Internal error: expected `allow_hex` for type `range` to be of type "boolean" or undefined, but saw %s',
dump(allow_hex)
))
end
-- Pattern ensures leading minus signs are accounted for.
local m1, m2 = match(val, "^(%s*%S.-)%-(%s*%S.*)")
if m1 then
m1 = convert_number(m1, allow_hex)
if m1 then
m2 = convert_number(m2, allow_hex)
if m2 then
return {m1, m2}
end
end
end
-- Try `val` if it couldn't be split into a range, and return a range of `val` to `val` if possible.
local num = convert_number(val, allow_hex)
if num then
return {num, num}
end
convert_val_error(val, name, (allow_hex and "decimal or hexadecimal " or "") .. "number or a hyphen-separated range of two numbers")
end,
["parameter"] = function(val, name, param)
-- Use the `no_trim` option, as any trimming will have already been done.
return scribunto_parameter_key(val, true)
end,
["qualifier"] = function(val, name, param)
return {val}
end,
["references"] = function(val, name, param)
return parse_references(val, make_parse_err(val, name))
end,
["genders"] = function(val, name, param)
if not val:find("[,<]") then
return {{spec = val}}
end
-- NOTE: We don't pass in allow_space_around_comma. Consistent with other comma-separated types, there shouldn't
-- be spaces around the comma.
return parse_gender_and_number_spec {
spec = val,
parse_err = make_parse_err(val, name),
allow_multiple = true,
}
end,
["script"] = function(val, name, param)
local method, func = param.method
if method == nil or method == "code" then
func, method = get_script_by_code, "code"
elseif method == "name" then
func, method = get_script_by_name, "name"
else
error(format('Internal error: expected `method` for type `script` to be "code", "name" or undefined, but saw %s', dump(method)))
end
return func(val) or convert_val_error(val, name, "script " .. method, "[[WT:LOS]]")
end,
["string"] = function(val, name, param) -- To be removed as unnecessary.
track("string")
return val
end,
-- TODO: add support for resolving to unsupported titles.
-- TODO: split this into "page name" (i.e. internal) and "link target" (i.e. external as well), which is more intuitive.
["title"] = function(val, name, param)
local namespace = param.namespace
if namespace == nil then
namespace = 0
else
local valid_type = type(namespace) ~= "number" and 'of type "number" or undefined' or
not namespaces[namespace] and "a valid namespace number" or
nil
if valid_type then
error(format('Internal error: expected `namespace` for type `title` to be %s, but saw %s', valid_type, dump(namespace)))
end
end
-- Decode entities. WARNING: mw.title.makeTitle must be called with `decoded` (as it doesn't decode) and mw.title.new must be called with `val` (as it does decode, so double-decoding needs to be avoided).
local decoded, prefix, title = decode_entities(val), param.prefix
-- If the input is a fragment, treat the title as the current title with the input fragment.
if sub(decoded, 1, 1) == "#" then
-- If prefix is "force", only get the current title if it's in the specified namespace. current_title includes the namespace prefix.
if current_namespace == nil then
local current_title = mw_title.getCurrentTitle()
current_title_text, current_namespace = current_title.prefixedText, current_title.namespace
end
if not (prefix == "force" and namespace ~= current_namespace) then
title = new_title(current_title_text .. val)
end
elseif prefix == "force" then
-- Unconditionally add the namespace prefix (mw.title.makeTitle).
title = make_title(namespace, decoded)
elseif prefix == "full override" then
-- The first input prefix will be used as an override (mw.title.new). This can be a namespace or interwiki prefix.
title = new_title(val, namespace)
elseif prefix == nil or prefix == "namespace override" then
-- Only allow namespace prefixes to override. Interwiki prefixes therefore need to be treated as plaintext (e.g. "el:All topics" with namespace 14 returns "el:Category:All topics", but we want "Category:el:All topics" instead; if the former is really needed, then the input ":el:Category:All topics" will work, as the initial colon overrides the namespace). mw.title.new can take namespace names as well as numbers in the second argument, and will throw an error if the input isn't a valid namespace, so this can be used to determine if a prefix is for a namespace, since mw.title.new will return successfully only if there's either no prefix or the prefix is for a valid namespace (in which case we want the override).
local success
success, title = pcall(new_title, val, match(decoded, "^.-%f[:]") or namespace)
-- Otherwise, get the title with mw.title.makeTitle, which unconditionally adds the namespace prefix, but behaves like mw.title.new if the namespace is 0.
if not success then
title = make_title(namespace, decoded)
end
else
error(format('Internal error: expected `prefix` for type `title` to be "force", "full override", "namespace override" or undefined, but saw %s', dump(prefix)))
end
local allow_external = param.allow_external
if allow_external == true then
return title or convert_val_error(val, name, "Wiktionary or external page title")
elseif not allow_external then
return title and is_internal_title(title) and title or convert_val_error(val, name, "Wiktionary page title")
end
error(format('Internal error: expected `allow_external` for type `title` to be of type "boolean" or undefined, but saw %s', dump(allow_external)))
end,
["Wikimedia language"] = function(val, name, param)
local fallback = param.fallback
if fallback == true then
return get_wm_lang_by_code_with_fallback(val) or convert_val_error(val, name, "Wikimedia language or language code")
elseif not fallback then
return get_wm_lang_by_code(val) or convert_val_error(val, name, "Wikimedia language code")
end
error(format('Internal error: expected `fallback` for type `Wikimedia language` to be of type "boolean" or undefined, but saw %s', dump(fallback)))
end,
}, {
-- TODO: decode HTML entities in all input values. Non-trivial to implement, because we need to avoid any downstream functions decoding the output from this module, which would be double-decoding. Note that "title" has this implemented already, and it needs to have both the raw input and the decoded input to avoid double-decoding by me.title.new, so any implementation can't be as simple as decoding in __call then passing the result to the handler.
__call = function(self, val, name, param, param_type, default)
local val_type = type(val)
-- TODO: check this for all possible parameter types.
if val_type == param_type then
return val
elseif val_type ~= "string" then
local expected = "string"
if default and (param_type == "boolean" or param_type == "number") then
expected = param_type .. " or " .. expected
end
error(format(
"Internal error: %sargument %s has the type %s; expected a %s.",
default and (default .. " for ") or "", name, dump(val_type), expected
))
end
local func = self[param_type]
if func == nil then
error(format("Internal error: %s is not a recognized parameter type.", dump(param_type)))
end
return func(val, name, param)
end
})
--[==[ func: export.convert_val(val, name, param)
Convert a parameter value according to the associated specs listed in the `params` table passed to
[[Module:parameters]]. `val` is the value to convert for a parameter whose name is `name` (used only in error messages).
`param` is the spec (the value part of the `params` table for the parameter). In place of passing in the parameter name,
`name` can be a function that throws an error, displaying the specified message along with the parameter name and value.
This function processes all the conversion-related fields in `param`, including `type`, `set`, `sublist`, `convert`,
etc. It returns the converted value.
]==]
local function convert_val(val, name, param, default)
local param_type = param.type or "string"
-- If param.type is a function, resolve it to a recognized type.
if is_callable(param_type) then
param_type = param_type(val)
end
local convert, sublist = param.convert, param.sublist
-- `val` might not be a string if it's the default value.
if sublist and type(val) == "string" then
local retlist, set = {}, param.set
if convert then
local thisindex, thisval, insval, parse_err = 0
if is_callable(name) then
-- We assume the passed-in error function in `name` already shows the parameter name and raw value.
function parse_err(msg)
name(format("%s: item #%s=%s",
msg_with_processed(msg, thisval, insval), thisindex, thisval)
)
end
else
function parse_err(msg)
error(format("%s: item #%s=%s of parameter %s=%s",
msg_with_processed(msg, thisval, insval), thisindex, thisval, name, val)
)
end
end
for v in split_sublist(val, name, sublist) do
thisindex, thisval = thisindex + 1, v
if set then
v = check_set(v, name, param, param_type)
end
insert(retlist, convert(type_handlers(v, name, param, param_type, default), parse_err))
end
else
for v in split_sublist(val, name, sublist) do
if set then
v = check_set(v, name, param, param_type)
end
insert(retlist, type_handlers(v, name, param, param_type, default))
end
end
return retlist
elseif param.set then
val = check_set(val, name, param, param_type)
end
local retval = type_handlers(val, name, param, param_type, default)
if convert then
local parse_err
if is_callable(name) then
-- We assume the passed-in error function in `name` already shows the parameter name and raw value.
if retval == val then
-- This is an optimization to avoid creating a closure. The second arm works correctly even
-- when retval == val.
parse_err = name
else
function parse_err(msg)
name(msg_with_processed(msg, val, retval))
end
end
else
function parse_err(msg)
error(format("%s: parameter %s=%s", msg_with_processed(msg, val, retval), name, val))
end
end
retval = convert(retval, parse_err)
end
-- If `sublist` is set but the input wasn't a string, return `retval` as a one-item list.
if sublist then
retval = {retval}
end
return retval
end
export.convert_val = convert_val -- used by [[Module:parameter utilities]]
local function unknown_param(name, val, args_unknown)
track("unknown parameters")
args_unknown[name] = val
return args_unknown
end
local function check_string_param_modifier(param_type, name, tag)
if param_type and not (param_type == "string" or param_type == "parameter" or is_callable(param_type)) then
internal_process_error(
"%s cannot be set unless %s is set to %s (the default), %s or a function: parameter %s has the type %s.",
tag, "type", "string", "parameter", name, param_type
)
end
end
local function hole_error(params, name, listname, this, nxt, extra)
-- `process_error` calls `dump` on values to be inserted into
-- error messages, but with numeric lists this causes "numeric"
-- to look like the name of the list rather than a description,
-- as `dump` adds quote marks. Insert it early to avoid this,
-- but add another %s specifier in all other cases, so that
-- actual list names will be displayed properly.
local offset, specifier, starting_from = 0, "%s", ""
local msg = "Item %%d in the list of %s parameters must be given if item %%d is given, because %sthere shouldn't be any gaps due to missing%s parameters."
local specs = {}
if type(listname) == "string" then
specs[2] = listname
elseif type(name) == "number" then
offset = name - 1 -- To get the original parameter.
specifier = "numeric"
-- If the list doesn't start at parameter 1, avoid implying
-- there can't be any gaps in the numeric parameters if
-- some parameter with a lower key is optional.
for j = name - 1, 1, -1 do
local _param = params[j]
if not (_param and _param.required) then
starting_from = format("(starting from parameter %d) ", dump(j + 1))
break
end
end
else
specs[2] = name
end
specs[1] = this + offset -- Absolute index for this item.
insert(specs, nxt + offset) -- Absolute index for the next item.
process_error(format(msg, specifier, starting_from, extra or ""), unpack(specs))
end
local function check_disallow_holes(params, val, name, listname, extra)
for i = 1, val.maxindex do
if val[i] == nil then
hole_error(params, name, listname, i, num_keys(val)[i], extra)
end
end
end
local function handle_holes(params, val, name)
local param = params[name]
local disallow_holes = param.disallow_holes
-- Iterate up the list, and throw an error if a hole is found.
if disallow_holes then
check_disallow_holes(params, val, name, param.list, " or empty")
end
-- Iterate up the list, and throw an error if a hole is found due to a
-- missing parameter, treating empty parameters as part of the list. This
-- applies beyond maxindex if blank arguments are supplied beyond it, so
-- isn't mutually exclusive with `disallow_holes`.
local empty = val.empty
if param.disallow_missing then
if empty then
-- Remove `empty` from `val`, so it doesn't get returned.
val.empty = nil
for i = 1, max(val.maxindex, empty.maxindex) do
if val[i] == nil and not empty[i] then
local keys = extend(num_keys(val), num_keys(empty))
sort(keys)
hole_error(params, name, param.list, i, keys[i])
end
end
-- If there's no table of empty parameters, the check is identical to
-- `disallow_holes`, except that the error message only refers to
-- missing parameters, not missing or empty ones. If `disallow_holes` is
-- also set, there's no point checking again.
elseif not disallow_holes then
check_disallow_holes(params, val, name, param.list)
end
end
-- If `allow_holes` is set, there's nothing left to do.
if param.allow_holes then
-- do nothing
-- Otherwise, remove any holes: `pairs` won't work, as it's unsorted, and
-- iterating from 1 to `maxindex` times out with inputs like |100000000000=,
-- so use num_keys to get a list of numerical keys sorted from lowest to
-- highest, then iterate up the list, moving each value in `val` to the
-- lowest unused positive integer key. This also avoids the need to create a
-- new table. If `disallow_holes` is specified, then there can't be any
-- holes in the list, so there's no reason to check again; this doesn't
-- apply to `disallow_missing`, however.
else
if not disallow_holes then
local keys, i = num_keys(val), 0
while true do
i = i + 1
local key = keys[i]
if key == nil then
break
elseif i ~= key then
track("holes compressed")
val[i], val[key] = val[key], nil
end
end
end
-- Some code depends on only numeric params being present when no holes are
-- allowed (e.g. by checking for the presence of arguments using next()), so
-- remove `maxindex`.
val.maxindex = nil
end
end
local function maybe_flatten(params, val, name)
local param = params[name]
if param.flatten then
if param.allow_holes then
process_error("For parameter %s, can't set both `allow_holes` and `flatten`", name)
end
if not param.sublist and param.type ~= "genders" and param.type ~= "labels" and
param.type ~= "references" and param.type ~= "qualifier" and param.type ~= "form of tags" then
process_error("For parameter %s, can only set `flatten` along with `sublist` or a list-generating type", name)
end
-- Do the flattening ourselves rather than calling flatten() in [[Module:table]], which will attempt to
-- flatten non-list objects like title objects, and cause an error in the process.
-- FIXME: We should do this in-place if possible.
local newlist = {}
for _, sublist in ipairs(val) do
for _, item in ipairs(sublist) do
insert(newlist, item)
end
end
val = newlist
end
return val
end
-- If both `template_default` and `default` are given, `template_default` takes precedence, but only on the template or
-- module page. This means a different default can be specified for the template or module page example. However,
-- `template_default` doesn't apply if any args are set, which helps (somewhat) with examples on documentation pages
-- transcluded into the template page. HACK: We still run into problems on documentation pages transcluded into the
-- template page when pagename= is set. Check this on the assumption that pagename= is fairly standard.
local function convert_default_val(name, param, pagename_set, any_args_set, add_empty_sublist)
if not pagename_set then
local val = param.template_default
if val ~= nil and not any_args_set and is_own_page() then
return convert_val(val, name, param, "template default")
end
end
local val = param.default
if val ~= nil then
return convert_val(val, name, param, "default")
-- Sublist parameters should return an empty table if not given, but only do
-- this if the parameter isn't also a list (in which case it will already
-- be an empty table).
-- FIXME: do this once all modules that pass in a sublist parameter treat an empty sublist identically to a nil argument; some currently do things based on the fact an argument exists at all.
-- elseif add_empty_sublist and param.sublist then
--return {}
end
end
--[==[
Process arguments with a given list of parameters. Return a table containing the processed arguments. The `args`
parameter specifies the arguments to be processed; they are the arguments you might retrieve from
{frame:getParent().args} (the template arguments) or in some cases {frame.args} (the invocation arguments). The `params`
parameter specifies a list of valid parameters, and consists of a table. If an argument is encountered that is not in
the parameter table, an error is thrown.
The structure of the `params` table is as described above in the intro comment.
'''WARNING:''' The `params` table is destructively modified to save memory. Nonetheless, different keys can share the
same value objects in memory without causing problems.
The `return_unknown` parameter, if set to {true}, prevents the function from triggering an error when it comes across an
argument with a name that it doesn't recognise. Instead, the return value is a pair of values: the first is the
processed arguments as usual, while the second contains all the unrecognised arguments that were left unprocessed. This
allows you to do multi-stage processing, where the entire set of arguments that a template should accept is not known at
once. For example, an inflection-table might do some generic processing on some arguments, but then defer processing of
the remainder to the function that handles a specific inflectional type.
]==]
function export.process(args, params, return_unknown)
-- Process parameters for specific properties
local args_new, args_unknown, any_args_set, required, patterns, list_args, index_list, args_placeholders, placeholders_n = {}
-- TODO: memoize the processing of each unique `param` value, since it's common for the same value to be used for many parameter names.
for name, param in pairs(params) do
validate_name(name, "parameter names")
if param ~= true then
local spec_type = type(param)
if type(param) ~= "table" then
internal_process_error(
"spec for parameter %s must be a table of specs or the value true, but found %s.",
name, spec_type ~= "boolean" and spec_type or param
)
end
-- Populate required table, and make sure aliases aren't set to required.
if param.required then
if required == nil then
required = {}
end
required[name] = true
end
local listname, alias_of = param.list, param.alias_of
if alias_of then
validate_name(alias_of, "the alias_of field of parameter ", name)
if alias_of == name then
internal_process_error(
"parameter %s cannot be an alias of itself.",
name
)
end
local main_param = params[alias_of]
-- Check that the alias_of is set to a valid parameter.
if not (main_param == true or type(main_param) == "table") then
internal_process_error(
"parameter %s is an alias of an invalid parameter.",
name
)
end
validate_alias_options(param, name, main_param, alias_of)
-- Aliases can't be lists unless the canonical parameter is also a list.
if listname and (main_param == true or not main_param.list) then
internal_process_error(
"list parameter %s is set as an alias of %s, which is not a list parameter.", name, alias_of
)
-- Can't be an alias of an alias.
elseif main_param ~= true then
local main_alias_of = main_param.alias_of
if main_alias_of ~= nil then
internal_process_error(
"alias_of cannot be set to another alias: parameter %s is set as an alias of %s, which is in turn an alias of %s. Set alias_of for %s to %s.",
name, alias_of, main_alias_of, name, main_alias_of
)
end
end
end
local replaced_by = param.replaced_by
if replaced_by then -- replaced_by can be `false`, which is OK
validate_name(replaced_by, "the replaced_by field of parameter ", name)
if replaced_by == name then
internal_process_error(
"parameter %s cannot be replaced by itself.",
name
)
end
local main_param = params[replaced_by]
-- Check that the replaced_by is set to a valid parameter.
if not (main_param == true or type(main_param) == "table") then
internal_process_error(
"parameter %s is set to be replaced by an invalid parameter.",
name
)
end
-- Can't be a replaced-by of a replaced-by.
if main_param ~= true then
local main_replaced_by = main_param.replaced_by
if main_replaced_by ~= nil then
internal_process_error(
"replaced_by cannot be set to another replaced-by parameter: parameter %s is set as replaced by %s, which is in turn replaced by %s. Set replaced_by for %s to %s.",
name, replaced_by, main_replaced_by, name, main_replaced_by
)
end
end
if param.instead ~= nil then
internal_process_error("the `instead` tag can only be given when `replaced_by` is set to `false`.")
end
elseif replaced_by == false then
if param.instead ~= nil and type(param.instead) ~= "string" then
internal_process_error(
"the `instead` tag must be a string, but saw %s.",
param.instead
)
end
end
if replaced_by ~= nil then
if param.reason ~= nil and type(param.reason) ~= "string" then
internal_process_error(
"the `reason` tag must be a string, but saw %s.",
param.reason
)
end
end
if listname then
if not alias_of then
local key = name
if type(name) == "string" then
key = gsub(name, "\1", "")
end
local list_arg = {maxindex = 0}
args_new[key] = list_arg
if list_args == nil then
list_args = {}
end
list_args[key] = list_arg
end
local list_type = type(listname)
if list_type == "string" then
-- If the list property is a string, then it represents the name
-- to be used as the prefix for list items. This is for use with lists
-- where the first item is a numbered parameter and the
-- subsequent ones are named, such as 1, pl2, pl3.
patterns = save_pattern(name, listname, patterns or {})
elseif listname ~= true then
internal_process_error(
"list field for parameter %s must be a boolean, string or undefined, but saw a %s.",
name, list_type
)
elseif type(name) == "number" then
if index_list ~= nil then
internal_process_error(
"only one numeric parameter can be a list, unless the list property is a string."
)
end
-- If the name is a number, then all indexed parameters from
-- this number onwards go in the list.
index_list = name
else
patterns = save_pattern(name, name, patterns or {})
end
if find(name, "\1", nil, true) then
if args_placeholders then
placeholders_n = placeholders_n + 1
args_placeholders[placeholders_n] = name
else
args_placeholders, placeholders_n = {name}, 1
end
end
end
end
end
--Process required changes to `params`.
if args_placeholders then
for i = 1, placeholders_n do
local name = args_placeholders[i]
params[gsub(name, "\1", "")], params[name] = params[name], nil
end
end
-- Process the arguments
for name, val in pairs(args) do
any_args_set = true
validate_name(name, "argument names", nil, true)
-- Guaranteeing that all values are strings avoids issues with type coercion being inconsistent between functions.
local val_type = type(val)
if val_type ~= "string" then
internal_process_error(
"argument %s has the type %s; all arguments must be strings.",
name, val_type
)
end
local orig_name, raw_type, index, canonical = name, type(name)
if raw_type == "number" then
if index_list and name >= index_list then
index = name - index_list + 1
name = index_list
end
elseif patterns then
-- Does this argument name match a pattern?
for pattern, pname in next, patterns do
index = match(name, pattern)
-- It matches, so store the parameter name and the
-- numeric index extracted from the argument name.
if index then
index = tonumber(index)
name = pname
break
end
end
end
local param = params[name]
-- If the argument is not in the list of parameters, store it in a separate list.
if not param then
args_unknown = unknown_param(name, val, args_unknown or {})
elseif param == true then
canonical = orig_name
val = php_trim(val)
if val ~= "" then
-- If the parameter is duplicated, throw an error.
if args_new[name] ~= nil then
process_error(
"Parameter %s has been entered more than once. This is probably because a parameter alias has been used.",
canonical
)
end
args_new[name] = val
end
else
if param.replaced_by == false then
process_error(
("Parameter %%s has been removed and is no longer valid%s.%s"):format(
param.reason and ", " .. param.reason or "",
param.instead and " Instead, " .. param.instead .. "." or ""),
name
)
elseif param.replaced_by then
process_error(
("Parameter %%s has been replaced by %%s%s."):format(
param.reason and ", " .. param.reason or ""),
name, param.replaced_by
)
end
if param.deprecated then
track("deprecated parameter", name)
end
if param.require_index then
-- Disallow require_index for numeric parameter names, as this doesn't make sense.
if raw_type == "number" then
internal_process_error(
"cannot set require_index for numeric parameter %s.",
name
)
-- If a parameter without the trailing index was found, and
-- require_index is set on the param, treat it
-- as if it isn't recognized.
elseif not index then
args_unknown = unknown_param(name, val, args_unknown or {})
end
end
-- Check that separate_no_index is not being used with a numeric parameter.
if param.separate_no_index then
if raw_type == "number" then
internal_process_error(
"cannot set separate_no_index for numeric parameter %s.",
name
)
elseif type(param.alias_of) == "number" then
internal_process_error(
"cannot set separate_no_index for parameter %s, as it is an alias of numeric parameter %s.",
name, param.alias_of
)
end
end
-- If no index was found, use 1 as the default index.
-- This makes list parameters like g, g2, g3 put g at index 1.
-- If `separate_no_index` is set, then use 0 as the default instead.
if not index and param.list then
index = param.separate_no_index and 0 or 1
end
-- Normalize to the canonical parameter name. If it's a list, but the alias is not, then determine the index.
local raw_name = param.alias_of
if raw_name then
raw_type = type(raw_name)
if raw_type == "number" then
name = raw_name
local main_param = params[raw_name]
if main_param ~= true and main_param.list then
if not index then
index = param.separate_no_index and 0 or 1
end
canonical = raw_name + index - 1
else
canonical = raw_name
end
else
name = gsub(raw_name, "\1", "")
local main_param = params[name]
if not index and main_param ~= true and main_param.list then
index = param.separate_no_index and 0 or 1
end
if not index or index == 0 then
canonical = name
elseif name == raw_name then
canonical = name .. index
else
canonical = gsub(raw_name, "\1", index)
end
end
else
canonical = orig_name
end
-- Only recognize demo parameters if this is the current template or module's
-- page, or its documentation page.
if param.demo and not is_own_page("include_documentation") then
args_unknown = unknown_param(name, val, args_unknown or {})
end
-- Remove leading and trailing whitespace unless no_trim is true.
if param.no_trim then
check_string_param_modifier(param.type, name, "no_trim")
else
val = php_trim(val)
end
-- Empty string is equivalent to nil unless allow_empty is true.
if param.allow_empty then
check_string_param_modifier(param.type, name, "allow_empty")
elseif val == "" then
-- If `disallow_missing` is set, keep track of empty parameters
-- via the `empty` field in `arg`, which will be used by the
-- `disallow_missing` check. This will be deleted before
-- returning.
if index and param.disallow_missing then
local arg = args_new[name]
local empty = arg.empty
if empty == nil then
empty = {maxindex = 0}
arg.empty = empty
end
empty[index] = true
if index > empty.maxindex then
empty.maxindex = index
end
end
val = nil
end
-- Allow boolean false.
if val ~= nil then
-- Convert to proper type if necessary.
local main_param = params[raw_name]
if main_param ~= true then
val = convert_val(val, orig_name, main_param or param)
end
-- Mark it as no longer required, as it is present.
if required then
required[name] = nil
end
-- Store the argument value.
if index then
local arg = args_new[name]
-- If the parameter is duplicated, throw an error.
if arg[index] ~= nil then
process_error(
"Parameter %s has been entered more than once. This is probably because a list parameter has been entered without an index and with index 1 at the same time, or because a parameter alias has been used.",
canonical
)
end
arg[index] = val
-- Store the highest index we find.
local maxindex = arg.maxindex
if index > maxindex then
maxindex = index
end
if arg[0] ~= nil then
arg.default, arg[0] = arg[0], nil
if maxindex < 1 then
maxindex = 1
end
end
arg.maxindex = maxindex
if not params[name].list then
args_new[name] = val
-- Don't store index 0, as it's a proxy for the default.
elseif index > 0 then
arg[index] = val
end
else
-- If the parameter is duplicated, throw an error.
if args_new[name] ~= nil then
process_error(
"Parameter %s has been entered more than once. This is probably because a parameter alias has been used.",
canonical
)
end
if not raw_name then
args_new[name] = val
else
local main_param = params[raw_name]
if main_param ~= true and main_param.list then
local main_arg = args_new[raw_name]
main_arg[1] = val
-- Store the highest index we find.
if main_arg.maxindex < 1 then
main_arg.maxindex = 1
end
else
args_new[raw_name] = val
end
end
end
end
end
end
-- Remove holes in any list parameters if needed. This must be handled
-- straight after the previous loop, as any instances of `empty` need to be
-- converted to nil.
if list_args then
for name, val in next, list_args do
handle_holes(params, val, name)
end
end
-- If the current page is the template which invoked this Lua instance, then ignore the `require` flag, as it
-- means we're viewing the template directly. Required parameters sometimes have a `template_default` key set,
-- which gets used in such cases as a demo.
-- Note: this won't work on other pages in the Template: namespace (including the /documentation subpage),
-- or if the #invoke: is on a page in another namespace.
local pagename_set = args_new.pagename
-- Handle defaults.
for name, param in pairs(params) do
if param ~= true then
local arg_new = args_new[name]
if arg_new == nil then
args_new[name] = convert_default_val(name, param, pagename_set, any_args_set, true)
elseif param.list and arg_new[1] == nil then
local default_val = convert_default_val(name, param, pagename_set, any_args_set)
if default_val ~= nil then
arg_new[1] = default_val
if arg_new.maxindex == 0 then
arg_new.maxindex = 1
end
end
end
end
end
-- Flatten nested lists if called for. This must come after setting the default.
if list_args then
for name, val in next, list_args do
args_new[name] = maybe_flatten(params, val, name)
end
end
-- The required table should now be empty.
-- If any parameters remain, throw an error, unless we're on the current template or module's page.
if required and next(required) ~= nil and not is_own_page() then
params_list_error(required, "required")
-- Return the arguments table.
-- If there are any unknown parameters, throw an error, unless return_unknown is set, in which case return args_unknown as a second return value.
elseif return_unknown then
return args_new, args_unknown or {}
elseif args_unknown and next(args_unknown) ~= nil then
params_list_error(args_unknown, "not used by this template")
end
return args_new
end
return export
c23kzesggrlowmn06oii7zu1bbzht4t
26502
26501
2026-07-07T09:55:56Z
Sibiru45
115
1 ralatan matan [[:id:Modul:parameters]]
26501
Scribunto
text/plain
--[==[TODO:
* Change certain flag names, as some are misnomers:
* Change `allow_holes` to `keep_holes`, because it's not the inverse of `disallow_holes`.
* Change `allow_empty` to `keep_empty`, as it causes them to be kept as "" instead of deleted.
* Sort out all the internal error calls. Manual error(format()) calls are used when certain parameters shouldn't be dumped, so find a way to avoid that.
]==]
local export = {}
local collation_module = "Module:collation"
local families_module = "Module:families"
local functions_module = "Module:fun"
local gender_and_number_utilities_module = "Module:gender and number utilities"
local labels_module = "Module:labels"
local languages_module = "Module:languages"
local math_module = "Module:math"
local pages_module = "Module:pages"
local parameters_finalize_set_module = "Module:parameters/finalizeSet"
local parameters_track_module = "Module:parameters/track"
local parse_utilities_module = "Module:parse utilities"
local references_module = "Module:references"
local scribunto_module = "Module:Scribunto"
local scripts_module = "Module:scripts"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local wikimedia_languages_module = "Module:wikimedia languages"
local yesno_module = "Module:yesno"
local mw = mw
local mw_title = mw.title
local string = string
local table = table
local dump = mw.dumpObject
local find = string.find
local format = string.format
local gsub = string.gsub
local insert = table.insert
local ipairs = ipairs
local list_to_text = mw.text.listToText
local make_title = mw_title.makeTitle
local match = string.match
local max = math.max
local new_title = mw_title.new
local next = next
local pairs = pairs
local pcall = pcall
local require = require
local sub = string.sub
local tonumber = tonumber
local type = type
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local current_title_text, current_namespace, sets -- Defined when needed.
local namespaces = mw.site.namespaces
--[==[
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 decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function extend(...)
extend = require(table_module).extend
return extend(...)
end
local function finalize_set(...)
finalize_set = require(parameters_finalize_set_module)
return finalize_set(...)
end
local function get_family_by_code(...)
get_family_by_code = require(families_module).getByCode
return get_family_by_code(...)
end
local function get_family_by_name(...)
get_family_by_name = require(families_module).getByCanonicalName
return get_family_by_name(...)
end
local function get_language_by_code(...)
get_language_by_code = require(languages_module).getByCode
return get_language_by_code(...)
end
local function get_language_by_name(...)
get_language_by_name = require(languages_module).getByCanonicalName
return get_language_by_name(...)
end
local function get_script_by_code(...)
get_script_by_code = require(scripts_module).getByCode
return get_script_by_code(...)
end
local function get_script_by_name(...)
get_script_by_name = require(scripts_module).getByCanonicalName
return get_script_by_name(...)
end
local function get_wm_lang_by_code(...)
get_wm_lang_by_code = require(wikimedia_languages_module).getByCode
return get_wm_lang_by_code(...)
end
local function get_wm_lang_by_code_with_fallback(...)
get_wm_lang_by_code_with_fallback = require(wikimedia_languages_module).getByCodeWithFallback
return get_wm_lang_by_code_with_fallback(...)
end
local function gsplit(...)
gsplit = require(string_utilities_module).gsplit
return gsplit(...)
end
local function is_callable(...)
is_callable = require(functions_module).is_callable
return is_callable(...)
end
local function is_integer(...)
is_integer = require(math_module).is_integer
return is_integer(...)
end
local function is_internal_title(...)
is_internal_title = require(pages_module).is_internal_title
return is_internal_title(...)
end
local function is_positive_integer(...)
is_positive_integer = require(math_module).is_positive_integer
return is_positive_integer(...)
end
local function iterate_list(...)
iterate_list = require(table_module).iterateList
return iterate_list(...)
end
local function num_keys(...)
num_keys = require(table_module).numKeys
return num_keys(...)
end
local function parse_gender_and_number_spec(...)
parse_gender_and_number_spec = require(gender_and_number_utilities_module).parse_gender_and_number_spec
return parse_gender_and_number_spec(...)
end
local function parse_references(...)
parse_references = require(references_module).parse_references
return parse_references(...)
end
local function pattern_escape(...)
pattern_escape = require(string_utilities_module).pattern_escape
return pattern_escape(...)
end
local function php_trim(...)
php_trim = require(scribunto_module).php_trim
return php_trim(...)
end
local function scribunto_parameter_key(...)
scribunto_parameter_key = require(scribunto_module).scribunto_parameter_key
return scribunto_parameter_key(...)
end
local function sort(...)
sort = require(collation_module).sort
return sort(...)
end
local function sorted_pairs(...)
sorted_pairs = require(table_module).sortedPairs
return sorted_pairs(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function split_labels_on_comma(...)
split_labels_on_comma = require(labels_module).split_labels_on_comma
return split_labels_on_comma(...)
end
local function split_on_comma(...)
split_on_comma = require(parse_utilities_module).split_on_comma
return split_on_comma(...)
end
local function tonumber_extended(...)
tonumber_extended = require(math_module).tonumber_extended
return tonumber_extended(...)
end
local function track(...)
track = require(parameters_track_module)
return track(...)
end
local function yesno(...)
yesno = require(yesno_module)
return yesno(...)
end
--[==[ intro:
This module is used to standardize template argument processing and checking. A typical workflow is as follows (based
on [[Module:translations]]):
{
...
local parent_args = frame:getParent().args
local params = {
[1] = {required = true, type = "language", default = "und"},
[2] = true,
[3] = {list = true},
["alt"] = true,
["id"] = true,
["sc"] = {type = "script"},
["tr"] = true,
["ts"] = true,
["lit"] = true,
}
local args = require("Module:parameters").process(parent_args, params)
-- Do further processing of the parsed arguments in `args`.
...
}
The `params` table should have the parameter names as the keys, and a (possibly empty) table of parameter tags as the
value. An empty table as the value merely states that the parameter exists, but should not receive any special
treatment; if desired, empty tables can be replaced with the value `true` as a perforamnce optimization.
Possible parameter tags are listed below:
; {required = true}
: The parameter is required; an error is shown if it is not present. The template's page itself is an exception; no
error is shown there.
; {default =}
: Specifies a default input value for the parameter, if it is absent or empty. This will be processed as though it were
the input instead, so (for example) {default = "und"} with the type {"language"} will return a language object for
[[:Category:Undetermined language|Undetermined language]] if no language code is provided. When used on list
parameters, this specifies a default value for the first item in the list only. Note that it is not possible to
generate a default that depends on the value of other parameters. If used together with {required = true}, the default
applies only to template pages (see the following entry), as a side effect of the fact that "required" parameters
aren't actually required on template pages. This can be used to show an example of the template in action when the
template page is visited; however, it is preferred to use `template_default` for this purpose, for clarity.
; {template_default =}
: Specifies a default input value for absent or empty parameters only on the template demo invocation (the invocation of
the template that is displayed when the template page that implements the template is viewed). Template pages are
pages in template space that invoke (through {{tl|#invoke:}}) the module that implements the template and calls
[[Module:parameters]]. For example, the page [[Template:en-noun]] implements the {{tl|en-noun}} template, which in
turn invokes [[Module:en-headword]], and is a template page for [[Module:en-headword]]. When the template page
[[Template:en-noun]] is visited, the {{tl|#invoke:}} of the template's module is expanded as if the template were
called without arguments, and the output is inserted at that point into the processed page. This output serves as a
sort of demo of the template's functionality. `template_default` can be used to supply default values for use only in
this demo. Since the template page may also contain other invocations of the same template (e.g. on the template's
documentation page, which is typically transcluded into the template page itself), `template_default` does not apply
if there are any arguments passed to the template or if the template is invoked on any other page but its own template
page (which is checked by comparing the name of the invoking template to the current pagename). Both
`template_default` and `default` can be specified for the same parameter. If this is done, `template_default` applies
for the argumentless template invocation on the template page, and `default` in all other circumstances As an example,
{{tl|cs-IPA}} uses the equivalent of {[1] = {default = "+", template_default = "příklad"}} to supply a default of
{"+"} for mainspace and documentation pages (which tells the module to use the value of the {{para|pagename}}
parameter, falling back to the actual pagename), but {"příklad"} (which means "example"), on [[Template:cs-IPA]].
; {alias_of =}
: Treat the parameter as an alias of another. When arguments are specified for this parameter, they will automatically
be renamed and stored under the alias name. This allows for parameters with multiple alternative names, while still
treating them as if they had only one name. The conversion-related properties of an aliased parameter (e.g. `type`,
`set`, `convert`, `sublist`) are taken from the aliasee, and the corrresponding properties set on the alias itself
are ignored; but other properties on the alias are taken from the alias's spec and not from the aliasee's spec. This
means, for example, that if you create an alias of a list parameter, the alias must also specify the `list` property
or it is not a list. (In such a case, a value specified for the alias goes into the first item of the aliasee's list.
You cannot make a list alias of a non-list parameter; this causes an error to be thrown.) Similarly, if you specify
`separate_no_index` on an aliasee but not on the alias, uses of the unindexed aliasee parameter are stored into the
`.default` key, but uses of the unindexed alias are stored into the first numbered key of the aliasee's list.
Aliases cannot be required, as this prevents the other name or names of the parameter from being used. Parameters
that are aliases and required at the same time cause an error to be thrown.
; {allow_empty = true}
: If the argument is an empty string value, it is not converted to {nil}, but kept as-is. The use of `allow_empty` is
disallowed if a type has been specified, and causes an error to be thrown.
; {no_trim = true}
: Spacing characters such as spaces and newlines at the beginning and end of a positional parameter are not removed.
(MediaWiki itself automatically trims spaces and newlines at the edge of named parameters.) The use of `no_trim` is
disallowed if a type has been specified, and causes an error to be thrown.
; {type =}
: Specifies what value type to convert the argument into. The default is to leave it as a text string. Alternatives are:
:; {type = "boolean"}
:: The value is treated as a boolean value, either true or false. No value, the empty string, and the strings {"0"},
{"no"}, {"n"}, {"false"}, {"f"} and {"off"} are treated as {false}, all other values are considered {true}.
:; {type = "number"}
:: The value is converted into a number, and throws an error if the value is not parsable as a number. Input values may
be signed (`+` or `-`), and may contain decimal points and leading zeroes. If {allow_hex = true}, then hexadecimal
values in the form {"0x100"} may optionally be used instead, which otherwise have the same syntax restrictions
(including signs, decimal digits, and leading zeroes after {"0x"}). Hexadecimal inputs are not case-sensitive. Lua's
special number values (`inf` and `nan`) are not possible inputs.
:; {type = "range"}
:: The value is interpreted as a hyphen-separated range of two numbers (e.g. {"2-4"} is interpreted as the range from
{2} to {4}). A number input without a hyphen is interpreted as a range from that number to itself (e.g. the input {"1"} is interpreted as the range from {1} to {1}). Any optional flags which are available for numbers will also work for ranges.
:; {type = "language"}
:: The value is interpreted as a full or [[Wiktionary:Languages#Etymology-only languages|etymology-only language]] code
language code (or name, if {method = "name"}) and converted into the corresponding object (see [[Module:languages]]).
If the code or name is invalid, then an error is thrown. The additional setting {family = true} can be given to allow
[[Wiktionary:Language families|language family codes]] to be considered valid and the corresponding object returned.
Note that to distinguish an etymology-only language object from a full language object, use
{object:hasType("language", "etymology-only")}.
:; {type = "full language"}
:: The value is interpreted as a full language code (or name, if {method = "name"}) and converted into the corresponding
object (see [[Module:languages]]). If the code or name is invalid, then an error is thrown. Etymology-only languages
are not allowed. The additional setting {family = true} can be given to allow
[[Wiktionary:Language families|language family codes]] to be considered valid and the corresponding object returned.
:; {type = "Wikimedia language"}
:: The value is interpreted as a code and converted into a Wikimedia language object. If the code is invalid, then an
error is thrown. If {fallback = true} is specified, conventional language codes which are different from their
Wikimedia equivalent will also be accepted as a fallback.
:; {type = "family"}
:: The value is interpreted as a language family code (or name, if {method = "name"}) and converted into the
corresponding object (see [[Module:families]]). If the code or name is invalid, then an error is thrown.
:; {type = "script"}
:: The value is interpreted as a script code (or name, if {method = "name"}) and converted into the corresponding object
(see [[Module:scripts]]). If the code or name is invalid, then an error is thrown.
:; {type = "title"}
:: The value is interpreted as a page title and converted into the corresponding object (see the
[[mw:Extension:Scribunto/Lua_reference_manual#Title_library|Title library]]). If the page title is invalid, then an
error is thrown; by default, external titles (i.e. those on other wikis) are not treated as valid. Options are:
::; {namespace = n}
::: The default namespace, where {n} is a namespace number; this is treated as {0} (the mainspace) if not specified.
::; {allow_external = true}
::: External titles are treated as valid.
::; {prefix = "namespace override"} (default)
::: The default namespace prefix will be prefixed to the value is already prefixed by a namespace prefix. For instance,
the input {"Foo"} with namespace {10} returns {"Template:Foo"}, {"Wiktionary:Foo"} returns {"Wiktionary:Foo"}, and
{"Template:Foo"} returns {"Template:Foo"}. Interwiki prefixes cannot act as overrides, however: the input {"fr:Foo"}
returns {"Template:fr:Foo"}.
::; {prefix = "force"}
::: The default namespace prefix will be prefixed unconditionally, even if the value already appears to be prefixed.
This is the way that {{tl|#invoke:}} works when calling modules from the module namespace ({828}): the input {"Foo"}
returns {"Module:Foo"}, {"Wiktionary:Foo"} returns {"Module:Wiktionary:Foo"}, and {"Module:Foo"} returns
{"Module:Module:Foo"}.
::; {prefix = "full override"}
::: The same as {prefix = "namespace override"}, except that interwiki prefixes can also act as overrides. For instance,
{"el:All topics"} with namespace {14} returns {"el:Category:All topics"}. Due to the limitations of MediaWiki, only
the first prefix in the value may act as an override, so the namespace cannot be overridden if the first prefix is
an interwiki prefix: e.g. {"el:Template:All topics"} with namespace {14} returns {"el:Category:Template:All topics"}.
:; {type = "parameter"}
:: The value is interpreted as the name of a parameter, and will be normalized using the method that Scribunto uses when
constructing a {frame.args} table of arguments. This means that integers will be converted to numbers, but all other
arguments will remain as strings (e.g. {"1"} will be normalized to {1}, but {"foo"} and {"1.5"} will remain
unchanged). Note that Scribunto also trims parameter names, following the same trimming method that this module
applies by default to all parameter types.
:: This type is useful when one set of input arguments is used to construct a {params} table for use in a subsequent
{export.process()} call with another set of input arguments; for instance, the set of valid parameters for a template
might be defined as {{tl|#invoke:[some module]|args=}} in the template, where {args} is a sublist of valid parameters
for the template.
:; {type = "qualifier"}
:: The value is interpreted as a qualifier and converted into the correct format for passing into `format_qualifiers()`
in [[Module:qualifier]] (which currently just means converting it to a one-item list).
:; {type = "labels"}
:: The value is interpreted as a comma-separated list of labels and converted into the correct format for passing into
`show_labels()` in [[Module:labels]] (which is currently a list of strings). Splitting is done on commas not followed
by whitespace, except that commas inside of double angle brackets do not count even if not followed by whitespace.
This type should be used by for normal labels (typically specified using {{para|l}} or {{para|ll}}) and accent
qualifiers (typically specified using {{para|a}} and {{para|aa}}).
:; {type = "references"}
:: The value is interpreted as one or more references, in the format prescribed by `parse_references()` in
[[Module:references]], and converted into a list of objects of the form accepted by `format_references()` in the same
module. If a syntax error is found in the reference format, an error is thrown.
:; {type = "genders"}
:: The value is interpreted as one or more comma-separated gender/number specs, in the format prescribed by
[[Module:gender and number]]. Inline modifiers (`<q:...>`, `<qq:...>`, `<l:...>`, `<ll:...>` or `<ref:...>`) may be
attached to a gender/number spec.
:; {type = "form of tags"}
:: The value is interpreted as an ampersand-separated list of grammar tags and converted into the correct format
for passing as `tags` into `tagged_inflections()` in [[Module:form of]] (which is currently a list of strings).
Splitting is always done by ampersands. This type should be used by for inflection qualifiers that act as
grammar tags (typically specified using {{para|infl}}).
:; {type = function(val) ... end}
:: `type` may be set to a function (or callable table), which must take the argument value as its sole argument, and must
output one of the other recognized types. This is particularly useful for lists (see below), where certain values need
to be interpreted differently to others.
; {list =}
: Treat the parameter as a list of values, each having its own parameter name, rather than a single value. The
parameters will have a number at the end, except optionally for the first (but see also {require_index = true}). For
example, {list = true} on a parameter named "head" will include the parameters {{para|head}} (or {{para|head1}}),
{{para|head2}}, {{para|head3}} and so on. If the parameter name is a number, another number doesn't get appended, but
the counting simply continues, e.g. for parameter {3} the sequence is {{para|3}}, {{para|4}}, {{para|5}} etc. List
parameters are returned as numbered lists, so for a template that is given the parameters `|head=a|head2=b|head3=c`,
the processed value of the parameter {"head"} will be { { "a", "b", "c" }}}.
: The value for {list =} can also be a string. This tells the module that parameters other than the first should have a
different name, which is useful when the first parameter in a list is a number, but the remainder is named. An example
would be for genders: {list = "g"} on a parameter named {1} would have parameters {{para|1}}, {{para|g2}}, {{para|g3}}
etc.
: If the number is not located at the end, it can be specified by putting {"\1"} at the number position. For example,
parameters {{para|f1accel}}, {{para|f2accel}}, ... can be captured by using the parameter name {"f\1accel"}, as is
done in [[Module:headword/templates]].
; {set =}
: Require that the value of the parameter be one of the specified values (or omitted, if {required = true} isn't given).
Two formats are allowed; either a list of possible values can be supplied, or a table can be supplied where the keys
are allowed values and the values are either `true` or a string naming a value found elsewhere in the table as a key.
In the latter case, the key is an alias and the value is the canonical value, and if the user uses the alias, it will
automatically be mapped to the canonical value. In such a case, the canonical value cannot itself be an alias. The use
of `set` is disallowed if {type = "boolean"} and causes an error to be thrown.
; {sublist =}
: The value of the parameter is a delimiter-separated list of individual raw values. The resulting field in `args` will
be a Lua list (i.e. a table with numeric indices) of the converted values. If {sublist = true} is given, the values
will be split on commas (possibly with whitespace on one or both sides of the comma, which is ignored). If
{sublist = "comma without whitespace"} is given, the values will be split on commas which are not followed by whitespace,
and which aren't preceded by an escaping backslash. Otherwise, the value of `sublist` should be either a Lua pattern
specifying the delimiter(s) to split on or a function (or callable table) to do the splitting, which is passed two values
(the value to split and a function to signal an error) and should return a list of the split values.
; {convert =}
: If given, this specifies a function (or callable table) to convert the raw parameter value into the Lua object used
during further processing. The function is passed two arguments, the raw parameter value itself and a function used to
signal an error during parsing or conversion, and should return one value, the converted parameter. The error-signaling
function contains the name and raw value of the parameter embedded into the message it generates, so these do not need to
specified in the message passed into it. If `type` is specified in conjunction with `convert`, the processing by
`type` happens first. If `sublist` is given in conjunction with `convert`, the raw parameter value will be split
appropriately and `convert` called on each resulting item.
; {allow_hex = true}
: When used in conjunction with {type = "number"}, allows hexadecimal numbers as inputs, in the format {"0x100"} (which is
not case-sensitive).
; {family = true}
: When used in conjunction with {type = "language"}, allows [[Wiktionary:Language families|language family codes]] to be
returned. To check if a given object refers to a language family, use {object:hasType("family")}.
; {method = "name"}
: When used in conjunction with {type = "language"}, {type = "family"} or {type = "script"}, checks for and parses a
language, family or script name instead of a code.
; {allow_holes = true}
: This is used in conjunction with list-type parameters. By default, the values are tightly packed in the resulting
list. This means that if, for example, an entry specified `head=a|head3=c` but not {{para|head2}}, the returned list
will be { {"a", "c"}}}, with the values stored at the indices {1} and {2}, not {1} and {3}. If it is desirable to keep
the numbering intact, for example if the numbers of several list parameters correlate with each other (like those of
{{tl|affix}}), then this tag should be specified.
: If {allow_holes = true} is given, there may be {nil} values in between two real values, which makes many of Lua's
table processing functions no longer work, like {#} or {ipairs()}. To remedy this, the resulting table will contain an
additional named value, `maxindex`, which tells you the highest numeric index that is present in the table. In the
example above, the resulting table will now be { { "a", nil, "c", maxindex = 3}}}. That way, you can iterate over the
values from {1} to `maxindex`, while skipping {nil} values in between.
; {disallow_holes = true}
: This is used in conjunction with list-type parameters. As mentioned above, normally if there is a hole in the source
arguments, e.g. `head=a|head3=c` but not {{para|head2}}, it will be removed in the returned list. If
{disallow_holes = true} is specified, however, an error is thrown in such a case. This should be used whenever there
are multiple list-type parameters that need to line up (e.g. both {{para|head}} and {{para|tr}} are available and
{{para|head3}} lines up with {{para|tr3}}), unless {allow_holes = true} is given and you are prepared to handle the
holes in the returned lists.
; {disallow_missing = true}
: This is similar to {disallow_holes = true}, but an error will not be thrown if an argument is blank, rather than
completely missing. This may be used to tolerate intermediate blank numerical parameters, which sometimes occur in list
templates. For instance, `head=a|head2=|head3=c` will not throw an error, but `head=a|head3=c` will.
; {require_index = true}
: This is used in conjunction with list-type parameters. By default, the first parameter can have its index omitted.
For example, a list parameter named `head` can have its first parameter specified as either {{para|head}} or
{{para|head1}}. If {require_index = true} is specified, however, only {{para|head1}} is recognized, and {{para|head}}
will be treated as an unknown parameter. {{tl|affixusex}} (and variants {{tl|suffixusex}}, {{tl|prefixusex}}) use
this, for example, on all list parameters.
; {separate_no_index = true}
: This is used to distinguish between {{para|head}} and {{para|head1}} as different parameters. For example, in
{{tl|affixusex}}, to distinguish between {{para|sc}} (a script code for all elements in the usex's language) and
{{para|sc1}} (the script code of the first element, used when the first element is prefixed with a language code to
indicate that it is in a different language). When this is used, the resulting table will contain an additional named
value, `default`, which contains the value for the indexless argument.
; {flatten = true}
: This is used in conjunction with list-type parameters when `sublist` or a list-generating type such as {"labels"} or
{"genders"} is also specified, and causes the resulting list to be flattened. Not currently compatible with
{allow_holes = true}.
; {replaced_by =}
: Specifies that the parameter is no longer valid, and has been replaced by some other mechanism. If the value of
`replaced_by` is a string, it is the name of the new parameter to use instead. Use the `reason` tag to specify the
reason why this change has been made, e.g.
{reason = "for consistency with the corresponding parameter in other Romance-language headword templates"}. If the
value of `replaced_by` is {false}, there is no replacement parameter. In this case, `instead` should be supplied
with a description of what to do instead, e.g.
{instead = "use an inline modifier on |2= such as <q:...>, <qq:...>, <l:...> or <ll:...>"}. You can also supply a
justification in `reason` if you feel it is appropriate or necessary to do so.
; {reason =}
: When used in conjunction with `replaced_by`, specifies the reason for the parameter replacement.
; {instead =}
: When used in conjunction with {replaced_by = false}, specifies what to do instead of using the removed parameter.
; {demo = true}
: This is used as a way to ensure that the parameter is only enabled on the template's own page (and its documentation
page), and in the User: namespace; otherwise, it will be treated as an unknown parameter. This should only be used if
special settings are required to showcase a template in its documentation (e.g. adjusting the pagename or disabling
categorization). In most cases, it should be possible to do this without using demo parameters, but they may be
required if a template/documentation page also contains real uses of the same template as well (e.g. {{tl|shortcut}}),
as a way to distinguish them.
; {deprecated = true}
: This is for tracking the use of deprecated parameters, including any aliases that are being brought out of use. See
[[Wiktionary:Tracking]] for more information.
]==]
-- Returns true if the current page is a template or module containing the current {{#invoke}}.
-- If the include_documentation argument is given, also returns true if the current page is either page's documentation page.
local own_page, own_page_or_documentation
local function is_own_page(include_documentation)
if own_page == nil then
if current_namespace == nil then
local current_title = mw_title.getCurrentTitle()
current_title_text, current_namespace = current_title.prefixedText, current_title.namespace
end
local frame = current_namespace == 828 and mw.getCurrentFrame() or
current_namespace == 10 and mw.getCurrentFrame():getParent()
if frame then
local frame_title_text = frame:getTitle()
own_page = current_title_text == frame_title_text
own_page_or_documentation = own_page or current_title_text == frame_title_text .. "/documentation"
else
own_page, own_page_or_documentation = false, false
end
end
return include_documentation and own_page_or_documentation or own_page
end
-------------------------------------- Some helper functions -----------------------------
-- Convert a list in `list` to a string, separating the final element from the preceding one(s) by `conjunction`. If
-- `dump_vals` is given, pass all values in `list` through mw.dumpObject() (WARNING: this destructively modifies
-- `list`). This is similar to serialCommaJoin() in [[Module:table]] when used with the `dontTag = true` option, but
-- internally uses mw.text.listToText().
local function concat_list(list, conjunction, dump_vals)
if dump_vals then
for k, v in pairs(list) do
list[k] = dump(v)
end
end
return list_to_text(list, nil, conjunction)
end
-- A helper function for use with generating error-signaling functions in the presence of raw value conversion. Format a
-- message `msg`, including the processed value `processed` if it is different from the raw value `rawval`; otherwise,
-- just return `msg`.
local function msg_with_processed(msg, rawval, processed)
if rawval == processed then
return msg
end
local processed_type = type(processed)
return format("%s (processed value %s)",
msg, (processed_type == "string" or processed_type == "number") and processed or dump(processed)
)
end
-- Separate form of tags with ampersand (&).
local function split_tags_on_ampersand(tags)
return split(tags, "&")
end
-------------------------------------- Error handling -----------------------------
local function process_error(fmt, ...)
local args = {...}
for i, val in ipairs(args) do
args[i] = dump(val)
end
if type(fmt) == "table" then
-- hacky signal that we're called from internal_process_error(), and not to omit stack frames
return error(format(fmt[1], unpack(args)))
end
return error(format(fmt, unpack(args)), 3)
end
local function internal_process_error(fmt, ...)
process_error({"Internal error in `params` table: " .. fmt}, ...)
end
-- Check that a parameter or argument is in the form form Scribunto normalizes input argument keys into (e.g. 1 not "1", "foo" not " foo "). Otherwise, it won't be possible to normalize inputs in the expected way. Unless is_argument is set, also check that the name only contains one placeholder at most, and that strings don't resolve to numeric keys once the placeholder has been substituted.
local function validate_name(name, desc, extra_name, is_argument)
local normalized = scribunto_parameter_key(name)
if name and name == normalized then
if is_argument or type(name) ~= "string" then
return
end
local placeholder = find(name, "\1", nil, true)
if not placeholder then
return
elseif find(name, "\1", placeholder + 1, true) then
error(format(
"Internal error: expected %s to only contain one placeholder, but saw %s",
extra_name and (desc .. dump(extra_name)) or desc, dump(name)
))
end
local first_name = gsub(name, "\1", "1")
normalized = scribunto_parameter_key(first_name)
if first_name == normalized then
return
end
error(format(
"Internal error: %s cannot resolve to numeric parameters once any placeholder has been substituted, but %s resolves to %s",
extra_name and (desc .. dump(extra_name)) or desc, dump(name), dump(normalized)
))
elseif normalized == nil then
error(format(
"Internal error: expected %s to be of type string or number, but saw %s",
extra_name and (desc .. dump(extra_name)) or desc, type(name)
))
end
error(format(
"Internal error: expected %s to be Scribunto-compatible: %s (a %s) should be %s (a %s)",
extra_name and (desc .. dump(extra_name)) or desc, dump(name), type(name), dump(normalized), type(normalized)
))
end
local function validate_alias_options(...)
local invalid = {
required = true,
default = true,
template_default = true,
allow_holes = true,
disallow_holes = true,
disallow_missing = true,
}
function validate_alias_options(param, name, main_param, alias_of)
for k in pairs(param) do
if invalid[k] then
track("bad alias option")
-- internal_process_error(
-- "parameter %s cannot have the option %s, as it is an alias of parameter %s.",
-- name, option, alias_of
-- )
end
end
-- Soon, aliases will inherit options from the main parameter via __index. Track cases where this would happen.
if main_param ~= true then
for k in pairs(main_param) do
if param[k] == nil and not invalid[k] then
if k == "list" then -- these need to be changed to list = false to retain current behaviour
track("mismatched list alias option")
elseif not (k == "type" or k == "set" or k == "sublist") then -- rarely specified on aliases, as they're effectively inherited already
track("mismatched alias option")
end
end
end
end
end
validate_alias_options(...)
end
-- TODO: give ranges instead of long lists, if possible.
--[==[ func: export.params_list_error(params, msg)
Given a key-value table of raw parameters `params`, display an error message about all the parameters seen in the table.
The parameter names are displayed in sorted order. `msg` should be e.g. {"required"} or {"not used by this template"}.
This is used internally to display error messages about required or invalid parameters, and can be used for the same
purpose by code that processes its own parameters (e.g. if the `return_unknown` flag is specified to `process`).
]==]
local function params_list_error(params, msg)
local list, n = {}, 0
for name in sorted_pairs(params) do
n = n + 1
list[n] = name
end
error(format(
"Parameter%s %s.",
format(n == 1 and " %s is" or "s %s are", concat_list(list, " and ", true)),
msg
), 3)
end
export.params_list_error = params_list_error
-- Helper function for use with convert_val_error(). Format a list of possible choices using `concat_list` and
-- conjunction "or", displaying "either " before the choices if there's more than one.
local function format_choice_list(valid)
return (#valid > 1 and "either " or "") .. concat_list(valid, " or ")
end
-- Signal an error for a value `val` that is not of the right type `valid` (which is either a string specifying a type, or
-- a list of possible values, in the case where `set` was used). `name` is the name of the parameter and can be a
-- function to signal an error (which is assumed to automatically display the parameter's name and value). `seetext` is
-- an optional additional explanatory link to display (e.g. [[WT:LOL]], the list of possible languages and codes).
local function convert_val_error(val, name, valid, seetext)
if is_callable(name) then
if type(valid) == "table" then
valid = "choice, must be " .. format_choice_list(valid)
end
name(format("Invalid %s; the value %s is not valid%s", valid, val, seetext and "; see " .. seetext or ""))
else
if type(valid) == "table" then
valid = format_choice_list(valid)
else
valid = "a valid " .. valid
end
error(format("Parameter %s must be %s; the value %s is not valid.%s", dump(name), valid, dump(val),
seetext and " See " .. seetext .. "." or ""))
end
end
-- Generate the appropriate error-signaling function given parameter value `val` and name `name`. If `name` is already
-- a function, it is just returned; otherwise a function is generated and returned that displays the passed-in messaeg
-- along with the parameter's name and value.
local function make_parse_err(val, name)
if is_callable(name) then
return name
end
return function(msg)
error(format("%s: parameter %s=%s", msg, name, val))
end
end
-------------------------------------- Value conversion -----------------------------
-- For a list parameter `name` and corresponding value `list_name` of the `list` field (which should have the same value
-- as `name` if `list = true` was given), generate a pattern to match parameters of the list and store the pattern as a
-- key in `patterns`, with corresponding value set to `name`. For example, if `list_name` is "tr", the pattern will
-- match "tr" as well as "tr1", "tr2", ..., "tr10", "tr11", etc. If the `list_name` contains a \1 in it, the numeric
-- portion goes in place of the \1. For example, if `list_name` is "f\1accel", the pattern will match "faccel",
-- "f1accel", "f2accel", etc. Any \1 in `name` is removed before storing into `patterns`.
local function save_pattern(name, list_name, patterns)
name = type(name) == "string" and gsub(name, "\1", "") or name
if find(list_name, "\1", nil, true) then
patterns["^" .. gsub(pattern_escape(list_name), "\1", "([1-9]%%d*)") .. "$"] = name
else
patterns["^" .. pattern_escape(list_name) .. "([1-9]%d*)$"] = name
list_name = list_name .. "\1"
end
validate_name(list_name, "the list field of parameter ", name)
return patterns
end
-- A helper function for use with `sublist`. It is an iterator function for use in a for-loop that returns split
-- elements of `val` using `sublist` (a Lua split pattern; boolean `true` to split on commas optionally surrounded by
-- whitespace; "comma without whitespace" to split only on commas not followed by whitespace which have not been escaped
-- by a backslash; or a function to do the splitting, which is passed two values, the value to split and a function to
-- signal an error, and should return a list of the split elements). `name` is the parameter name or error-signaling
-- function passed into convert_val().
local function split_sublist(val, name, sublist)
if sublist == true then
return gsplit(val, "%s*,%s*")
-- Split an argument on comma, but not comma followed by whitespace.
elseif sublist == "comma without whitespace" then
-- If difficult cases, use split_on_comma.
if find(val, "\\", nil, true) or match(val, ",%s") then
return iterate_list(split_on_comma(val))
end
-- Otherwise, use gsplit.
return gsplit(val, ",")
elseif type(sublist) == "string" then
return gsplit(val, sublist)
elseif not is_callable(sublist) then
error(format('Internal error: expected `sublist` to be of type "string" or "function" or boolean `true`, but saw %s', dump(sublist)))
end
return iterate_list(sublist(val, make_parse_err(val, name)))
end
-- For parameter named `name` with value `val` and param spec `param`, if the `set` field is specified, verify that the
-- value is one of the one specified in `set`, and throw an error otherwise. `name` is taken directly from the
-- corresponding parameter passed into convert_val() and may be a function to signal an error. Optional `param_type` is
-- a string specifying the conversion type of `val` and is used for special-casing: If `param_type` is "boolean", an
-- internal error is thrown (since `set` cannot be used in conjunction with booleans) and if `param_type` is "number",
-- no checking happens because in this case `set` contains numbers and is checked inside the number conversion function
-- itself, after converting `val` to a number. Return the canonical value of `val` (which may be different from `val`
-- if an alias map is given).
local function check_set(val, name, param, param_type)
if param_type == "boolean" then
error(format('Internal error: cannot use `set` with `type = "%s"`', param_type))
-- Needs to be special cased because the check happens after conversion to numbers.
elseif param_type == "number" then
return val
end
local set, map = param.set
if sets == nil then
map = finalize_set(set, name)
sets = {[set] = map}
else
map = sets[set]
if map == nil then
map = finalize_set(set, name)
sets[set] = map
end
end
local newval = map[val]
if newval == true then
return val
elseif newval ~= nil then
return newval
end
local list = {}
for k, v in sorted_pairs(map) do
if v == true then
insert(list, dump(k))
else
insert(list, ("%s (alias of %s)"):format(dump(k), dump(v)))
end
end
-- If the parameter is not required then put "or empty" at the end of the list, to avoid implying the parameter is actually required.
if not param.required then
insert(list, "empty")
end
convert_val_error(val, name, list)
end
local function convert_language(val, name, param, allow_etym)
local method, func = param.method
if method == nil or method == "code" then
func, method = get_language_by_code, "code"
elseif method == "name" then
func, method = get_language_by_name, "name"
else
error(format('Internal error: expected `method` for type `language` to be "code", "name" or undefined, but saw %s', dump(method)))
end
local lang = func(val, nil, allow_etym, param.family)
if lang then
return lang
end
local list, links = {"language"}, {"[[WT:LOL]]"}
if allow_etym then
insert(list, "etymology language")
insert(links, "[[WT:LOL/E]]")
end
if param.family then
insert(list, "family")
insert(links, "[[WT:LOF]]")
end
convert_val_error(val, name, concat_list(list, " or ") .. " " .. (method == "name" and "name" or "code"), concat_list(links, " and "))
end
local function convert_number(val, allow_hex)
-- Call tonumber_extended with the `real_finite` flag, which filters out ±infinity and NaN.
-- By default, specify base 10, which prevents 0x hex inputs from being converted.
-- If `allow_hex` is set, then don't give a base, which means 0x hex inputs will work.
local num = tonumber_extended(val, not allow_hex and 10 or nil, "finite_real")
if not num then
return num
end
if match(val, "[eEpP.]") then -- float
track("number not an integer")
end
if find(val, "+", nil, true) then
track("number with +")
end
-- Track various unusual number inputs to determine if it should be restricted to positive integers by default (possibly including 0).
if not is_positive_integer(num) then
track("number not a positive integer")
if num == 0 then
track("number is 0")
elseif not is_integer(num) then
track("number not an integer")
end
end
return num
end
-- TODO: validate parameter specs separately, as it's making the handler code really messy at the moment.
local type_handlers = setmetatable({
["boolean"] = function(val)
return yesno(val, true)
end,
["family"] = function(val, name, param)
local method, func = param.method
if method == nil or method == "code" then
func, method = get_family_by_code, "code"
elseif method == "name" then
func, method = get_family_by_name, "name"
else
error(format('Internal error: expected `method` for type `family` to be "code", "name" or undefined, but saw %s', dump(method)))
end
return func(val) or convert_val_error(val, name, "family " .. method, "[[WT:LOF]]")
end,
["labels"] = function(val, name, param)
-- FIXME: Should be able to pass in a parse_err function.
return split_labels_on_comma(val)
end,
["form of tags"] = function(val, name, param)
return split_tags_on_ampersand(val)
end,
["language"] = function(val, name, param)
return convert_language(val, name, param, true)
end,
["full language"] = convert_language,
["number"] = function(val, name, param)
local allow_hex = param.allow_hex
if allow_hex and allow_hex ~= true then
error(format(
'Internal error: expected `allow_hex` for type `number` to be of type "boolean" or undefined, but saw %s',
dump(allow_hex)
))
end
local num = convert_number(val, allow_hex)
if param.set then
-- Don't pass in "number" here; otherwise no checking will happen.
num = check_set(num, name, param)
end
if num then
return num
end
convert_val_error(val, name, (allow_hex and "decimal or hexadecimal " or "") .. "number")
end,
["range"] = function(val, name, param)
local allow_hex = param.allow_hex
if allow_hex and allow_hex ~= true then
error(format(
'Internal error: expected `allow_hex` for type `range` to be of type "boolean" or undefined, but saw %s',
dump(allow_hex)
))
end
-- Pattern ensures leading minus signs are accounted for.
local m1, m2 = match(val, "^(%s*%S.-)%-(%s*%S.*)")
if m1 then
m1 = convert_number(m1, allow_hex)
if m1 then
m2 = convert_number(m2, allow_hex)
if m2 then
return {m1, m2}
end
end
end
-- Try `val` if it couldn't be split into a range, and return a range of `val` to `val` if possible.
local num = convert_number(val, allow_hex)
if num then
return {num, num}
end
convert_val_error(val, name, (allow_hex and "decimal or hexadecimal " or "") .. "number or a hyphen-separated range of two numbers")
end,
["parameter"] = function(val, name, param)
-- Use the `no_trim` option, as any trimming will have already been done.
return scribunto_parameter_key(val, true)
end,
["qualifier"] = function(val, name, param)
return {val}
end,
["references"] = function(val, name, param)
return parse_references(val, make_parse_err(val, name))
end,
["genders"] = function(val, name, param)
if not val:find("[,<]") then
return {{spec = val}}
end
-- NOTE: We don't pass in allow_space_around_comma. Consistent with other comma-separated types, there shouldn't
-- be spaces around the comma.
return parse_gender_and_number_spec {
spec = val,
parse_err = make_parse_err(val, name),
allow_multiple = true,
}
end,
["script"] = function(val, name, param)
local method, func = param.method
if method == nil or method == "code" then
func, method = get_script_by_code, "code"
elseif method == "name" then
func, method = get_script_by_name, "name"
else
error(format('Internal error: expected `method` for type `script` to be "code", "name" or undefined, but saw %s', dump(method)))
end
return func(val) or convert_val_error(val, name, "script " .. method, "[[WT:LOS]]")
end,
["string"] = function(val, name, param) -- To be removed as unnecessary.
track("string")
return val
end,
-- TODO: add support for resolving to unsupported titles.
-- TODO: split this into "page name" (i.e. internal) and "link target" (i.e. external as well), which is more intuitive.
["title"] = function(val, name, param)
local namespace = param.namespace
if namespace == nil then
namespace = 0
else
local valid_type = type(namespace) ~= "number" and 'of type "number" or undefined' or
not namespaces[namespace] and "a valid namespace number" or
nil
if valid_type then
error(format('Internal error: expected `namespace` for type `title` to be %s, but saw %s', valid_type, dump(namespace)))
end
end
-- Decode entities. WARNING: mw.title.makeTitle must be called with `decoded` (as it doesn't decode) and mw.title.new must be called with `val` (as it does decode, so double-decoding needs to be avoided).
local decoded, prefix, title = decode_entities(val), param.prefix
-- If the input is a fragment, treat the title as the current title with the input fragment.
if sub(decoded, 1, 1) == "#" then
-- If prefix is "force", only get the current title if it's in the specified namespace. current_title includes the namespace prefix.
if current_namespace == nil then
local current_title = mw_title.getCurrentTitle()
current_title_text, current_namespace = current_title.prefixedText, current_title.namespace
end
if not (prefix == "force" and namespace ~= current_namespace) then
title = new_title(current_title_text .. val)
end
elseif prefix == "force" then
-- Unconditionally add the namespace prefix (mw.title.makeTitle).
title = make_title(namespace, decoded)
elseif prefix == "full override" then
-- The first input prefix will be used as an override (mw.title.new). This can be a namespace or interwiki prefix.
title = new_title(val, namespace)
elseif prefix == nil or prefix == "namespace override" then
-- Only allow namespace prefixes to override. Interwiki prefixes therefore need to be treated as plaintext (e.g. "el:All topics" with namespace 14 returns "el:Category:All topics", but we want "Category:el:All topics" instead; if the former is really needed, then the input ":el:Category:All topics" will work, as the initial colon overrides the namespace). mw.title.new can take namespace names as well as numbers in the second argument, and will throw an error if the input isn't a valid namespace, so this can be used to determine if a prefix is for a namespace, since mw.title.new will return successfully only if there's either no prefix or the prefix is for a valid namespace (in which case we want the override).
local success
success, title = pcall(new_title, val, match(decoded, "^.-%f[:]") or namespace)
-- Otherwise, get the title with mw.title.makeTitle, which unconditionally adds the namespace prefix, but behaves like mw.title.new if the namespace is 0.
if not success then
title = make_title(namespace, decoded)
end
else
error(format('Internal error: expected `prefix` for type `title` to be "force", "full override", "namespace override" or undefined, but saw %s', dump(prefix)))
end
local allow_external = param.allow_external
if allow_external == true then
return title or convert_val_error(val, name, "Wiktionary or external page title")
elseif not allow_external then
return title and is_internal_title(title) and title or convert_val_error(val, name, "Wiktionary page title")
end
error(format('Internal error: expected `allow_external` for type `title` to be of type "boolean" or undefined, but saw %s', dump(allow_external)))
end,
["Wikimedia language"] = function(val, name, param)
local fallback = param.fallback
if fallback == true then
return get_wm_lang_by_code_with_fallback(val) or convert_val_error(val, name, "Wikimedia language or language code")
elseif not fallback then
return get_wm_lang_by_code(val) or convert_val_error(val, name, "Wikimedia language code")
end
error(format('Internal error: expected `fallback` for type `Wikimedia language` to be of type "boolean" or undefined, but saw %s', dump(fallback)))
end,
}, {
-- TODO: decode HTML entities in all input values. Non-trivial to implement, because we need to avoid any downstream functions decoding the output from this module, which would be double-decoding. Note that "title" has this implemented already, and it needs to have both the raw input and the decoded input to avoid double-decoding by me.title.new, so any implementation can't be as simple as decoding in __call then passing the result to the handler.
__call = function(self, val, name, param, param_type, default)
local val_type = type(val)
-- TODO: check this for all possible parameter types.
if val_type == param_type then
return val
elseif val_type ~= "string" then
local expected = "string"
if default and (param_type == "boolean" or param_type == "number") then
expected = param_type .. " or " .. expected
end
error(format(
"Internal error: %sargument %s has the type %s; expected a %s.",
default and (default .. " for ") or "", name, dump(val_type), expected
))
end
local func = self[param_type]
if func == nil then
error(format("Internal error: %s is not a recognized parameter type.", dump(param_type)))
end
return func(val, name, param)
end
})
--[==[ func: export.convert_val(val, name, param)
Convert a parameter value according to the associated specs listed in the `params` table passed to
[[Module:parameters]]. `val` is the value to convert for a parameter whose name is `name` (used only in error messages).
`param` is the spec (the value part of the `params` table for the parameter). In place of passing in the parameter name,
`name` can be a function that throws an error, displaying the specified message along with the parameter name and value.
This function processes all the conversion-related fields in `param`, including `type`, `set`, `sublist`, `convert`,
etc. It returns the converted value.
]==]
local function convert_val(val, name, param, default)
local param_type = param.type or "string"
-- If param.type is a function, resolve it to a recognized type.
if is_callable(param_type) then
param_type = param_type(val)
end
local convert, sublist = param.convert, param.sublist
-- `val` might not be a string if it's the default value.
if sublist and type(val) == "string" then
local retlist, set = {}, param.set
if convert then
local thisindex, thisval, insval, parse_err = 0
if is_callable(name) then
-- We assume the passed-in error function in `name` already shows the parameter name and raw value.
function parse_err(msg)
name(format("%s: item #%s=%s",
msg_with_processed(msg, thisval, insval), thisindex, thisval)
)
end
else
function parse_err(msg)
error(format("%s: item #%s=%s of parameter %s=%s",
msg_with_processed(msg, thisval, insval), thisindex, thisval, name, val)
)
end
end
for v in split_sublist(val, name, sublist) do
thisindex, thisval = thisindex + 1, v
if set then
v = check_set(v, name, param, param_type)
end
insert(retlist, convert(type_handlers(v, name, param, param_type, default), parse_err))
end
else
for v in split_sublist(val, name, sublist) do
if set then
v = check_set(v, name, param, param_type)
end
insert(retlist, type_handlers(v, name, param, param_type, default))
end
end
return retlist
elseif param.set then
val = check_set(val, name, param, param_type)
end
local retval = type_handlers(val, name, param, param_type, default)
if convert then
local parse_err
if is_callable(name) then
-- We assume the passed-in error function in `name` already shows the parameter name and raw value.
if retval == val then
-- This is an optimization to avoid creating a closure. The second arm works correctly even
-- when retval == val.
parse_err = name
else
function parse_err(msg)
name(msg_with_processed(msg, val, retval))
end
end
else
function parse_err(msg)
error(format("%s: parameter %s=%s", msg_with_processed(msg, val, retval), name, val))
end
end
retval = convert(retval, parse_err)
end
-- If `sublist` is set but the input wasn't a string, return `retval` as a one-item list.
if sublist then
retval = {retval}
end
return retval
end
export.convert_val = convert_val -- used by [[Module:parameter utilities]]
local function unknown_param(name, val, args_unknown)
track("unknown parameters")
args_unknown[name] = val
return args_unknown
end
local function check_string_param_modifier(param_type, name, tag)
if param_type and not (param_type == "string" or param_type == "parameter" or is_callable(param_type)) then
internal_process_error(
"%s cannot be set unless %s is set to %s (the default), %s or a function: parameter %s has the type %s.",
tag, "type", "string", "parameter", name, param_type
)
end
end
local function hole_error(params, name, listname, this, nxt, extra)
-- `process_error` calls `dump` on values to be inserted into
-- error messages, but with numeric lists this causes "numeric"
-- to look like the name of the list rather than a description,
-- as `dump` adds quote marks. Insert it early to avoid this,
-- but add another %s specifier in all other cases, so that
-- actual list names will be displayed properly.
local offset, specifier, starting_from = 0, "%s", ""
local msg = "Item %%d in the list of %s parameters must be given if item %%d is given, because %sthere shouldn't be any gaps due to missing%s parameters."
local specs = {}
if type(listname) == "string" then
specs[2] = listname
elseif type(name) == "number" then
offset = name - 1 -- To get the original parameter.
specifier = "numeric"
-- If the list doesn't start at parameter 1, avoid implying
-- there can't be any gaps in the numeric parameters if
-- some parameter with a lower key is optional.
for j = name - 1, 1, -1 do
local _param = params[j]
if not (_param and _param.required) then
starting_from = format("(starting from parameter %d) ", dump(j + 1))
break
end
end
else
specs[2] = name
end
specs[1] = this + offset -- Absolute index for this item.
insert(specs, nxt + offset) -- Absolute index for the next item.
process_error(format(msg, specifier, starting_from, extra or ""), unpack(specs))
end
local function check_disallow_holes(params, val, name, listname, extra)
for i = 1, val.maxindex do
if val[i] == nil then
hole_error(params, name, listname, i, num_keys(val)[i], extra)
end
end
end
local function handle_holes(params, val, name)
local param = params[name]
local disallow_holes = param.disallow_holes
-- Iterate up the list, and throw an error if a hole is found.
if disallow_holes then
check_disallow_holes(params, val, name, param.list, " or empty")
end
-- Iterate up the list, and throw an error if a hole is found due to a
-- missing parameter, treating empty parameters as part of the list. This
-- applies beyond maxindex if blank arguments are supplied beyond it, so
-- isn't mutually exclusive with `disallow_holes`.
local empty = val.empty
if param.disallow_missing then
if empty then
-- Remove `empty` from `val`, so it doesn't get returned.
val.empty = nil
for i = 1, max(val.maxindex, empty.maxindex) do
if val[i] == nil and not empty[i] then
local keys = extend(num_keys(val), num_keys(empty))
sort(keys)
hole_error(params, name, param.list, i, keys[i])
end
end
-- If there's no table of empty parameters, the check is identical to
-- `disallow_holes`, except that the error message only refers to
-- missing parameters, not missing or empty ones. If `disallow_holes` is
-- also set, there's no point checking again.
elseif not disallow_holes then
check_disallow_holes(params, val, name, param.list)
end
end
-- If `allow_holes` is set, there's nothing left to do.
if param.allow_holes then
-- do nothing
-- Otherwise, remove any holes: `pairs` won't work, as it's unsorted, and
-- iterating from 1 to `maxindex` times out with inputs like |100000000000=,
-- so use num_keys to get a list of numerical keys sorted from lowest to
-- highest, then iterate up the list, moving each value in `val` to the
-- lowest unused positive integer key. This also avoids the need to create a
-- new table. If `disallow_holes` is specified, then there can't be any
-- holes in the list, so there's no reason to check again; this doesn't
-- apply to `disallow_missing`, however.
else
if not disallow_holes then
local keys, i = num_keys(val), 0
while true do
i = i + 1
local key = keys[i]
if key == nil then
break
elseif i ~= key then
track("holes compressed")
val[i], val[key] = val[key], nil
end
end
end
-- Some code depends on only numeric params being present when no holes are
-- allowed (e.g. by checking for the presence of arguments using next()), so
-- remove `maxindex`.
val.maxindex = nil
end
end
local function maybe_flatten(params, val, name)
local param = params[name]
if param.flatten then
if param.allow_holes then
process_error("For parameter %s, can't set both `allow_holes` and `flatten`", name)
end
if not param.sublist and param.type ~= "genders" and param.type ~= "labels" and
param.type ~= "references" and param.type ~= "qualifier" and param.type ~= "form of tags" then
process_error("For parameter %s, can only set `flatten` along with `sublist` or a list-generating type", name)
end
-- Do the flattening ourselves rather than calling flatten() in [[Module:table]], which will attempt to
-- flatten non-list objects like title objects, and cause an error in the process.
-- FIXME: We should do this in-place if possible.
local newlist = {}
for _, sublist in ipairs(val) do
for _, item in ipairs(sublist) do
insert(newlist, item)
end
end
val = newlist
end
return val
end
-- If both `template_default` and `default` are given, `template_default` takes precedence, but only on the template or
-- module page. This means a different default can be specified for the template or module page example. However,
-- `template_default` doesn't apply if any args are set, which helps (somewhat) with examples on documentation pages
-- transcluded into the template page. HACK: We still run into problems on documentation pages transcluded into the
-- template page when pagename= is set. Check this on the assumption that pagename= is fairly standard.
local function convert_default_val(name, param, pagename_set, any_args_set, add_empty_sublist)
if not pagename_set then
local val = param.template_default
if val ~= nil and not any_args_set and is_own_page() then
return convert_val(val, name, param, "template default")
end
end
local val = param.default
if val ~= nil then
return convert_val(val, name, param, "default")
-- Sublist parameters should return an empty table if not given, but only do
-- this if the parameter isn't also a list (in which case it will already
-- be an empty table).
-- FIXME: do this once all modules that pass in a sublist parameter treat an empty sublist identically to a nil argument; some currently do things based on the fact an argument exists at all.
-- elseif add_empty_sublist and param.sublist then
--return {}
end
end
--[==[
Process arguments with a given list of parameters. Return a table containing the processed arguments. The `args`
parameter specifies the arguments to be processed; they are the arguments you might retrieve from
{frame:getParent().args} (the template arguments) or in some cases {frame.args} (the invocation arguments). The `params`
parameter specifies a list of valid parameters, and consists of a table. If an argument is encountered that is not in
the parameter table, an error is thrown.
The structure of the `params` table is as described above in the intro comment.
'''WARNING:''' The `params` table is destructively modified to save memory. Nonetheless, different keys can share the
same value objects in memory without causing problems.
The `return_unknown` parameter, if set to {true}, prevents the function from triggering an error when it comes across an
argument with a name that it doesn't recognise. Instead, the return value is a pair of values: the first is the
processed arguments as usual, while the second contains all the unrecognised arguments that were left unprocessed. This
allows you to do multi-stage processing, where the entire set of arguments that a template should accept is not known at
once. For example, an inflection-table might do some generic processing on some arguments, but then defer processing of
the remainder to the function that handles a specific inflectional type.
]==]
function export.process(args, params, return_unknown)
-- Process parameters for specific properties
local args_new, args_unknown, any_args_set, required, patterns, list_args, index_list, args_placeholders, placeholders_n = {}
-- TODO: memoize the processing of each unique `param` value, since it's common for the same value to be used for many parameter names.
for name, param in pairs(params) do
validate_name(name, "parameter names")
if param ~= true then
local spec_type = type(param)
if type(param) ~= "table" then
internal_process_error(
"spec for parameter %s must be a table of specs or the value true, but found %s.",
name, spec_type ~= "boolean" and spec_type or param
)
end
-- Populate required table, and make sure aliases aren't set to required.
if param.required then
if required == nil then
required = {}
end
required[name] = true
end
local listname, alias_of = param.list, param.alias_of
if alias_of then
validate_name(alias_of, "the alias_of field of parameter ", name)
if alias_of == name then
internal_process_error(
"parameter %s cannot be an alias of itself.",
name
)
end
local main_param = params[alias_of]
-- Check that the alias_of is set to a valid parameter.
if not (main_param == true or type(main_param) == "table") then
internal_process_error(
"parameter %s is an alias of an invalid parameter.",
name
)
end
validate_alias_options(param, name, main_param, alias_of)
-- Aliases can't be lists unless the canonical parameter is also a list.
if listname and (main_param == true or not main_param.list) then
internal_process_error(
"list parameter %s is set as an alias of %s, which is not a list parameter.", name, alias_of
)
-- Can't be an alias of an alias.
elseif main_param ~= true then
local main_alias_of = main_param.alias_of
if main_alias_of ~= nil then
internal_process_error(
"alias_of cannot be set to another alias: parameter %s is set as an alias of %s, which is in turn an alias of %s. Set alias_of for %s to %s.",
name, alias_of, main_alias_of, name, main_alias_of
)
end
end
end
local replaced_by = param.replaced_by
if replaced_by then -- replaced_by can be `false`, which is OK
validate_name(replaced_by, "the replaced_by field of parameter ", name)
if replaced_by == name then
internal_process_error(
"parameter %s cannot be replaced by itself.",
name
)
end
local main_param = params[replaced_by]
-- Check that the replaced_by is set to a valid parameter.
if not (main_param == true or type(main_param) == "table") then
internal_process_error(
"parameter %s is set to be replaced by an invalid parameter.",
name
)
end
-- Can't be a replaced-by of a replaced-by.
if main_param ~= true then
local main_replaced_by = main_param.replaced_by
if main_replaced_by ~= nil then
internal_process_error(
"replaced_by cannot be set to another replaced-by parameter: parameter %s is set as replaced by %s, which is in turn replaced by %s. Set replaced_by for %s to %s.",
name, replaced_by, main_replaced_by, name, main_replaced_by
)
end
end
if param.instead ~= nil then
internal_process_error("the `instead` tag can only be given when `replaced_by` is set to `false`.")
end
elseif replaced_by == false then
if param.instead ~= nil and type(param.instead) ~= "string" then
internal_process_error(
"the `instead` tag must be a string, but saw %s.",
param.instead
)
end
end
if replaced_by ~= nil then
if param.reason ~= nil and type(param.reason) ~= "string" then
internal_process_error(
"the `reason` tag must be a string, but saw %s.",
param.reason
)
end
end
if listname then
if not alias_of then
local key = name
if type(name) == "string" then
key = gsub(name, "\1", "")
end
local list_arg = {maxindex = 0}
args_new[key] = list_arg
if list_args == nil then
list_args = {}
end
list_args[key] = list_arg
end
local list_type = type(listname)
if list_type == "string" then
-- If the list property is a string, then it represents the name
-- to be used as the prefix for list items. This is for use with lists
-- where the first item is a numbered parameter and the
-- subsequent ones are named, such as 1, pl2, pl3.
patterns = save_pattern(name, listname, patterns or {})
elseif listname ~= true then
internal_process_error(
"list field for parameter %s must be a boolean, string or undefined, but saw a %s.",
name, list_type
)
elseif type(name) == "number" then
if index_list ~= nil then
internal_process_error(
"only one numeric parameter can be a list, unless the list property is a string."
)
end
-- If the name is a number, then all indexed parameters from
-- this number onwards go in the list.
index_list = name
else
patterns = save_pattern(name, name, patterns or {})
end
if find(name, "\1", nil, true) then
if args_placeholders then
placeholders_n = placeholders_n + 1
args_placeholders[placeholders_n] = name
else
args_placeholders, placeholders_n = {name}, 1
end
end
end
end
end
--Process required changes to `params`.
if args_placeholders then
for i = 1, placeholders_n do
local name = args_placeholders[i]
params[gsub(name, "\1", "")], params[name] = params[name], nil
end
end
-- Process the arguments
for name, val in pairs(args) do
any_args_set = true
validate_name(name, "argument names", nil, true)
-- Guaranteeing that all values are strings avoids issues with type coercion being inconsistent between functions.
local val_type = type(val)
if val_type ~= "string" then
internal_process_error(
"argument %s has the type %s; all arguments must be strings.",
name, val_type
)
end
local orig_name, raw_type, index, canonical = name, type(name)
if raw_type == "number" then
if index_list and name >= index_list then
index = name - index_list + 1
name = index_list
end
elseif patterns then
-- Does this argument name match a pattern?
for pattern, pname in next, patterns do
index = match(name, pattern)
-- It matches, so store the parameter name and the
-- numeric index extracted from the argument name.
if index then
index = tonumber(index)
name = pname
break
end
end
end
local param = params[name]
-- If the argument is not in the list of parameters, store it in a separate list.
if not param then
args_unknown = unknown_param(name, val, args_unknown or {})
elseif param == true then
canonical = orig_name
val = php_trim(val)
if val ~= "" then
-- If the parameter is duplicated, throw an error.
if args_new[name] ~= nil then
process_error(
"Parameter %s has been entered more than once. This is probably because a parameter alias has been used.",
canonical
)
end
args_new[name] = val
end
else
if param.replaced_by == false then
process_error(
("Parameter %%s has been removed and is no longer valid%s.%s"):format(
param.reason and ", " .. param.reason or "",
param.instead and " Instead, " .. param.instead .. "." or ""),
name
)
elseif param.replaced_by then
process_error(
("Parameter %%s has been replaced by %%s%s."):format(
param.reason and ", " .. param.reason or ""),
name, param.replaced_by
)
end
if param.deprecated then
track("deprecated parameter", name)
end
if param.require_index then
-- Disallow require_index for numeric parameter names, as this doesn't make sense.
if raw_type == "number" then
internal_process_error(
"cannot set require_index for numeric parameter %s.",
name
)
-- If a parameter without the trailing index was found, and
-- require_index is set on the param, treat it
-- as if it isn't recognized.
elseif not index then
args_unknown = unknown_param(name, val, args_unknown or {})
end
end
-- Check that separate_no_index is not being used with a numeric parameter.
if param.separate_no_index then
if raw_type == "number" then
internal_process_error(
"cannot set separate_no_index for numeric parameter %s.",
name
)
elseif type(param.alias_of) == "number" then
internal_process_error(
"cannot set separate_no_index for parameter %s, as it is an alias of numeric parameter %s.",
name, param.alias_of
)
end
end
-- If no index was found, use 1 as the default index.
-- This makes list parameters like g, g2, g3 put g at index 1.
-- If `separate_no_index` is set, then use 0 as the default instead.
if not index and param.list then
index = param.separate_no_index and 0 or 1
end
-- Normalize to the canonical parameter name. If it's a list, but the alias is not, then determine the index.
local raw_name = param.alias_of
if raw_name then
raw_type = type(raw_name)
if raw_type == "number" then
name = raw_name
local main_param = params[raw_name]
if main_param ~= true and main_param.list then
if not index then
index = param.separate_no_index and 0 or 1
end
canonical = raw_name + index - 1
else
canonical = raw_name
end
else
name = gsub(raw_name, "\1", "")
local main_param = params[name]
if not index and main_param ~= true and main_param.list then
index = param.separate_no_index and 0 or 1
end
if not index or index == 0 then
canonical = name
elseif name == raw_name then
canonical = name .. index
else
canonical = gsub(raw_name, "\1", index)
end
end
else
canonical = orig_name
end
-- Only recognize demo parameters if this is the current template or module's
-- page, or its documentation page.
if param.demo and not is_own_page("include_documentation") then
args_unknown = unknown_param(name, val, args_unknown or {})
end
-- Remove leading and trailing whitespace unless no_trim is true.
if param.no_trim then
check_string_param_modifier(param.type, name, "no_trim")
else
val = php_trim(val)
end
-- Empty string is equivalent to nil unless allow_empty is true.
if param.allow_empty then
check_string_param_modifier(param.type, name, "allow_empty")
elseif val == "" then
-- If `disallow_missing` is set, keep track of empty parameters
-- via the `empty` field in `arg`, which will be used by the
-- `disallow_missing` check. This will be deleted before
-- returning.
if index and param.disallow_missing then
local arg = args_new[name]
local empty = arg.empty
if empty == nil then
empty = {maxindex = 0}
arg.empty = empty
end
empty[index] = true
if index > empty.maxindex then
empty.maxindex = index
end
end
val = nil
end
-- Allow boolean false.
if val ~= nil then
-- Convert to proper type if necessary.
local main_param = params[raw_name]
if main_param ~= true then
val = convert_val(val, orig_name, main_param or param)
end
-- Mark it as no longer required, as it is present.
if required then
required[name] = nil
end
-- Store the argument value.
if index then
local arg = args_new[name]
-- If the parameter is duplicated, throw an error.
if arg[index] ~= nil then
process_error(
"Parameter %s has been entered more than once. This is probably because a list parameter has been entered without an index and with index 1 at the same time, or because a parameter alias has been used.",
canonical
)
end
arg[index] = val
-- Store the highest index we find.
local maxindex = arg.maxindex
if index > maxindex then
maxindex = index
end
if arg[0] ~= nil then
arg.default, arg[0] = arg[0], nil
if maxindex < 1 then
maxindex = 1
end
end
arg.maxindex = maxindex
if not params[name].list then
args_new[name] = val
-- Don't store index 0, as it's a proxy for the default.
elseif index > 0 then
arg[index] = val
end
else
-- If the parameter is duplicated, throw an error.
if args_new[name] ~= nil then
process_error(
"Parameter %s has been entered more than once. This is probably because a parameter alias has been used.",
canonical
)
end
if not raw_name then
args_new[name] = val
else
local main_param = params[raw_name]
if main_param ~= true and main_param.list then
local main_arg = args_new[raw_name]
main_arg[1] = val
-- Store the highest index we find.
if main_arg.maxindex < 1 then
main_arg.maxindex = 1
end
else
args_new[raw_name] = val
end
end
end
end
end
end
-- Remove holes in any list parameters if needed. This must be handled
-- straight after the previous loop, as any instances of `empty` need to be
-- converted to nil.
if list_args then
for name, val in next, list_args do
handle_holes(params, val, name)
end
end
-- If the current page is the template which invoked this Lua instance, then ignore the `require` flag, as it
-- means we're viewing the template directly. Required parameters sometimes have a `template_default` key set,
-- which gets used in such cases as a demo.
-- Note: this won't work on other pages in the Template: namespace (including the /documentation subpage),
-- or if the #invoke: is on a page in another namespace.
local pagename_set = args_new.pagename
-- Handle defaults.
for name, param in pairs(params) do
if param ~= true then
local arg_new = args_new[name]
if arg_new == nil then
args_new[name] = convert_default_val(name, param, pagename_set, any_args_set, true)
elseif param.list and arg_new[1] == nil then
local default_val = convert_default_val(name, param, pagename_set, any_args_set)
if default_val ~= nil then
arg_new[1] = default_val
if arg_new.maxindex == 0 then
arg_new.maxindex = 1
end
end
end
end
end
-- Flatten nested lists if called for. This must come after setting the default.
if list_args then
for name, val in next, list_args do
args_new[name] = maybe_flatten(params, val, name)
end
end
-- The required table should now be empty.
-- If any parameters remain, throw an error, unless we're on the current template or module's page.
if required and next(required) ~= nil and not is_own_page() then
params_list_error(required, "required")
-- Return the arguments table.
-- If there are any unknown parameters, throw an error, unless return_unknown is set, in which case return args_unknown as a second return value.
elseif return_unknown then
return args_new, args_unknown or {}
elseif args_unknown and next(args_unknown) ~= nil then
params_list_error(args_unknown, "not used by this template")
end
return args_new
end
return export
c23kzesggrlowmn06oii7zu1bbzht4t
Modul:table
828
3692
26499
8023
2025-11-12T12:24:57Z
id>Bennylin
0
26499
Scribunto
text/plain
local export = {}
--[==[ intro:
This module provides functions for dealing with Lua tables. All of them, except for two helper functions, take a table
as their first argument.
Some functions are available as methods in the arrays created by [[Module:array]].
Functions by what they do:
* Create a new table:
** `shallowCopy`, `deepCopy`, `removeDuplicates`, `numKeys`, `compressSparseArray`, `keysToList`, `reverse`, `invert`, `listToSet`
* Create an array:
** `removeDuplicates`, `numKeys`, `compressSparseArray`, `keysToList`, `reverse`
* Return information about the table:
** `size`, `length`, `contains`, `isArray`, `deepEquals`
* Treat the table as an array (that is, operate on the values in the array portion of the table: values indexed by
consecutive integers starting at {1}):
** `removeDuplicates`, `length`, `contains`, `serialCommaJoin`, `reverseIpairs`, `reverse`, `invert`, `listToSet`, `isArray`
* Treat a table as a sparse array (that is, operate on values indexed by non-consecutive integers):
** `numKeys`, `maxIndex`, `compressSparseArray`, `sparseConcat`, `sparseIpairs`
* Generate an iterator:
** `sparseIpairs`, `sortedPairs`, `reverseIpairs`
* Other functions:
** `sparseConcat`, `serialCommaJoin`, `reverseConcat`
The original version was a copy of {{w|Module:TableTools}} on Wikipedia via [[c:Module:TableTools|Module:TableTools]] on
Commons, but in the course of time this module has been almost completely rewritten, with many new functions added. The
main legacy of this is the use of camelCase for function names rather than snake_case, as is normal in the English
Wiktionary.
]==]
local load_module = "Module:load"
local math_module = "Module:math"
local table = table
local concat = table.concat
local dump = mw.dumpObject
local ipairs = ipairs
local ipairs_default_iter = ipairs{export}
local next = next
local pairs = pairs
local require = require
local select = select
local signed_index -- defined as export.signedIndex
local table_len -- defined as export.length
local type = type
--[==[
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 is_integer(...)
is_integer = require(math_module).is_integer
return is_integer(...)
end
local function safe_require(...)
safe_require = require(load_module).safe_require
return safe_require(...)
end
--[==[
Given an array and a signed index, returns the true table index. If the signed index is negative, the array will be counted from the end, where {-1} is the highest index in the array; otherwise, the returned index will be the same. To aid optimization, the first argument may be a number representing the array length instead of the array itself; this is useful when the array length is already known, as it avoids recalculating it each time this function is called.]==]
function export.signedIndex(t, k)
if not is_integer(k) then
error("index must be an integer")
end
return k < 0 and (type(t) == "table" and table_len(t) or t) + k + 1 or k
end
signed_index = export.signedIndex
--[==[
An iterator which works like `pairs`, but ignores any `__pairs` metamethod.]==]
function export.rawPairs(t)
return next, t, nil
end
--[==[
An iterator which works like `ipairs`, but ignores any `__ipairs` metamethod.]==]
function export.rawIpairs(t)
return ipairs_default_iter, t, 0
end
--[==[
This returns the length of a table, or the first integer key n counting from 1 such that t[n + 1] is nil. It is a more reliable form of the operator `#`, which can become unpredictable under certain circumstances due to the implementation of tables under the hood in Lua, and therefore should not be used when dealing with arbitrary tables. `#` also does not use metamethods, so will return the wrong value in cases where it is desirable to take these into account (e.g. data loaded via `mw.loadData`). If `raw` is set, then metamethods will be ignored, giving the true table length.
For arrays, this function is faster than `export.size`.]==]
function export.length(t, raw)
local n = 0
if raw then
for i in ipairs_default_iter, t, 0 do
n = i
end
return n
end
repeat
n = n + 1
until t[n] == nil
return n - 1
end
table_len = export.length
local function getIteratorValues(i, j , step, t_len)
i, j = i and signed_index(t_len, i), j and signed_index(t_len, j)
if step == nil then
i, j = i or 1, j or t_len
return i, j, j < i and -1 or 1
elseif step == 0 or not is_integer(step) then
error("step must be a non-zero integer")
elseif step < 0 then
return i or t_len, j or 1, step
end
return i or 1, j or t_len, step
end
--[==[
Given an array `list` and function `func`, iterate through the array applying {func(r, k, v)}, and returning the result,
where `r` is the value calculated so far, `k` is an index, and `v` is the value at index `k`. For example,
{reduce(array, function(a, _, v) return a + v end)} will return the sum of `array`.
Optional arguments:
* `i`: start index; negative values count from the end of the array
* `j`: end index; negative values count from the end of the array
* `step`: step increment
These must be non-zero integers. The function will determine where to iterate from, whether to iterate forwards or
backwards and by how much, based on these inputs (see examples below for default behaviours).
Examples:
# No values for i, j or step results in forward iteration from the start to the end in steps of 1 (the default).
# step=-1 results in backward iteration from the end to the start in steps of 1.
# i=7, j=3 results in backward iteration from indices 7 to 3 in steps of 1 (i.e. step=-1).
# j=-3 results in forward iteration from the start to the 3rd last index.
# j=-3, step=-1 results in backward iteration from the end to the 3rd last index.]==]
function export.reduce(t, func, i, j, step)
i, j, step = getIteratorValues(i, j, step, table_len(t))
local ret = t[i]
for k = i + step, j, step do
ret = func(ret, k, t[k])
end
return ret
end
do
local function replace(t, func, i, j, step, generate)
local t_len = table_len(t)
-- Normalized i, j and step, based on the inputs.
local norm_i, norm_j, norm_step = getIteratorValues(i, j, step, t_len)
if norm_step > 0 then
i, j, step = 1, t_len, 1
else
i, j, step = t_len, 1, -1
end
-- "Signed" variables are multiplied by -1 if `step` is negative.
local t_new, signed_i, signed_j = generate and {} or t, norm_i * step, norm_j * step
for k = i, j, step do
-- Replace the values iff they're within the i to j range and `step` wouldn't skip the key.
-- Note: i > j if `step` is positive; i < j if `step` is negative. Otherwise, the range is empty.
local signed_k = k * step
if signed_k >= signed_i and signed_k <= signed_j and (k - norm_i) % norm_step == 0 then
t_new[k] = func(k, t[k])
-- Otherwise, add the existing value if `generate` is set.
elseif generate then
t_new[k] = t[k]
end
end
return t_new
end
--[==[
Given an array `list` and function `func`, iterate through the array applying {func(k, v)} (where `k` is an index, and
`v` is the value at index `k`), replacing the relevant values with the result. For example,
{apply(array, function(_, v) return 2 * v end)} will double each member of the array.
Optional arguments:
* `i`: start index; negative values count from the end of the array
* `j`: end index; negative values count from the end of the array
* `step`: step increment
These must be non-zero integers. The function will determine where to iterate from, whether to iterate forwards or
backwards and by how much, based on these inputs (see examples below for default behaviours).
Examples:
# No values for i, j or step results in forward iteration from the start to the end in steps of 1 (the default).
# step=-1 results in backward iteration from the end to the start in steps of 1.
# i=7, j=3 results in backward iteration from indices 7 to 3 in steps of 1 (i.e. step=-1).
# j=-3 results in forward iteration from the start to the 3rd last index.
# j=-3, step=-1 results in backward iteration from the end to the 3rd last index.]==]
function export.apply(t, func, i, j, step)
return replace(t, func, i, j, step, false)
end
--[==[
Given an array `list` and function `func`, iterate through the array applying {func(k, v)} (where `k` is an index, and
`v` is the value at index `k`), and return a shallow copy of the original array with the relevant values replaced. For example,
{generate(array, function(_, v) return 2 * v end)} will return a new array in which each value has been doubled.
Optional arguments:
* `i`: start index; negative values count from the end of the array
* `j`: end index; negative values count from the end of the array
* `step`: step increment
These must be non-zero integers. The function will determine where to iterate from, whether to iterate forwards or
backwards and by how much, based on these inputs (see examples below for default behaviours).
Examples:
# No values for i, j or step results in forward iteration from the start to the end in steps of 1 (the default).
# step=-1 results in backward iteration from the end to the start in steps of 1.
# i=7, j=3 results in backward iteration from indices 7 to 3 in steps of 1 (i.e. step=-1).
# j=-3 results in forward iteration from the start to the 3rd last index.
# j=-3, step=-1 results in backward iteration from the end to the 3rd last index.]==]
function export.generate(t, func, i, j, step)
return replace(t, func, i, j, step, true)
end
end
--[==[
Given an array `list` and function `func`, iterate through the array applying {func(k, v)} (where `k` is an index, and
`v` is the value at index `k`), and returning whether the function is true for all iterations.
Optional arguments:
* `i`: start index; negative values count from the end of the array
* `j`: end index; negative values count from the end of the array
* `step`: step increment
These must be non-zero integers. The function will determine where to iterate from, whether to iterate forwards or
backwards and by how much, based on these inputs (see examples below for default behaviours).
Examples:
# No values for i, j or step results in forward iteration from the start to the end in steps of 1 (the default).
# step=-1 results in backward iteration from the end to the start in steps of 1.
# i=7, j=3 results in backward iteration from indices 7 to 3 in steps of 1 (i.e. step=-1).
# j=-3 results in forward iteration from the start to the 3rd last index.
# j=-3, step=-1 results in backward iteration from the end to the 3rd last index.]==]
function export.all(t, func, i, j, step)
i, j, step = getIteratorValues(i, j, step, table_len(t))
for k = i, j, step do
if not func(k, t[k]) then
return false
end
end
return true
end
--[==[
Given an array `list` and function `func`, iterate through the array applying {func(k, v)} (where `k` is an index, and
`v` is the value at index `k`), and returning whether the function is true for at least one iteration.
Optional arguments:
* `i`: start index; negative values count from the end of the array
* `j`: end index; negative values count from the end of the array
* `step`: step increment
These must be non-zero integers. The function will determine where to iterate from, whether to iterate forwards or
backwards and by how much, based on these inputs (see examples below for default behaviours).
Examples:
# No values for i, j or step results in forward iteration from the start to the end in steps of 1 (the default).
# step=-1 results in backward iteration from the end to the start in steps of 1.
# i=7, j=3 results in backward iteration from indices 7 to 3 in steps of 1 (i.e. step=-1).
# j=-3 results in forward iteration from the start to the 3rd last index.
# j=-3, step=-1 results in backward iteration from the end to the 3rd last index.]==]
function export.any(t, func, i, j, step)
i, j, step = getIteratorValues(i, j, step, table_len(t))
for k = i, j, step do
if not not (func(k, t[k])) then
return true
end
end
return false
end
--[==[
Joins an array with serial comma and serial conjunction, normally {"and"}. An improvement on {mw.text.listToText},
which doesn't properly handle serial commas.
Options:
* `conj`: Conjunction to use; defaults to {"and"}.
* `punc`: Punctuation to use; default to {","}.
* `dontTag`: Don't tag the serial comma and serial {"and"}. For error messages, in which HTML cannot be used.
* `dump`: Each item will be serialized with {mw.dumpObject}. For warnings and error messages.]==]
function export.serialCommaJoin(seq, options)
-- If the `dump` option is set, determine the table length as part of the
-- dump loop, instead of calling `table_len` separately.
local length
if options and options.dump then
local i, item = 1, seq[1]
if item ~= nil then
local dumped = {}
repeat
dumped[i] = dump(item)
i = i + 1
item = seq[i]
until item == nil
seq = dumped
end
length = i - 1
else
length = table_len(seq)
end
if length == 0 then
return ""
elseif length == 1 then
return seq[1]
end
local conj = options and options.conj
if conj == nil then
conj = "and"
end
if length == 2 then
return seq[1] .. " " .. conj .. " " .. seq[2]
end
local punc, dont_tag
if options then
punc = options.punc
if punc == nil then
punc = ","
end
dont_tag = options.dontTag
else
punc = ","
end
local comma
if dont_tag then
comma = "" -- since by default the serial comma doesn't display, when we can't tag we shouldn't display it.
conj = " " .. conj .. " "
else
comma = "<span class=\"serial-comma\">" .. punc .. "</span>"
conj = "<span class=\"serial-and\"> " .. conj .. "</span> "
end
return concat(seq, punc .. " ", 1, length - 1) .. comma .. conj .. seq[length]
end
--[==[
A function which works like `table.concat`, but respects any `__index` metamethod. This is useful for data loaded via `mw.loadData`.]==]
function export.concat(t, sep, i, j)
local list, k = {}, 0
while true do
k = k + 1
local v = t[k]
if v == nil then
return concat(list, sep, i, j)
end
list[k] = v
end
end
--[==[
Add a list of aliases for a given key to a table. The aliases must be given as a table.]==]
function export.alias(t, k, aliases)
for _, alias in pairs(aliases) do
t[alias] = t[k]
end
end
local mt = {}
function mt:__index(k)
local submodule = safe_require("Module:table/" .. k)
self[k] = submodule
return submodule
end
return setmetatable(export, mt)
exw27st65r96fvgc4krew9cy4eyvdow
26500
23978
2026-07-07T09:55:56Z
Sibiru45
115
1 ralatan matan [[:id:Modul:table]]
23978
Scribunto
text/plain
local export = {}
--[==[ intro:
This module provides functions for dealing with Lua tables. All of them, except for two helper functions, take a table
as their first argument.
Some functions are available as methods in the arrays created by [[Module:array]].
Functions by what they do:
* Create a new table:
** `shallowCopy`, `deepCopy`, `removeDuplicates`, `numKeys`, `compressSparseArray`, `keysToList`, `reverse`, `invert`, `listToSet`
* Create an array:
** `removeDuplicates`, `numKeys`, `compressSparseArray`, `keysToList`, `reverse`
* Return information about the table:
** `size`, `length`, `contains`, `isArray`, `deepEquals`
* Treat the table as an array (that is, operate on the values in the array portion of the table: values indexed by
consecutive integers starting at {1}):
** `removeDuplicates`, `length`, `contains`, `serialCommaJoin`, `reverseIpairs`, `reverse`, `invert`, `listToSet`, `isArray`
* Treat a table as a sparse array (that is, operate on values indexed by non-consecutive integers):
** `numKeys`, `maxIndex`, `compressSparseArray`, `sparseConcat`, `sparseIpairs`
* Generate an iterator:
** `sparseIpairs`, `sortedPairs`, `reverseIpairs`
* Other functions:
** `sparseConcat`, `serialCommaJoin`, `reverseConcat`
The original version was a copy of {{w|Module:TableTools}} on Wikipedia via [[c:Module:TableTools|Module:TableTools]] on
Commons, but in the course of time this module has been almost completely rewritten, with many new functions added. The
main legacy of this is the use of camelCase for function names rather than snake_case, as is normal in the English
Wiktionary.
]==]
local load_module = "Module:load"
local math_module = "Module:math"
local table = table
local concat = table.concat
local dump = mw.dumpObject
local ipairs = ipairs
local ipairs_default_iter = ipairs{export}
local next = next
local pairs = pairs
local require = require
local select = select
local signed_index -- defined as export.signedIndex
local table_len -- defined as export.length
local type = type
--[==[
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 is_integer(...)
is_integer = require(math_module).is_integer
return is_integer(...)
end
local function safe_require(...)
safe_require = require(load_module).safe_require
return safe_require(...)
end
--[==[
Given an array and a signed index, returns the true table index. If the signed index is negative, the array will be counted from the end, where {-1} is the highest index in the array; otherwise, the returned index will be the same. To aid optimization, the first argument may be a number representing the array length instead of the array itself; this is useful when the array length is already known, as it avoids recalculating it each time this function is called.]==]
function export.signedIndex(t, k)
if not is_integer(k) then
error("index must be an integer")
end
return k < 0 and (type(t) == "table" and table_len(t) or t) + k + 1 or k
end
signed_index = export.signedIndex
--[==[
An iterator which works like `pairs`, but ignores any `__pairs` metamethod.]==]
function export.rawPairs(t)
return next, t, nil
end
--[==[
An iterator which works like `ipairs`, but ignores any `__ipairs` metamethod.]==]
function export.rawIpairs(t)
return ipairs_default_iter, t, 0
end
--[==[
This returns the length of a table, or the first integer key n counting from 1 such that t[n + 1] is nil. It is a more reliable form of the operator `#`, which can become unpredictable under certain circumstances due to the implementation of tables under the hood in Lua, and therefore should not be used when dealing with arbitrary tables. `#` also does not use metamethods, so will return the wrong value in cases where it is desirable to take these into account (e.g. data loaded via `mw.loadData`). If `raw` is set, then metamethods will be ignored, giving the true table length.
For arrays, this function is faster than `export.size`.]==]
function export.length(t, raw)
local n = 0
if raw then
for i in ipairs_default_iter, t, 0 do
n = i
end
return n
end
repeat
n = n + 1
until t[n] == nil
return n - 1
end
table_len = export.length
local function getIteratorValues(i, j , step, t_len)
i, j = i and signed_index(t_len, i), j and signed_index(t_len, j)
if step == nil then
i, j = i or 1, j or t_len
return i, j, j < i and -1 or 1
elseif step == 0 or not is_integer(step) then
error("step must be a non-zero integer")
elseif step < 0 then
return i or t_len, j or 1, step
end
return i or 1, j or t_len, step
end
--[==[
Given an array `list` and function `func`, iterate through the array applying {func(r, k, v)}, and returning the result,
where `r` is the value calculated so far, `k` is an index, and `v` is the value at index `k`. For example,
{reduce(array, function(a, _, v) return a + v end)} will return the sum of `array`.
Optional arguments:
* `i`: start index; negative values count from the end of the array
* `j`: end index; negative values count from the end of the array
* `step`: step increment
These must be non-zero integers. The function will determine where to iterate from, whether to iterate forwards or
backwards and by how much, based on these inputs (see examples below for default behaviours).
Examples:
# No values for i, j or step results in forward iteration from the start to the end in steps of 1 (the default).
# step=-1 results in backward iteration from the end to the start in steps of 1.
# i=7, j=3 results in backward iteration from indices 7 to 3 in steps of 1 (i.e. step=-1).
# j=-3 results in forward iteration from the start to the 3rd last index.
# j=-3, step=-1 results in backward iteration from the end to the 3rd last index.]==]
function export.reduce(t, func, i, j, step)
i, j, step = getIteratorValues(i, j, step, table_len(t))
local ret = t[i]
for k = i + step, j, step do
ret = func(ret, k, t[k])
end
return ret
end
do
local function replace(t, func, i, j, step, generate)
local t_len = table_len(t)
-- Normalized i, j and step, based on the inputs.
local norm_i, norm_j, norm_step = getIteratorValues(i, j, step, t_len)
if norm_step > 0 then
i, j, step = 1, t_len, 1
else
i, j, step = t_len, 1, -1
end
-- "Signed" variables are multiplied by -1 if `step` is negative.
local t_new, signed_i, signed_j = generate and {} or t, norm_i * step, norm_j * step
for k = i, j, step do
-- Replace the values iff they're within the i to j range and `step` wouldn't skip the key.
-- Note: i > j if `step` is positive; i < j if `step` is negative. Otherwise, the range is empty.
local signed_k = k * step
if signed_k >= signed_i and signed_k <= signed_j and (k - norm_i) % norm_step == 0 then
t_new[k] = func(k, t[k])
-- Otherwise, add the existing value if `generate` is set.
elseif generate then
t_new[k] = t[k]
end
end
return t_new
end
--[==[
Given an array `list` and function `func`, iterate through the array applying {func(k, v)} (where `k` is an index, and
`v` is the value at index `k`), replacing the relevant values with the result. For example,
{apply(array, function(_, v) return 2 * v end)} will double each member of the array.
Optional arguments:
* `i`: start index; negative values count from the end of the array
* `j`: end index; negative values count from the end of the array
* `step`: step increment
These must be non-zero integers. The function will determine where to iterate from, whether to iterate forwards or
backwards and by how much, based on these inputs (see examples below for default behaviours).
Examples:
# No values for i, j or step results in forward iteration from the start to the end in steps of 1 (the default).
# step=-1 results in backward iteration from the end to the start in steps of 1.
# i=7, j=3 results in backward iteration from indices 7 to 3 in steps of 1 (i.e. step=-1).
# j=-3 results in forward iteration from the start to the 3rd last index.
# j=-3, step=-1 results in backward iteration from the end to the 3rd last index.]==]
function export.apply(t, func, i, j, step)
return replace(t, func, i, j, step, false)
end
--[==[
Given an array `list` and function `func`, iterate through the array applying {func(k, v)} (where `k` is an index, and
`v` is the value at index `k`), and return a shallow copy of the original array with the relevant values replaced. For example,
{generate(array, function(_, v) return 2 * v end)} will return a new array in which each value has been doubled.
Optional arguments:
* `i`: start index; negative values count from the end of the array
* `j`: end index; negative values count from the end of the array
* `step`: step increment
These must be non-zero integers. The function will determine where to iterate from, whether to iterate forwards or
backwards and by how much, based on these inputs (see examples below for default behaviours).
Examples:
# No values for i, j or step results in forward iteration from the start to the end in steps of 1 (the default).
# step=-1 results in backward iteration from the end to the start in steps of 1.
# i=7, j=3 results in backward iteration from indices 7 to 3 in steps of 1 (i.e. step=-1).
# j=-3 results in forward iteration from the start to the 3rd last index.
# j=-3, step=-1 results in backward iteration from the end to the 3rd last index.]==]
function export.generate(t, func, i, j, step)
return replace(t, func, i, j, step, true)
end
end
--[==[
Given an array `list` and function `func`, iterate through the array applying {func(k, v)} (where `k` is an index, and
`v` is the value at index `k`), and returning whether the function is true for all iterations.
Optional arguments:
* `i`: start index; negative values count from the end of the array
* `j`: end index; negative values count from the end of the array
* `step`: step increment
These must be non-zero integers. The function will determine where to iterate from, whether to iterate forwards or
backwards and by how much, based on these inputs (see examples below for default behaviours).
Examples:
# No values for i, j or step results in forward iteration from the start to the end in steps of 1 (the default).
# step=-1 results in backward iteration from the end to the start in steps of 1.
# i=7, j=3 results in backward iteration from indices 7 to 3 in steps of 1 (i.e. step=-1).
# j=-3 results in forward iteration from the start to the 3rd last index.
# j=-3, step=-1 results in backward iteration from the end to the 3rd last index.]==]
function export.all(t, func, i, j, step)
i, j, step = getIteratorValues(i, j, step, table_len(t))
for k = i, j, step do
if not func(k, t[k]) then
return false
end
end
return true
end
--[==[
Given an array `list` and function `func`, iterate through the array applying {func(k, v)} (where `k` is an index, and
`v` is the value at index `k`), and returning whether the function is true for at least one iteration.
Optional arguments:
* `i`: start index; negative values count from the end of the array
* `j`: end index; negative values count from the end of the array
* `step`: step increment
These must be non-zero integers. The function will determine where to iterate from, whether to iterate forwards or
backwards and by how much, based on these inputs (see examples below for default behaviours).
Examples:
# No values for i, j or step results in forward iteration from the start to the end in steps of 1 (the default).
# step=-1 results in backward iteration from the end to the start in steps of 1.
# i=7, j=3 results in backward iteration from indices 7 to 3 in steps of 1 (i.e. step=-1).
# j=-3 results in forward iteration from the start to the 3rd last index.
# j=-3, step=-1 results in backward iteration from the end to the 3rd last index.]==]
function export.any(t, func, i, j, step)
i, j, step = getIteratorValues(i, j, step, table_len(t))
for k = i, j, step do
if not not (func(k, t[k])) then
return true
end
end
return false
end
--[==[
Joins an array with serial comma and serial conjunction, normally {"and"}. An improvement on {mw.text.listToText},
which doesn't properly handle serial commas.
Options:
* `conj`: Conjunction to use; defaults to {"and"}.
* `punc`: Punctuation to use; default to {","}.
* `dontTag`: Don't tag the serial comma and serial {"and"}. For error messages, in which HTML cannot be used.
* `dump`: Each item will be serialized with {mw.dumpObject}. For warnings and error messages.]==]
function export.serialCommaJoin(seq, options)
-- If the `dump` option is set, determine the table length as part of the
-- dump loop, instead of calling `table_len` separately.
local length
if options and options.dump then
local i, item = 1, seq[1]
if item ~= nil then
local dumped = {}
repeat
dumped[i] = dump(item)
i = i + 1
item = seq[i]
until item == nil
seq = dumped
end
length = i - 1
else
length = table_len(seq)
end
if length == 0 then
return ""
elseif length == 1 then
return seq[1]
end
local conj = options and options.conj
if conj == nil then
conj = "and"
end
if length == 2 then
return seq[1] .. " " .. conj .. " " .. seq[2]
end
local punc, dont_tag
if options then
punc = options.punc
if punc == nil then
punc = ","
end
dont_tag = options.dontTag
else
punc = ","
end
local comma
if dont_tag then
comma = "" -- since by default the serial comma doesn't display, when we can't tag we shouldn't display it.
conj = " " .. conj .. " "
else
comma = "<span class=\"serial-comma\">" .. punc .. "</span>"
conj = "<span class=\"serial-and\"> " .. conj .. "</span> "
end
return concat(seq, punc .. " ", 1, length - 1) .. comma .. conj .. seq[length]
end
--[==[
A function which works like `table.concat`, but respects any `__index` metamethod. This is useful for data loaded via `mw.loadData`.]==]
function export.concat(t, sep, i, j)
local list, k = {}, 0
while true do
k = k + 1
local v = t[k]
if v == nil then
return concat(list, sep, i, j)
end
list[k] = v
end
end
--[==[
Add a list of aliases for a given key to a table. The aliases must be given as a table.]==]
function export.alias(t, k, aliases)
for _, alias in pairs(aliases) do
t[alias] = t[k]
end
end
local mt = {}
function mt:__index(k)
local submodule = safe_require("Module:table/" .. k)
self[k] = submodule
return submodule
end
return setmetatable(export, mt)
exw27st65r96fvgc4krew9cy4eyvdow
Citakan:label
10
3711
26491
24223
2026-04-08T06:14:25Z
id>Swarabakti
0
26491
wikitext
text/x-wiki
<includeonly>{{#invoke:labels/templates|show}}</includeonly><noinclude>{{dokumentasi}}</noinclude>
4omfmjl2by1r8lhfc2dn4hiwiy3vb68
26492
26491
2026-07-07T09:55:56Z
Sibiru45
115
1 ralatan matan [[:id:Templat:label]]
26491
wikitext
text/x-wiki
<includeonly>{{#invoke:labels/templates|show}}</includeonly><noinclude>{{dokumentasi}}</noinclude>
4omfmjl2by1r8lhfc2dn4hiwiy3vb68
Modul:fun
828
4707
26497
10374
2025-11-12T12:24:58Z
id>Bennylin
0
26497
Scribunto
text/plain
local export = {}
local debug_track_module = "Module:debug/track"
local table_get_unprotected_metatable = "Module:table/getUnprotectedMetatable"
local chain -- defined below
local chain_iter -- defined below
local format = string.format
local gmatch = string.gmatch
local ipairs = ipairs
local is_callable -- defined below
local pairs = pairs
local pcall = pcall
local rawget = rawget
local require = require
local select = select
local tostring = tostring
local type = type
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local unroll -- defined below
local xpcall = xpcall
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function get_unprotected_metatable(...)
get_unprotected_metatable = require(table_get_unprotected_metatable)
return get_unprotected_metatable(...)
end
local function _iterString(iter, i)
i = i + 1
local char = iter()
if char ~= nil then
return i, char
end
end
-- Iterate over UTF-8-encoded codepoints in string.
local function iterString(str)
return _iterString, gmatch(str, ".[\128-\191]*"), 0
end
--[==[
Return {true} if the input is a function or functor (an object which can be called like a function, because it has a {__call} metamethod).
Note: if the input is an object with a {__call} metamethod, but this function is not able to find it because the object's metatable is protected with {__metatable}, then it will return {false} by default, or {nil} if the {allow_maybe} flag is set.]==]
function export.is_callable(f, allow_maybe)
if type(f) == "function" then
return true
end
-- An object is a functor if it has a `__call` metamethod. The only way to truly confirm this is by trying to call it, but that could be expensive or have side effects, so look for a `__call` metamethod instead. If the metatable is protected with `__metatable`, this may not be possible.
local mt = get_unprotected_metatable(f)
if mt == nil then
return false
-- `get_unprotected_metatable` returns false if the metatable is protected.
elseif mt == false then
debug_track("fun/is_callable/protected metatable")
if allow_maybe then
return nil
end
return false
end
-- `__call` metamethods have to be functions, so don't recurse to check it.
local __call = rawget(mt, "__call")
return __call and type(__call) == "function" or false
end
is_callable = export.is_callable
--[==[
A version of {xpcall} which takes any arguments to be given to {f} as additional arguments after the error handler.
This fixes a deficiency in the standard version of {xpcall}, which is not able to handle arguments to be given to {f}, and brings it in line with {pcall}.]==]
function export.xpcall(f, err_handler, ...)
-- If there are no arguments, just call xpcall() with `f`.
if select("#", ...) == 0 then
return xpcall(f, err_handler)
end
-- Any arguments have to be smuggled in via a table, as ... can't be an
-- upvalue, and it's not possible to use pcall() to get aroud this, because
-- xpcall() calls the error handler before the stack unwinds.
local args = {...}
return xpcall(function()
return f(unpack(args))
end, err_handler)
end
do
local function catch_values(f, success, ...)
if success then
return success, ...
-- Error message will only take this exact form if `f` is not callable,
-- because it will contain a traceback if it was thrown further up the
-- stack.
elseif (...) == format("attempt to call a %s value", type(f)) then
return false
end
return error(...)
end
--[==[
A special form of {pcall()}, which returns {true} plus the result value(s) if {f} is callable, or {false} if it isn't. Errors that occur within the called function are not protected.]==]
function export.try_call(f, ...)
local callable = is_callable(f, true)
if callable then
return true, f(...)
elseif callable == false then
return false
end
-- If `callable` is nil, there's a protected metatable, so there's no way to check without doing a protected call.
return catch_values(f, pcall(f, ...))
end
end
--[==[
Takes two or more functions as arguments, and returns a new function which calls each of the input functions in turn. Any arguments given to the returned function are given to the first function, and all other functions receive the output value(s) from the previous function.]==]
function export.chain(func1, func2, ...)
local function chained_func(...)
return func2(func1(...))
end
if select("#", ...) == 0 then
return chained_func
end
return chain(chained_func, ...)
end
chain = export.chain
--[==[
Takes the usual for-loop parameters (an iterator, plus an optional state and initial index), and unrolls the iterator by returning every (first) value returned by the iterator.
For instance, {unroll(pairs(t))} will return every key in {t}, and {unroll(string.gmatch(s, "%w+"))} will return every word in {s}.]==]
function export.unroll(iter, state, k)
k = iter(state, k)
if k ~= nil then
return k, unroll(iter, state, k)
end
end
unroll = export.unroll
--[==[
Takes a generator function (i.e. a function that returns an iterator, such as {ipairs}) and one or more additional functions, and returns a new generator function. Any arguments given to the new generator (e.g. an input table) are given to the original generator, and the additional functions are called on each iteration. The first additional function takes the output from the original iterator (i.e. the function returned by the original generator), and any further functions receive the output value(s) from the previous function. This can be used to modify the values returned from an iterator.]==]
function export.chainIter(gen, new_iter, ...)
if select("#", ...) > 0 then
new_iter = chain(new_iter, ...)
end
return function(...)
local orig_iter, state, k = gen(...)
-- k has to be the first value returned by orig_iter on the last iteration, not whatever new_iter returned.
local function catch_values(...)
k = ...
if k ~= nil then
return new_iter(...)
end
end
return function()
return catch_values(orig_iter(state, k))
end, state, k
end
end
chain_iter = export.chainIter
do
local function catch_values(start, iter, state, k, ...)
if start == k or k == nil then
return k, ...
end
return catch_values(start, iter, state, iter(state, k))
end
function export.iterateFrom(start, iter, state, k)
local first = true
return function(state, k)
if first then
first = false
return catch_values(start, iter, state, iter(state, k))
end
return iter(state, k)
end, state, k
end
end
-- map(function(number) return number ^ 2 end,
-- { 1, 2, 3 }) --> { 1, 4, 9 }
-- map(function (char) return string.char(string.byte(char) - 0x20) end,
-- "abc") --> { "A", "B", "C" }
function export.map(func, iterable, isArray)
local array = {}
for k, v in (type(iterable) == "string" and iterString or (isArray or iterable[1] ~= nil) and ipairs or pairs)(iterable) do
array[k] = func(v, k, iterable)
end
return array
end
function export.mapIter(func, iter, state, init)
-- init could be anything
local array, i = {}, 0
for x, y in iter, state, init do
i = i + 1
array[i] = func(y, x, state)
end
return array
end
do
local function iter_tuples(tuples)
local i = tuples.i
if i > 1 then
i = i - 1
tuples.i = i
return unpack(tuples[i])
end
end
-- Takes an iterator function, and returns a new iterator that iterates in reverse, given the same arguments.
-- Note: changes to the state during iteration are not taken into account, since all the return values are calculated in advance.
function export.reverseIter(func)
return function(...)
-- Store all returned values as a list of tuples, then iterate in reverse over that list.
local tuples, i, iter, state, val1 = {}, 0, func(...)
while true do
i = i + 1
local vals = {iter(state, val1)}
-- Terminates if the first return value is nil, even if other values are non-nil.
val1 = vals[1]
if val1 == nil then
tuples.i = i
return iter_tuples, tuples
end
tuples[i] = vals
end
end
end
end
function export.forEach(func, iterable, isArray)
for k, v in (type(iterable) == "string" and iterString or (isArray or iterable[1] ~= nil) and ipairs or pairs)(iterable) do
func(v, k, iterable)
end
return nil
end
-------------------------------------------------
-- From http://lua-users.org/wiki/CurriedLua
-- reverse(...) : take some tuple and return a tuple of elements in reverse order
--
-- e.g. "reverse(1,2,3)" returns 3,2,1
local function reverse(...)
-- reverse args by building a function to do it, similar to the unpack() example
local function reverseHelper(acc, v, ...)
if select("#", ...) == 0 then
return v, acc()
else
return reverseHelper(function() return v, acc() end, ...)
end
end
-- initial acc is the end of the list
return reverseHelper(function() return end, ...)
end
function export.curry(func, numArgs)
-- currying 2-argument functions seems to be the most popular application
numArgs = numArgs or 2
-- no sense currying for 1 arg or less
if numArgs <= 1 then return func end
-- helper takes an argTrace function, and number of arguments remaining to be applied
local function curryHelper(argTrace, n)
if n == 0 then
-- kick off argTrace, reverse argument list, and call the original function
return func(reverse(argTrace()))
else
-- "push" argument (by building a wrapper function) and decrement n
return function(onearg)
return curryHelper(function() return onearg, argTrace() end, n - 1)
end
end
end
-- push the terminal case of argTrace into the function first
return curryHelper(function() return end, numArgs)
end
-------------------------------------------------
-- some(function(val) return val % 2 == 0 end,
-- { 2, 3, 5, 7, 11 }) --> true
function export.some(func, t, isArray)
for k, v in ((isArray or t[1] ~= nil) and ipairs or pairs)(t) do
if func(v, k, t) then
return true
end
end
return false
end
-- all(function(val) return val % 2 == 0 end,
-- { 2, 4, 8, 10, 12 }) --> true
function export.all(func, t, isArray)
for k, v in ((isArray or t[1] ~= nil) and ipairs or pairs)(t) do
if not func(v, k, t) then
return false
end
end
return true
end
function export.filter(func, t, isArray)
local new_t = {}
if isArray or t[1] ~= nil then -- array
local new_i = 0
for i, v in ipairs(t) do
if func(v, i, t) then
new_i = new_i + 1
new_t[new_i] = v
end
end
else
for k, v in pairs(t) do
if func(v, k, t) then
new_t[k] = v -- or create array?
end
end
end
return new_t
end
function export.fold(func, t, accum)
for i, v in ipairs(t) do
accum = func(accum, v, i, t)
end
return accum
end
-------------------------------
-- Fancy stuff
local function capture(...)
local vals = {n = select("#", ...), ...}
return function()
return unpack(vals, 1, vals.n)
end
end
-- Log input and output of function.
-- Receives a function and returns a modified form of that function.
function export.logReturnValues(func, prefix)
return function(...)
local inputValues = capture(...)
local returnValues = capture(func(...))
if prefix then
mw.log(prefix, inputValues())
mw.log(returnValues())
else
mw.log(inputValues())
mw.log(returnValues())
end
return returnValues()
end
end
export.log = export.logReturnValues
-- Convenience function to make all functions in a table log their input and output.
function export.logAll(t)
for k, v in pairs(t) do
if is_callable(v) then
t[k] = export.logReturnValues(v, tostring(k))
end
end
return t
end
return export
mc1wbmetcrpjp1ihyth6j2ajabvak7y
26498
26497
2026-07-07T09:55:56Z
Sibiru45
115
1 ralatan matan [[:id:Modul:fun]]
26497
Scribunto
text/plain
local export = {}
local debug_track_module = "Module:debug/track"
local table_get_unprotected_metatable = "Module:table/getUnprotectedMetatable"
local chain -- defined below
local chain_iter -- defined below
local format = string.format
local gmatch = string.gmatch
local ipairs = ipairs
local is_callable -- defined below
local pairs = pairs
local pcall = pcall
local rawget = rawget
local require = require
local select = select
local tostring = tostring
local type = type
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local unroll -- defined below
local xpcall = xpcall
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function get_unprotected_metatable(...)
get_unprotected_metatable = require(table_get_unprotected_metatable)
return get_unprotected_metatable(...)
end
local function _iterString(iter, i)
i = i + 1
local char = iter()
if char ~= nil then
return i, char
end
end
-- Iterate over UTF-8-encoded codepoints in string.
local function iterString(str)
return _iterString, gmatch(str, ".[\128-\191]*"), 0
end
--[==[
Return {true} if the input is a function or functor (an object which can be called like a function, because it has a {__call} metamethod).
Note: if the input is an object with a {__call} metamethod, but this function is not able to find it because the object's metatable is protected with {__metatable}, then it will return {false} by default, or {nil} if the {allow_maybe} flag is set.]==]
function export.is_callable(f, allow_maybe)
if type(f) == "function" then
return true
end
-- An object is a functor if it has a `__call` metamethod. The only way to truly confirm this is by trying to call it, but that could be expensive or have side effects, so look for a `__call` metamethod instead. If the metatable is protected with `__metatable`, this may not be possible.
local mt = get_unprotected_metatable(f)
if mt == nil then
return false
-- `get_unprotected_metatable` returns false if the metatable is protected.
elseif mt == false then
debug_track("fun/is_callable/protected metatable")
if allow_maybe then
return nil
end
return false
end
-- `__call` metamethods have to be functions, so don't recurse to check it.
local __call = rawget(mt, "__call")
return __call and type(__call) == "function" or false
end
is_callable = export.is_callable
--[==[
A version of {xpcall} which takes any arguments to be given to {f} as additional arguments after the error handler.
This fixes a deficiency in the standard version of {xpcall}, which is not able to handle arguments to be given to {f}, and brings it in line with {pcall}.]==]
function export.xpcall(f, err_handler, ...)
-- If there are no arguments, just call xpcall() with `f`.
if select("#", ...) == 0 then
return xpcall(f, err_handler)
end
-- Any arguments have to be smuggled in via a table, as ... can't be an
-- upvalue, and it's not possible to use pcall() to get aroud this, because
-- xpcall() calls the error handler before the stack unwinds.
local args = {...}
return xpcall(function()
return f(unpack(args))
end, err_handler)
end
do
local function catch_values(f, success, ...)
if success then
return success, ...
-- Error message will only take this exact form if `f` is not callable,
-- because it will contain a traceback if it was thrown further up the
-- stack.
elseif (...) == format("attempt to call a %s value", type(f)) then
return false
end
return error(...)
end
--[==[
A special form of {pcall()}, which returns {true} plus the result value(s) if {f} is callable, or {false} if it isn't. Errors that occur within the called function are not protected.]==]
function export.try_call(f, ...)
local callable = is_callable(f, true)
if callable then
return true, f(...)
elseif callable == false then
return false
end
-- If `callable` is nil, there's a protected metatable, so there's no way to check without doing a protected call.
return catch_values(f, pcall(f, ...))
end
end
--[==[
Takes two or more functions as arguments, and returns a new function which calls each of the input functions in turn. Any arguments given to the returned function are given to the first function, and all other functions receive the output value(s) from the previous function.]==]
function export.chain(func1, func2, ...)
local function chained_func(...)
return func2(func1(...))
end
if select("#", ...) == 0 then
return chained_func
end
return chain(chained_func, ...)
end
chain = export.chain
--[==[
Takes the usual for-loop parameters (an iterator, plus an optional state and initial index), and unrolls the iterator by returning every (first) value returned by the iterator.
For instance, {unroll(pairs(t))} will return every key in {t}, and {unroll(string.gmatch(s, "%w+"))} will return every word in {s}.]==]
function export.unroll(iter, state, k)
k = iter(state, k)
if k ~= nil then
return k, unroll(iter, state, k)
end
end
unroll = export.unroll
--[==[
Takes a generator function (i.e. a function that returns an iterator, such as {ipairs}) and one or more additional functions, and returns a new generator function. Any arguments given to the new generator (e.g. an input table) are given to the original generator, and the additional functions are called on each iteration. The first additional function takes the output from the original iterator (i.e. the function returned by the original generator), and any further functions receive the output value(s) from the previous function. This can be used to modify the values returned from an iterator.]==]
function export.chainIter(gen, new_iter, ...)
if select("#", ...) > 0 then
new_iter = chain(new_iter, ...)
end
return function(...)
local orig_iter, state, k = gen(...)
-- k has to be the first value returned by orig_iter on the last iteration, not whatever new_iter returned.
local function catch_values(...)
k = ...
if k ~= nil then
return new_iter(...)
end
end
return function()
return catch_values(orig_iter(state, k))
end, state, k
end
end
chain_iter = export.chainIter
do
local function catch_values(start, iter, state, k, ...)
if start == k or k == nil then
return k, ...
end
return catch_values(start, iter, state, iter(state, k))
end
function export.iterateFrom(start, iter, state, k)
local first = true
return function(state, k)
if first then
first = false
return catch_values(start, iter, state, iter(state, k))
end
return iter(state, k)
end, state, k
end
end
-- map(function(number) return number ^ 2 end,
-- { 1, 2, 3 }) --> { 1, 4, 9 }
-- map(function (char) return string.char(string.byte(char) - 0x20) end,
-- "abc") --> { "A", "B", "C" }
function export.map(func, iterable, isArray)
local array = {}
for k, v in (type(iterable) == "string" and iterString or (isArray or iterable[1] ~= nil) and ipairs or pairs)(iterable) do
array[k] = func(v, k, iterable)
end
return array
end
function export.mapIter(func, iter, state, init)
-- init could be anything
local array, i = {}, 0
for x, y in iter, state, init do
i = i + 1
array[i] = func(y, x, state)
end
return array
end
do
local function iter_tuples(tuples)
local i = tuples.i
if i > 1 then
i = i - 1
tuples.i = i
return unpack(tuples[i])
end
end
-- Takes an iterator function, and returns a new iterator that iterates in reverse, given the same arguments.
-- Note: changes to the state during iteration are not taken into account, since all the return values are calculated in advance.
function export.reverseIter(func)
return function(...)
-- Store all returned values as a list of tuples, then iterate in reverse over that list.
local tuples, i, iter, state, val1 = {}, 0, func(...)
while true do
i = i + 1
local vals = {iter(state, val1)}
-- Terminates if the first return value is nil, even if other values are non-nil.
val1 = vals[1]
if val1 == nil then
tuples.i = i
return iter_tuples, tuples
end
tuples[i] = vals
end
end
end
end
function export.forEach(func, iterable, isArray)
for k, v in (type(iterable) == "string" and iterString or (isArray or iterable[1] ~= nil) and ipairs or pairs)(iterable) do
func(v, k, iterable)
end
return nil
end
-------------------------------------------------
-- From http://lua-users.org/wiki/CurriedLua
-- reverse(...) : take some tuple and return a tuple of elements in reverse order
--
-- e.g. "reverse(1,2,3)" returns 3,2,1
local function reverse(...)
-- reverse args by building a function to do it, similar to the unpack() example
local function reverseHelper(acc, v, ...)
if select("#", ...) == 0 then
return v, acc()
else
return reverseHelper(function() return v, acc() end, ...)
end
end
-- initial acc is the end of the list
return reverseHelper(function() return end, ...)
end
function export.curry(func, numArgs)
-- currying 2-argument functions seems to be the most popular application
numArgs = numArgs or 2
-- no sense currying for 1 arg or less
if numArgs <= 1 then return func end
-- helper takes an argTrace function, and number of arguments remaining to be applied
local function curryHelper(argTrace, n)
if n == 0 then
-- kick off argTrace, reverse argument list, and call the original function
return func(reverse(argTrace()))
else
-- "push" argument (by building a wrapper function) and decrement n
return function(onearg)
return curryHelper(function() return onearg, argTrace() end, n - 1)
end
end
end
-- push the terminal case of argTrace into the function first
return curryHelper(function() return end, numArgs)
end
-------------------------------------------------
-- some(function(val) return val % 2 == 0 end,
-- { 2, 3, 5, 7, 11 }) --> true
function export.some(func, t, isArray)
for k, v in ((isArray or t[1] ~= nil) and ipairs or pairs)(t) do
if func(v, k, t) then
return true
end
end
return false
end
-- all(function(val) return val % 2 == 0 end,
-- { 2, 4, 8, 10, 12 }) --> true
function export.all(func, t, isArray)
for k, v in ((isArray or t[1] ~= nil) and ipairs or pairs)(t) do
if not func(v, k, t) then
return false
end
end
return true
end
function export.filter(func, t, isArray)
local new_t = {}
if isArray or t[1] ~= nil then -- array
local new_i = 0
for i, v in ipairs(t) do
if func(v, i, t) then
new_i = new_i + 1
new_t[new_i] = v
end
end
else
for k, v in pairs(t) do
if func(v, k, t) then
new_t[k] = v -- or create array?
end
end
end
return new_t
end
function export.fold(func, t, accum)
for i, v in ipairs(t) do
accum = func(accum, v, i, t)
end
return accum
end
-------------------------------
-- Fancy stuff
local function capture(...)
local vals = {n = select("#", ...), ...}
return function()
return unpack(vals, 1, vals.n)
end
end
-- Log input and output of function.
-- Receives a function and returns a modified form of that function.
function export.logReturnValues(func, prefix)
return function(...)
local inputValues = capture(...)
local returnValues = capture(func(...))
if prefix then
mw.log(prefix, inputValues())
mw.log(returnValues())
else
mw.log(inputValues())
mw.log(returnValues())
end
return returnValues()
end
end
export.log = export.logReturnValues
-- Convenience function to make all functions in a table log their input and output.
function export.logAll(t)
for k, v in pairs(t) do
if is_callable(v) then
t[k] = export.logReturnValues(v, tostring(k))
end
end
return t
end
return export
mc1wbmetcrpjp1ihyth6j2ajabvak7y
Modul:bahasa
828
6769
26527
23973
2026-05-17T11:03:48Z
id>Swarabakti
0
26527
Scribunto
text/plain
local Families = require("Module:families")
local p = {}
local langNames = {
["mul"] = "Lintas bahasa",
-- Kode bahasa
["aa"] = "Afar",
["aaa"] = "Ghotuo",
["aab"] = "Alumu-Tesu",
["aac"] = "Ari",
["aad"] = "Amal",
["aaf"] = "Aranadan",
["aag"] = "Ambrak",
["aah"] = "Arapesh Abu'",
["aai"] = "Arifama-Miniafia",
["aak"] = "Ankave",
["aal"] = "Afade",
["aan"] = "Anambé",
["aap"] = "Arára Pará",
["aaq"] = "Penobscot",
["aas"] = "Aasax",
["aau"] = "Abau",
["aav-khs-pro"] = "Proto-Khasi",
["aav-nic-pro"] = "Proto-Nikobar",
["aav-pkl-pro"] = "Proto-Pnar-Khasi-Lyngngam",
["aav-pro"] = "Proto-Austroasiatik",
["aaw"] = "Solong",
["aax"] = "Mandobo Atas",
["aaz"] = "Amarasi",
["ab"] = "Abkhaz",
["aba"] = "Abé",
["abb"] = "Bankon",
["abc"] = "Ayta Ambala",
["abd"] = "Agta Camarines Norte",
["abe"] = "Abenaki",
["abf"] = "Abai Sungai",
["abg"] = "Abaga",
["abh"] = "Arab Tajik",
["abi"] = "Abidji",
["abj"] = "Aka-Bea",
["abl"] = "Lampung Nyo",
["abm"] = "Abanyom",
["abn"] = "Abua",
["abo"] = "Abon",
["abp"] = "Ayta Abenlen",
["abq"] = "Abaza",
["abr"] = "Abron",
["abs"] = "Melayu Ambon",
["abt"] = "Ambulas",
["abu"] = "Abure",
["abv"] = "Arab Baharna",
["abw"] = "Pal",
["abx"] = "Inabaknon",
["aby"] = "Aneme Wake",
["abz"] = "Abui",
["aca"] = "Achagua",
["acb"] = "Áncá",
["acd"] = "Gikyode",
["ace"] = "Aceh",
["ach"] = "Acholi",
["aci"] = "Aka-Cari",
["ack"] = "Aka-Kora",
["acl"] = "Akar-Bale",
["acm"] = "Arab Irak",
["acn"] = "Achang",
["acp"] = "Acipa Timur",
["acr"] = "Achi",
["acs"] = "Acroá",
["acu"] = "Achuar",
["acv"] = "Achumawi",
["acw"] = "Arab Hijaz",
["acx"] = "Arab Oman",
["acy"] = "Arab Siprus",
["acz"] = "Acheron",
["ada"] = "Adangme",
["adb"] = "Adabe",
["add"] = "Dzodinka",
["ade"] = "Adele",
["adf"] = "Arab Dhofar",
["adg"] = "Andegerebinha",
["adh"] = "Adhola",
["adi"] = "Adi",
["adj"] = "Adioukrou",
["adl"] = "Galo",
["adn"] = "Adang",
["ado"] = "Abu",
["adp"] = "Adap",
["adq"] = "Adangbe",
["adr"] = "Adonara",
["ads"] = "Isyarat Adamorobe",
["adt"] = "Adnyamathanha",
["adu"] = "Aduge",
["adw"] = "Amondawa",
["ady"] = "Adyghe",
["adz"] = "Adzera",
["ae"] = "Avestan",
["aea"] = "Areba",
["aeb"] = "Arab Tunisia",
["aed"] = "Isyarat Argentina",
["aee"] = "Pashayi Timur Laut",
["aek"] = "Haeke",
["ael"] = "Ambele",
["aem"] = "Arem",
["aen"] = "Isyarat Armenia",
["aeq"] = "Aer",
["aer"] = "Arrernte Timur",
["aes"] = "Alsea",
["aeu"] = "Akeu",
["aew"] = "Ambakich",
["aey"] = "Amele",
["aez"] = "Aeka",
["af"] = "Afrikaans",
["afa-pro"] = "Proto-Afroasiatik",
["afb"] = "Arab Teluk",
["afd"] = "Andai",
["afe"] = "Putukwam",
["afg"] = "Isyarat Afghan",
["afh"] = "Afrihili",
["afi"] = "Akrukay",
["afk"] = "Nanubae",
["afn"] = "Defaka",
["afo"] = "Eloyi",
["afp"] = "Tapei",
["afs"] = "Kreol Afro-Seminole",
["aft"] = "Afitti",
["afu"] = "Awutu",
["afz"] = "Obokuitai",
["aga"] = "Aguano",
["agb"] = "Legbo",
["agc"] = "Agatu",
["agd"] = "Agarabi",
["age"] = "Angal",
["agf"] = "Arguni",
["agg"] = "Angor",
["agh"] = "Ngelima",
["agi"] = "Agariya",
["agj"] = "Argobba",
["agk"] = "Agta Isarog",
["agl"] = "Fembe",
["agm"] = "Angaataha",
["agn"] = "Agutaynen",
["ago"] = "Tainae",
["agq"] = "Aghem",
["agr"] = "Aguaruna",
["ags"] = "Esimbi",
["agt"] = "Agta Cagayan Tengah",
["agu"] = "Aguacateca",
["agv"] = "Agta Remontado",
["agw"] = "Kahua",
["agx"] = "Aghul",
["agy"] = "Alta Selatan",
["agz"] = "Agta Mount Iriga",
["aha"] = "Ahanta",
["ahb"] = "Axamb",
["ahg"] = "Qimant",
["ahh"] = "Aghu",
["ahi"] = "Aizi Tiagbamrin",
["ahk"] = "Akha",
["ahl"] = "Igo",
["ahm"] = "Aizi Mobumrin",
["ahn"] = "Àhàn",
["aho"] = "Ahom",
["ahp"] = "Aizi Aproumu",
["ahr"] = "Ahirani",
["ahs"] = "Ashe",
["aht"] = "Ahtna",
["aia"] = "Arosi",
["aib"] = "Aynu",
["aic"] = "Ainbai",
["aid"] = "Alngith",
["aie"] = "Amara",
["aif"] = "Agi",
["aig"] = "Kreol Inggris Antigua dan Barbuda",
["aih"] = "Ai-Cham",
["aii"] = "Neo-Aramaik Asyur",
["aij"] = "Lishanid Noshan",
["aik"] = "Ake",
["ail"] = "Aimele",
["aim"] = "Aimol",
["ain"] = "Ainu",
["aio"] = "Aiton",
["aip"] = "Burumakok",
["air"] = "Airoran",
["ait"] = "Arikem",
["aiw"] = "Aari",
["aix"] = "Aighon",
["aiy"] = "Ali",
["aja"] = "Aja",
["ajg"] = "Adja",
["aji"] = "Ajië",
["ajn"] = "Andajin",
["ajp"] = "Arab Syam Selatan",
["ajw"] = "Ajawa",
["ajz"] = "Karbi Amri",
["ak"] = "Akan",
["akb"] = "Angkola",
["akc"] = "Mpur",
["akd"] = "Ukpet-Ehom",
["ake"] = "Akawaio",
["akf"] = "Akpa",
["akg"] = "Anakalangu",
["akh"] = "Angal Heneng",
["aki"] = "Aiome",
["akj"] = "Jeru",
["akk"] = "Akkad",
["akl"] = "Aklanon",
["akm"] = "Aka-Bo",
["ako"] = "Akurio",
["akp"] = "Siwu",
["akq"] = "Ak",
["akr"] = "Araki",
["aks"] = "Akaselem",
["akt"] = "Akolet",
["aku"] = "Akum",
["akv"] = "Akhvakh",
["akw"] = "Akwa",
["akx"] = "Aka-Kede",
["aky"] = "Aka-Kol",
["akz"] = "Alabama",
["ala"] = "Alago",
["alc"] = "Kawésqar",
["ald"] = "Allad",
["ale"] = "Aleut",
["alf"] = "Alege",
["alg-aga"] = "Agawam",
["alg-pro"] = "Proto-Algonquia",
["alh"] = "Alawa",
["ali"] = "Amaimon",
["alj"] = "Alangan",
["alk"] = "Alak",
["all"] = "Allar",
["alm"] = "Amblong",
["alo"] = "Larike-Wakasihu",
["alp"] = "Alune",
["alq"] = "Algonquin",
["alr"] = "Alutor",
["alt"] = "Altai Selatan",
["alu"] = "'Are'are",
["alv-ama"] = "Amasi",
["alv-bgu"] = "Baïnounk Gubëeher",
["alv-bua-pro"] = "Proto-Bua",
["alv-cng-pro"] = "Proto-Cangin",
["alv-edk-pro"] = "Proto-Edekiri",
["alv-edo-pro"] = "Proto-Edoid",
["alv-fli-pro"] = "Proto-Fali",
["alv-gbe-pro"] = "Proto-Gbe",
["alv-gng-pro"] = "Proto-Guang",
["alv-gtm-pro"] = "Proto-Togo Tengah",
["alv-gwa"] = "Gwara",
["alv-hei-pro"] = "Proto-Heiban",
["alv-ido-pro"] = "Proto-Idomoid",
["alv-igb-pro"] = "Proto-Igboid",
["alv-kwa-pro"] = "Proto-Kwa",
["alv-mum-pro"] = "Proto-Mumuye",
["alv-nup-pro"] = "Proto-Nupoid",
["alv-pro"] = "Proto-Atlantik-Kongo",
["alv-von-pro"] = "Proto-Volta-Niger",
["alv-yor-pro"] = "Proto-Yoruba",
["alv-yrd-pro"] = "Proto-Yoruboid",
["alw"] = "Alaba",
["alx"] = "Amol",
["aly"] = "Alyawarr",
["alz"] = "Alur",
["am"] = "Amharik",
["ama"] = "Amanayé",
["amb"] = "Ambo",
["amc"] = "Amahuaca",
["ame"] = "Yanesha'",
["amf"] = "Hamer-Banna",
["amg"] = "Amurdag",
["ami"] = "Amis",
["amj"] = "Amdang",
["amk"] = "Ambai",
["aml"] = "War-Jaintia",
["amm"] = "Ama",
["amn"] = "Amanab",
["amo"] = "Amo",
["amp"] = "Alamblak",
["amq"] = "Amahai",
["amr"] = "Amarakaeri",
["ams"] = "Amami-Oshima Selatan",
["amt"] = "Amto",
["amu"] = "Amuzgo Guerrero",
["amv"] = "Ambelau",
["amw"] = "Neo-Aramaik Barat",
["amx"] = "Anmatyerre",
["amy"] = "Ami",
["amz"] = "Atampaya",
["an"] = "Aragon",
["ana"] = "Andaqui",
["anb"] = "Andoa",
["anc"] = "Ngas",
["and"] = "Ansus",
["ane"] = "Xârâcùù",
["anf"] = "Animere",
["ang"] = "Inggris Kuno",
["anh"] = "Nend",
["ani"] = "Andi",
["anj"] = "Anor",
["ank"] = "Goemai",
["anl"] = "Anu",
["anm"] = "Anal",
["ann"] = "Obolo",
["ano"] = "Andoque",
["anp"] = "Angika",
["anq"] = "Jarawa",
["anr"] = "Andh",
["ans"] = "Anserma",
["ant"] = "Antakarinya",
["anu"] = "Anuak",
["anv"] = "Denya",
["anw"] = "Anaang",
["anx"] = "Andra-Hus",
["any"] = "Anyi",
["anz"] = "Anem",
["aoa"] = "Angolar",
["aob"] = "Abom",
["aoc"] = "Pemon",
["aod"] = "Andarum",
["aoe"] = "Angal Enen",
["aof"] = "Bragat",
["aog"] = "Angoram",
["aoi"] = "Anindilyakwa",
["aoj"] = "Mufian",
["aok"] = "Arhö",
["aol"] = "Alor",
["aom"] = "Ömie",
["aon"] = "Arapesh Bumbita",
["aor"] = "Aore",
["aos"] = "Taikat",
["aot"] = "Atong (India)",
["aou"] = "A'ou",
["aox"] = "Atorada",
["aoz"] = "Uab Meto",
["apa-pro"] = "Proto-Apache",
["apb"] = "Sa'a",
["apc"] = "Arab Syam Utara",
["apd"] = "Arab Sudan",
["ape"] = "Bukiyip",
["apf"] = "Agta Pahanan",
["apg"] = "Ampanang",
["aph"] = "Athpare",
["api"] = "Apiaká",
["apj"] = "Jicarilla",
["apk"] = "Apache Plains",
["apl"] = "Lipan",
["apm"] = "Chiricahua",
["apn"] = "Apinayé",
["apo"] = "Ambul",
["app"] = "Apma",
["apq"] = "A-Pucikwar",
["apr"] = "Arop-Lokep",
["aps"] = "Arop-Sissano",
["apt"] = "Apatani",
["apu"] = "Apurinã",
["apv"] = "Alapmunte",
["apw"] = "Apache Barat",
["apx"] = "Aputai",
["apy"] = "Apalaí",
["apz"] = "Safeyoka",
["aqc"] = "Archi",
["aqd"] = "Dogon Ampari",
["aqg"] = "Arigidi",
["aql-pro"] = "Proto-Algic",
["aqm"] = "Atohwaim",
["aqn"] = "Alta Utara",
["aqp"] = "Atakapa",
["aqr"] = "Arhâ",
["aqt"] = "Angaité",
["aqz"] = "Akuntsu",
["ar"] = "Arab",
["arc"] = "Aramaik",
["ard"] = "Arabana",
["are"] = "Arrernte Barat",
["arh"] = "Arhuaco",
["ari"] = "Arikara",
["arj"] = "Arapaso",
["ark"] = "Arikapú",
["arl"] = "Arabela",
["arn"] = "Mapudungun",
["aro"] = "Araona",
["arp"] = "Arapaho",
["arq"] = "Arab Aljazair",
["arr"] = "Arara-Karo",
["ars"] = "Arab Najdi",
["art-blk"] = "Bolak",
["art-bsp"] = "Black Speech",
["art-com"] = "Communicationssprache",
["art-dtk"] = "Dothraki",
["art-elo"] = "Eloi",
["art-gld"] = "Goa'uld",
["art-lap"] = "Lapine",
["art-man"] = "Mandalorian",
["art-mun"] = "Mundolinco",
["art-nav"] = "Na'vi",
["art-nox"] = "Noxilo",
["art-una"] = "Unas",
["art-vlh"] = "High Valyrian",
["aru"] = "Arua",
["arv"] = "Arbore",
["arw"] = "Arawak",
["arx"] = "Aruá",
["ary"] = "Arab Moroko",
["arz"] = "Arab Mesir",
["as"] = "Assam",
["asa"] = "Pare",
["asb"] = "Assiniboine",
["asc"] = "Asmat Pesisir Casuarina",
["ase"] = "Isyarat Amerika Serikat",
["asf"] = "Auslan",
["asg"] = "Cishingini",
["ash"] = "Abishira",
["asi"] = "Buruwai",
["asj"] = "Nsari",
["ask"] = "Ashkun",
["asl"] = "Asilulu",
["asn"] = "Xingú Asuriní",
["aso"] = "Dano",
["asp"] = "Isyarat Aljazair",
["asq"] = "Isyarat Austria",
["asr"] = "Asuri",
["ass"] = "Ipulo",
["ast"] = "Asturia",
["asu"] = "Tocantins Asurini",
["asv"] = "Asoa",
["asw"] = "Isyarat Aborigin Australia",
["asx"] = "Muratayak",
["asy"] = "Asmat Yaosakor",
["asz"] = "As",
["ata"] = "Pele-Ata",
["atb"] = "Zaiwa",
["atc"] = "Atsahuaca",
["atd"] = "Manobo Ata",
["ate"] = "Atemble",
["atg"] = "Okpela",
["ath-nic"] = "Nicola",
["ath-pro"] = "Proto-Athabaskan",
["ati"] = "Attié",
["atj"] = "Atikamekw",
["atk"] = "Ati",
["atl"] = "Agta Mount Iraya",
["atm"] = "Ata",
["ato"] = "Atong (Kamerun)",
["atp"] = "Atta Pudtol",
["atq"] = "Aralle-Tabulahan",
["atr"] = "Waimiri-Atroari",
["ats"] = "Gros Ventre",
["att"] = "Atta Pamplona",
["atu"] = "Reel",
["atv"] = "Altai Utara",
["atw"] = "Atsugewi",
["atx"] = "Arutani",
["aty"] = "Aneityum",
["atz"] = "Arta",
["aua"] = "Asumboa",
["aub"] = "Alugu",
["auc"] = "Huaorani",
["aud"] = "Anuta",
["auf-pro"] = "Proto-Arawa",
["aug"] = "Aguna",
["auh"] = "Aushi",
["aui"] = "Anuki",
["auj"] = "Awjila",
["auk"] = "Heyo",
["aul"] = "Aulua",
["aum"] = "Asu",
["aun"] = "One Molmo",
["auo"] = "Auyokawa",
["aup"] = "Makayam",
["auq"] = "Anus",
["aur"] = "Aruek",
["aus-alu"] = "Alungul",
["aus-and"] = "Andjingith",
["aus-ang"] = "Angkula",
["aus-arn-pro"] = "Proto-Arnhem",
["aus-bra"] = "Barranbinya",
["aus-brm"] = "Barunggam",
["aus-cww-pro"] = "Proto-New South Wales Tengah",
["aus-dal-pro"] = "Proto-Daly",
["aus-guw"] = "Guwar",
["aus-lsw"] = "Little Swanport",
["aus-mbi"] = "Mbiywom",
["aus-ngk"] = "Ngkoth",
["aus-nyu-pro"] = "Proto-Nyulnyulan",
["aus-pam-pro"] = "Proto-Pama-Nyungan",
["aus-tul"] = "Tulua",
["aus-uwi"] = "Uwinymil",
["aus-wdj-pro"] = "Proto-Iwaidjan",
["aus-won"] = "Wong-gie",
["aus-wul"] = "Wulguru",
["aus-ynk"] = "Yangkaal",
["aut"] = "Austral",
["auu"] = "Auye",
["auw"] = "Awyi",
["aux"] = "Aurá",
["auy"] = "Auyana",
["auz"] = "Arab Uzbek",
["av"] = "Avar",
["avb"] = "Avau",
["avd"] = "Alviri-Vidari",
["avi"] = "Avikam",
["avk"] = "Kotava",
["avm"] = "Angkamuthi",
["avn"] = "Avatime",
["avo"] = "Agavotaguerra",
["avs"] = "Aushiri",
["avt"] = "Au",
["avu"] = "Avokaya",
["avv"] = "Avá-Canoeiro",
["awa"] = "Awadhi",
["awb"] = "Awa (Papua)",
["awc"] = "Cicipu",
["awd-ama"] = "Amarizana",
["awd-amc-pro"] = "Proto-Amuesha-Chamicuro",
["awd-ana"] = "Anauyá",
["awd-apo"] = "Apolista",
["awd-cav"] = "Cavere",
["awd-gnu"] = "Guinau",
["awd-kar"] = "Cariay",
["awd-kaw"] = "Kawishana",
["awd-kmp-pro"] = "Proto-Kampa",
["awd-kus"] = "Kustenau",
["awd-man"] = "Manao",
["awd-mar"] = "Marawan",
["awd-mpr"] = "Maypure",
["awd-mrt"] = "Mariaté",
["awd-nwk-pro"] = "Proto-Nawiki",
["awd-pai"] = "Paikoneka",
["awd-pas"] = "Passé",
["awd-pro"] = "Proto-Arawak",
["awd-prw-pro"] = "Proto-Paresi-Waura",
["awd-she"] = "Shebayo",
["awd-taa-pro"] = "Proto-Ta-Arawak",
["awd-wai"] = "Wainumá",
["awd-yum"] = "Yumana",
["awe"] = "Awetí",
["awg"] = "Anguthimri",
["awh"] = "Awbono",
["awi"] = "Aekyom",
["awk"] = "Awabakal",
["awm"] = "Arawum",
["awn"] = "Awngi",
["awo"] = "Awak",
["awr"] = "Awera",
["aws"] = "Awyu Selatan",
["awt"] = "Araweté",
["awu"] = "Awyu Tengah",
["awv"] = "Awyu Jair",
["aww"] = "Awun",
["awx"] = "Awara",
["awy"] = "Awyu Edera",
["axb"] = "Abipon",
["axe"] = "Ayerrerenge",
["axg"] = "Arára Mato Grosso",
["axk"] = "Aka (Afrika Tengah)",
["axl"] = "Aranda Selatan Bawah",
["axm"] = "Armenia Pertengahan",
["axx"] = "Xaragure",
["ay"] = "Aymara",
["aya"] = "Awar",
["ayb"] = "Ayizo",
["ayd"] = "Ayabadhu",
["aye"] = "Ayere",
["ayg"] = "Nyanga (Togo)",
["ayi"] = "Leyigha",
["ayk"] = "Akuku",
["ayl"] = "Arab Libya",
["ayn"] = "Arab Yemen",
["ayo"] = "Ayoreo",
["ayp"] = "Arab Mesopotamia Utara",
["ayq"] = "Ayi",
["ays"] = "Sorsogon Ayta",
["ayt"] = "Ayta Bataan",
["ayu"] = "Ayu",
["ayy"] = "Ayta Tayabas",
["ayz"] = "Maybrat",
["az"] = "Azerbaijan",
["aza"] = "Azha",
["azc-caz"] = "Cazcan",
["azc-cup-pro"] = "Proto-Cupan",
["azc-ktn"] = "Kitanemuk",
["azc-nah-pro"] = "Proto-Nahuan",
["azc-num-pro"] = "Proto-Numic",
["azc-pro"] = "Proto-Uto-Aztecan",
["azc-tak-pro"] = "Proto-Takic",
["azc-tat"] = "Tataviam",
["azd"] = "Nahuatl Durango Timur",
["azg"] = "Amuzgo San Pedro Amuzgos",
["azm"] = "Amuzgo Ipalapa",
["azn"] = "Nahuatl Durango Barat",
["azo"] = "Awing",
["azt"] = "Atta Faire",
["azz"] = "Nahuatl Pegunungan Puebla",
["ba"] = "Bashkir",
["baa"] = "Babatana",
["bab"] = "Bainouk-Gunyuño",
["bac"] = "Baduy",
["bae"] = "Baré",
["baf"] = "Nubaca",
["bag"] = "Tuki",
["bah"] = "Kreol Bahama",
["baj"] = "Barakai",
["bal"] = "Baluchi",
["ban"] = "Bali",
["bao"] = "Waimaha",
["bap"] = "Bantawa",
["bar"] = "Bavaria",
["bas"] = "Basaa",
["bau"] = "Badanchi",
["bav"] = "Babungo",
["baw"] = "Bambili-Bambui",
["bax"] = "Bamum",
["bay"] = "Batuley",
["bba"] = "Baatonum",
["bbb"] = "Barai",
["bbc"] = "Batak Toba",
["bbd"] = "Bau",
["bbe"] = "Bangba",
["bbf"] = "Baibai",
["bbg"] = "Barama",
["bbh"] = "Bugan",
["bbi"] = "Barombi",
["bbj"] = "Ghomala'",
["bbk"] = "Babanki",
["bbl"] = "Bats",
["bbm"] = "Babango",
["bbn"] = "Uneapa",
["bbo"] = "Konabéré",
["bbp"] = "Banda Tengah Barat",
["bbq"] = "Bamali",
["bbr"] = "Girawa",
["bbs"] = "Bakpinka",
["bbt"] = "Mburku",
["bbu"] = "Bakulung",
["bbv"] = "Karnai",
["bbw"] = "Baba",
["bbx"] = "Bubia",
["bby"] = "Befang",
["bca"] = "Bai Tengah",
["bcb"] = "Bainouk-Samik",
["bcd"] = "Babar Utara",
["bce"] = "Bamenyam",
["bcf"] = "Bamu",
["bcg"] = "Baga Pokur",
["bch"] = "Bariai",
["bci"] = "Baoule",
["bcj"] = "Bardi",
["bck"] = "Bunaba",
["bcl"] = "Bikol Tengah",
["bcm"] = "Banoni",
["bcn"] = "Bibaali",
["bco"] = "Kaluli",
["bcp"] = "Bali (Kongo)",
["bcq"] = "Bench",
["bcr"] = "Babine-Witsuwit'en",
["bcs"] = "Kohumono",
["bct"] = "Bendi",
["bcu"] = "Biliau",
["bcv"] = "Shoo-Minda-Nye",
["bcw"] = "Bana",
["bcy"] = "Bacama",
["bcz"] = "Bainouk-Gunyaamolo",
["bda"] = "Bayot",
["bdb"] = "Basap",
["bdc"] = "Emberá-Baudó",
["bdd"] = "Bunama",
["bde"] = "Bade",
["bdf"] = "Biage",
["bdg"] = "Bonggi",
["bdh"] = "Tara Baka",
["bdi"] = "Burun",
["bdj"] = "Bai",
["bdk"] = "Budukh",
["bdl"] = "Bajau Indonesia",
["bdm"] = "Buduma",
["bdn"] = "Baldemu",
["bdo"] = "Morom",
["bdp"] = "Bende",
["bdq"] = "Bahnar",
["bdr"] = "Bajau Pesisir Barat",
["bds"] = "Burunge",
["bdt"] = "Bokoto",
["bdu"] = "Oroko",
["bdv"] = "Bodo Parja",
["bdw"] = "Baham",
["bdx"] = "Budong-Budong",
["bdy"] = "Bandjalang",
["bdz"] = "Badeshi",
["be"] = "Belarus",
["bea"] = "Beaver",
["beb"] = "Bebele",
["bec"] = "Iceve-Maci",
["bed"] = "Bedoanas",
["bee"] = "Byangsi",
["bef"] = "Benabena",
["beg"] = "Belait",
["beh"] = "Biali",
["bei"] = "Bekati'",
["bej"] = "Beja",
["bek"] = "Bebeli",
["bem"] = "Bemba",
["beo"] = "Beami",
["bep"] = "Besoa",
["beq"] = "Beembe",
["ber-fog"] = "Fogaha",
["ber-pro"] = "Proto-Berber",
["ber-zuw"] = "Zuwara",
["bes"] = "Besme",
["bet"] = "Bété Guiberoua",
["beu"] = "Blagar",
["bev"] = "Bété Daloa",
["bew"] = "Betawi",
["bex"] = "Jur Modo",
["bey"] = "Akuwagel",
["bez"] = "Kibena",
["bfa"] = "Bari",
["bfb"] = "Bareli Pauri",
["bfc"] = "Bai Utara",
["bfd"] = "Bafut",
["bfe"] = "Betaf",
["bff"] = "Bofi",
["bfg"] = "Kayan Busang",
["bfh"] = "Blafe",
["bfi"] = "Isyarat Britania",
["bfj"] = "Bafanji",
["bfk"] = "Isyarat Ban Khor",
["bfl"] = "Banda-Ndélé",
["bfm"] = "Mmen",
["bfn"] = "Bunak",
["bfo"] = "Birifor Malba",
["bfp"] = "Beba",
["bfq"] = "Badaga",
["bfr"] = "Bazigar",
["bfs"] = "Bai Selatan",
["bft"] = "Balti",
["bfu"] = "Gahri",
["bfw"] = "Bondo",
["bfx"] = "Bantayanon",
["bfy"] = "Bagheli",
["bfz"] = "Pahari Mahasu",
["bg"] = "Bulgaria",
["bga"] = "Gwamhi-Wuri",
["bgb"] = "Bobongko",
["bgc"] = "Haryanvi",
["bgd"] = "Bareli Rathwi",
["bge"] = "Bauria",
["bgf"] = "Bangandu",
["bgg"] = "Bugun",
["bgi"] = "Giangan",
["bgj"] = "Bangolan",
["bgk"] = "Bit",
["bgl"] = "Bo",
["bgo"] = "Baga Koga",
["bgq"] = "Bagri",
["bgr"] = "Chin Bawm",
["bgs"] = "Tagabawa",
["bgt"] = "Bughotu",
["bgu"] = "Mbongno",
["bgv"] = "Warkay-Bipim",
["bgw"] = "Bhatri",
["bgx"] = "Turki Balkan Gagauz",
["bgy"] = "Benggoi",
["bgz"] = "Banggai",
["bh"] = "Bihar",
["bha"] = "Bharia",
["bhb"] = "Bhili",
["bhc"] = "Biga",
["bhd"] = "Bhadrawahi",
["bhe"] = "Bhaya",
["bhf"] = "Odiai",
["bhg"] = "Binandere",
["bhh"] = "Bukhari",
["bhi"] = "Bhilali",
["bhj"] = "Bahing",
["bhl"] = "Bimin",
["bhm"] = "Bathari",
["bhn"] = "Neo-Aramaik Bohtan",
["bho"] = "Bhojpuri",
["bhp"] = "Bima",
["bhq"] = "Tukang Besi Selatan",
["bhs"] = "Buwal",
["bht"] = "Bhattiyali",
["bhu"] = "Bhunjia",
["bhv"] = "Bahau",
["bhw"] = "Biak",
["bhx"] = "Bhalay",
["bhy"] = "Bhele",
["bhz"] = "Bada",
["bi"] = "Bislama",
["bia"] = "Badimaya",
["bib"] = "Bissa",
["bic"] = "Bikaru",
["bid"] = "Bidiyo",
["bie"] = "Bepour",
["bif"] = "Biafada",
["big"] = "Biangai",
["bij"] = "Kwanka",
["bil"] = "Bile",
["bim"] = "Bimoba",
["bin"] = "Edo",
["bio"] = "Nai",
["bip"] = "Bila",
["biq"] = "Bipi",
["bir"] = "Bisorio",
["bit"] = "Berinomo",
["biu"] = "Biete",
["biv"] = "Birifor Selatan",
["biw"] = "Kol (Kamerun)",
["bix"] = "Bijori",
["biy"] = "Birhor",
["biz"] = "Baloi",
["bja"] = "Budza",
["bjb"] = "Barngarla",
["bjc"] = "Bariji",
["bje"] = "Mien Biao-Jiao",
["bjf"] = "Neo-Aramaik Barzani Jewish",
["bjg"] = "Bidyogo",
["bjh"] = "Bahinemo",
["bji"] = "Burji",
["bjj"] = "Kannauji",
["bjk"] = "Barok",
["bjl"] = "Bulu (Papua)",
["bjm"] = "Bajelani",
["bjn"] = "Banjar",
["bjo"] = "Banda Selatan-Tengah",
["bjp"] = "Fanamaket",
["bjr"] = "Binumarien",
["bjs"] = "Bajan",
["bjt"] = "Balanta-Ganja",
["bju"] = "Busuu",
["bjv"] = "Bedjond",
["bjw"] = "Bakwé",
["bjx"] = "Itneg Banao",
["bjy"] = "Bayali",
["bjz"] = "Baruga",
["bka"] = "Kyak",
["bkc"] = "Baka",
["bkd"] = "Binukid",
["bkf"] = "Beeke",
["bkg"] = "Buraka",
["bkh"] = "Bakoko",
["bki"] = "Baki",
["bkj"] = "Pande",
["bkk"] = "Brokskat",
["bkl"] = "Berik",
["bkm"] = "Kom (Kamerun)",
["bkn"] = "Bukitan",
["bko"] = "Kwa'",
["bkp"] = "Iboko",
["bkq"] = "Bakairí",
["bkr"] = "Bakumpai",
["bks"] = "Sorsogon Masbate",
["bkt"] = "Boloki",
["bku"] = "Buhid",
["bkv"] = "Bekwarra",
["bkw"] = "Bekwel",
["bkx"] = "Baikeno",
["bky"] = "Bokyi",
["bkz"] = "Bungku",
["bla"] = "Blackfoot",
["blb"] = "Bilua",
["blc"] = "Bella Coola",
["bld"] = "Bolango",
["ble"] = "Balanta-Kentohe",
["blf"] = "Buol",
["blg"] = "Balau",
["blh"] = "Kuwaa",
["bli"] = "Bolia",
["blj"] = "Bolongan",
["blk"] = "Karen Pa'o",
["bll"] = "Biloxi",
["blm"] = "Beli",
["bln"] = "Bicolano Catanduanes Selatan",
["blo"] = "Anii",
["blp"] = "Blablanga",
["blq"] = "Baluan-Pam",
["blr"] = "Blang",
["bls"] = "Balaesang",
["blt"] = "Tai Dam",
["blv"] = "Kibala",
["blw"] = "Balangao",
["blx"] = "Ayta Mag-Indi",
["bly"] = "Notre",
["blz"] = "Balantak",
["bm"] = "Bambara",
["bma"] = "Lame",
["bmb"] = "Bembe",
["bmc"] = "Biem",
["bmd"] = "Baga Manduri",
["bme"] = "Limassa",
["bmf"] = "Bom",
["bmg"] = "Bamwe",
["bmh"] = "Kein",
["bmi"] = "Bagirmi",
["bmj"] = "Bote-Majhi",
["bmk"] = "Ghayavi",
["bml"] = "Bomboli",
["bmn"] = "Bina",
["bmo"] = "Bambalang",
["bmp"] = "Bulgebi",
["bmq"] = "Bomu",
["bmr"] = "Muinane",
["bmt"] = "Mon Biao",
["bmu"] = "Somba-Siawari",
["bmv"] = "Bum",
["bmw"] = "Bomwali",
["bmx"] = "Baimak",
["bmz"] = "Baramu",
["bn"] = "Bengali",
["bna"] = "Bonerate",
["bnb"] = "Bookan",
["bnd"] = "Banda",
["bne"] = "Bintauna",
["bnf"] = "Masiwang",
["bng"] = "Benga",
["bni"] = "Bangi",
["bnj"] = "Tawbuid Timur",
["bnk"] = "Bierebo",
["bnl"] = "Boon",
["bnm"] = "Batanga",
["bnn"] = "Bunun",
["bno"] = "Asi",
["bnp"] = "Bola",
["bnq"] = "Bantik",
["bnr"] = "Butmas-Tur",
["bns"] = "Bundeli",
["bnt-bal"] = "Balong",
["bnt-bon"] = "Boma Nkuu",
["bnt-boy"] = "Boma Yumu",
["bnt-bwa"] = "Bwala",
["bnt-cmw"] = "Chimwiini",
["bnt-ind"] = "Indanga",
["bnt-lal"] = "Lala (Afrika Selatan)",
["bnt-lwl"] = "Lwel",
["bnt-mpi"] = "Mpiin",
["bnt-mpu"] = "Mpuono",
["bnt-ngu-pro"] = "Proto-Nguni",
["bnt-phu"] = "Phuthi",
["bnt-pro"] = "Proto-Bantu",
["bnt-sbo"] = "Boma Selatan",
["bnt-sts-pro"] = "Proto-Sotho-Tswana",
["bnu"] = "Bentong",
["bnv"] = "Beneraf",
["bnw"] = "Bisis",
["bnx"] = "Bangubangu",
["bny"] = "Bintulu",
["bnz"] = "Beezen",
["bo"] = "Tibet",
["boa"] = "Bora",
["bob"] = "Aweer",
["boe"] = "Mundabli",
["bof"] = "Bolon",
["bog"] = "Isyarat Bamako",
["boh"] = "Boma Utara",
["boi"] = "Barbareño",
["boj"] = "Anjam",
["bok"] = "Bonjo",
["bol"] = "Bole",
["bom"] = "Berom",
["bon"] = "Bine",
["boo"] = "Bozo Tiemacèwè",
["bop"] = "Bonkiman",
["boq"] = "Bogaya",
["bor"] = "Borôro",
["bot"] = "Bongo",
["bou"] = "Bondei",
["bov"] = "Tuwuli",
["bow"] = "Rema",
["box"] = "Buamu",
["boy"] = "Bodo (Afrika Tengah)",
["boz"] = "Bozo Tiéyaxo",
["bpa"] = "Dakaka",
["bpd"] = "Banda-Banda",
["bpg"] = "Bonggo",
["bph"] = "Botlikh",
["bpi"] = "Bagupi",
["bpj"] = "Binji",
["bpk"] = "Orowe",
["bpl"] = "Pijin Broome Pearling Lugger",
["bpm"] = "Biyom",
["bpn"] = "Dzao Min",
["bpo"] = "Anasi",
["bpp"] = "Kaure",
["bpq"] = "Melayu Banda",
["bpr"] = "Blaan Koronadal",
["bps"] = "Blaan Sarangani",
["bpt"] = "Barrow Point",
["bpu"] = "Bongu",
["bpv"] = "Marind Bian",
["bpx"] = "Bareli Palya",
["bpy"] = "Manipuri Bishnupriya",
["bpz"] = "Bilba",
["bqa"] = "Tchumbuli",
["bqb"] = "Bagusa",
["bqc"] = "Boko",
["bqd"] = "Bung",
["bqf"] = "Baga Kaloum",
["bqg"] = "Bago-Kusuntu",
["bqh"] = "Baima",
["bqi"] = "Bakhtiari",
["bqj"] = "Bandial",
["bqk"] = "Banda-Mbrès",
["bql"] = "Bilakura",
["bqm"] = "Wumboko",
["bqn"] = "Isyarat Bulgaria",
["bqo"] = "Balo",
["bqp"] = "Busa",
["bqq"] = "Biritai",
["bqr"] = "Burusu",
["bqs"] = "Bosngun",
["bqt"] = "Bamukumbit",
["bqu"] = "Boguru",
["bqv"] = "Begbere-Ejar",
["bqw"] = "Buru (Nigeria)",
["bqx"] = "Baangi",
["bqy"] = "Isyarat Bengkala",
["bqz"] = "Bakaka",
["br"] = "Breton",
["bra"] = "Braj",
["brb"] = "Lave",
["brc"] = "Kreol Belanda Berbice",
["brd"] = "Baraamu",
["brf"] = "Bera",
["brg"] = "Baure",
["brh"] = "Brahui",
["bri"] = "Mokpwe",
["brj"] = "Bieria",
["brk"] = "Birgid",
["brl"] = "Birwa",
["brm"] = "Barambu",
["brn"] = "Boruca",
["bro"] = "Brokkat",
["brp"] = "Barapasi",
["brq"] = "Breri",
["brr"] = "Birao",
["brs"] = "Baras",
["brt"] = "Bitare",
["bru"] = "Bru Timur",
["brv"] = "Bru Barat",
["brw"] = "Bellari",
["brx"] = "Bodo (India)",
["bry"] = "Burui",
["brz"] = "Bilbil",
["bsa"] = "Abinomn",
["bsb"] = "Bisaya Brunei",
["bsc"] = "Bassari",
["bse"] = "Wushi",
["bsf"] = "Bauchi",
["bsg"] = "Bashkardi",
["bsh"] = "Kamkata-viri",
["bsi"] = "Bassossi",
["bsj"] = "Bangwinji",
["bsk"] = "Burushaski",
["bsl"] = "Basa-Gumna",
["bsm"] = "Busami",
["bsn"] = "Barasana",
["bso"] = "Buso",
["bsp"] = "Baga Sitemu",
["bsq"] = "Bassa",
["bsr"] = "Bassa-Kontagora",
["bss"] = "Akoose",
["bst"] = "Basketo",
["bsu"] = "Bahonsuai",
["bsv"] = "Baga Sobané",
["bsw"] = "Baiso",
["bsx"] = "Yangkam",
["bsy"] = "Bisaya Sabah",
["bta"] = "Bata",
["btc"] = "Bati (Kamerun)",
["btd"] = "Pakpak",
["bte"] = "Gamo-Ningi",
["btf"] = "Birgit",
["btg"] = "Bété Gagnoa",
["bth"] = "Bidayuh Biatah",
["bti"] = "Burate",
["btj"] = "Melayu Bacan",
["btk-pro"] = "Proto-Batak",
["btm"] = "Mandailing",
["btn"] = "Ratagnon",
["bto"] = "Bicolano Iriga",
["btp"] = "Budibud",
["btq"] = "Batek",
["btr"] = "Baetora",
["bts"] = "Simalungun",
["btt"] = "Bete-Bendi",
["btu"] = "Batu",
["btv"] = "Bateri",
["btw"] = "Butuanon",
["btx"] = "Karo",
["bty"] = "Bobot",
["btz"] = "Alas-Kluet",
["bua"] = "Buryat",
["bub"] = "Bua",
["bud"] = "Ntcham",
["bue"] = "Beothuk",
["buf"] = "Bushoong",
["bug"] = "Bugis",
["buh"] = "Bunu Younuo",
["bui"] = "Bongili",
["buj"] = "Basa-Gurmana",
["buk"] = "Bukawa",
["bum"] = "Bulu (Kamerun)",
["bun"] = "Sherbro",
["buo"] = "Terei",
["bup"] = "Busoa",
["buq"] = "Brem",
["bus"] = "Bokobaru",
["but"] = "Bungain",
["buu"] = "Budu",
["buv"] = "Bun",
["buw"] = "Bubi",
["bux"] = "Boghom",
["buy"] = "Mmani",
["bva"] = "Barein",
["bvb"] = "Bube",
["bvc"] = "Baelelea",
["bvd"] = "Baeggu",
["bve"] = "Melayu Berau",
["bvf"] = "Boor",
["bvg"] = "Bonkeng",
["bvh"] = "Bure",
["bvi"] = "Belanda Viri",
["bvj"] = "Baan",
["bvk"] = "Bukat",
["bvl"] = "Isyarat Bolivia",
["bvm"] = "Bamunka",
["bvn"] = "Buna",
["bvo"] = "Bolgo",
["bvp"] = "Bumang",
["bvq"] = "Birri",
["bvr"] = "Burarra",
["bvt"] = "Bati",
["bvu"] = "Meratus",
["bvv"] = "Baniva",
["bvw"] = "Boga",
["bvx"] = "Babole",
["bvy"] = "Baybayanon",
["bvz"] = "Bauzi",
["bwa"] = "Bwatoo",
["bwb"] = "Namosi-Naitasiri-Serua",
["bwc"] = "Bwile",
["bwd"] = "Bwaidoka",
["bwe"] = "Karen Bwe",
["bwf"] = "Boselewa",
["bwg"] = "Barwe",
["bwh"] = "Bishuo",
["bwi"] = "Baniwa",
["bwj"] = "Bwamu Láá Láá",
["bwk"] = "Bauwaki",
["bwl"] = "Bwela",
["bwm"] = "Biwat",
["bwn"] = "Bunu Wunai",
["bwo"] = "Shinasha",
["bwp"] = "Mandobo Bawah",
["bwq"] = "Bobo Selatan",
["bwr"] = "Bura",
["bws"] = "Bomboma",
["bwt"] = "Bafaw",
["bwu"] = "Buli (Ghana)",
["bww"] = "Bwa",
["bwx"] = "Bunu Bu-Nao",
["bwy"] = "Bwamu Cwi",
["bwz"] = "Bwisi",
["bxa"] = "Bauro",
["bxb"] = "Belanda Bor",
["bxc"] = "Molengue",
["bxd"] = "Pela",
["bxe"] = "Ongota",
["bxf"] = "Bilur",
["bxg"] = "Bangala",
["bxh"] = "Buhutu",
["bxi"] = "Pirlatapa",
["bxj"] = "Bayungu",
["bxk"] = "Bukusu",
["bxl"] = "Jalkunan",
["bxn"] = "Burduna",
["bxo"] = "Barikanchi",
["bxp"] = "Bebil",
["bxq"] = "Beele",
["bxs"] = "Busam",
["bxv"] = "Berakou",
["bxw"] = "Banka",
["bxz"] = "Binahari",
["bya"] = "Batak Palawan",
["byb"] = "Bikya",
["byc"] = "Ubaghara",
["byd"] = "Benyadu'",
["bye"] = "Pouye",
["byf"] = "Bete",
["byg"] = "Baygo",
["byh"] = "Bujhyal",
["byi"] = "Buyu",
["byj"] = "Binawa",
["byk"] = "Biao",
["byl"] = "Bayono",
["bym"] = "Bidyara",
["byn"] = "Blin",
["byo"] = "Biyo",
["byp"] = "Bumaji",
["byq"] = "Basay",
["byr"] = "Baruya",
["bys"] = "Burak",
["byt"] = "Berti",
["byv"] = "Medumba",
["byw"] = "Belhariya",
["byx"] = "Qaqet",
["byz"] = "Banaro",
["bza"] = "Bandi",
["bzb"] = "Andio",
["bzd"] = "Bribri",
["bze"] = "Bozo Jenaama",
["bzf"] = "Boikin",
["bzg"] = "Babuza",
["bzh"] = "Buang Mapos",
["bzi"] = "Bisu",
["bzj"] = "Kreol Belize",
["bzk"] = "Kreol Nikaragua",
["bzl"] = "Boano (Sulawesi)",
["bzm"] = "Bolondo",
["bzn"] = "Boano (Maluku)",
["bzo"] = "Bozaba",
["bzp"] = "Kemberano",
["bzq"] = "Buli",
["bzr"] = "Biri",
["bzs"] = "Isyarat Brasil",
["bzu"] = "Burmeso",
["bzv"] = "Bebe",
["bzw"] = "Basa",
["bzx"] = "Bozo Hainyaxo",
["bzy"] = "Obanliku",
["bzz"] = "Evant",
["ca"] = "Katala",
["caa"] = "Ch'orti'",
["cab"] = "Garifuna",
["cac"] = "Chuj",
["cad"] = "Caddo",
["cae"] = "Laalaa",
["caf"] = "Carrier Selatan",
["cag"] = "Nivaclé",
["cah"] = "Cahuarano",
["caj"] = "Chané",
["cak"] = "Kaqchikel",
["cal"] = "Carolinia",
["cam"] = "Cemuhî",
["can"] = "Chambri",
["cao"] = "Chácobo",
["cap"] = "Chipaya",
["caq"] = "Nikobar Car",
["car"] = "Carib Galibi",
["cas"] = "Tsimané",
["cau-abz-pro"] = "Proto-Abkhaz-Abaza",
["cau-ava-pro"] = "Proto-Avaro-Andia",
["cau-cir-pro"] = "Proto-Circassia",
["cau-drg-pro"] = "Proto-Dargwa",
["cau-lzg-pro"] = "Proto-Lezghia",
["cau-nec-pro"] = "Proto-Kaukasia Timur Laut",
["cau-nkh-pro"] = "Proto-Nakh",
["cau-nwc-pro"] = "Proto-Kaukasia Barat Laut",
["cau-tsz-pro"] = "Proto-Tsezia",
["cav"] = "Cavineña",
["caw"] = "Callawalla",
["cax"] = "Chiquitano",
["cay"] = "Cayuga",
["caz"] = "Canichana",
["cba-ata"] = "Atanques",
["cba-cat"] = "Chibcha Catío",
["cba-dor"] = "Dorasque",
["cba-dui"] = "Duit",
["cba-hue"] = "Huetar",
["cba-nut"] = "Nutabe",
["cba-pro"] = "Proto-Chibcha",
["cbb"] = "Cabiyarí",
["cbc"] = "Carapana",
["cbd"] = "Carijona",
["cbg"] = "Chimila",
["cbi"] = "Chachi",
["cbj"] = "Ede Cabe",
["cbk"] = "Chavacano",
["cbl"] = "Chin Bualkhaw",
["cbn"] = "Kur Nyah",
["cbo"] = "Izora",
["cbq"] = "Shuba",
["cbr"] = "Cashibo-Cacataibo",
["cbs"] = "Cashinahua",
["cbt"] = "Chayahuita",
["cbu"] = "Candoshi-Shapra",
["cbv"] = "Cacua",
["cbw"] = "Kinabalian",
["cby"] = "Carabayo",
["cca"] = "Cauca",
["ccc"] = "Chamicuro",
["ccd"] = "Cafundó",
["cce"] = "Chopi",
["ccg"] = "Chamba Daka",
["cch"] = "Atsam",
["ccj"] = "Kasanga",
["ccl"] = "Cutchi-Swahili",
["ccm"] = "Kreol Melayu Malaka",
["ccn-pro"] = "Proto-Kaukasia Utara",
["cco"] = "Chinantec Comaltepec",
["ccp"] = "Chakma",
["ccr"] = "Cacaopera",
["ccs-gzn-pro"] = "Proto-Georgia-Zan",
["ccs-pro"] = "Proto-Kartvelia",
["cda"] = "Choni",
["cdc-cbm-pro"] = "Proto-Chad Tengah",
["cdc-mas-pro"] = "Proto-Masa",
["cdc-pro"] = "Proto-Chadic",
["cdd-pro"] = "Proto-Caddo",
["cde"] = "Chenchu",
["cdf"] = "Chiru",
["cdh"] = "Chambeali",
["cdi"] = "Chodri",
["cdj"] = "Churahi",
["cdm"] = "Chepang",
["cdn"] = "Chaudangsi",
["cdo"] = "Min Dong",
["cdr"] = "Cinda-Regi-Tiyal",
["cds"] = "Isyarat Chad",
["cdy"] = "Chadong",
["cdz"] = "Koda",
["ce"] = "Chechen",
["cea"] = "Chehalis Hilir",
["ceb"] = "Cebuano",
["ceg"] = "Chamacoco",
["cel-bry-pro"] = "Proto-Brythonic",
["cel-gal"] = "Gallaecia",
["cel-gau"] = "Gaulish",
["cel-pro"] = "Proto-Keltik",
["cen"] = "Cen",
["cet"] = "Centúúm",
["cfa"] = "Dijim-Bwilim",
["cfd"] = "Cara",
["cfg"] = "Como Karim",
["cfm"] = "Chin Falam",
["cga"] = "Changriwa",
["cgc"] = "Kagayanen",
["cgg"] = "Rukiga",
["cgk"] = "Chocangaca",
["ch"] = "Chamorro",
["chb"] = "Chibcha",
["chc"] = "Catawba",
["chd"] = "Chontal Oaxaca Pegunungan",
["chf"] = "Chontal Tabasco",
["chg"] = "Chagatai",
["chh"] = "Chinook",
["chi-pro"] = "Proto-Chimakuan",
["chj"] = "Chinantec Ojitlán",
["chk"] = "Chuuk",
["chl"] = "Cahuilla",
["chm-pro"] = "Proto-Mari",
["chn"] = "Chinook Jargon",
["cho"] = "Choctaw",
["chp"] = "Chipewyan",
["chq"] = "Chinantec Quiotepec",
["chr"] = "Cherokee",
["cht"] = "Cholón",
["chw"] = "Chuabo",
["chx"] = "Chantyal",
["chy"] = "Cheyenne",
["chz"] = "Chinantec Ozumacín",
["cia"] = "Cia-Cia",
["cib"] = "Gbe Ci",
["cic"] = "Chickasaw",
["cid"] = "Chimariko",
["cie"] = "Cineni",
["cih"] = "Chinali",
["cik"] = "Kinnauri Chitkuli",
["cim"] = "Cimbria",
["cin"] = "Cinta Larga",
["cip"] = "Chiapanec",
["cir"] = "Tiri",
["ciy"] = "Chaima",
["cja"] = "Cham Barat",
["cje"] = "Chru",
["cjh"] = "Chehalis Hulu",
["cji"] = "Chamalal",
["cjk"] = "Chokwe",
["cjm"] = "Cham Timur",
["cjn"] = "Chenapia",
["cjo"] = "Ashéninka Pajonal",
["cjp"] = "Cabécar",
["cjs"] = "Shor",
["cjv"] = "Chuave",
["cjy"] = "Jin",
["ckb"] = "Kurdi Tengah",
["ckh"] = "Chak",
["ckl"] = "Cibak",
["ckn"] = "Chin Kaang",
["cko"] = "Anufo",
["ckq"] = "Kajakse",
["ckr"] = "Kairak",
["cks"] = "Tayo",
["ckt"] = "Chukchi",
["cku"] = "Koasati",
["ckv"] = "Kavalan",
["ckx"] = "Caka",
["cky"] = "Cakfem-Mushere",
["ckz"] = "campuran Cakchiquel-Quiché",
["cla"] = "Ron",
["clc"] = "Chilcotin",
["cld"] = "Neo-Aramaik Khaldea",
["cle"] = "Chinantec Lealao",
["clh"] = "Chilisso",
["cli"] = "Chakali",
["clj"] = "Chin Laitu",
["clk"] = "Idu",
["cll"] = "Chala",
["clm"] = "Klallam",
["clo"] = "Chontal Oaxaca Dataran",
["clt"] = "Chin Lautu",
["clu"] = "Caluyanun",
["clw"] = "Chulym",
["cly"] = "Chatino Pegunungan Timur",
["cma"] = "Maa",
["cmc-pro"] = "Proto-Chamic",
["cme"] = "Cerma",
["cmg"] = "Mongolia Klasik",
["cmi"] = "Emberá-Chamí",
["cml"] = "Campalagian",
["cmm"] = "Michigamea",
["cmn"] = "Tionghoa Mandarin",
["cmo"] = "Mnong Tengah",
["cmr"] = "Chin Mro",
["cms"] = "Messapic",
["cmt"] = "Camtho",
["cna"] = "Changthang",
["cnb"] = "Chin Chinbon",
["cnc"] = "Côông",
["cng"] = "Qiang Utara",
["cnh"] = "Lai",
["cni"] = "Asháninka",
["cnk"] = "Chin Khumi",
["cnl"] = "Chinantec Lalana",
["cno"] = "Con",
["cns"] = "Asmat Tengah",
["cnt"] = "Chinantec Tepetotutla",
["cnu"] = "Chenoua",
["cnw"] = "Chin Ngawn",
["cnx"] = "Kernowek Pertengahan",
["co"] = "Korsika",
["coa"] = "Melayu Kepulauan Cocos",
["cob"] = "Chicomuceltec",
["coc"] = "Cocopa",
["cod"] = "Cocama",
["coe"] = "Koreguaje",
["cof"] = "Tsafiki",
["cog"] = "Chong",
["coh"] = "Chichonyi-Chidzihana-Chikauma",
["coj"] = "Cochimi",
["cok"] = "Santa Teresa Cora",
["col"] = "Columbia-Wenatchi",
["com"] = "Comanche",
["con"] = "Cofán",
["coo"] = "Comox",
["cop"] = "Coptic",
["coq"] = "Coquille",
["cot"] = "Caquinte",
["cou"] = "Wamey",
["cov"] = "Miao Cao",
["cow"] = "Cowlitz",
["cox"] = "Nanti",
["coy"] = "Coyaima",
["coz"] = "Chochotec",
["cpa"] = "Chinantec Palantla",
["cpb"] = "Ucayali-Yurúa Ashéninka",
["cpc"] = "Ajyíninka Apurucayali",
["cpe-mar"] = "Spirit Maroon",
["cpe-spp"] = "Pijin Perkebunan Samoa",
["cpg"] = "Yunani Kapadokia",
["cpi"] = "Pijin Inggris Tiongkok",
["cpn"] = "Cherepon",
["cpo"] = "Kpee",
["cps"] = "Capiznon",
["cpu"] = "Pichis Ashéninka",
["cpx"] = "Puxian",
["cpy"] = "Ucayali Ashéninka Selatan",
["cqd"] = "Miao Kluster Chuanqiandian",
["cr"] = "Cree",
["cra"] = "Chara",
["crb"] = "Carib Island",
["crc"] = "Lonwolwol",
["crd"] = "Coeur d'Alene",
["crf"] = "Caramanta",
["crg"] = "Michif",
["crh"] = "Tatar Krimea",
["cri"] = "Sãotomense",
["crj"] = "Cree Tenggara",
["crk"] = "Cree Plains",
["crl"] = "Cree Timur Laut",
["crm"] = "Cree Moose",
["crn"] = "Cora",
["cro"] = "Crow",
["crp-gep"] = "Pijin Grinlandia Barat",
["crp-mpp"] = "Pijin Portugis Makau",
["crp-rsn"] = "Russenorsk",
["crp-tnw"] = "Tangwang",
["crp-tpr"] = "Pijin Rusia Taimyr",
["crq"] = "Chorote Iyo'wujwa",
["crr"] = "Algonquian Carolina",
["crs"] = "Kreol Seychelle",
["crt"] = "Chorote Iyojwa'ja",
["crv"] = "Chaura",
["crw"] = "Chrau",
["crx"] = "Carrier",
["cry"] = "Cori",
["crz"] = "Cruzeño",
["cs"] = "Ceko",
["csa"] = "Chinantec Chiltepec",
["csb"] = "Kashubia",
["csc"] = "Isyarat Katala",
["csd"] = "Isyarat Chiangmai",
["cse"] = "Isyarat Ceko",
["csf"] = "Isyarat Kuba",
["csg"] = "Isyarat Cile",
["csh"] = "Chin Asho",
["csi"] = "Miwok Coast",
["csj"] = "Chin Songlai",
["csk"] = "Jola-Kasa",
["csl"] = "Isyarat Tionghoa",
["csm"] = "Miwok Sierra Tengah",
["csn"] = "Isyarat Kolombia",
["cso"] = "Chinantec Sochiapam",
["csq"] = "Isyarat Kroasia",
["csr"] = "Isyarat Kosta Rika",
["css"] = "Ohlone Selatan",
["cst"] = "Ohlone Utara",
["csu-bba-pro"] = "Proto-Bongo-Bagirmi",
["csu-maa-pro"] = "Proto-Mangbetu",
["csu-pro"] = "Proto-Sudan Tengah",
["csu-sar-pro"] = "Proto-Sara",
["csv"] = "Chin Sumtu",
["csw"] = "Cree Swampy",
["csy"] = "Chin Siyin",
["csz"] = "Coos",
["cta"] = "Chatino Tataltepec",
["ctc"] = "Chetco-Tolowa",
["ctd"] = "Chin Tedim",
["cte"] = "Chinantec Tepinapa",
["ctg"] = "Chittagong",
["cth"] = "Chin Thaiphum",
["ctl"] = "Chinantec Tlacoatzintepec",
["ctm"] = "Chitimacha",
["ctn"] = "Chhintange",
["cto"] = "Emberá-Catío",
["ctp"] = "Chatino Pegunungan Barat",
["ctp-san"] = "Chatino San Juan Quiahije",
["cts"] = "Bicolano Catanduanes Utara",
["ctt"] = "Wayanad Chetti",
["ctu"] = "Chol",
["ctz"] = "Chatino Zacatepec",
["cu"] = "Slavonia Gerejawi Kuno",
["cua"] = "Cua",
["cub"] = "Cubeo",
["cuc"] = "Chinantec Usila",
["cug"] = "Cung",
["cuh"] = "Chuka",
["cui"] = "Cuiba",
["cuj"] = "Piro Mashco",
["cuk"] = "Kuna",
["cul"] = "Culina",
["cuo"] = "Cumanagoto",
["cup"] = "Cupeño",
["cuq"] = "Cun",
["cur"] = "Chhulung",
["cus-ash"] = "Ashraaf",
["cus-hec-pro"] = "Proto-Cushitic Pegunungan Timur",
["cus-pro"] = "Proto-Cushitic",
["cus-som-pro"] = "Proto-Somaloid",
["cus-sou-pro"] = "Proto-Cushitic Selatan",
["cut"] = "Cuicatec Teutila",
["cuu"] = "Tai Ya",
["cuv"] = "Cuvok",
["cuw"] = "Chukwa",
["cux"] = "Cuicatec Tepeuxila",
["cuy"] = "Cuitlatec",
["cv"] = "Chuvash",
["cvg"] = "Chug",
["cvn"] = "Chinantec Valle Nacional",
["cwa"] = "Kabwa",
["cwb"] = "Maindo",
["cwd"] = "Cree Woods",
["cwe"] = "Kwere",
["cwg"] = "Chewong",
["cwt"] = "Kuwaataay",
["cy"] = "Welsh",
["cya"] = "Chatino Nopala",
["cyb"] = "Cayubaba",
["cyo"] = "Cuyunon",
["czh"] = "Huizhou",
["czk"] = "Knaanic",
["czn"] = "Chatino Zenzontepec",
["czo"] = "Min Zhong",
["czt"] = "Chin Zotung",
["da"] = "Denmark",
["daa"] = "Dangaléat",
["dac"] = "Dambi",
["dad"] = "Marik",
["dae"] = "Duupa",
["dag"] = "Dagbani",
["dah"] = "Gwahatike",
["dai"] = "Day",
["daj"] = "Daju Dar Fur",
["dak"] = "Dakota",
["dal"] = "Dahalo",
["dam"] = "Damakawa",
["dao"] = "Chin Daai",
["daq"] = "Maria Dandami",
["dar"] = "Dargwa",
["das"] = "Daho-Doo",
["dau"] = "Daju Dar Sila",
["dav"] = "Taita",
["daw"] = "Davawenyo",
["dax"] = "Dayi",
["daz"] = "Dao",
["dba"] = "Bangime",
["dbb"] = "Deno",
["dbd"] = "Dadiya",
["dbe"] = "Dabe",
["dbf"] = "Edopi",
["dbg"] = "Dom Dogul",
["dbi"] = "Doka",
["dbj"] = "Ida'an",
["dbl"] = "Dyirbal",
["dbm"] = "Duguri",
["dbn"] = "Duriankere",
["dbo"] = "Dulbu",
["dbp"] = "Duwai",
["dbq"] = "Daba",
["dbr"] = "Dabarre",
["dbt"] = "Ben Tey",
["dbu"] = "Dogon Bondum Dom",
["dbv"] = "Dungu",
["dbw"] = "Dogon Bankan Tey",
["dby"] = "Dibiyaso",
["dcc"] = "Deccani",
["dcr"] = "Negerhollands",
["dda"] = "Dadi Dadi",
["ddd"] = "Dongotono",
["dde"] = "Doondo",
["ddg"] = "Fataluku",
["ddi"] = "Diodio",
["ddj"] = "Jaru",
["ddn"] = "Dendi",
["ddo"] = "Tsez",
["ddr"] = "Dhudhuroa",
["dds"] = "Dogon Donno So",
["ddw"] = "Dawera-Daweloor",
["de"] = "Jerman",
["dec"] = "Dagik",
["ded"] = "Dedua",
["dee"] = "Dewoin",
["def"] = "Dezfuli",
["deg"] = "Degema",
["deh"] = "Dehwari",
["dei"] = "Demisa",
["dek"] = "Dek",
["dem"] = "Dem",
["den"] = "Slavey",
["dep"] = "Pijin Delaware",
["der"] = "Deori",
["des"] = "Desano",
["dev"] = "Domung",
["dez"] = "Dengese",
["dga"] = "Dagaare Selatan",
["dgb"] = "Bunoge",
["dgc"] = "Agta Casiguran Dumagat",
["dgd"] = "Dagaari Dioula",
["dge"] = "Degenan",
["dgg"] = "Doga",
["dgh"] = "Dghwede",
["dgi"] = "Dagara Utara",
["dgk"] = "Dagba",
["dgn"] = "Dagoman",
["dgo"] = "Dogri Hindi",
["dgr"] = "Dogrib",
["dgs"] = "Dogoso",
["dgt"] = "Ntra'ngith",
["dgw"] = "Daungwurrung",
["dgx"] = "Doghoro",
["dgz"] = "Daga",
["dhg"] = "Dhangu",
["dhi"] = "Dhimal",
["dhl"] = "Dhalandji",
["dhm"] = "Zemba",
["dhn"] = "Dhanki",
["dho"] = "Dhodia",
["dhr"] = "Tharrgari",
["dhs"] = "Dhaiso",
["dhu"] = "Dhurga",
["dhv"] = "Drehu",
["dhw"] = "Danuwar",
["dhx"] = "Dhungaloo",
["dia"] = "Dia",
["dib"] = "Dinka Tengah Selatan",
["dic"] = "Lakota Dida",
["did"] = "Didinga",
["dif"] = "Dieri",
["dig"] = "Digo",
["dii"] = "Dimbong",
["dij"] = "Dai",
["dik"] = "Dinka Barat Daya",
["dil"] = "Dilling",
["dim"] = "Dime",
["din"] = "Dinka",
["dio"] = "Dibo",
["dip"] = "Dinka Timur Laut",
["diq"] = "Zaza Selatan",
["dir"] = "Dirim",
["dis"] = "Dimasa",
["diu"] = "Gciriku",
["diw"] = "Dinka Barat Laut",
["dix"] = "Dixon Reef",
["diy"] = "Diuwe",
["diz"] = "Ding",
["dja"] = "Djadjawurrung",
["djb"] = "Djinba",
["djc"] = "Daju Dar Daju",
["djd"] = "Jaminjung",
["dje"] = "Zarma",
["djf"] = "Djangun",
["dji"] = "Djinang",
["djj"] = "Ndjébbana",
["djk"] = "Aukan",
["djl"] = "Djiwarli",
["djm"] = "Jamsay",
["djn"] = "Djauan",
["djo"] = "Jangkang",
["djr"] = "Djambarrpuyngu",
["dju"] = "Kapriman",
["djw"] = "Djawi",
["dka"] = "Dakpa",
["dkk"] = "Dakka",
["dkr"] = "Kuijau",
["dks"] = "Dinka Tenggara",
["dkx"] = "Mazagway",
["dlg"] = "Dolgan",
["dlk"] = "Dahalik",
["dlm"] = "Dalmatia",
["dln"] = "Darlong",
["dma"] = "Duma",
["dmb"] = "Dogon Mombo",
["dmc"] = "Gavak",
["dmd"] = "Madhi Madhi",
["dme"] = "Dugwor",
["dmf"] = "Medefaidrin",
["dmg"] = "Kinabatangan Hulu",
["dmk"] = "Domaaki",
["dml"] = "Dameli",
["dmm"] = "Dama (Nigeria)",
["dmn-dam"] = "Dama (Sierra Leone)",
["dmn-mdw-pro"] = "Proto-Mande Barat",
["dmn-pro"] = "Proto-Mande",
["dmo"] = "Kemezung",
["dmr"] = "Damar Timur",
["dms"] = "Dampelas",
["dmu"] = "Dubu",
["dmv"] = "Dumpas",
["dmw"] = "Mudburra",
["dmx"] = "Dema",
["dmy"] = "Demta",
["dna"] = "Dani Upper Grand Valley",
["dnd"] = "Daonda",
["dne"] = "Ndendeule",
["dng"] = "Dungan",
["dni"] = "Dani Lower Grand Valley",
["dnj"] = "Dan",
["dnk"] = "Dengka",
["dnn"] = "Dzuun",
["dno"] = "Ndrulo",
["dnr"] = "Danaru",
["dnt"] = "Dani Mid Grand Valley",
["dnu"] = "Danau",
["dnv"] = "Danu",
["dnw"] = "Dani Barat",
["dny"] = "Dení",
["doa"] = "Dom",
["dob"] = "Dobu",
["doc"] = "Kam Utara",
["doe"] = "Doe",
["dof"] = "Domu",
["doh"] = "Dong",
["doi"] = "Dogri",
["dok"] = "Dondo",
["dol"] = "Doso",
["don"] = "Doura",
["doo"] = "Dongo",
["dop"] = "Lukpa",
["doq"] = "Isyarat Dominika",
["dor"] = "Dori'o",
["dos"] = "Dogosé",
["dot"] = "Dass",
["dov"] = "Toka-Leya",
["dow"] = "Doyayo",
["dox"] = "Bussa",
["doy"] = "Dompo",
["doz"] = "Dorze",
["dpp"] = "Papar",
["dra-mkn"] = "Kannada Pertengahan",
["dra-okn"] = "Kannada Kuno",
["dra-ote"] = "Telugu Kuno",
["dra-pro"] = "Proto-Dravidia",
["drb"] = "Dair",
["drc"] = "Minderico",
["drd"] = "Darmiya",
["drg"] = "Rungus",
["dri"] = "Lela",
["drl"] = "Baagandji",
["drn"] = "Damar Barat",
["dro"] = "Melanau Daro-Matu",
["drq"] = "Dura",
["drs"] = "Gedeo",
["dru"] = "Rukai",
["dru-pro"] = "Proto-Rukai",
["dry"] = "Darai",
["dsb"] = "Sorbian Hilir",
["dse"] = "Isyarat Belanda",
["dsh"] = "Daasanach",
["dsi"] = "Disa",
["dsl"] = "Isyarat Denmark",
["dsn"] = "Dusner",
["dso"] = "Desiya",
["dsq"] = "Tadaksahak",
["dta"] = "Daur",
["dtb"] = "Kadazan Labuk-Kinabatangan",
["dtd"] = "Ditidaht",
["dth"] = "Adithinngithigh",
["dti"] = "Dogon Ana Tinga",
["dtk"] = "Dogon Tene Kan",
["dtm"] = "Dogon Tomo Kan",
["dto"] = "Tommo So",
["dtp"] = "Dusun Tengah",
["dtr"] = "Lotud",
["dts"] = "Dogon Toro So",
["dtt"] = "Dogon Toro Tegu",
["dtu"] = "Dogon Tebul Ure",
["dty"] = "Doteli",
["dua"] = "Duala",
["dub"] = "Dubli",
["duc"] = "Duna",
["due"] = "Agta Umiray Dumaget",
["duf"] = "Dumbea",
["dug"] = "Chiduruma",
["duh"] = "Dungra Bhil",
["dui"] = "Dumun",
["duk"] = "Uyajitaya",
["dul"] = "Agta Alabat Island",
["dum"] = "Belanda Pertengahan",
["dun"] = "Dusun Deyah",
["duo"] = "Agta Dupaningan",
["dup"] = "Duano",
["duq"] = "Dusun Malang",
["dur"] = "Dii",
["dus"] = "Dumi",
["duu"] = "Drung",
["duv"] = "Duvle",
["duw"] = "Dusun Witu",
["dux"] = "Duun",
["duy"] = "Agta Dicamay",
["duz"] = "Duli",
["dv"] = "Dhivehi",
["dva"] = "Duau",
["dwa"] = "Diri",
["dwr"] = "Dawro",
["dwu"] = "Dhuwal",
["dww"] = "Dawawa",
["dwy"] = "Dhuwaya",
["dwz"] = "Dewas Rai",
["dya"] = "Dyan",
["dyb"] = "Dyaberdyaber",
["dyd"] = "Dyugun",
["dyg"] = "Agta Villa Viciosa",
["dyi"] = "Djimini",
["dym"] = "Dogon Yanda",
["dyn"] = "Dyangadi",
["dyo"] = "Jola-Fonyi",
["dyu"] = "Dyula",
["dyy"] = "Dyaabugay",
["dz"] = "Dzongkha",
["dza"] = "Tunzu",
["dzg"] = "Dazaga",
["dzl"] = "Dzala",
["dzn"] = "Dzando",
["ebg"] = "Ebughu",
["ebk"] = "Bontoc Timur",
["ebr"] = "Ebrié",
["ebu"] = "Embu",
["ecr"] = "Eteocretan",
["ecs"] = "Isyarat Ekuador",
["ecy"] = "Eteocypriot",
["ee"] = "Ewe",
["eee"] = "E",
["efa"] = "Efai",
["efe"] = "Efe",
["efi"] = "Efik",
["ega"] = "Ega",
["egl"] = "Emilia",
["ego"] = "Eggon",
["egx-dem"] = "Demotic",
["egy"] = "Mesir",
["ehu"] = "Ehueun",
["eip"] = "Eipomek",
["eit"] = "Eitiep",
["eiv"] = "Askopan",
["eja"] = "Ejamat",
["eka"] = "Ekajuk",
["eke"] = "Ekit",
["ekg"] = "Ekari",
["eki"] = "Eki",
["ekl"] = "Kolhe",
["ekm"] = "Elip",
["eko"] = "Koti",
["ekp"] = "Ekpeye",
["ekr"] = "Yace",
["eky"] = "Kayah Timur",
["el"] = "Yunani",
["ele"] = "Elepi",
["elh"] = "El Hugeirat",
["eli"] = "Nding",
["elk"] = "Elkei",
["elm"] = "Eleme",
["elo"] = "El Molo",
["elu"] = "Elu",
["elu-prk"] = "Helu",
["elx"] = "Elamite",
["ema"] = "Emai",
["emb"] = "Embaloh",
["eme"] = "Emerillon",
["emg"] = "Meohang Timur",
["emi"] = "Mussau-Emira",
["emk"] = "Maninkakan Timur",
["emm"] = "Mamulique",
["emn"] = "Eman",
["emp"] = "Emberá Utara",
["ems"] = "Alutiiq",
["emu"] = "Muria Timur",
["emw"] = "Emplawas",
["emx"] = "Erromintxela",
["emy"] = "Maya Epigrafik",
["en"] = "Inggris",
["ena"] = "Apali",
["enb"] = "Markweeta",
["enc"] = "En",
["end"] = "Ende",
["enf"] = "Enets Hutan",
["enh"] = "Enets Tundra",
["enl"] = "Enlhet",
["enm"] = "Inggris Pertengahan",
["enn"] = "Engenni",
["eno"] = "Enggano",
["enq"] = "Enga",
["enr"] = "Emem",
["enu"] = "Enu",
["env"] = "Enwan",
["enw"] = "Enwang",
["enx"] = "Enxet",
["eo"] = "Esperanto",
["eot"] = "Eotile",
["epi"] = "Epie",
["era"] = "Eravallan",
["erg"] = "Sie",
["erh"] = "Eruwa",
["eri"] = "Ogea",
["erk"] = "Efate Selatan",
["ero"] = "Horpa",
["err"] = "Erre",
["ers"] = "Ersu",
["ert"] = "Eritai",
["erw"] = "Erokwanas",
["es"] = "Spanyol",
["ese"] = "Ese Ejja",
["esh"] = "Eshtehardi",
["esi"] = "Inupiaq Alaska Utara",
["esk"] = "Inupiaq Alaska Barat Laut",
["esl"] = "Isyarat Mesir",
["esm"] = "Esuma",
["esn"] = "Isyarat El Salvador",
["eso"] = "Isyarat Estonia",
["esq"] = "Esselen",
["ess"] = "Siberia Yupik Tengah",
["esu"] = "Yup'ik",
["esx-esk-pro"] = "Proto-Eskimo",
["esx-ink"] = "Inuktun",
["esx-inq"] = "Inuinnaqtun",
["esx-inu-pro"] = "Proto-Inuit",
["esx-pro"] = "Proto-Eskimo-Aleut",
["esx-tut"] = "Tunumiisut",
["esy"] = "Eskayan",
["et"] = "Estonia",
["etb"] = "Etebi",
["etc"] = "Etchemin",
["eth"] = "Isyarat Etiopia",
["etn"] = "Eton (Vanuatu)",
["eto"] = "Eton (Kamerun)",
["etr"] = "Edolo",
["ets"] = "Yekhee",
["ett"] = "Etruscan",
["etu"] = "Ejagham",
["etx"] = "Eten",
["etz"] = "Semimi",
["eu"] = "Basque",
["euq-pro"] = "Proto-Basque",
["eve"] = "Even",
["evh"] = "Uvbie",
["evn"] = "Evenki",
["ewo"] = "Ewondo",
["ext"] = "Extremadura",
["eya"] = "Eyak",
["eyo"] = "Keiyo",
["eza"] = "Ezaa",
["eze"] = "Uzekwe",
["fa"] = "Persia",
["faa"] = "Fasu",
["fab"] = "Annobonese",
["fad"] = "Wagi",
["faf"] = "Fagani",
["fag"] = "Finongan",
["fah"] = "Fali Baissa",
["fai"] = "Faiwol",
["faj"] = "Faita",
["fak"] = "Fang (Beboid)",
["fal"] = "Fali Selatan",
["fam"] = "Fam",
["fan"] = "Fang (Bantu)",
["fap"] = "Palor",
["far"] = "Fataleka",
["fau"] = "Fayu",
["fax"] = "Fala",
["fay"] = "Fars Barat Daya",
["faz"] = "Fars Barat Laut",
["fbl"] = "Bikol Albay Barat",
["fcs"] = "Isyarat Quebec",
["fer"] = "Feroge",
["ff"] = "Fula",
["ffi"] = "Foia Foia",
["fgr"] = "Fongoro",
["fi"] = "Finlandia",
["fia"] = "Nobiin",
["fie"] = "Fyer",
["fip"] = "Fipa",
["fir"] = "Firan",
["fit"] = "Meänkieli",
["fiw"] = "Fiwaga",
["fj"] = "Fiji",
["fkk"] = "Kirya-Konzel",
["fkv"] = "Kven",
["fla"] = "Salish Montana",
["flh"] = "Foau",
["fli"] = "Fali",
["fll"] = "Fali Utara",
["fln"] = "Flinders Island",
["flr"] = "Fuliiru",
["fly"] = "Tsotsitaal",
["fmp"] = "Fe'fe'",
["fmu"] = "Muria Barat Jauh",
["fng"] = "Fanagalo",
["fni"] = "Fania",
["fo"] = "Faroe",
["fod"] = "Foodo",
["foi"] = "Foi",
["fom"] = "Foma",
["fon"] = "Fon",
["for"] = "Fore",
["fos"] = "Siraya",
["fpe"] = "Pichinglis",
["fqs"] = "Fas",
["fr"] = "Prancis",
["frd"] = "Fordata",
["frm"] = "Prancis Pertengahan",
["fro"] = "Prancis Kuno",
["frp"] = "Franco-Provençal",
["frq"] = "Forak",
["frr"] = "Frisia Utara",
["frt"] = "Fortsenal",
["fse"] = "Isyarat Finlandia",
["fsl"] = "Isyarat Prancis",
["fss"] = "Isyarat Finlandia-Swedia",
["fud"] = "Futuna Timur",
["fuj"] = "Ko",
["fum"] = "Fum",
["fun"] = "Fulniô",
["fur"] = "Friuli",
["fut"] = "Futuna-Aniwa",
["fuu"] = "Furu",
["fuy"] = "Fuyug",
["fvr"] = "Fur",
["fwa"] = "Fwâi",
["fwe"] = "Fwe",
["fy"] = "Frisia Barat",
["ga"] = "Irlandia",
["gaa"] = "Ga",
["gab"] = "Gabri",
["gac"] = "campuran Great Andaman",
["gad"] = "Gaddang",
["gae"] = "Warekena",
["gaf"] = "Gende",
["gag"] = "Gagauz",
["gah"] = "Alekano",
["gai"] = "Borei",
["gaj"] = "Gadsup",
["gak"] = "Gamkonora",
["gal"] = "Galoli",
["gam"] = "Kandawo",
["gan"] = "Gan",
["gao"] = "Gants",
["gap"] = "Gal",
["gaq"] = "Gata'",
["gar"] = "Galeya",
["gas"] = "Adiwasi Garasia",
["gat"] = "Kenati",
["gau"] = "Kondekor",
["gaw"] = "Nobonob",
["gay"] = "Gayo",
["gba"] = "Gbaya",
["gbb"] = "Kaytetye",
["gbd"] = "Karadjeri",
["gbe"] = "Niksek",
["gbf"] = "Gaikundi",
["gbg"] = "Gbanziri",
["gbh"] = "Gbe Defi",
["gbi"] = "Galela",
["gbj"] = "Bodo Gadaba",
["gbk"] = "Gaddi",
["gbl"] = "Gamit",
["gbm"] = "Garhwali",
["gbn"] = "Mo'da",
["gbo"] = "Grebo Utara",
["gbp"] = "Gbaya-Bossangoa",
["gbq"] = "Gbaya-Bozoum",
["gbr"] = "Gbagyi",
["gbs"] = "Gbe Gbesi",
["gbu"] = "Gagadu",
["gbv"] = "Gbanu",
["gbw"] = "Gabi",
["gbx"] = "Gbe Xwla Timur",
["gby"] = "Gbari",
["gcc"] = "Mali",
["gcd"] = "Ganggalida",
["gce"] = "Galice",
["gcf"] = "Kreol Antilla",
["gcl"] = "Kreol Inggris Grenada",
["gcn"] = "Gaina",
["gcr"] = "Kreol Guiana",
["gct"] = "Jerman Colonia Tovar",
["gd"] = "Gaelik Skotlandia",
["gdb"] = "Ollari",
["gdc"] = "Gugu Badhun",
["gdd"] = "Gedaged",
["gde"] = "Gude",
["gdf"] = "Guduf-Gava",
["gdg"] = "Ga'dang",
["gdh"] = "Gadjerawang",
["gdi"] = "Gundi",
["gdj"] = "Kurtjar",
["gdk"] = "Gadang",
["gdl"] = "Dirasha",
["gdm"] = "Laal",
["gdn"] = "Umanakaina",
["gdo"] = "Godoberi",
["gdq"] = "Mehri",
["gdr"] = "Wipi",
["gds"] = "Isyarat Ghandruk",
["gdt"] = "Kungardutyi",
["gdu"] = "Gudu",
["gdx"] = "Godwari",
["gea"] = "Geruma",
["geb"] = "Kire",
["gec"] = "Grebo Gboloo",
["ged"] = "Gade",
["geg"] = "Gengle",
["geh"] = "Hutterisch",
["gei"] = "Gebe",
["gej"] = "Gen",
["gek"] = "Gerka",
["gel"] = "Fakkanci",
["gem-bur"] = "Burgundi",
["gem-pro"] = "Proto-Jermanik",
["geq"] = "Geme",
["ges"] = "Geser-Gorom",
["gev"] = "Viya",
["gew"] = "Gera",
["gex"] = "Garre",
["gey"] = "Enya",
["gez"] = "Ge'ez",
["gfk"] = "Patpatar",
["gft"] = "Gafat",
["gga"] = "Gao",
["ggb"] = "Gbii",
["ggd"] = "Gugadj",
["gge"] = "Guragone",
["ggg"] = "Gurgula",
["ggk"] = "Kungarakany",
["ggl"] = "Ganglau",
["ggn"] = "Gurung Timur",
["ggt"] = "Gitua",
["ggu"] = "Gban",
["ggw"] = "Gogodala",
["gha"] = "Ghadames",
["ghe"] = "Ghale Selatan",
["ghh"] = "Ghale Utara",
["ghk"] = "Karen Geko",
["ghl"] = "Ghulfan",
["ghn"] = "Ghanongga",
["gho"] = "Ghomara",
["ghr"] = "Ghera",
["ghs"] = "Guhu-Samane",
["ght"] = "Ghale Kutang",
["gia"] = "Kitja",
["gib"] = "Gibanawa",
["gid"] = "Gidar",
["gie"] = "Guébie",
["gig"] = "Goaria",
["gih"] = "Githabul",
["gii"] = "Girirra",
["gil"] = "Gilbert",
["gim"] = "Gimi (Goroka)",
["gin"] = "Hinukh",
["gio"] = "Gelao",
["gip"] = "Gimi (Austronesia)",
["giq"] = "Gelao Hijau",
["gir"] = "Gelao Merah",
["gis"] = "Giziga Utara",
["git"] = "Gitxsan",
["giu"] = "Mulao",
["giw"] = "Gelao Putih",
["gix"] = "Gilima",
["giy"] = "Giyug",
["giz"] = "Giziga Selatan",
["gji"] = "Geji",
["gjk"] = "Koli Kachi",
["gjm"] = "Gunditjmara",
["gjn"] = "Gonja",
["gju"] = "Gojri",
["gka"] = "Guya",
["gkd"] = "Magɨ",
["gke"] = "Ndai",
["gkn"] = "Gokana",
["gko"] = "Kok-Nar",
["gkp"] = "Kpelle Guinea",
["gl"] = "Galisia",
["glc"] = "Gula Bon",
["gld"] = "Nanai",
["glh"] = "Pashayi Barat Laut",
["glj"] = "Kulaal",
["glk"] = "Gilaki",
["glo"] = "Galambu",
["glr"] = "Glaro-Twabo",
["glu"] = "Gula",
["glw"] = "Glavda",
["gly"] = "Gule",
["gma"] = "Gambera",
["gmb"] = "Gula'alaa",
["gmd"] = "Mághdì",
["gme-cgo"] = "Gothik Krimea",
["gmg"] = "Magiyi",
["gmh"] = "Jerman Tinggi Pertengahan",
["gml"] = "Jerman Rendah Pertengahan",
["gmm"] = "Gbaya-Mbodomo",
["gmn"] = "Gimnime",
["gmq-gut"] = "Gutnish",
["gmq-jmk"] = "Jamtish",
["gmq-mno"] = "Norwegia Pertengahan",
["gmq-oda"] = "Denmark Kuno",
["gmq-osw"] = "Swedia Kuno",
["gmq-pro"] = "Proto-Norse",
["gmq-scy"] = "Skania",
["gmu"] = "Gumalu",
["gmv"] = "Gamo",
["gmw-bgh"] = "Bergish",
["gmw-cfr"] = "Franconia Tengah",
["gmw-ecg"] = "Jerman Tengah Timur",
["gmw-gts"] = "Gottscheerish",
["gmw-jdt"] = "Belanda Jersey",
["gmw-pro"] = "Proto-Jermanik Barat",
["gmw-rfr"] = "Franconia Rhine",
["gmw-stm"] = "Swabia Sathmar",
["gmw-tsx"] = "Sakson Transylvania",
["gmw-vog"] = "Volga",
["gmw-zps"] = "Jerman Zipser",
["gmx"] = "Magoma",
["gmy"] = "Yunani Mycenaean",
["gmz"] = "Mgbo",
["gn"] = "Guaraní",
["gn-cls"] = "Guaraní Klasik",
["gna"] = "Kaansa",
["gnb"] = "Gangte",
["gnc"] = "Guanche",
["gnd"] = "Zulgo-Gemzek",
["gne"] = "Ganang",
["gng"] = "Ngangam",
["gnh"] = "Lere",
["gni"] = "Gooniyandi",
["gnj"] = "Ngen",
["gnk"] = "ǁGana",
["gnl"] = "Gangulu",
["gnm"] = "Ginuman",
["gnn"] = "Gumatj",
["gnq"] = "Gana",
["gnr"] = "Gureng Gureng",
["gnt"] = "Guntai",
["gnu"] = "Gnau",
["gnw"] = "Guaraní Bolivia Barat",
["gnz"] = "Ganzi",
["goa"] = "Guro",
["gob"] = "Playero",
["goc"] = "Gorakor",
["god"] = "Godié",
["goe"] = "Gongduk",
["gof"] = "Gofa",
["gog"] = "Gogo",
["goh"] = "Jerman Tinggi Kuno",
["goi"] = "Gobasi",
["goj"] = "Gowlan",
["gol"] = "Gola",
["gon"] = "Gondi",
["goo"] = "Gone Dau",
["gop"] = "Yeretuar",
["goq"] = "Gorap",
["gor"] = "Gorontalo",
["got"] = "Gothik",
["gou"] = "Gavar",
["gov"] = "Goo",
["gow"] = "Gorowa",
["gox"] = "Gobu",
["goy"] = "Goundo",
["goz"] = "Gozarkhani",
["gpa"] = "Gupa-Abawa",
["gpn"] = "Taiap",
["gqa"] = "Ga'anda",
["gqi"] = "Guiqiong",
["gqn"] = "Kinikinao",
["gqr"] = "Gor",
["gqu"] = "Qau",
["gra"] = "Rajput Garasia",
["grb"] = "Grebo",
["grc"] = "Yunani Kuno",
["grd"] = "Guruntum",
["grg"] = "Madi",
["grh"] = "Gbiri-Niragu",
["gri"] = "Ghari",
["grj"] = "Grebo Selatan",
["grk-cal"] = "Yunani Calabria",
["grk-ita"] = "Yunani Italiot",
["grk-mar"] = "Yunani Mariupol",
["grk-pro"] = "Proto-Hellenik",
["grm"] = "Kota Marudu Talantang",
["gro"] = "Groma",
["grq"] = "Gorovu",
["grs"] = "Gresi",
["grt"] = "Garo",
["gru"] = "Kistane",
["grv"] = "Grebo Tengah",
["grw"] = "Gweda",
["grx"] = "Guriaso",
["gry"] = "Grebo Barclayville",
["grz"] = "Guramalum",
["gse"] = "Isyarat Ghana",
["gsg"] = "Isyarat Jerman",
["gsl"] = "Gusilay",
["gsm"] = "Isyarat Guatemala",
["gsn"] = "Gusan",
["gso"] = "Gbaya Barat Daya",
["gsp"] = "Wasembo",
["gss"] = "Isyarat Yunani",
["gsw"] = "Jerman Alemannik",
["gta"] = "Guató",
["gtu"] = "Aghu Tharrnggala",
["gu"] = "Gujarat",
["gua"] = "Shiki",
["gub"] = "Guajajára",
["guc"] = "Wayuu",
["gud"] = "Yocoboué Dida",
["gue"] = "Gurindji",
["guf"] = "Gupapuyngu",
["gug"] = "Guaraní Paraguay",
["guh"] = "Guahibo",
["gui"] = "Guaraní Bolivia Timur",
["guk"] = "Gumuz",
["gul"] = "Gullah",
["gum"] = "Guambiano",
["gun"] = "Guaraní Mbyá",
["guo"] = "Guayabero",
["gup"] = "Gunwinggu",
["guq"] = "Aché",
["gur"] = "Farefare",
["gus"] = "Isyarat Guinea",
["gut"] = "Maléku Jaíka",
["guu"] = "Yanomamö",
["guv"] = "Gey",
["guw"] = "Gun",
["gux"] = "Gourmanchéma",
["guz"] = "Gusii",
["gv"] = "Manx",
["gva"] = "Kaskihá",
["gvc"] = "Guanano",
["gve"] = "Duwet",
["gvf"] = "Golin",
["gvj"] = "Guajá",
["gvl"] = "Gulay",
["gvm"] = "Gurmana",
["gvn"] = "Kuku-Yalanji",
["gvo"] = "Gavião do Jiparaná",
["gvp"] = "Gavião Pará",
["gvr"] = "Gurung Barat",
["gvs"] = "Gumawana",
["gvy"] = "Guyani",
["gwa"] = "Mbato",
["gwb"] = "Gwa",
["gwc"] = "Kalami",
["gwd"] = "Gawwada",
["gwe"] = "Gweno",
["gwf"] = "Gowro",
["gwg"] = "Moo",
["gwi"] = "Gwich'in",
["gwj"] = "Gcwi",
["gwm"] = "Awngthim",
["gwn"] = "Gwandara",
["gwr"] = "Gwere",
["gwt"] = "Gawar-Bati",
["gwu"] = "Guwamu",
["gww"] = "Kwini",
["gwx"] = "Gua",
["gxx"] = "Wè Selatan",
["gya"] = "Gbaya Barat Laut",
["gyb"] = "Garus",
["gyd"] = "Kayardild",
["gye"] = "Gyem",
["gyf"] = "Gungabula",
["gyg"] = "Gbayi",
["gyi"] = "Gyele",
["gyl"] = "Gayil",
["gym"] = "Ngäbere",
["gyn"] = "Kreol Inggris Guyana",
["gyo"] = "Gyalsumdo",
["gyr"] = "Guarayu",
["gyy"] = "Gunya",
["gza"] = "Ganza",
["gzn"] = "Gane",
["ha"] = "Hausa",
["haa"] = "Hän",
["hab"] = "Isyarat Hanoi",
["hac"] = "Gurani",
["had"] = "Hatam",
["haf"] = "Isyarat Haiphong",
["hag"] = "Hanga",
["hah"] = "Hahon",
["hai"] = "Haida",
["haj"] = "Hajong",
["hak"] = "Hakka",
["hal"] = "Halang",
["ham"] = "Hewa",
["hao"] = "Hakö",
["hap"] = "Hupla",
["har"] = "Harari",
["has"] = "Haisla",
["hav"] = "Havu",
["haw"] = "Hawaii",
["hax"] = "Haida Selatan",
["hay"] = "Haya",
["haz"] = "Hazaragi",
["hba"] = "Hamba",
["hbb"] = "Huba",
["hbn"] = "Heiban",
["hbu"] = "Habu",
["hca"] = "Kreol Hindi Andaman",
["hch"] = "Huichol",
["hdn"] = "Haida Utara",
["hds"] = "Isyarat Honduras",
["hdy"] = "Hadiyya",
["he"] = "Ibrani",
["hea"] = "Miao Qiandong Utara",
["hed"] = "Herdé",
["heg"] = "Helong",
["heh"] = "Hehe",
["hei"] = "Heiltsuk",
["hem"] = "Hemba",
["hgm"] = "Haiǁom",
["hgw"] = "Haigwai",
["hhi"] = "Hoia Hoia",
["hhr"] = "Kerak",
["hhy"] = "Hoyahoya",
["hi"] = "Hindi",
["hia"] = "Lamang",
["hib"] = "Hibito",
["hid"] = "Hidatsa",
["hif"] = "Hindi Fiji",
["hig"] = "Kamwe",
["hih"] = "Pamosu",
["hii"] = "Hinduri",
["hij"] = "Hijuk",
["hik"] = "Seit-Kaitetu",
["hil"] = "Hiligaynon",
["hio"] = "Tshwa",
["hir"] = "Himarimã",
["hit"] = "Hitit",
["hiw"] = "Hiw",
["hix"] = "Hixkaryana",
["hji"] = "Haji",
["hka"] = "Kahe",
["hke"] = "Hunde",
["hkk"] = "Ke Hunjara-Kaina",
["hkn"] = "Mel-Khaonh",
["hks"] = "Isyarat Hong Kong",
["hla"] = "Halia",
["hlb"] = "Halbi",
["hld"] = "Halang Doan",
["hle"] = "Hlersu",
["hlt"] = "Nga La",
["hma"] = "Hmong Mashan Selatan",
["hmb"] = "Senni Humburi",
["hmc"] = "Hmong Huishui Tengah",
["hmd"] = "A-Hmao",
["hme"] = "Hmong Huishui Timur",
["hmf"] = "Hmong Don",
["hmg"] = "Hmong Guiyang Barat Daya",
["hmh"] = "Hmong Huishui Barat Daya",
["hmi"] = "Hmong Huishui Utara",
["hmj"] = "Ge",
["hmk"] = "Maek",
["hml"] = "Hmong Luopohe",
["hmm"] = "Hmong Mashan Tengah",
["hmn-pro"] = "Proto-Hmong",
["hmp"] = "Hmong Mashan Utara",
["hmq"] = "Miao Qiandong Timur",
["hmr"] = "Hmar",
["hms"] = "Miao Qiandong Selatan",
["hmt"] = "Hamtai",
["hmu"] = "Hamap",
["hmv"] = "Hmong Dô",
["hmw"] = "Hmong Mashan Barat",
["hmx-mie-pro"] = "Proto-Mien",
["hmx-pro"] = "Proto-Hmong-Mien",
["hmy"] = "Hmong Guiyang Selatan",
["hmz"] = "Hmong Shua",
["hna"] = "Mina",
["hnd"] = "Hindko Selatan",
["hne"] = "Chhattisgarhi",
["hnh"] = "ǁAni",
["hni"] = "Hani",
["hnj"] = "Hmong Green",
["hnn"] = "Hanunoo",
["hno"] = "Hindko Utara",
["hns"] = "Hindustani Karibia",
["hnu"] = "Hung",
["ho"] = "Motu Hiri",
["hoa"] = "Hoava",
["hob"] = "Mari Austronesia",
["hoc"] = "Ho",
["hod"] = "Holma",
["hoe"] = "Horom",
["hoh"] = "Hobyót",
["hoi"] = "Holikachuk",
["hoj"] = "Hadothi",
["hol"] = "Holu",
["hom"] = "Homa",
["hoo"] = "Holoholo",
["hop"] = "Hopi",
["hor"] = "Horo",
["hos"] = "Isyarat Kota Ho Chi Minh",
["hot"] = "Hote",
["hov"] = "Hovongan",
["how"] = "Honi",
["hoy"] = "Holiya",
["hoz"] = "Hozo",
["hpo"] = "Hpon",
["hps"] = "Isyarat Pijin Hawai'i",
["hra"] = "Hrangkhol",
["hrc"] = "Niwer Mil",
["hre"] = "Hre",
["hrk"] = "Haruku",
["hrm"] = "Miao Horned",
["hro"] = "Haroi",
["hrp"] = "Nhirrpi",
["hrt"] = "Hértevin",
["hru"] = "Hruso",
["hrw"] = "Warwar Feni",
["hrx"] = "Hunsrik",
["hrz"] = "Harzani",
["hsb"] = "Sorbian Hulu",
["hsh"] = "Isyarat Hungaria",
["hsl"] = "Isyarat Hausa",
["hsn"] = "Xiang",
["hss"] = "Harsusi",
["ht"] = "Kreol Haiti",
["hti"] = "Hoti",
["hto"] = "Huitoto Minica",
["hts"] = "Hadza",
["htu"] = "Hitu",
["hu"] = "Hungaria",
["hub"] = "Huambisa",
["huc"] = "ǂHoan",
["hud"] = "Huaulu",
["huf"] = "Humene",
["hug"] = "Huachipaeri",
["huh"] = "Huilliche",
["hui"] = "Huli",
["huj"] = "Hmong Guiyang Utara",
["huk"] = "Hulung",
["hul"] = "Hula",
["hum"] = "Hungana",
["huo"] = "Hu",
["hup"] = "Hupa",
["huq"] = "Tsat",
["hur"] = "Halkomelem",
["hus"] = "Wastek",
["huu"] = "Huitoto Murui",
["huv"] = "Huave",
["huw"] = "Hukumina",
["hux"] = "Huitoto Nüpode",
["huy"] = "Hulaulá",
["huz"] = "Hunzib",
["hvc"] = "budaya Vodoun Haiti",
["hvk"] = "Haveke",
["hvn"] = "Hawu",
["hwa"] = "Wané",
["hwc"] = "Kreol Hawaii",
["hwo"] = "Hwana",
["hy"] = "Armenia",
["hya"] = "Hya",
["hyx-pro"] = "Proto-Armenia",
["hz"] = "Herero",
["ia"] = "Interlingua",
["iai"] = "Iaai",
["ian"] = "Iatmul",
["iar"] = "Purari",
["iba"] = "Iban",
["ibb"] = "Ibibio",
["ibd"] = "Iwaidja",
["ibe"] = "Akpes",
["ibg"] = "Ibanag",
["ibh"] = "Bih",
["ibl"] = "Ibaloi",
["ibm"] = "Agoi",
["ibn"] = "Ibino",
["ibr"] = "Ibuoro",
["ibu"] = "Ibu",
["iby"] = "Ibani",
["ica"] = "Ede Ica",
["ich"] = "Etkywan",
["icl"] = "Isyarat Islandia",
["icr"] = "Kreol Inggris Islander",
["id"] = "Indonesia",
["ida"] = "Idakho-Isukha-Tiriki",
["idb"] = "Indo-Portugis",
["idc"] = "Idon",
["idd"] = "Ede Idaca",
["ide"] = "Idere",
["idi"] = "Idi",
["idr"] = "Indri",
["ids"] = "Idesa",
["idt"] = "Idaté",
["idu"] = "Idoma",
["ie"] = "Interlingue",
["ifa"] = "Ifugao Amganad",
["ifb"] = "Ifugao Batad",
["ife"] = "Ifè",
["iff"] = "Ifo",
["ifk"] = "Ifugao Tuwali",
["ifm"] = "Teke-Fuumu",
["ifu"] = "Ifugao Mayoyao",
["ify"] = "Kallahan Keley-I",
["ig"] = "Igbo",
["igb"] = "Ebira",
["ige"] = "Igede",
["igg"] = "Igana",
["igl"] = "Igala",
["igm"] = "Kanggape",
["ign"] = "Ignaciano",
["igo"] = "Isebe",
["igs"] = "Glosa",
["igw"] = "Igwe",
["ihb"] = "Pijin Iha",
["ihi"] = "Ihievbe",
["ihp"] = "Iha",
["ii"] = "Yi Sichuan",
["iir-nur-pro"] = "Proto-Nuristani",
["iir-pro"] = "Proto-Indo-Iran",
["ijc"] = "Izon",
["ije"] = "Biseni",
["ijj"] = "Ede Ije",
["ijn"] = "Kalabari",
["ijo-pro"] = "Proto-Ijoid",
["ijs"] = "Ijo Tenggara",
["ik"] = "Inupiaq",
["ike"] = "Inuktitut Kanada Timur",
["iki"] = "Iko",
["ikk"] = "Ika",
["ikl"] = "Ikulu",
["iko"] = "Olulumo-Ikom",
["ikp"] = "Ikpeshi",
["ikr"] = "Ikaranggal",
["iks"] = "Isyarat Inuit",
["ikt"] = "Inuvialuktun",
["ikv"] = "Iku-Gora-Ankwa",
["ikw"] = "Ikwere",
["ikx"] = "Ik",
["ikz"] = "Ikizu",
["ila"] = "Ile Ape",
["ilb"] = "Ila",
["ilg"] = "Ilgar",
["ili"] = "Turki Ili",
["ilk"] = "Ilongot",
["ill"] = "Iranun",
["ilo"] = "Ilokano",
["ils"] = "Isyarat Internasional",
["ilu"] = "Ili'uun",
["ilv"] = "Ilue",
["ima"] = "Mala Malasar",
["imi"] = "Anamgura",
["iml"] = "Miluk",
["imn"] = "Imonda",
["imo"] = "Imbongu",
["imr"] = "Imroing",
["ims"] = "Marsian",
["imy"] = "Milyan",
["inb"] = "Inga",
["inc-ash"] = "Prakrit Ashokan",
["inc-cen-pro"] = "Proto-Indo-Aryan Tengah",
["inc-gup"] = "Apabhramsa Gurjar",
["inc-kam"] = "Prakrit Kamarupi",
["inc-kha"] = "Prakrit Khasa",
["inc-kho"] = "Kholosi",
["inc-mas"] = "Assam Pertengahan",
["inc-mbn"] = "Bengal Pertengahan",
["inc-mgd"] = "Prakrit Magadhi",
["inc-mgu"] = "Gujarat Pertengahan",
["inc-mor"] = "Oriya Pertengahan",
["inc-oas"] = "Assam Awal",
["inc-obn"] = "Bengal Kuno",
["inc-ogu"] = "Gujarat Kuno",
["inc-ohi"] = "Hindi Kuno",
["inc-oor"] = "Oriya Kuno",
["inc-opa"] = "Punjab Kuno",
["inc-ork"] = "Kamta Kuno",
["inc-pra"] = "Prakrit",
["inc-pro"] = "Proto-Indo-Aryan",
["inc-psc"] = "Prakrit Paisaci",
["inc-sap"] = "Apabhramsa Sauraseni",
["inc-tak"] = "Apabhramsa Takka",
["inc-vra"] = "Apabhramsa Vracada",
["ine-ana-pro"] = "Proto-Anatolia",
["ine-bsl-pro"] = "Proto-Balto-Slavik",
["ine-pae"] = "Paeonia",
["ine-pro"] = "Proto-Indo-Eropa",
["ine-toc-pro"] = "Proto-Tocharia",
["ing"] = "Deg Xinag",
["inh"] = "Ingush",
["inj"] = "Inga Hutan",
["inl"] = "Isyarat Indonesia",
["inm"] = "Minaean",
["inn"] = "Isinai",
["ino"] = "Inoke-Yate",
["inp"] = "Iñapari",
["ins"] = "Isyarat India",
["int"] = "Intha",
["inz"] = "Ineseño",
["io"] = "Ido",
["ior"] = "Inor",
["iou"] = "Tuma-Irumu",
["iow"] = "Chiwere",
["ipi"] = "Ipili",
["ipo"] = "Ipiko",
["iqu"] = "Iquito",
["iqw"] = "Ikwo",
["ira-kms-pro"] = "Proto-Komisenia",
["ira-mny-pro"] = "Proto-Munji-Yidgha",
["ira-mpr-pro"] = "Proto-Medo-Parthia",
["ira-pat-pro"] = "Proto-Pathan",
["ira-pro"] = "Proto-Iran",
["ira-sgc-pro"] = "Proto-Sogdic",
["ira-sgi-pro"] = "Proto-Sanglechi-Ishkashimi",
["ira-shr-pro"] = "Proto-Shughni-Roshani",
["ira-shy-pro"] = "Proto-Shughni-Yazghulami",
["ira-sym-pro"] = "Proto-Shughni-Yazghulami-Munji",
["ira-wnj"] = "Vanji",
["ira-zgr-pro"] = "Proto-Zaza-Gorani",
["ire"] = "Iresim",
["irh"] = "Irarutu",
["iri"] = "Rigwe",
["irk"] = "Iraqw",
["irn"] = "Irantxe",
["iro-ere"] = "Erie",
["iro-min"] = "Mingo",
["iro-nor-pro"] = "Proto-Iroquois Utara",
["iro-pro"] = "Proto-Iroquois",
["irr"] = "Ir",
["iru"] = "Irula",
["irx"] = "Kamberau",
["iry"] = "Iraya",
["is"] = "Islandia",
["isa"] = "Isabi",
["isc"] = "Isconahua",
["isd"] = "Isnag",
["ise"] = "Isyarat Italia",
["isg"] = "Isyarat Irlandia",
["ish"] = "Esan",
["isi"] = "Nkem-Nkum",
["isk"] = "Ishkashimi",
["ism"] = "Masimasi",
["isn"] = "Isanzu",
["iso"] = "Isoko",
["isr"] = "Isyarat Israel",
["ist"] = "Istriot",
["isu"] = "Isu",
["it"] = "Italia",
["itb"] = "Itneg Binongan",
["itc-pro"] = "Proto-Italik",
["itd"] = "Tidung Nunukan",
["ite"] = "Itene",
["iti"] = "Itneg Inlaod",
["itk"] = "Judeo-Italia",
["itl"] = "Itelmen",
["itm"] = "Itu Mbon Uzo",
["ito"] = "Itonama",
["itr"] = "Iteri",
["its"] = "Itsekiri",
["itt"] = "Itneg Maeng",
["itv"] = "Itawit",
["itw"] = "Ito",
["itx"] = "Itik",
["ity"] = "Itneg Moyadan",
["itz"] = "Itzá",
["iu"] = "Inuktitut",
["ium"] = "Mien Iu",
["ivb"] = "Ibatan",
["ivv"] = "Ivatan",
["iwk"] = "I-Wak",
["iwm"] = "Iwam",
["iwo"] = "Iwur",
["iws"] = "Iwam Sepik",
["ixc"] = "Ixcatec",
["ixl"] = "Ixil",
["iya"] = "Iyayu",
["iyo"] = "Mesaka",
["iyx"] = "Yaa",
["izh"] = "Ingria",
["izi"] = "Izi-Ezaa-Ikwo-Mgbo",
["izr"] = "Izere",
["izz"] = "Izi",
["ja"] = "Jepang",
["jaa"] = "Jamamadí",
["jab"] = "Hyam",
["jac"] = "Jakaltek",
["jad"] = "Jahanka",
["jae"] = "Jabem",
["jaf"] = "Jara",
["jah"] = "Jah Hut",
["jaj"] = "Zazao",
["jal"] = "Yalahatan",
["jam"] = "Kreol Jamaika",
["jan"] = "Janday",
["jao"] = "Yanyuwa",
["jaq"] = "Yaqay",
["jas"] = "Jawa Kaledonia Baru",
["jat"] = "Jakati",
["jau"] = "Yaur",
["jax"] = "Melayu Jambi",
["jay"] = "Yan-nhangu",
["jaz"] = "Jawe",
["jbj"] = "Arandai",
["jbk"] = "Barikewa",
["jbn"] = "Nefusa",
["jbo"] = "Lojban",
["jbr"] = "Jofotek-Bromnya",
["jbt"] = "Jabutí",
["jbu"] = "Jukun Takum",
["jbw"] = "Yawijibaya",
["jcs"] = "Isyarat Jamaika (negara)",
["jct"] = "Krymchak",
["jda"] = "Jad",
["jdg"] = "Jadgali",
["jdt"] = "Judeo-Tat",
["jeb"] = "Jebero",
["jee"] = "Jerung",
["jeg"] = "Jeng",
["jeh"] = "Jeh",
["jei"] = "Yei",
["jek"] = "Kuo Jeri",
["jel"] = "Yelmek",
["jen"] = "Dza",
["jer"] = "Jere",
["jet"] = "Manem",
["jeu"] = "Jonkor Bourmataguil",
["jgb"] = "Ngbee",
["jgk"] = "Gwak",
["jgo"] = "Ngomba",
["jhi"] = "Jehai",
["jhs"] = "Isyarat Jhankot",
["jia"] = "Jina",
["jib"] = "Jibu",
["jic"] = "Tol",
["jid"] = "Bu",
["jie"] = "Jilbe",
["jig"] = "Jingulu",
["jih"] = "Shangzhai",
["jii"] = "Jiiddu",
["jil"] = "Jilim",
["jim"] = "Jimjimen",
["jio"] = "Jiamao",
["jiq"] = "Khroskyabs",
["jit"] = "Jita",
["jiu"] = "Jinuo Youle",
["jiv"] = "Shuar",
["jiy"] = "Jinuo Buyuan",
["jje"] = "Jeju",
["jjr"] = "Zhár",
["jka"] = "Kaera",
["jko"] = "Kubo",
["jkr"] = "Koro (India)",
["jku"] = "Labir",
["jle"] = "Ngile",
["jls"] = "Isyarat Jamaika",
["jma"] = "Dima",
["jmb"] = "Zumbun",
["jmc"] = "Machame",
["jmd"] = "Yamdena",
["jmi"] = "Jimi",
["jml"] = "Jumli",
["jmn"] = "Naga Makuri",
["jmr"] = "Kamara",
["jmw"] = "Mouwase",
["jmx"] = "Mixtec Juxtlahuaca Barat",
["jna"] = "Jangshung",
["jnd"] = "Jandavra",
["jng"] = "Yangman",
["jni"] = "Janji",
["jnj"] = "Yemsa",
["jnl"] = "Rawat",
["jns"] = "Jaunsari",
["job"] = "Joba",
["jod"] = "Wojenaka",
["jor"] = "Jorá",
["jos"] = "Isyarat Yordania",
["jow"] = "Jowulu",
["jpr"] = "Judeo-Persia",
["jpx-pro"] = "Proto-Jepang",
["jpx-ryu-pro"] = "Proto-Ryukyu",
["jqr"] = "Jaqaru",
["jra"] = "Jarai",
["jrr"] = "Jiru",
["jru"] = "Japrería",
["jsl"] = "Isyarat Jepang",
["jua"] = "Júma",
["jub"] = "Wannu",
["juc"] = "Jurchen",
["jud"] = "Worodougou",
["juh"] = "Hone",
["jui"] = "Ngadjuri",
["juk"] = "Wapan",
["jul"] = "Jirel",
["jum"] = "Jumjum",
["jun"] = "Juang",
["juo"] = "Jiba",
["jup"] = "Hupdë",
["jur"] = "Jurúna",
["jus"] = "Isyarat Jumla",
["jut"] = "Jutish",
["juu"] = "Ju",
["juw"] = "Wãpha",
["juy"] = "Juray",
["jv"] = "Jawa",
["jvd"] = "Javindo",
["jvn"] = "Jawa Karibia",
["jwi"] = "Jwira-Pepesa",
["jyy"] = "Jaya",
["ka"] = "Georgia",
["kaa"] = "Karakalpak",
["kab"] = "Kabyle",
["kac"] = "Jingpho",
["kad"] = "Kadara",
["kae"] = "Ketangalan",
["kaf"] = "Katso",
["kag"] = "Kajaman",
["kah"] = "Fer",
["kai"] = "Karekare",
["kaj"] = "Jju",
["kak"] = "Kallahan Kayapa",
["kam"] = "Kamba",
["kao"] = "Kassonke",
["kap"] = "Bezhta",
["kaq"] = "Capanahua",
["kar-pro"] = "Proto-Karen",
["kaw"] = "Jawa Kuno",
["kax"] = "Kao",
["kay"] = "Kamayurá",
["kba"] = "Kalarko",
["kbb"] = "Kaxuyana",
["kbc"] = "Kadiwéu",
["kbd"] = "Kabardia",
["kbe"] = "Kanju",
["kbh"] = "Camsá",
["kbi"] = "Kaptiau",
["kbj"] = "Kari",
["kbk"] = "Koiari Rumput",
["kbm"] = "Iwal",
["kbn"] = "Kare (Africa)",
["kbo"] = "Keliko",
["kbp"] = "Kabiyé",
["kbq"] = "Kamano",
["kbr"] = "Kafa",
["kbs"] = "Kande",
["kbt"] = "Gabadi",
["kbu"] = "Kabutra",
["kbv"] = "Kamberataro",
["kbw"] = "Kaiep",
["kbx"] = "Ap Ma",
["kbz"] = "Duhwa",
["kca"] = "Khanty",
["kcb"] = "Kawacha",
["kcc"] = "Lubila",
["kcd"] = "Kanum Ngkâlmpw",
["kce"] = "Kaivi",
["kcf"] = "Ukaan",
["kcg"] = "Tyap",
["kch"] = "Vono",
["kci"] = "Kamantan",
["kcj"] = "Kobiana",
["kck"] = "Kalanga",
["kcl"] = "Kala",
["kcm"] = "Gula Tar",
["kcn"] = "Nubi",
["kco"] = "Kinalakna",
["kcp"] = "Kanga",
["kcq"] = "Kamo",
["kcr"] = "Katla",
["kcs"] = "Koenoem",
["kct"] = "Kaian",
["kcu"] = "Kikami",
["kcv"] = "Kete",
["kcw"] = "Kabwari",
["kcx"] = "Kachama-Ganjule",
["kcy"] = "Korandje",
["kcz"] = "Konongo",
["kda"] = "Worimi",
["kdc"] = "Kutu",
["kdd"] = "Yankunytjatjara",
["kde"] = "Makonde",
["kdf"] = "Mamusi",
["kdg"] = "Seba",
["kdh"] = "Tem",
["kdi"] = "Kumam",
["kdj"] = "Karamojong",
["kdk"] = "Numee",
["kdl"] = "Tsikimba",
["kdm"] = "Kagoma",
["kdn"] = "Kunda",
["kdp"] = "Kaningdon-Nindem",
["kdq"] = "Koch",
["kdr"] = "Karaim",
["kdt"] = "Kuy",
["kdu"] = "Kadaru",
["kdv"] = "Kado",
["kdw"] = "Koneraw",
["kdx"] = "Kam",
["kdy"] = "Keder",
["kdz"] = "Kwaja",
["kea"] = "Kabuverdianu",
["keb"] = "Kélé",
["kec"] = "Keiga",
["ked"] = "Kerewe",
["kee"] = "Keres Timur",
["kef"] = "Kpessi",
["keg"] = "Tese",
["keh"] = "Keak",
["kei"] = "Kei",
["kej"] = "Kadar",
["kek"] = "Q'eqchi",
["kel"] = "Kela-Yela",
["kem"] = "Kemak",
["ken"] = "Kenyang",
["keo"] = "Kakwa",
["kep"] = "Kaikadi",
["keq"] = "Kamar",
["ker"] = "Kera",
["kes"] = "Kugbo",
["ket"] = "Ket",
["keu"] = "Akebu",
["kev"] = "Kanikkaran",
["kew"] = "Kewa",
["kex"] = "Kukna",
["key"] = "Kupia",
["kez"] = "Kukele",
["kfa"] = "Kodava",
["kfb"] = "Kolami",
["kfc"] = "Konda-Dora",
["kfd"] = "Koraga Korra",
["kfe"] = "Kota (India)",
["kff"] = "Koya",
["kfg"] = "Kudiya",
["kfh"] = "Kurichiya",
["kfi"] = "Kurumba Kannada",
["kfj"] = "Kemiehua",
["kfk"] = "Kinnauri",
["kfl"] = "Kung",
["kfn"] = "Kuk",
["kfo"] = "Koro (Afrika Barat)",
["kfp"] = "Korwa",
["kfq"] = "Korku",
["kfr"] = "Kachchi",
["kfs"] = "Bilaspuri",
["kft"] = "Kanjari",
["kfu"] = "Katkari",
["kfv"] = "Kurmukar",
["kfw"] = "Naga Kharam",
["kfx"] = "Pahari Kullu",
["kfy"] = "Kumaoni",
["kfz"] = "Koromfé",
["kg"] = "Kongo",
["kga"] = "Koyaga",
["kgb"] = "Kawe",
["kgd"] = "Kataang",
["kge"] = "Komering",
["kgf"] = "Kube",
["kgg"] = "Kusunda",
["kgi"] = "Isyarat Selangor",
["kgj"] = "Kham Gamale",
["kgk"] = "Kaiwá",
["kgl"] = "Kunggari",
["kgm"] = "Karipúna",
["kgn"] = "Karingani",
["kgo"] = "Krongo",
["kgp"] = "Kaingang",
["kgq"] = "Kamoro",
["kgr"] = "Abun",
["kgs"] = "Kumbainggar",
["kgt"] = "Somyev",
["kgu"] = "Kobol",
["kgv"] = "Karas",
["kgw"] = "Karon Dori",
["kgx"] = "Kamaru",
["kgy"] = "Kyerung",
["kha"] = "Khasi",
["khb"] = "Lü",
["khc"] = "Tukang Besi Utara",
["khd"] = "Kanum Bädi",
["khe"] = "Korowai",
["khf"] = "Khuen",
["khh"] = "Kehu",
["khi-kho-pro"] = "Proto-Khoe",
["khi-kun"] = "ǃKung",
["khj"] = "Kuturmi",
["khl"] = "Lusi",
["khn"] = "Khandeshi",
["kho"] = "Khotan",
["khp"] = "Kapauri",
["khq"] = "Koyra Chiini",
["khr"] = "Kharia",
["khs"] = "Kasua",
["kht"] = "Khamti",
["khu"] = "Nkhumbi",
["khv"] = "Khvarshi",
["khw"] = "Khowar",
["khx"] = "Kanu",
["khy"] = "Ekele",
["khz"] = "Keapara",
["ki"] = "Kikuyu",
["kia"] = "Kim",
["kib"] = "Koalib",
["kic"] = "Kickapoo",
["kid"] = "Koshin",
["kie"] = "Kibet",
["kif"] = "Kham Parbate Timur",
["kig"] = "Kimaama",
["kih"] = "Kilmeri",
["kii"] = "Kitsai",
["kij"] = "Kilivila",
["kil"] = "Kariya",
["kim"] = "Tofa",
["kio"] = "Kiowa",
["kip"] = "Kham Sheshi",
["kiq"] = "Kosadle",
["kis"] = "Kis",
["kit"] = "Agob",
["kiv"] = "Kimbu",
["kiw"] = "Kiwai Timur Laut",
["kix"] = "Naga Khiamniungan",
["kiy"] = "Kirikiri",
["kiz"] = "Kisi",
["kj"] = "Kwanyama",
["kja"] = "Mlap",
["kjb"] = "Q'anjob'al",
["kjc"] = "Konjo Pesisir",
["kjd"] = "Kiwai Selatan",
["kje"] = "Kisar",
["kjg"] = "Khmu",
["kjh"] = "Khakas",
["kji"] = "Zabana",
["kjj"] = "Khinalug",
["kjk"] = "Konjo Pegunungan",
["kjl"] = "Kham",
["kjm"] = "Kháng",
["kjn"] = "Kunjen",
["kjo"] = "Kinnauri Harijan",
["kjp"] = "Pwo Timur",
["kjq"] = "Keres Barat",
["kjr"] = "Kurudu",
["kjs"] = "Kewa Timur",
["kjt"] = "Pwo Phrae",
["kju"] = "Kashaya",
["kjx"] = "Ramopa",
["kjy"] = "Erave",
["kjz"] = "Bumthangkha",
["kk"] = "Kazakh",
["kka"] = "Kakanda",
["kkb"] = "Kwerisa",
["kkc"] = "Odoodee",
["kkd"] = "Kinuku",
["kke"] = "Kakabe",
["kkf"] = "Monpa Kalaktang",
["kkg"] = "Kalinga Mabaka Valley",
["kkh"] = "Khün",
["kki"] = "Kagulu",
["kkj"] = "Kako",
["kkk"] = "Kokota",
["kkl"] = "Yale Kosarek",
["kkm"] = "Kiong",
["kkn"] = "Kon Keu",
["kko"] = "Karko",
["kkp"] = "Koko-Bera",
["kkq"] = "Kaiku",
["kkr"] = "Kir-Balar",
["kks"] = "Kirfi",
["kkt"] = "Koi",
["kku"] = "Tumi",
["kkv"] = "Kangean",
["kkw"] = "Teke-Kukuya",
["kkx"] = "Kohin",
["kky"] = "Guugu Yimidhirr",
["kkz"] = "Kaska",
["kl"] = "Grinlandia",
["kla"] = "Klamath-Modoc",
["klb"] = "Kiliwa",
["klc"] = "Kolbila",
["kld"] = "Gamilaraay",
["kle"] = "Kulung",
["klf"] = "Kendeje",
["klg"] = "Kalagan Tagakaulu",
["klh"] = "Weliki",
["kli"] = "Kalumpang",
["klj"] = "Khalaj",
["klk"] = "Kono (Nigeria)",
["kll"] = "Kalagan Kagan",
["klm"] = "Kolom",
["kln"] = "Kalenjin",
["klo"] = "Kapya",
["klp"] = "Kamasa",
["klq"] = "Rumu",
["klr"] = "Khaling",
["kls"] = "Kalasha",
["klt"] = "Nukna",
["klu"] = "Klao",
["klv"] = "Maskelynes",
["klw"] = "Lindu",
["klx"] = "Koluwawa",
["kly"] = "Kalao",
["klz"] = "Kabola",
["km"] = "Khmer",
["kma"] = "Konni",
["kmb"] = "Kimbundu",
["kmc"] = "Kam Selatan",
["kmd"] = "Kalinga Madukayang",
["kme"] = "Bakole",
["kmf"] = "Kare (Papua)",
["kmg"] = "Kâte",
["kmh"] = "Kalam",
["kmi"] = "Kami",
["kmj"] = "Paharia Kumarbhag",
["kmk"] = "Kalinga Limos",
["kml"] = "Kalinga Tanudan",
["kmm"] = "Kom (India)",
["kmn"] = "Awtuw",
["kmo"] = "Kwoma",
["kmp"] = "Gimme",
["kmq"] = "Kwama",
["kmr"] = "Kurdi Utara",
["kms"] = "Kamasau",
["kmt"] = "Kemtuik",
["kmu"] = "Kanite",
["kmv"] = "Kreol Prancis Karipúna",
["kmw"] = "Kumu",
["kmx"] = "Waboda",
["kmy"] = "Koma",
["kmz"] = "Turki Khorasani",
["kn"] = "Kannada",
["kna"] = "Kanakuru",
["knb"] = "Kalinga Lubuagan",
["knd"] = "Konda",
["kne"] = "Kankanaey",
["knf"] = "Mankanya",
["kni"] = "Kanufi",
["knj"] = "Akatek",
["knk"] = "Kuranko",
["knl"] = "Keninjal",
["knm"] = "Kanamari",
["kno"] = "Kono (Sierra Leone)",
["knp"] = "Kwanja",
["knq"] = "Kintaq",
["knr"] = "Kaningra",
["kns"] = "Kensiu",
["knt"] = "Katukina",
["knu"] = "Kono (Guinea)",
["knv"] = "Tabo",
["knx"] = "Kanayatn",
["kny"] = "Kanyok",
["knz"] = "Kalamsé",
["ko"] = "Korea",
["ko-ear"] = "Korea Modern Awal",
["koa"] = "Konomala",
["koc"] = "Kpati",
["kod"] = "Kodi",
["koe"] = "Kacipo-Balesi",
["kof"] = "Kubi",
["kog"] = "Cogui",
["koh"] = "Koyo",
["koi"] = "Komi-Permyak",
["kok"] = "Konkani",
["kol"] = "Kol (Papua)",
["koo"] = "Konzo",
["kop"] = "Waube",
["koq"] = "Kota (Gabon)",
["kos"] = "Kosraean",
["kot"] = "Lagwan",
["kou"] = "Koke",
["kov"] = "Kudu-Camo",
["kow"] = "Kugama",
["koy"] = "Koyukon",
["koz"] = "Korak",
["kpa"] = "Kutto",
["kpb"] = "Kurumba Mullu",
["kpc"] = "Curripaco",
["kpd"] = "Koba",
["kpe"] = "Kpelle",
["kpf"] = "Komba",
["kpg"] = "Kapingamarangi",
["kph"] = "Kplang",
["kpi"] = "Kofei",
["kpj"] = "Karajá",
["kpk"] = "Kpan",
["kpl"] = "Kpala",
["kpm"] = "Koho",
["kpn"] = "Kepkiriwát",
["kpo"] = "Ikposo",
["kpp"] = "Karen Paku",
["kpq"] = "Korupun-Sela",
["kpr"] = "Korafe-Yegha",
["kps"] = "Tehit",
["kpt"] = "Karata",
["kpu"] = "Kafoa",
["kpv"] = "Komi-Zyrian",
["kpw"] = "Kobon",
["kpx"] = "Koiari Gunung",
["kpy"] = "Koryak",
["kpz"] = "Kupsabiny",
["kqa"] = "Mum",
["kqb"] = "Kovai",
["kqc"] = "Doromu-Koki",
["kqd"] = "Koy Sanjaq Surat",
["kqe"] = "Kalagan",
["kqf"] = "Kakabai",
["kqg"] = "Khe",
["kqh"] = "Kisankasa",
["kqi"] = "Koitabu",
["kqj"] = "Koromira",
["kqk"] = "Gbe Kotafon",
["kql"] = "Kyenele",
["kqm"] = "Khisa",
["kqn"] = "Kaonde",
["kqo"] = "Krahn Timur",
["kqp"] = "Kimré",
["kqq"] = "Krenak",
["kqr"] = "Kimaragang",
["kqs"] = "Kissi Utara",
["kqt"] = "Kadazan Sungai Klias",
["kqu"] = "Seroa",
["kqv"] = "Okolod",
["kqw"] = "Kandas",
["kqx"] = "Mser",
["kqy"] = "Koorete",
["kqz"] = "Korana",
["kr"] = "Kanuri",
["kra"] = "Kumhali",
["krb"] = "Karkin",
["krc"] = "Karachay-Balkar",
["krd"] = "Kairui-Midiki",
["kre"] = "Panará",
["krf"] = "Koro (Vanuatu)",
["krh"] = "Kurama",
["kri"] = "Krio",
["krj"] = "Kinaray-a",
["krk"] = "Kerek",
["krl"] = "Karelia",
["krm"] = "Krim",
["krn"] = "Sapo",
["kro-pro"] = "Proto-Kru",
["krp"] = "Korop",
["krr"] = "Kru'ng",
["krs"] = "Kresh",
["kru"] = "Kurukh",
["krv"] = "Kavet",
["krw"] = "Krahn Barat",
["krx"] = "Karon",
["kry"] = "Kryts",
["krz"] = "Kanum Sota",
["ks"] = "Kashmir",
["ksa"] = "Shuwa-Zamani",
["ksb"] = "Shambala",
["ksc"] = "Kalinga Selatan",
["ksd"] = "Tolai",
["kse"] = "Kuni",
["ksf"] = "Bafia",
["ksg"] = "Kusaghe",
["ksi"] = "Krisa",
["ksj"] = "Uare",
["ksk"] = "Kansa",
["ksl"] = "Kumalu",
["ksm"] = "Kumba",
["ksn"] = "Kasiguranin",
["kso"] = "Kofa",
["ksp"] = "Kaba",
["ksq"] = "Kwaami",
["ksr"] = "Borong",
["kss"] = "Kissi Selatan",
["kst"] = "Winyé",
["ksu"] = "Khamyang",
["ksv"] = "Kusu",
["ksw"] = "Karen S'gaw",
["ksx"] = "Kedang",
["ksy"] = "Kharia Thar",
["ksz"] = "Kodaku",
["kta"] = "Katua",
["ktb"] = "Kambaata",
["ktc"] = "Kholok",
["ktd"] = "Kokata",
["ktf"] = "Kwami",
["ktg"] = "Kalkatungu",
["kth"] = "Karanga",
["kti"] = "Muyu Utara",
["ktj"] = "Plapo Krumen",
["ktk"] = "Kaniet",
["ktl"] = "Koroshi",
["ktm"] = "Kurti",
["ktn"] = "Karitiâna",
["kto"] = "Kuot",
["ktp"] = "Kaduo",
["ktq"] = "Katabaga",
["ktr"] = "Kota Marudu Tinagas",
["kts"] = "Muyu Selatan",
["ktt"] = "Ketum",
["ktu"] = "Kituba",
["ktv"] = "Katu Timur",
["ktw"] = "Kato",
["ktx"] = "Kaxararí",
["kty"] = "Kango",
["ktz"] = "Juǀ'hoan",
["ku-pro"] = "Proto-Kurdi",
["kub"] = "Kutep",
["kuc"] = "Kwinsu",
["kud"] = "Auhelawa",
["kue"] = "Kuman",
["kuf"] = "Katu Barat",
["kug"] = "Kupa",
["kuh"] = "Kushi",
["kui"] = "Kuikúro",
["kuj"] = "Kuria",
["kuk"] = "Kepo'",
["kul"] = "Kulere",
["kum"] = "Kumyk",
["kun"] = "Kunama",
["kuo"] = "Kumukio",
["kup"] = "Kunimaipa",
["kuq"] = "Karipuna",
["kus"] = "Kusaal",
["kut"] = "Kutenai",
["kuu"] = "Kuskokwim Hulu",
["kuv"] = "Kur",
["kuw"] = "Kpagua",
["kux"] = "Kukatja",
["kuy"] = "Kuuku-Ya'u",
["kuz"] = "Kunza",
["kva"] = "Bagvalal",
["kvb"] = "Orang Rimba",
["kvc"] = "Kove",
["kvd"] = "Kui",
["kve"] = "Kalabakan",
["kvf"] = "Kabalai",
["kvg"] = "Kuni-Boazi",
["kvh"] = "Komodo",
["kvi"] = "Kwang",
["kvj"] = "Psikye",
["kvk"] = "Isyarat Korea",
["kvl"] = "Karen Brek",
["kvm"] = "Kendem",
["kvn"] = "Border Kuna",
["kvo"] = "Dobel",
["kvp"] = "Kompane",
["kvq"] = "Karen Geba",
["kvr"] = "Kerinci",
["kvt"] = "Karen Lahta",
["kvu"] = "Karen Yinbaw",
["kvv"] = "Kola",
["kvw"] = "Wersing",
["kvx"] = "Koli Parkari",
["kvy"] = "Karen Yintale",
["kvz"] = "Tsakwambo",
["kw"] = "Kernowek",
["kwa"] = "Dâw",
["kwb"] = "Baa",
["kwc"] = "Likwala",
["kwd"] = "Kwaio",
["kwe"] = "Kwerba",
["kwf"] = "Kwara'ae",
["kwg"] = "Sara Kaba Deme",
["kwh"] = "Kowiai",
["kwi"] = "Awa-Cuaiquer",
["kwj"] = "Kwanga",
["kwk"] = "Kwak'wala",
["kwl"] = "Kofyar",
["kwm"] = "Kwambi",
["kwn"] = "Kwangali",
["kwo"] = "Kwomtari",
["kwp"] = "Kodia",
["kwq"] = "Kwak",
["kwr"] = "Kwer",
["kws"] = "Kwese",
["kwt"] = "Kwesten",
["kwu"] = "Kwakum",
["kwv"] = "Sara Kaba Náà",
["kww"] = "Kwinti",
["kwx"] = "Khirwar",
["kwz"] = "Kwadi",
["kxa"] = "Kairiru",
["kxb"] = "Krobu",
["kxc"] = "Khonso",
["kxd"] = "Melayu Brunei",
["kxe"] = "Kakihum",
["kxf"] = "Karen Manumanaw",
["kxh"] = "Karo",
["kxi"] = "Murut Keningau",
["kxj"] = "Kulfa",
["kxk"] = "Karen Zayein",
["kxl"] = "Nepai Kurux",
["kxm"] = "Khmer Utara",
["kxn"] = "Kanowit",
["kxo"] = "Kanoé",
["kxp"] = "Koli Wadiyara",
["kxq"] = "Kanum Smärky",
["kxr"] = "Koro (Papua)",
["kxs"] = "Kangjia",
["kxt"] = "Koiwat",
["kxu"] = "Kui (India)",
["kxv"] = "Kuvi",
["kxw"] = "Konai",
["kxx"] = "Likuba",
["kxy"] = "Kayong",
["kxz"] = "Kerewo",
["ky"] = "Kirgiz",
["kya"] = "Kwaya",
["kyb"] = "Kalinga Butbut",
["kyc"] = "Kyaka",
["kyd"] = "Karey",
["kye"] = "Krache",
["kyf"] = "Kouya",
["kyg"] = "Keyagana",
["kyh"] = "Karok",
["kyi"] = "Kiput",
["kyj"] = "Karao",
["kyk"] = "Kamayo",
["kyl"] = "Kalapuya",
["kym"] = "Kpatili",
["kyn"] = "Karolanos",
["kyo"] = "Kelon",
["kyp"] = "Kang",
["kyq"] = "Kenga",
["kyr"] = "Kuruáya",
["kys"] = "Kayan Baram",
["kyt"] = "Kayagar",
["kyu"] = "Kayah Barat",
["kyv"] = "Kayort",
["kyw"] = "Kudmali",
["kyx"] = "Rapoisi",
["kyy"] = "Kambaira",
["kyz"] = "Kayabí",
["kza"] = "Karaboro Barat",
["kzb"] = "Kaibobo",
["kzc"] = "Kulango Bondoukou",
["kzd"] = "Kadai",
["kze"] = "Kosena",
["kzf"] = "Kaili Da'a",
["kzg"] = "Kikai",
["kzh"] = "Dongolawi",
["kzi"] = "Kelabit",
["kzj"] = "Kadazan Pesisir",
["kzk"] = "Kazukuru",
["kzl"] = "Kayeli",
["kzm"] = "Kais",
["kzn"] = "Kokola",
["kzo"] = "Kaningi",
["kzp"] = "Kaidipang",
["kzq"] = "Kaike",
["kzr"] = "Karang",
["kzs"] = "Dusun Sugut",
["kzt"] = "Dusun Tambunan",
["kzu"] = "Kayupulau",
["kzv"] = "Komyandaret",
["kzw"] = "Kariri",
["kzx"] = "Kamarian",
["kzy"] = "Kango-Sua",
["kzz"] = "Kalabra",
["la"] = "Latin",
["laa"] = "Lapuyan Subanun",
["lab"] = "Linear A",
["lac"] = "Lacandon",
["lad"] = "Ladino",
["lae"] = "Pattani",
["laf"] = "Lafofa",
["lag"] = "Langi",
["lah"] = "Lahnda",
["lai"] = "Lambya",
["laj"] = "Lango (Uganda)",
["lak"] = "Laka",
["lam"] = "Lamba",
["lan"] = "Laru",
["lap"] = "Kabba-Laka",
["laq"] = "Qabiao",
["lar"] = "Larteh",
["las"] = "Gur Lama",
["lau"] = "Laba",
["law"] = "Lauje",
["lax"] = "Tiwa",
["lay"] = "Bai Lama",
["laz"] = "Aribwatsa",
["lb"] = "Luksemburg",
["lbb"] = "Label",
["lbc"] = "Lakkia",
["lbe"] = "Lak",
["lbf"] = "Tinani",
["lbg"] = "Laopang",
["lbi"] = "La'bi",
["lbj"] = "Ladakhi",
["lbk"] = "Bontoc Tengah",
["lbl"] = "Bikol Libon",
["lbm"] = "Lodhi",
["lbn"] = "Lamet",
["lbo"] = "Laven",
["lbq"] = "Wampar",
["lbr"] = "Lorung Utara",
["lbs"] = "Isyarat Libya",
["lbt"] = "Lachi",
["lbu"] = "Labu",
["lbv"] = "Lavatbura-Lamusong",
["lbw"] = "Tolaki",
["lbx"] = "Lawangan-Pasir",
["lby"] = "Lamu-Lamu",
["lbz"] = "Lardil",
["lcc"] = "Legenyem",
["lcd"] = "Lola",
["lce"] = "Loncong",
["lcf"] = "Lubu",
["lch"] = "Luchazi",
["lcl"] = "Lisela",
["lcm"] = "Tungag",
["lcp"] = "Lawa Barat",
["lcq"] = "Luhu",
["lcs"] = "Lisabata-Nuniali",
["lda"] = "Kla",
["ldb"] = "Idun",
["ldd"] = "Luri (Nigeria)",
["ldg"] = "Lenyima",
["ldh"] = "Lamja-Dengsa-Tola",
["ldj"] = "Lemoro",
["ldk"] = "Leelau",
["ldl"] = "Kaan",
["ldm"] = "Landoma",
["ldn"] = "Láadan",
["ldo"] = "Loo",
["ldp"] = "Tso",
["ldq"] = "Lufu",
["lea"] = "Lega-Shabunda",
["leb"] = "Lala-Bisa",
["lec"] = "Leco",
["led"] = "Lendu",
["lee"] = "Lyélé",
["lef"] = "Lelemi",
["leh"] = "Lenje",
["lei"] = "Lemio",
["lej"] = "Lengola",
["lek"] = "Leipon",
["lel"] = "Lele (Kongo)",
["lem"] = "Nomaande",
["len"] = "Lenca Honduras",
["leo"] = "Leti (Kamerun)",
["lep"] = "Lepcha",
["leq"] = "Lembena",
["ler"] = "Lenkau",
["les"] = "Lese",
["let"] = "Lesing-Gelimi",
["leu"] = "Kara (Papua)",
["lev"] = "Lamma",
["lew"] = "Kaili",
["lex"] = "Luang",
["ley"] = "Lemolang",
["lez"] = "Lezgi",
["lfa"] = "Lefa",
["lfn"] = "Lingua Franca Nova",
["lg"] = "Luganda",
["lga"] = "Lungga",
["lgb"] = "Laghu",
["lgg"] = "Lugbara",
["lgh"] = "Laghuu",
["lgi"] = "Lengilu",
["lgk"] = "Neverver",
["lgl"] = "Wala",
["lgm"] = "Lega-Mwenga",
["lgn"] = "Opuuo",
["lgq"] = "Logba",
["lgr"] = "Lengo",
["lgs"] = "Isyarat Guinea-Bissau",
["lgt"] = "Pahi",
["lgu"] = "Longgu",
["lgz"] = "Ligenza",
["lha"] = "Laha (Vietnam)",
["lhh"] = "Laha",
["lhi"] = "Lahu Shi",
["lhl"] = "Lahul Lohar",
["lhn"] = "Lahanan",
["lhp"] = "Lhokpu",
["lhs"] = "Mlahsö",
["lht"] = "Lo-Toga",
["lhu"] = "Lahu",
["li"] = "Limburg",
["lia"] = "Limba Tengah Barat",
["lib"] = "Likum",
["lic"] = "Hlai",
["lid"] = "Nyindrou",
["lie"] = "Likila",
["lif"] = "Limbu",
["lig"] = "Ligbi",
["lih"] = "Lihir",
["lii"] = "Lingkhim",
["lij"] = "Liguria",
["lik"] = "Lika",
["lil"] = "Lillooet",
["lio"] = "Liki",
["lip"] = "Sekpele",
["liq"] = "Libido",
["lir"] = "Inggris Liberia",
["lis"] = "Lisu",
["liu"] = "Logorik",
["liv"] = "Livonia",
["liw"] = "Col",
["lix"] = "Liabuku",
["liy"] = "Banda-Bambari",
["liz"] = "Libinza",
["lja"] = "Golpa",
["lje"] = "Rampi",
["lji"] = "Laiyolo",
["ljl"] = "Lio",
["ljp"] = "Lampung Api",
["ljw"] = "Yirandali",
["ljx"] = "Yuru",
["lka"] = "Lakalei",
["lkb"] = "Kabras",
["lkc"] = "Kucong",
["lkd"] = "Lakondê",
["lke"] = "Kenyi",
["lkh"] = "Lakha",
["lki"] = "Laki",
["lkj"] = "Remun",
["lkl"] = "Laeko-Libuat",
["lkm"] = "Kalaamaya",
["lkn"] = "Lakon",
["lko"] = "Khayo",
["lkr"] = "Päri",
["lks"] = "Kisa",
["lkt"] = "Lakota",
["lku"] = "Kungkari",
["lky"] = "Lokoya",
["lla"] = "Lala-Roba",
["llb"] = "Lolo",
["llc"] = "Lele (Guinea)",
["lld"] = "Ladin",
["lle"] = "Lele (Papua)",
["llf"] = "Hermit",
["llg"] = "Lole",
["llh"] = "Lamu",
["lli"] = "Teke-Laali",
["llj"] = "Ladji-Ladji",
["llk"] = "Lelak",
["lll"] = "Lilau",
["llm"] = "Lasalimu",
["lln"] = "Lele (Chad)",
["llo"] = "Khlor",
["llp"] = "Efate Utara",
["llq"] = "Lolak",
["lls"] = "Isyarat Lituania",
["llu"] = "Lau",
["llx"] = "Lauan",
["lma"] = "Limba Timur",
["lmb"] = "Merei",
["lmc"] = "Limilngan",
["lmd"] = "Lumun",
["lme"] = "Pévé",
["lmf"] = "Lembata Selatan",
["lmg"] = "Lamogai",
["lmh"] = "Lambichhong",
["lmi"] = "Lombi",
["lmj"] = "Lembata Barat",
["lmk"] = "Lamkang",
["lml"] = "Raga",
["lmn"] = "Lambadi",
["lmo"] = "Lombard",
["lmp"] = "Limbum",
["lmq"] = "Lamatuka",
["lmr"] = "Lamalera",
["lmu"] = "Lamenu",
["lmv"] = "Lomaiviti",
["lmw"] = "Miwok Lake",
["lmx"] = "Laimbue",
["lmy"] = "Laboya",
["lmz"] = "Lumbee",
["ln"] = "Lingala",
["lna"] = "Langbashe",
["lnb"] = "Mbalanhu",
["lnd"] = "Lun Bawang",
["lnh"] = "Lanoh",
["lni"] = "Daantanai'",
["lnj"] = "Linngithigh",
["lnl"] = "Banda Tengah Selatan",
["lnm"] = "Langam",
["lnn"] = "Lorediakarkar",
["lno"] = "Lango (Sudan)",
["lns"] = "Lamnso'",
["lnu"] = "Longuda",
["lnw"] = "Lanima",
["lo"] = "Lao",
["loa"] = "Loloda",
["lob"] = "Lobi",
["loc"] = "Inonhan",
["lod"] = "Berawan",
["loe"] = "Saluan",
["lof"] = "Logol",
["log"] = "Logo",
["loh"] = "Narim",
["loi"] = "Lomakka",
["loj"] = "Lou",
["lok"] = "Loko",
["lol"] = "Mongo",
["lom"] = "Looma",
["lon"] = "Malawi Lomwe",
["loo"] = "Lombo",
["lop"] = "Lopa",
["loq"] = "Lobala",
["lor"] = "Téén",
["los"] = "Loniu",
["lot"] = "Lotuko",
["lou"] = "Kreol Louisiana",
["lov"] = "Lopi",
["low"] = "Lobu Tampias",
["lox"] = "Loun",
["loz"] = "Lozi",
["lpa"] = "Lelepa",
["lpe"] = "Lepki",
["lpn"] = "Naga Long Phuri",
["lpo"] = "Lipo",
["lpx"] = "Lopit",
["lra"] = "Rara Bakati'",
["lrc"] = "Luri Utara",
["lre"] = "Laurentian",
["lrg"] = "Laragia",
["lri"] = "Marachi",
["lrk"] = "Loarki",
["lrl"] = "Larestani",
["lrm"] = "Marama",
["lrn"] = "Lorang",
["lro"] = "Laro",
["lrr"] = "Lorung Selatan",
["lrt"] = "Melayu Larantuka",
["lrv"] = "Larevat",
["lrz"] = "Lemerig",
["lsa"] = "Lasgerdi",
["lsd"] = "Lishana Deni",
["lse"] = "Lusengo",
["lsh"] = "Lish",
["lsi"] = "Lashi",
["lsl"] = "Isyarat Latvia",
["lsm"] = "Saamia",
["lso"] = "Isyarat Laos",
["lsp"] = "Isyarat Panama",
["lsr"] = "Aruop",
["lss"] = "Lasi",
["lst"] = "Isyarat Trinidad dan Tobago",
["lsy"] = "Isyarat Mauritius",
["lt"] = "Lithuania",
["ltc"] = "Tionghoa Pertengahan",
["ltg"] = "Latgalian",
["lti"] = "Leti",
["ltn"] = "Latundê",
["lto"] = "Olutsotso",
["lts"] = "Lutachoni",
["ltu"] = "Latu",
["lu"] = "Luba-Katanga",
["lua"] = "Luba-Kasai",
["luc"] = "Aringa",
["lud"] = "Ludian",
["lue"] = "Luvale",
["luf"] = "Laua",
["lui"] = "Luiseño",
["luj"] = "Luna",
["luk"] = "Lunanakha",
["lul"] = "Olu'bo",
["lum"] = "Luimbi",
["lun"] = "Lunda",
["luo"] = "Luo",
["lup"] = "Lumbu",
["luq"] = "Lucumí",
["lur"] = "Laura",
["lus"] = "Mizo",
["lut"] = "Lushootseed",
["luu"] = "Lumba-Yakkha",
["luv"] = "Luwati",
["luy"] = "Luhya",
["luz"] = "Luri Selatan",
["lv"] = "Latvia",
["lva"] = "Maku'a",
["lvi"] = "Lawi",
["lvk"] = "Lavukaleve",
["lvu"] = "Levuka",
["lwa"] = "Lwalu",
["lwe"] = "Lewo Eleng",
["lwg"] = "Wanga",
["lwh"] = "Lachi Putih",
["lwl"] = "Lawa Timur",
["lwm"] = "Laomian",
["lwo"] = "Luwo",
["lws"] = "Isyarat Malawi",
["lwt"] = "Lewotobi",
["lwu"] = "Lawu",
["lww"] = "Lewo",
["lya"] = "Layakha",
["lyg"] = "Lyngngam",
["lyn"] = "Luyana",
["lzh"] = "Tionghoa Literatur",
["lzl"] = "Litzlitz",
["lzn"] = "Naga Leinong",
["lzz"] = "Laz",
["maa"] = "Mazatec San Jerónimo Tecóatl",
["mab"] = "Mixtec Yutanduchi",
["mad"] = "Madura",
["mae"] = "Bo-Rukul",
["maf"] = "Mafa",
["mag"] = "Magahi",
["mai"] = "Maithili",
["maj"] = "Mazatec Jalapa de Díaz",
["mak"] = "Makassar",
["mam"] = "Mam",
["man"] = "Mandingo",
["map-ata-pro"] = "Proto-Atayalic",
["map-bms"] = "Jawa Banyumasan",
["map-pro"] = "Proto-Austronesia",
["maq"] = "Mazatec Chiquihuitlán",
["mas"] = "Maasai",
["mat"] = "Matlatzinca",
["mau"] = "Mazatec Huautla",
["mav"] = "Sateré-Mawé",
["maw"] = "Mampruli",
["max"] = "Melayu Maluku Utara",
["maz"] = "Mazahua Tengah",
["mba"] = "Higaonon",
["mbb"] = "Manobo Bukidnon Barat",
["mbc"] = "Macushi",
["mbd"] = "Manobo Dibabawon",
["mbe"] = "Molale",
["mbf"] = "Melayu Baba",
["mbh"] = "Mangseng",
["mbi"] = "Manobo Ilianen",
["mbj"] = "Nadëb",
["mbk"] = "Malol",
["mbl"] = "Maxakalí",
["mbm"] = "Ombamba",
["mbn"] = "Macaguán",
["mbo"] = "Mbo (Kamerun)",
["mbp"] = "Wiwa",
["mbq"] = "Maisin",
["mbr"] = "Nukak Makú",
["mbs"] = "Manobo Sarangani",
["mbt"] = "Manobo Matigsalug",
["mbu"] = "Mbula-Bwazza",
["mbv"] = "Mbulungish",
["mbw"] = "Maring",
["mbx"] = "Mari Sepik",
["mby"] = "Memoni",
["mbz"] = "Mixtec Amoltepec",
["mca"] = "Maca",
["mcb"] = "Machiguenga",
["mcc"] = "Bitur",
["mcd"] = "Sharanahua",
["mce"] = "Mixtec Itundujia",
["mcf"] = "Matsés",
["mcg"] = "Mapoyo",
["mch"] = "Maquiritari",
["mci"] = "Mese",
["mcj"] = "Mvanip",
["mck"] = "Mbunda",
["mcl"] = "Macaguaje",
["mcm"] = "Kristang",
["mcn"] = "Masana",
["mco"] = "Mixe Coatlán",
["mcp"] = "Makaa",
["mcq"] = "Ese",
["mcr"] = "Menya",
["mcs"] = "Mambai",
["mcu"] = "Mambila Kamerun",
["mcv"] = "Minanibai",
["mcw"] = "Mawa",
["mcx"] = "Mpiemo",
["mcy"] = "Watut Selatan",
["mcz"] = "Mawan",
["mda"] = "Mada (Nigeria)",
["mdb"] = "Morigi",
["mdc"] = "Male",
["mdd"] = "Mbum",
["mde"] = "Bura Mabang",
["mdf"] = "Moksha",
["mdg"] = "Massalat",
["mdh"] = "Maguindanao",
["mdi"] = "Mamvu",
["mdj"] = "Mangbetu",
["mdk"] = "Mangbutu",
["mdl"] = "Isyarat Malta",
["mdm"] = "Mayogo",
["mdn"] = "Mbati",
["mdp"] = "Mbala",
["mdq"] = "Mbole",
["mdr"] = "Mandar",
["mds"] = "Maria",
["mdt"] = "Mbere",
["mdu"] = "Mboko",
["mdv"] = "Mixtec Santa Lucía Monteverde",
["mdw"] = "Mbosi",
["mdx"] = "Dizin",
["mdy"] = "Maale",
["mdz"] = "Suruí Do Pará",
["mea"] = "Menka",
["meb"] = "Ikobi-Mena",
["mec"] = "Mara",
["med"] = "Melpa",
["mee"] = "Mengen",
["mef"] = "Megam",
["meg"] = "Mea",
["meh"] = "Mixtec Tlaxiaco Barat Daya",
["mei"] = "Midob",
["mej"] = "Meyah",
["mek"] = "Mekeo",
["mel"] = "Melanau Tengah",
["mem"] = "Mangala",
["men"] = "Mende",
["meo"] = "Melayu Kedah",
["mep"] = "Miriwung",
["meq"] = "Merey",
["mer"] = "Meru",
["mes"] = "Masmaje",
["met"] = "Mato",
["meu"] = "Motu",
["mev"] = "Mano",
["mew"] = "Maaka",
["mey"] = "Hassaniya",
["mez"] = "Menominee",
["mfa"] = "Melayu Kelantan-Patani",
["mfb"] = "Bangka",
["mfc"] = "Mba",
["mfd"] = "Mendankwe-Nkwen",
["mfe"] = "Kreol Mauritia",
["mff"] = "Naki",
["mfg"] = "Mixifore",
["mfh"] = "Matal",
["mfi"] = "Wandala",
["mfj"] = "Mefele",
["mfk"] = "Mofu Utara",
["mfl"] = "Putai",
["mfm"] = "Marghi Selatan",
["mfn"] = "Mbembe Sungai Cross",
["mfo"] = "Mbe",
["mfp"] = "Melayu Makassar",
["mfq"] = "Moba",
["mfr"] = "Marrithiyel",
["mfs"] = "Isyarat Meksiko",
["mft"] = "Mokerang",
["mfu"] = "Mbwela",
["mfv"] = "Mandjak",
["mfw"] = "Mulaha",
["mfx"] = "Melo",
["mfy"] = "Mayo",
["mfz"] = "Mabaan",
["mg"] = "Malagasi",
["mga"] = "Irlandia Pertengahan",
["mgb"] = "Mararit",
["mgc"] = "Morokodo",
["mgd"] = "Moru",
["mge"] = "Mango",
["mgf"] = "Maklew",
["mgg"] = "Mpongmpong",
["mgh"] = "Makhuwa-Meetto",
["mgi"] = "Jili",
["mgj"] = "Abureni",
["mgk"] = "Mawes",
["mgl"] = "Maleu-Kilenge",
["mgm"] = "Mambae",
["mgn"] = "Mbangi",
["mgo"] = "Meta'",
["mgp"] = "Magar Timur",
["mgq"] = "Malila",
["mgr"] = "Mambwe-Lungu",
["mgs"] = "Manda (Tanzania)",
["mgt"] = "Mongol",
["mgu"] = "Mailu",
["mgv"] = "Matengo",
["mgw"] = "Matumbi",
["mgy"] = "Mbunga",
["mgz"] = "Mbugwe",
["mh"] = "Marshall",
["mha"] = "Manda (India)",
["mhb"] = "Mahongwe",
["mhc"] = "Mocho",
["mhd"] = "Mbugu",
["mhe"] = "Besisi",
["mhf"] = "Mamaa",
["mhg"] = "Margu",
["mhi"] = "Ma'di",
["mhj"] = "Mogholi",
["mhk"] = "Mungaka",
["mhl"] = "Mauwake",
["mhm"] = "Makhuwa-Moniga",
["mhn"] = "Mòcheno",
["mho"] = "Mashi",
["mhp"] = "Melayu Bali",
["mhq"] = "Mandan",
["mhr"] = "Mari Timur",
["mhs"] = "Buru",
["mht"] = "Mandahuaca",
["mhu"] = "Taraon",
["mhw"] = "Mbukushu",
["mhx"] = "Lhao Vo",
["mhy"] = "Ma'anyan",
["mhz"] = "Mor (Austronesia)",
["mi"] = "Maori",
["mia"] = "Miami",
["mib"] = "Mixtec Atatláhuca",
["mic"] = "Mi'kmaq",
["mid"] = "Mandaic",
["mie"] = "Mixtec Ocotepec",
["mif"] = "Mofu-Gudur",
["mig"] = "Mixtec San Miguel el Grande",
["mih"] = "Mixtec Chayuco",
["mii"] = "Mixtec Chigmecatitlán",
["mij"] = "Mungbam",
["mik"] = "Mikasuki",
["mil"] = "Mixtec Peñoles",
["mim"] = "Mixtec Alacatlatzala",
["min"] = "Minangkabau",
["min-ski"] = "Sakai",
["mio"] = "Mixtec Pinotepa Nacional",
["mip"] = "Mixtec Apasco-Apoala",
["miq"] = "Miskito",
["mir"] = "Mixe Isthmus",
["mit"] = "Mixtec Puebla Selatan",
["miu"] = "Mixtec Cacaloxtepec",
["miw"] = "Akoye",
["mix"] = "Mixtec Mixtepec",
["miy"] = "Mixtec Ayutla",
["miz"] = "Mixtec Coatzospan",
["mjb"] = "Makalero",
["mjc"] = "Mixtec San Juan Colorado",
["mjd"] = "Maidu Barat Laut",
["mje"] = "Muskum",
["mji"] = "Kim Mun",
["mjj"] = "Mawak",
["mjk"] = "Matukar",
["mjl"] = "Mandeali",
["mjm"] = "Medebur",
["mjn"] = "Mebu",
["mjo"] = "Malankuravan",
["mjp"] = "Malapandaram",
["mjq"] = "Malaryan",
["mjr"] = "Malavedan",
["mjs"] = "Miship",
["mjt"] = "Paharia Sawriya",
["mju"] = "Manna-Dora",
["mjv"] = "Mannan",
["mjw"] = "Karbi",
["mjx"] = "Mahali",
["mjy"] = "Mahican",
["mjz"] = "Majhi",
["mk"] = "Makedonia",
["mka"] = "Mbre",
["mkb"] = "Paharia Mal",
["mkc"] = "Siliput",
["mke"] = "Mawchi",
["mkf"] = "Miya",
["mkg"] = "Mak (Tiongkok)",
["mkh-asl-pro"] = "Proto-Aslian",
["mkh-ban-pro"] = "Proto-Bahnaric",
["mkh-kat-pro"] = "Proto-Katuic",
["mkh-khm-pro"] = "Proto-Khmuic",
["mkh-kmr-pro"] = "Proto-Khmeric",
["mkh-mmn"] = "Mon Pertengahan",
["mkh-mnc-pro"] = "Proto-Monic",
["mkh-mvi"] = "Vietnam Pertengahan",
["mkh-pal-pro"] = "Proto-Palaungic",
["mkh-pea-pro"] = "Proto-Pearic",
["mkh-pkn-pro"] = "Proto-Pakanic",
["mkh-pro"] = "Proto-Mon-Khmer",
["mkh-vie-pro"] = "Proto-Vietic",
["mki"] = "Dhatki",
["mkj"] = "Mokilese",
["mkk"] = "Byep",
["mkl"] = "Mokole",
["mkm"] = "Moklen",
["mkn"] = "Melayu Kupang",
["mko"] = "Mingang Doso",
["mkp"] = "Moikodi",
["mkq"] = "Miwok Bay",
["mkr"] = "Malas",
["mks"] = "Mixtec Silacayoapan",
["mkt"] = "Vamale",
["mku"] = "Maninka Konyanka",
["mkv"] = "Mafea",
["mkx"] = "Manobo Cinamiguin",
["mky"] = "Makian Timur",
["mkz"] = "Makasae",
["ml"] = "Malayalam",
["mla"] = "Tamambo",
["mlb"] = "Mbule",
["mlc"] = "Caolan",
["mle"] = "Manambu",
["mlf"] = "Mal",
["mlh"] = "Mape",
["mli"] = "Malimpung",
["mlj"] = "Miltu",
["mlk"] = "Ilwana",
["mll"] = "Malua Bay",
["mlm"] = "Mulam",
["mln"] = "Malango",
["mlo"] = "Mlomp",
["mlp"] = "Bargam",
["mlq"] = "Maninkakan Barat",
["mlr"] = "Vame",
["mls"] = "Masalit",
["mlu"] = "To'abaita",
["mlv"] = "Mwotlap",
["mlw"] = "Moloko",
["mlx"] = "Malfaxal",
["mlz"] = "Malaynon",
["mma"] = "Mama",
["mmb"] = "Momina",
["mmc"] = "Mazahua Michoacán",
["mmd"] = "Maonan",
["mme"] = "Mae",
["mmf"] = "Mundat",
["mmg"] = "Ambrym Utara",
["mmh"] = "Mehináku",
["mmi"] = "Musar",
["mmj"] = "Majhwar",
["mmk"] = "Mukha-Dora",
["mml"] = "Man Met",
["mmm"] = "Maii",
["mmn"] = "Mamanwa",
["mmo"] = "Buang Mangga",
["mmp"] = "Musan",
["mmq"] = "Aisi",
["mmr"] = "Miao Xiangxi Barat",
["mmt"] = "Malalamai",
["mmu"] = "Mmaala",
["mmv"] = "Miriti",
["mmw"] = "Emae",
["mmx"] = "Madak",
["mmy"] = "Migaama",
["mmz"] = "Mabaale",
["mn"] = "Mongolia",
["mna"] = "Mbula",
["mnb"] = "Muna",
["mnc"] = "Manchu",
["mnd"] = "Mondé",
["mne"] = "Naba",
["mnf"] = "Mundani",
["mng"] = "Mnong Timur",
["mnh"] = "Mono (Kongo)",
["mni"] = "Manipuri",
["mnj"] = "Munji",
["mnk"] = "Mandinka",
["mnl"] = "Tiale",
["mnm"] = "Mapena",
["mnn"] = "Mnong Selatan",
["mnp"] = "Min Bei",
["mnq"] = "Minriq",
["mnr"] = "Mono (California)",
["mns"] = "Mansi",
["mnt"] = "Maykulan",
["mnu"] = "Mer",
["mnv"] = "Rennellese",
["mnw"] = "Mon",
["mnw-tha"] = "Mon Thai",
["mnx"] = "Manikion",
["mny"] = "Manyawa",
["mnz"] = "Migani",
["moa"] = "Mwan",
["moc"] = "Mocoví",
["mod"] = "Mobilian",
["moe"] = "Montagnais",
["mog"] = "Mongondow",
["moh"] = "Mohawk",
["moi"] = "Mboi",
["moj"] = "Monzombo",
["mok"] = "Morori",
["mom"] = "Monimbo",
["moo"] = "Monom",
["mop"] = "Maya Mopan",
["moq"] = "Mor (Papua)",
["mor"] = "Moro",
["mos"] = "Moore",
["mot"] = "Barí",
["mou"] = "Mogum",
["mov"] = "Mojave",
["mow"] = "Moi (Kongo)",
["mox"] = "Molima",
["moy"] = "Shekkacho",
["moz"] = "Mukulu",
["mpa"] = "Mpoto",
["mpb"] = "Mullukmulluk",
["mpc"] = "Mangarayi",
["mpd"] = "Machinere",
["mpe"] = "Majang",
["mpg"] = "Marba",
["mph"] = "Maung",
["mpi"] = "Mpade",
["mpj"] = "Martu Wangka",
["mpk"] = "Mbara (Chad)",
["mpl"] = "Watut Pertengahan",
["mpm"] = "Mixtec Yosondúa",
["mpn"] = "Mindiri",
["mpo"] = "Miu",
["mpp"] = "Migabac",
["mpq"] = "Matís",
["mpr"] = "Vangunu",
["mps"] = "Dadibi",
["mpt"] = "Mian",
["mpu"] = "Makuráp",
["mpv"] = "Mungkip",
["mpw"] = "Mapidian",
["mpx"] = "Misima-Paneati",
["mpy"] = "Mapia",
["mpz"] = "Mpi",
["mqa"] = "Maba",
["mqb"] = "Mbuko",
["mqc"] = "Mangole",
["mqe"] = "Matepi",
["mqf"] = "Momuna",
["mqg"] = "Kutai Hulu",
["mqh"] = "Mixtec Tlazoyaltepec",
["mqi"] = "Mariri",
["mqj"] = "Mamasa",
["mqk"] = "Manobo Rajah Kabunsuwan",
["mql"] = "Mbelime",
["mqm"] = "Marquesan Selatan",
["mqn"] = "Moronene",
["mqo"] = "Modole",
["mqp"] = "Manipa",
["mqq"] = "Minokok",
["mqr"] = "Mander",
["mqs"] = "Makian Barat",
["mqt"] = "Mok",
["mqu"] = "Mandari",
["mqv"] = "Mosimo",
["mqw"] = "Murupi",
["mqx"] = "Mamuju",
["mqy"] = "Manggarai",
["mqz"] = "Malasanga",
["mr"] = "Marathi",
["mra"] = "Mlabri",
["mrb"] = "Marino",
["mrc"] = "Maricopa",
["mrd"] = "Magar Barat",
["mre"] = "Isyarat Martha's Vineyard",
["mrf"] = "Elseng",
["mrg"] = "Mising",
["mrh"] = "Chin Mara",
["mrj"] = "Mari Barat",
["mrk"] = "Hmwaveke",
["mrl"] = "Mortlockese",
["mrm"] = "Merlav",
["mrn"] = "Cheke Holo",
["mro"] = "Mru",
["mrp"] = "Morouas",
["mrq"] = "Marquesan Utara",
["mrr"] = "Maria Hill",
["mrs"] = "Maragus",
["mrt"] = "Margi",
["mru"] = "Mono (Kamerun)",
["mrv"] = "Mangarevan",
["mrw"] = "Maranao",
["mrx"] = "Dineor",
["mry"] = "Karaga Mandaya",
["mrz"] = "Marind",
["ms"] = "Melayu",
["ms-tma"] = "Talang Mamak",
["msb"] = "Masbatenyo",
["msc"] = "Maninka Sankaran",
["msd"] = "Isyarat Maya Yucatec",
["mse"] = "Musey",
["msf"] = "Mekwei",
["msg"] = "Moraid",
["msi"] = "Melayu Sabah",
["msj"] = "Ma",
["msk"] = "Mansaka",
["msl"] = "Molof",
["msm"] = "Manobo Agusan",
["msn"] = "Vurës",
["mso"] = "Mombum",
["msp"] = "Maritsauá",
["msq"] = "Caac",
["msr"] = "Isyarat Mongolia",
["mss"] = "Masela Barat",
["msu"] = "Musom",
["msv"] = "Maslam",
["msw"] = "Mansoanka",
["msx"] = "Moresada",
["msy"] = "Aruamu",
["msz"] = "Momare",
["mt"] = "Malta",
["mta"] = "Manobo Cotabato",
["mtb"] = "Anyin Morofo",
["mtc"] = "Munit",
["mtd"] = "Mualang",
["mte"] = "Alu",
["mtf"] = "Murik (Papua)",
["mtg"] = "Una",
["mth"] = "Munggui",
["mti"] = "Maiwa (Papua)",
["mtj"] = "Moskona",
["mtk"] = "Mbe'",
["mtl"] = "Montol",
["mtm"] = "Mator",
["mtn"] = "Matagalpa",
["mto"] = "Mixe Totontepec",
["mtp"] = "Wichí Lhamtés Nocten",
["mtq"] = "Muong",
["mtr"] = "Mewari",
["mts"] = "Yora",
["mtt"] = "Mota",
["mtu"] = "Mixtec Tututepec",
["mtv"] = "Asaro'o",
["mtw"] = "Magahat",
["mtx"] = "Mixtec Tidaá",
["mty"] = "Nabi",
["mua"] = "Mundang",
["mub"] = "Mubi",
["muc"] = "Mbu'",
["mud"] = "Aleut Mednyj",
["mue"] = "Media Lengua",
["mug"] = "Musgu",
["muh"] = "Mündü",
["mui"] = "Musi",
["mui-plm"] = "Palembang", -- hanya dipakai di Wikikamus
["muj"] = "Mabire",
["mum"] = "Maiwala",
["mun-pro"] = "Proto-Munda",
["muo"] = "Nyong",
["mup"] = "Malvi",
["muq"] = "Miao Xiangxi Timur",
["mur"] = "Murle",
["mus"] = "Creek",
["mut"] = "Muria Barat",
["muu"] = "Yaaku",
["muv"] = "Muthuvan",
["mux"] = "Bo-Ung",
["muy"] = "Muyang",
["muz"] = "Mursi",
["mva"] = "Manam",
["mvb"] = "Mattole",
["mvd"] = "Mamboru",
["mvg"] = "Mixtec Yucuañe",
["mvh"] = "Mire",
["mvi"] = "Miyako",
["mvk"] = "Mekmek",
["mvl"] = "Mbara (Australia)",
["mvm"] = "Muya",
["mvn"] = "Minaveha",
["mvo"] = "Marovo",
["mvp"] = "Duri",
["mvq"] = "Moere",
["mvr"] = "Marau",
["mvs"] = "Massep",
["mvt"] = "Mpotovoro",
["mvu"] = "Marfa",
["mvv"] = "Murut Tagal",
["mvw"] = "Machinga",
["mvx"] = "Meoswar",
["mvy"] = "Indus Kohistani",
["mvz"] = "Mesqan",
["mwa"] = "Mwatebu",
["mwb"] = "Juwal",
["mwc"] = "Are",
["mwe"] = "Mwera",
["mwf"] = "Murrinh-Patha",
["mwg"] = "Aiklep",
["mwh"] = "Mouk-Aria",
["mwi"] = "Labo",
["mwk"] = "Maninkakan Kita",
["mwl"] = "Mirandese",
["mwm"] = "Sar",
["mwn"] = "Nyamwanga",
["mwo"] = "Maewo Tengah",
["mwp"] = "Kala Lagaw Ya",
["mwq"] = "Chin Mün",
["mwr"] = "Marwari",
["mws"] = "Mwimbi-Muthambi",
["mwt"] = "Moken",
["mwu"] = "Mittu",
["mwv"] = "Mentawai",
["mww"] = "Hmong Putih",
["mwz"] = "Moingi",
["mxa"] = "Mixtec Oaxaca Barat Laut",
["mxb"] = "Mixtec Tezoatlán",
["mxd"] = "Modang",
["mxe"] = "Mele-Fila",
["mxf"] = "Malgbe",
["mxg"] = "Mbangala",
["mxh"] = "Mvuba",
["mxi"] = "Mozarabic",
["mxj"] = "Miju",
["mxk"] = "Monumbo",
["mxl"] = "Gbe Maxi",
["mxm"] = "Meramera",
["mxn"] = "Moi",
["mxo"] = "Mbowe",
["mxp"] = "Mixe Tlahuitoltepec",
["mxq"] = "Mixe Juquila",
["mxr"] = "Murik (Malaysia)",
["mxs"] = "Mixtec Huitepec",
["mxt"] = "Mixtec Jamiltepec",
["mxu"] = "Mada (Kamerun)",
["mxv"] = "Mixtec Metlatónoc",
["mxw"] = "Namo",
["mxx"] = "Mahou",
["mxy"] = "Mixtec Nochixtlán Tenggara",
["mxz"] = "Masela Tengah",
["my"] = "Burma",
["myb"] = "Mbay",
["myc"] = "Mayeka",
["mye"] = "Myene",
["myf"] = "Bambassi",
["myg"] = "Manta",
["myh"] = "Makah",
["myj"] = "Mangayat",
["myk"] = "Senoufo Mamara",
["myl"] = "Moma",
["mym"] = "Me'en",
["myn-chl"] = "Ch'olti'",
["myn-pro"] = "Proto-Maya",
["myo"] = "Anfillo",
["myp"] = "Pirahã",
["myr"] = "Muniche",
["mys"] = "Mesmes",
["myu"] = "Mundurukú",
["myv"] = "Erzya",
["myw"] = "Muyuw",
["myx"] = "Masaba",
["myy"] = "Macuna",
["myz"] = "Mandaic Klasik",
["mza"] = "Mixtec Santa María Zacatepec",
["mzb"] = "Berber Sahara Utara",
["mzc"] = "Isyarat Madagaskar",
["mzd"] = "Malimba",
["mze"] = "Morawa",
["mzg"] = "Isyarat Monastic",
["mzh"] = "Wichí Lhamtés Güisnay",
["mzi"] = "Mazatec Ixcatlán",
["mzj"] = "Manya",
["mzk"] = "Mambila Nigeria",
["mzl"] = "Mixe Mazatlán",
["mzm"] = "Mumuye",
["mzn"] = "Mazanderani",
["mzo"] = "Matipuhy",
["mzp"] = "Movima",
["mzq"] = "Mori Atas",
["mzr"] = "Marúbo",
["mzs"] = "Makau",
["mzt"] = "Mintil",
["mzu"] = "Inapang",
["mzv"] = "Manza",
["mzw"] = "Deg",
["mzx"] = "Mawayana",
["mzy"] = "Isyarat Mozambik",
["mzz"] = "Maiadomu",
["na"] = "Nauru",
["naa"] = "Namla",
["nab"] = "Nambikwara",
["nac"] = "Narak",
["nae"] = "Naka'ela",
["naf"] = "Nabak",
["nag"] = "Naga Pijin",
["nah"] = "Nahuatl",
["nai-ala"] = "Alazapa",
["nai-bay"] = "Bayogoula",
["nai-bvy"] = "Yokuts Buena Vista",
["nai-cal"] = "Calusa",
["nai-chi"] = "Chiquimulilla",
["nai-chu-pro"] = "Proto-Chumash",
["nai-cig"] = "Ciguayo",
["nai-ckn-pro"] = "Proto-Chinookan",
["nai-dly"] = "Yokuts Delta",
["nai-gsy"] = "Gashowu",
["nai-guz"] = "Guazacapán",
["nai-hit"] = "Hitchiti",
["nai-ipa"] = "Ipai",
["nai-jtp"] = "Jutiapa",
["nai-jum"] = "Jumaytepeque",
["nai-kat"] = "Kathlamet",
["nai-klp-pro"] = "Proto-Kalapuyan",
["nai-knm"] = "Konomihu",
["nai-kry"] = "Yokuts Sungai Kings",
["nai-kum"] = "Kumeyaay",
["nai-mac"] = "Macoris",
["nai-mdu-pro"] = "Proto-Maidun",
["nai-miz-pro"] = "Proto-Mixe-Zoque",
["nai-mus-pro"] = "Proto-Muskogean",
["nai-nao"] = "Naolan",
["nai-nrs"] = "Shasta New River",
["nai-nvy"] = "Yokuts Lembah Utara",
["nai-okw"] = "Okwanuchu",
["nai-per"] = "Pericú",
["nai-pic"] = "Picuris",
["nai-plp-pro"] = "Proto-Plateau Penutian",
["nai-ply"] = "Palewyami",
["nai-pom-pro"] = "Proto-Pomo",
["nai-qng"] = "Quinigua",
["nai-sca-pro"] = "Proto-Siouan-Catawban",
["nai-sin"] = "Sinacantán",
["nai-sln"] = "Lenca El Salvador",
["nai-spt"] = "Sahaptin",
["nai-svy"] = "Yokuts Lembah Selatan",
["nai-tap"] = "Tapachultec",
["nai-taw"] = "Tawasa",
["nai-teq"] = "Tequistlatec",
["nai-tip"] = "Tipai",
["nai-tky"] = "Yokuts Tule-Kaweah",
["nai-tot-pro"] = "Proto-Totozoquean",
["nai-tsi-pro"] = "Proto-Tsimshianic",
["nai-utn-pro"] = "Proto-Utian",
["nai-wai"] = "Waikuri",
["nai-yup"] = "Yupiltepeque",
["naj"] = "Nalu",
["nak"] = "Nakanai",
["nal"] = "Nalik",
["nam"] = "Ngan'gityemerri",
["nan"] = "Min Nan",
["nan-hbl"] = "Hokkien", -- hanya dipakai di Wikikamus
["nan-tws"] = "Tiociu", -- hanya dipakai di Wikikamus
["nao"] = "Naaba",
["nap"] = "Neapolitan",
["naq"] = "Khoekhoe",
["nar"] = "Iguta",
["nas"] = "Nasioi",
["nat"] = "Hungworo",
["naw"] = "Nawuri",
["nax"] = "Nakwi",
["nay"] = "Ngarrindjeri",
["naz"] = "Nahuatl Coatepec",
["nb"] = "Norwegia Bokmål",
["nba"] = "Nyemba",
["nbb"] = "Ndoe",
["nbc"] = "Chang",
["nbd"] = "Ngbinda",
["nbe"] = "Naga Konyak",
["nbg"] = "Nagarchal",
["nbh"] = "Ngamo",
["nbi"] = "Naga Mao",
["nbj"] = "Ngarinman",
["nbk"] = "Nake",
["nbm"] = "Ngbaka Ma'bo",
["nbn"] = "Kuri",
["nbo"] = "Nkukoli",
["nbp"] = "Nnam",
["nbq"] = "Nggem",
["nbr"] = "Numana",
["nbs"] = "Isyarat Namibia",
["nbt"] = "Na",
["nbu"] = "Naga Rongmei",
["nbv"] = "Ngamambo",
["nbw"] = "Ngbandi Selatan",
["nby"] = "Ningera",
["nca"] = "Iyo",
["ncb"] = "Nikobar Tengah",
["ncc"] = "Ponam",
["ncd"] = "Nachering",
["nce"] = "Yale",
["ncf"] = "Notsi",
["ncg"] = "Nisga'a",
["nch"] = "Nahuatl Huasteca Tengah",
["nci"] = "Nahuatl Klasik",
["ncj"] = "Nahuatl Puebla Utara",
["nck"] = "Nakara",
["ncl"] = "Nahuatl Michoacán",
["ncm"] = "Nambo",
["ncn"] = "Nauna",
["nco"] = "Sibe",
["ncr"] = "Ncane",
["ncs"] = "Isyarat Nikaragua",
["nct"] = "Naga Chothe",
["ncu"] = "Chumburung",
["ncx"] = "Nahuatl Puebla Tengah",
["ncz"] = "Natchez",
["nd"] = "Ndebele Utara",
["nda"] = "Ndasa",
["ndb"] = "Kenswei Nsei",
["ndc"] = "Ndau",
["ndd"] = "Nde-Nsele-Nta",
["ndf"] = "Nadruvian",
["ndg"] = "Ndengereko",
["ndh"] = "Ndali",
["ndi"] = "Chamba Leko",
["ndj"] = "Ndamba",
["ndk"] = "Ndaka",
["ndl"] = "Ndolo",
["ndm"] = "Ndam",
["ndn"] = "Ngundi",
["ndp"] = "Ndo",
["ndq"] = "Ndombe",
["ndr"] = "Ndoola",
["nds"] = "Jerman Hilir",
["ndt"] = "Ndunga",
["ndu"] = "Dugun",
["ndv"] = "Ndut",
["ndw"] = "Ndobo",
["ndx"] = "Nduga",
["ndy"] = "Lutos",
["ndz"] = "Ndogo",
["ne"] = "Nepal",
["nea"] = "Ngad'a Timur",
["neb"] = "Toura",
["nec"] = "Nedebang",
["ned"] = "Nde-Gbite",
["nee"] = "Kumak",
["nef"] = "Nefamese",
["neg"] = "Negidal",
["neh"] = "Nyenkha",
["nej"] = "Neko",
["nek"] = "Neku",
["nem"] = "Nemi",
["nen"] = "Nengone",
["neo"] = "Ná-Meo",
["neq"] = "Mixe Tengah Utara",
["ner"] = "Yahadian",
["nes"] = "Kinnauri Bhoti",
["net"] = "Nete",
["neu"] = "Neo",
["nev"] = "Nyaheun",
["new"] = "Newar",
["nex"] = "Neme",
["ney"] = "Neyo",
["nez"] = "Nez Perce",
["nfa"] = "Dhao",
["nfd"] = "Ahwai",
["nfl"] = "Aiwoo",
["nfr"] = "Nafaanra",
["nfu"] = "Mfumte",
["ng"] = "Ndonga",
["nga"] = "Ngbaka",
["ngb"] = "Ngbandi Utara",
["ngc"] = "Ngombe (Kongo)",
["ngd"] = "Ngando (Republik Afrika Tengah)",
["nge"] = "Ngemba",
["ngf-pro"] = "Proto-Trans-Papua",
["ngg"] = "Ngbaka Manza",
["ngh"] = "Nǀuu",
["ngi"] = "Ngizim",
["ngj"] = "Ngie",
["ngk"] = "Ngalkbun",
["ngl"] = "Lomwe",
["ngm"] = "Kreol Ngatik Men's",
["ngn"] = "Ngwo",
["ngo"] = "Ngoni",
["ngp"] = "Ngulu",
["ngq"] = "Ngoreme",
["ngr"] = "Nagu",
["ngs"] = "Gvoko",
["ngt"] = "Ngeq",
["ngu"] = "Nahuatl Guerrero",
["ngv"] = "Nagumi",
["ngw"] = "Ngwaba",
["ngx"] = "Nggwahyi",
["ngy"] = "Tibea",
["ngz"] = "Ngungwel",
["nha"] = "Nhanda",
["nhb"] = "Beng",
["nhc"] = "Nahuatl Tabasco",
["nhd"] = "Chiripá",
["nhe"] = "Nahuatl Huasteca Timur",
["nhf"] = "Nhuwala",
["nhg"] = "Nahuatl Tetelcingo",
["nhh"] = "Nahari",
["nhi"] = "Nahuatl Zacatlán-Ahuacatlán-Tepetzintla",
["nhk"] = "Nahuatl Cosoleacaque",
["nhm"] = "Nahuatl Morelos",
["nhn"] = "Nahuatl Tengah",
["nho"] = "Takuu",
["nhp"] = "Nahuatl Pajapan",
["nhq"] = "Nahuatl Huaxcaleca",
["nhr"] = "Naro",
["nht"] = "Nahuatl Ometepec",
["nhu"] = "Noone",
["nhv"] = "Nahuatl Temascaltepec",
["nhw"] = "Nahuatl Huasteca Barat",
["nhx"] = "Nahuatl Mecayapan",
["nhy"] = "Nahuatl Oaxaca Utara",
["nhz"] = "Nahuatl Santa María La Alta",
["nia"] = "Nias",
["nib"] = "Nakame",
["nic-bco-pro"] = "Proto-Benue-Kongo",
["nic-bod-pro"] = "Proto-Bantoid",
["nic-eov-pro"] = "Proto-Oti-Volta Timur",
["nic-gns-pro"] = "Proto-Gurunsi",
["nic-grf-pro"] = "Proto-Grassfields",
["nic-gur-pro"] = "Proto-Gur",
["nic-jkn-pro"] = "Proto-Jukunoid",
["nic-lcr-pro"] = "Proto-Hilir Sungai Cross",
["nic-ogo-pro"] = "Proto-Ogoni",
["nic-ovo-pro"] = "Proto-Oti-Volta",
["nic-plt-pro"] = "Proto-Plateau",
["nic-pro"] = "Proto-Niger-Kongo",
["nic-ubg-pro"] = "Proto-Ubangian",
["nic-ucr-pro"] = "Proto-Hulu Sungai Cross",
["nic-vco-pro"] = "Proto-Volta-Kongo",
["nid"] = "Ngandi",
["nie"] = "Niellim",
["nif"] = "Nek",
["nig"] = "Ngalakan",
["nih"] = "Nyiha",
["nii"] = "Nii",
["nij"] = "Ngaju",
["nik"] = "Nikobar Selatan",
["nil"] = "Nila",
["nim"] = "Nilamba",
["nin"] = "Ninzo",
["nio"] = "Nganasan",
["niq"] = "Nandi",
["nir"] = "Nimboran",
["nis"] = "Nimi",
["nit"] = "Kolami Tenggara",
["niu"] = "Niuean",
["niv"] = "Nivkh",
["niw"] = "Nimo",
["nix"] = "Hema",
["niy"] = "Ngiti",
["niz"] = "Ningil",
["nja"] = "Nzanyi",
["njb"] = "Naga Nocte",
["njh"] = "Naga Lotha",
["nji"] = "Gudanji",
["njj"] = "Njen",
["njl"] = "Njalgulgule",
["njm"] = "Angami",
["njn"] = "Naga Liangmai",
["njo"] = "Ao",
["njr"] = "Njerep",
["njs"] = "Nisa",
["njt"] = "Pijin Ndyuka-Trio",
["nju"] = "Ngadjunmaya",
["njx"] = "Kunyi",
["njy"] = "Njyem",
["njz"] = "Nyishi",
["nka"] = "Nkoya",
["nkb"] = "Naga Khoibu",
["nkc"] = "Nkongho",
["nkd"] = "Koireng",
["nke"] = "Duke",
["nkf"] = "Naga Inpui",
["nkg"] = "Nekgini",
["nkh"] = "Naga Khezha",
["nki"] = "Naga Thangal",
["nkj"] = "Nakai",
["nkk"] = "Nokuku",
["nkm"] = "Namat",
["nkn"] = "Nkangala",
["nko"] = "Nkonya",
["nkp"] = "Niuatoputapu",
["nkq"] = "Nkami",
["nkr"] = "Nukuoro",
["nks"] = "Asmat Utara",
["nkt"] = "Nyika",
["nku"] = "Kulango Bouna",
["nkw"] = "Nkutu",
["nkx"] = "Nkoroo",
["nkz"] = "Nkari",
["nl"] = "Belanda",
["nla"] = "Ngombale",
["nlc"] = "Nalca",
["nle"] = "Nyala Timur",
["nlg"] = "Gela",
["nli"] = "Grangali",
["nlj"] = "Nyali",
["nlk"] = "Yali Ninia",
["nll"] = "Nihali",
["nlm"] = "Mankiyali",
["nlo"] = "Ngul",
["nlq"] = "Naga Lao",
["nlu"] = "Nchumbulu",
["nlv"] = "Nahuatl Orizaba",
["nlw"] = "Walangama",
["nlx"] = "Nahali",
["nly"] = "Nyamal",
["nlz"] = "Nalögo",
["nma"] = "Naga Maram",
["nmb"] = "Big Nambas",
["nmc"] = "Ngam",
["nmd"] = "Ndumu",
["nme"] = "Naga Mzieme",
["nmf"] = "Naga Tangkhul",
["nmg"] = "Kwasio",
["nmh"] = "Naga Monsang",
["nmi"] = "Nyam",
["nmj"] = "Ngombe (Republik Afrika Tengah)",
["nmk"] = "Namakura",
["nml"] = "Ndemli",
["nmm"] = "Manangba",
["nmn"] = "ǃXóõ",
["nmo"] = "Naga Moyon",
["nmp"] = "Nimanbur",
["nmq"] = "Nambya",
["nmr"] = "Nimbari",
["nms"] = "Letemboi",
["nmt"] = "Namonuito",
["nmu"] = "Maidu Timur Laut",
["nmv"] = "Ngamini",
["nmw"] = "Nimoa",
["nmy"] = "Namuyi",
["nmz"] = "Nawdm",
["nn"] = "Norwegia Nynorsk",
["nna"] = "Nyangumarta",
["nnb"] = "Nande",
["nnc"] = "Nancere",
["nnd"] = "Ambae Barat",
["nne"] = "Ngandyera",
["nnf"] = "Ngaing",
["nng"] = "Naga Maring",
["nnh"] = "Ngiemboon",
["nni"] = "Nuaulu Utara",
["nnj"] = "Nyangatom",
["nnk"] = "Nankina",
["nnl"] = "Naga Rengma Utara",
["nnm"] = "Namia",
["nnn"] = "Ngete",
["nnp"] = "Wancho",
["nnq"] = "Ngindo",
["nnr"] = "Narungga",
["nnt"] = "Nanticoke",
["nnu"] = "Dwang",
["nnv"] = "Nukunu",
["nnw"] = "Nuni Selatan",
["nnx"] = "Ngong",
["nny"] = "Nyangga",
["nnz"] = "Nda'nda'",
["no"] = "Norwegia",
["noa"] = "Woun Meu",
["noc"] = "Nuk",
["nod"] = "Thai Utara",
["noe"] = "Nimadi",
["nof"] = "Nomane",
["nog"] = "Nogai",
["noh"] = "Nomu",
["noi"] = "Noiri",
["noj"] = "Nonuya",
["nok"] = "Nooksack",
["nol"] = "Nomlaki",
["nom"] = "Nocamán",
["non"] = "Norse Kuno",
["nop"] = "Numanggang",
["noq"] = "Ngongo",
["nos"] = "Nisu Timur",
["not"] = "Nomatsiguenga",
["nou"] = "Ewage-Notu",
["nov"] = "Novial",
["now"] = "Nyambo",
["noy"] = "Noy",
["noz"] = "Nayi",
["npa"] = "Phu Nar",
["npb"] = "Nupbikha",
["npg"] = "Ponyo",
["nph"] = "Phom",
["npl"] = "Nahuatl Puebla Tenggara",
["npn"] = "Mondropolon",
["npo"] = "Naga Pochuri",
["nps"] = "Nipsan",
["npu"] = "Naga Puimei",
["npy"] = "Napu",
["nqg"] = "Ede Nago",
["nqk"] = "Kura Ede Nago",
["nql"] = "Ngendelengo",
["nqm"] = "Ndom",
["nqn"] = "Nen",
["nqo"] = "N'Ko",
["nqq"] = "Naga Kyan-Karyaw",
["nqy"] = "Akyaung Ari",
["nr"] = "Ndebele Selatan",
["nra"] = "Ngom",
["nrb"] = "Nara",
["nrc"] = "Noric",
["nre"] = "Naga Rengma Selatan",
["nrf"] = "Norman",
["nrg"] = "Narango",
["nri"] = "Naga Chokri",
["nrk"] = "Ngarla",
["nrl"] = "Ngarluma",
["nrm"] = "Narom",
["nrn"] = "Norn",
["nrp"] = "Picene Utara",
["nrr"] = "Norra",
["nrt"] = "Kalapuya Utara",
["nru"] = "Narua",
["nrx"] = "Ngurmbur",
["nrz"] = "Lala (Papua)",
["nsa"] = "Naga Sangtam",
["nsb"] = "Nossob Hilir",
["nsc"] = "Nshi",
["nsd"] = "Nisu Selatan",
["nse"] = "Nsenga",
["nsg"] = "Ngasa",
["nsh"] = "Ngoshie",
["nsi"] = "Isyarat Nigeria",
["nsk"] = "Naskapi",
["nsl"] = "Isyarat Norwegia",
["nsm"] = "Sema",
["nsn"] = "Nehan",
["nso"] = "Sotho Utara",
["nsp"] = "Isyarat Nepal",
["nsq"] = "Miwok Sierra Utara",
["nsr"] = "Isyarat Maritim",
["nss"] = "Nali",
["nst"] = "Tangsa",
["nsu"] = "Nahuatl Sierra Negra",
["nsv"] = "Nisu Barat Daya",
["nsw"] = "Navut",
["nsx"] = "Nsongo",
["nsy"] = "Nasal",
["nsz"] = "Nisenan",
["ntd"] = "Tidung Sesayap",
["nte"] = "Nathembo",
["ntg"] = "Ngantangarra",
["nti"] = "Natioro",
["ntj"] = "Ngaanyatjarra",
["ntk"] = "Ikoma",
["ntm"] = "Nateni",
["nto"] = "Ntomba",
["ntp"] = "Tepehuan Utara",
["ntr"] = "Delo",
["nts"] = "Natagaimas",
["ntu"] = "Natügu",
["ntw"] = "Nottoway",
["ntx"] = "Somra",
["nty"] = "Mantsi",
["nua"] = "Yuaga",
["nub-har"] = "Haraza",
["nub-pro"] = "Proto-Nubia",
["nuc"] = "Nukuini",
["nud"] = "Ngala",
["nue"] = "Ngundu",
["nuf"] = "Nusu",
["nug"] = "Nungali",
["nuh"] = "Ndunda",
["nui"] = "Ngumbi",
["nuj"] = "Nyole (Uganda)",
["nuk"] = "Nootka",
["nul"] = "Nusa Laut",
["num"] = "Niuafo'ou",
["nun"] = "Anong",
["nuo"] = "Nguôn",
["nup"] = "Nupe",
["nuq"] = "Nukumanu",
["nur"] = "Nuguria",
["nus"] = "Nuer",
["nut"] = "Nung",
["nuu"] = "Ngbundu",
["nuv"] = "Nuni Utara",
["nuw"] = "Nguluwan",
["nux"] = "Mehek",
["nuy"] = "Nunggubuyu",
["nuz"] = "Nahuatl Tlamacazapa",
["nv"] = "Navajo",
["nvh"] = "Nasarian",
["nvm"] = "Namiae",
["nvo"] = "Nyokon",
["nwa"] = "Nawathinehena",
["nwb"] = "Nyabwa",
["nwc"] = "Newar Klasik",
["nwe"] = "Ngwe",
["nwi"] = "Tanna Barat Daya",
["nwm"] = "Nyamusa-Molo",
["nwo"] = "Nauo",
["nwr"] = "Nawaru",
["nwx"] = "Newar Pertengahan",
["nwy"] = "Nottoway-Meherrin",
["nxa"] = "Nauete",
["nxd"] = "Ngando (Kongo)",
["nxe"] = "Nage",
["nxg"] = "Ngadha",
["nxi"] = "Nindi",
["nxl"] = "Nuaulu Selatan",
["nxm"] = "Numidia",
["nxn"] = "Ngawun",
["nxo"] = "Ndambomo",
["nxq"] = "Naxi",
["nxr"] = "Ninggerum",
["nxu"] = "Narau",
["nxx"] = "Nafri",
["ny"] = "Chichewa",
["nyb"] = "Nyangbo",
["nyc"] = "Nyanga-li",
["nyd"] = "Nyole (Kenya)",
["nye"] = "Nyengo",
["nyf"] = "Giryama",
["nyg"] = "Nyindu",
["nyh"] = "Nyigina",
["nyi"] = "Nyimang",
["nyj"] = "Nyanga (Kongo)",
["nyk"] = "Nyaneka",
["nyl"] = "Nyeu",
["nym"] = "Nyamwezi",
["nyn"] = "Nyankole",
["nyo"] = "Nyoro",
["nyp"] = "Nyang'i",
["nys"] = "Nyunga",
["nyt"] = "Nyawaygi",
["nyu"] = "Nyungwe",
["nyv"] = "Nyulnyul",
["nyw"] = "Nyaw",
["nyx"] = "Nganyaywana",
["nyy"] = "Nyakyusa",
["nza"] = "Mbembe Tigon",
["nzb"] = "Njebi",
["nzd"] = "Nzadi",
["nzi"] = "Nzima",
["nzk"] = "Nzakara",
["nzm"] = "Naga Zeme",
["nzs"] = "Isyarat Selandia Baru",
["nzu"] = "Teke Tengah",
["nzy"] = "Nzakambay",
["nzz"] = "Dogon Nanga Dama",
["oaa"] = "Orok",
["oac"] = "Oroch",
["oav"] = "Avar Kuno",
["obi"] = "Obispeño",
["obk"] = "Bontoc Selatan",
["obl"] = "Oblo",
["obm"] = "Moabite",
["obo"] = "Manobo Obo",
["obr"] = "Burma Kuno",
["obt"] = "Breton Kuno",
["obu"] = "Obulom",
["oc"] = "Occitan",
["oca"] = "Ocaina",
["och"] = "Tionghoa Kuno",
["oco"] = "Kernowek Kuno",
["ocu"] = "Tlahuica",
["oda"] = "Odut",
["odk"] = "Od",
["odt"] = "Belanda Kuno",
["odu"] = "Odual",
["ofo"] = "Ofo",
["ofs"] = "Frisia Kuno",
["ofu"] = "Efutop",
["ogb"] = "Ogbia",
["ogc"] = "Ogbah",
["oge"] = "Georgia Kuno",
["ogg"] = "Ogbogolo",
["ogo"] = "Khana",
["ogu"] = "Ogbronuagum",
["ohu"] = "Hungaria Kuno",
["oia"] = "Oirata",
["oin"] = "One Inebu",
["oj"] = "Ojibwe",
["ojb"] = "Ojibwa Barat Laut",
["ojc"] = "Ojibwa Tengah",
["ojg"] = "Ojibwa Timur",
["ojp"] = "Jepang Kuno",
["ojs"] = "Ojibwa Severn",
["ojv"] = "Jawa Ontong",
["ojw"] = "Ojibwa Barat",
["oka"] = "Okanagan",
["okb"] = "Okobo",
["okd"] = "Okodia",
["oke"] = "Okpe (Edo Barat Daya)",
["okg"] = "Kok-Paponk",
["okh"] = "Koresh-e Rostam",
["oki"] = "Okiek",
["okj"] = "Oko-Juwoi",
["okk"] = "One Kwamtim",
["okl"] = "Isyarat Kent Kuno",
["okm"] = "Korea Pertengahan",
["okn"] = "Oki-No-Erabu",
["oko"] = "Korea Kuno",
["okr"] = "Kirike",
["oks"] = "Oko-Eni-Osayen",
["oku"] = "Oku",
["okv"] = "Orokaiva",
["okx"] = "Okpe (Edo Barat Laut)",
["okz"] = "Khmer Kuno",
["old"] = "Mochi",
["ole"] = "Olekha",
["olm"] = "Oloma",
["olo"] = "Livvi",
["olr"] = "Olrat",
["olt"] = "Lithuania Kuno",
["olu"] = "Kuvale",
["om"] = "Oromo",
["oma"] = "Omaha-Ponca",
["omb"] = "Omba",
["omc"] = "Mochica",
["omg"] = "Omagua",
["omi"] = "Omi",
["omk"] = "Omok",
["oml"] = "Ombo",
["omn"] = "Minoan",
["omo"] = "Utarmbung",
["omp"] = "Manipuri Kuno",
["omq-cha-pro"] = "Proto-Chatino",
["omq-maz-pro"] = "Proto-Mazatec",
["omq-mix-pro"] = "Proto-Mixtecan",
["omq-mxt-pro"] = "Proto-Mixtec",
["omq-otp-pro"] = "Proto-Oto-Pamean",
["omq-pro"] = "Proto-Oto-Manguean",
["omq-tel"] = "Mixtec Teposcolula",
["omq-teo"] = "Chatino Teojomulco",
["omq-tri-pro"] = "Proto-Trique",
["omq-zap-pro"] = "Proto-Zapotecan",
["omq-zpc-pro"] = "Proto-Zapotec",
["omr"] = "Marathi Kuno",
["omt"] = "Omotik",
["omu"] = "Omurano",
["omv-aro-pro"] = "Proto-Aroid",
["omv-diz-pro"] = "Proto-Dizoid",
["omv-pro"] = "Proto-Omotic",
["omw"] = "Tairora Selatan",
["omx"] = "Mon Kuno",
["ona"] = "Selk'nam",
["onb"] = "Lingao",
["one"] = "Oneida",
["ong"] = "Olo",
["oni"] = "Onin",
["onj"] = "Onjob",
["onk"] = "One Kabore",
["onn"] = "Onobasulu",
["ono"] = "Onondaga",
["onp"] = "Sartang",
["onr"] = "One Utara",
["ons"] = "Ono",
["ont"] = "Ontenu",
["onu"] = "Unua",
["onw"] = "Nubia Kuno",
["onx"] = "Pijin Onin",
["ood"] = "O'odham",
["oog"] = "Ong",
["oon"] = "Önge",
["oor"] = "Oorlams",
["oos"] = "Ossetik Kuno",
["opa"] = "Okpamheri",
["opk"] = "Kopkaka",
["opm"] = "Oksapmin",
["opo"] = "Opao",
["opt"] = "Opata",
["opy"] = "Ofayé",
["or"] = "Oriya",
["ora"] = "Oroha",
["ore"] = "Orejón",
["org"] = "Oring",
["orh"] = "Oroqen",
["oro"] = "Orokolo",
["orr"] = "Oruma",
["ort"] = "Adiwasi Oriya",
["oru"] = "Ormuri",
["orv"] = "Slavik Timur Kuno",
["orw"] = "Oro Win",
["orx"] = "Oro",
["orz"] = "Ormu",
["os"] = "Ossetia",
["os-pro"] = "Proto-Ossetic",
["osa"] = "Osage",
["osc"] = "Oscan",
["osi"] = "Using",
["osn"] = "Sunda Kuno",
["oso"] = "Ososo",
["osp"] = "Spanyol Kuno",
["ost"] = "Osatu",
["osu"] = "One Selatan",
["osx"] = "Saxon Kuno",
["ota"] = "Turki Ottoman",
["otb"] = "Tibet Kuno",
["otd"] = "Ot Danum",
["ote"] = "Otomi Mezquital",
["oti"] = "Oti",
["otk"] = "Turkik Kuno",
["otl"] = "Otomi Tilapa",
["otm"] = "Otomi Pegunungan Timur",
["otn"] = "Otomi Tenango",
["oto-otm-pro"] = "Proto-Otomi",
["oto-pro"] = "Proto-Otomian",
["otq"] = "Otomi Querétaro",
["otr"] = "Otoro",
["ots"] = "Otomi Estado de México",
["ott"] = "Otomi Temoaya",
["otu"] = "Otuke",
["otw"] = "Ottawa",
["otx"] = "Otomi Texcatepec",
["oty"] = "Tamil Kuno",
["otz"] = "Otomi Ixtenco",
["oub"] = "Glio-Oubi",
["oue"] = "Oune",
["oui"] = "Uighur Kuno",
["oum"] = "Ouma",
["ovd"] = "Elfdalia",
["owi"] = "Owiniga",
["owl"] = "Welsh Kuno",
["oyb"] = "Oy",
["oyd"] = "Oyda",
["oym"] = "Wayampi",
["oyy"] = "Oya'oya",
["ozm"] = "Koonzime",
["pa"] = "Punjab",
["paa-kom"] = "Kómnzo",
["paa-kwn"] = "Kuwani",
["paa-nha-pro"] = "Proto-Halmahera Utara",
["paa-nun"] = "Nungon",
["pab"] = "Pareci",
["pac"] = "Pacoh",
["pad"] = "Paumarí",
["pae"] = "Pagibete",
["paf"] = "Paranawát",
["pag"] = "Pangasinan",
["pah"] = "Tenharim",
["pai"] = "Pe",
["pak"] = "Parakanã",
["pal"] = "Persia Pertengahan",
["pam"] = "Kapampangan",
["PAN"] = "Proto-Austronesia",
["pao"] = "Paiute Utara",
["pap"] = "Papiamentu",
["paq"] = "Parya",
["par"] = "Panamint",
["pas"] = "Papasena",
["pat"] = "Papitalai",
["pau"] = "Palauan",
["pav"] = "Wari'",
["paw"] = "Pawnee",
["pax"] = "Pankararé",
["pay"] = "Pech",
["paz"] = "Pankararú",
["pbb"] = "Páez",
["pbc"] = "Patamona",
["pbe"] = "Popoloca Mezontla",
["pbf"] = "Popoloca Coyotepec",
["pbg"] = "Paraujano",
["pbh"] = "Panare",
["pbi"] = "Podoko",
["pbl"] = "Mak (Nigeria)",
["pbm"] = "Mazatec Puebla",
["pbn"] = "Kpasam",
["pbo"] = "Papel",
["pbp"] = "Badyara",
["pbr"] = "Pangwa",
["pbs"] = "Pame Tengah",
["pbv"] = "Pnar",
["pby"] = "Pyu",
["pca"] = "Popoloca Santa Inés Ahuatempan",
["pcb"] = "Pear",
["pcc"] = "Bouyei",
["pcd"] = "Picard",
["pce"] = "Palaung Ruching",
["pcf"] = "Paliyan",
["pcg"] = "Paniya",
["pch"] = "Pardhan",
["pci"] = "Duruwa",
["pcj"] = "Parenga",
["pck"] = "Paite",
["pcl"] = "Pardhi",
["pcm"] = "Pijin Nigeria",
["pcn"] = "Piti",
["pcp"] = "Pacahuara",
["pcw"] = "Pyapun",
["pda"] = "Anam",
["pdc"] = "Jerman Pennsylvania",
["pdi"] = "Pa Di",
["pdn"] = "Fedan",
["pdo"] = "Padoe",
["pdt"] = "Plautdietsch",
["pdu"] = "Kayan",
["pea"] = "Indonesia Peranakan",
["peb"] = "Pomo Timur",
["ped"] = "Mala (Papua)",
["pee"] = "Taje",
["pef"] = "Pomo Timur Laut",
["peg"] = "Pengo",
["peh"] = "Bonan",
["pei"] = "Chichimeca-Jonaz",
["pej"] = "Pomo Utara",
["pek"] = "Penchal",
["pel"] = "Pekal",
["pem"] = "Phende",
["peo"] = "Persia Kuno",
["pep"] = "Kunja",
["peq"] = "Pomo Selatan",
["pev"] = "Pémono",
["pex"] = "Petats",
["pey"] = "Peco",
["pez"] = "Penan Timur",
["pfa"] = "Pááfang",
["pfe"] = "Peere",
["pga"] = "Arab Juba",
["pgd"] = "Gandhari",
["pgg"] = "Pangwali",
["pgi"] = "Pagi",
["pgk"] = "Rerep",
["pgl"] = "Irlandia Primitif",
["pgn"] = "Paelignian",
["pgs"] = "Pangseng",
["pgu"] = "Isam",
["pgz"] = "Isyarat Papua Nugini",
["pha"] = "Pa-Hng",
["phd"] = "Phudagi",
["phg"] = "Phuong",
["phh"] = "Phukha",
["phi-din"] = "Agta Dinapigue",
["phi-kal-pro"] = "Proto-Kalamian",
["phi-nag"] = "Agta Nagtipunan",
["phi-pro"] = "Proto-Filipina",
["phk"] = "Phake",
["phl"] = "Phalura",
["phm"] = "Phimbi",
["phn"] = "Fenisia",
["pho"] = "Phunoi",
["phq"] = "Phana'",
["phr"] = "Pahari-Potwari",
["pht"] = "Phu Thai",
["phu"] = "Phuan",
["phv"] = "Pahlavani",
["phw"] = "Phangduwali",
["pi"] = "Pali",
["pia"] = "Pima Bajo",
["pib"] = "Yine",
["pic"] = "Pinji",
["pid"] = "Piaroa",
["pie"] = "Piro",
["pif"] = "Pingelapese",
["pig"] = "Pisabo",
["pih"] = "Pitcairn-Norfolk",
["pii"] = "Pini",
["pij"] = "Pijao",
["pil"] = "Yom",
["pim"] = "Powhatan",
["pin"] = "Piame",
["pio"] = "Piapoco",
["pip"] = "Pero",
["pir"] = "Piratapuyo",
["pis"] = "Pijin",
["pit"] = "Pitta-Pitta",
["piu"] = "Pintupi-Luritja",
["piv"] = "Pileni",
["piw"] = "Pimbwe",
["pix"] = "Piu",
["piy"] = "Piya-Kwonci",
["piz"] = "Pije",
["pjt"] = "Pitjantjatjara",
["pka"] = "Prakrit Ardhamagadhi",
["pkb"] = "Kipfokomo",
["pkc"] = "Baekje",
["pkg"] = "Pak-Tong",
["pkh"] = "Pankhu",
["pkn"] = "Pakanha",
["pko"] = "Pökoot",
["pkp"] = "Pukapukan",
["pkr"] = "Kurumba Attapady",
["pks"] = "Isyarat Pakistan",
["pkt"] = "Maleng",
["pku"] = "Paku",
["pl"] = "Polandia",
["pla"] = "Miani",
["plb"] = "Polonombauk",
["plc"] = "Palawano Tengah",
["ple"] = "Palu'e",
["plg"] = "Pilagá",
["plh"] = "Paulohi",
["plj"] = "Polci",
["plk"] = "Shina Kohistani",
["pll"] = "Palaung Shwe",
["pln"] = "Palenquero",
["plo"] = "Popoluca Oluta",
["plq"] = "Palaic",
["plr"] = "Senoufo Palaka",
["pls"] = "Popoloca San Marcos Tlalcoyalco",
["plu"] = "Palikur",
["plv"] = "Palawano Barat Daya",
["plw"] = "Palawano Brooke's Point",
["ply"] = "Bolyu",
["plz"] = "Paluan",
["pma"] = "Paama",
["pmb"] = "Pambia",
["pmd"] = "Pallanganmiddang",
["pme"] = "Pwaamei",
["pmf"] = "Pamona",
["pmh"] = "Prakrit Maharastri",
["pmi"] = "Pumi Utara",
["pmj"] = "Pumi Selatan",
["pmk"] = "Pamlico",
["pml"] = "Sabir",
["pmm"] = "Pol",
["pmn"] = "Pam",
["pmo"] = "Pom",
["PMP"] = "Proto-Melayu-Polinesia",
["pmq"] = "Pame Utara",
["pmr"] = "Paynamar",
["pms"] = "Piedmont",
["pmt"] = "Tuamotuan",
["pmu"] = "Panjabi Mirpur",
["pmw"] = "Miwok Plains",
["pmx"] = "Naga Poumei",
["pmy"] = "Melayu Papua",
["pmz"] = "Pame Selatan",
["pna"] = "Punan Bah-Biau",
["pnb"] = "Panjabi Barat",
["pnc"] = "Pannei",
["pnd"] = "Mpinda",
["pne"] = "Penan Barat",
["png"] = "Pongu",
["pnh"] = "Penrhyn",
["pni"] = "Aoheng",
["pnj"] = "Pinjarup",
["pnk"] = "Paunaca",
["pnl"] = "Paleni",
["pnm"] = "Punan Batu",
["pnn"] = "Pinai-Hagahai",
["pno"] = "Panobo",
["pnp"] = "Pancana",
["pnq"] = "Pana (Afrika Barat)",
["pnr"] = "Panim",
["pns"] = "Ponosakan",
["pnt"] = "Yunani Pontic",
["pnu"] = "Bunu Jiongnai",
["pnv"] = "Pinigura",
["pnw"] = "Panyjima",
["pnx"] = "Phong-Kniang",
["pny"] = "Pinyin",
["pnz"] = "Pana (Afrika Tengah)",
["poc"] = "Poqomam",
["poe"] = "Popoloca San Juan Atzingo",
["pof"] = "Poke",
["pog"] = "Potiguára",
["poh"] = "Poqomchi'",
["poi"] = "Popoluca Pegunungan",
["pok"] = "Pokangá",
["pom"] = "Pomo Tenggara",
["pon"] = "Pohnpei",
["poo"] = "Pomo Tengah",
["pop"] = "Pwapwa",
["poq"] = "Popoluca Texistepec",
["pos"] = "Popoluca Sayula",
["pot"] = "Potawatomi",
["pov"] = "Kreol Guinea-Bissau",
["pow"] = "Popoloca San Felipe Otlaltepec",
["pox"] = "Polabia",
["poy"] = "Pogolo",
["poz-abi"] = "Abai",
["poz-bal"] = "Baliledo",
["poz-btk-pro"] = "Proto-Bungku-Tolaki",
["poz-cet-pro"] = "Proto-Melayu-Polinesia Tengah Timur",
["poz-hce-pro"] = "Proto-Halmahera-Cenderawasih",
["poz-lgx-pro"] = "Proto-Lampung",
["poz-mcm-pro"] = "Proto-Melayu-Chamik",
["poz-mly-pro"] = "Proto-Melayik",
["poz-msa-pro"] = "Proto-Melayu-Sumbawa",
["poz-oce-pro"] = "Proto-Oseanik",
["poz-pep-pro"] = "Proto-Polinesia Timur",
["poz-pnp-pro"] = "Proto-Polinesia Inti",
["poz-pol-pro"] = "Proto-Polinesia",
["poz-pro"] = "Proto-Melayu-Polinesia",
["poz-sml"] = "Melayu Sarawak",
["poz-ssw-pro"] = "Proto-Sulawesi Selatan",
["poz-sus-pro"] = "Proto-Sunda-Sulawesi",
["poz-swa-pro"] = "Proto-Sarawak Utara",
["poz-ter"] = "Melayu Terengganu",
["ppa"] = "Pao",
["ppe"] = "Papi",
["ppi"] = "Paipai",
["ppk"] = "Uma",
["ppl"] = "Pipil",
["ppm"] = "Papuma",
["ppn"] = "Papapana",
["ppo"] = "Folopa",
["ppq"] = "Pei",
["pps"] = "Popoloca San Luís Temalacayuca",
["ppt"] = "Pa",
["ppu"] = "Papora",
["pqa"] = "Pa'a",
["pqe-pro"] = "Proto-Melayu-Polinesia Timur",
["pqm"] = "Malecite-Passamaquoddy",
["pra-niy"] = "Prakrit Niya",
["prc"] = "Parachi",
["pre"] = "Principense",
["prf"] = "Paranan",
["prg"] = "Prusia Kuno",
["prh"] = "Porohanon",
["pri"] = "Paicî",
["prk"] = "Parauk",
["prl"] = "Isyarat Peru",
["prm"] = "Kibiri",
["prn"] = "Prasuni",
["pro"] = "Occitan Kuno",
["prq"] = "Ashéninka Perené",
["prr"] = "Puri",
["prt"] = "Phai",
["pru"] = "Puragi",
["prw"] = "Parawen",
["prx"] = "Purik",
["prz"] = "Isyarat Providencia",
["ps"] = "Pashto",
["psa"] = "Awyu Asue",
["psc"] = "Isyarat Persia",
["psd"] = "Isyarat Plains Indian",
["pse"] = "Melayu Barisan Selatan",
["psg"] = "Isyarat Penang",
["psh"] = "Pashayi Barat Daya",
["psi"] = "Pashayi Tenggara",
["psl"] = "Isyarat Puerto Riko",
["psm"] = "Pauserna",
["psn"] = "Panasuan",
["pso"] = "Isyarat Polandia",
["psp"] = "Isyarat Filipina",
["psq"] = "Pasi",
["psr"] = "Isyarat Portugis",
["pss"] = "Kaulong",
["psu"] = "Prakrit Sauraseni",
["psw"] = "Port Sandwich",
["psy"] = "Piscataway",
["pt"] = "Portugis",
["pta"] = "Pai Tavytera",
["pth"] = "Pataxó Hã-Ha-Hãe",
["pti"] = "Pintiini",
["ptn"] = "Patani",
["pto"] = "Zo'é",
["ptp"] = "Patep",
["ptq"] = "Pattapu",
["ptr"] = "Piamatsina",
["ptt"] = "Enrekang",
["ptu"] = "Bambam",
["ptv"] = "Port Vato",
["ptw"] = "Pentlatch",
["pty"] = "Pathiya",
["pua"] = "Purepecha",
["pub"] = "Purum",
["puc"] = "Punan Merap",
["pud"] = "Punan Aput",
["pue"] = "Puelche",
["puf"] = "Punan Merah",
["pug"] = "Phuie",
["pui"] = "Puinave",
["puj"] = "Punan Tubu",
["pum"] = "Puma",
["puo"] = "Puoc",
["pup"] = "Pulabu",
["puq"] = "Puquina",
["pur"] = "Puruborá",
["put"] = "Putoh",
["puu"] = "Punu",
["puw"] = "Puluwat",
["pux"] = "Puare",
["puy"] = "Purisimeño",
["pwa"] = "Pawaia",
["pwb"] = "Panawa",
["pwg"] = "Gapapaiwa",
["pwi"] = "Patwin",
["pwm"] = "Molbog",
["pwn"] = "Paiwan",
["pwo"] = "Pwo Barat",
["pwr"] = "Powari",
["pww"] = "Pwo Utara",
["pxm"] = "Mixe Quetzaltepec",
["pye"] = "Pye Krumen",
["pym"] = "Fyam",
["pyn"] = "Poyanáwa",
["pys"] = "Isyarat Paraguay",
["pyu"] = "Puyuma",
["pyx"] = "Tircul",
["pyy"] = "Pyen",
["pzh"] = "Pazeh",
["pzn"] = "Naga Para",
["qfa-adm-pro"] = "Proto-Great Andaman",
["qfa-bet-pro"] = "Proto-Be-Tai",
["qfa-cka-pro"] = "Proto-Chukotko-Kamchatka",
["qfa-hur-pro"] = "Proto-Hurro-Urartia",
["qfa-kad-pro"] = "Proto-Kadu",
["qfa-kms-pro"] = "Proto-Kam-Sui",
["qfa-kor-pro"] = "Proto-Korea",
["qfa-kra-pro"] = "Proto-Kra",
["qfa-lic-pro"] = "Proto-Hlai",
["qfa-onb-pro"] = "Proto-Be",
["qfa-ong-pro"] = "Proto-Ongan",
["qfa-tak-pro"] = "Proto-Kra-Dai",
["qfa-xgx-tuh"] = "Tuyuhun",
["qfa-xgx-tuo"] = "Tuoba",
["qfa-xgx-wuh"] = "Wuhuan",
["qfa-xgx-xbi"] = "Xianbei",
["qfa-yen-pro"] = "Proto-Yenisei",
["qfa-yuk-pro"] = "Proto-Yukaghir",
["qu"] = "Quechua",
["qua"] = "Quapaw",
["quc"] = "K'iche'",
["qui"] = "Quileute",
["qum"] = "Sipakapense",
["qun"] = "Quinault",
["quq"] = "Quinqui",
["quv"] = "Sacapulteco",
["qvy"] = "Queyu",
["qwc"] = "Quechua Klasik",
["qwe-kch"] = "Kichwa",
["qwm"] = "Kipchak",
["qwt"] = "Kwalhioqua-Tlatskanai",
["qxs"] = "Qiang Selatan",
["qya"] = "Quenya",
["qyp"] = "Quiripi",
["raa"] = "Dungmali",
["rab"] = "Chamling",
["rac"] = "Rasawa",
["rad"] = "Rade",
["raf"] = "Meohang Barat",
["rag"] = "Logooli",
["rah"] = "Rabha",
["rai"] = "Ramoaaina",
["raj"] = "Rajasthani",
["rak"] = "Tulu-Bohuai",
["ral"] = "Ralte",
["ram"] = "Canela",
["ran"] = "Riantana",
["rao"] = "Rao",
["rap"] = "Rapa Nui",
["raq"] = "Saam",
["rar"] = "Rarotongan",
["ras"] = "Tegali",
["rat"] = "Razajerdi",
["rau"] = "Raute",
["rav"] = "Sampang",
["raw"] = "Rawang",
["rax"] = "Rang",
["ray"] = "Rapa",
["raz"] = "Rahambuu",
["rbb"] = "Palaung Rumai",
["rbk"] = "Bontoc Utara",
["rbl"] = "Bikol Miraya",
["rcf"] = "Kreol Prancis Réunion",
["rdb"] = "Rudbari",
["rea"] = "Rerau",
["reb"] = "Rembong",
["ree"] = "Kayan Rejang",
["reg"] = "Kara (Tanzania)",
["rei"] = "Reli",
["rej"] = "Rejang",
["rel"] = "Rendille",
["rem"] = "Remo",
["ren"] = "Rengao",
["rer"] = "Rer Bare",
["res"] = "Reshe",
["ret"] = "Retta",
["rey"] = "Reyesano",
["rga"] = "Roria",
["rge"] = "Yunani Romani",
["rgk"] = "Rangkas",
["rgn"] = "Romagnol",
["rgr"] = "Resígaro",
["rgs"] = "Roglai Selatan",
["rgu"] = "Ringgou",
["rhg"] = "Rohingya",
["rhp"] = "Yahang",
["ria"] = "Reang",
["rif"] = "Tarifit",
["ril"] = "Riang",
["rim"] = "Nyaturu",
["rin"] = "Nungu",
["rir"] = "Ribun",
["rit"] = "Ritarungo",
["riu"] = "Riung",
["rjg"] = "Rajong",
["rji"] = "Raji",
["rjs"] = "Rajbanshi",
["rka"] = "Kraol",
["rkb"] = "Rikbaktsa",
["rkh"] = "Rakahanga-Manihiki",
["rki"] = "Rakhine",
["rkm"] = "Marka",
["rkt"] = "Kamta",
["rkw"] = "Arakwal",
["rm"] = "Romansch",
["rma"] = "Rama",
["rmb"] = "Rembarunga",
["rmc"] = "Romani Karpathia",
["rmd"] = "Denmark Traveller",
["rme"] = "Angloromani",
["rmf"] = "Romani Kalo Finlandia",
["rmg"] = "Norwegia Traveller",
["rmh"] = "Murkim",
["rmi"] = "Lomavren",
["rmk"] = "Romkun",
["rml"] = "Romani Baltik",
["rmm"] = "Roma",
["rmn"] = "Romani Balkan",
["rmo"] = "Romani Sinte",
["rmp"] = "Rempi",
["rmq"] = "Caló",
["rms"] = "Isyarat Romania",
["rmt"] = "Domari",
["rmu"] = "Romani Tavringer",
["rmv"] = "Romanova",
["rmw"] = "Romani Welsh",
["rmx"] = "Romam",
["rmy"] = "Romani Vlax",
["rmz"] = "Marma",
["rnd"] = "Ruwund",
["rng"] = "Ronga",
["rnl"] = "Ranglong",
["rnn"] = "Roon",
["rnp"] = "Rongpo",
["rnw"] = "Rungwa",
["ro"] = "Romania",
["roa-ang"] = "Angevin",
["roa-bbn"] = "Bourbonnais-Berrichon",
["roa-brg"] = "Bourguignon",
["roa-cha"] = "Champenois",
["roa-fcm"] = "Franc-Comtois",
["roa-gal"] = "Gallo",
["roa-leo"] = "Leon",
["roa-lor"] = "Lorrain",
["roa-oan"] = "Navarro-Aragon",
["roa-oca"] = "Katala Kuno",
["roa-ole"] = "Leon Kuno",
["roa-opt"] = "Galisia-Portugis Kuno",
["roa-orl"] = "Orléan",
["roa-poi"] = "Poitevin-Saintongeais",
["roa-tar"] = "Tarantino",
["roa-tou"] = "Tourangeau",
["rob"] = "Tae'",
["roc"] = "Roglai Cacgia",
["rod"] = "Rogo",
["roe"] = "Ronji",
["rof"] = "Rombo",
["rog"] = "Roglai Utara",
["rol"] = "Romblomanon",
["rom"] = "Romani",
["roo"] = "Rotokas",
["rop"] = "Kriol",
["ror"] = "Rongga",
["rou"] = "Runga",
["row"] = "Dela-Oenale",
["rpn"] = "Repanbitip",
["rpt"] = "Rapting",
["rri"] = "Ririo",
["rro"] = "Roro",
["rrt"] = "Arritinngithigh",
["rsb"] = "Romano-Serbia",
["rsl"] = "Isyarat Rusia",
["rsm"] = "Isyarat Miriwoong",
["rtc"] = "Rungtu",
["rth"] = "Ratahan",
["rtm"] = "Rotuman",
["rtw"] = "Rathawi",
["ru"] = "Rusia",
["rub"] = "Gungu",
["ruc"] = "Ruuli",
["rue"] = "Rusyn",
["ruf"] = "Luguru",
["rug"] = "Roviana",
["ruh"] = "Ruga",
["rui"] = "Rufiji",
["ruk"] = "Che",
["ruo"] = "Istro-Romania",
["rup"] = "Aromania",
["ruq"] = "Megleno-Romania",
["rut"] = "Rutul",
["ruu"] = "Lobu Lanas",
["ruy"] = "Mala (Nigeria)",
["ruz"] = "Ruma",
["rw"] = "Rwanda-Rundi",
["rwa"] = "Rawo",
["rwk"] = "Rwa",
["rwm"] = "Amba",
["rwo"] = "Rawa",
["rxd"] = "Ngardi",
["rxw"] = "Karuwali",
["ryn"] = "Amami-Oshima Utara",
["rys"] = "Yaeyama",
["ryu"] = "Okinawa",
["rzh"] = "Razihi",
["sa"] = "Sanskerta",
["saa"] = "Saba",
["sab"] = "Buglere",
["sac"] = "Fox",
["sad"] = "Sandawe",
["sae"] = "Sabanê",
["saf"] = "Safaliba",
["sah"] = "Yakut",
["sai-ajg"] = "Ajagua",
["sai-all"] = "Allentiac",
["sai-and"] = "Andoquero",
["sai-ayo"] = "Ayomán",
["sai-bae"] = "Baenan",
["sai-bag"] = "Bagua",
["sai-bet"] = "Betoi",
["sai-bor-pro"] = "Proto-Boran",
["sai-cac"] = "Cacán",
["sai-caq"] = "Caranqui",
["sai-car-pro"] = "Proto-Cariban",
["sai-cat"] = "Catacao",
["sai-cer-pro"] = "Proto-Cerrado",
["sai-chi"] = "Chirino",
["sai-chn"] = "Chaná",
["sai-chp"] = "Chapacura",
["sai-chr"] = "Charrua",
["sai-chu"] = "Churuya",
["sai-cje-pro"] = "Proto-Jê Tengah",
["sai-cmg"] = "Comechingon",
["sai-cno"] = "Chono",
["sai-cnr"] = "Cañari",
["sai-coe"] = "Coeruna",
["sai-col"] = "Colán",
["sai-cop"] = "Copallén",
["sai-crd"] = "Puri Coroado",
["sai-ctq"] = "Catuquinaru",
["sai-cul"] = "Culli",
["sai-cva"] = "Cueva",
["sai-esm"] = "Esmeralda",
["sai-ewa"] = "Ewarhuyana",
["sai-gam"] = "Gamela",
["sai-gay"] = "Gayón",
["sai-gmo"] = "Guamo",
["sai-gue"] = "Güenoa",
["sai-hau"] = "Haush",
["sai-hoc-pro"] = "Proto-Huitoto-Ocaina",
["sai-jee-pro"] = "Proto-Jê",
["sai-jko"] = "Jeikó",
["sai-jrj"] = "Jirajara",
["sai-kat"] = "Katembri",
["sai-mal"] = "Malalí",
["sai-mar"] = "Maratino",
["sai-mat"] = "Matanawi",
["sai-mcn"] = "Mocana",
["sai-men"] = "Menien",
["sai-mil"] = "Millcayac",
["sai-mlb"] = "Malibu",
["sai-msk"] = "Masakará",
["sai-muc"] = "Mucuchí",
["sai-mue"] = "Muellama",
["sai-muz"] = "Muzo",
["sai-mys"] = "Maynas",
["sai-nat"] = "Natú",
["sai-nje-pro"] = "Proto-Jê Utara",
["sai-opo"] = "Opón",
["sai-oto"] = "Otomaco",
["sai-pal"] = "Palta",
["sai-pam"] = "Pamigua",
["sai-par"] = "Paratió",
["sai-pnz"] = "Panzaleo",
["sai-prh"] = "Puruhá",
["sai-ptg"] = "Patagón",
["sai-pur"] = "Purukotó",
["sai-pyg"] = "Payaguá",
["sai-pyk"] = "Pykobjê",
["sai-qmb"] = "Quimbaya",
["sai-qtm"] = "Quitemo",
["sai-rab"] = "Rabona",
["sai-ram"] = "Ramanos",
["sai-sac"] = "Sácata",
["sai-san"] = "Sanaviron",
["sai-sap"] = "Sapará",
["sai-sec"] = "Sechura",
["sai-sin"] = "Sinúfana",
["sai-sje-pro"] = "Proto-Jê Selatan",
["sai-tab"] = "Tabancale",
["sai-tal"] = "Tallán",
["sai-tap"] = "Tapayuna",
["sai-tar-pro"] = "Proto-Taranoan",
["sai-teu"] = "Teushen",
["sai-tim"] = "Timote",
["sai-tpr"] = "Taparita",
["sai-trr"] = "Tarairiú",
["sai-wai"] = "Waitaká",
["sai-way"] = "Wayumará",
["sai-wit-pro"] = "Proto-Witotoan",
["sai-wnm"] = "Wanham",
["sai-xoc"] = "Xocó",
["sai-yao"] = "Yao (Amerika Selatan)",
["sai-yar"] = "Yarumá",
["sai-yri"] = "Yuri",
["sai-yup"] = "Yupua",
["sai-yur"] = "Yurumanguí",
["saj"] = "Sahu",
["sak"] = "Sake",
["sal-pro"] = "Proto-Salish",
["sam"] = "Aramaik Samaria",
["sao"] = "Sause",
["saq"] = "Samburu",
["sar"] = "Saraveca",
["sas"] = "Sasak",
["sat"] = "Santali",
["sau"] = "Saleman",
["sav"] = "Saafi-Saafi",
["saw"] = "Sawi",
["sax"] = "Sa",
["say"] = "Saya",
["saz"] = "Saurashtra",
["sba"] = "Ngambay",
["sbb"] = "Simbo",
["sbc"] = "Gele'",
["sbd"] = "Samo Selatan",
["sbe"] = "Saliba (Papua)",
["sbf"] = "Shabo",
["sbg"] = "Seget",
["sbh"] = "Sori-Harengan",
["sbi"] = "Seti",
["sbj"] = "Surbakhal",
["sbk"] = "Safwa",
["sbl"] = "Botolan Sambal",
["sbm"] = "Sagala",
["sbn"] = "Sindhi Bhil",
["sbo"] = "Sabüm",
["sbp"] = "Sangu (Tanzania)",
["sbq"] = "Sileibi",
["sbr"] = "Murut Sembakung",
["sbs"] = "Subiya",
["sbt"] = "Kimki",
["sbu"] = "Bhoti Stod",
["sbv"] = "Sabine",
["sbw"] = "Simba",
["sbx"] = "Seberuang",
["sby"] = "Soli",
["sbz"] = "Sara Kaba",
["sc"] = "Sardinia",
["scb"] = "Chut",
["sce"] = "Dongxiang",
["scf"] = "Kreol Prancis San Miguel",
["scg"] = "Sanggau",
["sch"] = "Sakachep",
["sci"] = "Kreol Melayu Sri Lanka",
["sck"] = "Sadri",
["scl"] = "Shina",
["scn"] = "Sisilia",
["sco"] = "Skots",
["scp"] = "Yolmo",
["scq"] = "Sa'och",
["scs"] = "Slavey Utara",
["scu"] = "Shumcho",
["scv"] = "Sheni",
["scw"] = "Sha",
["scx"] = "Sicel",
["sd"] = "Sindhi",
["sda"] = "Toraja-Sa'dan",
["sdb"] = "Shabak",
["sdc"] = "Sassarese",
["sde"] = "Surubu",
["sdf"] = "Sarli",
["sdg"] = "Savi",
["sdh"] = "Kurdi Selatan",
["sdj"] = "Suundi",
["sdk"] = "Sos Kundi",
["sdl"] = "Isyarat Arab Saudi",
["sdm"] = "Semandang",
["sdn"] = "Gallurese",
["sdo"] = "Bidayuh Bukar-Sadung",
["sdp"] = "Sherdukpen",
["sdr"] = "Sadri Oraon",
["sds"] = "Berber Tunisia",
["sdu"] = "Sarudu",
["sdv-daj-pro"] = "Proto-Daju",
["sdv-eje-pro"] = "Proto-Jebel Timur",
["sdv-nil-pro"] = "Proto-Nilotic",
["sdv-nyi-pro"] = "Proto-Nyima",
["sdv-tmn-pro"] = "Proto-Taman",
["sdx"] = "Melanau Sibu",
["se"] = "Sami Utara",
["sea"] = "Semai",
["sec"] = "Sechelt",
["sed"] = "Sedang",
["see"] = "Seneca",
["sef"] = "Senoufo Cebaara",
["seg"] = "Segeju",
["seh"] = "Sena",
["sei"] = "Seri",
["sej"] = "Sene",
["sek"] = "Sekani",
["sel-nor"] = "Selkup Utara",
["sel-pro"] = "Proto-Selkup",
["sel-sou"] = "Selkup Selatan",
["sem-amm"] = "Ammonite",
["sem-amo"] = "Amorite",
["sem-cha"] = "Chaha",
["sem-dad"] = "Dadanitic",
["sem-dum"] = "Dumaitic",
["sem-has"] = "Hasaitic",
["sem-him"] = "Himyaritic",
["sem-his"] = "Hismaic",
["sem-mhr"] = "Muher",
["sem-pro"] = "Proto-Semitik",
["sem-saf"] = "Safaitic",
["sem-srb"] = "Arab Selatan Kuno",
["sem-tay"] = "Taymanitic",
["sem-tha"] = "Thamudic",
["sem-wes-pro"] = "Proto-Semit Barat",
["sen"] = "Sénoufo Nanerigé",
["seo"] = "Suarmin",
["sep"] = "Sénoufo Sìcìté",
["seq"] = "Sénoufo Senara",
["ser"] = "Serrano",
["ses"] = "Senni Koyraboro",
["set"] = "Sentani",
["seu"] = "Serui-Laut",
["sev"] = "Senoufo Nyarafolo",
["sew"] = "Sewa Bay",
["sey"] = "Secoya",
["sez"] = "Chin Senthang",
["sfb"] = "Isyarat Belgia Prancis",
["sfm"] = "Miao Small Flowery",
["sfs"] = "Isyarat Afrika Selatan",
["sfw"] = "Sehwi",
["sg"] = "Sango",
["sga"] = "Irlandia Kuno",
["sgb"] = "Ayta Mag-Anchi",
["sgc"] = "Kipsigis",
["sgd"] = "Surigaonon",
["sge"] = "Segai",
["sgg"] = "Isyarat Swiss-Jerman",
["sgh"] = "Shughni",
["sgi"] = "Suga",
["sgk"] = "Sangkong",
["sgm"] = "Singa",
["sgp"] = "Singpho",
["sgr"] = "Sangisari",
["sgs"] = "Samogitia",
["sgt"] = "Brokpake",
["sgu"] = "Salas",
["sgw"] = "Sebat Bet Gurage",
["sgx"] = "Isyarat Sierra Leone",
["sgy"] = "Sanglechi",
["sgz"] = "Sursurunga",
["sh"] = "Serbo-Kroasia",
["sha"] = "Shall-Zwall",
["shb"] = "Ninam",
["shc"] = "Sonde",
["shd"] = "Kundal Shahi",
["she"] = "Sheko",
["shg"] = "Shua",
["shh"] = "Shoshone",
["shi"] = "Tashelhit",
["shj"] = "Shatt",
["shk"] = "Shilluk",
["shl"] = "Shendu",
["shm"] = "Shahrudi",
["shn"] = "Shan",
["sho"] = "Shanga",
["shp"] = "Shipibo-Conibo",
["shq"] = "Sala",
["shr"] = "Shi",
["shs"] = "Shuswap",
["sht"] = "Shasta",
["shu"] = "Arab Chad",
["shv"] = "Shehri",
["shw"] = "Shwai",
["shx"] = "She",
["shy"] = "Tachawit",
["shz"] = "Senoufo Syenara",
["si"] = "Sinhala",
["sia"] = "Sami Akkala",
["sib"] = "Sebop",
["sid"] = "Sidamo",
["sie"] = "Simaa",
["sif"] = "Siamou",
["sig"] = "Paasaal",
["sih"] = "Zire",
["sii"] = "Shom Peng",
["sij"] = "Numbami",
["sik"] = "Sikiana",
["sil"] = "Tumulung Sisaala",
["sim"] = "Seim",
["sio-pro"] = "Proto-Siouan",
["sip"] = "Sikkim",
["siq"] = "Sonia",
["sir"] = "Siri",
["sis"] = "Siuslaw",
["sit-bok"] = "Bokar",
["sit-cha"] = "Chairel",
["sit-gkh"] = "Gokhy",
["sit-hrs-pro"] = "Proto-Hrusish",
["sit-jap"] = "Japhug",
["sit-kha-pro"] = "Proto-Kham",
["sit-liz"] = "Lizu",
["sit-luu-pro"] = "Proto-Luish",
["sit-mor"] = "Moran",
["sit-prn"] = "Puiron",
["sit-pro"] = "Proto-Sino-Tibet",
["sit-sit"] = "Situ",
["sit-tan-pro"] = "Proto-Tani",
["sit-tgm"] = "Tangam",
["sit-tos"] = "Tosu",
["sit-tsh"] = "Tshobdun",
["sit-zbu"] = "Zbu",
["siu"] = "Sinagen",
["siv"] = "Sumariup",
["siw"] = "Siwai",
["six"] = "Sumau",
["siy"] = "Sivandi",
["siz"] = "Siwi",
["sja"] = "Epena",
["sjb"] = "Basap Sajau",
["sjd"] = "Sami Kildin",
["sje"] = "Sami Pite",
["sjg"] = "Assangori",
["sjk"] = "Sami Kemi",
["sjl"] = "Miji",
["sjm"] = "Mapun",
["sjn"] = "Sindarin",
["sjo"] = "Xibe",
["sjp"] = "Surjapuri",
["sjr"] = "Siar-Lak",
["sjs"] = "Senhaja De Srair",
["sjt"] = "Sami Ter",
["sju"] = "Sami Ume",
["sjw"] = "Shawnee",
["sk"] = "Slowakia",
["ska"] = "Skagit",
["skb"] = "Saek",
["skc"] = "Ma Manda",
["skd"] = "Miwok Sierra Selatan",
["ske"] = "Ske",
["skf"] = "Mekéns",
["skh"] = "Sikule",
["ski"] = "Sika",
["skj"] = "Seke",
["skk"] = "Sok",
["skm"] = "Sakam",
["skn"] = "Subanon Kolibugan",
["sko"] = "Seko Tengah",
["skp"] = "Sekapan",
["skq"] = "Sininkere",
["skr"] = "Saraiki",
["sks"] = "Maia",
["skt"] = "Sakata",
["sku"] = "Sakao",
["skv"] = "Skou",
["skw"] = "Kreol Belanda Skepi",
["skx"] = "Seko Padang",
["sky"] = "Sikaiana",
["skz"] = "Sekar",
["sl"] = "Slovenia",
["sla-pro"] = "Proto-Slavik",
["slc"] = "Saliba (Colombia)",
["sld"] = "Sissala",
["sle"] = "Sholaga",
["slf"] = "Isyarat Swiss-Italia",
["slg"] = "Murut Selungai",
["slh"] = "Salish Puget Sound Selatan",
["slj"] = "Salumá",
["sll"] = "Salt-Yui",
["slm"] = "Sama Pangutaran",
["sln"] = "Salinan",
["slp"] = "Lamaholot",
["slq"] = "Salchuq",
["slr"] = "Salar",
["sls"] = "Isyarat Singapura",
["slt"] = "Sila",
["slu"] = "Selaru",
["slw"] = "Sialum",
["slx"] = "Salampasu",
["sly"] = "Selayar",
["slz"] = "Ma'ya",
["sm"] = "Samoa",
["sma"] = "Sami Selatan",
["smb"] = "Simbari",
["smc"] = "Som",
["smd"] = "Sama",
["smf"] = "Auwe",
["smg"] = "Simbali",
["smh"] = "Samei",
["smi-pro"] = "Proto-Sami",
["smj"] = "Sami Lule",
["smk"] = "Bolinao",
["sml"] = "Sama Tengah",
["smm"] = "Musasa",
["smn"] = "Sami Inari",
["smp"] = "Ibrani Samaria",
["smq"] = "Samo",
["smr"] = "Simeulue",
["sms"] = "Sami Skolt",
["smt"] = "Simte",
["smu"] = "Somray",
["smv"] = "Samvedi",
["smw"] = "Sumbawa",
["smx"] = "Samba",
["smy"] = "Semnani",
["smz"] = "Simeku",
["sn"] = "Shona",
["snb"] = "Sebuyau",
["snc"] = "Sinaugoro",
["sne"] = "Bidayuh Bau",
["snf"] = "Noon",
["sng"] = "Sanga (Kongo)",
["sni"] = "Sensi",
["snj"] = "Sango Riverain",
["snk"] = "Soninke",
["snl"] = "Sangil",
["snm"] = "Ma'di Selatan",
["snn"] = "Siona",
["sno"] = "Snohomish",
["snp"] = "Siane",
["snq"] = "Sangu (Gabon)",
["snr"] = "Sihan",
["sns"] = "Nahavaq",
["snu"] = "Senggi",
["snv"] = "Sa'ban",
["snw"] = "Selee",
["snx"] = "Sam",
["sny"] = "Saniyo-Hiyewe",
["snz"] = "Kou",
["so"] = "Somali",
["soa"] = "Thai Song",
["sob"] = "Sobei",
["soc"] = "Soko",
["sod"] = "Songoora",
["soe"] = "Songomeno",
["sog"] = "Sogdian",
["soh"] = "Aka (Sudan)",
["soi"] = "Sonha",
["sok"] = "Sokoro",
["sol"] = "Solos",
["son-pro"] = "Proto-Songhay",
["soo"] = "Nsong",
["sop"] = "Songe",
["soq"] = "Kanasi",
["sor"] = "Somrai",
["sos"] = "Seenku",
["sou"] = "Thai Selatan",
["sov"] = "Sonsorolese",
["sow"] = "Sowanda",
["sox"] = "Swo",
["soy"] = "Miyobe",
["soz"] = "Temi",
["spb"] = "Sepa",
["spc"] = "Sapé",
["spd"] = "Saep",
["spe"] = "Sepa (Papua)",
["spg"] = "Sian",
["spi"] = "Saponi",
["spk"] = "Sengo",
["spl"] = "Selepet",
["spm"] = "Sepen",
["spn"] = "Sanapaná",
["spo"] = "Spokane",
["spp"] = "Supyire",
["spr"] = "Saparua",
["sps"] = "Saposa",
["spt"] = "Bhoti Spiti",
["spu"] = "Sapuan",
["spv"] = "Sambalpuri",
["spx"] = "Picene Selatan",
["spy"] = "Sabaot",
["sq"] = "Albania",
["sqa"] = "Shama-Sambuga",
["sqh"] = "Shau",
["sqj-pro"] = "Proto-Albania",
["sqk"] = "Isyarat Albania",
["sqm"] = "Suma",
["sqn"] = "Susquehannock",
["sqo"] = "Sorkhei",
["sqq"] = "Sou",
["sqr"] = "Siculo-Arab",
["sqs"] = "Isyarat Sri Lanka",
["sqt"] = "Soqotri",
["squ"] = "Squamish",
["sra"] = "Saruga",
["srb"] = "Sora",
["sre"] = "Sara",
["srf"] = "Nafi",
["srg"] = "Sulod",
["srh"] = "Sarikoli",
["sri"] = "Siriano",
["srk"] = "Murut Serudung",
["srl"] = "Isirawa",
["srm"] = "Saramaccan",
["srn"] = "Sranan Tongo",
["srq"] = "Sirionó",
["srr"] = "Serer",
["srs"] = "Tsuut'ina",
["srt"] = "Sauri",
["sru"] = "Suruí",
["srv"] = "Sorsogon Waray",
["srw"] = "Serua",
["srx"] = "Sirmauri",
["sry"] = "Sera",
["srz"] = "Shahmirzadi",
["ss"] = "Swazi",
["ssa-klk-pro"] = "Proto-Kuliak",
["ssa-kom-pro"] = "Proto-Koman",
["ssa-pro"] = "Proto-Nilo-Saharan",
["ssb"] = "Sama Selatan",
["ssc"] = "Suba-Simbiti",
["ssd"] = "Siroi",
["sse"] = "Balangingi",
["ssf"] = "Thao",
["ssg"] = "Seimat",
["ssh"] = "Arab Shihhi",
["ssi"] = "Sansi",
["ssj"] = "Sausi",
["ssk"] = "Sunam",
["ssl"] = "Sisaala Barat",
["ssm"] = "Semnam",
["sso"] = "Sissano",
["ssp"] = "Isyarat Spanyol",
["ssq"] = "So'a",
["ssr"] = "Isyarat Swiss-Prancis",
["sss"] = "Sô",
["sst"] = "Sinasina",
["ssu"] = "Susuami",
["ssv"] = "Shark Bay",
["ssx"] = "Samberigi",
["ssy"] = "Saho",
["ssz"] = "Sengseng",
["st"] = "Sotho",
["stb"] = "Subanen Utara",
["std"] = "Sentinel",
["ste"] = "Liana-Seti",
["stf"] = "Seta",
["stg"] = "Trieng",
["sth"] = "Shelta",
["sti"] = "Stieng Bulo",
["stj"] = "Samo Matya",
["stk"] = "Arammba",
["stm"] = "Setaman",
["stn"] = "Owa",
["sto"] = "Stoney",
["stp"] = "Tepehuan Tenggara",
["stq"] = "Frisia Saterland",
["str"] = "Saanich",
["sts"] = "Shumashti",
["stt"] = "Stieng Budeh",
["stu"] = "Samtao",
["stv"] = "Silt'e",
["stw"] = "Satawalese",
["sty"] = "Siberia Tatar",
["su"] = "Sunda",
["sua"] = "Sulka",
["sub"] = "Suku",
["suc"] = "Subanon Barat",
["sue"] = "Suena",
["sug"] = "Suganga",
["sui"] = "Suki",
["suk"] = "Sukuma",
["suq"] = "Suri",
["sur"] = "Mwaghavul",
["sus"] = "Susu",
["sut"] = "Subtiaba",
["suv"] = "Sulung",
["suw"] = "Sumbwa",
["sux"] = "Sumeria",
["suy"] = "Suyá",
["suz"] = "Sunwar",
["sv"] = "Swedia",
["sva"] = "Svan",
["svb"] = "Ulau-Suain",
["svc"] = "Kreol Inggris Vincent",
["sve"] = "Serili",
["svk"] = "Isyarat Slowakia",
["svm"] = "Slavomolisano",
["svs"] = "Savosavo",
["svx"] = "Skalvian",
["sw"] = "Swahili",
["swb"] = "Comorian Maore",
["swf"] = "Sere",
["swg"] = "Swabia",
["swi"] = "Sui",
["swj"] = "Sira",
["swl"] = "Isyarat Swedia",
["swm"] = "Samosa",
["swn"] = "Sokna",
["swo"] = "Shanenawa",
["swp"] = "Suau",
["swq"] = "Sharwa",
["swr"] = "Saweru",
["sws"] = "Seluwasan",
["swt"] = "Sawila",
["swu"] = "Suwawa",
["sww"] = "Sowa",
["swx"] = "Suruahá",
["swy"] = "Sarua",
["sxb"] = "Suba",
["sxc"] = "Sicanian",
["sxe"] = "Sighu",
["sxg"] = "Shixing",
["sxk"] = "Kalapuya Selatan",
["sxl"] = "Selonian",
["sxm"] = "Samre",
["sxn"] = "Sangir",
["sxo"] = "Sorothaptic",
["sxr"] = "Saaroa",
["sxs"] = "Sasaru",
["sxw"] = "Gbe Saxwe",
["sya"] = "Siang",
["syb"] = "Subanen Tengah",
["syc"] = "Suriah Klasik",
["syd-fne"] = "Nenets Hutan",
["syd-pro"] = "Proto-Samoyedic",
["syi"] = "Seki",
["syk"] = "Sukur",
["syl"] = "Sylheti",
["sym"] = "Samo Maya",
["syn"] = "Senaya",
["syo"] = "Suoy",
["sys"] = "Sinyar",
["syw"] = "Kagate",
["syx"] = "Osamayi",
["syy"] = "Isyarat Al-Sayyid Bedouin",
["sza"] = "Semelai",
["szb"] = "Ngalum",
["szc"] = "Semaq Beri",
["szd"] = "Seru",
["sze"] = "Seze",
["szg"] = "Sengele",
["szl"] = "Silesia",
["szn"] = "Sula",
["szp"] = "Suabo",
["szv"] = "Isubu",
["szw"] = "Sawai",
["szy"] = "Sakizaya",
["ta"] = "Tamil",
["taa"] = "Tanana Hilir",
["tab"] = "Tabasaran",
["tac"] = "Tarahumara Dataran",
["tad"] = "Tause",
["tae"] = "Tariana",
["taf"] = "Tapirapé",
["tag"] = "Tagoi",
["tai-pro"] = "Proto-Tai",
["tai-swe-pro"] = "Proto-Tai Barat Daya",
["taj"] = "Tamang Timur",
["tak"] = "Tala",
["tal"] = "Tal",
["tan"] = "Tangale",
["tao"] = "Yami",
["tap"] = "Taabwa",
["tar"] = "Tarahumara Tengah",
["tas"] = "Tây Bồi",
["tau"] = "Tanana Hulu",
["tav"] = "Tatuyo",
["taw"] = "Tai",
["tax"] = "Tamki",
["tay"] = "Atayal",
["taz"] = "Tocho",
["tba"] = "Aikanã",
["tbb"] = "Tapeba",
["tbc"] = "Takia",
["tbd"] = "Kaki Ae",
["tbe"] = "Tanimbili",
["tbf"] = "Mandara",
["tbg"] = "Tairora Utara",
["tbh"] = "Thurawal",
["tbi"] = "Gaam",
["tbj"] = "Tiang",
["tbk"] = "Tagbanwa Calamian",
["tbl"] = "Tboli",
["tbm"] = "Tagbu",
["tbn"] = "Tunebo Barro Negro",
["tbo"] = "Tawala",
["tbp"] = "Taworta",
["tbq-bdg-pro"] = "Proto-Bodo-Garo",
["tbq-kuk-pro"] = "Proto-Kuki-Chin",
["tbq-lal-pro"] = "Proto-Lalo",
["tbq-laz"] = "Laze",
["tbq-lob-pro"] = "Proto-Lolo-Burma",
["tbq-lol-pro"] = "Proto-Loloish",
["tbq-ngo"] = "Ngochang",
["tbq-plg"] = "Pai-lang",
["tbr"] = "Tumtum",
["tbs"] = "Tanguat",
["tbt"] = "Kitembo",
["tbu"] = "Tubar",
["tbv"] = "Tobo",
["tbw"] = "Tagbanwa",
["tbx"] = "Kapin",
["tby"] = "Tabaru",
["tbz"] = "Ditammari",
["tca"] = "Ticuna",
["tcb"] = "Tanacross",
["tcc"] = "Datooga",
["tcd"] = "Tafi",
["tce"] = "Tutchone Selatan",
["tcf"] = "Malinaltepec Tlapanec",
["tcg"] = "Tamagario",
["tch"] = "Kreol Inggris Turks dan Caicos",
["tci"] = "Wára",
["tck"] = "Tchitchege",
["tcl"] = "Taman (Myanmar)",
["tcm"] = "Tanahmerah",
["tco"] = "Taungyo",
["tcp"] = "Chin Tawr",
["tcq"] = "Kaiy",
["tcs"] = "Kreol Torres Strait",
["tct"] = "T'en",
["tcu"] = "Tarahumara Tenggara",
["tcw"] = "Totonac Tecpatlán",
["tcx"] = "Toda",
["tcy"] = "Tulu",
["tcz"] = "Chin Thado",
["tda"] = "Tagdal",
["tdb"] = "Panchpargania",
["tdc"] = "Emberá-Tadó",
["tdd"] = "Tai Nüa",
["tde"] = "Dogon Tiranige Diga",
["tdf"] = "Talieng",
["tdg"] = "Tamang Barat",
["tdh"] = "Thulung",
["tdi"] = "Tomadino",
["tdj"] = "Tajio",
["tdk"] = "Tambas",
["tdl"] = "Sur",
["tdm"] = "Taruma",
["tdn"] = "Tondano",
["tdo"] = "Teme",
["tdq"] = "Tita",
["tdr"] = "Todrah",
["tds"] = "Doutai",
["tdt"] = "Tetun Dili",
["tdu"] = "Dusun Tempasuk",
["tdv"] = "Toro",
["tdy"] = "Tadyawan",
["te"] = "Telugu",
["tea"] = "Temiar",
["teb"] = "Tetete",
["tec"] = "Terik",
["ted"] = "Tepo Krumen",
["tee"] = "Tepehua Huehuetla",
["tef"] = "Teressa",
["teg"] = "Teke-Tege",
["teh"] = "Tehuelche",
["tei"] = "Torricelli",
["tek"] = "Teke Ibali",
["tem"] = "Temne",
["ten"] = "Tama (Colombia)",
["teo"] = "Ateso",
["tep"] = "Tepecano",
["teq"] = "Temein",
["ter"] = "Tereno",
["tes"] = "Tengger",
["tet"] = "Tetum",
["teu"] = "Soo",
["tev"] = "Teor",
["tew"] = "Tewa",
["tex"] = "Tennet",
["tey"] = "Tulishi",
["tez"] = "Tetserret",
["tfi"] = "Gbe Tofin",
["tfn"] = "Dena'ina",
["tfo"] = "Tefaro",
["tfr"] = "Teribe",
["tft"] = "Ternate",
["tg"] = "Tajik",
["tga"] = "Sagalla",
["tgb"] = "Tobilung",
["tgc"] = "Tigak",
["tgd"] = "Ciwogai",
["tge"] = "Tamang Gorkha Timur",
["tgf"] = "Chali",
["tgh"] = "Kreol Inggris Tobago",
["tgi"] = "Lawunuia",
["tgn"] = "Tandaganon",
["tgo"] = "Sudest",
["tgp"] = "Tangoa",
["tgq"] = "Tring",
["tgr"] = "Tareng",
["tgs"] = "Nume",
["tgt"] = "Tagbanwa Tengah",
["tgu"] = "Tanggu",
["tgv"] = "Tingui-Boto",
["tgw"] = "Senoufo Tagwana",
["tgx"] = "Tagish",
["tgy"] = "Togoyo",
["th"] = "Thai",
["thc"] = "Tai Hang Tong",
["thd"] = "Kuuk Thaayorre",
["the"] = "Tharu Chitwania",
["thf"] = "Thangmi",
["thh"] = "Tarahumara Utara",
["thi"] = "Tai Long",
["thk"] = "Tharaka",
["thl"] = "Tharu Dangaura",
["thm"] = "Thavung",
["thn"] = "Thachanadan",
["thp"] = "Thompson",
["thq"] = "Tharu Kochila",
["thr"] = "Tharu Rana",
["ths"] = "Thakali",
["tht"] = "Tahltan",
["thu"] = "Thuri",
["thy"] = "Tha",
["ti"] = "Tigrinya",
["tic"] = "Tira",
["tif"] = "Tifal",
["tig"] = "Tigre",
["tih"] = "Murut Timugon",
["tii"] = "Tiene",
["tij"] = "Tilung",
["tik"] = "Tikar",
["til"] = "Tillamook",
["tim"] = "Timbe",
["tin"] = "Tindi",
["tio"] = "Teop",
["tip"] = "Trimuris",
["tiq"] = "Tiéfo",
["tis"] = "Itneg Masadiit",
["tit"] = "Tinigua",
["tiu"] = "Adasen",
["tiv"] = "Tiv",
["tiw"] = "Tiwi",
["tix"] = "Tiwa Selatan",
["tiy"] = "Tiruray",
["tiz"] = "Tai Hongjin",
["tja"] = "Tajuasohn",
["tjg"] = "Tunjung",
["tji"] = "Tujia Utara",
["tjl"] = "Tai Laing",
["tjm"] = "Timucua",
["tjn"] = "Tonjon",
["tjs"] = "Tujia Selatan",
["tju"] = "Tjurruru",
["tjw"] = "Chaap Wuurong",
["tk"] = "Turkmen",
["tka"] = "Truká",
["tkb"] = "Buksa",
["tkd"] = "Tukudede",
["tke"] = "Takwane",
["tkf"] = "Tukumanféd",
["tkl"] = "Tokelauan",
["tkm"] = "Takelma",
["tkn"] = "Toku-No-Shima",
["tkp"] = "Tikopia",
["tkq"] = "Tee",
["tkr"] = "Tsakhur",
["tks"] = "Ramandi",
["tkt"] = "Tharu Kathoriya",
["tku"] = "Totonac Necaxa Hulu",
["tkv"] = "Mur Pano",
["tkw"] = "Teanu",
["tkx"] = "Tangko",
["tkz"] = "Takua",
["tl"] = "Tagalog",
["tla"] = "Tepehuan Barat Daya",
["tlb"] = "Tobelo",
["tlc"] = "Totonac Misantla",
["tld"] = "Talaud",
["tlf"] = "Telefol",
["tlg"] = "Tofanma",
["tlh"] = "Klingon",
["tli"] = "Tlingit",
["tlj"] = "Talinga-Bwisi",
["tlk"] = "Taloki",
["tll"] = "Tetela",
["tlm"] = "Tolomako",
["tln"] = "Talondo'",
["tlo"] = "Talodi",
["tlp"] = "Totonac Filomena Mata-Coahuitlán",
["tlq"] = "Tai Loi",
["tlr"] = "Talise",
["tls"] = "Tambotalo",
["tlt"] = "Teluti",
["tlu"] = "Tulehu",
["tlv"] = "Taliabu",
["tlx"] = "Khehek",
["tly"] = "Talysh",
["tma"] = "Tama (Chad)",
["tmb"] = "Avava",
["tmc"] = "Tumak",
["tmd"] = "Haruai",
["tme"] = "Tremembé",
["tmf"] = "Toba-Maskoy",
["tmg"] = "Ternateño",
["tmh"] = "Tuareg",
["tmi"] = "Tutuba",
["tmj"] = "Samarokena",
["tmk"] = "Tamang Barat Laut",
["tml"] = "Tamnim Citak",
["tmm"] = "Tai Thanh",
["tmn"] = "Taman",
["tmo"] = "Temoq",
["tmq"] = "Tumleo",
["tms"] = "Tima",
["tmt"] = "Tasmate",
["tmu"] = "Iau",
["tmv"] = "Motembo",
["tmy"] = "Tami",
["tmz"] = "Tamanaku",
["tn"] = "Tswana",
["tna"] = "Tacana",
["tnb"] = "Tunebo Barat",
["tnc"] = "Tanimuca-Retuarã",
["tnd"] = "Tunebo Angosturas",
["tne"] = "Kallahan Tinoc",
["tng"] = "Tobanga",
["tnh"] = "Maiani",
["tni"] = "Tandia",
["tnk"] = "Kwamera",
["tnl"] = "Lenakel",
["tnm"] = "Tabla",
["tnn"] = "Tanna Utara",
["tno"] = "Toromono",
["tnp"] = "Whitesands",
["tnq"] = "Taíno",
["tnr"] = "Bedik",
["tns"] = "Tenis",
["tnt"] = "Tontemboan",
["tnu"] = "Tay Khang",
["tnv"] = "Tangchangya",
["tnw"] = "Tonsawang",
["tnx"] = "Tanema",
["tny"] = "Tongwe",
["tnz"] = "Ten'edn",
["to"] = "Tonga",
["tob"] = "Toba",
["toc"] = "Totonac Coyutla",
["tod"] = "Toma",
["tof"] = "Gizrra",
["tog"] = "Tonga (Malawi)",
["toh"] = "Tonga (Mozambique)",
["toi"] = "Tonga (Zambia)",
["toj"] = "Tojolabal",
["tok"] = "Toki Pona",
["tol"] = "Tolowa",
["tom"] = "Tombulu",
["too"] = "Totonac Xicotepec de Juárez",
["top"] = "Totonac Papantla",
["toq"] = "Toposa",
["tor"] = "Togbo-Vara Banda",
["tos"] = "Totonac Pegunungan",
["tou"] = "Tho",
["tov"] = "Taromi Hulu",
["tow"] = "Jemez",
["tox"] = "Tobian",
["toy"] = "Topoiyo",
["toz"] = "To",
["tpa"] = "Taupota",
["tpc"] = "Me'phaa Azoyú",
["tpe"] = "Tippera",
["tpf"] = "Tarpia",
["tpg"] = "Kula",
["tpi"] = "Tok Pisin",
["tpj"] = "Tapieté",
["tpk"] = "Tupinikin",
["tpl"] = "Me'phaa Tlacoapa",
["tpm"] = "Tampulma",
["tpn"] = "Tupinambá",
["tpo"] = "Tai Pao",
["tpp"] = "Tepehua Pisaflores",
["tpq"] = "Tukpa",
["tpr"] = "Tuparí",
["tpt"] = "Tepehua Tlachichilco",
["tpu"] = "Tampuan",
["tpv"] = "Tanapag",
["tpw"] = "Tupi Kuno",
["tpx"] = "Me'phaa Acatepec",
["tpy"] = "Trumai",
["tpz"] = "Tinputz",
["tqb"] = "Tembé",
["tql"] = "Lehali",
["tqm"] = "Turumsa",
["tqn"] = "Tenino",
["tqo"] = "Toaripi",
["tqp"] = "Tomoip",
["tqq"] = "Tunni",
["tqr"] = "Torona",
["tqt"] = "Totonac Barat",
["tqu"] = "Touo",
["tqw"] = "Tonkawa",
["tr"] = "Turki",
["tra"] = "Tirahi",
["trb"] = "Terebu",
["trc"] = "Triqui Copala",
["trd"] = "Turi",
["tre"] = "Tarangan Timur",
["trf"] = "Kreol Inggris Trinidad",
["trg"] = "Lishán Didán",
["trh"] = "Turaka",
["tri"] = "Trió",
["trj"] = "Toram",
["trk-dkh"] = "Dukhan",
["trk-oat"] = "Turki Anatolia Kuno",
["trk-pro"] = "Proto-Turkik",
["trl"] = "Skotlandia Traveller",
["trm"] = "Tregami",
["trn"] = "Trinitario",
["tro"] = "Tarao",
["trp"] = "Kokborok",
["trq"] = "Triqui San Martín Itunyoso",
["trr"] = "Taushiro",
["trs"] = "Triqui Chicahuaxtla",
["trt"] = "Tunggare",
["tru"] = "Turoyo",
["trv"] = "Taroko",
["trw"] = "Torwali",
["trx"] = "Tringgus",
["try"] = "Turung",
["trz"] = "Torá",
["ts"] = "Tsonga",
["tsa"] = "Tsaangi",
["tsb"] = "Tsamai",
["tsc"] = "Tswa",
["tsd"] = "Tsakonia",
["tse"] = "Isyarat Tunisia",
["tsf"] = "Tamang Barat Daya",
["tsg"] = "Tausug",
["tsh"] = "Tsuvan",
["tsi"] = "Tsimshian",
["tsj"] = "Tshangla",
["tsl"] = "Ts'ün-Lao",
["tsm"] = "Isyarat Turki",
["tsp"] = "Toussian Utara",
["tsq"] = "Isyarat Thai",
["tsr"] = "Akei",
["tss"] = "Isyarat Taiwan",
["tsu"] = "Tsou",
["tsv"] = "Tsogo",
["tsw"] = "Tsishingini",
["tsx"] = "Mubami",
["tsy"] = "Isyarat Tebul",
["tt"] = "Tatar",
["tta"] = "Tutelo",
["ttb"] = "Gaa",
["ttc"] = "Tektiteko",
["ttd"] = "Tauade",
["tte"] = "Bwanabwana",
["ttf"] = "Tuotomb",
["ttg"] = "Tutong",
["tth"] = "Ta'oih Hulu",
["tti"] = "Tobati",
["ttj"] = "Tooro",
["ttk"] = "Totoro",
["ttl"] = "Totela",
["ttm"] = "Tutchone Utara",
["ttn"] = "Towei",
["tto"] = "Ta'oih Hilir",
["ttp"] = "Tombelala",
["ttr"] = "Tera",
["tts"] = "Isan",
["ttt"] = "Tat",
["ttu"] = "Torau",
["ttv"] = "Titan",
["ttw"] = "Long Wat",
["tty"] = "Sikaritai",
["ttz"] = "Tsum",
["tua"] = "Wiarumus",
["tub"] = "Tübatulabal",
["tuc"] = "Mutu",
["tud"] = "Tuxá",
["tue"] = "Tuyuca",
["tuf"] = "Tunebo Tengah",
["tug"] = "Tunia",
["tuh"] = "Taulil",
["tui"] = "Tupuri",
["tuj"] = "O'Hongana Manyawa",
["tul"] = "Tula",
["tum"] = "Tumbuka",
["tun"] = "Tunica",
["tuo"] = "Tucano",
["tup-gua-pro"] = "Proto-Tupi-Guarani",
["tup-kab"] = "Kabishiana",
["tup-pro"] = "Proto-Tupian",
["tuq"] = "Tedaga",
["tus"] = "Tuscarora",
["tuu"] = "Tututni",
["tuv"] = "Turkana",
["tuw-kkl"] = "Kyakala",
["tuw-pro"] = "Proto-Tungusic",
["tuw-sol"] = "Solon",
["tux"] = "Tuxináwa",
["tuy"] = "Tugen",
["tuz"] = "Turka",
["tva"] = "Vaghua",
["tvd"] = "Tsuvadi",
["tve"] = "Te'un",
["tvg"] = "Tugu",
["tvk"] = "Ambrym Tenggara",
["tvl"] = "Tuvaluan",
["tvm"] = "Tela-Masbuar",
["tvn"] = "Tavoyan",
["tvo"] = "Tidore",
["tvs"] = "Taveta",
["tvt"] = "Naga Tutsa",
["tvu"] = "Tunen",
["tvw"] = "Sedoa",
["tvx"] = "Taivoan",
["tvy"] = "Pijin Timor",
["twa"] = "Twana",
["twb"] = "Tawbuid Barat",
["twc"] = "Teshenawa",
["twe"] = "Teiwa",
["twf"] = "Taos",
["twg"] = "Tereweng",
["twh"] = "Tai Dón",
["twm"] = "Monpa Tawang",
["twn"] = "Twendi",
["two"] = "Tswapong",
["twp"] = "Ere",
["twq"] = "Tasawaq",
["twr"] = "Tarahumara Barat Daya",
["twt"] = "Turiwára",
["twu"] = "Termanu",
["tww"] = "Tuwari",
["twy"] = "Tawoyan",
["txa"] = "Tombonuo",
["txb"] = "Tocharian B",
["txc"] = "Tsetsaut",
["txe"] = "Totoli",
["txg"] = "Tangut",
["txh"] = "Thracian",
["txi"] = "Ikpeng",
["txj"] = "Tarjumo",
["txm"] = "Tomini",
["txn"] = "Tarangan Barat",
["txo"] = "Toto",
["txq"] = "Tii",
["txr"] = "Tartessian",
["txs"] = "Tonsea",
["txt"] = "Citak",
["txu"] = "Kayapó",
["txx"] = "Tatana",
["ty"] = "Tahiti",
["tya"] = "Tauya",
["tye"] = "Kyenga",
["tyh"] = "O'du",
["tyi"] = "Teke-Tsaayi",
["tyj"] = "Tai Do",
["tyl"] = "Thu Lao",
["tyn"] = "Kombai",
["typ"] = "Kuku-Thaypan",
["tyr"] = "Tai Daeng",
["tys"] = "Sapa",
["tyt"] = "Tày Tac",
["tyu"] = "Kua",
["tyv"] = "Tuvan",
["tyx"] = "Teke-Tyee",
["tyz"] = "Tày",
["tza"] = "Isyarat Tanzania",
["tzh"] = "Tzeltal",
["tzj"] = "Tz'utujil",
["tzl"] = "Talossan",
["tzm"] = "Atlas Tamazight Tengah",
["tzn"] = "Tugun",
["tzo"] = "Tzotzil",
["tzx"] = "Tabriak",
["uam"] = "Uamué",
["uan"] = "Kuan",
["uar"] = "Tairuma",
["uba"] = "Ubang",
["ubi"] = "Ubi",
["ubl"] = "Bikol Buhi'non",
["ubr"] = "Ubir",
["ubu"] = "Umbu-Ungu",
["uby"] = "Ubykh",
["uda"] = "Uda",
["ude"] = "Udihe",
["udg"] = "Muduga",
["udi"] = "Udi",
["udj"] = "Ujir",
["udl"] = "Uldeme",
["udm"] = "Udmurt",
["udu"] = "Uduk",
["ues"] = "Kioko",
["ufi"] = "Ufim",
["ug"] = "Uighur",
["uga"] = "Ugaritic",
["ugb"] = "Kuku-Ugbanh",
["uge"] = "Ughele",
["ugn"] = "Isyarat Uganda",
["ugo"] = "Gong",
["ugy"] = "Isyarat Uruguay",
["uha"] = "Uhami",
["uhn"] = "Damal",
["uis"] = "Uisai",
["uiv"] = "Iyive",
["uji"] = "Tanjijili",
["uk"] = "Ukraina",
["uka"] = "Kaburi",
["ukg"] = "Ukuriguma",
["ukh"] = "Ukhwejo",
["ukk"] = "Muak Sa-aak",
["ukl"] = "Isyarat Ukraina",
["ukp"] = "Ukpe-Bayobiri",
["ukq"] = "Ukwa",
["uks"] = "Isyarat Kaapor",
["uku"] = "Ukue",
["ukw"] = "Ukwuani-Aboh-Ndoni",
["uky"] = "Kuuk Yak",
["ula"] = "Fungwa",
["ulb"] = "Olukumi",
["ulc"] = "Ulch",
["ule"] = "Lule",
["ulf"] = "Afra",
["uli"] = "Ulithian",
["ulk"] = "Meriam",
["ull"] = "Ullatan",
["ulm"] = "Ulumanda'",
["uln"] = "Unserdeutsch",
["ulu"] = "Uma' Lung",
["ulw"] = "Ulwa",
["uma"] = "Umatilla",
["umb"] = "Umbundu",
["umc"] = "Marrucinian",
["umd"] = "Umbindhamu",
["umg"] = "Umbuygamu",
["umi"] = "Ukit",
["umm"] = "Umon",
["umn"] = "Naga Makyan",
["umo"] = "Umotína",
["ump"] = "Umpila",
["umr"] = "Umbugarla",
["ums"] = "Pendau",
["umu"] = "Munsee",
["una"] = "Watut Utara",
["und"] = "Tidak diketahui",
["und-isa"] = "Isaurian",
["und-kas"] = "Kassite",
["und-mil"] = "Milang",
["und-mmd"] = "Mimi Decorse",
["und-mmn"] = "Mimi Nachtigal",
["und-phi"] = "Filistin",
["und-wji"] = "Jicaque Barat",
["une"] = "Uneme",
["ung"] = "Ngarinyin",
["unk"] = "Enawené-Nawé",
["unm"] = "Unami",
["unn"] = "Kurnai",
["unr"] = "Mundari",
["unu"] = "Unubahe",
["unx"] = "Munda",
["unz"] = "Kaili Unde",
["uok"] = "Uokha",
["uon"] = "Kulon",
["upi"] = "Umeda",
["upv"] = "Uripiv-Wala-Rano-Atchin",
["ur"] = "Urdu",
["ura"] = "Urarina",
["urb"] = "Urubú-Kaapor",
["urc"] = "Urningangg",
["ure"] = "Uru",
["urf"] = "Uradhi",
["urg"] = "Urigina",
["urh"] = "Urhobo",
["uri"] = "Urim",
["urj-fin-pro"] = "Proto-Finnic",
["urj-koo"] = "Komi Kuno",
["urj-kuk"] = "Kukkuzi",
["urj-kya"] = "Komi-Yazva",
["urj-mdv-pro"] = "Proto-Mordvinic",
["urj-prm-pro"] = "Proto-Permic",
["urj-pro"] = "Proto-Uralic",
["urj-ugr-pro"] = "Proto-Ugric",
["urk"] = "Urak Lawoi'",
["url"] = "Urali",
["urm"] = "Urapmin",
["urn"] = "Uruangnirin",
["uro"] = "Ura (Papua)",
["urp"] = "Uru-Pa-In",
["urr"] = "Lehalurup",
["urt"] = "Urat",
["uru"] = "Urumi",
["urv"] = "Uruava",
["urw"] = "Sop",
["urx"] = "Urimo",
["ury"] = "Orya",
["urz"] = "Uru-Eu-Wau-Wau",
["usa"] = "Usarufa",
["ush"] = "Ushojo",
["usi"] = "Usui",
["usk"] = "Usaghade",
["usp"] = "Uspanteco",
["uss"] = "Saare",
["usu"] = "Uya",
["uta"] = "Otank",
["ute"] = "Ute",
["uth"] = "Hun",
["utp"] = "Aba",
["utr"] = "Etulo",
["utu"] = "Utu",
["uum"] = "Urum",
["uun"] = "Kulon-Pazeh",
["uur"] = "Ura (Vanuatu)",
["uuu"] = "U",
["uve"] = "Uvean Barat",
["uvh"] = "Uri",
["uvl"] = "Lote",
["uwa"] = "Kuku-Uwanh",
["uya"] = "Doko-Uyanga",
["uz"] = "Uzbek",
["vaa"] = "Vaagri Booli",
["vae"] = "Vale",
["vag"] = "Vagla",
["vah"] = "Varhadi",
["vai"] = "Vai",
["vaj"] = "Sekele",
["val"] = "Vehes",
["vam"] = "Vanimo",
["van"] = "Valman",
["vao"] = "Vao",
["vap"] = "Vaiphei",
["var"] = "Huarijio",
["vas"] = "Vasavi",
["vau"] = "Vanuma",
["vav"] = "Varli",
["vay"] = "Vayu",
["vbb"] = "Babar Tenggara",
["vbk"] = "Bontoc Barat Daya",
["ve"] = "Venda",
["vec"] = "Venesia",
["ved"] = "Veddah",
["vem"] = "Vemgo-Mabas",
["veo"] = "Ventureño",
["vep"] = "Veps",
["ver"] = "Mom Jango",
["vgr"] = "Vaghri",
["vgt"] = "Isyarat Flemish",
["vi"] = "Vietnam",
["vic"] = "Kreol Virgin Islands",
["vid"] = "Vidunda",
["vif"] = "Vili",
["vig"] = "Viemo",
["vil"] = "Vilela",
["vis"] = "Vishavan",
["vit"] = "Viti",
["viv"] = "Iduna",
["vka"] = "Kariyarra",
["vki"] = "Ija-Zuba",
["vkj"] = "Kujarge",
["vkk"] = "Kaur",
["vkl"] = "Kulisusu",
["vkm"] = "Kamakan",
["vko"] = "Kodeoha",
["vkp"] = "Kreol Portugis Korlai",
["vkt"] = "Kutai Hilir",
["vku"] = "Kurrama",
["vlp"] = "Valpei",
["vls"] = "Flemish Barat",
["vma"] = "Martuthunira",
["vmb"] = "Mbabaram",
["vmc"] = "Mixtec Juxtlahuaca",
["vmd"] = "Koraga Mudu",
["vme"] = "Masela Timur",
["vmf"] = "Franconia Timur",
["vmg"] = "Minigir",
["vmh"] = "Maraghei",
["vmi"] = "Miwa",
["vmj"] = "Mixtec Ixtayutla",
["vmk"] = "Makhuwa-Shirima",
["vml"] = "Malgana",
["vmm"] = "Mixtec Mitlatongo",
["vmp"] = "Mazatec Soyaltepec",
["vmq"] = "Mixtec Soyaltepec",
["vmr"] = "Marenje",
["vmu"] = "Muluridyi",
["vmv"] = "Valley Maidu",
["vmw"] = "Makhuwa",
["vmx"] = "Mixtec Tamazola",
["vmy"] = "Mazatec Ayautla",
["vmz"] = "Mazatec Mazatlán",
["vnk"] = "Lovono",
["vnm"] = "Neve'ei",
["vnp"] = "Vunapu",
["vo"] = "Volapük",
["vor"] = "Voro",
["vot"] = "Votic",
["vra"] = "Vera'a",
["vro"] = "Võro",
["vrs"] = "Varisi",
["vrt"] = "Banam Bay",
["vsi"] = "Isyarat Moldova",
["vsl"] = "Isyarat Venezuela",
["vsv"] = "Isyarat Valencia",
["vto"] = "Vitou",
["vum"] = "Vumbu",
["vun"] = "Vunjo",
["vut"] = "Vute",
["vwa"] = "Awa (Tiongkok)",
["wa"] = "Walloon",
["waa"] = "Walla Walla",
["wab"] = "Wab",
["wac"] = "Wasco-Wishram",
["wad"] = "Wandamen",
["waf"] = "Wakoná",
["wag"] = "Wa'ema",
["wah"] = "Watubela",
["waj"] = "Waffa",
["wal"] = "Wolaytta",
["wam"] = "Massachusett",
["wan"] = "Wan",
["wao"] = "Wappo",
["wap"] = "Wapishana",
["waq"] = "Wageman",
["war"] = "Waray-Waray",
["was"] = "Washo",
["wat"] = "Kaninuwa",
["wau"] = "Wauja",
["wav"] = "Waka",
["waw"] = "Waiwai",
["wax"] = "Watam",
["way"] = "Wayana",
["waz"] = "Wampur",
["wba"] = "Warao",
["wbb"] = "Wabo",
["wbe"] = "Waritai",
["wbf"] = "Wara",
["wbh"] = "Wanda",
["wbi"] = "Wanji",
["wbj"] = "Alagwa",
["wbk"] = "Waigali",
["wbl"] = "Wakhi",
["wbm"] = "Wa",
["wbp"] = "Warlpiri",
["wbq"] = "Waddar",
["wbr"] = "Wagdi",
["wbt"] = "Wanman",
["wbv"] = "Wajarri",
["wbw"] = "Woi",
["wca"] = "Yanomámi",
["wci"] = "Gbe Waci",
["wdd"] = "Wandji",
["wdg"] = "Wadaginam",
["wdj"] = "Wadjiginy",
["wdt"] = "Wendat",
["wdu"] = "Wadjigu",
["wdy"] = "Wadjabangayi",
["wea"] = "Wewaw",
["wec"] = "Wè Barat",
["wed"] = "Wedau",
["weh"] = "Weh",
["wei"] = "Kiunum",
["wem"] = "Gbe Weme",
["weo"] = "Wemale",
["wer"] = "Weri",
["wes"] = "Pijin Kamerun",
["wet"] = "Perai",
["weu"] = "Welaung",
["wew"] = "Weyewa",
["wfg"] = "Yafi",
["wga"] = "Wagaya",
["wgb"] = "Wagawaga",
["wgg"] = "Wangganguru",
["wgi"] = "Wahgi",
["wgo"] = "Waigeo",
["wgu"] = "Wirangu",
["wgy"] = "Warrgamay",
["wha"] = "Manusela",
["whg"] = "Wahgi Utara",
["whk"] = "Kenyah Wahau",
["whu"] = "Kayan Wahau",
["wib"] = "Toussian Selatan",
["wic"] = "Wichita",
["wie"] = "Wik-Epa",
["wif"] = "Wik-Keyangan",
["wig"] = "Wik-Ngathana",
["wih"] = "Wik-Me'anha",
["wii"] = "Minidien",
["wij"] = "Wik-Iiyanh",
["wik"] = "Wikalkan",
["wil"] = "Wilawila",
["wim"] = "Wik-Mungkan",
["win"] = "Winnebago",
["wir"] = "Wiraféd",
["wiu"] = "Wiru",
["wiv"] = "Muduapa",
["wiy"] = "Wiyot",
["wja"] = "Waja",
["wji"] = "Warji",
["wka"] = "Kw'adza",
["wkb"] = "Kumbaran",
["wkd"] = "Mo",
["wkl"] = "Kalanadi",
["wku"] = "Kunduvadi",
["wkw"] = "Wakawaka",
["wky"] = "Wangkayutyuru",
["wla"] = "Walio",
["wlc"] = "Comorian Mwali",
["wle"] = "Wolane",
["wlg"] = "Kunbarlang",
["wli"] = "Waioli",
["wlk"] = "Wailaki",
["wll"] = "Wali (Sudan)",
["wlm"] = "Welsh Pertengahan",
["wlo"] = "Wolio",
["wlr"] = "Wailapa",
["wls"] = "Wallisian",
["wlu"] = "Wuliwuli",
["wlv"] = "Wichí Lhamtés Vejoz",
["wlw"] = "Walak",
["wlx"] = "Wali (Ghana)",
["wly"] = "Waling",
["wmb"] = "Wambaya",
["wmc"] = "Wamas",
["wmd"] = "Mamaindé",
["wme"] = "Wambule",
["wmh"] = "Waima'a",
["wmi"] = "Wamin",
["wmm"] = "Maiwa",
["wmn"] = "Waamwang",
["wmo"] = "Wam",
["wms"] = "Wambon",
["wmt"] = "Walmajarri",
["wmw"] = "Mwani",
["wmx"] = "Womo",
["wnb"] = "Wanambre",
["wnc"] = "Wantoat",
["wnd"] = "Wandarang",
["wne"] = "Waneci",
["wng"] = "Wanggom",
["wni"] = "Comorian Ndzwani",
["wnk"] = "Wanukaka",
["wnm"] = "Wanggamala",
["wno"] = "Wano",
["wnp"] = "Wanap",
["wnu"] = "Usan",
["wnw"] = "Wintu",
["wny"] = "Wanyi",
["wo"] = "Wolof",
["woa"] = "Tyaraity",
["wob"] = "Wè Utara",
["woc"] = "Wogeo",
["wod"] = "Wolani",
["woe"] = "Woleaian",
["wog"] = "Wogamusin",
["woi"] = "Kamang",
["wok"] = "Longto",
["wom"] = "Perema",
["won"] = "Wongo",
["woo"] = "Manombai",
["wor"] = "Woria",
["wos"] = "Hanga Hundi",
["wow"] = "Wawonii",
["wpc"] = "Wirö",
["wra"] = "Warapu",
["wrb"] = "Warluwara",
["wrg"] = "Warungu",
["wrh"] = "Wiradhuri",
["wri"] = "Wariyangga",
["wrk"] = "Garawa",
["wrl"] = "Warlmanpa",
["wrm"] = "Warumungu",
["wrn"] = "Warnang",
["wro"] = "Worora",
["wrp"] = "Waropen",
["wrr"] = "Wardaman",
["wrs"] = "Waris",
["wru"] = "Waru",
["wrv"] = "Waruna",
["wrw"] = "Gugu Warra",
["wrx"] = "Wae Rana",
["wrz"] = "Warray",
["wsa"] = "Warembori",
["wsi"] = "Wusi",
["wsk"] = "Waskia",
["wsr"] = "Owenia",
["wss"] = "Wasa",
["wsu"] = "Wasu",
["wsv"] = "Wotapuri-Katarqalai",
["wtf"] = "Watiwa",
["wth"] = "Wathaurong",
["wti"] = "Berta",
["wtk"] = "Watakataui",
["wtm"] = "Mewati",
["wtw"] = "Wotu",
["wua"] = "Wikngenchera",
["wub"] = "Wunambal",
["wud"] = "Wudu",
["wuh"] = "Wutunhua",
["wul"] = "Silimo",
["wum"] = "Wumbvu",
["wun"] = "Bungu",
["wur"] = "Wurrugu",
["wut"] = "Wutung",
["wuu"] = "Wu",
["wuv"] = "Wuvulu-Aua",
["wux"] = "Wulna",
["wuy"] = "Wauyai",
["wwa"] = "Waama",
["wwo"] = "Dorig",
["wwr"] = "Warrwa",
["www"] = "Wawa",
["wxa"] = "Waxianghua",
["wxw"] = "Wardandi",
["wya"] = "Wyandot",
["wyb"] = "Ngiyambaa",
["wyi"] = "Woiwurrung",
["wym"] = "Vilamovian",
["wyr"] = "Wayoró",
["wyy"] = "Fiji Barat",
["xaa"] = "Arab Andalusia",
["xab"] = "Sambe",
["xac"] = "Kachari",
["xad"] = "Adai",
["xae"] = "Aequian",
["xag"] = "Aghwan",
["xai"] = "Kaimbé",
["xaj"] = "Ararandewára",
["xak"] = "Maku",
["xal"] = "Kalmyk",
["xam"] = "ǀXam",
["xan"] = "Xamtanga",
["xao"] = "Khao",
["xap"] = "Apalachee",
["xaq"] = "Aquitania",
["xar"] = "Karami",
["xas"] = "Kamassian",
["xat"] = "Katawixi",
["xau"] = "Kauwera",
["xav"] = "Xavante",
["xaw"] = "Kawaiisu",
["xay"] = "Kayan Mahakam",
["xbb"] = "Burdekin Hilir",
["xbc"] = "Baktria",
["xbd"] = "Bindal",
["xbe"] = "Bigambal",
["xbg"] = "Bunganditj",
["xbi"] = "Kombio",
["xbj"] = "Birrpayi",
["xbm"] = "Breton Pertengahan",
["xbn"] = "Kenaboi",
["xbo"] = "Bulgar",
["xbp"] = "Bibbulman",
["xbr"] = "Kambera",
["xbw"] = "Kambiwá",
["xby"] = "Butchulla",
["xcb"] = "Cumbric",
["xcc"] = "Camunic",
["xce"] = "Keltiberia",
["xch"] = "Chemakum",
["xcl"] = "Armenia Kuno",
["xcm"] = "Comecrudo",
["xcn"] = "Cotoname",
["xco"] = "Khwarezmian",
["xcr"] = "Carian",
["xct"] = "Tibet Klasik",
["xcu"] = "Curonian",
["xcv"] = "Chuvan",
["xcw"] = "Coahuilteco",
["xcy"] = "Cayuse",
["xda"] = "Darkinjung",
["xdc"] = "Dacian",
["xdk"] = "Dharug",
["xdm"] = "Edomite",
["xdy"] = "Dayak Melayu",
["xeb"] = "Eblaite",
["xed"] = "Hdi",
["xeg"] = "ǁXegwi",
["xel"] = "Kelo",
["xem"] = "Kembayan",
["xep"] = "Epi-Olmec",
["xer"] = "Xerénte",
["xes"] = "Kesawai",
["xet"] = "Xetá",
["xeu"] = "Keoru-Ahia",
["xfa"] = "Faliscan",
["xga"] = "Galatia",
["xgb"] = "Gbin",
["xgd"] = "Gudang",
["xgf"] = "Gabrielino-Fernandeño",
["xgg"] = "Goreng",
["xgi"] = "Garingbal",
["xgl"] = "Galindan",
["xgm"] = "Darumbal",
["xgn-mgl"] = "Mongghul",
["xgn-mgr"] = "Mangghuer",
["xgn-pro"] = "Proto-Mongolia",
["xgn-rou"] = "Rouran",
["xgr"] = "Garza",
["xgu"] = "Unggumi",
["xgw"] = "Guwa",
["xh"] = "Xhosa",
["xha"] = "Harami",
["xhc"] = "Hunnic",
["xhd"] = "Hadrami",
["xhe"] = "Khetrani",
["xhm"] = "Khmer Pertengahan",
["xhr"] = "Hernican",
["xht"] = "Hattic",
["xhu"] = "Hurria",
["xhv"] = "Khua",
["xib"] = "Iberia",
["xii"] = "Xiri",
["xil"] = "Illyria",
["xin"] = "Xinca",
["xir"] = "Xiriâna",
["xis"] = "Kisan",
["xiv"] = "Lembah Indus",
["xiy"] = "Xipaya",
["xjb"] = "Minjungbal",
["xka"] = "Kalkoti",
["xkb"] = "Manigri-Kambolé Ede Nago",
["xkc"] = "Khoini",
["xkd"] = "Kayan Mendalam",
["xke"] = "Kereho",
["xkf"] = "Khengkha",
["xkg"] = "Kagoro",
["xki"] = "Isyarat Kenya",
["xkj"] = "Kajali",
["xkk"] = "Kaco'",
["xkl"] = "Bakung",
["xkn"] = "Kayan Sungai Kayan",
["xko"] = "Kiorr",
["xkp"] = "Kabatei",
["xkq"] = "Koroni",
["xkr"] = "Xakriabá",
["xks"] = "Kumbewaha",
["xkt"] = "Kantosi",
["xku"] = "Kaamba",
["xkv"] = "Kgalagadi",
["xkw"] = "Kembra",
["xkx"] = "Karore",
["xky"] = "Uma' Lasan",
["xkz"] = "Kurtöp",
["xla"] = "Kamula",
["xlb"] = "Loup B",
["xlc"] = "Lycia",
["xld"] = "Lydia",
["xle"] = "Lemnia",
["xlg"] = "Liguria Kuno",
["xli"] = "Liburnian",
["xlo"] = "Loup A",
["xlp"] = "Lepontic",
["xls"] = "Lusitania",
["xlu"] = "Luwia",
["xly"] = "Elymian",
["xmb"] = "Mbonga",
["xmc"] = "Makhuwa-Marrevone",
["xmd"] = "Mbudum",
["xme-ker"] = "Kermanic",
["xme-kls"] = "Kalasuri",
["xme-klt"] = "Kilit",
["xme-mid"] = "Media Pertengahan",
["xme-old"] = "Media Kuno",
["xme-ott"] = "Tati Kuno",
["xme-taf"] = "Tafreshi",
["xme-ttc-pro"] = "Proto-Tatic",
["xmf"] = "Mingrelian",
["xmg"] = "Mengaka",
["xmh"] = "Kugu-Muminh",
["xmj"] = "Majera",
["xmk"] = "Makedonia Kuno",
["xml"] = "Isyarat Malaysia",
["xmm"] = "Melayu Manado",
["xmo"] = "Morerebi",
["xmp"] = "Kuku-Mu'inh",
["xmq"] = "Kuku-Mangk",
["xmr"] = "Meroitic",
["xms"] = "Isyarat Maroko",
["xmt"] = "Matbat",
["xmu"] = "Kamu",
["xmx"] = "Maden",
["xmy"] = "Mayaguduna",
["xmz"] = "Mori Bawah",
["xna"] = "Arab Utara Kuno",
["xnb"] = "Kanakanabu",
["xnd-pro"] = "Proto-Na-Dene",
["xng"] = "Mongol Pertengahan",
["xnh"] = "Kuanhua",
["xni"] = "Ngarigu",
["xnk"] = "Nganakarti",
["xnn"] = "Kankanay Utara",
["xnr"] = "Kangri",
["xns"] = "Kanashi",
["xnt"] = "Narragansett",
["xnu"] = "Nukunul",
["xny"] = "Nyiyaparli",
["xoc"] = "O'chi'chi'",
["xod"] = "Kokoda",
["xog"] = "Soga",
["xoi"] = "Kominimung",
["xok"] = "Xokleng",
["xom"] = "Komo",
["xon"] = "Konkomba",
["xoo"] = "Xukurú",
["xop"] = "Kopar",
["xor"] = "Korubo",
["xow"] = "Kowaki",
["xpa"] = "Pirriya",
["xpb"] = "Pyemmairre",
["xpc"] = "Pecheneg",
["xpd"] = "Paredarerme",
["xpe"] = "Kpelle Liberia",
["xpf"] = "Tasmania Tenggara",
["xpg"] = "Phrygia",
["xph"] = "Tyerrernotepanner",
["xpi"] = "Pictish",
["xpj"] = "Mpalitjanh",
["xpk"] = "Kulina",
["xpl"] = "Port Sorell",
["xpm"] = "Pumpokol",
["xpn"] = "Kapinawá",
["xpo"] = "Pochutec",
["xpp"] = "Puyo-Paekche",
["xpq"] = "Mohegan-Pequot",
["xpr"] = "Parthia",
["xps"] = "Pisidian",
["xpu"] = "Punic",
["xpv"] = "Tommeginne",
["xpw"] = "Peerapper",
["xpx"] = "Toogee",
["xpy"] = "Buyeo",
["xpz"] = "Bruny Island",
["xqa"] = "Karakhanid",
["xqt"] = "Qatabanian",
["xra"] = "Krahô",
["xrb"] = "Karaboro Timur",
["xrd"] = "Gundungurra",
["xre"] = "Kreye",
["xrg"] = "Minang",
["xri"] = "Krikati-Timbira",
["xrm"] = "Armazic",
["xrn"] = "Arin",
["xrq"] = "Karranga",
["xrr"] = "Raetic",
["xrt"] = "Aranama-Tamique",
["xru"] = "Marriammu",
["xrw"] = "Karawa",
["xsa"] = "Sabaean",
["xsb"] = "Sambali",
["xsc-pro"] = "Proto-Scythia",
["xsc-sak-pro"] = "Proto-Saka",
["xsc-skw-pro"] = "Proto-Saka-Wakhi",
["xsd"] = "Sidetic",
["xse"] = "Sempan",
["xsh"] = "Shamang",
["xsi"] = "Sio",
["xsj"] = "Subi",
["xsl"] = "Slavey Selatan",
["xsm"] = "Kasem",
["xsn"] = "Sanga (Nigeria)",
["xso"] = "Solano",
["xsp"] = "Silopi",
["xsq"] = "Makhuwa-Saka",
["xsr"] = "Sherpa",
["xss"] = "Assan",
["xsu"] = "Sanumá",
["xsv"] = "Sudovian",
["xsy"] = "Saisiyat",
["xta"] = "Mixtec Alcozauca",
["xtb"] = "Mixtec Chazumba",
["xtc"] = "Kadugli",
["xtd"] = "Mixtec Diuxi-Tilantongo",
["xte"] = "Ketengban",
["xth"] = "Yitha Yitha",
["xti"] = "Mixtec Sinicahua",
["xtj"] = "Mixtec San Juan Teita",
["xtl"] = "Mixtec Tijaltepec",
["xtm"] = "Mixtec Magdalena Peñasco",
["xtn"] = "Mixtec Tlaxiaco Utara",
["xto"] = "Tocharian A",
["xtp"] = "Mixtec San Miguel Piedras",
["xtq"] = "Tumshuqese",
["xtr"] = "Tripuri Awal",
["xts"] = "Mixtec Sindihui",
["xtt"] = "Mixtec Tacahua",
["xtu"] = "Mixtec Cuyamecalco",
["xtv"] = "Thawa",
["xtw"] = "Tawandê",
["xty"] = "Mixtec Yoloxochitl",
["xtz"] = "Tasmania",
["xua"] = "Kurumba Alu",
["xub"] = "Kurumba Betta",
["xud"] = "Umiida",
["xug"] = "Kunigami",
["xuj"] = "Kurumba Jennu",
["xul"] = "Ngunawal",
["xum"] = "Umbrian",
["xun"] = "Unggaranggu",
["xuo"] = "Kuo",
["xup"] = "Umpqua Hulu",
["xur"] = "Urartian",
["xut"] = "Kuthant",
["xuu"] = "Khwe",
["xve"] = "Venetic",
["xvn"] = "Vandalic",
["xvo"] = "Volscian",
["xvs"] = "Vestinian",
["xwa"] = "Kwaza",
["xwc"] = "Woccon",
["xwd"] = "Wadi Wadi",
["xwe"] = "Gbe Xwela",
["xwg"] = "Kwegu",
["xwj"] = "Wajuk",
["xwk"] = "Wangkumara",
["xwl"] = "Gbe Xwla Barat",
["xwo"] = "Written Oirat",
["xwr"] = "Kwerba Mamberamo",
["xww"] = "Wemba-Wemba",
["xxb"] = "Boro",
["xxk"] = "Ke'o",
["xxm"] = "Minkin",
["xxr"] = "Koropó",
["xxt"] = "Tambora",
["xya"] = "Yaygir",
["xyb"] = "Yandjibara",
["xyl"] = "Yalakalore",
["xyt"] = "Mayi-Thakurti",
["xyy"] = "Yorta Yorta",
["xzh"] = "Zhang-Zhung",
["xzm"] = "Zemgalian",
["xzp"] = "Zapotec Kuno",
["yaa"] = "Yaminahua",
["yab"] = "Yuhup",
["yac"] = "Yali Lembah Pass",
["yad"] = "Yagua",
["yae"] = "Pumé",
["yaf"] = "Yaka",
["yag"] = "Yámana",
["yah"] = "Yazghulami",
["yai"] = "Yagnobi",
["yaj"] = "Banda-Yangere",
["yak"] = "Yakima",
["yal"] = "Yalunka",
["yam"] = "Yamba",
["yan"] = "Mayangna",
["yao"] = "Yao",
["yap"] = "Yapese",
["yaq"] = "Yaqui",
["yar"] = "Yabarana",
["yas"] = "Gunu",
["yat"] = "Yambeta",
["yau"] = "Yuwana",
["yav"] = "Yangben",
["yaw"] = "Yawalapití",
["yay"] = "Agwagwune",
["yaz"] = "Lokaa",
["yba"] = "Yala",
["ybb"] = "Yemba",
["ybe"] = "Yugur Barat",
["ybh"] = "Yakkha",
["ybi"] = "Yamphu",
["ybj"] = "Hasha",
["ybk"] = "Bokha",
["ybl"] = "Yukuben",
["ybm"] = "Yaben",
["ybn"] = "Yabaâna",
["ybo"] = "Yabong",
["ybx"] = "Yawiyo",
["yby"] = "Yaweyuha",
["ych"] = "Chesu",
["ycl"] = "Lolopo",
["ycn"] = "Yucuna",
["ycp"] = "Chepya",
["ycr"] = "Kreol Yilan",
["yda"] = "Yanda",
["yde"] = "Yangum Dey",
["ydg"] = "Yidgha",
["ydk"] = "Yoidik",
["yea"] = "Ravula",
["yec"] = "Yeniche",
["yee"] = "Yimas",
["yei"] = "Yeni",
["yej"] = "Yevanic",
["yen"] = "Yendang",
["yer"] = "Tarok",
["yes"] = "Yeskwa",
["yet"] = "Yetfa",
["yeu"] = "Yerukula",
["yev"] = "Yapunda",
["yey"] = "Yeyi",
["ygi"] = "Yiningayi",
["ygl"] = "Yangum Gel",
["ygm"] = "Yagomi",
["ygp"] = "Gepo",
["ygr"] = "Yagaria",
["ygs"] = "Isyarat Yolngu",
["ygu"] = "Yugul",
["ygw"] = "Yagwoia",
["yha"] = "Baha",
["yhl"] = "Phowa Hlepho",
["yi"] = "Yiddish",
["yia"] = "Yinggarda",
["yif"] = "Ache",
["yig"] = "Nasu Wusa",
["yii"] = "Yidiny",
["yij"] = "Yindjibarndi",
["yik"] = "Lalo Dongshanba",
["yil"] = "Yindjilandji",
["yim"] = "Naga Yimchungru",
["yin"] = "Yinchia",
["yip"] = "Pholo",
["yiq"] = "Miqie",
["yir"] = "Awyu Utara",
["yis"] = "Yis",
["yit"] = "Lalu Timur",
["yiu"] = "Awu",
["yiv"] = "Nisu Utara",
["yix"] = "Yi Axi",
["yiy"] = "Yir-Yoront",
["yiz"] = "Azhe",
["yka"] = "Yakan",
["ykg"] = "Yukaghir Utara",
["ykh"] = "Mongol Khamnigan",
["yki"] = "Yoke",
["ykk"] = "Yakaikeke",
["ykl"] = "Khlula",
["ykm"] = "Kap",
["ykn"] = "Kua-nsi",
["yko"] = "Yasa",
["ykr"] = "Yekora",
["ykt"] = "Kathu",
["yku"] = "Kuamasi",
["yky"] = "Yakoma",
["yla"] = "Yaul",
["ylb"] = "Yaleba",
["yle"] = "Yele",
["ylg"] = "Yelogu",
["yli"] = "Yali Angguruk",
["yll"] = "Yil",
["ylm"] = "Limi",
["yln"] = "Langnian Buyang",
["ylo"] = "Yi Naluo",
["ylr"] = "Yalarnnga",
["ylu"] = "Aribwaung",
["yly"] = "Nyâlayu",
["ymb"] = "Yambes",
["ymc"] = "Muji Selatan",
["ymd"] = "Muda",
["yme"] = "Yameo",
["ymg"] = "Yamongeri",
["ymh"] = "Mili",
["ymi"] = "Moji",
["ymk"] = "Makwe",
["yml"] = "Iamalele",
["ymm"] = "Maay",
["ymn"] = "Sunum",
["ymo"] = "Mon Yangum",
["ymp"] = "Yamap",
["ymq"] = "Muji Qila",
["ymr"] = "Malasar",
["yms"] = "Mysian",
["ymx"] = "Muji Utara",
["ymz"] = "Muzi",
["yna"] = "Aluo",
["ynd"] = "Yandruwandha",
["yne"] = "Lang'e",
["yng"] = "Yango",
["ynk"] = "Naukanski",
["ynl"] = "Yangulam",
["ynn"] = "Yana",
["yno"] = "Yong",
["yns"] = "Yansi",
["ynu"] = "Yahuna",
["yo"] = "Yoruba",
["yob"] = "Yoba",
["yog"] = "Yogad",
["yoi"] = "Yonaguni",
["yol"] = "Yola",
["yom"] = "Yombe",
["yon"] = "Yongkom",
["yox"] = "Yoron",
["yoy"] = "Yoy",
["ypa"] = "Phala",
["ypb"] = "Phowa Labo",
["ypg"] = "Phola",
["yph"] = "Phupha",
["ypk-pro"] = "Proto-Yupik",
["ypm"] = "Phuma",
["ypn"] = "Phowa Ani",
["ypo"] = "Alo Phola",
["ypp"] = "Phupa",
["ypz"] = "Phuza",
["yra"] = "Yerakai",
["yrb"] = "Yareba",
["yre"] = "Yaouré",
["yri"] = "Yarí",
["yrk"] = "Nenets Tundra",
["yrl"] = "Nheengatu",
["yrn"] = "Yerong",
["yro"] = "Yaroamë",
["yrw"] = "Yarawata",
["yry"] = "Yarluyandi",
["ysc"] = "Jassic",
["ysd"] = "Samatao",
["ysg"] = "Sonaga",
["ysl"] = "Isyarat Yugoslavia",
["ysn"] = "Sani",
["yso"] = "Nisi",
["ysp"] = "Lolopo Selatan",
["ysr"] = "Sirenik",
["yss"] = "Yessan-Mayo",
["ysy"] = "Sanie",
["yta"] = "Talu",
["ytl"] = "Tanglang",
["ytp"] = "Thopho",
["ytw"] = "Yout Wam",
["yty"] = "Yatay",
["yua"] = "Maya Yucatec",
["yub"] = "Yugambal",
["yuc"] = "Yuchi",
["yue"] = "Kanton",
["yuf"] = "Havasupai-Walapai-Yavapai",
["yug"] = "Yug",
["yui"] = "Yurutí",
["yuj"] = "Karkar-Yuri",
["yuk"] = "Yuki",
["yul"] = "Yulu",
["yum"] = "Yuma",
["yun"] = "Bena",
["yup"] = "Yukpa",
["yuq"] = "Yuqui",
["yur"] = "Yurok",
["yut"] = "Yopno",
["yuw"] = "Yau Finisterre",
["yux"] = "Yukaghir Selatan",
["yuy"] = "Yugur Timur",
["yuz"] = "Yuracare",
["yva"] = "Yawa",
["yvt"] = "Yavitero",
["ywa"] = "Kalou",
["ywg"] = "Yinhawangka",
["ywl"] = "Lalu Barat",
["ywn"] = "Yawanawa",
["ywq"] = "Nasu",
["ywr"] = "Yawuru",
["ywt"] = "Lalo Xishanba",
["ywu"] = "Nasu Wumeng",
["yww"] = "Yawarawarga",
["yxa"] = "Mayawali",
["yxg"] = "Yagara",
["yxl"] = "Yarli",
["yxm"] = "Yinwum",
["yxu"] = "Yuyu",
["yxy"] = "Yabula Yabula",
["yyu"] = "Yau Torricelli",
["yyz"] = "Ayizi",
["yzg"] = "E'ma Buyang",
["yzk"] = "Zokhuo",
["za"] = "Zhuang",
["zaa"] = "Zapotec Sierra de Juárez",
["zab"] = "Zapotec San Juan Guelavía",
["zac"] = "Zapotec Ocotlán",
["zad"] = "Zapotec Cajonos",
["zae"] = "Zapotec Yareni",
["zaf"] = "Zapotec Ayoquesco",
["zag"] = "Zaghawa",
["zah"] = "Zangwal",
["zai"] = "Zapotec Isthmus",
["zaj"] = "Zaramo",
["zak"] = "Zanaki",
["zal"] = "Zauzou",
["zam"] = "Zapotec Mahuatlán Tengah",
["zao"] = "Zapotec Ozolotepec",
["zap"] = "Zapotec",
["zaq"] = "Zapotec Aloápam",
["zar"] = "Zapotec Rincón",
["zas"] = "Zapotec Santo Domingo Albarradas",
["zat"] = "Zapotec Tabaa",
["zau"] = "Zangskari",
["zav"] = "Zapotec Yatzachi",
["zaw"] = "Zapotec Mitla",
["zax"] = "Zapotec Xadani",
["zay"] = "Zayse-Zergulla",
["zaz"] = "Zari",
["zbt"] = "Batui",
["zca"] = "Zapotec Coatecas Altas",
["zdj"] = "Comorian Ngazidja",
["zea"] = "Zealandic",
["zeg"] = "Zenag",
["zen"] = "Zenaga",
["zga"] = "Kinga",
["zgh"] = "Maroko Amazigh",
["zgr"] = "Magori",
["zh"] = "Tionghoa",
["zhb"] = "Zhaba",
["zhi"] = "Zhire",
["zhn"] = "Zhuang Nong",
["zhw"] = "Zhoa",
["zhx-min-pro"] = "Proto-Min",
["zhx-sht"] = "Tuhua Shaozhou",
["zhx-tai"] = "Taishan",
["zhx-teo"] = "Teochew",
["zia"] = "Zia",
["zib"] = "Isyarat Zimbabwe",
["zik"] = "Zimakani",
["zil"] = "Zialo",
["zim"] = "Mesme",
["zin"] = "Zinza",
["zir"] = "Ziriya",
["ziw"] = "Zigula",
["ziz"] = "Zizilivakan",
["zka"] = "Kaimbulawa",
["zkb"] = "Koibal",
["zkg"] = "Goguryeo",
["zkh"] = "Turkik Khorezmian",
["zkk"] = "Karankawa",
["zko"] = "Kott",
["zkp"] = "São Paulo Kaingáng",
["zkr"] = "Zakhring",
["zkt"] = "Khitan",
["zku"] = "Kaurna",
["zkv"] = "Krevinian",
["zkz"] = "Khazar",
["zle-ono"] = "Novgorod Kuno",
["zle-ort"] = "Ruthenia Kuno",
["zlw-ocs"] = "Ceko Kuno",
["zlw-opl"] = "Polandia Kuno",
["zlw-pom-pro"] = "Proto-Pomerania",
["zlw-slv"] = "Slovincian",
["zma"] = "Manda (Australia)",
["zmb"] = "Zimba",
["zmc"] = "Margany",
["zmd"] = "Maridan",
["zme"] = "Mangerr",
["zmf"] = "Mfinu",
["zmg"] = "Ke Marti",
["zmh"] = "Makolkol",
["zmi"] = "Melayu Negeri Sembilan",
["zmj"] = "Maridjabin",
["zmk"] = "Mandandanyi",
["zml"] = "Madngele",
["zmm"] = "Marimanindji",
["zmn"] = "Mbangwe",
["zmo"] = "Molo",
["zmp"] = "Mbuun",
["zmq"] = "Mituku",
["zmr"] = "Maranungku",
["zms"] = "Mbesa",
["zmt"] = "Maringarr",
["zmu"] = "Muruwari",
["zmv"] = "Mbariman-Gudhinma",
["zmw"] = "Mbo (Kongo)",
["zmx"] = "Bomitaba",
["zmy"] = "Mariyedi",
["zmz"] = "Mbandja",
["zna"] = "Gula Zan",
["zne"] = "Zande",
["zng"] = "Mang",
["znk"] = "Manangkari",
["zns"] = "Mangas",
["zoc"] = "Zoque Copainalá",
["zoh"] = "Zoque Chimalapa",
["zom"] = "Zou",
["zoo"] = "Zapotec Asunción Mixtepec",
["zoq"] = "Zoque Tabasco",
["zor"] = "Zoque Rayón",
["zos"] = "Zoque Francisco León",
["zpa"] = "Zapotec Lachiguiri",
["zpb"] = "Zapotec Yautepec",
["zpc"] = "Zapotec Choapan",
["zpd"] = "Zapotec Ixtlán Tenggara",
["zpe"] = "Zapotec Petapa",
["zpf"] = "Zapotec San Pedro Quiatoni",
["zpg"] = "Zapotec Guevea de Humboldt",
["zph"] = "Zapotec Totomachapan",
["zpi"] = "Zapotec Santa María Quiegolani",
["zpj"] = "Zapotec Quiavicuzas",
["zpk"] = "Zapotec Tlacolulita",
["zpl"] = "Zapotec Lachixío",
["zpm"] = "Zapotec Mixtepec",
["zpn"] = "Zapotec Santa Inés Yatzechi",
["zpo"] = "Zapotec Amatlán",
["zpp"] = "Zapotec El Alto",
["zpq"] = "Zapotec Zoogocho",
["zpr"] = "Zapotec Santiago Xanica",
["zps"] = "Zapotec Coatlán",
["zpt"] = "Zapotec San Vicente Coatlán",
["zpu"] = "Zapotec Yalálag",
["zpv"] = "Zapotec Chichicapan",
["zpw"] = "Zapotec Zaniza",
["zpx"] = "Zapotec San Baltazar Loxicha",
["zpy"] = "Zapotec Mazaltepec",
["zpz"] = "Zapotec Texmelucan",
["zra"] = "Kaya",
["zrg"] = "Mirgan",
["zrn"] = "Zirenkel",
["zro"] = "Záparo",
["zrs"] = "Mairasi",
["zsa"] = "Sarasira",
["zsk"] = "Kaskean",
["zsl"] = "Isyarat Zambia",
["zsr"] = "Zapotec Rincon Selatan",
["zsu"] = "Sukurum",
["zte"] = "Zapotec Elotepec",
["ztg"] = "Zapotec Xanaguía",
["ztl"] = "Zapotec Lapaguía-Guivini",
["ztm"] = "Zapotec San Agustín Mixtepec",
["ztn"] = "Zapotec Santa Catarina Albarradas",
["ztp"] = "Zapotec Loxicha",
["ztq"] = "Zapotec Quioquitani-Quierí",
["zts"] = "Zapotec Tilquiapan",
["ztt"] = "Zapotec Tejalapan",
["ztu"] = "Zapotec San Pablo Güilá",
["ztx"] = "Zapotec Zaachila",
["zty"] = "Zapotec Yatee",
["zu"] = "Zulu",
["zua"] = "Zeem",
["zuh"] = "Tokano",
["zum"] = "Kumzari",
["zun"] = "Zuni",
["zuy"] = "Zumaya",
["zwa"] = "Zay",
["zyp"] = "Zyphe",
["zza"] = "Zazaki",
["zzj"] = "Zhuang Zuojiang",
}
local protoLangs = {
["ine-pro"] = true,
["map-pro"] = true,
["PAN"] = true,
["phi-pro"] = true,
["PMP"] = true,
["poz-pro"] = true,
["poz-mly-pro"] = true
}
-- Interwiki table
local interwikis = {
aa = true, ab = true, af = true, ak = true, am = true, an = true, ang = true,
ar = true, as = true, ast = true, av = true, ay = true, az = true, bcl = true,
be = true, bew = true, bg = true, bh = true, bi = true, bjn = true, blk = true,
bm = true, bn = true, bo = true, br = true, bs = true, btm = true, ca = true,
ch = true, chr = true, ckb = true, co = true, cr = true, cs = true, csb = true,
cy = true, da = true, de = true, diq = true, dv = true, dz = true, el = true,
en = true, eo = true, es = true, et = true, eu = true, fa = true, fi = true,
fj = true, fo = true, fr = true, fy = true, ga = true, gd = true, gl = true,
gn = true, gom = true, gor = true, gu = true, guw = true, gv = true, ha = true,
he = true, hi = true, hif = true, hr = true, hsb = true, hu = true, hy = true,
ia = true, ie = true, ig = true, ik = true, ["io"] = true, ["is"] = true, it = true,
iu = true, ja = true, jbo = true, jv = true, ka = true, kaa = true, kbd = true,
kcg = true, kk = true, kl = true, km = true, kn = true, ko = true, ks = true,
ku = true, kw = true, ky = true, la = true, lb = true, li = true, lmo = true,
ln = true, lo = true, lt = true, lv = true, mad = true, mg = true, mh = true,
mi = true, ["min"] = true, mk = true, ml = true, mn = true, mni = true, mnw = true,
mr = true, ms = true, mt = true, my = true, na = true, nah = true, nds = true,
ne = true, nia = true, nl = true, nn = true, no = true, oc = true, om = true,
["or"] = true, pa = true, pi = true, pl = true, pnb = true, ps = true, pt = true,
qu = true, rm = true, rn = true, ro = true, ru = true, rw = true, sa = true,
sat = true, sc = true, scn = true, sd = true, sg = true, sh = true, shn = true,
shy = true, si = true, sk = true, skr = true, sl = true, sm = true, sn = true,
so = true, sq = true, sr = true, ss = true, st = true, su = true, sv = true,
sw = true, ta = true, tcy = true, te = true, tg = true, th = true, ti = true,
tk = true, tl = true, tn = true, to = true, tpi = true, tr = true, ts = true,
tt = true, tw = true, ug = true, uk = true, ur = true, uz = true, vec = true,
vi = true, vo = true, wa = true, wo = true, xh = true, yi = true, yo = true,
za = true, zh = true, ["zh-min-nan"] = true, zu = true,
-- Mapped codes
mly = "ms", msa = "ms", msi = "ms", zlm = "ms", zsm = "ms", ["nan-hbl"] = "zh-min-nan"
}
-- Return interwiki link
function p.getInterwikiLink(lang, title)
local targetLang = interwikis[lang]
if targetLang == nil then
return lang
elseif targetLang == true then
return string.format("[[:%s:%s|%s]]", lang, title, lang)
else
return string.format("[[:%s:%s|%s]]", targetLang, title, lang)
end
end
-- Get full language name (returns nil if invalid)
function p.getLangName(frame)
local args = frame.args
local code = mw.text.trim(args[1] or "")
local nocap = args.nocap or ""
local name = langNames[code]
if not name then return nil end
local prefix = ""
-- Check if code is a language family
local familyObj = Families.getByCode(code)
if familyObj then
prefix = "Rumpun bahasa "
elseif code ~= "mul" then
prefix = "Bahasa "
end
local fullName = prefix .. name
if nocap == "1" and mw.ustring.len(fullName) > 0 then
local first = mw.ustring.sub(fullName, 1, 1)
local rest = mw.ustring.sub(fullName, 2)
fullName = mw.ustring.lower(first) .. rest
end
return fullName
end
function p.getLangNameByCode(code, nocap)
code = mw.text.trim(code or "")
nocap = nocap or ""
local name = langNames[code]
if not name then return nil end
local prefix = ""
local familyObj = Families.getByCode(code)
if familyObj then
prefix = "Rumpun bahasa "
elseif code ~= "mul" then
prefix = "Bahasa "
end
local fullName = prefix .. name
if nocap == "1" and mw.ustring.len(fullName) > 0 then
local first = mw.ustring.sub(fullName, 1, 1)
local rest = mw.ustring.sub(fullName, 2)
fullName = mw.ustring.lower(first) .. rest
end
return fullName
end
-- Get language code (returns nil if invalid)
function p.getLangCode(frame)
local code = mw.text.trim((frame.args and frame.args[1]) or "")
if langNames[code] then
return code
else
return nil
end
end
function p.getLangCodeByCode(code)
code = mw.text.trim(code or "")
if langNames[code] then
return code
end
return nil
end
-- Expose tables
p.protoLangs = protoLangs
p.langNames = langNames
p.interwikis = interwikis
return p
72qcr3melsj0ofs7102r2g74i70hv2r
26528
26391
2026-07-07T09:55:58Z
Sibiru45
115
1 ralatan matan [[:id:Modul:bahasa]]
26391
Scribunto
text/plain
local p = {}
local langNames = {
["mul"] = "Lintas bahasa",
-- Kode bahasa
["aa"] = "Afar",
["aaa"] = "Ghotuo",
["aab"] = "Alumu-Tesu",
["aac"] = "Ari",
["aad"] = "Amal",
["aaf"] = "Aranadan",
["aag"] = "Ambrak",
["aah"] = "Arapesh Abu'",
["aai"] = "Arifama-Miniafia",
["aak"] = "Ankave",
["aal"] = "Afade",
["aan"] = "Anambé",
["aap"] = "Arára Pará",
["aaq"] = "Penobscot",
["aas"] = "Aasax",
["aau"] = "Abau",
["aav-khs-pro"] = "Proto-Khasian",
["aav-nic-pro"] = "Proto-Nikobar",
["aav-pkl-pro"] = "Proto-Pnar-Khasi-Lyngngam",
["aav-pro"] = "Proto-Austroasiatik",
["aaw"] = "Solong",
["aax"] = "Mandobo Atas",
["aaz"] = "Amarasi",
["ab"] = "Abkhaz",
["aba"] = "Abé",
["abb"] = "Bankon",
["abc"] = "Ayta Ambala",
["abd"] = "Agta Camarines Norte",
["abe"] = "Abenaki",
["abf"] = "Abai Sungai",
["abg"] = "Abaga",
["abh"] = "Arab Tajik",
["abi"] = "Abidji",
["abj"] = "Aka-Bea",
["abl"] = "Abung",
["abm"] = "Abanyom",
["abn"] = "Abua",
["abo"] = "Abon",
["abp"] = "Ayta Abenlen",
["abq"] = "Abaza",
["abr"] = "Abron",
["abs"] = "Malayu Ambon",
["abt"] = "Ambulas",
["abu"] = "Abure",
["abv"] = "Arab Baharna",
["abw"] = "Pal",
["abx"] = "Inabaknon",
["aby"] = "Aneme Wake",
["abz"] = "Abui",
["aca"] = "Achagua",
["acb"] = "Áncá",
["acd"] = "Gikyode",
["ace"] = "Aceh",
["ach"] = "Acholi",
["aci"] = "Aka-Cari",
["ack"] = "Aka-Kora",
["acl"] = "Akar-Bale",
["acm"] = "Arab Irak",
["acn"] = "Achang",
["acp"] = "Acipa Timur",
["acr"] = "Achi",
["acs"] = "Acroá",
["acu"] = "Achuar",
["acv"] = "Achumawi",
["acw"] = "Arab Hijaz",
["acx"] = "Arab Oman",
["acy"] = "Arab Siprus",
["acz"] = "Acheron",
["ada"] = "Adangme",
["adb"] = "Adabe",
["add"] = "Dzodinka",
["ade"] = "Adele",
["adf"] = "Arab Dhofar",
["adg"] = "Andegerebinha",
["adh"] = "Adhola",
["adi"] = "Adi",
["adj"] = "Adioukrou",
["adl"] = "Galo",
["adn"] = "Adang",
["ado"] = "Abu",
["adp"] = "Adap",
["adq"] = "Adangbe",
["adr"] = "Adonara",
["ads"] = "Isyarat Adamorobe",
["adt"] = "Adnyamathanha",
["adu"] = "Aduge",
["adw"] = "Amondawa",
["ady"] = "Adyghe",
["adz"] = "Adzera",
["ae"] = "Avestan",
["aea"] = "Areba",
["aeb"] = "Arab Tunisia",
["aed"] = "Isyarat Argentina",
["aee"] = "Pashayi Timur Laut",
["aek"] = "Haeke",
["ael"] = "Ambele",
["aem"] = "Arem",
["aen"] = "Isyarat Armenia",
["aeq"] = "Aer",
["aer"] = "Arrernte Timur",
["aes"] = "Alsea",
["aeu"] = "Akeu",
["aew"] = "Ambakich",
["aey"] = "Amele",
["aez"] = "Aeka",
["af"] = "Afrikaans",
["afa-pro"] = "Proto-Afroasiatik",
["afb"] = "Arab Teluk",
["afd"] = "Andai",
["afe"] = "Putukwam",
["afg"] = "Isyarat Afghan",
["afh"] = "Afrihili",
["afi"] = "Akrukay",
["afk"] = "Nanubae",
["afn"] = "Defaka",
["afo"] = "Eloyi",
["afp"] = "Tapei",
["afs"] = "Kreol Afro-Seminole",
["aft"] = "Afitti",
["afu"] = "Awutu",
["afz"] = "Obokuitai",
["aga"] = "Aguano",
["agb"] = "Legbo",
["agc"] = "Agatu",
["agd"] = "Agarabi",
["age"] = "Angal",
["agf"] = "Arguni",
["agg"] = "Angor",
["agh"] = "Ngelima",
["agi"] = "Agariya",
["agj"] = "Argobba",
["agk"] = "Agta Isarog",
["agl"] = "Fembe",
["agm"] = "Angaataha",
["agn"] = "Agutaynen",
["ago"] = "Tainae",
["agq"] = "Aghem",
["agr"] = "Aguaruna",
["ags"] = "Esimbi",
["agt"] = "Agta Cagayan Tengah",
["agu"] = "Aguacateca",
["agv"] = "Agta Remontado",
["agw"] = "Kahua",
["agx"] = "Aghul",
["agy"] = "Alta Selatan",
["agz"] = "Agta Mount Iriga",
["aha"] = "Ahanta",
["ahb"] = "Axamb",
["ahg"] = "Qimant",
["ahh"] = "Aghu",
["ahi"] = "Aizi Tiagbamrin",
["ahk"] = "Akha",
["ahl"] = "Igo",
["ahm"] = "Aizi Mobumrin",
["ahn"] = "Àhàn",
["aho"] = "Ahom",
["ahp"] = "Aizi Aproumu",
["ahr"] = "Ahirani",
["ahs"] = "Ashe",
["aht"] = "Ahtna",
["aia"] = "Arosi",
["aib"] = "Aynu",
["aic"] = "Ainbai",
["aid"] = "Alngith",
["aie"] = "Amara",
["aif"] = "Agi",
["aig"] = "Kreol Inggris Antigua dan Barbuda",
["aih"] = "Ai-Cham",
["aii"] = "Neo-Aramaik Asyur",
["aij"] = "Lishanid Noshan",
["aik"] = "Ake",
["ail"] = "Aimele",
["aim"] = "Aimol",
["ain"] = "Ainu",
["aio"] = "Aiton",
["aip"] = "Burumakok",
["air"] = "Airoran",
["ait"] = "Arikem",
["aiw"] = "Aari",
["aix"] = "Aighon",
["aiy"] = "Ali",
["aja"] = "Aja",
["ajg"] = "Adja",
["aji"] = "Ajië",
["ajn"] = "Andajin",
["ajp"] = "Arab Syam Selatan",
["ajw"] = "Ajawa",
["ajz"] = "Karbi Amri",
["ak"] = "Akan",
["akb"] = "Angkola",
["akc"] = "Mpur",
["akd"] = "Ukpet-Ehom",
["ake"] = "Akawaio",
["akf"] = "Akpa",
["akg"] = "Anakalangu",
["akh"] = "Angal Heneng",
["aki"] = "Aiome",
["akj"] = "Jeru",
["akk"] = "Akkadian",
["akl"] = "Aklanon",
["akm"] = "Aka-Bo",
["ako"] = "Akurio",
["akp"] = "Siwu",
["akq"] = "Ak",
["akr"] = "Araki",
["aks"] = "Akaselem",
["akt"] = "Akolet",
["aku"] = "Akum",
["akv"] = "Akhvakh",
["akw"] = "Akwa",
["akx"] = "Aka-Kede",
["aky"] = "Aka-Kol",
["akz"] = "Alabama",
["ala"] = "Alago",
["alc"] = "Kawésqar",
["ald"] = "Alladian",
["ale"] = "Aleut",
["alf"] = "Alege",
["alg-aga"] = "Agawam",
["alg-pro"] = "Proto-Algonquian",
["alh"] = "Alawa",
["ali"] = "Amaimon",
["alj"] = "Alangan",
["alk"] = "Alak",
["all"] = "Allar",
["alm"] = "Amblong",
["alo"] = "Larike-Wakasihu",
["alp"] = "Alune",
["alq"] = "Algonquin",
["alr"] = "Alutor",
["alt"] = "Altai Selatan",
["alu"] = "'Are'are",
["alv-ama"] = "Amasi",
["alv-bgu"] = "Baïnounk Gubëeher",
["alv-bua-pro"] = "Proto-Bua",
["alv-cng-pro"] = "Proto-Cangin",
["alv-edk-pro"] = "Proto-Edekiri",
["alv-edo-pro"] = "Proto-Edoid",
["alv-fli-pro"] = "Proto-Fali",
["alv-gbe-pro"] = "Proto-Gbe",
["alv-gng-pro"] = "Proto-Guang",
["alv-gtm-pro"] = "Proto-Togo Tengah",
["alv-gwa"] = "Gwara",
["alv-hei-pro"] = "Proto-Heiban",
["alv-ido-pro"] = "Proto-Idomoid",
["alv-igb-pro"] = "Proto-Igboid",
["alv-kwa-pro"] = "Proto-Kwa",
["alv-mum-pro"] = "Proto-Mumuye",
["alv-nup-pro"] = "Proto-Nupoid",
["alv-pro"] = "Proto-Atlantik-Kongo",
["alv-von-pro"] = "Proto-Volta-Niger",
["alv-yor-pro"] = "Proto-Yoruba",
["alv-yrd-pro"] = "Proto-Yoruboid",
["alw"] = "Alaba",
["alx"] = "Amol",
["aly"] = "Alyawarr",
["alz"] = "Alur",
["am"] = "Amharik",
["ama"] = "Amanayé",
["amb"] = "Ambo",
["amc"] = "Amahuaca",
["ame"] = "Yanesha'",
["amf"] = "Hamer-Banna",
["amg"] = "Amurdag",
["ami"] = "Amis",
["amj"] = "Amdang",
["amk"] = "Ambai",
["aml"] = "War-Jaintia",
["amm"] = "Ama",
["amn"] = "Amanab",
["amo"] = "Amo",
["amp"] = "Alamblak",
["amq"] = "Amahai",
["amr"] = "Amarakaeri",
["ams"] = "Amami-Oshima Selatan",
["amt"] = "Amto",
["amu"] = "Amuzgo Guerrero",
["amv"] = "Ambelau",
["amw"] = "Neo-Aramaik Barat",
["amx"] = "Anmatyerre",
["amy"] = "Ami",
["amz"] = "Atampaya",
["an"] = "Aragon",
["ana"] = "Andaqui",
["anb"] = "Andoa",
["anc"] = "Ngas",
["and"] = "Ansus",
["ane"] = "Xârâcùù",
["anf"] = "Animere",
["ang"] = "Inggris Kuna",
["anh"] = "Nend",
["ani"] = "Andi",
["anj"] = "Anor",
["ank"] = "Goemai",
["anl"] = "Anu",
["anm"] = "Anal",
["ann"] = "Obolo",
["ano"] = "Andoque",
["anp"] = "Angika",
["anq"] = "Jarawa",
["anr"] = "Andh",
["ans"] = "Anserma",
["ant"] = "Antakarinya",
["anu"] = "Anuak",
["anv"] = "Denya",
["anw"] = "Anaang",
["anx"] = "Andra-Hus",
["any"] = "Anyi",
["anz"] = "Anem",
["aoa"] = "Angolar",
["aob"] = "Abom",
["aoc"] = "Pemon",
["aod"] = "Andarum",
["aoe"] = "Angal Enen",
["aof"] = "Bragat",
["aog"] = "Angoram",
["aoi"] = "Anindilyakwa",
["aoj"] = "Mufian",
["aok"] = "Arhö",
["aol"] = "Alor",
["aom"] = "Ömie",
["aon"] = "Arapesh Bumbita",
["aor"] = "Aore",
["aos"] = "Taikat",
["aot"] = "Atong (India)",
["aou"] = "A'ou",
["aox"] = "Atorada",
["aoz"] = "Uab Meto",
["apa-pro"] = "Proto-Apache",
["apb"] = "Sa'a",
["apc"] = "Arab Syam Utara",
["apd"] = "Arab Sudan",
["ape"] = "Bukiyip",
["apf"] = "Agta Pahanan",
["apg"] = "Ampanang",
["aph"] = "Athpare",
["api"] = "Apiaká",
["apj"] = "Jicarilla",
["apk"] = "Apache Plains",
["apl"] = "Lipan",
["apm"] = "Chiricahua",
["apn"] = "Apinayé",
["apo"] = "Ambul",
["app"] = "Apma",
["apq"] = "A-Pucikwar",
["apr"] = "Arop-Lokep",
["aps"] = "Arop-Sissano",
["apt"] = "Apatani",
["apu"] = "Apurinã",
["apv"] = "Alapmunte",
["apw"] = "Apache Barat",
["apx"] = "Aputai",
["apy"] = "Apalaí",
["apz"] = "Safeyoka",
["aqc"] = "Archi",
["aqd"] = "Dogon Ampari",
["aqg"] = "Arigidi",
["aql-pro"] = "Proto-Algic",
["aqm"] = "Atohwaim",
["aqn"] = "Alta Utara",
["aqp"] = "Atakapa",
["aqr"] = "Arhâ",
["aqt"] = "Angaité",
["aqz"] = "Akuntsu",
["ar"] = "Arab",
["arc"] = "Aramaik",
["ard"] = "Arabana",
["are"] = "Arrernte Barat",
["arh"] = "Arhuaco",
["ari"] = "Arikara",
["arj"] = "Arapaso",
["ark"] = "Arikapú",
["arl"] = "Arabela",
["arn"] = "Mapudungun",
["aro"] = "Araona",
["arp"] = "Arapaho",
["arq"] = "Arab Aljazair",
["arr"] = "Arara-Karo",
["ars"] = "Arab Najdi",
["art-blk"] = "Bolak",
["art-bsp"] = "Black Speech",
["art-com"] = "Communicationssprache",
["art-dtk"] = "Dothraki",
["art-elo"] = "Eloi",
["art-gld"] = "Goa'uld",
["art-lap"] = "Lapine",
["art-man"] = "Mandalorian",
["art-mun"] = "Mundolinco",
["art-nav"] = "Na'vi",
["art-nox"] = "Noxilo",
["art-una"] = "Unas",
["art-vlh"] = "High Valyrian",
["aru"] = "Arua",
["arv"] = "Arbore",
["arw"] = "Arawak",
["arx"] = "Aruá",
["ary"] = "Arab Moroko",
["arz"] = "Arab Mesir",
["as"] = "Assam",
["asa"] = "Pare",
["asb"] = "Assiniboine",
["asc"] = "Asmat Pesisir Casuarina",
["ase"] = "Isyarat Amerika Serikat",
["asf"] = "Auslan",
["asg"] = "Cishingini",
["ash"] = "Abishira",
["asi"] = "Buruwai",
["asj"] = "Nsari",
["ask"] = "Ashkun",
["asl"] = "Asilulu",
["asn"] = "Xingú Asuriní",
["aso"] = "Dano",
["asp"] = "Isyarat Aljazair",
["asq"] = "Isyarat Austria",
["asr"] = "Asuri",
["ass"] = "Ipulo",
["ast"] = "Asturian",
["asu"] = "Tocantins Asurini",
["asv"] = "Asoa",
["asw"] = "Isyarat Aborigin Australia",
["asx"] = "Muratayak",
["asy"] = "Asmat Yaosakor",
["asz"] = "As",
["ata"] = "Pele-Ata",
["atb"] = "Zaiwa",
["atc"] = "Atsahuaca",
["atd"] = "Manobo Ata",
["ate"] = "Atemble",
["atg"] = "Okpela",
["ath-nic"] = "Nicola",
["ath-pro"] = "Proto-Athabaskan",
["ati"] = "Attié",
["atj"] = "Atikamekw",
["atk"] = "Ati",
["atl"] = "Agta Mount Iraya",
["atm"] = "Ata",
["ato"] = "Atong (Kamerun)",
["atp"] = "Atta Pudtol",
["atq"] = "Aralle-Tabulahan",
["atr"] = "Waimiri-Atroari",
["ats"] = "Gros Ventre",
["att"] = "Atta Pamplona",
["atu"] = "Reel",
["atv"] = "Altai Utara",
["atw"] = "Atsugewi",
["atx"] = "Arutani",
["aty"] = "Aneityum",
["atz"] = "Arta",
["aua"] = "Asumboa",
["aub"] = "Alugu",
["auc"] = "Huaorani",
["aud"] = "Anuta",
["auf-pro"] = "Proto-Arawa",
["aug"] = "Aguna",
["auh"] = "Aushi",
["aui"] = "Anuki",
["auj"] = "Awjila",
["auk"] = "Heyo",
["aul"] = "Aulua",
["aum"] = "Asu",
["aun"] = "One Molmo",
["auo"] = "Auyokawa",
["aup"] = "Makayam",
["auq"] = "Anus",
["aur"] = "Aruek",
["aus-alu"] = "Alungul",
["aus-and"] = "Andjingith",
["aus-ang"] = "Angkula",
["aus-arn-pro"] = "Proto-Arnhem",
["aus-bra"] = "Barranbinya",
["aus-brm"] = "Barunggam",
["aus-cww-pro"] = "Proto-New South Wales Tengah",
["aus-dal-pro"] = "Proto-Daly",
["aus-guw"] = "Guwar",
["aus-lsw"] = "Little Swanport",
["aus-mbi"] = "Mbiywom",
["aus-ngk"] = "Ngkoth",
["aus-nyu-pro"] = "Proto-Nyulnyulan",
["aus-pam-pro"] = "Proto-Pama-Nyungan",
["aus-tul"] = "Tulua",
["aus-uwi"] = "Uwinymil",
["aus-wdj-pro"] = "Proto-Iwaidjan",
["aus-won"] = "Wong-gie",
["aus-wul"] = "Wulguru",
["aus-ynk"] = "Yangkaal",
["aut"] = "Austral",
["auu"] = "Auye",
["auw"] = "Awyi",
["aux"] = "Aurá",
["auy"] = "Auyana",
["auz"] = "Arab Uzbek",
["av"] = "Avar",
["avb"] = "Avau",
["avd"] = "Alviri-Vidari",
["avi"] = "Avikam",
["avk"] = "Kotava",
["avm"] = "Angkamuthi",
["avn"] = "Avatime",
["avo"] = "Agavotaguerra",
["avs"] = "Aushiri",
["avt"] = "Au",
["avu"] = "Avokaya",
["avv"] = "Avá-Canoeiro",
["awa"] = "Awadhi",
["awb"] = "Awa (Papua)",
["awc"] = "Cicipu",
["awd-ama"] = "Amarizana",
["awd-amc-pro"] = "Proto-Amuesha-Chamicuro",
["awd-ana"] = "Anauyá",
["awd-apo"] = "Apolista",
["awd-cav"] = "Cavere",
["awd-gnu"] = "Guinau",
["awd-kar"] = "Cariay",
["awd-kaw"] = "Kawishana",
["awd-kmp-pro"] = "Proto-Kampa",
["awd-kus"] = "Kustenau",
["awd-man"] = "Manao",
["awd-mar"] = "Marawan",
["awd-mpr"] = "Maypure",
["awd-mrt"] = "Mariaté",
["awd-nwk-pro"] = "Proto-Nawiki",
["awd-pai"] = "Paikoneka",
["awd-pas"] = "Passé",
["awd-pro"] = "Proto-Arawak",
["awd-prw-pro"] = "Proto-Paresi-Waura",
["awd-she"] = "Shebayo",
["awd-taa-pro"] = "Proto-Ta-Arawak",
["awd-wai"] = "Wainumá",
["awd-yum"] = "Yumana",
["awe"] = "Awetí",
["awg"] = "Anguthimri",
["awh"] = "Awbono",
["awi"] = "Aekyom",
["awk"] = "Awabakal",
["awm"] = "Arawum",
["awn"] = "Awngi",
["awo"] = "Awak",
["awr"] = "Awera",
["aws"] = "Awyu Selatan",
["awt"] = "Araweté",
["awu"] = "Awyu Tengah",
["awv"] = "Awyu Jair",
["aww"] = "Awun",
["awx"] = "Awara",
["awy"] = "Awyu Edera",
["axb"] = "Abipon",
["axe"] = "Ayerrerenge",
["axg"] = "Arára Mato Grosso",
["axk"] = "Aka (Afrika Tengah)",
["axl"] = "Aranda Selatan Bawah",
["axm"] = "Armenia Tengahan",
["axx"] = "Xaragure",
["ay"] = "Aymara",
["aya"] = "Awar",
["ayb"] = "Ayizo",
["ayd"] = "Ayabadhu",
["aye"] = "Ayere",
["ayg"] = "Nyanga (Togo)",
["ayi"] = "Leyigha",
["ayk"] = "Akuku",
["ayl"] = "Arab Libya",
["ayn"] = "Arab Yemen",
["ayo"] = "Ayoreo",
["ayp"] = "Arab Mesopotamia Utara",
["ayq"] = "Ayi",
["ays"] = "Sorsogon Ayta",
["ayt"] = "Ayta Bataan",
["ayu"] = "Ayu",
["ayy"] = "Ayta Tayabas",
["ayz"] = "Maybrat",
["az"] = "Azerbaijan",
["aza"] = "Azha",
["azc-caz"] = "Cazcan",
["azc-cup-pro"] = "Proto-Cupan",
["azc-ktn"] = "Kitanemuk",
["azc-nah-pro"] = "Proto-Nahuan",
["azc-num-pro"] = "Proto-Numic",
["azc-pro"] = "Proto-Uto-Aztecan",
["azc-tak-pro"] = "Proto-Takic",
["azc-tat"] = "Tataviam",
["azd"] = "Nahuatl Durango Timur",
["azg"] = "Amuzgo San Pedro Amuzgos",
["azm"] = "Amuzgo Ipalapa",
["azn"] = "Nahuatl Durango Barat",
["azo"] = "Awing",
["azt"] = "Atta Faire",
["azz"] = "Nahuatl Pegunungan Puebla",
["ba"] = "Bashkir",
["baa"] = "Babatana",
["bab"] = "Bainouk-Gunyuño",
["bac"] = "Badui",
["bae"] = "Baré",
["baf"] = "Nubaca",
["bag"] = "Tuki",
["bah"] = "Kreol Bahama",
["baj"] = "Barakai",
["bal"] = "Baluchi",
["ban"] = "Bali",
["bao"] = "Waimaha",
["bap"] = "Bantawa",
["bar"] = "Bavarian",
["bas"] = "Basaa",
["bau"] = "Badanchi",
["bav"] = "Babungo",
["baw"] = "Bambili-Bambui",
["bax"] = "Bamum",
["bay"] = "Batuley",
["bba"] = "Baatonum",
["bbb"] = "Barai",
["bbc"] = "Batak Toba",
["bbd"] = "Bau",
["bbe"] = "Bangba",
["bbf"] = "Baibai",
["bbg"] = "Barama",
["bbh"] = "Bugan",
["bbi"] = "Barombi",
["bbj"] = "Ghomala'",
["bbk"] = "Babanki",
["bbl"] = "Bats",
["bbm"] = "Babango",
["bbn"] = "Uneapa",
["bbo"] = "Konabéré",
["bbp"] = "Banda Tengah Barat",
["bbq"] = "Bamali",
["bbr"] = "Girawa",
["bbs"] = "Bakpinka",
["bbt"] = "Mburku",
["bbu"] = "Bakulung",
["bbv"] = "Karnai",
["bbw"] = "Baba",
["bbx"] = "Bubia",
["bby"] = "Befang",
["bca"] = "Bai Tengah",
["bcb"] = "Bainouk-Samik",
["bcd"] = "Babar Utara",
["bce"] = "Bamenyam",
["bcf"] = "Bamu",
["bcg"] = "Baga Pokur",
["bch"] = "Bariai",
["bci"] = "Baoule",
["bcj"] = "Bardi",
["bck"] = "Bunaba",
["bcl"] = "Bikol Tengah",
["bcm"] = "Banoni",
["bcn"] = "Bibaali",
["bco"] = "Kaluli",
["bcp"] = "Bali (Kongo)",
["bcq"] = "Bench",
["bcr"] = "Babine-Witsuwit'en",
["bcs"] = "Kohumono",
["bct"] = "Bendi",
["bcu"] = "Biliau",
["bcv"] = "Shoo-Minda-Nye",
["bcw"] = "Bana",
["bcy"] = "Bacama",
["bcz"] = "Bainouk-Gunyaamolo",
["bda"] = "Bayot",
["bdb"] = "Basap",
["bdc"] = "Emberá-Baudó",
["bdd"] = "Bunama",
["bde"] = "Bade",
["bdf"] = "Biage",
["bdg"] = "Bonggi",
["bdh"] = "Tara Baka",
["bdi"] = "Burun",
["bdj"] = "Bai",
["bdk"] = "Budukh",
["bdl"] = "Bajau (Indunisia)",
["bdm"] = "Buduma",
["bdn"] = "Baldemu",
["bdo"] = "Morom",
["bdp"] = "Bende",
["bdq"] = "Bahnar",
["bdr"] = "Bajau Pesisir Barat",
["bds"] = "Burunge",
["bdt"] = "Bokoto",
["bdu"] = "Oroko",
["bdv"] = "Bodo Parja",
["bdw"] = "Baham",
["bdx"] = "Budong-Budong",
["bdy"] = "Bandjalang",
["bdz"] = "Badeshi",
["be"] = "Belarus",
["bea"] = "Beaver",
["beb"] = "Bebele",
["bec"] = "Iceve-Maci",
["bed"] = "Bedoanas",
["bee"] = "Byangsi",
["bef"] = "Benabena",
["beg"] = "Belait",
["beh"] = "Biali",
["bei"] = "Bekati'",
["bej"] = "Beja",
["bek"] = "Bebeli",
["bem"] = "Bemba",
["beo"] = "Beami",
["bep"] = "Besoa",
["beq"] = "Beembe",
["ber-fog"] = "Fogaha",
["ber-pro"] = "Proto-Berber",
["ber-zuw"] = "Zuwara",
["bes"] = "Besme",
["bet"] = "Bété Guiberoua",
["beu"] = "Blagar",
["bev"] = "Bété Daloa",
["bew"] = "Betawi",
["bex"] = "Jur Modo",
["bey"] = "Akuwagel",
["bez"] = "Kibena",
["bfa"] = "Bari",
["bfb"] = "Bareli Pauri",
["bfc"] = "Bai Utara",
["bfd"] = "Bafut",
["bfe"] = "Betaf",
["bff"] = "Bofi",
["bfg"] = "Kayan Busang",
["bfh"] = "Blafe",
["bfi"] = "Isyarat Britania",
["bfj"] = "Bafanji",
["bfk"] = "Isyarat Ban Khor",
["bfl"] = "Banda-Ndélé",
["bfm"] = "Mmen",
["bfn"] = "Bunak",
["bfo"] = "Birifor Malba",
["bfp"] = "Beba",
["bfq"] = "Badaga",
["bfr"] = "Bazigar",
["bfs"] = "Bai Selatan",
["bft"] = "Balti",
["bfu"] = "Gahri",
["bfw"] = "Bondo",
["bfx"] = "Bantayanon",
["bfy"] = "Bagheli",
["bfz"] = "Pahari Mahasu",
["bg"] = "Bulgaria",
["bga"] = "Gwamhi-Wuri",
["bgb"] = "Bobongko",
["bgc"] = "Haryanvi",
["bgd"] = "Bareli Rathwi",
["bge"] = "Bauria",
["bgf"] = "Bangandu",
["bgg"] = "Bugun",
["bgi"] = "Giangan",
["bgj"] = "Bangolan",
["bgk"] = "Bit",
["bgl"] = "Bo",
["bgo"] = "Baga Koga",
["bgq"] = "Bagri",
["bgr"] = "Chin Bawm",
["bgs"] = "Tagabawa",
["bgt"] = "Bughotu",
["bgu"] = "Mbongno",
["bgv"] = "Warkay-Bipim",
["bgw"] = "Bhatri",
["bgx"] = "Turki Balkan Gagauz",
["bgy"] = "Benggoi",
["bgz"] = "Banggai",
["bh"] = "Bihar",
["bha"] = "Bharia",
["bhb"] = "Bhili",
["bhc"] = "Biga",
["bhd"] = "Bhadrawahi",
["bhe"] = "Bhaya",
["bhf"] = "Odiai",
["bhg"] = "Binandere",
["bhh"] = "Bukhari",
["bhi"] = "Bhilali",
["bhj"] = "Bahing",
["bhl"] = "Bimin",
["bhm"] = "Bathari",
["bhn"] = "Neo-Aramaik Bohtan",
["bho"] = "Bhojpuri",
["bhp"] = "Bima",
["bhq"] = "Tukang Besi Selatan",
["bhs"] = "Buwal",
["bht"] = "Bhattiyali",
["bhu"] = "Bhunjia",
["bhv"] = "Bahau",
["bhw"] = "Biak",
["bhx"] = "Bhalay",
["bhy"] = "Bhele",
["bhz"] = "Bada",
["bi"] = "Bislama",
["bia"] = "Badimaya",
["bib"] = "Bissa",
["bic"] = "Bikaru",
["bid"] = "Bidiyo",
["bie"] = "Bepour",
["bif"] = "Biafada",
["big"] = "Biangai",
["bij"] = "Kwanka",
["bil"] = "Bile",
["bim"] = "Bimoba",
["bin"] = "Edo",
["bio"] = "Nai",
["bip"] = "Bila",
["biq"] = "Bipi",
["bir"] = "Bisorio",
["bit"] = "Berinomo",
["biu"] = "Biete",
["biv"] = "Birifor Selatan",
["biw"] = "Kol (Kamerun)",
["bix"] = "Bijori",
["biy"] = "Birhor",
["biz"] = "Baloi",
["bja"] = "Budza",
["bjb"] = "Barngarla",
["bjc"] = "Bariji",
["bje"] = "Mien Biao-Jiao",
["bjf"] = "Neo-Aramaik Barzani Jewish",
["bjg"] = "Bidyogo",
["bjh"] = "Bahinemo",
["bji"] = "Burji",
["bjj"] = "Kannauji",
["bjk"] = "Barok",
["bjl"] = "Bulu (Papua)",
["bjm"] = "Bajelani",
["bjn"] = "Banjar",
["bjo"] = "Banda Selatan-Tengah",
["bjp"] = "Fanamaket",
["bjr"] = "Binumarien",
["bjs"] = "Bajan",
["bjt"] = "Balanta-Ganja",
["bju"] = "Busuu",
["bjv"] = "Bedjond",
["bjw"] = "Bakwé",
["bjx"] = "Itneg Banao",
["bjy"] = "Bayali",
["bjz"] = "Baruga",
["bka"] = "Kyak",
["bkc"] = "Baka",
["bkd"] = "Binukid",
["bkf"] = "Beeke",
["bkg"] = "Buraka",
["bkh"] = "Bakoko",
["bki"] = "Baki",
["bkj"] = "Pande",
["bkk"] = "Brokskat",
["bkl"] = "Berik",
["bkm"] = "Kom (Kamerun)",
["bkn"] = "Bukitan",
["bko"] = "Kwa'",
["bkp"] = "Iboko",
["bkq"] = "Bakairí",
["bkr"] = "Bakumpai",
["bks"] = "Sorsogon Masbate",
["bkt"] = "Boloki",
["bku"] = "Buhid",
["bkv"] = "Bekwarra",
["bkw"] = "Bekwel",
["bkx"] = "Baikeno",
["bky"] = "Bokyi",
["bkz"] = "Bungku",
["bla"] = "Blackfoot",
["blb"] = "Bilua",
["blc"] = "Bella Coola",
["bld"] = "Bolango",
["ble"] = "Balanta-Kentohe",
["blf"] = "Buol",
["blg"] = "Balau",
["blh"] = "Kuwaa",
["bli"] = "Bolia",
["blj"] = "Bolongan",
["blk"] = "Karen Pa'o",
["bll"] = "Biloxi",
["blm"] = "Beli",
["bln"] = "Bicolano Catanduanes Selatan",
["blo"] = "Anii",
["blp"] = "Blablanga",
["blq"] = "Baluan-Pam",
["blr"] = "Blang",
["bls"] = "Balaesang",
["blt"] = "Tai Dam",
["blv"] = "Kibala",
["blw"] = "Balangao",
["blx"] = "Ayta Mag-Indi",
["bly"] = "Notre",
["blz"] = "Balantak",
["bm"] = "Bambara",
["bma"] = "Lame",
["bmb"] = "Bembe",
["bmc"] = "Biem",
["bmd"] = "Baga Manduri",
["bme"] = "Limassa",
["bmf"] = "Bom",
["bmg"] = "Bamwe",
["bmh"] = "Kein",
["bmi"] = "Bagirmi",
["bmj"] = "Bote-Majhi",
["bmk"] = "Ghayavi",
["bml"] = "Bomboli",
["bmn"] = "Bina",
["bmo"] = "Bambalang",
["bmp"] = "Bulgebi",
["bmq"] = "Bomu",
["bmr"] = "Muinane",
["bmt"] = "Mon Biao",
["bmu"] = "Somba-Siawari",
["bmv"] = "Bum",
["bmw"] = "Bomwali",
["bmx"] = "Baimak",
["bmz"] = "Baramu",
["bn"] = "Bengal",
["bna"] = "Bonerate",
["bnb"] = "Bookan",
["bnd"] = "Banda",
["bne"] = "Bintauna",
["bnf"] = "Masiwang",
["bng"] = "Benga",
["bni"] = "Bangi",
["bnj"] = "Tawbuid Timur",
["bnk"] = "Bierebo",
["bnl"] = "Boon",
["bnm"] = "Batanga",
["bnn"] = "Bunun",
["bno"] = "Asi",
["bnp"] = "Bola",
["bnq"] = "Bantik",
["bnr"] = "Butmas-Tur",
["bns"] = "Bundeli",
["bnt-bal"] = "Balong",
["bnt-bon"] = "Boma Nkuu",
["bnt-boy"] = "Boma Yumu",
["bnt-bwa"] = "Bwala",
["bnt-cmw"] = "Chimwiini",
["bnt-ind"] = "Indanga",
["bnt-lal"] = "Lala (Afrika Selatan)",
["bnt-lwl"] = "Lwel",
["bnt-mpi"] = "Mpiin",
["bnt-mpu"] = "Mpuono",
["bnt-ngu-pro"] = "Proto-Nguni",
["bnt-phu"] = "Phuthi",
["bnt-pro"] = "Proto-Bantu",
["bnt-sbo"] = "Boma Selatan",
["bnt-sts-pro"] = "Proto-Sotho-Tswana",
["bnu"] = "Bentong",
["bnv"] = "Beneraf",
["bnw"] = "Bisis",
["bnx"] = "Bangubangu",
["bny"] = "Bintulu",
["bnz"] = "Beezen",
["bo"] = "Tibet",
["boa"] = "Bora",
["bob"] = "Aweer",
["boe"] = "Mundabli",
["bof"] = "Bolon",
["bog"] = "Isyarat Bamako",
["boh"] = "Boma Utara",
["boi"] = "Barbareño",
["boj"] = "Anjam",
["bok"] = "Bonjo",
["bol"] = "Bole",
["bom"] = "Berom",
["bon"] = "Bine",
["boo"] = "Bozo Tiemacèwè",
["bop"] = "Bonkiman",
["boq"] = "Bogaya",
["bor"] = "Borôro",
["bot"] = "Bongo",
["bou"] = "Bondei",
["bov"] = "Tuwuli",
["bow"] = "Rema",
["box"] = "Buamu",
["boy"] = "Bodo (Afrika Tengah)",
["boz"] = "Bozo Tiéyaxo",
["bpa"] = "Dakaka",
["bpd"] = "Banda-Banda",
["bpg"] = "Bonggo",
["bph"] = "Botlikh",
["bpi"] = "Bagupi",
["bpj"] = "Binji",
["bpk"] = "Orowe",
["bpl"] = "Pijin Broome Pearling Lugger",
["bpm"] = "Biyom",
["bpn"] = "Dzao Min",
["bpo"] = "Anasi",
["bpp"] = "Kaure",
["bpq"] = "Malayu Banda",
["bpr"] = "Blaan Koronadal",
["bps"] = "Blaan Sarangani",
["bpt"] = "Barrow Point",
["bpu"] = "Bongu",
["bpv"] = "Marind Bian",
["bpx"] = "Bareli Palya",
["bpy"] = "Manipur Bishnupriya",
["bpz"] = "Bilba",
["bqa"] = "Tchumbuli",
["bqb"] = "Bagusa",
["bqc"] = "Boko",
["bqd"] = "Bung",
["bqf"] = "Baga Kaloum",
["bqg"] = "Bago-Kusuntu",
["bqh"] = "Baima",
["bqi"] = "Bakhtiari",
["bqj"] = "Bandial",
["bqk"] = "Banda-Mbrès",
["bql"] = "Bilakura",
["bqm"] = "Wumboko",
["bqn"] = "Isyarat Bulgaria",
["bqo"] = "Balo",
["bqp"] = "Busa",
["bqq"] = "Biritai",
["bqr"] = "Burusu",
["bqs"] = "Bosngun",
["bqt"] = "Bamukumbit",
["bqu"] = "Boguru",
["bqv"] = "Begbere-Ejar",
["bqw"] = "Buru (Nigeria)",
["bqx"] = "Baangi",
["bqy"] = "Isyarat Bengkala",
["bqz"] = "Bakaka",
["br"] = "Breton",
["bra"] = "Braj",
["brb"] = "Lave",
["brc"] = "Kreol Walanda Berbice",
["brd"] = "Baraamu",
["brf"] = "Bera",
["brg"] = "Baure",
["brh"] = "Brahui",
["bri"] = "Mokpwe",
["brj"] = "Bieria",
["brk"] = "Birgid",
["brl"] = "Birwa",
["brm"] = "Barambu",
["brn"] = "Boruca",
["bro"] = "Brokkat",
["brp"] = "Barapasi",
["brq"] = "Breri",
["brr"] = "Birao",
["brs"] = "Baras",
["brt"] = "Bitare",
["bru"] = "Bru Timur",
["brv"] = "Bru Barat",
["brw"] = "Bellari",
["brx"] = "Bodo (India)",
["bry"] = "Burui",
["brz"] = "Bilbil",
["bsa"] = "Abinomn",
["bsb"] = "Bisaya Brunei",
["bsc"] = "Bassari",
["bse"] = "Wushi",
["bsf"] = "Bauchi",
["bsg"] = "Bashkardi",
["bsh"] = "Kamkata-viri",
["bsi"] = "Bassossi",
["bsj"] = "Bangwinji",
["bsk"] = "Burushaski",
["bsl"] = "Basa-Gumna",
["bsm"] = "Busami",
["bsn"] = "Barasana",
["bso"] = "Buso",
["bsp"] = "Baga Sitemu",
["bsq"] = "Bassa",
["bsr"] = "Bassa-Kontagora",
["bss"] = "Akoose",
["bst"] = "Basketo",
["bsu"] = "Bahonsuai",
["bsv"] = "Baga Sobané",
["bsw"] = "Baiso",
["bsx"] = "Yangkam",
["bsy"] = "Bisaya Sabah",
["bta"] = "Bata",
["btc"] = "Bati (Kamerun)",
["btd"] = "Pakpak",
["bte"] = "Gamo-Ningi",
["btf"] = "Birgit",
["btg"] = "Bété Gagnoa",
["bth"] = "Bidayuh Biatah",
["bti"] = "Burate",
["btj"] = "Malayu Bacan",
["btk-pro"] = "Proto-Batak",
["btm"] = "Mandailing",
["btn"] = "Ratagnon",
["bto"] = "Bicolano Iriga",
["btp"] = "Budibud",
["btq"] = "Batek",
["btr"] = "Baetora",
["bts"] = "Simalungun",
["btt"] = "Bete-Bendi",
["btu"] = "Batu",
["btv"] = "Bateri",
["btw"] = "Butuanon",
["btx"] = "Karo",
["bty"] = "Bobot",
["btz"] = "Alas-Kluet",
["bua"] = "Buryat",
["bub"] = "Bua",
["bud"] = "Ntcham",
["bue"] = "Beothuk",
["buf"] = "Bushoong",
["bug"] = "Bugis",
["buh"] = "Bunu Younuo",
["bui"] = "Bongili",
["buj"] = "Basa-Gurmana",
["buk"] = "Bukawa",
["bum"] = "Bulu (Kamerun)",
["bun"] = "Sherbro",
["buo"] = "Terei",
["bup"] = "Busoa",
["buq"] = "Brem",
["bus"] = "Bokobaru",
["but"] = "Bungain",
["buu"] = "Budu",
["buv"] = "Bun",
["buw"] = "Bubi",
["bux"] = "Boghom",
["buy"] = "Mmani",
["bva"] = "Barein",
["bvb"] = "Bube",
["bvc"] = "Baelelea",
["bvd"] = "Baeggu",
["bve"] = "Berau",
["bvf"] = "Boor",
["bvg"] = "Bonkeng",
["bvh"] = "Bure",
["bvi"] = "Walanda Viri",
["bvj"] = "Baan",
["bvk"] = "Bukat",
["bvl"] = "Isyarat Bolivia",
["bvm"] = "Bamunka",
["bvn"] = "Buna",
["bvo"] = "Bolgo",
["bvp"] = "Bumang",
["bvq"] = "Birri",
["bvr"] = "Burarra",
["bvt"] = "Bati (Indunisia)",
["bvu"] = "Malayu Bukit",
["bvv"] = "Baniva",
["bvw"] = "Boga",
["bvx"] = "Babole",
["bvy"] = "Baybayanon",
["bvz"] = "Bauzi",
["bwa"] = "Bwatoo",
["bwb"] = "Namosi-Naitasiri-Serua",
["bwc"] = "Bwile",
["bwd"] = "Bwaidoka",
["bwe"] = "Karen Bwe",
["bwf"] = "Boselewa",
["bwg"] = "Barwe",
["bwh"] = "Bishuo",
["bwi"] = "Baniwa",
["bwj"] = "Bwamu Láá Láá",
["bwk"] = "Bauwaki",
["bwl"] = "Bwela",
["bwm"] = "Biwat",
["bwn"] = "Bunu Wunai",
["bwo"] = "Shinasha",
["bwp"] = "Mandobo Bawah",
["bwq"] = "Bobo Selatan",
["bwr"] = "Bura",
["bws"] = "Bomboma",
["bwt"] = "Bafaw",
["bwu"] = "Buli (Ghana)",
["bww"] = "Bwa",
["bwx"] = "Bunu Bu-Nao",
["bwy"] = "Bwamu Cwi",
["bwz"] = "Bwisi",
["bxa"] = "Bauro",
["bxb"] = "Walanda Bor",
["bxc"] = "Molengue",
["bxd"] = "Pela",
["bxe"] = "Ongota",
["bxf"] = "Bilur",
["bxg"] = "Bangala",
["bxh"] = "Buhutu",
["bxi"] = "Pirlatapa",
["bxj"] = "Bayungu",
["bxk"] = "Bukusu",
["bxl"] = "Jalkunan",
["bxn"] = "Burduna",
["bxo"] = "Barikanchi",
["bxp"] = "Bebil",
["bxq"] = "Beele",
["bxs"] = "Busam",
["bxv"] = "Berakou",
["bxw"] = "Banka",
["bxz"] = "Binahari",
["bya"] = "Batak Palawan",
["byb"] = "Bikya",
["byc"] = "Ubaghara",
["byd"] = "Benyadu'",
["bye"] = "Pouye",
["byf"] = "Bete",
["byg"] = "Baygo",
["byh"] = "Bujhyal",
["byi"] = "Buyu",
["byj"] = "Binawa",
["byk"] = "Biao",
["byl"] = "Bayono",
["bym"] = "Bidyara",
["byn"] = "Blin",
["byo"] = "Biyo",
["byp"] = "Bumaji",
["byq"] = "Basay",
["byr"] = "Baruya",
["bys"] = "Burak",
["byt"] = "Berti",
["byv"] = "Medumba",
["byw"] = "Belhariya",
["byx"] = "Qaqet",
["byz"] = "Banaro",
["bza"] = "Bandi",
["bzb"] = "Andio",
["bzd"] = "Bribri",
["bze"] = "Bozo Jenaama",
["bzf"] = "Boikin",
["bzg"] = "Babuza",
["bzh"] = "Buang Mapos",
["bzi"] = "Bisu",
["bzj"] = "Kreol Belize",
["bzk"] = "Kreol Nikaragua",
["bzl"] = "Boano (Sulawesi)",
["bzm"] = "Bolondo",
["bzn"] = "Boano (Maluku)",
["bzo"] = "Bozaba",
["bzp"] = "Kemberano",
["bzq"] = "Buli (Indunisia)",
["bzr"] = "Biri",
["bzs"] = "Isyarat Brasil",
["bzu"] = "Burmeso",
["bzv"] = "Bebe",
["bzw"] = "Basa",
["bzx"] = "Bozo Hainyaxo",
["bzy"] = "Obanliku",
["bzz"] = "Evant",
["ca"] = "Katala",
["caa"] = "Ch'orti'",
["cab"] = "Garifuna",
["cac"] = "Chuj",
["cad"] = "Caddo",
["cae"] = "Laalaa",
["caf"] = "Carrier Selatan",
["cag"] = "Nivaclé",
["cah"] = "Cahuarano",
["caj"] = "Chané",
["cak"] = "Kaqchikel",
["cal"] = "Carolinian",
["cam"] = "Cemuhî",
["can"] = "Chambri",
["cao"] = "Chácobo",
["cap"] = "Chipaya",
["caq"] = "Nikobar Car",
["car"] = "Carib Galibi",
["cas"] = "Tsimané",
["cau-abz-pro"] = "Proto-Abkhaz-Abaza",
["cau-ava-pro"] = "Proto-Avaro-Andian",
["cau-cir-pro"] = "Proto-Circassian",
["cau-drg-pro"] = "Proto-Dargwa",
["cau-lzg-pro"] = "Proto-Lezghian",
["cau-nec-pro"] = "Proto-Kaukasia Timur Laut",
["cau-nkh-pro"] = "Proto-Nakh",
["cau-nwc-pro"] = "Proto-Kaukasia Barat Laut",
["cau-tsz-pro"] = "Proto-Tsezian",
["cav"] = "Cavineña",
["caw"] = "Callawalla",
["cax"] = "Chiquitano",
["cay"] = "Cayuga",
["caz"] = "Canichana",
["cba-ata"] = "Atanques",
["cba-cat"] = "Chibcha Catío",
["cba-dor"] = "Dorasque",
["cba-dui"] = "Duit",
["cba-hue"] = "Huetar",
["cba-nut"] = "Nutabe",
["cba-pro"] = "Proto-Chibcha",
["cbb"] = "Cabiyarí",
["cbc"] = "Carapana",
["cbd"] = "Carijona",
["cbg"] = "Chimila",
["cbi"] = "Chachi",
["cbj"] = "Ede Cabe",
["cbk"] = "Chavacano",
["cbl"] = "Chin Bualkhaw",
["cbn"] = "Kur Nyah",
["cbo"] = "Izora",
["cbq"] = "Shuba",
["cbr"] = "Cashibo-Cacataibo",
["cbs"] = "Cashinahua",
["cbt"] = "Chayahuita",
["cbu"] = "Candoshi-Shapra",
["cbv"] = "Cacua",
["cbw"] = "Kinabalian",
["cby"] = "Carabayo",
["cca"] = "Cauca",
["ccc"] = "Chamicuro",
["ccd"] = "Cafundó",
["cce"] = "Chopi",
["ccg"] = "Chamba Daka",
["cch"] = "Atsam",
["ccj"] = "Kasanga",
["ccl"] = "Cutchi-Swahili",
["ccm"] = "Kreol Malayu Malaka",
["ccn-pro"] = "Proto-Kaukasia Utara",
["cco"] = "Chinantec Comaltepec",
["ccp"] = "Chakma",
["ccr"] = "Cacaopera",
["ccs-gzn-pro"] = "Proto-Georgia-Zan",
["ccs-pro"] = "Proto-Kartvelian",
["cda"] = "Choni",
["cdc-cbm-pro"] = "Proto-Chad Tengah",
["cdc-mas-pro"] = "Proto-Masa",
["cdc-pro"] = "Proto-Chadic",
["cdd-pro"] = "Proto-Caddo",
["cde"] = "Chenchu",
["cdf"] = "Chiru",
["cdh"] = "Chambeali",
["cdi"] = "Chodri",
["cdj"] = "Churahi",
["cdm"] = "Chepang",
["cdn"] = "Chaudangsi",
["cdo"] = "Min Dong",
["cdr"] = "Cinda-Regi-Tiyal",
["cds"] = "Isyarat Chad",
["cdy"] = "Chadong",
["cdz"] = "Koda",
["ce"] = "Chechen",
["cea"] = "Chehalis Hilir",
["ceb"] = "Cebuano",
["ceg"] = "Chamacoco",
["cel-bry-pro"] = "Proto-Brythonic",
["cel-gal"] = "Gallaecian",
["cel-gau"] = "Gaulish",
["cel-pro"] = "Proto-Keltik",
["cen"] = "Cen",
["cet"] = "Centúúm",
["cfa"] = "Dijim-Bwilim",
["cfd"] = "Cara",
["cfg"] = "Como Karim",
["cfm"] = "Chin Falam",
["cga"] = "Changriwa",
["cgc"] = "Kagayanen",
["cgg"] = "Rukiga",
["cgk"] = "Chocangaca",
["ch"] = "Chamorro",
["chb"] = "Chibcha",
["chc"] = "Catawba",
["chd"] = "Chontal Oaxaca Pegunungan",
["chf"] = "Chontal Tabasco",
["chg"] = "Chagatai",
["chh"] = "Chinook",
["chi-pro"] = "Proto-Chimakuan",
["chj"] = "Chinantec Ojitlán",
["chk"] = "Chuuk",
["chl"] = "Cahuilla",
["chm-pro"] = "Proto-Mari",
["chn"] = "Chinook Jargon",
["cho"] = "Choctaw",
["chp"] = "Chipewyan",
["chq"] = "Chinantec Quiotepec",
["chr"] = "Cherokee",
["cht"] = "Cholón",
["chw"] = "Chuabo",
["chx"] = "Chantyal",
["chy"] = "Cheyenne",
["chz"] = "Chinantec Ozumacín",
["cia"] = "Cia-Cia",
["cib"] = "Gbe Ci",
["cic"] = "Chickasaw",
["cid"] = "Chimariko",
["cie"] = "Cineni",
["cih"] = "Chinali",
["cik"] = "Kinnauri Chitkuli",
["cim"] = "Cimbrian",
["cin"] = "Cinta Larga",
["cip"] = "Chiapanec",
["cir"] = "Tiri",
["ciy"] = "Chaima",
["cja"] = "Cham Barat",
["cje"] = "Chru",
["cjh"] = "Chehalis Hulu",
["cji"] = "Chamalal",
["cjk"] = "Chokwe",
["cjm"] = "Cham Timur",
["cjn"] = "Chenapian",
["cjo"] = "Ashéninka Pajonal",
["cjp"] = "Cabécar",
["cjs"] = "Shor",
["cjv"] = "Chuave",
["cjy"] = "Jin",
["ckb"] = "Kurdi Tengah",
["ckh"] = "Chak",
["ckl"] = "Cibak",
["ckn"] = "Chin Kaang",
["cko"] = "Anufo",
["ckq"] = "Kajakse",
["ckr"] = "Kairak",
["cks"] = "Tayo",
["ckt"] = "Chukchi",
["cku"] = "Koasati",
["ckv"] = "Kavalan",
["ckx"] = "Caka",
["cky"] = "Cakfem-Mushere",
["ckz"] = "campuran Cakchiquel-Quiché",
["cla"] = "Ron",
["clc"] = "Chilcotin",
["cld"] = "Neo-Aramaik Khaldea",
["cle"] = "Chinantec Lealao",
["clh"] = "Chilisso",
["cli"] = "Chakali",
["clj"] = "Chin Laitu",
["clk"] = "Idu",
["cll"] = "Chala",
["clm"] = "Klallam",
["clo"] = "Chontal Oaxaca Dataran",
["clt"] = "Chin Lautu",
["clu"] = "Caluyanun",
["clw"] = "Chulym",
["cly"] = "Chatino Pegunungan Timur",
["cma"] = "Maa",
["cmc-pro"] = "Proto-Chamic",
["cme"] = "Cerma",
["cmg"] = "Mongolia Klasik",
["cmi"] = "Emberá-Chamí",
["cml"] = "Campalagian",
["cmm"] = "Michigamea",
["cmn"] = "Tionghoa Mandarin",
["cmo"] = "Mnong Tengah",
["cmr"] = "Chin Mro",
["cms"] = "Messapic",
["cmt"] = "Camtho",
["cna"] = "Changthang",
["cnb"] = "Chin Chinbon",
["cnc"] = "Côông",
["cng"] = "Qiang Utara",
["cnh"] = "Lai",
["cni"] = "Asháninka",
["cnk"] = "Chin Khumi",
["cnl"] = "Chinantec Lalana",
["cno"] = "Con",
["cns"] = "Asmat Tengah",
["cnt"] = "Chinantec Tepetotutla",
["cnu"] = "Chenoua",
["cnw"] = "Chin Ngawn",
["cnx"] = "Cornish Tengahan",
["co"] = "Korsika",
["coa"] = "Malayu Kapulauan Kokos",
["cob"] = "Chicomuceltec",
["coc"] = "Cocopa",
["cod"] = "Cocama",
["coe"] = "Koreguaje",
["cof"] = "Tsafiki",
["cog"] = "Chong",
["coh"] = "Chichonyi-Chidzihana-Chikauma",
["coj"] = "Cochimi",
["cok"] = "Santa Teresa Cora",
["col"] = "Columbia-Wenatchi",
["com"] = "Comanche",
["con"] = "Cofán",
["coo"] = "Comox",
["cop"] = "Coptic",
["coq"] = "Coquille",
["cot"] = "Caquinte",
["cou"] = "Wamey",
["cov"] = "Miao Cao",
["cow"] = "Cowlitz",
["cox"] = "Nanti",
["coy"] = "Coyaima",
["coz"] = "Chochotec",
["cpa"] = "Chinantec Palantla",
["cpb"] = "Ucayali-Yurúa Ashéninka",
["cpc"] = "Ajyíninka Apurucayali",
["cpe-mar"] = "Spirit Maroon",
["cpe-spp"] = "Pijin Perkebunan Samoa",
["cpg"] = "Yunani Kapadokia",
["cpi"] = "Pijin Inggris Tiongkok",
["cpn"] = "Cherepon",
["cpo"] = "Kpee",
["cps"] = "Capiznon",
["cpu"] = "Pichis Ashéninka",
["cpx"] = "Puxian",
["cpy"] = "Ucayali Ashéninka Selatan",
["cqd"] = "Miao Kluster Chuanqiandian",
["cr"] = "Cree",
["cra"] = "Chara",
["crb"] = "Carib Island",
["crc"] = "Lonwolwol",
["crd"] = "Coeur d'Alene",
["crf"] = "Caramanta",
["crg"] = "Michif",
["crh"] = "Tatar Krimea",
["cri"] = "Sãotomense",
["crj"] = "Cree Tenggara",
["crk"] = "Cree Plains",
["crl"] = "Cree Timur Laut",
["crm"] = "Cree Moose",
["crn"] = "Cora",
["cro"] = "Crow",
["crp-gep"] = "Pijin Grinlandia Barat",
["crp-mpp"] = "Pijin Purtugis Makau",
["crp-rsn"] = "Russenorsk",
["crp-tnw"] = "Tangwang",
["crp-tpr"] = "Pijin Rusia Taimyr",
["crq"] = "Chorote Iyo'wujwa",
["crr"] = "Algonquian Carolina",
["crs"] = "Kreol Seychelle",
["crt"] = "Chorote Iyojwa'ja",
["crv"] = "Chaura",
["crw"] = "Chrau",
["crx"] = "Carrier",
["cry"] = "Cori",
["crz"] = "Cruzeño",
["cs"] = "Ceko",
["csa"] = "Chinantec Chiltepec",
["csb"] = "Kashubian",
["csc"] = "Isyarat Katala",
["csd"] = "Isyarat Chiangmai",
["cse"] = "Isyarat Ceko",
["csf"] = "Isyarat Kuba",
["csg"] = "Isyarat Cile",
["csh"] = "Chin Asho",
["csi"] = "Miwok Coast",
["csj"] = "Chin Songlai",
["csk"] = "Jola-Kasa",
["csl"] = "Isyarat Tionghoa",
["csm"] = "Miwok Sierra Tengah",
["csn"] = "Isyarat Kolombia",
["cso"] = "Chinantec Sochiapam",
["csq"] = "Isyarat Kroasia",
["csr"] = "Isyarat Kosta Rika",
["css"] = "Ohlone Selatan",
["cst"] = "Ohlone Utara",
["csu-bba-pro"] = "Proto-Bongo-Bagirmi",
["csu-maa-pro"] = "Proto-Mangbetu",
["csu-pro"] = "Proto-Sudan Tengah",
["csu-sar-pro"] = "Proto-Sara",
["csv"] = "Chin Sumtu",
["csw"] = "Cree Swampy",
["csy"] = "Chin Siyin",
["csz"] = "Coos",
["cta"] = "Chatino Tataltepec",
["ctc"] = "Chetco-Tolowa",
["ctd"] = "Chin Tedim",
["cte"] = "Chinantec Tepinapa",
["ctg"] = "Chittagonian",
["cth"] = "Chin Thaiphum",
["ctl"] = "Chinantec Tlacoatzintepec",
["ctm"] = "Chitimacha",
["ctn"] = "Chhintange",
["cto"] = "Emberá-Catío",
["ctp"] = "Chatino Pegunungan Barat",
["ctp-san"] = "Chatino San Juan Quiahije",
["cts"] = "Bicolano Catanduanes Utara",
["ctt"] = "Wayanad Chetti",
["ctu"] = "Chol",
["ctz"] = "Chatino Zacatepec",
["cu"] = "Slavonia Gerejawi Kuna",
["cua"] = "Cua",
["cub"] = "Cubeo",
["cuc"] = "Chinantec Usila",
["cug"] = "Cung",
["cuh"] = "Chuka",
["cui"] = "Cuiba",
["cuj"] = "Piro Mashco",
["cuk"] = "Kuna",
["cul"] = "Culina",
["cuo"] = "Cumanagoto",
["cup"] = "Cupeño",
["cuq"] = "Cun",
["cur"] = "Chhulung",
["cus-ash"] = "Ashraaf",
["cus-hec-pro"] = "Proto-Cushitic Pegunungan Timur",
["cus-pro"] = "Proto-Cushitic",
["cus-som-pro"] = "Proto-Somaloid",
["cus-sou-pro"] = "Proto-Cushitic Selatan",
["cut"] = "Cuicatec Teutila",
["cuu"] = "Tai Ya",
["cuv"] = "Cuvok",
["cuw"] = "Chukwa",
["cux"] = "Cuicatec Tepeuxila",
["cuy"] = "Cuitlatec",
["cv"] = "Chuvash",
["cvg"] = "Chug",
["cvn"] = "Chinantec Valle Nacional",
["cwa"] = "Kabwa",
["cwb"] = "Maindo",
["cwd"] = "Cree Woods",
["cwe"] = "Kwere",
["cwg"] = "Chewong",
["cwt"] = "Kuwaataay",
["cy"] = "Welsh",
["cya"] = "Chatino Nopala",
["cyb"] = "Cayubaba",
["cyo"] = "Cuyunon",
["czh"] = "Huizhou",
["czk"] = "Knaanic",
["czn"] = "Chatino Zenzontepec",
["czo"] = "Min Zhong",
["czt"] = "Chin Zotung",
["da"] = "Denmark",
["daa"] = "Dangaléat",
["dac"] = "Dambi",
["dad"] = "Marik",
["dae"] = "Duupa",
["dag"] = "Dagbani",
["dah"] = "Gwahatike",
["dai"] = "Day",
["daj"] = "Daju Dar Fur",
["dak"] = "Dakota",
["dal"] = "Dahalo",
["dam"] = "Damakawa",
["dao"] = "Chin Daai",
["daq"] = "Maria Dandami",
["dar"] = "Dargwa",
["das"] = "Daho-Doo",
["dau"] = "Daju Dar Sila",
["dav"] = "Taita",
["daw"] = "Davawenyo",
["dax"] = "Dayi",
["daz"] = "Dao",
["dba"] = "Bangime",
["dbb"] = "Deno",
["dbd"] = "Dadiya",
["dbe"] = "Dabe",
["dbf"] = "Edopi",
["dbg"] = "Dom Dogul",
["dbi"] = "Doka",
["dbj"] = "Ida'an",
["dbl"] = "Dyirbal",
["dbm"] = "Duguri",
["dbn"] = "Duriankere",
["dbo"] = "Dulbu",
["dbp"] = "Duwai",
["dbq"] = "Daba",
["dbr"] = "Dabarre",
["dbt"] = "Ben Tey",
["dbu"] = "Dogon Bondum Dom",
["dbv"] = "Dungu",
["dbw"] = "Dogon Bankan Tey",
["dby"] = "Dibiyaso",
["dcc"] = "Deccani",
["dcr"] = "Negerhollands",
["dda"] = "Dadi Dadi",
["ddd"] = "Dongotono",
["dde"] = "Doondo",
["ddg"] = "Fataluku",
["ddi"] = "Diodio",
["ddj"] = "Jaru",
["ddn"] = "Dendi",
["ddo"] = "Tsez",
["ddr"] = "Dhudhuroa",
["dds"] = "Dogon Donno So",
["ddw"] = "Dawera-Daweloor",
["de"] = "Jirman",
["dec"] = "Dagik",
["ded"] = "Dedua",
["dee"] = "Dewoin",
["def"] = "Dezfuli",
["deg"] = "Degema",
["deh"] = "Dehwari",
["dei"] = "Demisa",
["dek"] = "Dek",
["dem"] = "Dem",
["den"] = "Slavey",
["dep"] = "Pijin Delaware",
["der"] = "Deori",
["des"] = "Desano",
["dev"] = "Domung",
["dez"] = "Dengese",
["dga"] = "Dagaare Selatan",
["dgb"] = "Bunoge",
["dgc"] = "Agta Casiguran Dumagat",
["dgd"] = "Dagaari Dioula",
["dge"] = "Degenan",
["dgg"] = "Doga",
["dgh"] = "Dghwede",
["dgi"] = "Dagara Utara",
["dgk"] = "Dagba",
["dgn"] = "Dagoman",
["dgo"] = "Dogri Hindi",
["dgr"] = "Dogrib",
["dgs"] = "Dogoso",
["dgt"] = "Ntra'ngith",
["dgw"] = "Daungwurrung",
["dgx"] = "Doghoro",
["dgz"] = "Daga",
["dhg"] = "Dhangu",
["dhi"] = "Dhimal",
["dhl"] = "Dhalandji",
["dhm"] = "Zemba",
["dhn"] = "Dhanki",
["dho"] = "Dhodia",
["dhr"] = "Tharrgari",
["dhs"] = "Dhaiso",
["dhu"] = "Dhurga",
["dhv"] = "Drehu",
["dhw"] = "Danuwar",
["dhx"] = "Dhungaloo",
["dia"] = "Dia",
["dib"] = "Dinka Tengah Selatan",
["dic"] = "Lakota Dida",
["did"] = "Didinga",
["dif"] = "Dieri",
["dig"] = "Digo",
["dii"] = "Dimbong",
["dij"] = "Dai",
["dik"] = "Dinka Barat Daya",
["dil"] = "Dilling",
["dim"] = "Dime",
["din"] = "Dinka",
["dio"] = "Dibo",
["dip"] = "Dinka Timur Laut",
["dir"] = "Dirim",
["dis"] = "Dimasa",
["diu"] = "Gciriku",
["diw"] = "Dinka Barat Laut",
["dix"] = "Dixon Reef",
["diy"] = "Diuwe",
["diz"] = "Ding",
["dja"] = "Djadjawurrung",
["djb"] = "Djinba",
["djc"] = "Daju Dar Daju",
["djd"] = "Jaminjung",
["dje"] = "Zarma",
["djf"] = "Djangun",
["dji"] = "Djinang",
["djj"] = "Ndjébbana",
["djk"] = "Aukan",
["djl"] = "Djiwarli",
["djm"] = "Jamsay",
["djn"] = "Djauan",
["djo"] = "Jangkang",
["djr"] = "Djambarrpuyngu",
["dju"] = "Kapriman",
["djw"] = "Djawi",
["dka"] = "Dakpa",
["dkk"] = "Dakka",
["dkr"] = "Kuijau",
["dks"] = "Dinka Tenggara",
["dkx"] = "Mazagway",
["dlg"] = "Dolgan",
["dlk"] = "Dahalik",
["dlm"] = "Dalmatian",
["dln"] = "Darlong",
["dma"] = "Duma",
["dmb"] = "Dogon Mombo",
["dmc"] = "Gavak",
["dmd"] = "Madhi Madhi",
["dme"] = "Dugwor",
["dmf"] = "Medefaidrin",
["dmg"] = "Kinabatangan Hulu",
["dmk"] = "Domaaki",
["dml"] = "Dameli",
["dmm"] = "Dama (Nigeria)",
["dmn-dam"] = "Dama (Sierra Leone)",
["dmn-mdw-pro"] = "Proto-Mande Barat",
["dmn-pro"] = "Proto-Mande",
["dmo"] = "Kemezung",
["dmr"] = "Damar Timur",
["dms"] = "Dampelas",
["dmu"] = "Dubu",
["dmv"] = "Dumpas",
["dmw"] = "Mudburra",
["dmx"] = "Dema",
["dmy"] = "Demta",
["dna"] = "Dani Upper Grand Valley",
["dnd"] = "Daonda",
["dne"] = "Ndendeule",
["dng"] = "Dungan",
["dni"] = "Dani Lower Grand Valley",
["dnj"] = "Dan",
["dnk"] = "Dengka",
["dnn"] = "Dzuun",
["dno"] = "Ndrulo",
["dnr"] = "Danaru",
["dnt"] = "Dani Mid Grand Valley",
["dnu"] = "Danau",
["dnv"] = "Danu",
["dnw"] = "Dani Barat",
["dny"] = "Dení",
["doa"] = "Dom",
["dob"] = "Dobu",
["doc"] = "Kam Utara",
["doe"] = "Doe",
["dof"] = "Domu",
["doh"] = "Dong",
["doi"] = "Dogri",
["dok"] = "Dondo",
["dol"] = "Doso",
["don"] = "Doura",
["doo"] = "Dongo",
["dop"] = "Lukpa",
["doq"] = "Isyarat Dominika",
["dor"] = "Dori'o",
["dos"] = "Dogosé",
["dot"] = "Dass",
["dov"] = "Toka-Leya",
["dow"] = "Doyayo",
["dox"] = "Bussa",
["doy"] = "Dompo",
["doz"] = "Dorze",
["dpp"] = "Papar",
["dra-mkn"] = "Kannada Tengahan",
["dra-okn"] = "Kannada Kuna",
["dra-ote"] = "Telugu Kuna",
["dra-pro"] = "Proto-Dravidia",
["drb"] = "Dair",
["drc"] = "Minderico",
["drd"] = "Darmiya",
["drg"] = "Rungus",
["dri"] = "Lela",
["drl"] = "Baagandji",
["drn"] = "Damar Barat",
["dro"] = "Melanau Daro-Matu",
["drq"] = "Dura",
["drs"] = "Gedeo",
["dru"] = "Rukai",
["dru-pro"] = "Proto-Rukai",
["dry"] = "Darai",
["dsb"] = "Sorbian Hilir",
["dse"] = "Isyarat Walanda",
["dsh"] = "Daasanach",
["dsi"] = "Disa",
["dsl"] = "Isyarat Denmark",
["dsn"] = "Dusner",
["dso"] = "Desiya",
["dsq"] = "Tadaksahak",
["dta"] = "Daur",
["dtb"] = "Kadazan Labuk-Kinabatangan",
["dtd"] = "Ditidaht",
["dth"] = "Adithinngithigh",
["dti"] = "Dogon Ana Tinga",
["dtk"] = "Dogon Tene Kan",
["dtm"] = "Dogon Tomo Kan",
["dto"] = "Tommo So",
["dtp"] = "Dusun Tengah",
["dtr"] = "Lotud",
["dts"] = "Dogon Toro So",
["dtt"] = "Dogon Toro Tegu",
["dtu"] = "Dogon Tebul Ure",
["dty"] = "Doteli",
["dua"] = "Duala",
["dub"] = "Dubli",
["duc"] = "Duna",
["due"] = "Agta Umiray Dumaget",
["duf"] = "Dumbea",
["dug"] = "Chiduruma",
["duh"] = "Dungra Bhil",
["dui"] = "Dumun",
["duk"] = "Uyajitaya",
["dul"] = "Agta Alabat Island",
["dum"] = "Walanda Tengahan",
["dun"] = "Dayak Deah",
["duo"] = "Agta Dupaningan",
["dup"] = "Duano",
["duq"] = "Dusun Malang",
["dur"] = "Dii",
["dus"] = "Dumi",
["duu"] = "Drung",
["duv"] = "Duvle",
["duw"] = "Dusun Witu",
["dux"] = "Duun",
["duy"] = "Agta Dicamay",
["duz"] = "Duli",
["dv"] = "Dhivehi",
["dva"] = "Duau",
["dwa"] = "Diri",
["dwr"] = "Dawro",
["dwu"] = "Dhuwal",
["dww"] = "Dawawa",
["dwy"] = "Dhuwaya",
["dwz"] = "Dewas Rai",
["dya"] = "Dyan",
["dyb"] = "Dyaberdyaber",
["dyd"] = "Dyugun",
["dyg"] = "Agta Villa Viciosa",
["dyi"] = "Djimini",
["dym"] = "Dogon Yanda",
["dyn"] = "Dyangadi",
["dyo"] = "Jola-Fonyi",
["dyu"] = "Dyula",
["dyy"] = "Dyaabugay",
["dz"] = "Dzongkha",
["dza"] = "Tunzu",
["dzg"] = "Dazaga",
["dzl"] = "Dzala",
["dzn"] = "Dzando",
["ebg"] = "Ebughu",
["ebk"] = "Bontoc Timur",
["ebr"] = "Ebrié",
["ebu"] = "Embu",
["ecr"] = "Eteocretan",
["ecs"] = "Isyarat Ekuador",
["ecy"] = "Eteocypriot",
["ee"] = "Ewe",
["eee"] = "E",
["efa"] = "Efai",
["efe"] = "Efe",
["efi"] = "Efik",
["ega"] = "Ega",
["egl"] = "Emilian",
["ego"] = "Eggon",
["egx-dem"] = "Demotic",
["egy"] = "Mesir",
["ehu"] = "Ehueun",
["eip"] = "Eipomek",
["eit"] = "Eitiep",
["eiv"] = "Askopan",
["eja"] = "Ejamat",
["eka"] = "Ekajuk",
["eke"] = "Ekit",
["ekg"] = "Ekari",
["eki"] = "Eki",
["ekl"] = "Kolhe",
["ekm"] = "Elip",
["eko"] = "Koti",
["ekp"] = "Ekpeye",
["ekr"] = "Yace",
["eky"] = "Kayah Timur",
["el"] = "Yunani",
["ele"] = "Elepi",
["elh"] = "El Hugeirat",
["eli"] = "Nding",
["elk"] = "Elkei",
["elm"] = "Eleme",
["elo"] = "El Molo",
["elu"] = "Elu",
["elu-prk"] = "Helu",
["elx"] = "Elamite",
["ema"] = "Emai",
["emb"] = "Embaloh",
["eme"] = "Emerillon",
["emg"] = "Meohang Timur",
["emi"] = "Mussau-Emira",
["emk"] = "Maninkakan Timur",
["emm"] = "Mamulique",
["emn"] = "Eman",
["emp"] = "Emberá Utara",
["ems"] = "Alutiiq",
["emu"] = "Muria Timur",
["emw"] = "Emplawas",
["emx"] = "Erromintxela",
["emy"] = "Maya Epigrafik",
["en"] = "Inggris",
["ena"] = "Apali",
["enb"] = "Markweeta",
["enc"] = "En",
["end"] = "Ende",
["enf"] = "Enets Hutan",
["enh"] = "Enets Tundra",
["enl"] = "Enlhet",
["enm"] = "Inggris Tengahan",
["enn"] = "Engenni",
["eno"] = "Enggano",
["enq"] = "Enga",
["enr"] = "Emem",
["enu"] = "Enu",
["env"] = "Enwan",
["enw"] = "Enwang",
["enx"] = "Enxet",
["eo"] = "Esperanto",
["eot"] = "Eotile",
["epi"] = "Epie",
["era"] = "Eravallan",
["erg"] = "Sie",
["erh"] = "Eruwa",
["eri"] = "Ogea",
["erk"] = "Efate Selatan",
["ero"] = "Horpa",
["err"] = "Erre",
["ers"] = "Ersu",
["ert"] = "Eritai",
["erw"] = "Erokwanas",
["es"] = "Sapanyul",
["ese"] = "Ese Ejja",
["esh"] = "Eshtehardi",
["esi"] = "Inupiaq Alaska Utara",
["esk"] = "Inupiaq Alaska Barat Laut",
["esl"] = "Isyarat Mesir",
["esm"] = "Esuma",
["esn"] = "Isyarat El Salvador",
["eso"] = "Isyarat Estonia",
["esq"] = "Esselen",
["ess"] = "Siberia Yupik Tengah",
["esu"] = "Yup'ik",
["esx-esk-pro"] = "Proto-Eskimo",
["esx-ink"] = "Inuktun",
["esx-inq"] = "Inuinnaqtun",
["esx-inu-pro"] = "Proto-Inuit",
["esx-pro"] = "Proto-Eskimo-Aleut",
["esx-tut"] = "Tunumiisut",
["esy"] = "Eskayan",
["et"] = "Estonia",
["etb"] = "Etebi",
["etc"] = "Etchemin",
["eth"] = "Isyarat Etiopia",
["etn"] = "Eton (Vanuatu)",
["eto"] = "Eton (Kamerun)",
["etr"] = "Edolo",
["ets"] = "Yekhee",
["ett"] = "Etruscan",
["etu"] = "Ejagham",
["etx"] = "Eten",
["etz"] = "Semimi",
["eu"] = "Basque",
["euq-pro"] = "Proto-Basque",
["eve"] = "Even",
["evh"] = "Uvbie",
["evn"] = "Evenki",
["ewo"] = "Ewondo",
["ext"] = "Extremadura",
["eya"] = "Eyak",
["eyo"] = "Keiyo",
["eza"] = "Ezaa",
["eze"] = "Uzekwe",
["fa"] = "Persia",
["faa"] = "Fasu",
["fab"] = "Annobonese",
["fad"] = "Wagi",
["faf"] = "Fagani",
["fag"] = "Finongan",
["fah"] = "Fali Baissa",
["fai"] = "Faiwol",
["faj"] = "Faita",
["fak"] = "Fang (Beboid)",
["fal"] = "Fali Selatan",
["fam"] = "Fam",
["fan"] = "Fang (Bantu)",
["fap"] = "Palor",
["far"] = "Fataleka",
["fau"] = "Fayu",
["fax"] = "Fala",
["fay"] = "Fars Barat Daya",
["faz"] = "Fars Barat Laut",
["fbl"] = "Bikol Albay Barat",
["fcs"] = "Isyarat Quebec",
["fer"] = "Feroge",
["ff"] = "Fula",
["ffi"] = "Foia Foia",
["fgr"] = "Fongoro",
["fi"] = "Finlandia",
["fia"] = "Nobiin",
["fie"] = "Fyer",
["fip"] = "Fipa",
["fir"] = "Firan",
["fit"] = "Meänkieli",
["fiw"] = "Fiwaga",
["fj"] = "Fiji",
["fkk"] = "Kirya-Konzel",
["fkv"] = "Kven",
["fla"] = "Salish Montana",
["flh"] = "Foau",
["fli"] = "Fali",
["fll"] = "Fali Utara",
["fln"] = "Flinders Island",
["flr"] = "Fuliiru",
["fly"] = "Tsotsitaal",
["fmp"] = "Fe'fe'",
["fmu"] = "Muria Barat Jauh",
["fng"] = "Fanagalo",
["fni"] = "Fania",
["fo"] = "Faroe",
["fod"] = "Foodo",
["foi"] = "Foi",
["fom"] = "Foma",
["fon"] = "Fon",
["for"] = "Fore",
["fos"] = "Siraya",
["fpe"] = "Pichinglis",
["fqs"] = "Fas",
["fr"] = "Parancis",
["frd"] = "Fordata",
["frm"] = "Parancis Tengahan",
["fro"] = "Parancis Kuna",
["frp"] = "Franco-Provençal",
["frq"] = "Forak",
["frr"] = "Frisia Utara",
["frt"] = "Fortsenal",
["fse"] = "Isyarat Finlandia",
["fsl"] = "Isyarat Parancis",
["fss"] = "Isyarat Finlandia-Swedia",
["fud"] = "Futuna Timur",
["fuj"] = "Ko",
["fum"] = "Fum",
["fun"] = "Fulniô",
["fur"] = "Friulian",
["fut"] = "Futuna-Aniwa",
["fuu"] = "Furu",
["fuy"] = "Fuyug",
["fvr"] = "Fur",
["fwa"] = "Fwâi",
["fwe"] = "Fwe",
["fy"] = "Frisia Barat",
["ga"] = "Irlandia",
["gaa"] = "Ga",
["gab"] = "Gabri",
["gac"] = "campuran Great Andaman",
["gad"] = "Gaddang",
["gae"] = "Warekena",
["gaf"] = "Gende",
["gag"] = "Gagauz",
["gah"] = "Alekano",
["gai"] = "Borei",
["gaj"] = "Gadsup",
["gak"] = "Gamkonora",
["gal"] = "Galoli",
["gam"] = "Kandawo",
["gan"] = "Gan",
["gao"] = "Gants",
["gap"] = "Gal",
["gaq"] = "Gata'",
["gar"] = "Galeya",
["gas"] = "Adiwasi Garasia",
["gat"] = "Kenati",
["gau"] = "Kondekor",
["gaw"] = "Nobonob",
["gay"] = "Gayo",
["gba"] = "Gbaya",
["gbb"] = "Kaytetye",
["gbd"] = "Karadjeri",
["gbe"] = "Niksek",
["gbf"] = "Gaikundi",
["gbg"] = "Gbanziri",
["gbh"] = "Gbe Defi",
["gbi"] = "Galela",
["gbj"] = "Bodo Gadaba",
["gbk"] = "Gaddi",
["gbl"] = "Gamit",
["gbm"] = "Garhwali",
["gbn"] = "Mo'da",
["gbo"] = "Grebo Utara",
["gbp"] = "Gbaya-Bossangoa",
["gbq"] = "Gbaya-Bozoum",
["gbr"] = "Gbagyi",
["gbs"] = "Gbe Gbesi",
["gbu"] = "Gagadu",
["gbv"] = "Gbanu",
["gbw"] = "Gabi",
["gbx"] = "Gbe Xwla Timur",
["gby"] = "Gbari",
["gcc"] = "Mali",
["gcd"] = "Ganggalida",
["gce"] = "Galice",
["gcf"] = "Kreol Antilla",
["gcl"] = "Kreol Inggris Grenada",
["gcn"] = "Gaina",
["gcr"] = "Kreol Guiana",
["gct"] = "Jirman Colonia Tovar",
["gd"] = "Gaelik Skotlandia",
["gdb"] = "Ollari",
["gdc"] = "Gugu Badhun",
["gdd"] = "Gedaged",
["gde"] = "Gude",
["gdf"] = "Guduf-Gava",
["gdg"] = "Ga'dang",
["gdh"] = "Gadjerawang",
["gdi"] = "Gundi",
["gdj"] = "Kurtjar",
["gdk"] = "Gadang",
["gdl"] = "Dirasha",
["gdm"] = "Laal",
["gdn"] = "Umanakaina",
["gdo"] = "Godoberi",
["gdq"] = "Mehri",
["gdr"] = "Wipi",
["gds"] = "Isyarat Ghandruk",
["gdt"] = "Kungardutyi",
["gdu"] = "Gudu",
["gdx"] = "Godwari",
["gea"] = "Geruma",
["geb"] = "Kire",
["gec"] = "Grebo Gboloo",
["ged"] = "Gade",
["geg"] = "Gengle",
["geh"] = "Hutterisch",
["gei"] = "Gebe",
["gej"] = "Gen",
["gek"] = "Gerka",
["gel"] = "Fakkanci",
["gem-bur"] = "Burgundi",
["gem-pro"] = "Proto-Jirmanik",
["geq"] = "Geme",
["ges"] = "Geser-Gorom",
["gev"] = "Viya",
["gew"] = "Gera",
["gex"] = "Garre",
["gey"] = "Enya",
["gez"] = "Ge'ez",
["gfk"] = "Patpatar",
["gft"] = "Gafat",
["gga"] = "Gao",
["ggb"] = "Gbii",
["ggd"] = "Gugadj",
["gge"] = "Guragone",
["ggg"] = "Gurgula",
["ggk"] = "Kungarakany",
["ggl"] = "Ganglau",
["ggn"] = "Gurung Timur",
["ggt"] = "Gitua",
["ggu"] = "Gban",
["ggw"] = "Gogodala",
["gha"] = "Ghadames",
["ghe"] = "Ghale Selatan",
["ghh"] = "Ghale Utara",
["ghk"] = "Karen Geko",
["ghl"] = "Ghulfan",
["ghn"] = "Ghanongga",
["gho"] = "Ghomara",
["ghr"] = "Ghera",
["ghs"] = "Guhu-Samane",
["ght"] = "Ghale Kutang",
["gia"] = "Kitja",
["gib"] = "Gibanawa",
["gid"] = "Gidar",
["gie"] = "Guébie",
["gig"] = "Goaria",
["gih"] = "Githabul",
["gii"] = "Girirra",
["gil"] = "Gilbert",
["gim"] = "Gimi (Goroka)",
["gin"] = "Hinukh",
["gio"] = "Gelao",
["gip"] = "Gimi (Austronesia)",
["giq"] = "Gelao Hijau",
["gir"] = "Gelao Merah",
["gis"] = "Giziga Utara",
["git"] = "Gitxsan",
["giu"] = "Mulao",
["giw"] = "Gelao Putih",
["gix"] = "Gilima",
["giy"] = "Giyug",
["giz"] = "Giziga Selatan",
["gji"] = "Geji",
["gjk"] = "Koli Kachi",
["gjm"] = "Gunditjmara",
["gjn"] = "Gonja",
["gju"] = "Gojri",
["gka"] = "Guya",
["gkd"] = "Magɨ",
["gke"] = "Ndai",
["gkn"] = "Gokana",
["gko"] = "Kok-Nar",
["gkp"] = "Kpelle Guinea",
["gl"] = "Galisia",
["glc"] = "Gula Bon",
["gld"] = "Nanai",
["glh"] = "Pashayi Barat Laut",
["glj"] = "Kulaal",
["glk"] = "Gilaki",
["glo"] = "Galambu",
["glr"] = "Glaro-Twabo",
["glu"] = "Gula",
["glw"] = "Glavda",
["gly"] = "Gule",
["gma"] = "Gambera",
["gmb"] = "Gula'alaa",
["gmd"] = "Mághdì",
["gme-cgo"] = "Gothik Krimea",
["gmg"] = "Magiyi",
["gmh"] = "Jirman Tinggi Tengahan",
["gml"] = "Jirman Rendah Tengahan",
["gmm"] = "Gbaya-Mbodomo",
["gmn"] = "Gimnime",
["gmq-gut"] = "Gutnish",
["gmq-jmk"] = "Jamtish",
["gmq-mno"] = "Norwegia Tengahan",
["gmq-oda"] = "Denmark Kuna",
["gmq-osw"] = "Swedia Kuna",
["gmq-pro"] = "Proto-Norse",
["gmq-scy"] = "Scanian",
["gmu"] = "Gumalu",
["gmv"] = "Gamo",
["gmw-bgh"] = "Bergish",
["gmw-cfr"] = "Franconia Tengah",
["gmw-ecg"] = "Jirman Tengah Timur",
["gmw-gts"] = "Gottscheerish",
["gmw-jdt"] = "Walanda Jersey",
["gmw-pro"] = "Proto-Jirman Barat",
["gmw-rfr"] = "Franconia Rhine",
["gmw-stm"] = "Swabia Sathmar",
["gmw-tsx"] = "Saxon Transylvania",
["gmw-vog"] = "Jirman Volga",
["gmw-zps"] = "Jirman Zipser",
["gmx"] = "Magoma",
["gmy"] = "Yunani Mycenaean",
["gmz"] = "Mgbo",
["gn"] = "Guaraní",
["gn-cls"] = "Guaraní Klasik",
["gna"] = "Kaansa",
["gnb"] = "Gangte",
["gnc"] = "Guanche",
["gnd"] = "Zulgo-Gemzek",
["gne"] = "Ganang",
["gng"] = "Ngangam",
["gnh"] = "Lere",
["gni"] = "Gooniyandi",
["gnj"] = "Ngen",
["gnk"] = "ǁGana",
["gnl"] = "Gangulu",
["gnm"] = "Ginuman",
["gnn"] = "Gumatj",
["gnq"] = "Gana",
["gnr"] = "Gureng Gureng",
["gnt"] = "Guntai",
["gnu"] = "Gnau",
["gnw"] = "Guaraní Bolivia Barat",
["gnz"] = "Ganzi",
["goa"] = "Guro",
["gob"] = "Playero",
["goc"] = "Gorakor",
["god"] = "Godié",
["goe"] = "Gongduk",
["gof"] = "Gofa",
["gog"] = "Gogo",
["goh"] = "Jirman Tinggi Kuna",
["goi"] = "Gobasi",
["goj"] = "Gowlan",
["gol"] = "Gola",
["gon"] = "Gondi",
["goo"] = "Gone Dau",
["gop"] = "Yeretuar",
["goq"] = "Gorap",
["gor"] = "Gorontalo",
["got"] = "Gothik",
["gou"] = "Gavar",
["gov"] = "Goo",
["gow"] = "Gorowa",
["gox"] = "Gobu",
["goy"] = "Goundo",
["goz"] = "Gozarkhani",
["gpa"] = "Gupa-Abawa",
["gpn"] = "Taiap",
["gqa"] = "Ga'anda",
["gqi"] = "Guiqiong",
["gqn"] = "Kinikinao",
["gqr"] = "Gor",
["gqu"] = "Qau",
["gra"] = "Rajput Garasia",
["grb"] = "Grebo",
["grc"] = "Yunani Kuna",
["grd"] = "Guruntum",
["grg"] = "Madi",
["grh"] = "Gbiri-Niragu",
["gri"] = "Ghari",
["grj"] = "Grebo Selatan",
["grk-cal"] = "Yunani Calabrian",
["grk-ita"] = "Yunani Italiot",
["grk-mar"] = "Yunani Mariupol",
["grk-pro"] = "Proto-Hellenik",
["grm"] = "Kota Marudu Talantang",
["gro"] = "Groma",
["grq"] = "Gorovu",
["grs"] = "Gresi",
["grt"] = "Garo",
["gru"] = "Kistane",
["grv"] = "Grebo Tengah",
["grw"] = "Gweda",
["grx"] = "Guriaso",
["gry"] = "Grebo Barclayville",
["grz"] = "Guramalum",
["gse"] = "Isyarat Ghana",
["gsg"] = "Isyarat Jirman",
["gsl"] = "Gusilay",
["gsm"] = "Isyarat Guatemala",
["gsn"] = "Gusan",
["gso"] = "Gbaya Barat Daya",
["gsp"] = "Wasembo",
["gss"] = "Isyarat Yunani",
["gsw"] = "Jirman Alemannik",
["gta"] = "Guató",
["gtu"] = "Aghu Tharrnggala",
["gu"] = "Gujarat",
["gua"] = "Shiki",
["gub"] = "Guajajára",
["guc"] = "Wayuu",
["gud"] = "Yocoboué Dida",
["gue"] = "Gurindji",
["guf"] = "Gupapuyngu",
["gug"] = "Guaraní Paraguay",
["guh"] = "Guahibo",
["gui"] = "Guaraní Bolivia Timur",
["guk"] = "Gumuz",
["gul"] = "Gullah",
["gum"] = "Guambiano",
["gun"] = "Guaraní Mbyá",
["guo"] = "Guayabero",
["gup"] = "Gunwinggu",
["guq"] = "Aché",
["gur"] = "Farefare",
["gus"] = "Isyarat Guinea",
["gut"] = "Maléku Jaíka",
["guu"] = "Yanomamö",
["guv"] = "Gey",
["guw"] = "Gun",
["gux"] = "Gourmanchéma",
["guz"] = "Gusii",
["gv"] = "Manx",
["gva"] = "Kaskihá",
["gvc"] = "Guanano",
["gve"] = "Duwet",
["gvf"] = "Golin",
["gvj"] = "Guajá",
["gvl"] = "Gulay",
["gvm"] = "Gurmana",
["gvn"] = "Kuku-Yalanji",
["gvo"] = "Gavião do Jiparaná",
["gvp"] = "Gavião Pará",
["gvr"] = "Gurung Barat",
["gvs"] = "Gumawana",
["gvy"] = "Guyani",
["gwa"] = "Mbato",
["gwb"] = "Gwa",
["gwc"] = "Kalami",
["gwd"] = "Gawwada",
["gwe"] = "Gweno",
["gwf"] = "Gowro",
["gwg"] = "Moo",
["gwi"] = "Gwich'in",
["gwj"] = "Gcwi",
["gwm"] = "Awngthim",
["gwn"] = "Gwandara",
["gwr"] = "Gwere",
["gwt"] = "Gawar-Bati",
["gwu"] = "Guwamu",
["gww"] = "Kwini",
["gwx"] = "Gua",
["gxx"] = "Wè Selatan",
["gya"] = "Gbaya Barat Laut",
["gyb"] = "Garus",
["gyd"] = "Kayardild",
["gye"] = "Gyem",
["gyf"] = "Gungabula",
["gyg"] = "Gbayi",
["gyi"] = "Gyele",
["gyl"] = "Gayil",
["gym"] = "Ngäbere",
["gyn"] = "Kreol Inggris Guyana",
["gyo"] = "Gyalsumdo",
["gyr"] = "Guarayu",
["gyy"] = "Gunya",
["gza"] = "Ganza",
["gzn"] = "Gane",
["ha"] = "Hausa",
["haa"] = "Hän",
["hab"] = "Isyarat Hanoi",
["hac"] = "Gurani",
["had"] = "Hatam",
["haf"] = "Isyarat Haiphong",
["hag"] = "Hanga",
["hah"] = "Hahon",
["hai"] = "Haida",
["haj"] = "Hajong",
["hak"] = "Hakka",
["hal"] = "Halang",
["ham"] = "Hewa",
["hao"] = "Hakö",
["hap"] = "Hupla",
["har"] = "Harari",
["has"] = "Haisla",
["hav"] = "Havu",
["haw"] = "Hawaii",
["hax"] = "Haida Selatan",
["hay"] = "Haya",
["haz"] = "Hazaragi",
["hba"] = "Hamba",
["hbb"] = "Huba",
["hbn"] = "Heiban",
["hbu"] = "Habu",
["hca"] = "Kreol Hindi Andaman",
["hch"] = "Huichol",
["hdn"] = "Haida Utara",
["hds"] = "Isyarat Honduras",
["hdy"] = "Hadiyya",
["he"] = "Ibrani",
["hea"] = "Miao Qiandong Utara",
["hed"] = "Herdé",
["heg"] = "Helong",
["heh"] = "Hehe",
["hei"] = "Heiltsuk",
["hem"] = "Hemba",
["hgm"] = "Haiǁom",
["hgw"] = "Haigwai",
["hhi"] = "Hoia Hoia",
["hhr"] = "Kerak",
["hhy"] = "Hoyahoya",
["hi"] = "Hindi",
["hia"] = "Lamang",
["hib"] = "Hibito",
["hid"] = "Hidatsa",
["hif"] = "Hindi Fiji",
["hig"] = "Kamwe",
["hih"] = "Pamosu",
["hii"] = "Hinduri",
["hij"] = "Hijuk",
["hik"] = "Seit-Kaitetu",
["hil"] = "Hiligaynon",
["hio"] = "Tshwa",
["hir"] = "Himarimã",
["hit"] = "Hitit",
["hiw"] = "Hiw",
["hix"] = "Hixkaryana",
["hji"] = "Haji",
["hka"] = "Kahe",
["hke"] = "Hunde",
["hkk"] = "Ke Hunjara-Kaina",
["hkn"] = "Mel-Khaonh",
["hks"] = "Isyarat Hong Kong",
["hla"] = "Halia",
["hlb"] = "Halbi",
["hld"] = "Halang Doan",
["hle"] = "Hlersu",
["hlt"] = "Nga La",
["hma"] = "Hmong Mashan Selatan",
["hmb"] = "Senni Humburi",
["hmc"] = "Hmong Huishui Tengah",
["hmd"] = "A-Hmao",
["hme"] = "Hmong Huishui Timur",
["hmf"] = "Hmong Don",
["hmg"] = "Hmong Guiyang Barat Daya",
["hmh"] = "Hmong Huishui Barat Daya",
["hmi"] = "Hmong Huishui Utara",
["hmj"] = "Ge",
["hmk"] = "Maek",
["hml"] = "Hmong Luopohe",
["hmm"] = "Hmong Mashan Tengah",
["hmn-pro"] = "Proto-Hmong",
["hmp"] = "Hmong Mashan Utara",
["hmq"] = "Miao Qiandong Timur",
["hmr"] = "Hmar",
["hms"] = "Miao Qiandong Selatan",
["hmt"] = "Hamtai",
["hmu"] = "Hamap",
["hmv"] = "Hmong Dô",
["hmw"] = "Hmong Mashan Barat",
["hmx-mie-pro"] = "Proto-Mien",
["hmx-pro"] = "Proto-Hmong-Mien",
["hmy"] = "Hmong Guiyang Selatan",
["hmz"] = "Hmong Shua",
["hna"] = "Mina",
["hnd"] = "Hindko Selatan",
["hne"] = "Chhattisgarhi",
["hnh"] = "ǁAni",
["hni"] = "Hani",
["hnj"] = "Hmong Green",
["hnn"] = "Hanunoo",
["hno"] = "Hindko Utara",
["hns"] = "Hindustani Karibia",
["hnu"] = "Hung",
["ho"] = "Motu Hiri",
["hoa"] = "Hoava",
["hob"] = "Mari Austronesia",
["hoc"] = "Ho",
["hod"] = "Holma",
["hoe"] = "Horom",
["hoh"] = "Hobyót",
["hoi"] = "Holikachuk",
["hoj"] = "Hadothi",
["hol"] = "Holu",
["hom"] = "Homa",
["hoo"] = "Holoholo",
["hop"] = "Hopi",
["hor"] = "Horo",
["hos"] = "Isyarat Kota Ho Chi Minh",
["hot"] = "Hote",
["hov"] = "Hovongan",
["how"] = "Honi",
["hoy"] = "Holiya",
["hoz"] = "Hozo",
["hpo"] = "Hpon",
["hps"] = "Isyarat Pijin Hawai'i",
["hra"] = "Hrangkhol",
["hrc"] = "Niwer Mil",
["hre"] = "Hre",
["hrk"] = "Haruku",
["hrm"] = "Miao Horned",
["hro"] = "Haroi",
["hrp"] = "Nhirrpi",
["hrt"] = "Hértevin",
["hru"] = "Hruso",
["hrw"] = "Warwar Feni",
["hrx"] = "Hunsrik",
["hrz"] = "Harzani",
["hsb"] = "Sorbian Hulu",
["hsh"] = "Isyarat Hungaria",
["hsl"] = "Isyarat Hausa",
["hsn"] = "Xiang",
["hss"] = "Harsusi",
["ht"] = "Kreol Haiti",
["hti"] = "Hoti",
["hto"] = "Huitoto Minica",
["hts"] = "Hadza",
["htu"] = "Hitu",
["hu"] = "Hungaria",
["hub"] = "Huambisa",
["huc"] = "ǂHoan",
["hud"] = "Huaulu",
["huf"] = "Humene",
["hug"] = "Huachipaeri",
["huh"] = "Huilliche",
["hui"] = "Huli",
["huj"] = "Hmong Guiyang Utara",
["huk"] = "Hulung",
["hul"] = "Hula",
["hum"] = "Hungana",
["huo"] = "Hu",
["hup"] = "Hupa",
["huq"] = "Tsat",
["hur"] = "Halkomelem",
["hus"] = "Wastek",
["huu"] = "Huitoto Murui",
["huv"] = "Huave",
["huw"] = "Hukumina",
["hux"] = "Huitoto Nüpode",
["huy"] = "Hulaulá",
["huz"] = "Hunzib",
["hvc"] = "budaya Vodoun Haiti",
["hvk"] = "Haveke",
["hvn"] = "Sabu",
["hwa"] = "Wané",
["hwc"] = "Kreol Hawaii",
["hwo"] = "Hwana",
["hy"] = "Armenia",
["hya"] = "Hya",
["hyx-pro"] = "Proto-Armenia",
["hz"] = "Herero",
["ia"] = "Interlingua",
["iai"] = "Iaai",
["ian"] = "Iatmul",
["iar"] = "Purari",
["iba"] = "Iban",
["ibb"] = "Ibibio",
["ibd"] = "Iwaidja",
["ibe"] = "Akpes",
["ibg"] = "Ibanag",
["ibh"] = "Bih",
["ibl"] = "Ibaloi",
["ibm"] = "Agoi",
["ibn"] = "Ibino",
["ibr"] = "Ibuoro",
["ibu"] = "Ibu",
["iby"] = "Ibani",
["ica"] = "Ede Ica",
["ich"] = "Etkywan",
["icl"] = "Isyarat Islandia",
["icr"] = "Kreol Inggris Islander",
["id"] = "Indunisia",
["ida"] = "Idakho-Isukha-Tiriki",
["idb"] = "Indo-Purtugis",
["idc"] = "Idon",
["idd"] = "Ede Idaca",
["ide"] = "Idere",
["idi"] = "Idi",
["idr"] = "Indri",
["ids"] = "Idesa",
["idt"] = "Idaté",
["idu"] = "Idoma",
["ie"] = "Interlingue",
["ifa"] = "Ifugao Amganad",
["ifb"] = "Ifugao Batad",
["ife"] = "Ifè",
["iff"] = "Ifo",
["ifk"] = "Ifugao Tuwali",
["ifm"] = "Teke-Fuumu",
["ifu"] = "Ifugao Mayoyao",
["ify"] = "Kallahan Keley-I",
["ig"] = "Igbo",
["igb"] = "Ebira",
["ige"] = "Igede",
["igg"] = "Igana",
["igl"] = "Igala",
["igm"] = "Kanggape",
["ign"] = "Ignaciano",
["igo"] = "Isebe",
["igs"] = "Glosa",
["igw"] = "Igwe",
["ihb"] = "Pijin Iha",
["ihi"] = "Ihievbe",
["ihp"] = "Iha",
["ii"] = "Yi Sichuan",
["iir-nur-pro"] = "Proto-Nuristani",
["iir-pro"] = "Proto-Indo-Iran",
["ijc"] = "Izon",
["ije"] = "Biseni",
["ijj"] = "Ede Ije",
["ijn"] = "Kalabari",
["ijo-pro"] = "Proto-Ijoid",
["ijs"] = "Ijo Tenggara",
["ik"] = "Inupiaq",
["ike"] = "Inuktitut Kanada Timur",
["iki"] = "Iko",
["ikk"] = "Ika",
["ikl"] = "Ikulu",
["iko"] = "Olulumo-Ikom",
["ikp"] = "Ikpeshi",
["ikr"] = "Ikaranggal",
["iks"] = "Isyarat Inuit",
["ikt"] = "Inuvialuktun",
["ikv"] = "Iku-Gora-Ankwa",
["ikw"] = "Ikwere",
["ikx"] = "Ik",
["ikz"] = "Ikizu",
["ila"] = "Ile Ape",
["ilb"] = "Ila",
["ilg"] = "Ilgar",
["ili"] = "Turki Ili",
["ilk"] = "Ilongot",
["ill"] = "Iranun",
["ilo"] = "Ilocano",
["ils"] = "Isyarat Internasional",
["ilu"] = "Ili'uun",
["ilv"] = "Ilue",
["ima"] = "Mala Malasar",
["imi"] = "Anamgura",
["iml"] = "Miluk",
["imn"] = "Imonda",
["imo"] = "Imbongu",
["imr"] = "Imroing",
["ims"] = "Marsian",
["imy"] = "Milyan",
["inb"] = "Inga",
["inc-ash"] = "Prakrit Ashokan",
["inc-cen-pro"] = "Proto-Indo-Aryan Tengah",
["inc-gup"] = "Apabhramsa Gurjar",
["inc-kam"] = "Prakrit Kamarupi",
["inc-kha"] = "Prakrit Khasa",
["inc-kho"] = "Kholosi",
["inc-mas"] = "Assam Tengahan",
["inc-mbn"] = "Bengal Tengahan",
["inc-mgd"] = "Prakrit Magadhi",
["inc-mgu"] = "Gujarat Tengahan",
["inc-mor"] = "Oriya Tengahan",
["inc-oas"] = "Assam Awal",
["inc-obn"] = "Bengal Kuna",
["inc-ogu"] = "Gujarat Kuna",
["inc-ohi"] = "Hindi Kuna",
["inc-oor"] = "Oriya Kuna",
["inc-opa"] = "Punjab Kuna",
["inc-ork"] = "Kamta Kuna",
["inc-pra"] = "Prakrit",
["inc-pro"] = "Proto-Indo-Aryan",
["inc-psc"] = "Prakrit Paisaci",
["inc-sap"] = "Apabhramsa Sauraseni",
["inc-tak"] = "Apabhramsa Takka",
["inc-vra"] = "Apabhramsa Vracada",
["ine-ana-pro"] = "Proto-Anatolia",
["ine-bsl-pro"] = "Proto-Balto-Slavik",
["ine-pae"] = "Paeonian",
["ine-pro"] = "Proto-Indo-Eropa",
["ine-toc-pro"] = "Proto-Tocharian",
["ing"] = "Deg Xinag",
["inh"] = "Ingush",
["inj"] = "Inga Hutan",
["inl"] = "Isyarat Indunisia",
["inm"] = "Minaean",
["inn"] = "Isinai",
["ino"] = "Inoke-Yate",
["inp"] = "Iñapari",
["ins"] = "Isyarat India",
["int"] = "Intha",
["inz"] = "Ineseño",
["io"] = "Ido",
["ior"] = "Inor",
["iou"] = "Tuma-Irumu",
["iow"] = "Chiwere",
["ipi"] = "Ipili",
["ipo"] = "Ipiko",
["iqu"] = "Iquito",
["iqw"] = "Ikwo",
["ira-kms-pro"] = "Proto-Komisenian",
["ira-mny-pro"] = "Proto-Munji-Yidgha",
["ira-mpr-pro"] = "Proto-Medo-Parthian",
["ira-pat-pro"] = "Proto-Pathan",
["ira-pro"] = "Proto-Iran",
["ira-sgc-pro"] = "Proto-Sogdic",
["ira-sgi-pro"] = "Proto-Sanglechi-Ishkashimi",
["ira-shr-pro"] = "Proto-Shughni-Roshani",
["ira-shy-pro"] = "Proto-Shughni-Yazghulami",
["ira-sym-pro"] = "Proto-Shughni-Yazghulami-Munji",
["ira-wnj"] = "Vanji",
["ira-zgr-pro"] = "Proto-Zaza-Gorani",
["ire"] = "Iresim",
["irh"] = "Irarutu",
["iri"] = "Rigwe",
["irk"] = "Iraqw",
["irn"] = "Irantxe",
["iro-ere"] = "Erie",
["iro-min"] = "Mingo",
["iro-nor-pro"] = "Proto-Iroquois Utara",
["iro-pro"] = "Proto-Iroquois",
["irr"] = "Ir",
["iru"] = "Irula",
["irx"] = "Kamberau",
["iry"] = "Iraya",
["is"] = "Islandik",
["isa"] = "Isabi",
["isc"] = "Isconahua",
["isd"] = "Isnag",
["ise"] = "Isyarat Italia",
["isg"] = "Isyarat Irlandia",
["ish"] = "Esan",
["isi"] = "Nkem-Nkum",
["isk"] = "Ishkashimi",
["ism"] = "Masimasi",
["isn"] = "Isanzu",
["iso"] = "Isoko",
["isr"] = "Isyarat Israel",
["ist"] = "Istriot",
["isu"] = "Isu",
["it"] = "Italia",
["itb"] = "Itneg Binongan",
["itc-pro"] = "Proto-Italik",
["itd"] = "Tidong Selatan",
["ite"] = "Itene",
["iti"] = "Itneg Inlaod",
["itk"] = "Judeo-Italia",
["itl"] = "Itelmen",
["itm"] = "Itu Mbon Uzo",
["ito"] = "Itonama",
["itr"] = "Iteri",
["its"] = "Itsekiri",
["itt"] = "Itneg Maeng",
["itv"] = "Itawit",
["itw"] = "Ito",
["itx"] = "Itik",
["ity"] = "Itneg Moyadan",
["itz"] = "Itzá",
["iu"] = "Inuktitut",
["ium"] = "Mien Iu",
["ivb"] = "Ibatan",
["ivv"] = "Ivatan",
["iwk"] = "I-Wak",
["iwm"] = "Iwam",
["iwo"] = "Iwur",
["iws"] = "Iwam Sepik",
["ixc"] = "Ixcatec",
["ixl"] = "Ixil",
["iya"] = "Iyayu",
["iyo"] = "Mesaka",
["iyx"] = "Yaa",
["izh"] = "Ingrian",
["izi"] = "Izi-Ezaa-Ikwo-Mgbo",
["izr"] = "Izere",
["izz"] = "Izi",
["ja"] = "Japang",
["jaa"] = "Jamamadí",
["jab"] = "Hyam",
["jac"] = "Jakaltek",
["jad"] = "Jahanka",
["jae"] = "Jabem",
["jaf"] = "Jara",
["jah"] = "Jah Hut",
["jaj"] = "Zazao",
["jal"] = "Yalahatan",
["jam"] = "Kreol Jamaika",
["jan"] = "Janday",
["jao"] = "Yanyuwa",
["jaq"] = "Yaqay",
["jas"] = "Jawa Kaledonia Baru",
["jat"] = "Jakati",
["jau"] = "Yaur",
["jax"] = "Malayu Jambi",
["jay"] = "Yan-nhangu",
["jaz"] = "Jawe",
["jbj"] = "Arandai",
["jbk"] = "Barikewa",
["jbn"] = "Nefusa",
["jbo"] = "Lojban",
["jbr"] = "Jofotek-Bromnya",
["jbt"] = "Jabutí",
["jbu"] = "Jukun Takum",
["jbw"] = "Yawijibaya",
["jcs"] = "Isyarat Jamaika (negara)",
["jct"] = "Krymchak",
["jda"] = "Jad",
["jdg"] = "Jadgali",
["jdt"] = "Judeo-Tat",
["jeb"] = "Jebero",
["jee"] = "Jerung",
["jeg"] = "Jeng",
["jeh"] = "Jeh",
["jei"] = "Yei",
["jek"] = "Kuo Jeri",
["jel"] = "Yelmek",
["jen"] = "Dza",
["jer"] = "Jere",
["jet"] = "Manem",
["jeu"] = "Jonkor Bourmataguil",
["jgb"] = "Ngbee",
["jgk"] = "Gwak",
["jgo"] = "Ngomba",
["jhi"] = "Jehai",
["jhs"] = "Isyarat Jhankot",
["jia"] = "Jina",
["jib"] = "Jibu",
["jic"] = "Tol",
["jid"] = "Bu",
["jie"] = "Jilbe",
["jig"] = "Jingulu",
["jih"] = "Shangzhai",
["jii"] = "Jiiddu",
["jil"] = "Jilim",
["jim"] = "Jimjimen",
["jio"] = "Jiamao",
["jiq"] = "Khroskyabs",
["jit"] = "Jita",
["jiu"] = "Jinuo Youle",
["jiv"] = "Shuar",
["jiy"] = "Jinuo Buyuan",
["jje"] = "Jeju",
["jjr"] = "Zhár",
["jka"] = "Kaera",
["jko"] = "Kubo",
["jkr"] = "Koro (India)",
["jku"] = "Labir",
["jle"] = "Ngile",
["jls"] = "Isyarat Jamaika",
["jma"] = "Dima",
["jmb"] = "Zumbun",
["jmc"] = "Machame",
["jmd"] = "Yamdena",
["jmi"] = "Jimi",
["jml"] = "Jumli",
["jmn"] = "Naga Makuri",
["jmr"] = "Kamara",
["jmw"] = "Mouwase",
["jmx"] = "Mixtec Juxtlahuaca Barat",
["jna"] = "Jangshung",
["jnd"] = "Jandavra",
["jng"] = "Yangman",
["jni"] = "Janji",
["jnj"] = "Yemsa",
["jnl"] = "Rawat",
["jns"] = "Jaunsari",
["job"] = "Joba",
["jod"] = "Wojenaka",
["jor"] = "Jorá",
["jos"] = "Isyarat Yordania",
["jow"] = "Jowulu",
["jpr"] = "Judeo-Persia",
["jpx-pro"] = "Proto-Japang",
["jpx-ryu-pro"] = "Proto-Ryukyu",
["jqr"] = "Jaqaru",
["jra"] = "Jarai",
["jrr"] = "Jiru",
["jru"] = "Japrería",
["jsl"] = "Isyarat Japang",
["jua"] = "Júma",
["jub"] = "Wannu",
["juc"] = "Jurchen",
["jud"] = "Worodougou",
["juh"] = "Hone",
["jui"] = "Ngadjuri",
["juk"] = "Wapan",
["jul"] = "Jirel",
["jum"] = "Jumjum",
["jun"] = "Juang",
["juo"] = "Jiba",
["jup"] = "Hupdë",
["jur"] = "Jurúna",
["jus"] = "Isyarat Jumla",
["jut"] = "Jutish",
["juu"] = "Ju",
["juw"] = "Wãpha",
["juy"] = "Juray",
["jv"] = "Jawa",
["jvd"] = "Javindo",
["jvn"] = "Jawa Karibia",
["jwi"] = "Jwira-Pepesa",
["jyy"] = "Jaya",
["ka"] = "Georgia",
["kaa"] = "Karakalpak",
["kab"] = "Kabyle",
["kac"] = "Jingpho",
["kad"] = "Kadara",
["kae"] = "Ketangalan",
["kaf"] = "Katso",
["kag"] = "Kajaman",
["kah"] = "Fer",
["kai"] = "Karekare",
["kaj"] = "Jju",
["kak"] = "Kallahan Kayapa",
["kam"] = "Kamba",
["kao"] = "Kassonke",
["kap"] = "Bezhta",
["kaq"] = "Capanahua",
["kar-pro"] = "Proto-Karen",
["kaw"] = "Jawa Kuna",
["kax"] = "Kao",
["kay"] = "Kamayurá",
["kba"] = "Kalarko",
["kbb"] = "Kaxuyana",
["kbc"] = "Kadiwéu",
["kbd"] = "Kabardian",
["kbe"] = "Kanju",
["kbh"] = "Camsá",
["kbi"] = "Kaptiau",
["kbj"] = "Kari",
["kbk"] = "Koiari Rumput",
["kbm"] = "Iwal",
["kbn"] = "Kare (Africa)",
["kbo"] = "Keliko",
["kbp"] = "Kabiyé",
["kbq"] = "Kamano",
["kbr"] = "Kafa",
["kbs"] = "Kande",
["kbt"] = "Gabadi",
["kbu"] = "Kabutra",
["kbv"] = "Kamberataro",
["kbw"] = "Kaiep",
["kbx"] = "Ap Ma",
["kbz"] = "Duhwa",
["kca"] = "Khanty",
["kcb"] = "Kawacha",
["kcc"] = "Lubila",
["kcd"] = "Kanum Ngkâlmpw",
["kce"] = "Kaivi",
["kcf"] = "Ukaan",
["kcg"] = "Tyap",
["kch"] = "Vono",
["kci"] = "Kamantan",
["kcj"] = "Kobiana",
["kck"] = "Kalanga",
["kcl"] = "Kala",
["kcm"] = "Gula Tar",
["kcn"] = "Nubi",
["kco"] = "Kinalakna",
["kcp"] = "Kanga",
["kcq"] = "Kamo",
["kcr"] = "Katla",
["kcs"] = "Koenoem",
["kct"] = "Kaian",
["kcu"] = "Kikami",
["kcv"] = "Kete",
["kcw"] = "Kabwari",
["kcx"] = "Kachama-Ganjule",
["kcy"] = "Korandje",
["kcz"] = "Konongo",
["kda"] = "Worimi",
["kdc"] = "Kutu",
["kdd"] = "Yankunytjatjara",
["kde"] = "Makonde",
["kdf"] = "Mamusi",
["kdg"] = "Seba",
["kdh"] = "Tem",
["kdi"] = "Kumam",
["kdj"] = "Karamojong",
["kdk"] = "Numee",
["kdl"] = "Tsikimba",
["kdm"] = "Kagoma",
["kdn"] = "Kunda",
["kdp"] = "Kaningdon-Nindem",
["kdq"] = "Koch",
["kdr"] = "Karaim",
["kdt"] = "Kuy",
["kdu"] = "Kadaru",
["kdv"] = "Kado",
["kdw"] = "Koneraw",
["kdx"] = "Kam",
["kdy"] = "Keder",
["kdz"] = "Kwaja",
["kea"] = "Kabuverdianu",
["keb"] = "Kélé",
["kec"] = "Keiga",
["ked"] = "Kerewe",
["kee"] = "Keres Timur",
["kef"] = "Kpessi",
["keg"] = "Tese",
["keh"] = "Keak",
["kei"] = "Kei",
["kej"] = "Kadar",
["kek"] = "Q'eqchi",
["kel"] = "Kela-Yela",
["kem"] = "Kemak",
["ken"] = "Kenyang",
["keo"] = "Kakwa",
["kep"] = "Kaikadi",
["keq"] = "Kamar",
["ker"] = "Kera",
["kes"] = "Kugbo",
["ket"] = "Ket",
["keu"] = "Akebu",
["kev"] = "Kanikkaran",
["kew"] = "Kewa",
["kex"] = "Kukna",
["key"] = "Kupia",
["kez"] = "Kukele",
["kfa"] = "Kodava",
["kfb"] = "Kolami",
["kfc"] = "Konda-Dora",
["kfd"] = "Koraga Korra",
["kfe"] = "Kota (India)",
["kff"] = "Koya",
["kfg"] = "Kudiya",
["kfh"] = "Kurichiya",
["kfi"] = "Kurumba Kannada",
["kfj"] = "Kemiehua",
["kfk"] = "Kinnauri",
["kfl"] = "Kung",
["kfn"] = "Kuk",
["kfo"] = "Koro (Afrika Barat)",
["kfp"] = "Korwa",
["kfq"] = "Korku",
["kfr"] = "Kachchi",
["kfs"] = "Bilaspuri",
["kft"] = "Kanjari",
["kfu"] = "Katkari",
["kfv"] = "Kurmukar",
["kfw"] = "Naga Kharam",
["kfx"] = "Pahari Kullu",
["kfy"] = "Kumaoni",
["kfz"] = "Koromfé",
["kg"] = "Kongo",
["kga"] = "Koyaga",
["kgb"] = "Kawe",
["kgd"] = "Kataang",
["kge"] = "Komering",
["kgf"] = "Kube",
["kgg"] = "Kusunda",
["kgi"] = "Isyarat Selangor",
["kgj"] = "Kham Gamale",
["kgk"] = "Kaiwá",
["kgl"] = "Kunggari",
["kgm"] = "Karipúna",
["kgn"] = "Karingani",
["kgo"] = "Krongo",
["kgp"] = "Kaingang",
["kgq"] = "Kamoro",
["kgr"] = "Abun",
["kgs"] = "Kumbainggar",
["kgt"] = "Somyev",
["kgu"] = "Kobol",
["kgv"] = "Karas",
["kgw"] = "Karon Dori",
["kgx"] = "Kamaru",
["kgy"] = "Kyerung",
["kha"] = "Khasi",
["khb"] = "Lü",
["khc"] = "Tukang Besi Utara",
["khd"] = "Kanum Bädi",
["khe"] = "Korowai",
["khf"] = "Khuen",
["khh"] = "Kehu",
["khi-kho-pro"] = "Proto-Khoe",
["khi-kun"] = "ǃKung",
["khj"] = "Kuturmi",
["khl"] = "Lusi",
["khn"] = "Khandeshi",
["kho"] = "Khotan",
["khp"] = "Kapauri",
["khq"] = "Koyra Chiini",
["khr"] = "Kharia",
["khs"] = "Kasua",
["kht"] = "Khamti",
["khu"] = "Nkhumbi",
["khv"] = "Khvarshi",
["khw"] = "Khowar",
["khx"] = "Kanu",
["khy"] = "Ekele",
["khz"] = "Keapara",
["ki"] = "Kikuyu",
["kia"] = "Kim",
["kib"] = "Koalib",
["kic"] = "Kickapoo",
["kid"] = "Koshin",
["kie"] = "Kibet",
["kif"] = "Kham Parbate Timur",
["kig"] = "Kimaama",
["kih"] = "Kilmeri",
["kii"] = "Kitsai",
["kij"] = "Kilivila",
["kil"] = "Kariya",
["kim"] = "Tofa",
["kio"] = "Kiowa",
["kip"] = "Kham Sheshi",
["kiq"] = "Kosadle",
["kis"] = "Kis",
["kit"] = "Agob",
["kiv"] = "Kimbu",
["kiw"] = "Kiwai Timur Laut",
["kix"] = "Naga Khiamniungan",
["kiy"] = "Kirikiri",
["kiz"] = "Kisi",
["kj"] = "Kwanyama",
["kja"] = "Mlap",
["kjb"] = "Q'anjob'al",
["kjc"] = "Konjo Pesisir",
["kjd"] = "Kiwai Selatan",
["kje"] = "Kisar",
["kjg"] = "Khmu",
["kjh"] = "Khakas",
["kji"] = "Zabana",
["kjj"] = "Khinalug",
["kjk"] = "Konjo Pegunungan",
["kjl"] = "Kham",
["kjm"] = "Kháng",
["kjn"] = "Kunjen",
["kjo"] = "Kinnauri Harijan",
["kjp"] = "Pwo Timur",
["kjq"] = "Keres Barat",
["kjr"] = "Kurudu",
["kjs"] = "Kewa Timur",
["kjt"] = "Pwo Phrae",
["kju"] = "Kashaya",
["kjx"] = "Ramopa",
["kjy"] = "Erave",
["kjz"] = "Bumthangkha",
["kk"] = "Kazakh",
["kka"] = "Kakanda",
["kkb"] = "Kwerisa",
["kkc"] = "Odoodee",
["kkd"] = "Kinuku",
["kke"] = "Kakabe",
["kkf"] = "Monpa Kalaktang",
["kkg"] = "Kalinga Mabaka Valley",
["kkh"] = "Khün",
["kki"] = "Kagulu",
["kkj"] = "Kako",
["kkk"] = "Kokota",
["kkl"] = "Yale Kosarek",
["kkm"] = "Kiong",
["kkn"] = "Kon Keu",
["kko"] = "Karko",
["kkp"] = "Koko-Bera",
["kkq"] = "Kaiku",
["kkr"] = "Kir-Balar",
["kks"] = "Kirfi",
["kkt"] = "Koi",
["kku"] = "Tumi",
["kkv"] = "Kangayan",
["kkw"] = "Teke-Kukuya",
["kkx"] = "Kohin",
["kky"] = "Guugu Yimidhirr",
["kkz"] = "Kaska",
["kl"] = "Grinlandik",
["kla"] = "Klamath-Modoc",
["klb"] = "Kiliwa",
["klc"] = "Kolbila",
["kld"] = "Gamilaraay",
["kle"] = "Kulung",
["klf"] = "Kendeje",
["klg"] = "Kalagan Tagakaulu",
["klh"] = "Weliki",
["kli"] = "Kalumpang",
["klj"] = "Khalaj",
["klk"] = "Kono (Nigeria)",
["kll"] = "Kalagan Kagan",
["klm"] = "Kolom",
["kln"] = "Kalenjin",
["klo"] = "Kapya",
["klp"] = "Kamasa",
["klq"] = "Rumu",
["klr"] = "Khaling",
["kls"] = "Kalasha",
["klt"] = "Nukna",
["klu"] = "Klao",
["klv"] = "Maskelynes",
["klw"] = "Lindu",
["klx"] = "Koluwawa",
["kly"] = "Kalao",
["klz"] = "Kabola",
["km"] = "Khmer",
["kma"] = "Konni",
["kmb"] = "Kimbundu",
["kmc"] = "Kam Selatan",
["kmd"] = "Kalinga Madukayang",
["kme"] = "Bakole",
["kmf"] = "Kare (Papua)",
["kmg"] = "Kâte",
["kmh"] = "Kalam",
["kmi"] = "Kami",
["kmj"] = "Paharia Kumarbhag",
["kmk"] = "Kalinga Limos",
["kml"] = "Kalinga Tanudan",
["kmm"] = "Kom (India)",
["kmn"] = "Awtuw",
["kmo"] = "Kwoma",
["kmp"] = "Gimme",
["kmq"] = "Kwama",
["kmr"] = "Kurdi Utara",
["kms"] = "Kamasau",
["kmt"] = "Kemtuik",
["kmu"] = "Kanite",
["kmv"] = "Kreol Parancis Karipúna",
["kmw"] = "Kumu",
["kmx"] = "Waboda",
["kmy"] = "Koma",
["kmz"] = "Turki Khorasani",
["kn"] = "Kannada",
["kna"] = "Kanakuru",
["knb"] = "Kalinga Lubuagan",
["knd"] = "Konda",
["kne"] = "Kankanaey",
["knf"] = "Mankanya",
["kni"] = "Kanufi",
["knj"] = "Akatek",
["knk"] = "Kuranko",
["knl"] = "Keninjal",
["knm"] = "Kanamari",
["kno"] = "Kono (Sierra Leone)",
["knp"] = "Kwanja",
["knq"] = "Kintaq",
["knr"] = "Kaningra",
["kns"] = "Kensiu",
["knt"] = "Katukina",
["knu"] = "Kono (Guinea)",
["knv"] = "Tabo",
["knx"] = "Kanayatn",
["kny"] = "Kanyok",
["knz"] = "Kalamsé",
["ko"] = "Korea",
["ko-ear"] = "Korea Modern Awal",
["koa"] = "Konomala",
["koc"] = "Kpati",
["kod"] = "Kodi",
["koe"] = "Kacipo-Balesi",
["kof"] = "Kubi",
["kog"] = "Cogui",
["koh"] = "Koyo",
["koi"] = "Komi-Permyak",
["kok"] = "Konkani",
["kol"] = "Kol (Papua)",
["koo"] = "Konzo",
["kop"] = "Waube",
["koq"] = "Kota (Gabon)",
["kos"] = "Kosraean",
["kot"] = "Lagwan",
["kou"] = "Koke",
["kov"] = "Kudu-Camo",
["kow"] = "Kugama",
["koy"] = "Koyukon",
["koz"] = "Korak",
["kpa"] = "Kutto",
["kpb"] = "Kurumba Mullu",
["kpc"] = "Curripaco",
["kpd"] = "Koba",
["kpe"] = "Kpelle",
["kpf"] = "Komba",
["kpg"] = "Kapingamarangi",
["kph"] = "Kplang",
["kpi"] = "Kofei",
["kpj"] = "Karajá",
["kpk"] = "Kpan",
["kpl"] = "Kpala",
["kpm"] = "Koho",
["kpn"] = "Kepkiriwát",
["kpo"] = "Ikposo",
["kpp"] = "Karen Paku",
["kpq"] = "Korupun-Sela",
["kpr"] = "Korafe-Yegha",
["kps"] = "Tehit",
["kpt"] = "Karata",
["kpu"] = "Kafoa",
["kpv"] = "Komi-Zyrian",
["kpw"] = "Kobon",
["kpx"] = "Koiari Gunung",
["kpy"] = "Koryak",
["kpz"] = "Kupsabiny",
["kqa"] = "Mum",
["kqb"] = "Kovai",
["kqc"] = "Doromu-Koki",
["kqd"] = "Koy Sanjaq Surat",
["kqe"] = "Kalagan",
["kqf"] = "Kakabai",
["kqg"] = "Khe",
["kqh"] = "Kisankasa",
["kqi"] = "Koitabu",
["kqj"] = "Koromira",
["kqk"] = "Gbe Kotafon",
["kql"] = "Kyenele",
["kqm"] = "Khisa",
["kqn"] = "Kaonde",
["kqo"] = "Krahn Timur",
["kqp"] = "Kimré",
["kqq"] = "Krenak",
["kqr"] = "Kimaragang",
["kqs"] = "Kissi Utara",
["kqt"] = "Kadazan Sungai Klias",
["kqu"] = "Seroa",
["kqv"] = "Okolod",
["kqw"] = "Kandas",
["kqx"] = "Mser",
["kqy"] = "Koorete",
["kqz"] = "Korana",
["kr"] = "Kanuri",
["kra"] = "Kumhali",
["krb"] = "Karkin",
["krc"] = "Karachay-Balkar",
["krd"] = "Kairui-Midiki",
["kre"] = "Panará",
["krf"] = "Koro (Vanuatu)",
["krh"] = "Kurama",
["kri"] = "Krio",
["krj"] = "Kinaray-a",
["krk"] = "Kerek",
["krl"] = "Karelian",
["krm"] = "Krim",
["krn"] = "Sapo",
["kro-pro"] = "Proto-Kru",
["krp"] = "Korop",
["krr"] = "Kru'ng",
["krs"] = "Kresh",
["kru"] = "Kurukh",
["krv"] = "Kavet",
["krw"] = "Krahn Barat",
["krx"] = "Karon",
["kry"] = "Kryts",
["krz"] = "Kanum Sota",
["ks"] = "Kashmir",
["ksa"] = "Shuwa-Zamani",
["ksb"] = "Shambala",
["ksc"] = "Kalinga Selatan",
["ksd"] = "Tolai",
["kse"] = "Kuni",
["ksf"] = "Bafia",
["ksg"] = "Kusaghe",
["ksi"] = "Krisa",
["ksj"] = "Uare",
["ksk"] = "Kansa",
["ksl"] = "Kumalu",
["ksm"] = "Kumba",
["ksn"] = "Kasiguranin",
["kso"] = "Kofa",
["ksp"] = "Kaba",
["ksq"] = "Kwaami",
["ksr"] = "Borong",
["kss"] = "Kissi Selatan",
["kst"] = "Winyé",
["ksu"] = "Khamyang",
["ksv"] = "Kusu",
["ksw"] = "Karen S'gaw",
["ksx"] = "Kedang",
["ksy"] = "Kharia Thar",
["ksz"] = "Kodaku",
["kta"] = "Katua",
["ktb"] = "Kambaata",
["ktc"] = "Kholok",
["ktd"] = "Kokata",
["ktf"] = "Kwami",
["ktg"] = "Kalkatungu",
["kth"] = "Karanga",
["kti"] = "Muyu Utara",
["ktj"] = "Plapo Krumen",
["ktk"] = "Kaniet",
["ktl"] = "Koroshi",
["ktm"] = "Kurti",
["ktn"] = "Karitiâna",
["kto"] = "Kuot",
["ktp"] = "Kaduo",
["ktq"] = "Katabaga",
["ktr"] = "Kota Marudu Tinagas",
["kts"] = "Muyu Selatan",
["ktt"] = "Ketum",
["ktu"] = "Kituba",
["ktv"] = "Katu Timur",
["ktw"] = "Kato",
["ktx"] = "Kaxararí",
["kty"] = "Kango",
["ktz"] = "Juǀ'hoan",
["ku-pro"] = "Proto-Kurdi",
["kub"] = "Kutep",
["kuc"] = "Kwinsu",
["kud"] = "Auhelawa",
["kue"] = "Kuman",
["kuf"] = "Katu Barat",
["kug"] = "Kupa",
["kuh"] = "Kushi",
["kui"] = "Kuikúro",
["kuj"] = "Kuria",
["kuk"] = "Kepo'",
["kul"] = "Kulere",
["kum"] = "Kumyk",
["kun"] = "Kunama",
["kuo"] = "Kumukio",
["kup"] = "Kunimaipa",
["kuq"] = "Karipuna",
["kus"] = "Kusaal",
["kut"] = "Kutenai",
["kuu"] = "Kuskokwim Hulu",
["kuv"] = "Kur",
["kuw"] = "Kpagua",
["kux"] = "Kukatja",
["kuy"] = "Kuuku-Ya'u",
["kuz"] = "Kunza",
["kva"] = "Bagvalal",
["kvb"] = "Orang Rimba",
["kvc"] = "Kove",
["kvd"] = "Kui (Indunisia)",
["kve"] = "Kalabakan",
["kvf"] = "Kabalai",
["kvg"] = "Kuni-Boazi",
["kvh"] = "Komodo",
["kvi"] = "Kwang",
["kvj"] = "Psikye",
["kvk"] = "Isyarat Korea",
["kvl"] = "Karen Brek",
["kvm"] = "Kendem",
["kvn"] = "Border Kuna",
["kvo"] = "Dobel",
["kvp"] = "Kompane",
["kvq"] = "Karen Geba",
["kvr"] = "Karinci",
["kvt"] = "Karen Lahta",
["kvu"] = "Karen Yinbaw",
["kvv"] = "Kola",
["kvw"] = "Wersing",
["kvx"] = "Koli Parkari",
["kvy"] = "Karen Yintale",
["kvz"] = "Tsakwambo",
["kw"] = "Cornish",
["kwa"] = "Dâw",
["kwb"] = "Baa",
["kwc"] = "Likwala",
["kwd"] = "Kwaio",
["kwe"] = "Kwerba",
["kwf"] = "Kwara'ae",
["kwg"] = "Sara Kaba Deme",
["kwh"] = "Kowiai",
["kwi"] = "Awa-Cuaiquer",
["kwj"] = "Kwanga",
["kwk"] = "Kwak'wala",
["kwl"] = "Kofyar",
["kwm"] = "Kwambi",
["kwn"] = "Kwangali",
["kwo"] = "Kwomtari",
["kwp"] = "Kodia",
["kwq"] = "Kwak",
["kwr"] = "Kwer",
["kws"] = "Kwese",
["kwt"] = "Kwesten",
["kwu"] = "Kwakum",
["kwv"] = "Sara Kaba Náà",
["kww"] = "Kwinti",
["kwx"] = "Khirwar",
["kwz"] = "Kwadi",
["kxa"] = "Kairiru",
["kxb"] = "Krobu",
["kxc"] = "Khonso",
["kxd"] = "Malayu Brunei",
["kxe"] = "Kakihum",
["kxf"] = "Karen Manumanaw",
["kxh"] = "Karo",
["kxi"] = "Murut Keningau",
["kxj"] = "Kulfa",
["kxk"] = "Karen Zayein",
["kxl"] = "Nepai Kurux",
["kxm"] = "Khmer Utara",
["kxn"] = "Kanowit",
["kxo"] = "Kanoé",
["kxp"] = "Koli Wadiyara",
["kxq"] = "Kanum Smärky",
["kxr"] = "Koro (Papua)",
["kxs"] = "Kangjia",
["kxt"] = "Koiwat",
["kxu"] = "Kui (India)",
["kxv"] = "Kuvi",
["kxw"] = "Konai",
["kxx"] = "Likuba",
["kxy"] = "Kayong",
["kxz"] = "Kerewo",
["ky"] = "Kirgiz",
["kya"] = "Kwaya",
["kyb"] = "Kalinga Butbut",
["kyc"] = "Kyaka",
["kyd"] = "Karey",
["kye"] = "Krache",
["kyf"] = "Kouya",
["kyg"] = "Keyagana",
["kyh"] = "Karok",
["kyi"] = "Kiput",
["kyj"] = "Karao",
["kyk"] = "Kamayo",
["kyl"] = "Kalapuya",
["kym"] = "Kpatili",
["kyn"] = "Karolanos",
["kyo"] = "Kelon",
["kyp"] = "Kang",
["kyq"] = "Kenga",
["kyr"] = "Kuruáya",
["kys"] = "Kayan Baram",
["kyt"] = "Kayagar",
["kyu"] = "Kayah Barat",
["kyv"] = "Kayort",
["kyw"] = "Kudmali",
["kyx"] = "Rapoisi",
["kyy"] = "Kambaira",
["kyz"] = "Kayabí",
["kza"] = "Karaboro Barat",
["kzb"] = "Kaibobo",
["kzc"] = "Kulango Bondoukou",
["kzd"] = "Kadai",
["kze"] = "Kosena",
["kzf"] = "Kaili Da'a",
["kzg"] = "Kikai",
["kzh"] = "Dongolawi",
["kzi"] = "Kelabit",
["kzj"] = "Kadazan Pesisir",
["kzk"] = "Kazukuru",
["kzl"] = "Kayeli",
["kzm"] = "Kais",
["kzn"] = "Kokola",
["kzo"] = "Kaningi",
["kzp"] = "Kaidipang",
["kzq"] = "Kaike",
["kzr"] = "Karang",
["kzs"] = "Dusun Sugut",
["kzt"] = "Dusun Tambunan",
["kzu"] = "Kayupulau",
["kzv"] = "Komyandaret",
["kzw"] = "Kariri",
["kzx"] = "Kamarian",
["kzy"] = "Kango-Sua",
["kzz"] = "Kalabra",
["la"] = "Latin",
["laa"] = "Lapuyan Subanun",
["lab"] = "Linear A",
["lac"] = "Lacandon",
["lad"] = "Ladino",
["lae"] = "Pattani",
["laf"] = "Lafofa",
["lag"] = "Langi",
["lah"] = "Lahnda",
["lai"] = "Lambya",
["laj"] = "Lango (Uganda)",
["lak"] = "Laka",
["lam"] = "Lamba",
["lan"] = "Laru",
["lap"] = "Kabba-Laka",
["laq"] = "Qabiao",
["lar"] = "Larteh",
["las"] = "Gur Lama",
["lau"] = "Laba",
["law"] = "Lauje",
["lax"] = "Tiwa",
["lay"] = "Bai Lama",
["laz"] = "Aribwatsa",
["lb"] = "Luksemburg",
["lbb"] = "Label",
["lbc"] = "Lakkia",
["lbe"] = "Lak",
["lbf"] = "Tinani",
["lbg"] = "Laopang",
["lbi"] = "La'bi",
["lbj"] = "Ladakhi",
["lbk"] = "Bontoc Tengah",
["lbl"] = "Bikol Libon",
["lbm"] = "Lodhi",
["lbn"] = "Lamet",
["lbo"] = "Laven",
["lbq"] = "Wampar",
["lbr"] = "Lorung Utara",
["lbs"] = "Isyarat Libya",
["lbt"] = "Lachi",
["lbu"] = "Labu",
["lbv"] = "Lavatbura-Lamusong",
["lbw"] = "Tolaki",
["lbx"] = "Lawangan-Pasér",
["lby"] = "Lamu-Lamu",
["lbz"] = "Lardil",
["lcc"] = "Legenyem",
["lcd"] = "Lola",
["lce"] = "Loncong",
["lcf"] = "Lubu",
["lch"] = "Luchazi",
["lcl"] = "Lisela",
["lcm"] = "Tungag",
["lcp"] = "Lawa Barat",
["lcq"] = "Luhu",
["lcs"] = "Lisabata-Nuniali",
["lda"] = "Kla",
["ldb"] = "Idun",
["ldd"] = "Luri (Nigeria)",
["ldg"] = "Lenyima",
["ldh"] = "Lamja-Dengsa-Tola",
["ldj"] = "Lemoro",
["ldk"] = "Leelau",
["ldl"] = "Kaan",
["ldm"] = "Landoma",
["ldn"] = "Láadan",
["ldo"] = "Loo",
["ldp"] = "Tso",
["ldq"] = "Lufu",
["lea"] = "Lega-Shabunda",
["leb"] = "Lala-Bisa",
["lec"] = "Leco",
["led"] = "Lendu",
["lee"] = "Lyélé",
["lef"] = "Lelemi",
["leh"] = "Lenje",
["lei"] = "Lemio",
["lej"] = "Lengola",
["lek"] = "Leipon",
["lel"] = "Lele (Kongo)",
["lem"] = "Nomaande",
["len"] = "Lenca Honduras",
["leo"] = "Leti (Kamerun)",
["lep"] = "Lepcha",
["leq"] = "Lembena",
["ler"] = "Lenkau",
["les"] = "Lese",
["let"] = "Lesing-Gelimi",
["leu"] = "Kara (Papua)",
["lev"] = "Lamma",
["lew"] = "Kaili Ledo",
["lex"] = "Luang",
["ley"] = "Lemolang",
["lez"] = "Lezgi",
["lfa"] = "Lefa",
["lfn"] = "Lingua Franca Nova",
["lg"] = "Luganda",
["lga"] = "Lungga",
["lgb"] = "Laghu",
["lgg"] = "Lugbara",
["lgh"] = "Laghuu",
["lgi"] = "Lengilu",
["lgk"] = "Neverver",
["lgl"] = "Wala",
["lgm"] = "Lega-Mwenga",
["lgn"] = "Opuuo",
["lgq"] = "Logba",
["lgr"] = "Lengo",
["lgs"] = "Isyarat Guinea-Bissau",
["lgt"] = "Pahi",
["lgu"] = "Longgu",
["lgz"] = "Ligenza",
["lha"] = "Laha (Vietnam)",
["lhh"] = "Laha (Indunisia)",
["lhi"] = "Lahu Shi",
["lhl"] = "Lahul Lohar",
["lhn"] = "Lahanan",
["lhp"] = "Lhokpu",
["lhs"] = "Mlahsö",
["lht"] = "Lo-Toga",
["lhu"] = "Lahu",
["li"] = "Limburg",
["lia"] = "Limba Tengah Barat",
["lib"] = "Likum",
["lic"] = "Hlai",
["lid"] = "Nyindrou",
["lie"] = "Likila",
["lif"] = "Limbu",
["lig"] = "Ligbi",
["lih"] = "Lihir",
["lii"] = "Lingkhim",
["lij"] = "Liguria",
["lik"] = "Lika",
["lil"] = "Lillooet",
["lio"] = "Liki",
["lip"] = "Sekpele",
["liq"] = "Libido",
["lir"] = "Inggris Liberia",
["lis"] = "Lisu",
["liu"] = "Logorik",
["liv"] = "Livonia",
["liw"] = "Col",
["lix"] = "Liabuku",
["liy"] = "Banda-Bambari",
["liz"] = "Libinza",
["lja"] = "Golpa",
["lje"] = "Rampi",
["lji"] = "Laiyolo",
["ljl"] = "Lio",
["ljp"] = "Lampung Api",
["ljw"] = "Yirandali",
["ljx"] = "Yuru",
["lka"] = "Lakalei",
["lkb"] = "Kabras",
["lkc"] = "Kucong",
["lkd"] = "Lakondê",
["lke"] = "Kenyi",
["lkh"] = "Lakha",
["lki"] = "Laki",
["lkj"] = "Remun",
["lkl"] = "Laeko-Libuat",
["lkm"] = "Kalaamaya",
["lkn"] = "Lakon",
["lko"] = "Khayo",
["lkr"] = "Päri",
["lks"] = "Kisa",
["lkt"] = "Lakota",
["lku"] = "Kungkari",
["lky"] = "Lokoya",
["lla"] = "Lala-Roba",
["llb"] = "Lolo",
["llc"] = "Lele (Guinea)",
["lld"] = "Ladin",
["lle"] = "Lele (Papua)",
["llf"] = "Hermit",
["llg"] = "Lole",
["llh"] = "Lamu",
["lli"] = "Teke-Laali",
["llj"] = "Ladji-Ladji",
["llk"] = "Lelak",
["lll"] = "Lilau",
["llm"] = "Lasalimu",
["lln"] = "Lele (Chad)",
["llo"] = "Khlor",
["llp"] = "Efate Utara",
["llq"] = "Lolak",
["lls"] = "Isyarat Lituania",
["llu"] = "Lau",
["llx"] = "Lauan",
["lma"] = "Limba Timur",
["lmb"] = "Merei",
["lmc"] = "Limilngan",
["lmd"] = "Lumun",
["lme"] = "Pévé",
["lmf"] = "Lembata Selatan",
["lmg"] = "Lamogai",
["lmh"] = "Lambichhong",
["lmi"] = "Lombi",
["lmj"] = "Lembata Barat",
["lmk"] = "Lamkang",
["lml"] = "Raga",
["lmn"] = "Lambadi",
["lmo"] = "Lombard",
["lmp"] = "Limbum",
["lmq"] = "Lamatuka",
["lmr"] = "Lamalera",
["lmu"] = "Lamenu",
["lmv"] = "Lomaiviti",
["lmw"] = "Miwok Lake",
["lmx"] = "Laimbue",
["lmy"] = "Laboya",
["lmz"] = "Lumbee",
["ln"] = "Lingala",
["lna"] = "Langbashe",
["lnb"] = "Mbalanhu",
["lnd"] = "Lun Bawang",
["lnh"] = "Lanoh",
["lni"] = "Daantanai'",
["lnj"] = "Linngithigh",
["lnl"] = "Banda Tengah Selatan",
["lnm"] = "Langam",
["lnn"] = "Lorediakarkar",
["lno"] = "Lango (Sudan)",
["lns"] = "Lamnso'",
["lnu"] = "Longuda",
["lnw"] = "Lanima",
["lo"] = "Lao",
["loa"] = "Loloda",
["lob"] = "Lobi",
["loc"] = "Inonhan",
["lod"] = "Berawan",
["loe"] = "Saluan",
["lof"] = "Logol",
["log"] = "Logo",
["loh"] = "Narim",
["loi"] = "Lomakka",
["loj"] = "Lou",
["lok"] = "Loko",
["lol"] = "Mongo",
["lom"] = "Looma",
["lon"] = "Malawi Lomwe",
["loo"] = "Lombo",
["lop"] = "Lopa",
["loq"] = "Lobala",
["lor"] = "Téén",
["los"] = "Loniu",
["lot"] = "Lotuko",
["lou"] = "Kreol Louisiana",
["lov"] = "Lopi",
["low"] = "Lobu Tampias",
["lox"] = "Loun",
["loz"] = "Lozi",
["lpa"] = "Lelepa",
["lpe"] = "Lepki",
["lpn"] = "Naga Long Phuri",
["lpo"] = "Lipo",
["lpx"] = "Lopit",
["lra"] = "Rara Bakati'",
["lrc"] = "Luri Utara",
["lre"] = "Laurentian",
["lrg"] = "Laragia",
["lri"] = "Marachi",
["lrk"] = "Loarki",
["lrl"] = "Larestani",
["lrm"] = "Marama",
["lrn"] = "Lorang",
["lro"] = "Laro",
["lrr"] = "Lorung Selatan",
["lrt"] = "Malayu Larantuka",
["lrv"] = "Larevat",
["lrz"] = "Lemerig",
["lsa"] = "Lasgerdi",
["lsd"] = "Lishana Deni",
["lse"] = "Lusengo",
["lsh"] = "Lish",
["lsi"] = "Lashi",
["lsl"] = "Isyarat Latvia",
["lsm"] = "Saamia",
["lso"] = "Isyarat Laos",
["lsp"] = "Isyarat Panama",
["lsr"] = "Aruop",
["lss"] = "Lasi",
["lst"] = "Isyarat Trinidad dan Tobago",
["lsy"] = "Isyarat Mauritius",
["lt"] = "Lithuania",
["ltc"] = "Tionghoa Tengahan",
["ltg"] = "Latgalian",
["lti"] = "Leti (Indunisia)",
["ltn"] = "Latundê",
["lto"] = "Olutsotso",
["lts"] = "Lutachoni",
["ltu"] = "Latu",
["lu"] = "Luba-Katanga",
["lua"] = "Luba-Kasai",
["luc"] = "Aringa",
["lud"] = "Ludian",
["lue"] = "Luvale",
["luf"] = "Laua",
["lui"] = "Luiseño",
["luj"] = "Luna",
["luk"] = "Lunanakha",
["lul"] = "Olu'bo",
["lum"] = "Luimbi",
["lun"] = "Lunda",
["luo"] = "Luo",
["lup"] = "Lumbu",
["luq"] = "Lucumí",
["lur"] = "Laura",
["lus"] = "Mizo",
["lut"] = "Lushootseed",
["luu"] = "Lumba-Yakkha",
["luv"] = "Luwati",
["luy"] = "Luhya",
["luz"] = "Luri Selatan",
["lv"] = "Latvia",
["lva"] = "Maku'a",
["lvi"] = "Lawi",
["lvk"] = "Lavukaleve",
["lvu"] = "Levuka",
["lwa"] = "Lwalu",
["lwe"] = "Lewo Eleng",
["lwg"] = "Wanga",
["lwh"] = "Lachi Putih",
["lwl"] = "Lawa Timur",
["lwm"] = "Laomian",
["lwo"] = "Luwo",
["lws"] = "Isyarat Malawi",
["lwt"] = "Lewotobi",
["lwu"] = "Lawu",
["lww"] = "Lewo",
["lya"] = "Layakha",
["lyg"] = "Lyngngam",
["lyn"] = "Luyana",
["lzh"] = "Tionghoa Literatur",
["lzl"] = "Litzlitz",
["lzn"] = "Naga Leinong",
["lzz"] = "Laz",
["maa"] = "Mazatec San Jerónimo Tecóatl",
["mab"] = "Mixtec Yutanduchi",
["mad"] = "Madura",
["mae"] = "Bo-Rukul",
["maf"] = "Mafa",
["mag"] = "Magahi",
["mai"] = "Maithili",
["maj"] = "Mazatec Jalapa de Díaz",
["mak"] = "Mangkasar",
["mam"] = "Mam",
["man"] = "Mandingo",
["map-ata-pro"] = "Proto-Atayalic",
["map-bms"] = "Jawa Banyumasan",
["map-pro"] = "Proto-Austronesia",
["maq"] = "Mazatec Chiquihuitlán",
["mas"] = "Maasai",
["mat"] = "Matlatzinca",
["mau"] = "Mazatec Huautla",
["mav"] = "Sateré-Mawé",
["maw"] = "Mampruli",
["max"] = "Malayu Maluku Utara",
["maz"] = "Mazahua Tengah",
["mba"] = "Higaonon",
["mbb"] = "Manobo Bukidnon Barat",
["mbc"] = "Macushi",
["mbd"] = "Manobo Dibabawon",
["mbe"] = "Molale",
["mbf"] = "Malayu Baba",
["mbh"] = "Mangseng",
["mbi"] = "Manobo Ilianen",
["mbj"] = "Nadëb",
["mbk"] = "Malol",
["mbl"] = "Maxakalí",
["mbm"] = "Ombamba",
["mbn"] = "Macaguán",
["mbo"] = "Mbo (Kamerun)",
["mbp"] = "Wiwa",
["mbq"] = "Maisin",
["mbr"] = "Nukak Makú",
["mbs"] = "Manobo Sarangani",
["mbt"] = "Manobo Matigsalug",
["mbu"] = "Mbula-Bwazza",
["mbv"] = "Mbulungish",
["mbw"] = "Maring",
["mbx"] = "Mari Sepik",
["mby"] = "Memoni",
["mbz"] = "Mixtec Amoltepec",
["mca"] = "Maca",
["mcb"] = "Machiguenga",
["mcc"] = "Bitur",
["mcd"] = "Sharanahua",
["mce"] = "Mixtec Itundujia",
["mcf"] = "Matsés",
["mcg"] = "Mapoyo",
["mch"] = "Maquiritari",
["mci"] = "Mese",
["mcj"] = "Mvanip",
["mck"] = "Mbunda",
["mcl"] = "Macaguaje",
["mcm"] = "Kristang",
["mcn"] = "Masana",
["mco"] = "Mixe Coatlán",
["mcp"] = "Makaa",
["mcq"] = "Ese",
["mcr"] = "Menya",
["mcs"] = "Mambai",
["mcu"] = "Mambila Kamerun",
["mcv"] = "Minanibai",
["mcw"] = "Mawa",
["mcx"] = "Mpiemo",
["mcy"] = "Watut Selatan",
["mcz"] = "Mawan",
["mda"] = "Mada (Nigeria)",
["mdb"] = "Morigi",
["mdc"] = "Male",
["mdd"] = "Mbum",
["mde"] = "Bura Mabang",
["mdf"] = "Moksha",
["mdg"] = "Massalat",
["mdh"] = "Maguindanao",
["mdi"] = "Mamvu",
["mdj"] = "Mangbetu",
["mdk"] = "Mangbutu",
["mdl"] = "Isyarat Malta",
["mdm"] = "Mayogo",
["mdn"] = "Mbati",
["mdp"] = "Mbala",
["mdq"] = "Mbole",
["mdr"] = "Mandar",
["mds"] = "Maria",
["mdt"] = "Mbere",
["mdu"] = "Mboko",
["mdv"] = "Mixtec Santa Lucía Monteverde",
["mdw"] = "Mbosi",
["mdx"] = "Dizin",
["mdy"] = "Maale",
["mdz"] = "Suruí Do Pará",
["mea"] = "Menka",
["meb"] = "Ikobi-Mena",
["mec"] = "Mara",
["med"] = "Melpa",
["mee"] = "Mengen",
["mef"] = "Megam",
["meg"] = "Mea",
["meh"] = "Mixtec Tlaxiaco Barat Daya",
["mei"] = "Midob",
["mej"] = "Meyah",
["mek"] = "Mekeo",
["mel"] = "Melanau Tengah",
["mem"] = "Mangala",
["men"] = "Mende",
["meo"] = "Malayu Kedah",
["mep"] = "Miriwung",
["meq"] = "Merey",
["mer"] = "Meru",
["mes"] = "Masmaje",
["met"] = "Mato",
["meu"] = "Motu",
["mev"] = "Mano",
["mew"] = "Maaka",
["mey"] = "Hassaniya",
["mez"] = "Menominee",
["mfa"] = "Malayu Pattani",
["mfb"] = "Bangka",
["mfc"] = "Mba",
["mfd"] = "Mendankwe-Nkwen",
["mfe"] = "Kreol Mauritia",
["mff"] = "Naki",
["mfg"] = "Mixifore",
["mfh"] = "Matal",
["mfi"] = "Wandala",
["mfj"] = "Mefele",
["mfk"] = "Mofu Utara",
["mfl"] = "Putai",
["mfm"] = "Marghi Selatan",
["mfn"] = "Mbembe Sungai Cross",
["mfo"] = "Mbe",
["mfp"] = "Malayu Mangkasar",
["mfq"] = "Moba",
["mfr"] = "Marrithiyel",
["mfs"] = "Isyarat Meksiko",
["mft"] = "Mokerang",
["mfu"] = "Mbwela",
["mfv"] = "Mandjak",
["mfw"] = "Mulaha",
["mfx"] = "Melo",
["mfy"] = "Mayo",
["mfz"] = "Mabaan",
["mg"] = "Malagasy",
["mga"] = "Irlandia Tengahan",
["mgb"] = "Mararit",
["mgc"] = "Morokodo",
["mgd"] = "Moru",
["mge"] = "Mango",
["mgf"] = "Maklew",
["mgg"] = "Mpongmpong",
["mgh"] = "Makhuwa-Meetto",
["mgi"] = "Jili",
["mgj"] = "Abureni",
["mgk"] = "Mawes",
["mgl"] = "Maleu-Kilenge",
["mgm"] = "Mambae",
["mgn"] = "Mbangi",
["mgo"] = "Meta'",
["mgp"] = "Magar Timur",
["mgq"] = "Malila",
["mgr"] = "Mambwe-Lungu",
["mgs"] = "Manda (Tanzania)",
["mgt"] = "Mongol",
["mgu"] = "Mailu",
["mgv"] = "Matengo",
["mgw"] = "Matumbi",
["mgy"] = "Mbunga",
["mgz"] = "Mbugwe",
["mh"] = "Marshall",
["mha"] = "Manda (India)",
["mhb"] = "Mahongwe",
["mhc"] = "Mocho",
["mhd"] = "Mbugu",
["mhe"] = "Besisi",
["mhf"] = "Mamaa",
["mhg"] = "Margu",
["mhi"] = "Ma'di",
["mhj"] = "Mogholi",
["mhk"] = "Mungaka",
["mhl"] = "Mauwake",
["mhm"] = "Makhuwa-Moniga",
["mhn"] = "Mòcheno",
["mho"] = "Mashi",
["mhp"] = "Malayu Bali",
["mhq"] = "Mandan",
["mhr"] = "Mari Timur",
["mhs"] = "Buru (Indunisia)",
["mht"] = "Mandahuaca",
["mhu"] = "Taraon",
["mhw"] = "Mbukushu",
["mhx"] = "Lhao Vo",
["mhy"] = "Ma'anyan",
["mhz"] = "Mor (Austronesia)",
["mi"] = "Maori",
["mia"] = "Miami",
["mib"] = "Mixtec Atatláhuca",
["mic"] = "Mi'kmaq",
["mid"] = "Mandaic",
["mie"] = "Mixtec Ocotepec",
["mif"] = "Mofu-Gudur",
["mig"] = "Mixtec San Miguel el Grande",
["mih"] = "Mixtec Chayuco",
["mii"] = "Mixtec Chigmecatitlán",
["mij"] = "Mungbam",
["mik"] = "Mikasuki",
["mil"] = "Mixtec Peñoles",
["mim"] = "Mixtec Alacatlatzala",
["min"] = "Minangkabau",
["mio"] = "Mixtec Pinotepa Nacional",
["mip"] = "Mixtec Apasco-Apoala",
["miq"] = "Miskito",
["mir"] = "Mixe Isthmus",
["mit"] = "Mixtec Puebla Selatan",
["miu"] = "Mixtec Cacaloxtepec",
["miw"] = "Akoye",
["mix"] = "Mixtec Mixtepec",
["miy"] = "Mixtec Ayutla",
["miz"] = "Mixtec Coatzospan",
["mjb"] = "Makalero",
["mjc"] = "Mixtec San Juan Colorado",
["mjd"] = "Maidu Barat Laut",
["mje"] = "Muskum",
["mji"] = "Kim Mun",
["mjj"] = "Mawak",
["mjk"] = "Matukar",
["mjl"] = "Mandeali",
["mjm"] = "Medebur",
["mjn"] = "Mebu",
["mjo"] = "Malankuravan",
["mjp"] = "Malapandaram",
["mjq"] = "Malaryan",
["mjr"] = "Malavedan",
["mjs"] = "Miship",
["mjt"] = "Paharia Sawriya",
["mju"] = "Manna-Dora",
["mjv"] = "Mannan",
["mjw"] = "Karbi",
["mjx"] = "Mahali",
["mjy"] = "Mahican",
["mjz"] = "Majhi",
["mk"] = "Makedonia",
["mka"] = "Mbre",
["mkb"] = "Paharia Mal",
["mkc"] = "Siliput",
["mke"] = "Mawchi",
["mkf"] = "Miya",
["mkg"] = "Mak (Tiongkok)",
["mkh-asl-pro"] = "Proto-Aslian",
["mkh-ban-pro"] = "Proto-Bahnaric",
["mkh-kat-pro"] = "Proto-Katuic",
["mkh-khm-pro"] = "Proto-Khmuic",
["mkh-kmr-pro"] = "Proto-Khmeric",
["mkh-mmn"] = "Mon Tengahan",
["mkh-mnc-pro"] = "Proto-Monic",
["mkh-mvi"] = "Vietnam Tengahan",
["mkh-pal-pro"] = "Proto-Palaungic",
["mkh-pea-pro"] = "Proto-Pearic",
["mkh-pkn-pro"] = "Proto-Pakanic",
["mkh-pro"] = "Proto-Mon-Khmer",
["mkh-vie-pro"] = "Proto-Vietic",
["mki"] = "Dhatki",
["mkj"] = "Mokilese",
["mkk"] = "Byep",
["mkl"] = "Mokole",
["mkm"] = "Moklen",
["mkn"] = "Malayu Kupang",
["mko"] = "Mingang Doso",
["mkp"] = "Moikodi",
["mkq"] = "Miwok Bay",
["mkr"] = "Malas",
["mks"] = "Mixtec Silacayoapan",
["mkt"] = "Vamale",
["mku"] = "Maninka Konyanka",
["mkv"] = "Mafea",
["mkx"] = "Manobo Cinamiguin",
["mky"] = "Makian Timur",
["mkz"] = "Makasae",
["ml"] = "Malayalam",
["mla"] = "Tamambo",
["mlb"] = "Mbule",
["mlc"] = "Caolan",
["mle"] = "Manambu",
["mlf"] = "Mal",
["mlh"] = "Mape",
["mli"] = "Malimpung",
["mlj"] = "Miltu",
["mlk"] = "Ilwana",
["mll"] = "Malua Bay",
["mlm"] = "Mulam",
["mln"] = "Malango",
["mlo"] = "Mlomp",
["mlp"] = "Bargam",
["mlq"] = "Maninkakan Barat",
["mlr"] = "Vame",
["mls"] = "Masalit",
["mlu"] = "To'abaita",
["mlv"] = "Mwotlap",
["mlw"] = "Moloko",
["mlx"] = "Malfaxal",
["mlz"] = "Malaynon",
["mma"] = "Mama",
["mmb"] = "Momina",
["mmc"] = "Mazahua Michoacán",
["mmd"] = "Maonan",
["mme"] = "Mae",
["mmf"] = "Mundat",
["mmg"] = "Ambrym Utara",
["mmh"] = "Mehináku",
["mmi"] = "Musar",
["mmj"] = "Majhwar",
["mmk"] = "Mukha-Dora",
["mml"] = "Man Met",
["mmm"] = "Maii",
["mmn"] = "Mamanwa",
["mmo"] = "Buang Mangga",
["mmp"] = "Musan",
["mmq"] = "Aisi",
["mmr"] = "Miao Xiangxi Barat",
["mmt"] = "Malalamai",
["mmu"] = "Mmaala",
["mmv"] = "Miriti",
["mmw"] = "Emae",
["mmx"] = "Madak",
["mmy"] = "Migaama",
["mmz"] = "Mabaale",
["mn"] = "Mongolia",
["mna"] = "Mbula",
["mnb"] = "Muna",
["mnc"] = "Manchu",
["mnd"] = "Mondé",
["mne"] = "Naba",
["mnf"] = "Mundani",
["mng"] = "Mnong Timur",
["mnh"] = "Mono (Kongo)",
["mni"] = "Manipur",
["mnj"] = "Munji",
["mnk"] = "Mandinka",
["mnl"] = "Tiale",
["mnm"] = "Mapena",
["mnn"] = "Mnong Selatan",
["mnp"] = "Min Bei",
["mnq"] = "Minriq",
["mnr"] = "Mono (California)",
["mns"] = "Mansi",
["mnt"] = "Maykulan",
["mnu"] = "Mer",
["mnv"] = "Rennellese",
["mnw"] = "Mon",
["mnw-tha"] = "Mon Thai",
["mnx"] = "Manikion",
["mny"] = "Manyawa",
["mnz"] = "Moni",
["moa"] = "Mwan",
["moc"] = "Mocoví",
["mod"] = "Mobilian",
["moe"] = "Montagnais",
["mog"] = "Mongondow",
["moh"] = "Mohawk",
["moi"] = "Mboi",
["moj"] = "Monzombo",
["mok"] = "Morori",
["mom"] = "Monimbo",
["moo"] = "Monom",
["mop"] = "Maya Mopan",
["moq"] = "Mor (Papua)",
["mor"] = "Moro",
["mos"] = "Moore",
["mot"] = "Barí",
["mou"] = "Mogum",
["mov"] = "Mojave",
["mow"] = "Moi (Kongo)",
["mox"] = "Molima",
["moy"] = "Shekkacho",
["moz"] = "Mukulu",
["mpa"] = "Mpoto",
["mpb"] = "Mullukmulluk",
["mpc"] = "Mangarayi",
["mpd"] = "Machinere",
["mpe"] = "Majang",
["mpg"] = "Marba",
["mph"] = "Maung",
["mpi"] = "Mpade",
["mpj"] = "Martu Wangka",
["mpk"] = "Mbara (Chad)",
["mpl"] = "Watut Tengahan",
["mpm"] = "Mixtec Yosondúa",
["mpn"] = "Mindiri",
["mpo"] = "Miu",
["mpp"] = "Migabac",
["mpq"] = "Matís",
["mpr"] = "Vangunu",
["mps"] = "Dadibi",
["mpt"] = "Mian",
["mpu"] = "Makuráp",
["mpv"] = "Mungkip",
["mpw"] = "Mapidian",
["mpx"] = "Misima-Paneati",
["mpy"] = "Mapia",
["mpz"] = "Mpi",
["mqa"] = "Maba",
["mqb"] = "Mbuko",
["mqc"] = "Mangole",
["mqe"] = "Matepi",
["mqf"] = "Momuna",
["mqg"] = "Kutai Hulu",
["mqh"] = "Mixtec Tlazoyaltepec",
["mqi"] = "Mariri",
["mqj"] = "Mamasa",
["mqk"] = "Manobo Rajah Kabunsuwan",
["mql"] = "Mbelime",
["mqm"] = "Marquesan Selatan",
["mqn"] = "Moronene",
["mqo"] = "Modole",
["mqp"] = "Manipa",
["mqq"] = "Minokok",
["mqr"] = "Mander",
["mqs"] = "Makian Barat",
["mqt"] = "Mok",
["mqu"] = "Mandari",
["mqv"] = "Mosimo",
["mqw"] = "Murupi",
["mqx"] = "Mamuju",
["mqy"] = "Manggarai",
["mqz"] = "Malasanga",
["mr"] = "Marathi",
["mra"] = "Mlabri",
["mrb"] = "Marino",
["mrc"] = "Maricopa",
["mrd"] = "Magar Barat",
["mre"] = "Isyarat Martha's Vineyard",
["mrf"] = "Elseng",
["mrg"] = "Mising",
["mrh"] = "Chin Mara",
["mrj"] = "Mari Barat",
["mrk"] = "Hmwaveke",
["mrl"] = "Mortlockese",
["mrm"] = "Merlav",
["mrn"] = "Cheke Holo",
["mro"] = "Mru",
["mrp"] = "Morouas",
["mrq"] = "Marquesan Utara",
["mrr"] = "Maria Hill",
["mrs"] = "Maragus",
["mrt"] = "Margi",
["mru"] = "Mono (Kamerun)",
["mrv"] = "Mangarevan",
["mrw"] = "Maranao",
["mrx"] = "Dineor",
["mry"] = "Karaga Mandaya",
["mrz"] = "Marind",
["ms"] = "Malayu",
["msb"] = "Masbatenyo",
["msc"] = "Maninka Sankaran",
["msd"] = "Isyarat Maya Yucatec",
["mse"] = "Musey",
["msf"] = "Mekwei",
["msg"] = "Moraid",
["msi"] = "Malayu Sabah",
["msj"] = "Ma",
["msk"] = "Mansaka",
["msl"] = "Molof",
["msm"] = "Manobo Agusan",
["msn"] = "Vurës",
["mso"] = "Mombum",
["msp"] = "Maritsauá",
["msq"] = "Caac",
["msr"] = "Isyarat Mongolia",
["mss"] = "Masela Barat",
["msu"] = "Musom",
["msv"] = "Maslam",
["msw"] = "Mansoanka",
["msx"] = "Moresada",
["msy"] = "Aruamu",
["msz"] = "Momare",
["mt"] = "Malta",
["mta"] = "Manobo Cotabato",
["mtb"] = "Anyin Morofo",
["mtc"] = "Munit",
["mtd"] = "Mualang",
["mte"] = "Alu",
["mtf"] = "Murik (Papua)",
["mtg"] = "Una",
["mth"] = "Munggui",
["mti"] = "Maiwa (Papua)",
["mtj"] = "Moskona",
["mtk"] = "Mbe'",
["mtl"] = "Montol",
["mtm"] = "Mator",
["mtn"] = "Matagalpa",
["mto"] = "Mixe Totontepec",
["mtp"] = "Wichí Lhamtés Nocten",
["mtq"] = "Muong",
["mtr"] = "Mewari",
["mts"] = "Yora",
["mtt"] = "Mota",
["mtu"] = "Mixtec Tututepec",
["mtv"] = "Asaro'o",
["mtw"] = "Magahat",
["mtx"] = "Mixtec Tidaá",
["mty"] = "Nabi",
["mua"] = "Mundang",
["mub"] = "Mubi",
["muc"] = "Mbu'",
["mud"] = "Aleut Mednyj",
["mue"] = "Media Lengua",
["mug"] = "Musgu",
["muh"] = "Mündü",
["mui"] = "Musi",
["mui-plm"] = "Palembang", -- hanya dipakai di Wikikamus
["muj"] = "Mabire",
["mum"] = "Maiwala",
["mun-pro"] = "Proto-Munda",
["muo"] = "Nyong",
["mup"] = "Malvi",
["muq"] = "Miao Xiangxi Timur",
["mur"] = "Murle",
["mus"] = "Creek",
["mut"] = "Muria Barat",
["muu"] = "Yaaku",
["muv"] = "Muthuvan",
["mux"] = "Bo-Ung",
["muy"] = "Muyang",
["muz"] = "Mursi",
["mva"] = "Manam",
["mvb"] = "Mattole",
["mvd"] = "Mamboru",
["mvg"] = "Mixtec Yucuañe",
["mvh"] = "Mire",
["mvi"] = "Miyako",
["mvk"] = "Mekmek",
["mvl"] = "Mbara (Australia)",
["mvm"] = "Muya",
["mvn"] = "Minaveha",
["mvo"] = "Marovo",
["mvp"] = "Duri",
["mvq"] = "Moere",
["mvr"] = "Marau",
["mvs"] = "Massep",
["mvt"] = "Mpotovoro",
["mvu"] = "Marfa",
["mvv"] = "Murut Tagal",
["mvw"] = "Machinga",
["mvx"] = "Meoswar",
["mvy"] = "Indus Kohistani",
["mvz"] = "Mesqan",
["mwa"] = "Mwatebu",
["mwb"] = "Juwal",
["mwc"] = "Are",
["mwe"] = "Mwera",
["mwf"] = "Murrinh-Patha",
["mwg"] = "Aiklep",
["mwh"] = "Mouk-Aria",
["mwi"] = "Labo",
["mwk"] = "Maninkakan Kita",
["mwl"] = "Mirandese",
["mwm"] = "Sar",
["mwn"] = "Nyamwanga",
["mwo"] = "Maewo Tengah",
["mwp"] = "Kala Lagaw Ya",
["mwq"] = "Chin Mün",
["mwr"] = "Marwari",
["mws"] = "Mwimbi-Muthambi",
["mwt"] = "Moken",
["mwu"] = "Mittu",
["mwv"] = "Mentawai",
["mww"] = "Hmong Putih",
["mwz"] = "Moingi",
["mxa"] = "Mixtec Oaxaca Barat Laut",
["mxb"] = "Mixtec Tezoatlán",
["mxd"] = "Modang",
["mxe"] = "Mele-Fila",
["mxf"] = "Malgbe",
["mxg"] = "Mbangala",
["mxh"] = "Mvuba",
["mxi"] = "Mozarabic",
["mxj"] = "Miju",
["mxk"] = "Monumbo",
["mxl"] = "Gbe Maxi",
["mxm"] = "Meramera",
["mxn"] = "Moi (Indunisia)",
["mxo"] = "Mbowe",
["mxp"] = "Mixe Tlahuitoltepec",
["mxq"] = "Mixe Juquila",
["mxr"] = "Murik (Malaysia)",
["mxs"] = "Mixtec Huitepec",
["mxt"] = "Mixtec Jamiltepec",
["mxu"] = "Mada (Kamerun)",
["mxv"] = "Mixtec Metlatónoc",
["mxw"] = "Namo",
["mxx"] = "Mahou",
["mxy"] = "Mixtec Nochixtlán Tenggara",
["mxz"] = "Masela Tengah",
["my"] = "Burma",
["myb"] = "Mbay",
["myc"] = "Mayeka",
["mye"] = "Myene",
["myf"] = "Bambassi",
["myg"] = "Manta",
["myh"] = "Makah",
["myj"] = "Mangayat",
["myk"] = "Senoufo Mamara",
["myl"] = "Moma",
["mym"] = "Me'en",
["myn-chl"] = "Ch'olti'",
["myn-pro"] = "Proto-Maya",
["myo"] = "Anfillo",
["myp"] = "Pirahã",
["myr"] = "Muniche",
["mys"] = "Mesmes",
["myu"] = "Mundurukú",
["myv"] = "Erzya",
["myw"] = "Muyuw",
["myx"] = "Masaba",
["myy"] = "Macuna",
["myz"] = "Mandaic Klasik",
["mza"] = "Mixtec Santa María Zacatepec",
["mzb"] = "Berber Sahara Utara",
["mzc"] = "Isyarat Madagaskar",
["mzd"] = "Malimba",
["mze"] = "Morawa",
["mzg"] = "Isyarat Monastic",
["mzh"] = "Wichí Lhamtés Güisnay",
["mzi"] = "Mazatec Ixcatlán",
["mzj"] = "Manya",
["mzk"] = "Mambila Nigeria",
["mzl"] = "Mixe Mazatlán",
["mzm"] = "Mumuye",
["mzn"] = "Mazanderani",
["mzo"] = "Matipuhy",
["mzp"] = "Movima",
["mzq"] = "Mori Atas",
["mzr"] = "Marúbo",
["mzs"] = "Makau",
["mzt"] = "Mintil",
["mzu"] = "Inapang",
["mzv"] = "Manza",
["mzw"] = "Deg",
["mzx"] = "Mawayana",
["mzy"] = "Isyarat Mozambik",
["mzz"] = "Maiadomu",
["na"] = "Nauru",
["naa"] = "Namla",
["nab"] = "Nambikwara",
["nac"] = "Narak",
["nae"] = "Naka'ela",
["naf"] = "Nabak",
["nag"] = "Naga Pijin",
["nah"] = "Nahuatl",
["nai-ala"] = "Alazapa",
["nai-bay"] = "Bayogoula",
["nai-bvy"] = "Yokuts Buena Vista",
["nai-cal"] = "Calusa",
["nai-chi"] = "Chiquimulilla",
["nai-chu-pro"] = "Proto-Chumash",
["nai-cig"] = "Ciguayo",
["nai-ckn-pro"] = "Proto-Chinookan",
["nai-dly"] = "Yokuts Delta",
["nai-gsy"] = "Gashowu",
["nai-guz"] = "Guazacapán",
["nai-hit"] = "Hitchiti",
["nai-ipa"] = "Ipai",
["nai-jtp"] = "Jutiapa",
["nai-jum"] = "Jumaytepeque",
["nai-kat"] = "Kathlamet",
["nai-klp-pro"] = "Proto-Kalapuyan",
["nai-knm"] = "Konomihu",
["nai-kry"] = "Yokuts Sungai Kings",
["nai-kum"] = "Kumeyaay",
["nai-mac"] = "Macoris",
["nai-mdu-pro"] = "Proto-Maidun",
["nai-miz-pro"] = "Proto-Mixe-Zoque",
["nai-mus-pro"] = "Proto-Muskogean",
["nai-nao"] = "Naolan",
["nai-nrs"] = "Shasta New River",
["nai-nvy"] = "Yokuts Lembah Utara",
["nai-okw"] = "Okwanuchu",
["nai-per"] = "Pericú",
["nai-pic"] = "Picuris",
["nai-plp-pro"] = "Proto-Plateau Penutian",
["nai-ply"] = "Palewyami",
["nai-pom-pro"] = "Proto-Pomo",
["nai-qng"] = "Quinigua",
["nai-sca-pro"] = "Proto-Siouan-Catawban",
["nai-sin"] = "Sinacantán",
["nai-sln"] = "Lenca El Salvador",
["nai-spt"] = "Sahaptin",
["nai-svy"] = "Yokuts Lembah Selatan",
["nai-tap"] = "Tapachultec",
["nai-taw"] = "Tawasa",
["nai-teq"] = "Tequistlatec",
["nai-tip"] = "Tipai",
["nai-tky"] = "Yokuts Tule-Kaweah",
["nai-tot-pro"] = "Proto-Totozoquean",
["nai-tsi-pro"] = "Proto-Tsimshianic",
["nai-utn-pro"] = "Proto-Utian",
["nai-wai"] = "Waikuri",
["nai-yup"] = "Yupiltepeque",
["naj"] = "Nalu",
["nak"] = "Nakanai",
["nal"] = "Nalik",
["nam"] = "Ngan'gityemerri",
["nan"] = "Min Nan",
["nan-hbl"] = "Hokkien", -- hanya dipakai di Wikikamus
["nan-tws"] = "Tiociu", -- hanya dipakai di Wikikamus
["nao"] = "Naaba",
["nap"] = "Neapolitan",
["naq"] = "Khoekhoe",
["nar"] = "Iguta",
["nas"] = "Nasioi",
["nat"] = "Hungworo",
["naw"] = "Nawuri",
["nax"] = "Nakwi",
["nay"] = "Ngarrindjeri",
["naz"] = "Nahuatl Coatepec",
["nb"] = "Norwegia Bokmål",
["nba"] = "Nyemba",
["nbb"] = "Ndoe",
["nbc"] = "Chang",
["nbd"] = "Ngbinda",
["nbe"] = "Naga Konyak",
["nbg"] = "Nagarchal",
["nbh"] = "Ngamo",
["nbi"] = "Naga Mao",
["nbj"] = "Ngarinman",
["nbk"] = "Nake",
["nbm"] = "Ngbaka Ma'bo",
["nbn"] = "Kuri",
["nbo"] = "Nkukoli",
["nbp"] = "Nnam",
["nbq"] = "Nggem",
["nbr"] = "Numana",
["nbs"] = "Isyarat Namibia",
["nbt"] = "Na",
["nbu"] = "Naga Rongmei",
["nbv"] = "Ngamambo",
["nbw"] = "Ngbandi Selatan",
["nby"] = "Ningera",
["nca"] = "Iyo",
["ncb"] = "Nikobar Tengah",
["ncc"] = "Ponam",
["ncd"] = "Nachering",
["nce"] = "Yale",
["ncf"] = "Notsi",
["ncg"] = "Nisga'a",
["nch"] = "Nahuatl Huasteca Tengah",
["nci"] = "Nahuatl Klasik",
["ncj"] = "Nahuatl Puebla Utara",
["nck"] = "Nakara",
["ncl"] = "Nahuatl Michoacán",
["ncm"] = "Nambo",
["ncn"] = "Nauna",
["nco"] = "Sibe",
["ncr"] = "Ncane",
["ncs"] = "Isyarat Nikaragua",
["nct"] = "Naga Chothe",
["ncu"] = "Chumburung",
["ncx"] = "Nahuatl Puebla Tengah",
["ncz"] = "Natchez",
["nd"] = "Ndebele Utara",
["nda"] = "Ndasa",
["ndb"] = "Kenswei Nsei",
["ndc"] = "Ndau",
["ndd"] = "Nde-Nsele-Nta",
["ndf"] = "Nadruvian",
["ndg"] = "Ndengereko",
["ndh"] = "Ndali",
["ndi"] = "Chamba Leko",
["ndj"] = "Ndamba",
["ndk"] = "Ndaka",
["ndl"] = "Ndolo",
["ndm"] = "Ndam",
["ndn"] = "Ngundi",
["ndp"] = "Ndo",
["ndq"] = "Ndombe",
["ndr"] = "Ndoola",
["nds"] = "Jirman Hilir",
["nds-de"] = "Jirman Hilir Jirman",
["nds-nl"] = "Saxon Hilir Walanda",
["ndt"] = "Ndunga",
["ndu"] = "Dugun",
["ndv"] = "Ndut",
["ndw"] = "Ndobo",
["ndx"] = "Nduga",
["ndy"] = "Lutos",
["ndz"] = "Ndogo",
["ne"] = "Nepal",
["nea"] = "Ngad'a Timur",
["neb"] = "Toura",
["nec"] = "Nedebang",
["ned"] = "Nde-Gbite",
["nee"] = "Kumak",
["nef"] = "Nefamese",
["neg"] = "Negidal",
["neh"] = "Nyenkha",
["nej"] = "Neko",
["nek"] = "Neku",
["nem"] = "Nemi",
["nen"] = "Nengone",
["neo"] = "Ná-Meo",
["neq"] = "Mixe Tengah Utara",
["ner"] = "Yahadian",
["nes"] = "Kinnauri Bhoti",
["net"] = "Nete",
["neu"] = "Neo",
["nev"] = "Nyaheun",
["new"] = "Newar",
["nex"] = "Neme",
["ney"] = "Neyo",
["nez"] = "Nez Perce",
["nfa"] = "Dhao",
["nfd"] = "Ahwai",
["nfl"] = "Aiwoo",
["nfr"] = "Nafaanra",
["nfu"] = "Mfumte",
["ng"] = "Ndonga",
["nga"] = "Ngbaka",
["ngb"] = "Ngbandi Utara",
["ngc"] = "Ngombe (Kongo)",
["ngd"] = "Ngando (Republik Afrika Tengah)",
["nge"] = "Ngemba",
["ngf-pro"] = "Proto-Trans-Papua",
["ngg"] = "Ngbaka Manza",
["ngh"] = "Nǀuu",
["ngi"] = "Ngizim",
["ngj"] = "Ngie",
["ngk"] = "Ngalkbun",
["ngl"] = "Lomwe",
["ngm"] = "Kreol Ngatik Men's",
["ngn"] = "Ngwo",
["ngo"] = "Ngoni",
["ngp"] = "Ngulu",
["ngq"] = "Ngoreme",
["ngr"] = "Nagu",
["ngs"] = "Gvoko",
["ngt"] = "Ngeq",
["ngu"] = "Nahuatl Guerrero",
["ngv"] = "Nagumi",
["ngw"] = "Ngwaba",
["ngx"] = "Nggwahyi",
["ngy"] = "Tibea",
["ngz"] = "Ngungwel",
["nha"] = "Nhanda",
["nhb"] = "Beng",
["nhc"] = "Nahuatl Tabasco",
["nhd"] = "Chiripá",
["nhe"] = "Nahuatl Huasteca Timur",
["nhf"] = "Nhuwala",
["nhg"] = "Nahuatl Tetelcingo",
["nhh"] = "Nahari",
["nhi"] = "Nahuatl Zacatlán-Ahuacatlán-Tepetzintla",
["nhk"] = "Nahuatl Cosoleacaque",
["nhm"] = "Nahuatl Morelos",
["nhn"] = "Nahuatl Tengah",
["nho"] = "Takuu",
["nhp"] = "Nahuatl Pajapan",
["nhq"] = "Nahuatl Huaxcaleca",
["nhr"] = "Naro",
["nht"] = "Nahuatl Ometepec",
["nhu"] = "Noone",
["nhv"] = "Nahuatl Temascaltepec",
["nhw"] = "Nahuatl Huasteca Barat",
["nhx"] = "Nahuatl Mecayapan",
["nhy"] = "Nahuatl Oaxaca Utara",
["nhz"] = "Nahuatl Santa María La Alta",
["nia"] = "Nias",
["nib"] = "Nakame",
["nic-bco-pro"] = "Proto-Benue-Kongo",
["nic-bod-pro"] = "Proto-Bantoid",
["nic-eov-pro"] = "Proto-Oti-Volta Timur",
["nic-gns-pro"] = "Proto-Gurunsi",
["nic-grf-pro"] = "Proto-Grassfields",
["nic-gur-pro"] = "Proto-Gur",
["nic-jkn-pro"] = "Proto-Jukunoid",
["nic-lcr-pro"] = "Proto-Hilir Sungai Cross",
["nic-ogo-pro"] = "Proto-Ogoni",
["nic-ovo-pro"] = "Proto-Oti-Volta",
["nic-plt-pro"] = "Proto-Plateau",
["nic-pro"] = "Proto-Niger-Kongo",
["nic-ubg-pro"] = "Proto-Ubangian",
["nic-ucr-pro"] = "Proto-Hulu Sungai Cross",
["nic-vco-pro"] = "Proto-Volta-Kongo",
["nid"] = "Ngandi",
["nie"] = "Niellim",
["nif"] = "Nek",
["nig"] = "Ngalakan",
["nih"] = "Nyiha",
["nii"] = "Nii",
["nij"] = "Ngaju",
["nik"] = "Nikobar Selatan",
["nil"] = "Nila",
["nim"] = "Nilamba",
["nin"] = "Ninzo",
["nio"] = "Nganasan",
["niq"] = "Nandi",
["nir"] = "Nimboran",
["nis"] = "Nimi",
["nit"] = "Kolami Tenggara",
["niu"] = "Niuean",
["niv"] = "Nivkh",
["niw"] = "Nimo",
["nix"] = "Hema",
["niy"] = "Ngiti",
["niz"] = "Ningil",
["nja"] = "Nzanyi",
["njb"] = "Naga Nocte",
["njh"] = "Naga Lotha",
["nji"] = "Gudanji",
["njj"] = "Njen",
["njl"] = "Njalgulgule",
["njm"] = "Angami",
["njn"] = "Naga Liangmai",
["njo"] = "Ao",
["njr"] = "Njerep",
["njs"] = "Nisa",
["njt"] = "Pijin Ndyuka-Trio",
["nju"] = "Ngadjunmaya",
["njx"] = "Kunyi",
["njy"] = "Njyem",
["njz"] = "Nyishi",
["nka"] = "Nkoya",
["nkb"] = "Naga Khoibu",
["nkc"] = "Nkongho",
["nkd"] = "Koireng",
["nke"] = "Duke",
["nkf"] = "Naga Inpui",
["nkg"] = "Nekgini",
["nkh"] = "Naga Khezha",
["nki"] = "Naga Thangal",
["nkj"] = "Nakai",
["nkk"] = "Nokuku",
["nkm"] = "Namat",
["nkn"] = "Nkangala",
["nko"] = "Nkonya",
["nkp"] = "Niuatoputapu",
["nkq"] = "Nkami",
["nkr"] = "Nukuoro",
["nks"] = "Asmat Utara",
["nkt"] = "Nyika",
["nku"] = "Kulango Bouna",
["nkw"] = "Nkutu",
["nkx"] = "Nkoroo",
["nkz"] = "Nkari",
["nl"] = "Walanda",
["nla"] = "Ngombale",
["nlc"] = "Nalca",
["nle"] = "Nyala Timur",
["nlg"] = "Gela",
["nli"] = "Grangali",
["nlj"] = "Nyali",
["nlk"] = "Yali Ninia",
["nll"] = "Nihali",
["nlm"] = "Mankiyali",
["nlo"] = "Ngul",
["nlq"] = "Naga Lao",
["nlu"] = "Nchumbulu",
["nlv"] = "Nahuatl Orizaba",
["nlw"] = "Walangama",
["nlx"] = "Nahali",
["nly"] = "Nyamal",
["nlz"] = "Nalögo",
["nma"] = "Naga Maram",
["nmb"] = "Big Nambas",
["nmc"] = "Ngam",
["nmd"] = "Ndumu",
["nme"] = "Naga Mzieme",
["nmf"] = "Naga Tangkhul",
["nmg"] = "Kwasio",
["nmh"] = "Naga Monsang",
["nmi"] = "Nyam",
["nmj"] = "Ngombe (Republik Afrika Tengah)",
["nmk"] = "Namakura",
["nml"] = "Ndemli",
["nmm"] = "Manangba",
["nmn"] = "ǃXóõ",
["nmo"] = "Naga Moyon",
["nmp"] = "Nimanbur",
["nmq"] = "Nambya",
["nmr"] = "Nimbari",
["nms"] = "Letemboi",
["nmt"] = "Namonuito",
["nmu"] = "Maidu Timur Laut",
["nmv"] = "Ngamini",
["nmw"] = "Nimoa",
["nmy"] = "Namuyi",
["nmz"] = "Nawdm",
["nn"] = "Norwegia Nynorsk",
["nna"] = "Nyangumarta",
["nnb"] = "Nande",
["nnc"] = "Nancere",
["nnd"] = "Ambae Barat",
["nne"] = "Ngandyera",
["nnf"] = "Ngaing",
["nng"] = "Naga Maring",
["nnh"] = "Ngiemboon",
["nni"] = "Nuaulu Utara",
["nnj"] = "Nyangatom",
["nnk"] = "Nankina",
["nnl"] = "Naga Rengma Utara",
["nnm"] = "Namia",
["nnn"] = "Ngete",
["nnp"] = "Wancho",
["nnq"] = "Ngindo",
["nnr"] = "Narungga",
["nnt"] = "Nanticoke",
["nnu"] = "Dwang",
["nnv"] = "Nukunu",
["nnw"] = "Nuni Selatan",
["nnx"] = "Ngong",
["nny"] = "Nyangga",
["nnz"] = "Nda'nda'",
["no"] = "Norwegia",
["noa"] = "Woun Meu",
["noc"] = "Nuk",
["nod"] = "Thai Utara",
["noe"] = "Nimadi",
["nof"] = "Nomane",
["nog"] = "Nogai",
["noh"] = "Nomu",
["noi"] = "Noiri",
["noj"] = "Nonuya",
["nok"] = "Nooksack",
["nol"] = "Nomlaki",
["nom"] = "Nocamán",
["non"] = "Norse Kuna",
["nop"] = "Numanggang",
["noq"] = "Ngongo",
["nos"] = "Nisu Timur",
["not"] = "Nomatsiguenga",
["nou"] = "Ewage-Notu",
["nov"] = "Novial",
["now"] = "Nyambo",
["noy"] = "Noy",
["noz"] = "Nayi",
["npa"] = "Phu Nar",
["npb"] = "Nupbikha",
["npg"] = "Ponyo",
["nph"] = "Phom",
["npl"] = "Nahuatl Puebla Tenggara",
["npn"] = "Mondropolon",
["npo"] = "Naga Pochuri",
["nps"] = "Nipsan",
["npu"] = "Naga Puimei",
["npy"] = "Napu",
["nqg"] = "Ede Nago",
["nqk"] = "Kura Ede Nago",
["nql"] = "Ngendelengo",
["nqm"] = "Ndom",
["nqn"] = "Nen",
["nqo"] = "N'Ko",
["nqq"] = "Naga Kyan-Karyaw",
["nqy"] = "Akyaung Ari",
["nr"] = "Ndebele Selatan",
["nra"] = "Ngom",
["nrb"] = "Nara",
["nrc"] = "Noric",
["nre"] = "Naga Rengma Selatan",
["nrf"] = "Norman",
["nrg"] = "Narango",
["nri"] = "Naga Chokri",
["nrk"] = "Ngarla",
["nrl"] = "Ngarluma",
["nrm"] = "Narom",
["nrn"] = "Norn",
["nrp"] = "Picene Utara",
["nrr"] = "Norra",
["nrt"] = "Kalapuya Utara",
["nru"] = "Narua",
["nrx"] = "Ngurmbur",
["nrz"] = "Lala (Papua)",
["nsa"] = "Naga Sangtam",
["nsb"] = "Nossob Hilir",
["nsc"] = "Nshi",
["nsd"] = "Nisu Selatan",
["nse"] = "Nsenga",
["nsg"] = "Ngasa",
["nsh"] = "Ngoshie",
["nsi"] = "Isyarat Nigeria",
["nsk"] = "Naskapi",
["nsl"] = "Isyarat Norwegia",
["nsm"] = "Sema",
["nsn"] = "Nehan",
["nso"] = "Sotho Utara",
["nsp"] = "Isyarat Nepal",
["nsq"] = "Miwok Sierra Utara",
["nsr"] = "Isyarat Maritim",
["nss"] = "Nali",
["nst"] = "Tangsa",
["nsu"] = "Nahuatl Sierra Negra",
["nsv"] = "Nisu Barat Daya",
["nsw"] = "Navut",
["nsx"] = "Nsongo",
["nsy"] = "Nasal",
["nsz"] = "Nisenan",
["ntd"] = "Tidong Utara",
["nte"] = "Nathembo",
["ntg"] = "Ngantangarra",
["nti"] = "Natioro",
["ntj"] = "Ngaanyatjarra",
["ntk"] = "Ikoma",
["ntm"] = "Nateni",
["nto"] = "Ntomba",
["ntp"] = "Tepehuan Utara",
["ntr"] = "Delo",
["nts"] = "Natagaimas",
["ntu"] = "Natügu",
["ntw"] = "Nottoway",
["ntx"] = "Somra",
["nty"] = "Mantsi",
["nua"] = "Yuaga",
["nub-har"] = "Haraza",
["nub-pro"] = "Proto-Nubian",
["nuc"] = "Nukuini",
["nud"] = "Ngala",
["nue"] = "Ngundu",
["nuf"] = "Nusu",
["nug"] = "Nungali",
["nuh"] = "Ndunda",
["nui"] = "Ngumbi",
["nuj"] = "Nyole (Uganda)",
["nuk"] = "Nootka",
["nul"] = "Nusa Laut",
["num"] = "Niuafo'ou",
["nun"] = "Anong",
["nuo"] = "Nguôn",
["nup"] = "Nupe",
["nuq"] = "Nukumanu",
["nur"] = "Nuguria",
["nus"] = "Nuer",
["nut"] = "Nung",
["nuu"] = "Ngbundu",
["nuv"] = "Nuni Utara",
["nuw"] = "Nguluwan",
["nux"] = "Mehek",
["nuy"] = "Nunggubuyu",
["nuz"] = "Nahuatl Tlamacazapa",
["nv"] = "Navajo",
["nvh"] = "Nasarian",
["nvm"] = "Namiae",
["nvo"] = "Nyokon",
["nwa"] = "Nawathinehena",
["nwb"] = "Nyabwa",
["nwc"] = "Newar Klasik",
["nwe"] = "Ngwe",
["nwi"] = "Tanna Barat Daya",
["nwm"] = "Nyamusa-Molo",
["nwo"] = "Nauo",
["nwr"] = "Nawaru",
["nwx"] = "Newar Tengahan",
["nwy"] = "Nottoway-Meherrin",
["nxa"] = "Nauete",
["nxd"] = "Ngando (Kongo)",
["nxe"] = "Nage",
["nxg"] = "Ngadha",
["nxi"] = "Nindi",
["nxl"] = "Nuaulu Selatan",
["nxm"] = "Numidia",
["nxn"] = "Ngawun",
["nxo"] = "Ndambomo",
["nxq"] = "Naxi",
["nxr"] = "Ninggerum",
["nxu"] = "Narau",
["nxx"] = "Nafri",
["ny"] = "Chichewa",
["nyb"] = "Nyangbo",
["nyc"] = "Nyanga-li",
["nyd"] = "Nyole (Kenya)",
["nye"] = "Nyengo",
["nyf"] = "Giryama",
["nyg"] = "Nyindu",
["nyh"] = "Nyigina",
["nyi"] = "Nyimang",
["nyj"] = "Nyanga (Kongo)",
["nyk"] = "Nyaneka",
["nyl"] = "Nyeu",
["nym"] = "Nyamwezi",
["nyn"] = "Nyankole",
["nyo"] = "Nyoro",
["nyp"] = "Nyang'i",
["nys"] = "Nyunga",
["nyt"] = "Nyawaygi",
["nyu"] = "Nyungwe",
["nyv"] = "Nyulnyul",
["nyw"] = "Nyaw",
["nyx"] = "Nganyaywana",
["nyy"] = "Nyakyusa",
["nza"] = "Mbembe Tigon",
["nzb"] = "Njebi",
["nzd"] = "Nzadi",
["nzi"] = "Nzima",
["nzk"] = "Nzakara",
["nzm"] = "Naga Zeme",
["nzs"] = "Isyarat Selandia Baru",
["nzu"] = "Teke Tengah",
["nzy"] = "Nzakambay",
["nzz"] = "Dogon Nanga Dama",
["oaa"] = "Orok",
["oac"] = "Oroch",
["oav"] = "Avar Kuna",
["obi"] = "Obispeño",
["obk"] = "Bontoc Selatan",
["obl"] = "Oblo",
["obm"] = "Moabite",
["obo"] = "Manobo Obo",
["obr"] = "Burma Kuna",
["obt"] = "Breton Kuna",
["obu"] = "Obulom",
["oc"] = "Occitan",
["oca"] = "Ocaina",
["och"] = "Tionghoa Kuna",
["oco"] = "Cornish Kuna",
["ocu"] = "Tlahuica",
["oda"] = "Odut",
["odk"] = "Od",
["odt"] = "Walanda Kuna",
["odu"] = "Odual",
["ofo"] = "Ofo",
["ofs"] = "Frisia Kuna",
["ofu"] = "Efutop",
["ogb"] = "Ogbia",
["ogc"] = "Ogbah",
["oge"] = "Georgia Kuna",
["ogg"] = "Ogbogolo",
["ogo"] = "Khana",
["ogu"] = "Ogbronuagum",
["ohu"] = "Hungaria Kuna",
["oia"] = "Oirata",
["oin"] = "One Inebu",
["oj"] = "Ojibwe",
["ojb"] = "Ojibwa Barat Laut",
["ojc"] = "Ojibwa Tengah",
["ojg"] = "Ojibwa Timur",
["ojp"] = "Japang Kuna",
["ojs"] = "Ojibwa Severn",
["ojv"] = "Jawa Ontong",
["ojw"] = "Ojibwa Barat",
["oka"] = "Okanagan",
["okb"] = "Okobo",
["okd"] = "Okodia",
["oke"] = "Okpe (Edo Barat Daya)",
["okg"] = "Kok-Paponk",
["okh"] = "Koresh-e Rostam",
["oki"] = "Okiek",
["okj"] = "Oko-Juwoi",
["okk"] = "One Kwamtim",
["okl"] = "Isyarat Kent Kuna",
["okm"] = "Korea Tengahan",
["okn"] = "Oki-No-Erabu",
["oko"] = "Korea Kuna",
["okr"] = "Kirike",
["oks"] = "Oko-Eni-Osayen",
["oku"] = "Oku",
["okv"] = "Orokaiva",
["okx"] = "Okpe (Edo Barat Laut)",
["okz"] = "Khmer Kuna",
["old"] = "Mochi",
["ole"] = "Olekha",
["olm"] = "Oloma",
["olo"] = "Livvi",
["olr"] = "Olrat",
["olt"] = "Lithuania Kuna",
["olu"] = "Kuvale",
["om"] = "Oromo",
["oma"] = "Omaha-Ponca",
["omb"] = "Omba",
["omc"] = "Mochica",
["omg"] = "Omagua",
["omi"] = "Omi",
["omk"] = "Omok",
["oml"] = "Ombo",
["omn"] = "Minoan",
["omo"] = "Utarmbung",
["omp"] = "Manipur Kuna",
["omq-cha-pro"] = "Proto-Chatino",
["omq-maz-pro"] = "Proto-Mazatec",
["omq-mix-pro"] = "Proto-Mixtecan",
["omq-mxt-pro"] = "Proto-Mixtec",
["omq-otp-pro"] = "Proto-Oto-Pamean",
["omq-pro"] = "Proto-Oto-Manguean",
["omq-tel"] = "Mixtec Teposcolula",
["omq-teo"] = "Chatino Teojomulco",
["omq-tri-pro"] = "Proto-Trique",
["omq-zap-pro"] = "Proto-Zapotecan",
["omq-zpc-pro"] = "Proto-Zapotec",
["omr"] = "Marathi Kuna",
["omt"] = "Omotik",
["omu"] = "Omurano",
["omv-aro-pro"] = "Proto-Aroid",
["omv-diz-pro"] = "Proto-Dizoid",
["omv-pro"] = "Proto-Omotic",
["omw"] = "Tairora Selatan",
["omx"] = "Mon Kuna",
["ona"] = "Selk'nam",
["onb"] = "Lingao",
["one"] = "Oneida",
["ong"] = "Olo",
["oni"] = "Onin",
["onj"] = "Onjob",
["onk"] = "One Kabore",
["onn"] = "Onobasulu",
["ono"] = "Onondaga",
["onp"] = "Sartang",
["onr"] = "One Utara",
["ons"] = "Ono",
["ont"] = "Ontenu",
["onu"] = "Unua",
["onw"] = "Nubia Kuna",
["onx"] = "Pijin Onin",
["ood"] = "O'odham",
["oog"] = "Ong",
["oon"] = "Önge",
["oor"] = "Oorlams",
["oos"] = "Ossetik Kuna",
["opa"] = "Okpamheri",
["opk"] = "Kopkaka",
["opm"] = "Oksapmin",
["opo"] = "Opao",
["opt"] = "Opata",
["opy"] = "Ofayé",
["or"] = "Oriya",
["ora"] = "Oroha",
["ore"] = "Orejón",
["org"] = "Oring",
["orh"] = "Oroqen",
["oro"] = "Orokolo",
["orr"] = "Oruma",
["ort"] = "Adiwasi Oriya",
["oru"] = "Ormuri",
["orv"] = "Slavik Timur Kuna",
["orw"] = "Oro Win",
["orx"] = "Oro",
["orz"] = "Ormu",
["os"] = "Ossetian",
["os-pro"] = "Proto-Ossetic",
["osa"] = "Osage",
["osc"] = "Oscan",
["osi"] = "Osing",
["osn"] = "Sunda Kuna",
["oso"] = "Ososo",
["osp"] = "Spanyol Kuna",
["ost"] = "Osatu",
["osu"] = "One Selatan",
["osx"] = "Saxon Kuna",
["ota"] = "Turki Ottoman",
["otb"] = "Tibet Kuna",
["otd"] = "Ot Danum",
["ote"] = "Otomi Mezquital",
["oti"] = "Oti",
["otk"] = "Turkik Kuna",
["otl"] = "Otomi Tilapa",
["otm"] = "Otomi Pegunungan Timur",
["otn"] = "Otomi Tenango",
["oto-otm-pro"] = "Proto-Otomi",
["oto-pro"] = "Proto-Otomian",
["otq"] = "Otomi Querétaro",
["otr"] = "Otoro",
["ots"] = "Otomi Estado de México",
["ott"] = "Otomi Temoaya",
["otu"] = "Otuke",
["otw"] = "Ottawa",
["otx"] = "Otomi Texcatepec",
["oty"] = "Tamil Kuna",
["otz"] = "Otomi Ixtenco",
["oub"] = "Glio-Oubi",
["oue"] = "Oune",
["oui"] = "Uighur Kuna",
["oum"] = "Ouma",
["ovd"] = "Elfdalian",
["owi"] = "Owiniga",
["owl"] = "Welsh Kuna",
["oyb"] = "Oy",
["oyd"] = "Oyda",
["oym"] = "Wayampi",
["oyy"] = "Oya'oya",
["ozm"] = "Koonzime",
["pa"] = "Punjab",
["paa-kom"] = "Kómnzo",
["paa-kwn"] = "Kuwani",
["paa-nha-pro"] = "Proto-Halmahera Utara",
["paa-nun"] = "Nungon",
["pab"] = "Pareci",
["pac"] = "Pacoh",
["pad"] = "Paumarí",
["pae"] = "Pagibete",
["paf"] = "Paranawát",
["pag"] = "Pangasinan",
["pah"] = "Tenharim",
["pai"] = "Pe",
["pak"] = "Parakanã",
["pal"] = "Persia Tengahan",
["pam"] = "Kapampangan",
["pao"] = "Paiute Utara",
["pap"] = "Papiamentu",
["paq"] = "Parya",
["par"] = "Panamint",
["pas"] = "Papasena",
["pat"] = "Papitalai",
["pau"] = "Palauan",
["pav"] = "Wari'",
["paw"] = "Pawnee",
["pax"] = "Pankararé",
["pay"] = "Pech",
["paz"] = "Pankararú",
["pbb"] = "Páez",
["pbc"] = "Patamona",
["pbe"] = "Popoloca Mezontla",
["pbf"] = "Popoloca Coyotepec",
["pbg"] = "Paraujano",
["pbh"] = "Panare",
["pbi"] = "Podoko",
["pbl"] = "Mak (Nigeria)",
["pbm"] = "Mazatec Puebla",
["pbn"] = "Kpasam",
["pbo"] = "Papel",
["pbp"] = "Badyara",
["pbr"] = "Pangwa",
["pbs"] = "Pame Tengah",
["pbv"] = "Pnar",
["pby"] = "Pyu",
["pca"] = "Popoloca Santa Inés Ahuatempan",
["pcb"] = "Pear",
["pcc"] = "Bouyei",
["pcd"] = "Picard",
["pce"] = "Palaung Ruching",
["pcf"] = "Paliyan",
["pcg"] = "Paniya",
["pch"] = "Pardhan",
["pci"] = "Duruwa",
["pcj"] = "Parenga",
["pck"] = "Paite",
["pcl"] = "Pardhi",
["pcm"] = "Pijin Nigeria",
["pcn"] = "Piti",
["pcp"] = "Pacahuara",
["pcw"] = "Pyapun",
["pda"] = "Anam",
["pdc"] = "Jirman Pennsylvania",
["pdi"] = "Pa Di",
["pdn"] = "Fedan",
["pdo"] = "Padoe",
["pdt"] = "Plautdietsch",
["pdu"] = "Kayan",
["pea"] = "Peranakan Indunisia",
["peb"] = "Pomo Timur",
["ped"] = "Mala (Papua)",
["pee"] = "Taje",
["pef"] = "Pomo Timur Laut",
["peg"] = "Pengo",
["peh"] = "Bonan",
["pei"] = "Chichimeca-Jonaz",
["pej"] = "Pomo Utara",
["pek"] = "Penchal",
["pel"] = "Pekal",
["pem"] = "Phende",
["peo"] = "Persia Kuna",
["pep"] = "Kunja",
["peq"] = "Pomo Selatan",
["pev"] = "Pémono",
["pex"] = "Petats",
["pey"] = "Petjo",
["pez"] = "Penan Timur",
["pfa"] = "Pááfang",
["pfe"] = "Peere",
["pga"] = "Arab Juba",
["pgd"] = "Gandhari",
["pgg"] = "Pangwali",
["pgi"] = "Pagi",
["pgk"] = "Rerep",
["pgl"] = "Irlandia Primitif",
["pgn"] = "Paelignian",
["pgs"] = "Pangseng",
["pgu"] = "Isam",
["pgz"] = "Isyarat Papua Nugini",
["pha"] = "Pa-Hng",
["phd"] = "Phudagi",
["phg"] = "Phuong",
["phh"] = "Phukha",
["phi-din"] = "Agta Dinapigue",
["phi-kal-pro"] = "Proto-Kalamian",
["phi-nag"] = "Agta Nagtipunan",
["phi-pro"] = "Proto-Filipina",
["phk"] = "Phake",
["phl"] = "Phalura",
["phm"] = "Phimbi",
["phn"] = "Punisia",
["pho"] = "Phunoi",
["phq"] = "Phana'",
["phr"] = "Pahari-Potwari",
["pht"] = "Phu Thai",
["phu"] = "Phuan",
["phv"] = "Pahlavani",
["phw"] = "Phangduwali",
["pi"] = "Pali",
["pia"] = "Pima Bajo",
["pib"] = "Yine",
["pic"] = "Pinji",
["pid"] = "Piaroa",
["pie"] = "Piro",
["pif"] = "Pingelapese",
["pig"] = "Pisabo",
["pih"] = "Pitcairn-Norfolk",
["pii"] = "Pini",
["pij"] = "Pijao",
["pil"] = "Yom",
["pim"] = "Powhatan",
["pin"] = "Piame",
["pio"] = "Piapoco",
["pip"] = "Pero",
["pir"] = "Piratapuyo",
["pis"] = "Pijin",
["pit"] = "Pitta-Pitta",
["piu"] = "Pintupi-Luritja",
["piv"] = "Pileni",
["piw"] = "Pimbwe",
["pix"] = "Piu",
["piy"] = "Piya-Kwonci",
["piz"] = "Pije",
["pjt"] = "Pitjantjatjara",
["pka"] = "Prakrit Ardhamagadhi",
["pkb"] = "Kipfokomo",
["pkc"] = "Baekje",
["pkg"] = "Pak-Tong",
["pkh"] = "Pankhu",
["pkn"] = "Pakanha",
["pko"] = "Pökoot",
["pkp"] = "Pukapukan",
["pkr"] = "Kurumba Attapady",
["pks"] = "Isyarat Pakistan",
["pkt"] = "Maleng",
["pku"] = "Paku",
["pl"] = "Polandia",
["pla"] = "Miani",
["plb"] = "Polonombauk",
["plc"] = "Palawano Tengah",
["ple"] = "Palu'e",
["plg"] = "Pilagá",
["plh"] = "Paulohi",
["plj"] = "Polci",
["plk"] = "Shina Kohistani",
["pll"] = "Palaung Shwe",
["pln"] = "Palenquero",
["plo"] = "Popoluca Oluta",
["plq"] = "Palaic",
["plr"] = "Senoufo Palaka",
["pls"] = "Popoloca San Marcos Tlalcoyalco",
["plu"] = "Palikur",
["plv"] = "Palawano Barat Daya",
["plw"] = "Palawano Brooke's Point",
["ply"] = "Bolyu",
["plz"] = "Paluan",
["pma"] = "Paama",
["pmb"] = "Pambia",
["pmd"] = "Pallanganmiddang",
["pme"] = "Pwaamei",
["pmf"] = "Pamona",
["pmh"] = "Prakrit Maharastri",
["pmi"] = "Pumi Utara",
["pmj"] = "Pumi Selatan",
["pmk"] = "Pamlico",
["pml"] = "Sabir",
["pmm"] = "Pol",
["pmn"] = "Pam",
["pmo"] = "Pom",
["pmq"] = "Pame Utara",
["pmr"] = "Paynamar",
["pms"] = "Piedmont",
["pmt"] = "Tuamotuan",
["pmu"] = "Panjabi Mirpur",
["pmw"] = "Miwok Plains",
["pmx"] = "Naga Poumei",
["pmy"] = "Malayu Papua",
["pmz"] = "Pame Selatan",
["pna"] = "Punan Bah-Biau",
["pnb"] = "Panjabi Barat",
["pnc"] = "Pannei",
["pnd"] = "Mpinda",
["pne"] = "Penan Barat",
["png"] = "Pongu",
["pnh"] = "Penrhyn",
["pni"] = "Aoheng",
["pnj"] = "Pinjarup",
["pnk"] = "Paunaca",
["pnl"] = "Paleni",
["pnm"] = "Punan Batu",
["pnn"] = "Pinai-Hagahai",
["pno"] = "Panobo",
["pnp"] = "Pancana",
["pnq"] = "Pana (Afrika Barat)",
["pnr"] = "Panim",
["pns"] = "Ponosakan",
["pnt"] = "Yunani Pontic",
["pnu"] = "Bunu Jiongnai",
["pnv"] = "Pinigura",
["pnw"] = "Panyjima",
["pnx"] = "Phong-Kniang",
["pny"] = "Pinyin",
["pnz"] = "Pana (Afrika Tengah)",
["poc"] = "Poqomam",
["poe"] = "Popoloca San Juan Atzingo",
["pof"] = "Poke",
["pog"] = "Potiguára",
["poh"] = "Poqomchi'",
["poi"] = "Popoluca Pegunungan",
["pok"] = "Pokangá",
["pom"] = "Pomo Tenggara",
["pon"] = "Pohnpeian",
["poo"] = "Pomo Tengah",
["pop"] = "Pwapwa",
["poq"] = "Popoluca Texistepec",
["pos"] = "Popoluca Sayula",
["pot"] = "Potawatomi",
["pov"] = "Kreol Guinea-Bissau",
["pow"] = "Popoloca San Felipe Otlaltepec",
["pox"] = "Polabian",
["poy"] = "Pogolo",
["poz-abi"] = "Abai",
["poz-bal"] = "Baliledo",
["poz-btk-pro"] = "Proto-Bungku-Tolaki",
["poz-cet-pro"] = "Proto-Malayu-Polinesia Tengah Timur",
["poz-hce-pro"] = "Proto-Halmahera-Cenderawasih",
["poz-lgx-pro"] = "Proto-Lampung",
["poz-mcm-pro"] = "Proto-Malayu-Chamik",
["poz-mly-pro"] = "Proto-Melayik",
["poz-msa-pro"] = "Proto-Malayu-Sumbawa",
["poz-oce-pro"] = "Proto-Oseanik",
["poz-pep-pro"] = "Proto-Polinesia Timur",
["poz-pnp-pro"] = "Proto-Nuclear Polinesia",
["poz-pol-pro"] = "Proto-Polinesia",
["poz-pro"] = "Proto-Malayu-Polinesia",
["poz-sml"] = "Malayu Sarawak",
["poz-ssw-pro"] = "Proto-Sulawesi Selatan",
["poz-sus-pro"] = "Proto-Sunda-Sulawesi",
["poz-swa-pro"] = "Proto-Sarawak Utara",
["poz-ter"] = "Malayu Terengganu",
["ppa"] = "Pao",
["ppe"] = "Papi",
["ppi"] = "Paipai",
["ppk"] = "Uma",
["ppl"] = "Pipil",
["ppm"] = "Papuma",
["ppn"] = "Papapana",
["ppo"] = "Folopa",
["ppq"] = "Pei",
["pps"] = "Popoloca San Luís Temalacayuca",
["ppt"] = "Pa",
["ppu"] = "Papora",
["pqa"] = "Pa'a",
["pqe-pro"] = "Proto-Malayu-Polinesia Timur",
["pqm"] = "Malecite-Passamaquoddy",
["pra-niy"] = "Prakrit Niya",
["prc"] = "Parachi",
["pre"] = "Principense",
["prf"] = "Paranan",
["prg"] = "Prusia Kuna",
["prh"] = "Porohanon",
["pri"] = "Paicî",
["prk"] = "Parauk",
["prl"] = "Isyarat Peru",
["prm"] = "Kibiri",
["prn"] = "Prasuni",
["pro"] = "Occitan Kuna",
["prq"] = "Ashéninka Perené",
["prr"] = "Puri",
["prt"] = "Phai",
["pru"] = "Puragi",
["prw"] = "Parawen",
["prx"] = "Purik",
["prz"] = "Isyarat Providencia",
["ps"] = "Pashto",
["psa"] = "Awyu Asue",
["psc"] = "Isyarat Persia",
["psd"] = "Isyarat Plains Indian",
["pse"] = "Malayu Tengah",
["psg"] = "Isyarat Penang",
["psh"] = "Pashayi Barat Daya",
["psi"] = "Pashayi Tenggara",
["psl"] = "Isyarat Puerto Riko",
["psm"] = "Pauserna",
["psn"] = "Panasuan",
["pso"] = "Isyarat Polandia",
["psp"] = "Isyarat Filipina",
["psq"] = "Pasi",
["psr"] = "Isyarat Purtugis",
["pss"] = "Kaulong",
["psu"] = "Prakrit Sauraseni",
["psw"] = "Port Sandwich",
["psy"] = "Piscataway",
["pt"] = "Purtugis",
["pta"] = "Pai Tavytera",
["pth"] = "Pataxó Hã-Ha-Hãe",
["pti"] = "Pintiini",
["ptn"] = "Patani",
["pto"] = "Zo'é",
["ptp"] = "Patep",
["ptq"] = "Pattapu",
["ptr"] = "Piamatsina",
["ptt"] = "Enrekang",
["ptu"] = "Bambam",
["ptv"] = "Port Vato",
["ptw"] = "Pentlatch",
["pty"] = "Pathiya",
["pua"] = "Purepecha",
["pub"] = "Purum",
["puc"] = "Punan Merap",
["pud"] = "Punan Aput",
["pue"] = "Puelche",
["puf"] = "Punan Merah",
["pug"] = "Phuie",
["pui"] = "Puinave",
["puj"] = "Punan Tubu",
["pum"] = "Puma",
["puo"] = "Puoc",
["pup"] = "Pulabu",
["puq"] = "Puquina",
["pur"] = "Puruborá",
["put"] = "Putoh",
["puu"] = "Punu",
["puw"] = "Puluwat",
["pux"] = "Puare",
["puy"] = "Purisimeño",
["pwa"] = "Pawaia",
["pwb"] = "Panawa",
["pwg"] = "Gapapaiwa",
["pwi"] = "Patwin",
["pwm"] = "Molbog",
["pwn"] = "Paiwan",
["pwo"] = "Pwo Barat",
["pwr"] = "Powari",
["pww"] = "Pwo Utara",
["pxm"] = "Mixe Quetzaltepec",
["pye"] = "Pye Krumen",
["pym"] = "Fyam",
["pyn"] = "Poyanáwa",
["pys"] = "Isyarat Paraguay",
["pyu"] = "Puyuma",
["pyx"] = "Tircul",
["pyy"] = "Pyen",
["pzh"] = "Pazeh",
["pzn"] = "Naga Para",
["qfa-adm-pro"] = "Proto-Great Andaman",
["qfa-bet-pro"] = "Proto-Be-Tai",
["qfa-cka-pro"] = "Proto-Chukotko-Kamchatkan",
["qfa-hur-pro"] = "Proto-Hurro-Urartian",
["qfa-kad-pro"] = "Proto-Kadu",
["qfa-kms-pro"] = "Proto-Kam-Sui",
["qfa-kor-pro"] = "Proto-Korea",
["qfa-kra-pro"] = "Proto-Kra",
["qfa-lic-pro"] = "Proto-Hlai",
["qfa-onb-pro"] = "Proto-Be",
["qfa-ong-pro"] = "Proto-Ongan",
["qfa-tak-pro"] = "Proto-Kra-Dai",
["qfa-xgx-tuh"] = "Tuyuhun",
["qfa-xgx-tuo"] = "Tuoba",
["qfa-xgx-wuh"] = "Wuhuan",
["qfa-xgx-xbi"] = "Xianbei",
["qfa-yen-pro"] = "Proto-Yeniseian",
["qfa-yuk-pro"] = "Proto-Yukaghir",
["qu"] = "Quechua",
["qua"] = "Quapaw",
["quc"] = "K'iche'",
["qui"] = "Quileute",
["qum"] = "Sipakapense",
["qun"] = "Quinault",
["quq"] = "Quinqui",
["quv"] = "Sacapulteco",
["qvy"] = "Queyu",
["qwc"] = "Quechua Klasik",
["qwe-kch"] = "Kichwa",
["qwm"] = "Kipchak",
["qwt"] = "Kwalhioqua-Tlatskanai",
["qxs"] = "Qiang Selatan",
["qya"] = "Quenya",
["qyp"] = "Quiripi",
["raa"] = "Dungmali",
["rab"] = "Chamling",
["rac"] = "Rasawa",
["rad"] = "Rade",
["raf"] = "Meohang Barat",
["rag"] = "Logooli",
["rah"] = "Rabha",
["rai"] = "Ramoaaina",
["raj"] = "Rajasthani",
["rak"] = "Tulu-Bohuai",
["ral"] = "Ralte",
["ram"] = "Canela",
["ran"] = "Riantana",
["rao"] = "Rao",
["rap"] = "Rapa Nui",
["raq"] = "Saam",
["rar"] = "Rarotongan",
["ras"] = "Tegali",
["rat"] = "Razajerdi",
["rau"] = "Raute",
["rav"] = "Sampang",
["raw"] = "Rawang",
["rax"] = "Rang",
["ray"] = "Rapa",
["raz"] = "Rahambuu",
["rbb"] = "Palaung Rumai",
["rbk"] = "Bontoc Utara",
["rbl"] = "Bikol Miraya",
["rcf"] = "Kreol Parancis Réunion",
["rdb"] = "Rudbari",
["rea"] = "Rerau",
["reb"] = "Rembong",
["ree"] = "Kayan Rejang",
["reg"] = "Kara (Tanzania)",
["rei"] = "Reli",
["rej"] = "Rejang",
["rel"] = "Rendille",
["rem"] = "Remo",
["ren"] = "Rengao",
["rer"] = "Rer Bare",
["res"] = "Reshe",
["ret"] = "Retta",
["rey"] = "Reyesano",
["rga"] = "Roria",
["rge"] = "Yunani Romani",
["rgk"] = "Rangkas",
["rgn"] = "Romagnol",
["rgr"] = "Resígaro",
["rgs"] = "Roglai Selatan",
["rgu"] = "Ringgou",
["rhg"] = "Rohingya",
["rhp"] = "Yahang",
["ria"] = "Reang",
["rif"] = "Tarifit",
["ril"] = "Riang",
["rim"] = "Nyaturu",
["rin"] = "Nungu",
["rir"] = "Ribun",
["rit"] = "Ritarungo",
["riu"] = "Riung",
["rjg"] = "Rajong",
["rji"] = "Raji",
["rjs"] = "Rajbanshi",
["rka"] = "Kraol",
["rkb"] = "Rikbaktsa",
["rkh"] = "Rakahanga-Manihiki",
["rki"] = "Rakhine",
["rkm"] = "Marka",
["rkt"] = "Kamta",
["rkw"] = "Arakwal",
["rm"] = "Romansch",
["rma"] = "Rama",
["rmb"] = "Rembarunga",
["rmc"] = "Romani Karpathia",
["rmd"] = "Denmark Traveller",
["rme"] = "Angloromani",
["rmf"] = "Romani Kalo Finlandia",
["rmg"] = "Norwegia Traveller",
["rmh"] = "Murkim",
["rmi"] = "Lomavren",
["rmk"] = "Romkun",
["rml"] = "Romani Baltik",
["rmm"] = "Roma",
["rmn"] = "Romani Balkan",
["rmo"] = "Romani Sinte",
["rmp"] = "Rempi",
["rmq"] = "Caló",
["rms"] = "Isyarat Romania",
["rmt"] = "Domari",
["rmu"] = "Romani Tavringer",
["rmv"] = "Romanova",
["rmw"] = "Romani Welsh",
["rmx"] = "Romam",
["rmy"] = "Romani Vlax",
["rmz"] = "Marma",
["rnd"] = "Ruwund",
["rng"] = "Ronga",
["rnl"] = "Ranglong",
["rnn"] = "Roon",
["rnp"] = "Rongpo",
["rnw"] = "Rungwa",
["ro"] = "Romanian",
["roa-ang"] = "Angevin",
["roa-bbn"] = "Bourbonnais-Berrichon",
["roa-brg"] = "Bourguignon",
["roa-cha"] = "Champenois",
["roa-fcm"] = "Franc-Comtois",
["roa-gal"] = "Gallo",
["roa-leo"] = "Leon",
["roa-lor"] = "Lorrain",
["roa-oan"] = "Navarro-Aragon",
["roa-oca"] = "Katala Kuna",
["roa-ole"] = "Leon Kuna",
["roa-opt"] = "Galisia-Purtugis Kuna",
["roa-orl"] = "Orléan",
["roa-poi"] = "Poitevin-Saintongeais",
["roa-tar"] = "Tarantino",
["roa-tou"] = "Tourangeau",
["rob"] = "Tae'",
["roc"] = "Roglai Cacgia",
["rod"] = "Rogo",
["roe"] = "Ronji",
["rof"] = "Rombo",
["rog"] = "Roglai Utara",
["rol"] = "Romblomanon",
["rom"] = "Romani",
["roo"] = "Rotokas",
["rop"] = "Kriol",
["ror"] = "Rongga",
["rou"] = "Runga",
["row"] = "Dela-Oenale",
["rpn"] = "Repanbitip",
["rpt"] = "Rapting",
["rri"] = "Ririo",
["rro"] = "Roro",
["rrt"] = "Arritinngithigh",
["rsb"] = "Romano-Serbia",
["rsl"] = "Isyarat Rusia",
["rsm"] = "Isyarat Miriwoong",
["rtc"] = "Rungtu",
["rth"] = "Ratahan",
["rtm"] = "Rotuman",
["rtw"] = "Rathawi",
["ru"] = "Rusia",
["rub"] = "Gungu",
["ruc"] = "Ruuli",
["rue"] = "Rusyn",
["ruf"] = "Luguru",
["rug"] = "Roviana",
["ruh"] = "Ruga",
["rui"] = "Rufiji",
["ruk"] = "Che",
["ruo"] = "Istro-Romanian",
["rup"] = "Aromania",
["ruq"] = "Megleno-Romanian",
["rut"] = "Rutul",
["ruu"] = "Lobu Lanas",
["ruy"] = "Mala (Nigeria)",
["ruz"] = "Ruma",
["rw"] = "Rwanda-Rundi",
["rwa"] = "Rawo",
["rwk"] = "Rwa",
["rwm"] = "Amba",
["rwo"] = "Rawa",
["rxd"] = "Ngardi",
["rxw"] = "Karuwali",
["ryn"] = "Amami-Oshima Utara",
["rys"] = "Yaeyama",
["ryu"] = "Okinawa",
["rzh"] = "Razihi",
["sa"] = "Sanskerta",
["saa"] = "Saba",
["sab"] = "Buglere",
["sac"] = "Fox",
["sad"] = "Sandawe",
["sae"] = "Sabanê",
["saf"] = "Safaliba",
["sah"] = "Yakut",
["sai-ajg"] = "Ajagua",
["sai-all"] = "Allentiac",
["sai-and"] = "Andoquero",
["sai-ayo"] = "Ayomán",
["sai-bae"] = "Baenan",
["sai-bag"] = "Bagua",
["sai-bet"] = "Betoi",
["sai-bor-pro"] = "Proto-Boran",
["sai-cac"] = "Cacán",
["sai-caq"] = "Caranqui",
["sai-car-pro"] = "Proto-Cariban",
["sai-cat"] = "Catacao",
["sai-cer-pro"] = "Proto-Cerrado",
["sai-chi"] = "Chirino",
["sai-chn"] = "Chaná",
["sai-chp"] = "Chapacura",
["sai-chr"] = "Charrua",
["sai-chu"] = "Churuya",
["sai-cje-pro"] = "Proto-Jê Tengah",
["sai-cmg"] = "Comechingon",
["sai-cno"] = "Chono",
["sai-cnr"] = "Cañari",
["sai-coe"] = "Coeruna",
["sai-col"] = "Colán",
["sai-cop"] = "Copallén",
["sai-crd"] = "Puri Coroado",
["sai-ctq"] = "Catuquinaru",
["sai-cul"] = "Culli",
["sai-cva"] = "Cueva",
["sai-esm"] = "Esmeralda",
["sai-ewa"] = "Ewarhuyana",
["sai-gam"] = "Gamela",
["sai-gay"] = "Gayón",
["sai-gmo"] = "Guamo",
["sai-gue"] = "Güenoa",
["sai-hau"] = "Haush",
["sai-hoc-pro"] = "Proto-Huitoto-Ocaina",
["sai-jee-pro"] = "Proto-Jê",
["sai-jko"] = "Jeikó",
["sai-jrj"] = "Jirajara",
["sai-kat"] = "Katembri",
["sai-mal"] = "Malalí",
["sai-mar"] = "Maratino",
["sai-mat"] = "Matanawi",
["sai-mcn"] = "Mocana",
["sai-men"] = "Menien",
["sai-mil"] = "Millcayac",
["sai-mlb"] = "Malibu",
["sai-msk"] = "Masakará",
["sai-muc"] = "Mucuchí",
["sai-mue"] = "Muellama",
["sai-muz"] = "Muzo",
["sai-mys"] = "Maynas",
["sai-nat"] = "Natú",
["sai-nje-pro"] = "Proto-Jê Utara",
["sai-opo"] = "Opón",
["sai-oto"] = "Otomaco",
["sai-pal"] = "Palta",
["sai-pam"] = "Pamigua",
["sai-par"] = "Paratió",
["sai-pnz"] = "Panzaleo",
["sai-prh"] = "Puruhá",
["sai-ptg"] = "Patagón",
["sai-pur"] = "Purukotó",
["sai-pyg"] = "Payaguá",
["sai-pyk"] = "Pykobjê",
["sai-qmb"] = "Quimbaya",
["sai-qtm"] = "Quitemo",
["sai-rab"] = "Rabona",
["sai-ram"] = "Ramanos",
["sai-sac"] = "Sácata",
["sai-san"] = "Sanaviron",
["sai-sap"] = "Sapará",
["sai-sec"] = "Sechura",
["sai-sin"] = "Sinúfana",
["sai-sje-pro"] = "Proto-Jê Selatan",
["sai-tab"] = "Tabancale",
["sai-tal"] = "Tallán",
["sai-tap"] = "Tapayuna",
["sai-tar-pro"] = "Proto-Taranoan",
["sai-teu"] = "Teushen",
["sai-tim"] = "Timote",
["sai-tpr"] = "Taparita",
["sai-trr"] = "Tarairiú",
["sai-wai"] = "Waitaká",
["sai-way"] = "Wayumará",
["sai-wit-pro"] = "Proto-Witotoan",
["sai-wnm"] = "Wanham",
["sai-xoc"] = "Xocó",
["sai-yao"] = "Yao (Amerika Selatan)",
["sai-yar"] = "Yarumá",
["sai-yri"] = "Yuri",
["sai-yup"] = "Yupua",
["sai-yur"] = "Yurumanguí",
["saj"] = "Sahu",
["sak"] = "Sake",
["sal-pro"] = "Proto-Salish",
["sam"] = "Aramaik Samaria",
["sao"] = "Sause",
["saq"] = "Samburu",
["sar"] = "Saraveca",
["sas"] = "Sasak",
["sat"] = "Santali",
["sau"] = "Saleman",
["sav"] = "Saafi-Saafi",
["saw"] = "Sawi",
["sax"] = "Sa",
["say"] = "Saya",
["saz"] = "Saurashtra",
["sba"] = "Ngambay",
["sbb"] = "Simbo",
["sbc"] = "Gele'",
["sbd"] = "Samo Selatan",
["sbe"] = "Saliba (Papua)",
["sbf"] = "Shabo",
["sbg"] = "Seget",
["sbh"] = "Sori-Harengan",
["sbi"] = "Seti",
["sbj"] = "Surbakhal",
["sbk"] = "Safwa",
["sbl"] = "Botolan Sambal",
["sbm"] = "Sagala",
["sbn"] = "Sindhi Bhil",
["sbo"] = "Sabüm",
["sbp"] = "Sangu (Tanzania)",
["sbq"] = "Sileibi",
["sbr"] = "Murut Sembakung",
["sbs"] = "Subiya",
["sbt"] = "Kimki",
["sbu"] = "Bhoti Stod",
["sbv"] = "Sabine",
["sbw"] = "Simba",
["sbx"] = "Seberuang",
["sby"] = "Soli",
["sbz"] = "Sara Kaba",
["sc"] = "Sardinia",
["scb"] = "Chut",
["sce"] = "Dongxiang",
["scf"] = "Kreol Parancis San Miguel",
["scg"] = "Sanggau",
["sch"] = "Sakachep",
["sci"] = "Kreol Malayu Sri Lanka",
["sck"] = "Sadri",
["scl"] = "Shina",
["scn"] = "Sisilia",
["sco"] = "Scots",
["scp"] = "Yolmo",
["scq"] = "Sa'och",
["scs"] = "Slavey Utara",
["scu"] = "Shumcho",
["scv"] = "Sheni",
["scw"] = "Sha",
["scx"] = "Sicel",
["sd"] = "Sindhi",
["sda"] = "Toraja Sa'dan",
["sdb"] = "Shabak",
["sdc"] = "Sassarese",
["sde"] = "Surubu",
["sdf"] = "Sarli",
["sdg"] = "Savi",
["sdh"] = "Kurdi Selatan",
["sdj"] = "Suundi",
["sdk"] = "Sos Kundi",
["sdl"] = "Isyarat Arab Saudi",
["sdm"] = "Semandang",
["sdn"] = "Gallurese",
["sdo"] = "Bidayuh Bukar-Sadung",
["sdp"] = "Sherdukpen",
["sdr"] = "Sadri Oraon",
["sds"] = "Berber Tunisia",
["sdu"] = "Sarudu",
["sdv-daj-pro"] = "Proto-Daju",
["sdv-eje-pro"] = "Proto-Jebel Timur",
["sdv-nil-pro"] = "Proto-Nilotic",
["sdv-nyi-pro"] = "Proto-Nyima",
["sdv-tmn-pro"] = "Proto-Taman",
["sdx"] = "Melanau Sibu",
["se"] = "Sami Utara",
["sea"] = "Semai",
["sec"] = "Sechelt",
["sed"] = "Sedang",
["see"] = "Seneca",
["sef"] = "Senoufo Cebaara",
["seg"] = "Segeju",
["seh"] = "Sena",
["sei"] = "Seri",
["sej"] = "Sene",
["sek"] = "Sekani",
["sel-nor"] = "Selkup Utara",
["sel-pro"] = "Proto-Selkup",
["sel-sou"] = "Selkup Selatan",
["sem-amm"] = "Ammonite",
["sem-amo"] = "Amorite",
["sem-cha"] = "Chaha",
["sem-dad"] = "Dadanitic",
["sem-dum"] = "Dumaitic",
["sem-has"] = "Hasaitic",
["sem-him"] = "Himyaritic",
["sem-his"] = "Hismaic",
["sem-mhr"] = "Muher",
["sem-pro"] = "Proto-Semitik",
["sem-saf"] = "Safaitic",
["sem-srb"] = "Arab Selatan Kuna",
["sem-tay"] = "Taymanitic",
["sem-tha"] = "Thamudic",
["sem-wes-pro"] = "Proto-Semit Barat",
["sen"] = "Sénoufo Nanerigé",
["seo"] = "Suarmin",
["sep"] = "Sénoufo Sìcìté",
["seq"] = "Sénoufo Senara",
["ser"] = "Serrano",
["ses"] = "Senni Koyraboro",
["set"] = "Sentani",
["seu"] = "Serui-Laut",
["sev"] = "Senoufo Nyarafolo",
["sew"] = "Sewa Bay",
["sey"] = "Secoya",
["sez"] = "Chin Senthang",
["sfb"] = "Isyarat Belgia Parancis",
["sfm"] = "Miao Small Flowery",
["sfs"] = "Isyarat Afrika Selatan",
["sfw"] = "Sehwi",
["sg"] = "Sango",
["sga"] = "Irlandia Kuna",
["sgb"] = "Ayta Mag-Anchi",
["sgc"] = "Kipsigis",
["sgd"] = "Surigaonon",
["sge"] = "Segai",
["sgg"] = "Isyarat Swiss-Jirman",
["sgh"] = "Shughni",
["sgi"] = "Suga",
["sgk"] = "Sangkong",
["sgm"] = "Singa",
["sgp"] = "Singpho",
["sgr"] = "Sangisari",
["sgs"] = "Samogitia",
["sgt"] = "Brokpake",
["sgu"] = "Salas",
["sgw"] = "Sebat Bet Gurage",
["sgx"] = "Isyarat Sierra Leone",
["sgy"] = "Sanglechi",
["sgz"] = "Sursurunga",
["sh"] = "Serbo-Kroasia",
["sha"] = "Shall-Zwall",
["shb"] = "Ninam",
["shc"] = "Sonde",
["shd"] = "Kundal Shahi",
["she"] = "Sheko",
["shg"] = "Shua",
["shh"] = "Shoshone",
["shi"] = "Tashelhit",
["shj"] = "Shatt",
["shk"] = "Shilluk",
["shl"] = "Shendu",
["shm"] = "Shahrudi",
["shn"] = "Shan",
["sho"] = "Shanga",
["shp"] = "Shipibo-Conibo",
["shq"] = "Sala",
["shr"] = "Shi",
["shs"] = "Shuswap",
["sht"] = "Shasta",
["shu"] = "Arab Chad",
["shv"] = "Shehri",
["shw"] = "Shwai",
["shx"] = "She",
["shy"] = "Tachawit",
["shz"] = "Senoufo Syenara",
["si"] = "Sinhala",
["sia"] = "Sami Akkala",
["sib"] = "Sebop",
["sid"] = "Sidamo",
["sie"] = "Simaa",
["sif"] = "Siamou",
["sig"] = "Paasaal",
["sih"] = "Zire",
["sii"] = "Shom Peng",
["sij"] = "Numbami",
["sik"] = "Sikiana",
["sil"] = "Tumulung Sisaala",
["sim"] = "Seim",
["sio-pro"] = "Proto-Siouan",
["sip"] = "Sikkim",
["siq"] = "Sonia",
["sir"] = "Siri",
["sis"] = "Siuslaw",
["sit-bok"] = "Bokar",
["sit-cha"] = "Chairel",
["sit-gkh"] = "Gokhy",
["sit-hrs-pro"] = "Proto-Hrusish",
["sit-jap"] = "Japhug",
["sit-kha-pro"] = "Proto-Kham",
["sit-liz"] = "Lizu",
["sit-luu-pro"] = "Proto-Luish",
["sit-mor"] = "Moran",
["sit-prn"] = "Puiron",
["sit-pro"] = "Proto-Sino-Tibet",
["sit-sit"] = "Situ",
["sit-tan-pro"] = "Proto-Tani",
["sit-tgm"] = "Tangam",
["sit-tos"] = "Tosu",
["sit-tsh"] = "Tshobdun",
["sit-zbu"] = "Zbu",
["siu"] = "Sinagen",
["siv"] = "Sumariup",
["siw"] = "Siwai",
["six"] = "Sumau",
["siy"] = "Sivandi",
["siz"] = "Siwi",
["sja"] = "Epena",
["sjb"] = "Basap Sajau",
["sjd"] = "Sami Kildin",
["sje"] = "Sami Pite",
["sjg"] = "Assangori",
["sjk"] = "Sami Kemi",
["sjl"] = "Miji",
["sjm"] = "Mapun",
["sjn"] = "Sindarin",
["sjo"] = "Xibe",
["sjp"] = "Surjapuri",
["sjr"] = "Siar-Lak",
["sjs"] = "Senhaja De Srair",
["sjt"] = "Sami Ter",
["sju"] = "Sami Ume",
["sjw"] = "Shawnee",
["sk"] = "Slowakia",
["ska"] = "Skagit",
["skb"] = "Saek",
["skc"] = "Ma Manda",
["skd"] = "Miwok Sierra Selatan",
["ske"] = "Ske",
["skf"] = "Mekéns",
["skh"] = "Sikule",
["ski"] = "Sika",
["skj"] = "Seke",
["skk"] = "Sok",
["skm"] = "Sakam",
["skn"] = "Subanon Kolibugan",
["sko"] = "Seko Tengah",
["skp"] = "Sekapan",
["skq"] = "Sininkere",
["skr"] = "Saraiki",
["sks"] = "Maia",
["skt"] = "Sakata",
["sku"] = "Sakao",
["skv"] = "Skou",
["skw"] = "Kreol Walanda Skepi",
["skx"] = "Seko Padang",
["sky"] = "Sikaiana",
["skz"] = "Sekar",
["sl"] = "Slovenia",
["sla-pro"] = "Proto-Slavik",
["slc"] = "Saliba (Colombia)",
["sld"] = "Sissala",
["sle"] = "Sholaga",
["slf"] = "Isyarat Swiss-Italia",
["slg"] = "Murut Selungai",
["slh"] = "Salish Puget Sound Selatan",
["slj"] = "Salumá",
["sll"] = "Salt-Yui",
["slm"] = "Sama Pangutaran",
["sln"] = "Salinan",
["slp"] = "Lamaholot",
["slq"] = "Salchuq",
["slr"] = "Salar",
["sls"] = "Isyarat Singapura",
["slt"] = "Sila",
["slu"] = "Selaru",
["slw"] = "Sialum",
["slx"] = "Salampasu",
["sly"] = "Selayar",
["slz"] = "Ma'ya",
["sm"] = "Samoa",
["sma"] = "Sami Selatan",
["smb"] = "Simbari",
["smc"] = "Som",
["smd"] = "Sama",
["smf"] = "Auwe",
["smg"] = "Simbali",
["smh"] = "Samei",
["smi-pro"] = "Proto-Sami",
["smj"] = "Sami Lule",
["smk"] = "Bolinao",
["sml"] = "Sama Tengah",
["smm"] = "Musasa",
["smn"] = "Sami Inari",
["smp"] = "Ibrani Samaria",
["smq"] = "Samo",
["smr"] = "Simeulue",
["sms"] = "Sami Skolt",
["smt"] = "Simte",
["smu"] = "Somray",
["smv"] = "Samvedi",
["smw"] = "Sumbawa",
["smx"] = "Samba",
["smy"] = "Semnani",
["smz"] = "Simeku",
["sn"] = "Shona",
["snb"] = "Sebuyau",
["snc"] = "Sinaugoro",
["sne"] = "Bidayuh Bau",
["snf"] = "Noon",
["sng"] = "Sanga (Kongo)",
["sni"] = "Sensi",
["snj"] = "Sango Riverain",
["snk"] = "Soninke",
["snl"] = "Sangil",
["snm"] = "Ma'di Selatan",
["snn"] = "Siona",
["sno"] = "Snohomish",
["snp"] = "Siane",
["snq"] = "Sangu (Gabon)",
["snr"] = "Sihan",
["sns"] = "Nahavaq",
["snu"] = "Senggi",
["snv"] = "Sa'ban",
["snw"] = "Selee",
["snx"] = "Sam",
["sny"] = "Saniyo-Hiyewe",
["snz"] = "Kou",
["so"] = "Somali",
["soa"] = "Thai Song",
["sob"] = "Sobei",
["soc"] = "Soko",
["sod"] = "Songoora",
["soe"] = "Songomeno",
["sog"] = "Sogdian",
["soh"] = "Aka (Sudan)",
["soi"] = "Sonha",
["sok"] = "Sokoro",
["sol"] = "Solos",
["son-pro"] = "Proto-Songhay",
["soo"] = "Nsong",
["sop"] = "Songe",
["soq"] = "Kanasi",
["sor"] = "Somrai",
["sos"] = "Seenku",
["sou"] = "Thai Selatan",
["sov"] = "Sonsorolese",
["sow"] = "Sowanda",
["sox"] = "Swo",
["soy"] = "Miyobe",
["soz"] = "Temi",
["spb"] = "Sepa (Indunisia)",
["spc"] = "Sapé",
["spd"] = "Saep",
["spe"] = "Sepa (Papua)",
["spg"] = "Sian",
["spi"] = "Saponi",
["spk"] = "Sengo",
["spl"] = "Selepet",
["spm"] = "Sepen",
["spn"] = "Sanapaná",
["spo"] = "Spokane",
["spp"] = "Supyire",
["spr"] = "Saparua",
["sps"] = "Saposa",
["spt"] = "Bhoti Spiti",
["spu"] = "Sapuan",
["spv"] = "Sambalpuri",
["spx"] = "Picene Selatan",
["spy"] = "Sabaot",
["sq"] = "Albania",
["sqa"] = "Shama-Sambuga",
["sqh"] = "Shau",
["sqj-pro"] = "Proto-Albania",
["sqk"] = "Isyarat Albania",
["sqm"] = "Suma",
["sqn"] = "Susquehannock",
["sqo"] = "Sorkhei",
["sqq"] = "Sou",
["sqr"] = "Siculo-Arab",
["sqs"] = "Isyarat Sri Lanka",
["sqt"] = "Soqotri",
["squ"] = "Squamish",
["sra"] = "Saruga",
["srb"] = "Sora",
["sre"] = "Sara",
["srf"] = "Nafi",
["srg"] = "Sulod",
["srh"] = "Sarikoli",
["sri"] = "Siriano",
["srk"] = "Murut Serudung",
["srl"] = "Isirawa",
["srm"] = "Saramaccan",
["srn"] = "Sranan Tongo",
["srq"] = "Sirionó",
["srr"] = "Serer",
["srs"] = "Tsuut'ina",
["srt"] = "Sauri",
["sru"] = "Suruí",
["srv"] = "Sorsogon Waray",
["srw"] = "Serua",
["srx"] = "Sirmauri",
["sry"] = "Sera",
["srz"] = "Shahmirzadi",
["ss"] = "Swazi",
["ssa-klk-pro"] = "Proto-Kuliak",
["ssa-kom-pro"] = "Proto-Koman",
["ssa-pro"] = "Proto-Nilo-Saharan",
["ssb"] = "Sama Selatan",
["ssc"] = "Suba-Simbiti",
["ssd"] = "Siroi",
["sse"] = "Balangingi",
["ssf"] = "Thao",
["ssg"] = "Seimat",
["ssh"] = "Arab Shihhi",
["ssi"] = "Sansi",
["ssj"] = "Sausi",
["ssk"] = "Sunam",
["ssl"] = "Sisaala Barat",
["ssm"] = "Semnam",
["sso"] = "Sissano",
["ssp"] = "Isyarat Spanyol",
["ssq"] = "So'a",
["ssr"] = "Isyarat Swiss-Parancis",
["sss"] = "Sô",
["sst"] = "Sinasina",
["ssu"] = "Susuami",
["ssv"] = "Shark Bay",
["ssx"] = "Samberigi",
["ssy"] = "Saho",
["ssz"] = "Sengseng",
["st"] = "Sotho",
["stb"] = "Subanen Utara",
["std"] = "Sentinel",
["ste"] = "Liana-Seti",
["stf"] = "Seta",
["stg"] = "Trieng",
["sth"] = "Shelta",
["sti"] = "Stieng Bulo",
["stj"] = "Samo Matya",
["stk"] = "Arammba",
["stm"] = "Setaman",
["stn"] = "Owa",
["sto"] = "Stoney",
["stp"] = "Tepehuan Tenggara",
["stq"] = "Frisia Saterland",
["str"] = "Saanich",
["sts"] = "Shumashti",
["stt"] = "Stieng Budeh",
["stu"] = "Samtao",
["stv"] = "Silt'e",
["stw"] = "Satawalese",
["sty"] = "Siberia Tatar",
["su"] = "Sunda",
["sua"] = "Sulka",
["sub"] = "Suku",
["suc"] = "Subanon Barat",
["sue"] = "Suena",
["sug"] = "Suganga",
["sui"] = "Suki",
["suk"] = "Sukuma",
["suq"] = "Suri",
["sur"] = "Mwaghavul",
["sus"] = "Susu",
["sut"] = "Subtiaba",
["suv"] = "Sulung",
["suw"] = "Sumbwa",
["sux"] = "Sumerian",
["suy"] = "Suyá",
["suz"] = "Sunwar",
["sv"] = "Swedia",
["sva"] = "Svan",
["svb"] = "Ulau-Suain",
["svc"] = "Kreol Inggris Vincent",
["sve"] = "Serili",
["svk"] = "Isyarat Slowakia",
["svm"] = "Slavomolisano",
["svs"] = "Savosavo",
["svx"] = "Skalvian",
["sw"] = "Swahili",
["swb"] = "Comorian Maore",
["swf"] = "Sere",
["swg"] = "Swabia",
["swi"] = "Sui",
["swj"] = "Sira",
["swl"] = "Isyarat Swedia",
["swm"] = "Samosa",
["swn"] = "Sokna",
["swo"] = "Shanenawa",
["swp"] = "Suau",
["swq"] = "Sharwa",
["swr"] = "Saweru",
["sws"] = "Seluwasan",
["swt"] = "Sawila",
["swu"] = "Suwawa",
["sww"] = "Sowa",
["swx"] = "Suruahá",
["swy"] = "Sarua",
["sxb"] = "Suba",
["sxc"] = "Sicanian",
["sxe"] = "Sighu",
["sxg"] = "Shixing",
["sxk"] = "Kalapuya Selatan",
["sxl"] = "Selonian",
["sxm"] = "Samre",
["sxn"] = "Sangir",
["sxo"] = "Sorothaptic",
["sxr"] = "Saaroa",
["sxs"] = "Sasaru",
["sxw"] = "Gbe Saxwe",
["sya"] = "Siang",
["syb"] = "Subanen Tengah",
["syc"] = "Suriah Klasik",
["syd-fne"] = "Nenets Hutan",
["syd-pro"] = "Proto-Samoyedic",
["syi"] = "Seki",
["syk"] = "Sukur",
["syl"] = "Sylheti",
["sym"] = "Samo Maya",
["syn"] = "Senaya",
["syo"] = "Suoy",
["sys"] = "Sinyar",
["syw"] = "Kagate",
["syx"] = "Osamayi",
["syy"] = "Isyarat Al-Sayyid Bedouin",
["sza"] = "Semelai",
["szb"] = "Ngalum",
["szc"] = "Semaq Beri",
["szd"] = "Seru",
["sze"] = "Seze",
["szg"] = "Sengele",
["szl"] = "Silesian",
["szn"] = "Sula",
["szp"] = "Suabo",
["szv"] = "Isubu",
["szw"] = "Sawai",
["szy"] = "Sakizaya",
["ta"] = "Tamil",
["taa"] = "Tanana Hilir",
["tab"] = "Tabasaran",
["tac"] = "Tarahumara Dataran",
["tad"] = "Tause",
["tae"] = "Tariana",
["taf"] = "Tapirapé",
["tag"] = "Tagoi",
["tai-pro"] = "Proto-Tai",
["tai-swe-pro"] = "Proto-Tai Barat Daya",
["taj"] = "Tamang Timur",
["tak"] = "Tala",
["tal"] = "Tal",
["tan"] = "Tangale",
["tao"] = "Yami",
["tap"] = "Taabwa",
["tar"] = "Tarahumara Tengah",
["tas"] = "Tây Bồi",
["tau"] = "Tanana Hulu",
["tav"] = "Tatuyo",
["taw"] = "Tai",
["tax"] = "Tamki",
["tay"] = "Atayal",
["taz"] = "Tocho",
["tba"] = "Aikanã",
["tbb"] = "Tapeba",
["tbc"] = "Takia",
["tbd"] = "Kaki Ae",
["tbe"] = "Tanimbili",
["tbf"] = "Mandara",
["tbg"] = "Tairora Utara",
["tbh"] = "Thurawal",
["tbi"] = "Gaam",
["tbj"] = "Tiang",
["tbk"] = "Tagbanwa Calamian",
["tbl"] = "Tboli",
["tbm"] = "Tagbu",
["tbn"] = "Tunebo Barro Negro",
["tbo"] = "Tawala",
["tbp"] = "Taworta",
["tbq-bdg-pro"] = "Proto-Bodo-Garo",
["tbq-kuk-pro"] = "Proto-Kuki-Chin",
["tbq-lal-pro"] = "Proto-Lalo",
["tbq-laz"] = "Laze",
["tbq-lob-pro"] = "Proto-Lolo-Burma",
["tbq-lol-pro"] = "Proto-Loloish",
["tbq-ngo"] = "Ngochang",
["tbq-plg"] = "Pai-lang",
["tbr"] = "Tumtum",
["tbs"] = "Tanguat",
["tbt"] = "Kitembo",
["tbu"] = "Tubar",
["tbv"] = "Tobo",
["tbw"] = "Tagbanwa",
["tbx"] = "Kapin",
["tby"] = "Tabaru",
["tbz"] = "Ditammari",
["tca"] = "Ticuna",
["tcb"] = "Tanacross",
["tcc"] = "Datooga",
["tcd"] = "Tafi",
["tce"] = "Tutchone Selatan",
["tcf"] = "Malinaltepec Tlapanec",
["tcg"] = "Tamagario",
["tch"] = "Kreol Inggris Turks dan Caicos",
["tci"] = "Wára",
["tck"] = "Tchitchege",
["tcl"] = "Taman (Myanmar)",
["tcm"] = "Tanahmerah",
["tco"] = "Taungyo",
["tcp"] = "Chin Tawr",
["tcq"] = "Kaiy",
["tcs"] = "Kreol Torres Strait",
["tct"] = "T'en",
["tcu"] = "Tarahumara Tenggara",
["tcw"] = "Totonac Tecpatlán",
["tcx"] = "Toda",
["tcy"] = "Tulu",
["tcz"] = "Chin Thado",
["tda"] = "Tagdal",
["tdb"] = "Panchpargania",
["tdc"] = "Emberá-Tadó",
["tdd"] = "Tai Nüa",
["tde"] = "Dogon Tiranige Diga",
["tdf"] = "Talieng",
["tdg"] = "Tamang Barat",
["tdh"] = "Thulung",
["tdi"] = "Tomadino",
["tdj"] = "Tajio",
["tdk"] = "Tambas",
["tdl"] = "Sur",
["tdm"] = "Taruma",
["tdn"] = "Tondano",
["tdo"] = "Teme",
["tdq"] = "Tita",
["tdr"] = "Todrah",
["tds"] = "Doutai",
["tdt"] = "Tetun Dili",
["tdu"] = "Dusun Tempasuk",
["tdv"] = "Toro",
["tdy"] = "Tadyawan",
["te"] = "Telugu",
["tea"] = "Temiar",
["teb"] = "Tetete",
["tec"] = "Terik",
["ted"] = "Tepo Krumen",
["tee"] = "Tepehua Huehuetla",
["tef"] = "Teressa",
["teg"] = "Teke-Tege",
["teh"] = "Tehuelche",
["tei"] = "Torricelli",
["tek"] = "Teke Ibali",
["tem"] = "Temne",
["ten"] = "Tama (Colombia)",
["teo"] = "Ateso",
["tep"] = "Tepecano",
["teq"] = "Temein",
["ter"] = "Tereno",
["tes"] = "Tengger",
["tet"] = "Tetum",
["teu"] = "Soo",
["tev"] = "Teor",
["tew"] = "Tewa",
["tex"] = "Tennet",
["tey"] = "Tulishi",
["tez"] = "Tetserret",
["tfi"] = "Gbe Tofin",
["tfn"] = "Dena'ina",
["tfo"] = "Tefaro",
["tfr"] = "Teribe",
["tft"] = "Ternate",
["tg"] = "Tajik",
["tga"] = "Sagalla",
["tgb"] = "Tobilung",
["tgc"] = "Tigak",
["tgd"] = "Ciwogai",
["tge"] = "Tamang Gorkha Timur",
["tgf"] = "Chali",
["tgh"] = "Kreol Inggris Tobago",
["tgi"] = "Lawunuia",
["tgn"] = "Tandaganon",
["tgo"] = "Sudest",
["tgp"] = "Tangoa",
["tgq"] = "Tring",
["tgr"] = "Tareng",
["tgs"] = "Nume",
["tgt"] = "Tagbanwa Tengah",
["tgu"] = "Tanggu",
["tgv"] = "Tingui-Boto",
["tgw"] = "Senoufo Tagwana",
["tgx"] = "Tagish",
["tgy"] = "Togoyo",
["th"] = "Thai",
["thc"] = "Tai Hang Tong",
["thd"] = "Kuuk Thaayorre",
["the"] = "Tharu Chitwania",
["thf"] = "Thangmi",
["thh"] = "Tarahumara Utara",
["thi"] = "Tai Long",
["thk"] = "Tharaka",
["thl"] = "Tharu Dangaura",
["thm"] = "Thavung",
["thn"] = "Thachanadan",
["thp"] = "Thompson",
["thq"] = "Tharu Kochila",
["thr"] = "Tharu Rana",
["ths"] = "Thakali",
["tht"] = "Tahltan",
["thu"] = "Thuri",
["thy"] = "Tha",
["ti"] = "Tigrinya",
["tic"] = "Tira",
["tif"] = "Tifal",
["tig"] = "Tigre",
["tih"] = "Murut Timugon",
["tii"] = "Tiene",
["tij"] = "Tilung",
["tik"] = "Tikar",
["til"] = "Tillamook",
["tim"] = "Timbe",
["tin"] = "Tindi",
["tio"] = "Teop",
["tip"] = "Trimuris",
["tiq"] = "Tiéfo",
["tis"] = "Itneg Masadiit",
["tit"] = "Tinigua",
["tiu"] = "Adasen",
["tiv"] = "Tiv",
["tiw"] = "Tiwi",
["tix"] = "Tiwa Selatan",
["tiy"] = "Tiruray",
["tiz"] = "Tai Hongjin",
["tja"] = "Tajuasohn",
["tjg"] = "Tunjung",
["tji"] = "Tujia Utara",
["tjl"] = "Tai Laing",
["tjm"] = "Timucua",
["tjn"] = "Tonjon",
["tjs"] = "Tujia Selatan",
["tju"] = "Tjurruru",
["tjw"] = "Chaap Wuurong",
["tk"] = "Turkmen",
["tka"] = "Truká",
["tkb"] = "Buksa",
["tkd"] = "Tukudede",
["tke"] = "Takwane",
["tkf"] = "Tukumanféd",
["tkl"] = "Tokelauan",
["tkm"] = "Takelma",
["tkn"] = "Toku-No-Shima",
["tkp"] = "Tikopia",
["tkq"] = "Tee",
["tkr"] = "Tsakhur",
["tks"] = "Ramandi",
["tkt"] = "Tharu Kathoriya",
["tku"] = "Totonac Necaxa Hulu",
["tkv"] = "Mur Pano",
["tkw"] = "Teanu",
["tkx"] = "Tangko",
["tkz"] = "Takua",
["tl"] = "Tagalog",
["tla"] = "Tepehuan Barat Daya",
["tlb"] = "Tobelo",
["tlc"] = "Totonac Misantla",
["tld"] = "Talaud",
["tlf"] = "Telefol",
["tlg"] = "Tofanma",
["tlh"] = "Klingon",
["tli"] = "Tlingit",
["tlj"] = "Talinga-Bwisi",
["tlk"] = "Taloki",
["tll"] = "Tetela",
["tlm"] = "Tolomako",
["tln"] = "Talondo'",
["tlo"] = "Talodi",
["tlp"] = "Totonac Filomena Mata-Coahuitlán",
["tlq"] = "Tai Loi",
["tlr"] = "Talise",
["tls"] = "Tambotalo",
["tlt"] = "Teluti",
["tlu"] = "Tulehu",
["tlv"] = "Taliabu",
["tlx"] = "Khehek",
["tly"] = "Talysh",
["tma"] = "Tama (Chad)",
["tmb"] = "Avava",
["tmc"] = "Tumak",
["tmd"] = "Haruai",
["tme"] = "Tremembé",
["tmf"] = "Toba-Maskoy",
["tmg"] = "Ternateño",
["tmh"] = "Tuareg",
["tmi"] = "Tutuba",
["tmj"] = "Samarokena",
["tmk"] = "Tamang Barat Laut",
["tml"] = "Tamnim Citak",
["tmm"] = "Tai Thanh",
["tmn"] = "Taman (Indunisia)",
["tmo"] = "Temoq",
["tmq"] = "Tumleo",
["tms"] = "Tima",
["tmt"] = "Tasmate",
["tmu"] = "Iau",
["tmv"] = "Motembo",
["tmy"] = "Tami",
["tmz"] = "Tamanaku",
["tn"] = "Tswana",
["tna"] = "Tacana",
["tnb"] = "Tunebo Barat",
["tnc"] = "Tanimuca-Retuarã",
["tnd"] = "Tunebo Angosturas",
["tne"] = "Kallahan Tinoc",
["tng"] = "Tobanga",
["tnh"] = "Maiani",
["tni"] = "Tandia",
["tnk"] = "Kwamera",
["tnl"] = "Lenakel",
["tnm"] = "Tabla",
["tnn"] = "Tanna Utara",
["tno"] = "Toromono",
["tnp"] = "Whitesands",
["tnq"] = "Taíno",
["tnr"] = "Bedik",
["tns"] = "Tenis",
["tnt"] = "Tontemboan",
["tnu"] = "Tay Khang",
["tnv"] = "Tangchangya",
["tnw"] = "Tonsawang",
["tnx"] = "Tanema",
["tny"] = "Tongwe",
["tnz"] = "Ten'edn",
["to"] = "Tonga",
["tob"] = "Toba",
["toc"] = "Totonac Coyutla",
["tod"] = "Toma",
["tof"] = "Gizrra",
["tog"] = "Tonga (Malawi)",
["toh"] = "Tonga (Mozambique)",
["toi"] = "Tonga (Zambia)",
["toj"] = "Tojolabal",
["tok"] = "Toki Pona",
["tol"] = "Tolowa",
["tom"] = "Tombulu",
["too"] = "Totonac Xicotepec de Juárez",
["top"] = "Totonac Papantla",
["toq"] = "Toposa",
["tor"] = "Togbo-Vara Banda",
["tos"] = "Totonac Pegunungan",
["tou"] = "Tho",
["tov"] = "Taromi Hulu",
["tow"] = "Jemez",
["tox"] = "Tobian",
["toy"] = "Topoiyo",
["toz"] = "To",
["tpa"] = "Taupota",
["tpc"] = "Me'phaa Azoyú",
["tpe"] = "Tippera",
["tpf"] = "Tarpia",
["tpg"] = "Kula",
["tpi"] = "Tok Pisin",
["tpj"] = "Tapieté",
["tpk"] = "Tupinikin",
["tpl"] = "Me'phaa Tlacoapa",
["tpm"] = "Tampulma",
["tpn"] = "Tupinambá",
["tpo"] = "Tai Pao",
["tpp"] = "Tepehua Pisaflores",
["tpq"] = "Tukpa",
["tpr"] = "Tuparí",
["tpt"] = "Tepehua Tlachichilco",
["tpu"] = "Tampuan",
["tpv"] = "Tanapag",
["tpw"] = "Tupi Kuna",
["tpx"] = "Me'phaa Acatepec",
["tpy"] = "Trumai",
["tpz"] = "Tinputz",
["tqb"] = "Tembé",
["tql"] = "Lehali",
["tqm"] = "Turumsa",
["tqn"] = "Tenino",
["tqo"] = "Toaripi",
["tqp"] = "Tomoip",
["tqq"] = "Tunni",
["tqr"] = "Torona",
["tqt"] = "Totonac Barat",
["tqu"] = "Touo",
["tqw"] = "Tonkawa",
["tr"] = "Turki",
["tra"] = "Tirahi",
["trb"] = "Terebu",
["trc"] = "Triqui Copala",
["trd"] = "Turi",
["tre"] = "Tarangan Timur",
["trf"] = "Kreol Inggris Trinidad",
["trg"] = "Lishán Didán",
["trh"] = "Turaka",
["tri"] = "Trió",
["trj"] = "Toram",
["trk-dkh"] = "Dukhan",
["trk-oat"] = "Turki Anatolia Kuna",
["trk-pro"] = "Proto-Turkik",
["trl"] = "Skotlandia Traveller",
["trm"] = "Tregami",
["trn"] = "Trinitario",
["tro"] = "Tarao",
["trp"] = "Kokborok",
["trq"] = "Triqui San Martín Itunyoso",
["trr"] = "Taushiro",
["trs"] = "Triqui Chicahuaxtla",
["trt"] = "Tunggare",
["tru"] = "Turoyo",
["trv"] = "Taroko",
["trw"] = "Torwali",
["trx"] = "Tringgus",
["try"] = "Turung",
["trz"] = "Torá",
["ts"] = "Tsonga",
["tsa"] = "Tsaangi",
["tsb"] = "Tsamai",
["tsc"] = "Tswa",
["tsd"] = "Tsakonian",
["tse"] = "Isyarat Tunisia",
["tsf"] = "Tamang Barat Daya",
["tsg"] = "Tausug",
["tsh"] = "Tsuvan",
["tsi"] = "Tsimshian",
["tsj"] = "Tshangla",
["tsl"] = "Ts'ün-Lao",
["tsm"] = "Isyarat Turki",
["tsp"] = "Toussian Utara",
["tsq"] = "Isyarat Thai",
["tsr"] = "Akei",
["tss"] = "Isyarat Taiwan",
["tsu"] = "Tsou",
["tsv"] = "Tsogo",
["tsw"] = "Tsishingini",
["tsx"] = "Mubami",
["tsy"] = "Isyarat Tebul",
["tt"] = "Tatar",
["tta"] = "Tutelo",
["ttb"] = "Gaa",
["ttc"] = "Tektiteko",
["ttd"] = "Tauade",
["tte"] = "Bwanabwana",
["ttf"] = "Tuotomb",
["ttg"] = "Tutong",
["tth"] = "Ta'oih Hulu",
["tti"] = "Tobati",
["ttj"] = "Tooro",
["ttk"] = "Totoro",
["ttl"] = "Totela",
["ttm"] = "Tutchone Utara",
["ttn"] = "Towei",
["tto"] = "Ta'oih Hilir",
["ttp"] = "Tombelala",
["ttr"] = "Tera",
["tts"] = "Isan",
["ttt"] = "Tat",
["ttu"] = "Torau",
["ttv"] = "Titan",
["ttw"] = "Long Wat",
["tty"] = "Sikaritai",
["ttz"] = "Tsum",
["tua"] = "Wiarumus",
["tub"] = "Tübatulabal",
["tuc"] = "Mutu",
["tud"] = "Tuxá",
["tue"] = "Tuyuca",
["tuf"] = "Tunebo Tengah",
["tug"] = "Tunia",
["tuh"] = "Taulil",
["tui"] = "Tupuri",
["tuj"] = "O'Hongana Manyawa",
["tul"] = "Tula",
["tum"] = "Tumbuka",
["tun"] = "Tunica",
["tuo"] = "Tucano",
["tup-gua-pro"] = "Proto-Tupi-Guarani",
["tup-kab"] = "Kabishiana",
["tup-pro"] = "Proto-Tupian",
["tuq"] = "Tedaga",
["tus"] = "Tuscarora",
["tuu"] = "Tututni",
["tuv"] = "Turkana",
["tuw-kkl"] = "Kyakala",
["tuw-pro"] = "Proto-Tungusic",
["tuw-sol"] = "Solon",
["tux"] = "Tuxináwa",
["tuy"] = "Tugen",
["tuz"] = "Turka",
["tva"] = "Vaghua",
["tvd"] = "Tsuvadi",
["tve"] = "Te'un",
["tvk"] = "Ambrym Tenggara",
["tvl"] = "Tuvaluan",
["tvm"] = "Tela-Masbuar",
["tvn"] = "Tavoyan",
["tvo"] = "Tidore",
["tvs"] = "Taveta",
["tvt"] = "Naga Tutsa",
["tvu"] = "Tunen",
["tvw"] = "Sedoa",
["tvx"] = "Taivoan",
["tvy"] = "Pijin Timor",
["twa"] = "Twana",
["twb"] = "Tawbuid Barat",
["twc"] = "Teshenawa",
["twe"] = "Teiwa",
["twf"] = "Taos",
["twg"] = "Tereweng",
["twh"] = "Tai Dón",
["twm"] = "Monpa Tawang",
["twn"] = "Twendi",
["two"] = "Tswapong",
["twp"] = "Ere",
["twq"] = "Tasawaq",
["twr"] = "Tarahumara Barat Daya",
["twt"] = "Turiwára",
["twu"] = "Termanu",
["tww"] = "Tuwari",
["twy"] = "Tawoyan",
["txa"] = "Tombonuo",
["txb"] = "Tocharian B",
["txc"] = "Tsetsaut",
["txe"] = "Totoli",
["txg"] = "Tangut",
["txh"] = "Thracian",
["txi"] = "Ikpeng",
["txj"] = "Tarjumo",
["txm"] = "Tomini",
["txn"] = "Tarangan Barat",
["txo"] = "Toto",
["txq"] = "Tii",
["txr"] = "Tartessian",
["txs"] = "Tonsea",
["txt"] = "Citak",
["txu"] = "Kayapó",
["txx"] = "Tatana",
["ty"] = "Tahiti",
["tya"] = "Tauya",
["tye"] = "Kyenga",
["tyh"] = "O'du",
["tyi"] = "Teke-Tsaayi",
["tyj"] = "Tai Do",
["tyl"] = "Thu Lao",
["tyn"] = "Kombai",
["typ"] = "Kuku-Thaypan",
["tyr"] = "Tai Daeng",
["tys"] = "Sapa",
["tyt"] = "Tày Tac",
["tyu"] = "Kua",
["tyv"] = "Tuvan",
["tyx"] = "Teke-Tyee",
["tyz"] = "Tày",
["tza"] = "Isyarat Tanzania",
["tzh"] = "Tzeltal",
["tzj"] = "Tz'utujil",
["tzl"] = "Talossan",
["tzm"] = "Atlas Tamazight Tengah",
["tzn"] = "Tugun",
["tzo"] = "Tzotzil",
["tzx"] = "Tabriak",
["uam"] = "Uamué",
["uan"] = "Kuan",
["uar"] = "Tairuma",
["uba"] = "Ubang",
["ubi"] = "Ubi",
["ubl"] = "Bikol Buhi'non",
["ubr"] = "Ubir",
["ubu"] = "Umbu-Ungu",
["uby"] = "Ubykh",
["uda"] = "Uda",
["ude"] = "Udihe",
["udg"] = "Muduga",
["udi"] = "Udi",
["udj"] = "Ujir",
["udl"] = "Uldeme",
["udm"] = "Udmurt",
["udu"] = "Uduk",
["ues"] = "Kioko",
["ufi"] = "Ufim",
["ug"] = "Uighur",
["uga"] = "Ugaritic",
["ugb"] = "Kuku-Ugbanh",
["uge"] = "Ughele",
["ugn"] = "Isyarat Uganda",
["ugo"] = "Gong",
["ugy"] = "Isyarat Uruguay",
["uha"] = "Uhami",
["uhn"] = "Damal",
["uis"] = "Uisai",
["uiv"] = "Iyive",
["uji"] = "Tanjijili",
["uk"] = "Ukraina",
["uka"] = "Kaburi",
["ukg"] = "Ukuriguma",
["ukh"] = "Ukhwejo",
["ukk"] = "Muak Sa-aak",
["ukl"] = "Isyarat Ukraina",
["ukp"] = "Ukpe-Bayobiri",
["ukq"] = "Ukwa",
["uks"] = "Isyarat Kaapor",
["uku"] = "Ukue",
["ukw"] = "Ukwuani-Aboh-Ndoni",
["uky"] = "Kuuk Yak",
["ula"] = "Fungwa",
["ulb"] = "Olukumi",
["ulc"] = "Ulch",
["ule"] = "Lule",
["ulf"] = "Afra",
["uli"] = "Ulithian",
["ulk"] = "Meriam",
["ull"] = "Ullatan",
["ulm"] = "Ulumanda'",
["uln"] = "Unserdeutsch",
["ulu"] = "Uma' Lung",
["ulw"] = "Ulwa",
["uma"] = "Umatilla",
["umb"] = "Umbundu",
["umc"] = "Marrucinian",
["umd"] = "Umbindhamu",
["umg"] = "Umbuygamu",
["umi"] = "Ukit",
["umm"] = "Umon",
["umn"] = "Naga Makyan",
["umo"] = "Umotína",
["ump"] = "Umpila",
["umr"] = "Umbugarla",
["ums"] = "Pendau",
["umu"] = "Munsee",
["una"] = "Watut Utara",
["und"] = "Undetermined",
["und-isa"] = "Isaurian",
["und-kas"] = "Kassite",
["und-mil"] = "Milang",
["und-mmd"] = "Mimi Decorse",
["und-mmn"] = "Mimi Nachtigal",
["und-phi"] = "Filistin",
["und-wji"] = "Jicaque Barat",
["une"] = "Uneme",
["ung"] = "Ngarinyin",
["unk"] = "Enawené-Nawé",
["unm"] = "Unami",
["unn"] = "Kurnai",
["unr"] = "Mundari",
["unu"] = "Unubahe",
["unx"] = "Munda",
["unz"] = "Kaili Unde",
["uok"] = "Uokha",
["uon"] = "Kulon",
["upi"] = "Umeda",
["upv"] = "Uripiv-Wala-Rano-Atchin",
["ur"] = "Urdu",
["ura"] = "Urarina",
["urb"] = "Urubú-Kaapor",
["urc"] = "Urningangg",
["ure"] = "Uru",
["urf"] = "Uradhi",
["urg"] = "Urigina",
["urh"] = "Urhobo",
["uri"] = "Urim",
["urj-fin-pro"] = "Proto-Finnic",
["urj-koo"] = "Komi Kuna",
["urj-kuk"] = "Kukkuzi",
["urj-kya"] = "Komi-Yazva",
["urj-mdv-pro"] = "Proto-Mordvinic",
["urj-prm-pro"] = "Proto-Permic",
["urj-pro"] = "Proto-Uralic",
["urj-ugr-pro"] = "Proto-Ugric",
["urk"] = "Urak Lawoi'",
["url"] = "Urali",
["urm"] = "Urapmin",
["urn"] = "Uruangnirin",
["uro"] = "Ura (Papua)",
["urp"] = "Uru-Pa-In",
["urr"] = "Lehalurup",
["urt"] = "Urat",
["uru"] = "Urumi",
["urv"] = "Uruava",
["urw"] = "Sop",
["urx"] = "Urimo",
["ury"] = "Orya",
["urz"] = "Uru-Eu-Wau-Wau",
["usa"] = "Usarufa",
["ush"] = "Ushojo",
["usi"] = "Usui",
["usk"] = "Usaghade",
["usp"] = "Uspanteco",
["uss"] = "Saare",
["usu"] = "Uya",
["uta"] = "Otank",
["ute"] = "Ute",
["uth"] = "Hun",
["utp"] = "Aba",
["utr"] = "Etulo",
["utu"] = "Utu",
["uum"] = "Urum",
["uun"] = "Kulon-Pazeh",
["uur"] = "Ura (Vanuatu)",
["uuu"] = "U",
["uve"] = "Uvean Barat",
["uvh"] = "Uri",
["uvl"] = "Lote",
["uwa"] = "Kuku-Uwanh",
["uya"] = "Doko-Uyanga",
["uz"] = "Uzbek",
["vaa"] = "Vaagri Booli",
["vae"] = "Vale",
["vag"] = "Vagla",
["vah"] = "Varhadi",
["vai"] = "Vai",
["vaj"] = "Sekele",
["val"] = "Vehes",
["vam"] = "Vanimo",
["van"] = "Valman",
["vao"] = "Vao",
["vap"] = "Vaiphei",
["var"] = "Huarijio",
["vas"] = "Vasavi",
["vau"] = "Vanuma",
["vav"] = "Varli",
["vay"] = "Vayu",
["vbb"] = "Babar Tenggara",
["vbk"] = "Bontoc Barat Daya",
["ve"] = "Venda",
["vec"] = "Venetian",
["ved"] = "Veddah",
["vem"] = "Vemgo-Mabas",
["veo"] = "Ventureño",
["vep"] = "Veps",
["ver"] = "Mom Jango",
["vgr"] = "Vaghri",
["vgt"] = "Isyarat Flemish",
["vi"] = "Vietnam",
["vic"] = "Kreol Virgin Islands",
["vid"] = "Vidunda",
["vif"] = "Vili",
["vig"] = "Viemo",
["vil"] = "Vilela",
["vis"] = "Vishavan",
["vit"] = "Viti",
["viv"] = "Iduna",
["vka"] = "Kariyarra",
["vki"] = "Ija-Zuba",
["vkj"] = "Kujarge",
["vkk"] = "Kaur",
["vkl"] = "Kulisusu",
["vkm"] = "Kamakan",
["vko"] = "Kodeoha",
["vkp"] = "Kreol Purtugis Korlai",
["vkt"] = "Kutai Hilir",
["vku"] = "Kurrama",
["vlp"] = "Valpei",
["vls"] = "Flemish Barat",
["vma"] = "Martuthunira",
["vmb"] = "Mbabaram",
["vmc"] = "Mixtec Juxtlahuaca",
["vmd"] = "Koraga Mudu",
["vme"] = "Masela Timur",
["vmf"] = "Franconia Timur",
["vmg"] = "Minigir",
["vmh"] = "Maraghei",
["vmi"] = "Miwa",
["vmj"] = "Mixtec Ixtayutla",
["vmk"] = "Makhuwa-Shirima",
["vml"] = "Malgana",
["vmm"] = "Mixtec Mitlatongo",
["vmp"] = "Mazatec Soyaltepec",
["vmq"] = "Mixtec Soyaltepec",
["vmr"] = "Marenje",
["vmu"] = "Muluridyi",
["vmv"] = "Valley Maidu",
["vmw"] = "Makhuwa",
["vmx"] = "Mixtec Tamazola",
["vmy"] = "Mazatec Ayautla",
["vmz"] = "Mazatec Mazatlán",
["vnk"] = "Lovono",
["vnm"] = "Neve'ei",
["vnp"] = "Vunapu",
["vo"] = "Volapük",
["vor"] = "Voro",
["vot"] = "Votic",
["vra"] = "Vera'a",
["vro"] = "Võro",
["vrs"] = "Varisi",
["vrt"] = "Banam Bay",
["vsi"] = "Isyarat Moldova",
["vsl"] = "Isyarat Venezuela",
["vsv"] = "Isyarat Valencia",
["vto"] = "Vitou",
["vum"] = "Vumbu",
["vun"] = "Vunjo",
["vut"] = "Vute",
["vwa"] = "Awa (Tiongkok)",
["wa"] = "Walloon",
["waa"] = "Walla Walla",
["wab"] = "Wab",
["wac"] = "Wasco-Wishram",
["wad"] = "Wandamen",
["waf"] = "Wakoná",
["wag"] = "Wa'ema",
["wah"] = "Watubela",
["waj"] = "Waffa",
["wal"] = "Wolaytta",
["wam"] = "Massachusett",
["wan"] = "Wan",
["wao"] = "Wappo",
["wap"] = "Wapishana",
["waq"] = "Wageman",
["war"] = "Waray-Waray",
["was"] = "Washo",
["wat"] = "Kaninuwa",
["wau"] = "Wauja",
["wav"] = "Waka",
["waw"] = "Waiwai",
["wax"] = "Watam",
["way"] = "Wayana",
["waz"] = "Wampur",
["wba"] = "Warao",
["wbb"] = "Wabo",
["wbe"] = "Waritai",
["wbf"] = "Wara",
["wbh"] = "Wanda",
["wbi"] = "Wanji",
["wbj"] = "Alagwa",
["wbk"] = "Waigali",
["wbl"] = "Wakhi",
["wbm"] = "Wa",
["wbp"] = "Warlpiri",
["wbq"] = "Waddar",
["wbr"] = "Wagdi",
["wbt"] = "Wanman",
["wbv"] = "Wajarri",
["wbw"] = "Woi",
["wca"] = "Yanomámi",
["wci"] = "Gbe Waci",
["wdd"] = "Wandji",
["wdg"] = "Wadaginam",
["wdj"] = "Wadjiginy",
["wdt"] = "Wendat",
["wdu"] = "Wadjigu",
["wdy"] = "Wadjabangayi",
["wea"] = "Wewaw",
["wec"] = "Wè Barat",
["wed"] = "Wedau",
["weh"] = "Weh",
["wei"] = "Kiunum",
["wem"] = "Gbe Weme",
["weo"] = "Wemale",
["wer"] = "Weri",
["wes"] = "Pijin Kamerun",
["wet"] = "Perai",
["weu"] = "Welaung",
["wew"] = "Weyewa",
["wfg"] = "Yafi",
["wga"] = "Wagaya",
["wgb"] = "Wagawaga",
["wgg"] = "Wangganguru",
["wgi"] = "Wahgi",
["wgo"] = "Waigeo",
["wgu"] = "Wirangu",
["wgy"] = "Warrgamay",
["wha"] = "Manusela",
["whg"] = "Wahgi Utara",
["whk"] = "Kenyah Wahau",
["whu"] = "Kayan Wahau",
["wib"] = "Toussian Selatan",
["wic"] = "Wichita",
["wie"] = "Wik-Epa",
["wif"] = "Wik-Keyangan",
["wig"] = "Wik-Ngathana",
["wih"] = "Wik-Me'anha",
["wii"] = "Minidien",
["wij"] = "Wik-Iiyanh",
["wik"] = "Wikalkan",
["wil"] = "Wilawila",
["wim"] = "Wik-Mungkan",
["win"] = "Winnebago",
["wir"] = "Wiraféd",
["wiu"] = "Wiru",
["wiv"] = "Muduapa",
["wiy"] = "Wiyot",
["wja"] = "Waja",
["wji"] = "Warji",
["wka"] = "Kw'adza",
["wkb"] = "Kumbaran",
["wkd"] = "Mo",
["wkl"] = "Kalanadi",
["wku"] = "Kunduvadi",
["wkw"] = "Wakawaka",
["wky"] = "Wangkayutyuru",
["wla"] = "Walio",
["wlc"] = "Comorian Mwali",
["wle"] = "Wolane",
["wlg"] = "Kunbarlang",
["wli"] = "Waioli",
["wlk"] = "Wailaki",
["wll"] = "Wali (Sudan)",
["wlm"] = "Welsh Tengahan",
["wlo"] = "Wolio",
["wlr"] = "Wailapa",
["wls"] = "Wallisian",
["wlu"] = "Wuliwuli",
["wlv"] = "Wichí Lhamtés Vejoz",
["wlw"] = "Walak",
["wlx"] = "Wali (Ghana)",
["wly"] = "Waling",
["wmb"] = "Wambaya",
["wmc"] = "Wamas",
["wmd"] = "Mamaindé",
["wme"] = "Wambule",
["wmh"] = "Waima'a",
["wmi"] = "Wamin",
["wmm"] = "Maiwa (Indunisia)",
["wmn"] = "Waamwang",
["wmo"] = "Wam",
["wms"] = "Wambon",
["wmt"] = "Walmajarri",
["wmw"] = "Mwani",
["wmx"] = "Womo",
["wnb"] = "Wanambre",
["wnc"] = "Wantoat",
["wnd"] = "Wandarang",
["wne"] = "Waneci",
["wng"] = "Wanggom",
["wni"] = "Comorian Ndzwani",
["wnk"] = "Wanukaka",
["wnm"] = "Wanggamala",
["wno"] = "Wano",
["wnp"] = "Wanap",
["wnu"] = "Usan",
["wnw"] = "Wintu",
["wny"] = "Wanyi",
["wo"] = "Wolof",
["woa"] = "Tyaraity",
["wob"] = "Wè Utara",
["woc"] = "Wogeo",
["wod"] = "Wolani",
["woe"] = "Woleaian",
["wog"] = "Wogamusin",
["woi"] = "Kamang",
["wok"] = "Longto",
["wom"] = "Perema",
["won"] = "Wongo",
["woo"] = "Manombai",
["wor"] = "Woria",
["wos"] = "Hanga Hundi",
["wow"] = "Wawonii",
["wpc"] = "Wirö",
["wra"] = "Warapu",
["wrb"] = "Warluwara",
["wrg"] = "Warungu",
["wrh"] = "Wiradhuri",
["wri"] = "Wariyangga",
["wrk"] = "Garawa",
["wrl"] = "Warlmanpa",
["wrm"] = "Warumungu",
["wrn"] = "Warnang",
["wro"] = "Worora",
["wrp"] = "Waropen",
["wrr"] = "Wardaman",
["wrs"] = "Waris",
["wru"] = "Waru",
["wrv"] = "Waruna",
["wrw"] = "Gugu Warra",
["wrx"] = "Wae Rana",
["wrz"] = "Warray",
["wsa"] = "Warembori",
["wsi"] = "Wusi",
["wsk"] = "Waskia",
["wsr"] = "Owenia",
["wss"] = "Wasa",
["wsu"] = "Wasu",
["wsv"] = "Wotapuri-Katarqalai",
["wtf"] = "Watiwa",
["wth"] = "Wathaurong",
["wti"] = "Berta",
["wtk"] = "Watakataui",
["wtm"] = "Mewati",
["wtw"] = "Wotu",
["wua"] = "Wikngenchera",
["wub"] = "Wunambal",
["wud"] = "Wudu",
["wuh"] = "Wutunhua",
["wul"] = "Silimo",
["wum"] = "Wumbvu",
["wun"] = "Bungu",
["wur"] = "Wurrugu",
["wut"] = "Wutung",
["wuu"] = "Wu",
["wuv"] = "Wuvulu-Aua",
["wux"] = "Wulna",
["wuy"] = "Wauyai",
["wwa"] = "Waama",
["wwo"] = "Dorig",
["wwr"] = "Warrwa",
["www"] = "Wawa",
["wxa"] = "Waxianghua",
["wxw"] = "Wardandi",
["wya"] = "Wyandot",
["wyb"] = "Ngiyambaa",
["wyi"] = "Woiwurrung",
["wym"] = "Vilamovian",
["wyr"] = "Wayoró",
["wyy"] = "Fiji Barat",
["xaa"] = "Arab Andalusia",
["xab"] = "Sambe",
["xac"] = "Kachari",
["xad"] = "Adai",
["xae"] = "Aequian",
["xag"] = "Aghwan",
["xai"] = "Kaimbé",
["xaj"] = "Ararandewára",
["xak"] = "Maku",
["xal"] = "Kalmyk",
["xam"] = "ǀXam",
["xan"] = "Xamtanga",
["xao"] = "Khao",
["xap"] = "Apalachee",
["xaq"] = "Aquitanian",
["xar"] = "Karami",
["xas"] = "Kamassian",
["xat"] = "Katawixi",
["xau"] = "Kauwera",
["xav"] = "Xavante",
["xaw"] = "Kawaiisu",
["xay"] = "Kayan Mahakam",
["xbb"] = "Burdekin Hilir",
["xbc"] = "Baktria",
["xbd"] = "Bindal",
["xbe"] = "Bigambal",
["xbg"] = "Bunganditj",
["xbi"] = "Kombio",
["xbj"] = "Birrpayi",
["xbm"] = "Breton Tengahan",
["xbn"] = "Kenaboi",
["xbo"] = "Bulgar",
["xbp"] = "Bibbulman",
["xbr"] = "Kambera",
["xbw"] = "Kambiwá",
["xby"] = "Butchulla",
["xcb"] = "Cumbric",
["xcc"] = "Camunic",
["xce"] = "Celtiberian",
["xch"] = "Chemakum",
["xcl"] = "Armenia Kuna",
["xcm"] = "Comecrudo",
["xcn"] = "Cotoname",
["xco"] = "Khwarezmian",
["xcr"] = "Carian",
["xct"] = "Tibet Klasik",
["xcu"] = "Curonian",
["xcv"] = "Chuvan",
["xcw"] = "Coahuilteco",
["xcy"] = "Cayuse",
["xda"] = "Darkinjung",
["xdc"] = "Dacian",
["xdk"] = "Dharug",
["xdm"] = "Edomite",
["xdy"] = "Malayu Dayak",
["xeb"] = "Eblaite",
["xed"] = "Hdi",
["xeg"] = "ǁXegwi",
["xel"] = "Kelo",
["xem"] = "Kembayan",
["xep"] = "Epi-Olmec",
["xer"] = "Xerénte",
["xes"] = "Kesawai",
["xet"] = "Xetá",
["xeu"] = "Keoru-Ahia",
["xfa"] = "Faliscan",
["xga"] = "Galatian",
["xgb"] = "Gbin",
["xgd"] = "Gudang",
["xgf"] = "Gabrielino-Fernandeño",
["xgg"] = "Goreng",
["xgi"] = "Garingbal",
["xgl"] = "Galindan",
["xgm"] = "Darumbal",
["xgn-mgl"] = "Mongghul",
["xgn-mgr"] = "Mangghuer",
["xgn-pro"] = "Proto-Mongolia",
["xgn-rou"] = "Rouran",
["xgr"] = "Garza",
["xgu"] = "Unggumi",
["xgw"] = "Guwa",
["xh"] = "Xhosa",
["xha"] = "Harami",
["xhc"] = "Hunnic",
["xhd"] = "Hadrami",
["xhe"] = "Khetrani",
["xhm"] = "Khmer Tengahan",
["xhr"] = "Hernican",
["xht"] = "Hattic",
["xhu"] = "Hurrian",
["xhv"] = "Khua",
["xib"] = "Iberian",
["xii"] = "Xiri",
["xil"] = "Illyrian",
["xin"] = "Xinca",
["xir"] = "Xiriâna",
["xis"] = "Kisan",
["xiv"] = "Lembah Indus",
["xiy"] = "Xipaya",
["xjb"] = "Minjungbal",
["xka"] = "Kalkoti",
["xkb"] = "Manigri-Kambolé Ede Nago",
["xkc"] = "Khoini",
["xkd"] = "Kayan Mendalam",
["xke"] = "Kereho",
["xkf"] = "Khengkha",
["xkg"] = "Kagoro",
["xki"] = "Isyarat Kenya",
["xkj"] = "Kajali",
["xkk"] = "Kaco'",
["xkl"] = "Bakung",
["xkn"] = "Kayan Sungai Kayan",
["xko"] = "Kiorr",
["xkp"] = "Kabatei",
["xkq"] = "Koroni",
["xkr"] = "Xakriabá",
["xks"] = "Kumbewaha",
["xkt"] = "Kantosi",
["xku"] = "Kaamba",
["xkv"] = "Kgalagadi",
["xkw"] = "Kembra",
["xkx"] = "Karore",
["xky"] = "Uma' Lasan",
["xkz"] = "Kurtöp",
["xla"] = "Kamula",
["xlb"] = "Loup B",
["xlc"] = "Lycian",
["xld"] = "Lydian",
["xle"] = "Lemnian",
["xlg"] = "Liguria Kuna",
["xli"] = "Liburnian",
["xlo"] = "Loup A",
["xlp"] = "Lepontic",
["xls"] = "Lusitania",
["xlu"] = "Luwian",
["xly"] = "Elymian",
["xmb"] = "Mbonga",
["xmc"] = "Makhuwa-Marrevone",
["xmd"] = "Mbudum",
["xme-ker"] = "Kermanic",
["xme-kls"] = "Kalasuri",
["xme-klt"] = "Kilit",
["xme-mid"] = "Media Tengahan",
["xme-old"] = "Media Kuna",
["xme-ott"] = "Tati Kuna",
["xme-taf"] = "Tafreshi",
["xme-ttc-pro"] = "Proto-Tatic",
["xmf"] = "Mingrelian",
["xmg"] = "Mengaka",
["xmh"] = "Kugu-Muminh",
["xmj"] = "Majera",
["xmk"] = "Makedonia Kuna",
["xml"] = "Isyarat Malaysia",
["xmm"] = "Malayu Manado",
["xmo"] = "Morerebi",
["xmp"] = "Kuku-Mu'inh",
["xmq"] = "Kuku-Mangk",
["xmr"] = "Meroitic",
["xms"] = "Isyarat Maroko",
["xmt"] = "Matbat",
["xmu"] = "Kamu",
["xmx"] = "Maden",
["xmy"] = "Mayaguduna",
["xmz"] = "Mori Bawah",
["xna"] = "Arab Utara Kuna",
["xnb"] = "Kanakanabu",
["xnd-pro"] = "Proto-Na-Dene",
["xng"] = "Mongol Tengahan",
["xnh"] = "Kuanhua",
["xni"] = "Ngarigu",
["xnk"] = "Nganakarti",
["xnn"] = "Kankanay Utara",
["xnr"] = "Kangri",
["xns"] = "Kanashi",
["xnt"] = "Narragansett",
["xnu"] = "Nukunul",
["xny"] = "Nyiyaparli",
["xoc"] = "O'chi'chi'",
["xod"] = "Kokoda",
["xog"] = "Soga",
["xoi"] = "Kominimung",
["xok"] = "Xokleng",
["xom"] = "Komo",
["xon"] = "Konkomba",
["xoo"] = "Xukurú",
["xop"] = "Kopar",
["xor"] = "Korubo",
["xow"] = "Kowaki",
["xpa"] = "Pirriya",
["xpb"] = "Pyemmairre",
["xpc"] = "Pecheneg",
["xpd"] = "Paredarerme",
["xpe"] = "Kpelle Liberia",
["xpf"] = "Tasmania Tenggara",
["xpg"] = "Phrygian",
["xph"] = "Tyerrernotepanner",
["xpi"] = "Pictish",
["xpj"] = "Mpalitjanh",
["xpk"] = "Kulina",
["xpl"] = "Port Sorell",
["xpm"] = "Pumpokol",
["xpn"] = "Kapinawá",
["xpo"] = "Pochutec",
["xpp"] = "Puyo-Paekche",
["xpq"] = "Mohegan-Pequot",
["xpr"] = "Parthian",
["xps"] = "Pisidian",
["xpu"] = "Punic",
["xpv"] = "Tommeginne",
["xpw"] = "Peerapper",
["xpx"] = "Toogee",
["xpy"] = "Buyeo",
["xpz"] = "Bruny Island",
["xqa"] = "Karakhanid",
["xqt"] = "Qatabanian",
["xra"] = "Krahô",
["xrb"] = "Karaboro Timur",
["xrd"] = "Gundungurra",
["xre"] = "Kreye",
["xrg"] = "Minang",
["xri"] = "Krikati-Timbira",
["xrm"] = "Armazic",
["xrn"] = "Arin",
["xrq"] = "Karranga",
["xrr"] = "Raetic",
["xrt"] = "Aranama-Tamique",
["xru"] = "Marriammu",
["xrw"] = "Karawa",
["xsa"] = "Sabaean",
["xsb"] = "Sambali",
["xsc-pro"] = "Proto-Scythia",
["xsc-sak-pro"] = "Proto-Saka",
["xsc-skw-pro"] = "Proto-Saka-Wakhi",
["xsd"] = "Sidetic",
["xse"] = "Sempan",
["xsh"] = "Shamang",
["xsi"] = "Sio",
["xsj"] = "Subi",
["xsl"] = "Slavey Selatan",
["xsm"] = "Kasem",
["xsn"] = "Sanga (Nigeria)",
["xso"] = "Solano",
["xsp"] = "Silopi",
["xsq"] = "Makhuwa-Saka",
["xsr"] = "Sherpa",
["xss"] = "Assan",
["xsu"] = "Sanumá",
["xsv"] = "Sudovian",
["xsy"] = "Saisiyat",
["xta"] = "Mixtec Alcozauca",
["xtb"] = "Mixtec Chazumba",
["xtc"] = "Kadugli",
["xtd"] = "Mixtec Diuxi-Tilantongo",
["xte"] = "Ketengban",
["xth"] = "Yitha Yitha",
["xti"] = "Mixtec Sinicahua",
["xtj"] = "Mixtec San Juan Teita",
["xtl"] = "Mixtec Tijaltepec",
["xtm"] = "Mixtec Magdalena Peñasco",
["xtn"] = "Mixtec Tlaxiaco Utara",
["xto"] = "Tocharian A",
["xtp"] = "Mixtec San Miguel Piedras",
["xtq"] = "Tumshuqese",
["xtr"] = "Tripuri Awal",
["xts"] = "Mixtec Sindihui",
["xtt"] = "Mixtec Tacahua",
["xtu"] = "Mixtec Cuyamecalco",
["xtv"] = "Thawa",
["xtw"] = "Tawandê",
["xty"] = "Mixtec Yoloxochitl",
["xtz"] = "Tasmania",
["xua"] = "Kurumba Alu",
["xub"] = "Kurumba Betta",
["xud"] = "Umiida",
["xug"] = "Kunigami",
["xuj"] = "Kurumba Jennu",
["xul"] = "Ngunawal",
["xum"] = "Umbrian",
["xun"] = "Unggaranggu",
["xuo"] = "Kuo",
["xup"] = "Umpqua Hulu",
["xur"] = "Urartian",
["xut"] = "Kuthant",
["xuu"] = "Khwe",
["xve"] = "Venetic",
["xvn"] = "Vandalic",
["xvo"] = "Volscian",
["xvs"] = "Vestinian",
["xwa"] = "Kwaza",
["xwc"] = "Woccon",
["xwd"] = "Wadi Wadi",
["xwe"] = "Gbe Xwela",
["xwg"] = "Kwegu",
["xwj"] = "Wajuk",
["xwk"] = "Wangkumara",
["xwl"] = "Gbe Xwla Barat",
["xwo"] = "Written Oirat",
["xwr"] = "Kwerba Mamberamo",
["xww"] = "Wemba-Wemba",
["xxb"] = "Boro",
["xxk"] = "Ke'o",
["xxm"] = "Minkin",
["xxr"] = "Koropó",
["xxt"] = "Tambora",
["xya"] = "Yaygir",
["xyb"] = "Yandjibara",
["xyl"] = "Yalakalore",
["xyt"] = "Mayi-Thakurti",
["xyy"] = "Yorta Yorta",
["xzh"] = "Zhang-Zhung",
["xzm"] = "Zemgalian",
["xzp"] = "Zapotec Kuna",
["yaa"] = "Yaminahua",
["yab"] = "Yuhup",
["yac"] = "Yali Lembah Pass",
["yad"] = "Yagua",
["yae"] = "Pumé",
["yaf"] = "Yaka",
["yag"] = "Yámana",
["yah"] = "Yazghulami",
["yai"] = "Yagnobi",
["yaj"] = "Banda-Yangere",
["yak"] = "Yakima",
["yal"] = "Yalunka",
["yam"] = "Yamba",
["yan"] = "Mayangna",
["yao"] = "Yao",
["yap"] = "Yapese",
["yaq"] = "Yaqui",
["yar"] = "Yabarana",
["yas"] = "Gunu",
["yat"] = "Yambeta",
["yau"] = "Yuwana",
["yav"] = "Yangben",
["yaw"] = "Yawalapití",
["yay"] = "Agwagwune",
["yaz"] = "Lokaa",
["yba"] = "Yala",
["ybb"] = "Yemba",
["ybe"] = "Yugur Barat",
["ybh"] = "Yakkha",
["ybi"] = "Yamphu",
["ybj"] = "Hasha",
["ybk"] = "Bokha",
["ybl"] = "Yukuben",
["ybm"] = "Yaben",
["ybn"] = "Yabaâna",
["ybo"] = "Yabong",
["ybx"] = "Yawiyo",
["yby"] = "Yaweyuha",
["ych"] = "Chesu",
["ycl"] = "Lolopo",
["ycn"] = "Yucuna",
["ycp"] = "Chepya",
["ycr"] = "Kreol Yilan",
["yda"] = "Yanda",
["yde"] = "Yangum Dey",
["ydg"] = "Yidgha",
["ydk"] = "Yoidik",
["yea"] = "Ravula",
["yec"] = "Yeniche",
["yee"] = "Yimas",
["yei"] = "Yeni",
["yej"] = "Yevanic",
["yen"] = "Yendang",
["yer"] = "Tarok",
["yes"] = "Yeskwa",
["yet"] = "Yetfa",
["yeu"] = "Yerukula",
["yev"] = "Yapunda",
["yey"] = "Yeyi",
["ygi"] = "Yiningayi",
["ygl"] = "Yangum Gel",
["ygm"] = "Yagomi",
["ygp"] = "Gepo",
["ygr"] = "Yagaria",
["ygs"] = "Isyarat Yolngu",
["ygu"] = "Yugul",
["ygw"] = "Yagwoia",
["yha"] = "Baha",
["yhl"] = "Phowa Hlepho",
["yi"] = "Yiddish",
["yia"] = "Yinggarda",
["yif"] = "Ache",
["yig"] = "Nasu Wusa",
["yii"] = "Yidiny",
["yij"] = "Yindjibarndi",
["yik"] = "Lalo Dongshanba",
["yil"] = "Yindjilandji",
["yim"] = "Naga Yimchungru",
["yin"] = "Yinchia",
["yip"] = "Pholo",
["yiq"] = "Miqie",
["yir"] = "Awyu Utara",
["yis"] = "Yis",
["yit"] = "Lalu Timur",
["yiu"] = "Awu",
["yiv"] = "Nisu Utara",
["yix"] = "Yi Axi",
["yiy"] = "Yir-Yoront",
["yiz"] = "Azhe",
["yka"] = "Yakan",
["ykg"] = "Yukaghir Utara",
["ykh"] = "Mongol Khamnigan",
["yki"] = "Yoke",
["ykk"] = "Yakaikeke",
["ykl"] = "Khlula",
["ykm"] = "Kap",
["ykn"] = "Kua-nsi",
["yko"] = "Yasa",
["ykr"] = "Yekora",
["ykt"] = "Kathu",
["yku"] = "Kuamasi",
["yky"] = "Yakoma",
["yla"] = "Yaul",
["ylb"] = "Yaleba",
["yle"] = "Yele",
["ylg"] = "Yelogu",
["yli"] = "Yali Angguruk",
["yll"] = "Yil",
["ylm"] = "Limi",
["yln"] = "Langnian Buyang",
["ylo"] = "Yi Naluo",
["ylr"] = "Yalarnnga",
["ylu"] = "Aribwaung",
["yly"] = "Nyâlayu",
["ymb"] = "Yambes",
["ymc"] = "Muji Selatan",
["ymd"] = "Muda",
["yme"] = "Yameo",
["ymg"] = "Yamongeri",
["ymh"] = "Mili",
["ymi"] = "Moji",
["ymk"] = "Makwe",
["yml"] = "Iamalele",
["ymm"] = "Maay",
["ymn"] = "Sunum",
["ymo"] = "Mon Yangum",
["ymp"] = "Yamap",
["ymq"] = "Muji Qila",
["ymr"] = "Malasar",
["yms"] = "Mysian",
["ymx"] = "Muji Utara",
["ymz"] = "Muzi",
["yna"] = "Aluo",
["ynd"] = "Yandruwandha",
["yne"] = "Lang'e",
["yng"] = "Yango",
["ynk"] = "Naukanski",
["ynl"] = "Yangulam",
["ynn"] = "Yana",
["yno"] = "Yong",
["yns"] = "Yansi",
["ynu"] = "Yahuna",
["yo"] = "Yoruba",
["yob"] = "Yoba",
["yog"] = "Yogad",
["yoi"] = "Yonaguni",
["yol"] = "Yola",
["yom"] = "Yombe",
["yon"] = "Yongkom",
["yox"] = "Yoron",
["yoy"] = "Yoy",
["ypa"] = "Phala",
["ypb"] = "Phowa Labo",
["ypg"] = "Phola",
["yph"] = "Phupha",
["ypk-pro"] = "Proto-Yupik",
["ypm"] = "Phuma",
["ypn"] = "Phowa Ani",
["ypo"] = "Alo Phola",
["ypp"] = "Phupa",
["ypz"] = "Phuza",
["yra"] = "Yerakai",
["yrb"] = "Yareba",
["yre"] = "Yaouré",
["yri"] = "Yarí",
["yrk"] = "Nenets Tundra",
["yrl"] = "Nheengatu",
["yrn"] = "Yerong",
["yro"] = "Yaroamë",
["yrw"] = "Yarawata",
["yry"] = "Yarluyandi",
["ysc"] = "Jassic",
["ysd"] = "Samatao",
["ysg"] = "Sonaga",
["ysl"] = "Isyarat Yugoslavia",
["ysn"] = "Sani",
["yso"] = "Nisi",
["ysp"] = "Lolopo Selatan",
["ysr"] = "Sirenik",
["yss"] = "Yessan-Mayo",
["ysy"] = "Sanie",
["yta"] = "Talu",
["ytl"] = "Tanglang",
["ytp"] = "Thopho",
["ytw"] = "Yout Wam",
["yty"] = "Yatay",
["yua"] = "Maya Yucatec",
["yub"] = "Yugambal",
["yuc"] = "Yuchi",
["yue"] = "Kanton",
["yuf"] = "Havasupai-Walapai-Yavapai",
["yug"] = "Yug",
["yui"] = "Yurutí",
["yuj"] = "Karkar-Yuri",
["yuk"] = "Yuki",
["yul"] = "Yulu",
["yum"] = "Yuma",
["yun"] = "Bena",
["yup"] = "Yukpa",
["yuq"] = "Yuqui",
["yur"] = "Yurok",
["yut"] = "Yopno",
["yuw"] = "Yau Finisterre",
["yux"] = "Yukaghir Selatan",
["yuy"] = "Yugur Timur",
["yuz"] = "Yuracare",
["yva"] = "Yawa",
["yvt"] = "Yavitero",
["ywa"] = "Kalou",
["ywg"] = "Yinhawangka",
["ywl"] = "Lalu Barat",
["ywn"] = "Yawanawa",
["ywq"] = "Nasu",
["ywr"] = "Yawuru",
["ywt"] = "Lalo Xishanba",
["ywu"] = "Nasu Wumeng",
["yww"] = "Yawarawarga",
["yxa"] = "Mayawali",
["yxg"] = "Yagara",
["yxl"] = "Yarli",
["yxm"] = "Yinwum",
["yxu"] = "Yuyu",
["yxy"] = "Yabula Yabula",
["yyu"] = "Yau Torricelli",
["yyz"] = "Ayizi",
["yzg"] = "E'ma Buyang",
["yzk"] = "Zokhuo",
["za"] = "Zhuang",
["zaa"] = "Zapotec Sierra de Juárez",
["zab"] = "Zapotec San Juan Guelavía",
["zac"] = "Zapotec Ocotlán",
["zad"] = "Zapotec Cajonos",
["zae"] = "Zapotec Yareni",
["zaf"] = "Zapotec Ayoquesco",
["zag"] = "Zaghawa",
["zah"] = "Zangwal",
["zai"] = "Zapotec Isthmus",
["zaj"] = "Zaramo",
["zak"] = "Zanaki",
["zal"] = "Zauzou",
["zam"] = "Zapotec Mahuatlán Tengah",
["zao"] = "Zapotec Ozolotepec",
["zap"] = "Zapotec",
["zaq"] = "Zapotec Aloápam",
["zar"] = "Zapotec Rincón",
["zas"] = "Zapotec Santo Domingo Albarradas",
["zat"] = "Zapotec Tabaa",
["zau"] = "Zangskari",
["zav"] = "Zapotec Yatzachi",
["zaw"] = "Zapotec Mitla",
["zax"] = "Zapotec Xadani",
["zay"] = "Zayse-Zergulla",
["zaz"] = "Zari",
["zbt"] = "Batui",
["zca"] = "Zapotec Coatecas Altas",
["zdj"] = "Comorian Ngazidja",
["zea"] = "Zealandic",
["zeg"] = "Zenag",
["zen"] = "Zenaga",
["zga"] = "Kinga",
["zgh"] = "Maroko Amazigh",
["zgr"] = "Magori",
["zh"] = "Tionghoa",
["zhb"] = "Zhaba",
["zhi"] = "Zhire",
["zhn"] = "Zhuang Nong",
["zhw"] = "Zhoa",
["zhx-min-pro"] = "Proto-Min",
["zhx-sht"] = "Tuhua Shaozhou",
["zhx-tai"] = "Taishan",
["zhx-teo"] = "Teochew",
["zia"] = "Zia",
["zib"] = "Isyarat Zimbabwe",
["zik"] = "Zimakani",
["zil"] = "Zialo",
["zim"] = "Mesme",
["zin"] = "Zinza",
["zir"] = "Ziriya",
["ziw"] = "Zigula",
["ziz"] = "Zizilivakan",
["zka"] = "Kaimbulawa",
["zkb"] = "Koibal",
["zkg"] = "Goguryeo",
["zkh"] = "Turkik Khorezmian",
["zkk"] = "Karankawa",
["zko"] = "Kott",
["zkp"] = "São Paulo Kaingáng",
["zkr"] = "Zakhring",
["zkt"] = "Khitan",
["zku"] = "Kaurna",
["zkv"] = "Krevinian",
["zkz"] = "Khazar",
["zle-ono"] = "Novgorod Kuna",
["zle-ort"] = "Ruthenia Kuna",
["zlw-ocs"] = "Ceko Kuna",
["zlw-opl"] = "Polandia Kuna",
["zlw-pom-pro"] = "Proto-Pomerania",
["zlw-slv"] = "Slovincian",
["zma"] = "Manda (Australia)",
["zmb"] = "Zimba",
["zmc"] = "Margany",
["zmd"] = "Maridan",
["zme"] = "Mangerr",
["zmf"] = "Mfinu",
["zmg"] = "Ke Marti",
["zmh"] = "Makolkol",
["zmi"] = "Malayu Negeri Sembilan",
["zmj"] = "Maridjabin",
["zmk"] = "Mandandanyi",
["zml"] = "Madngele",
["zmm"] = "Marimanindji",
["zmn"] = "Mbangwe",
["zmo"] = "Molo",
["zmp"] = "Mbuun",
["zmq"] = "Mituku",
["zmr"] = "Maranungku",
["zms"] = "Mbesa",
["zmt"] = "Maringarr",
["zmu"] = "Muruwari",
["zmv"] = "Mbariman-Gudhinma",
["zmw"] = "Mbo (Kongo)",
["zmx"] = "Bomitaba",
["zmy"] = "Mariyedi",
["zmz"] = "Mbandja",
["zna"] = "Gula Zan",
["zne"] = "Zande",
["zng"] = "Mang",
["znk"] = "Manangkari",
["zns"] = "Mangas",
["zoc"] = "Zoque Copainalá",
["zoh"] = "Zoque Chimalapa",
["zom"] = "Zou",
["zoo"] = "Zapotec Asunción Mixtepec",
["zoq"] = "Zoque Tabasco",
["zor"] = "Zoque Rayón",
["zos"] = "Zoque Francisco León",
["zpa"] = "Zapotec Lachiguiri",
["zpb"] = "Zapotec Yautepec",
["zpc"] = "Zapotec Choapan",
["zpd"] = "Zapotec Ixtlán Tenggara",
["zpe"] = "Zapotec Petapa",
["zpf"] = "Zapotec San Pedro Quiatoni",
["zpg"] = "Zapotec Guevea de Humboldt",
["zph"] = "Zapotec Totomachapan",
["zpi"] = "Zapotec Santa María Quiegolani",
["zpj"] = "Zapotec Quiavicuzas",
["zpk"] = "Zapotec Tlacolulita",
["zpl"] = "Zapotec Lachixío",
["zpm"] = "Zapotec Mixtepec",
["zpn"] = "Zapotec Santa Inés Yatzechi",
["zpo"] = "Zapotec Amatlán",
["zpp"] = "Zapotec El Alto",
["zpq"] = "Zapotec Zoogocho",
["zpr"] = "Zapotec Santiago Xanica",
["zps"] = "Zapotec Coatlán",
["zpt"] = "Zapotec San Vicente Coatlán",
["zpu"] = "Zapotec Yalálag",
["zpv"] = "Zapotec Chichicapan",
["zpw"] = "Zapotec Zaniza",
["zpx"] = "Zapotec San Baltazar Loxicha",
["zpy"] = "Zapotec Mazaltepec",
["zpz"] = "Zapotec Texmelucan",
["zra"] = "Kaya",
["zrg"] = "Mirgan",
["zrn"] = "Zirenkel",
["zro"] = "Záparo",
["zrs"] = "Mairasi",
["zsa"] = "Sarasira",
["zsk"] = "Kaskean",
["zsl"] = "Isyarat Zambia",
["zsr"] = "Zapotec Rincon Selatan",
["zsu"] = "Sukurum",
["zte"] = "Zapotec Elotepec",
["ztg"] = "Zapotec Xanaguía",
["ztl"] = "Zapotec Lapaguía-Guivini",
["ztm"] = "Zapotec San Agustín Mixtepec",
["ztn"] = "Zapotec Santa Catarina Albarradas",
["ztp"] = "Zapotec Loxicha",
["ztq"] = "Zapotec Quioquitani-Quierí",
["zts"] = "Zapotec Tilquiapan",
["ztt"] = "Zapotec Tejalapan",
["ztu"] = "Zapotec San Pablo Güilá",
["ztx"] = "Zapotec Zaachila",
["zty"] = "Zapotec Yatee",
["zu"] = "Zulu",
["zua"] = "Zeem",
["zuh"] = "Tokano",
["zum"] = "Kumzari",
["zun"] = "Zuni",
["zuy"] = "Zumaya",
["zwa"] = "Zay",
["zyp"] = "Zyphe",
["zza"] = "Zazaki",
["zzj"] = "Zhuang Zuojiang",
}
local langFamilies = {
["ine"] = true,
["map"] = true,
["poz"] = true,
["poz-mly"] = true
}
local protoLangs = {
["ine-pro"] = true,
["map-pro"] = true,
["poz-pro"] = true,
["poz-mly-pro"] = true
}
-- Interwiki table
local interwikis = {
aa = true, ab = true, af = true, ak = true, am = true, an = true, ang = true,
ar = true, as = true, ast = true, av = true, ay = true, az = true, bcl = true,
be = true, bew = true, bg = true, bh = true, bi = true, blk = true, ["id"] = true,
bm = true, bn = true, bo = true, br = true, bs = true, btm = true, ca = true,
ch = true, chr = true, ckb = true, co = true, cr = true, cs = true, csb = true,
cy = true, da = true, de = true, diq = true, dv = true, dz = true, el = true,
en = true, eo = true, es = true, et = true, eu = true, fa = true, fi = true,
fj = true, fo = true, fr = true, fy = true, ga = true, gd = true, gl = true,
gn = true, gom = true, gor = true, gu = true, guw = true, gv = true, ha = true,
he = true, hi = true, hif = true, hr = true, hsb = true, hu = true, hy = true,
ia = true, ie = true, ig = true, ik = true, ["io"] = true, ["is"] = true, it = true,
iu = true, ja = true, jbo = true, jv = true, ka = true, kaa = true, kbd = true,
kcg = true, kk = true, kl = true, km = true, kn = true, ko = true, ks = true,
ku = true, kw = true, ky = true, la = true, lb = true, li = true, lmo = true,
ln = true, lo = true, lt = true, lv = true, mad = true, mg = true, mh = true,
mi = true, ["min"] = true, mk = true, ml = true, mn = true, mni = true, mnw = true,
mr = true, ms = true, mt = true, my = true, na = true, nah = true, nds = true,
ne = true, nia = true, nl = true, nn = true, no = true, oc = true, om = true,
["or"] = true, pa = true, pi = true, pl = true, pnb = true, ps = true, pt = true,
qu = true, rm = true, rn = true, ro = true, ru = true, rw = true, sa = true,
sat = true, sc = true, scn = true, sd = true, sg = true, sh = true, shn = true,
shy = true, si = true, sk = true, skr = true, sl = true, sm = true, sn = true,
so = true, sq = true, sr = true, ss = true, st = true, su = true, sv = true,
sw = true, ta = true, tcy = true, te = true, tg = true, th = true, ti = true,
tk = true, tl = true, tn = true, to = true, tpi = true, tr = true, ts = true,
tt = true, tw = true, ug = true, uk = true, ur = true, uz = true, vec = true,
vi = true, vo = true, wa = true, wo = true, xh = true, yi = true, yo = true,
za = true, zh = true, zu = true,
-- Mapped codes
mly = "ms", msa = "ms", msi = "ms", zlm = "ms", zsm = "ms"
}
-- Return interwiki link
function p.getInterwikiLink(lang, title)
local targetLang = interwikis[lang]
if targetLang == nil then
return lang
elseif targetLang == true then
return string.format("[[:%s:%s|%s]]", lang, title, lang)
else
return string.format("[[:%s:%s|%s]]", targetLang, title, lang)
end
end
-- Get full language name (returns nil if invalid)
function p.getLangName(frame)
local args = frame.args
local code = mw.text.trim(args[1] or "")
local nocap = args.nocap or ""
local name = langNames[code]
if not name then return nil end
local prefix = ""
if langFamilies[code] then
prefix = "Rumpun basa "
elseif code ~= "mul" then
prefix = "Basa "
end
local fullName = prefix .. name
if nocap == "1" and mw.ustring.len(fullName) > 0 then
local first = mw.ustring.sub(fullName, 1, 1)
local rest = mw.ustring.sub(fullName, 2)
fullName = mw.ustring.lower(first) .. rest
end
return fullName
end
function p.getLangNameByCode(code, nocap)
code = mw.text.trim(code or "")
nocap = nocap or ""
local name = langNames[code]
if not name then return nil end
local prefix = ""
if langFamilies[code] then
prefix = "Rumpun basa "
elseif code ~= "mul" then
prefix = "Basa "
end
local fullName = prefix .. name
if nocap == "1" and mw.ustring.len(fullName) > 0 then
local first = mw.ustring.sub(fullName, 1, 1)
local rest = mw.ustring.sub(fullName, 2)
fullName = mw.ustring.lower(first) .. rest
end
return fullName
end
-- Get language code (returns nil if invalid)
function p.getLangCode(frame)
local code = mw.text.trim((frame.args and frame.args[1]) or "")
if langNames[code] then
return code
else
return nil
end
end
function p.getLangCodeByCode(code)
code = mw.text.trim(code or "")
if langNames[code] then
return code
end
return nil
end
-- Expose tables
p.langFamilies = langFamilies
p.protoLangs = protoLangs
p.langNames = langNames
p.interwikis = interwikis
return p
n3y6d2iqnalww90rubquflusu872ao3
Modul:families
828
6772
26509
2025-11-08T17:37:18Z
id>Ekirahardian
0
Perbarui dari en.wikipedia.org
26509
Scribunto
text/plain
local export = {}
local families_by_name_module = "Module:families/canonical names"
local families_data_module = "Module:families/data"
local json_module = "Module:JSON"
local language_like_module = "Module:language-like"
local languages_module = "Module:languages"
local load_module = "Module:load"
local table_module = "Module:table"
local get_by_code -- Defined below.
local gmatch = string.gmatch
local insert = table.insert
local ipairs = ipairs
local make_object -- Defined below.
local pairs = pairs
local require = require
local setmetatable = setmetatable
local type = type
--[==[
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 category_name_has_suffix(...)
category_name_has_suffix = require(language_like_module).categoryNameHasSuffix
return category_name_has_suffix(...)
end
local function category_name_to_code(...)
category_name_to_code = require(language_like_module).categoryNameToCode
return category_name_to_code(...)
end
local function deep_copy(...)
deep_copy = require(table_module).deepCopy
return deep_copy(...)
end
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
end
local function keys_to_list(...)
keys_to_list = require(table_module).keysToList
return keys_to_list(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function make_lang_object(...)
make_lang_object = require(languages_module).makeObject
return make_lang_object(...)
end
local function to_json(...)
to_json = require(json_module).toJSON
return to_json(...)
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 families_by_name
local function get_families_by_name()
families_by_name, get_families_by_name = load_data(families_by_name_module), nil
return families_by_name
end
local families_data
local function get_families_data()
families_data, get_families_data = load_data(families_data_module), nil
return families_data
end
local families_suffixes
local function get_families_suffixes()
families_suffixes, get_families_suffixes = {
"languages",
"lects"
}, nil
return families_suffixes
end
local Family = {}
Family.__index = Family
--[==[
Return the family code of the family, e.g. {"ine"} for the Indo-European languages.
]==]
function Family:getCode()
return self._code
end
--[==[
Return the canonical name of the family. This is the name used to represent that language family on Wiktionary,
and is guaranteed to be unique to that family alone. Example: {"Indo-European"} for the Indo-European languages.
]==]
function Family:getCanonicalName()
local name = self._name
if name == nil then
name = self._data[1]
self._name = name
end
return name
end
--[==[
Return the display form of the family. For families, this is the same as the value returned by
{getCategoryName("nocap")}, i.e. it reads <code>"<var>name</var> languages"</code> (e.g.
{"Indo-Iranian languages"}). For full and etymology-only languages, this is the same as the canonical name, and
for scripts, it reads <code>"<var>name</var> script"</code> (e.g. {"Arabic script"}). The displayed text used in
{makeCategoryLink()} is always the same as the display form.
]==]
function Family:getDisplayForm()
return self:getCategoryName("nocap")
end
function Family:getAliases()
Family.getAliases = require(language_like_module).getAliases
return self:getAliases()
end
function Family:getVarieties(flatten)
Family.getVarieties = require(language_like_module).getVarieties
return self:getVarieties(flatten)
end
function Family:getOtherNames()
Family.getOtherNames = require(language_like_module).getOtherNames
return self:getOtherNames()
end
function Family:getAllNames()
Family.getAllNames = require(language_like_module).getAllNames
return self:getAllNames()
end
--[==[Returns a table of types as a lookup table (with the types as keys).
The possible types are
* {family}: This object is a family.
* {full}: This object is a "full" family. This includes all families but a couple of etymology-only
families for Old and Middle Iranian languages.
* {etymology-only}: This object is an etymology-only family, similar to etymology-only languages. There
are currently only two such families, for Old Iranian languages and Middle Iranian
languages (which do not represent proper clades and have no proto-languages, hence
cannot be full families).
]==]
function Family:getTypes()
local types = self._types
if types == nil then
types = {family = true}
if self:getFullCode() == self:getCode() then
types.full = true
else
types["etymology-only"] = true
end
local rawtypes = self._data.type
if rawtypes then
for t in gmatch(rawtypes, "[^,]+") do
types[t] = true
end
end
self._types = types
end
return types
end
--[==[Given a list of types as strings, returns true if the family has all of them.]==]
function Family:hasType(...)
Family.hasType = require(language_like_module).hasType
return self:hasType(...)
end
--[==[Returns a {Family} object for the superfamily that the family belongs to.]==]
function Family:getFamily()
if self._familyObject == nil then
local familyCode = self:getFamilyCode()
if familyCode then
self._familyObject = get_by_code(familyCode)
else
self._familyObject = false
end
end
return self._familyObject or nil
end
--[==[Returns the code of the family's superfamily.]==]
function Family:getFamilyCode()
if not self._familyCode then
self._familyCode = self._data[3]
end
return self._familyCode
end
--[==[Returns the canonical name of the family's superfamily.]==]
function Family:getFamilyName()
if self._familyName == nil then
local family = self:getFamily()
if family then
self._familyName = family:getCanonicalName()
else
self._familyName = false
end
end
return self._familyName or nil
end
--[==[Check whether the family belongs to {superfamily} (which can be a family code or object), and returns a boolean. If more than one is given, returns {true} if the family belongs to any of them. A family is '''not''' considered to belong to itself.]==]
function Family:inFamily(...)
for _, superfamily in ipairs{...} do
if type(superfamily) == "table" then
superfamily = superfamily:getCode()
end
local family, code = self:getFamily()
while family do
code = family:getCode()
if code == superfamily then
return true
end
family = family:getFamily()
-- If family is parent to itself, return false.
if family and family:getCode() == code then
return false
end
end
return false
end
end
function Family:getParent()
if self._parentObject == nil then
local parentCode = self:getParentCode()
if parentCode then
self._parentObject = get_lang(parentCode, nil, true, true)
else
self._parentObject = false
end
end
return self._parentObject or nil
end
function Family:getParentCode()
if not self._parentCode then
self._parentCode = self._data.parent
end
return self._parentCode
end
function Family:getParentName()
if self._parentName == nil then
local parent = self:getParent()
if parent then
self._parentName = parent:getCanonicalName()
else
self._parentName = false
end
end
return self._parentName or nil
end
function Family:getParentChain()
if not self._parentChain then
self._parentChain = {}
local parent = self:getParent()
while parent do
insert(self._parentChain, parent)
parent = parent:getParent()
end
end
return self._parentChain
end
function Family:hasParent(...)
--checkObject("family", nil, ...)
for _, other_family in ipairs{...} do
for _, parent in ipairs(self:getParentChain()) do
if type(other_family) == "string" then
if other_family == parent:getCode() then return true end
else
if other_family:getCode() == parent:getCode() then return true end
end
end
end
return false
end
--[==[
If the family is etymology-only, this iterates through its parents until a full family is found, and the
corresponding object is returned. If the family is a full family, then it simply returns itself.
]==]
function Family:getFull()
if not self._fullObject then
local fullCode = self:getFullCode()
if fullCode ~= self:getCode() then
self._fullObject = get_lang(fullCode, nil, nil, true)
else
self._fullObject = self
end
end
return self._fullObject
end
--[==[
If the family is etymology-only, this iterates through its parents until a full family is found, and the
corresponding code is returned. If the family is a full family, then it simply returns the family code.
]==]
function Family:getFullCode()
return self._fullCode or self:getCode()
end
--[==[
If the family is etymology-only, this iterates through its parents until a full family is found, and the
corresponding canonical name is returned. If the family is a full family, then it simply returns the canonical name
of the family.
]==]
function Family:getFullName()
if self._fullName == nil then
local full = self:getFull()
if full then
self._fullName = full:getCanonicalName()
else
self._fullName = false
end
end
return self._fullName or nil
end
--[==[
Return a {Language} object (see [[Module:languages]]) for the proto-language of this family, if one exists.
Otherwise, return {nil}.
]==]
function Family:getProtoLanguage()
if self._protoLanguageObject == nil then
self._protoLanguageObject = get_lang(self._data.protoLanguage or self:getCode() .. "-pro", nil, true) or false
end
return self._protoLanguageObject or nil
end
function Family:getProtoLanguageCode()
if self._protoLanguageCode == nil then
local protoLanguage = self:getProtoLanguage()
self._protoLanguageCode = protoLanguage and protoLanguage:getCode() or false
end
return self._protoLanguageCode or nil
end
function Family:getProtoLanguageName()
if not self._protoLanguageName then
self._protoLanguageName = self:getProtoLanguage():getCanonicalName()
end
return self._protoLanguageName
end
function Family:hasAncestor(...)
-- Go up the family tree until a protolanguage is found.
local family = self
local protolang = family:getProtoLanguage()
while not protolang do
family = family:getFamily()
protolang = family:getProtoLanguage()
-- Return false if the family is its own family, to avoid an infinite loop.
if family:getFamilyCode() == family:getCode() then
return false
end
end
-- If the protolanguage is not in the family, it must therefore be ancestral to it. Check if it is a match.
for _, otherlang in ipairs{...} do
if (
type(otherlang) == "string" and protolang:getCode() == otherlang or
type(otherlang) == "table" and protolang:getCode() == otherlang:getCode()
) and not protolang:inFamily(self) then
return true
end
end
-- If not, check the protolanguage's ancestry.
return protolang:hasAncestor(...)
end
local function fetch_descendants(self, format)
local 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")
local descendants = {}
-- Iterate over all three datasets.
for _, data in ipairs{languages, etymology_languages, families} do
for code in pairs(data) do
local lang = get_lang(code, nil, true, true)
if lang:inFamily(self) then
if format == "object" then
insert(descendants, lang)
elseif format == "code" then
insert(descendants, code)
elseif format == "name" then
insert(descendants, lang:getCanonicalName())
end
end
end
end
return descendants
end
function Family:getDescendants()
if not self._descendantObjects then
self._descendantObjects = fetch_descendants(self, "object")
end
return self._descendantObjects
end
function Family:getDescendantCodes()
if not self._descendantCodes then
self._descendantCodes = fetch_descendants(self, "code")
end
return self._descendantCodes
end
function Family:getDescendantNames()
if not self._descendantNames then
self._descendantNames = fetch_descendants(self, "name")
end
return self._descendantNames
end
function Family:hasDescendant(...)
for _, lang in ipairs{...} do
if type(lang) == "string" then
lang = get_lang(lang, nil, true)
end
if lang:inFamily(self) then
return true
end
end
return false
end
--[==[
Return the name of the main category of that family. Example: {"Germanic languages"} for the Germanic languages,
whose category is at [[:Category:Germanic languages]].
Unless optional argument `nocap` is given, the family name at the beginning of the returned value will be
capitalized. This capitalization is correct for category names, but not if the family name is lowercase and
the returned value of this function is used in the middle of a sentence. (For example, the pseudo-family with
the code {qfa-mix} has the name {"mixed"}, which should remain lowercase when used as part of the category name
[[:Category:Terms derived from mixed languages]] but should be capitalized in [[:Category:Mixed languages]].)
If you are considering using {getCategoryName("nocap")}, use {getDisplayForm()} instead.
]==]
function Family:getCategoryName(nocap)
local name = self._data[1]
if category_name_has_suffix(name, families_suffixes or get_families_suffixes()) then
name = name .. " languages"
end
if not nocap then
name = mw.getContentLanguage():ucfirst(name)
end
return name
end
function Family:makeCategoryLink()
return "[[:Category:" .. self:getCategoryName() .. "|" .. self:getDisplayForm() .. "]]"
end
--[==[Returns the Wikidata item id for the family or <code>nil</code>. This corresponds to the the second field in the data modules.]==]
function Family:getWikidataItem()
Family.getWikidataItem = require(language_like_module).getWikidataItem
return self:getWikidataItem()
end
--[==[
Returns the name of the Wikipedia article for the family. `project` specifies the language and project to retrieve
the article from, defaulting to {"enwiki"} for the English Wikipedia. Normally if specified it should be the project
code for a specific-language Wikipedia e.g. "zhwiki" for the Chinese Wikipedia, but it can be any project, including
non-Wikipedia ones. If the project is the English Wikipedia and the property {wikipedia_article} is present in the data
module it will be used first. In all other cases, a sitelink will be generated from {:getWikidataItem} (if set). The
resulting value (or lack of value) is cached so that subsequent calls are fast. If no value could be determined, and
`noCategoryFallback` is {false}, {:getCategoryName} is used as fallback; otherwise, {nil} is returned. Note that if
`noCategoryFallback` is {nil} or omitted, it defaults to {false} if the project is the English Wikipedia, otherwise
to {true}. In other words, under normal circumstances, if the English Wikipedia article couldn't be retrieved, the
return value will fall back to a link to the family's category, but this won't normally happen for any other project.
]==]
function Family:getWikipediaArticle(noCategoryFallback, project)
Family.getWikipediaArticle = require(language_like_module).getWikipediaArticle
return self:getWikipediaArticle(noCategoryFallback, project)
end
function Family:makeWikipediaLink()
return "[[w:" .. self:getWikipediaArticle() .. "|" .. self:getCanonicalName() .. "]]"
end
--[==[Returns the name of the Wikimedia Commons category page for the family.]==]
function Family:getCommonsCategory()
Family.getCommonsCategory = require(language_like_module).getCommonsCategory
return self:getCommonsCategory()
end
function Family:toJSON(opts)
local ret = {
canonicalName = self:getCanonicalName(),
categoryName = self:getCategoryName("nocap"),
code = self:getCode(),
parent = self:getParentCode(),
full = self:getFullCode(),
family = self:getFamilyCode(),
protoLanguage = self:getProtoLanguageCode(),
aliases = self:getAliases(),
varieties = self:getVarieties(),
otherNames = self:getOtherNames(),
type = keys_to_list(self:getTypes()),
wikidataItem = self:getWikidataItem(),
wikipediaArticle = self:getWikipediaArticle(true),
}
-- Use `deep_copy` when returning a table, so that there are no editing restrictions imposed by `mw.loadData`.
return opts and opts.lua_table and deep_copy(ret) or to_json(ret, opts)
end
function Family:getData()
return self._data
end
function export.makeObject(code, data)
local data_type = type(data)
if data_type ~= "table" then
error(("bad argument #2 to 'makeObject' (table expected, got %s)"):format(data_type))
end
return setmetatable({_data = data, _code = code, _fullCode = code}, Family)
end
make_object = export.makeObject
--[==[
Finds the family whose code matches the one provided. If it exists, it returns a {Family} object representing the
family. Otherwise, it returns {nil}.]==]
function export.getByCode(code)
local data = (families_data or get_families_data())[code]
if data == nil then
return nil
elseif data.parent == nil then
return make_object(code, data)
end
return make_lang_object(code, data)
end
get_by_code = export.getByCode
--[==[
Look for the family whose canonical name (the name used to represent that family on Wiktionary) matches the one
provided. If it exists, it returns a {Family} object representing the family. Otherwise, it returns {nil}. The
canonical name of families should always be unique (it is an error for two families on Wiktionary to share the same
canonical name), so this is guaranteed to give at most one result.]==]
function export.getByCanonicalName(name)
if name == nil then
return nil
end
local code = (families_by_name or get_families_by_name())[name]
if code == nil then
return nil
end
return get_by_code(code)
end
--[==[
Look for the family whose category name (the name used in categories for that family) matches the one provided.
If it exists, it returns a {Family} object representing the family. Otherwise, it returns {nil}. In almost all cases,
the category name for a family is its canonical name plus the word "languages", e.g. "Indo-European" has the category
name "Indo-European languages". Where a canonical name ends with "languages" or "lects", the category name is identical
to the canonical name.]==]
function export.getByCategoryName(name)
if name == nil then
return nil
end
local code = category_name_to_code(
name,
" languages",
families_by_name or get_families_by_name(),
families_suffixes or get_families_suffixes()
)
if code == nil then
return nil
end
return get_by_code(code)
end
return export
fghmplf4bs9ps1pal2p2xqhxeaofioy
26510
17459
2026-07-07T09:55:57Z
Sibiru45
115
1 ralatan matan [[:id:Modul:families]]
17459
Scribunto
text/plain
local export = {}
local families_by_name_module = "Module:families/canonical names"
local families_data_module = "Module:families/data"
local json_module = "Module:JSON"
local language_like_module = "Module:language-like"
local languages_module = "Module:languages"
local load_module = "Module:load"
local table_module = "Module:table"
local get_by_code -- Defined below.
local gmatch = string.gmatch
local insert = table.insert
local ipairs = ipairs
local make_object -- Defined below.
local pairs = pairs
local require = require
local setmetatable = setmetatable
local type = type
--[==[
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 category_name_has_suffix(...)
category_name_has_suffix = require(language_like_module).categoryNameHasSuffix
return category_name_has_suffix(...)
end
local function category_name_to_code(...)
category_name_to_code = require(language_like_module).categoryNameToCode
return category_name_to_code(...)
end
local function deep_copy(...)
deep_copy = require(table_module).deepCopy
return deep_copy(...)
end
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
end
local function keys_to_list(...)
keys_to_list = require(table_module).keysToList
return keys_to_list(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function make_lang_object(...)
make_lang_object = require(languages_module).makeObject
return make_lang_object(...)
end
local function to_json(...)
to_json = require(json_module).toJSON
return to_json(...)
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 families_by_name
local function get_families_by_name()
families_by_name, get_families_by_name = load_data(families_by_name_module), nil
return families_by_name
end
local families_data
local function get_families_data()
families_data, get_families_data = load_data(families_data_module), nil
return families_data
end
local families_suffixes
local function get_families_suffixes()
families_suffixes, get_families_suffixes = {
"languages",
"lects"
}, nil
return families_suffixes
end
local Family = {}
Family.__index = Family
--[==[
Return the family code of the family, e.g. {"ine"} for the Indo-European languages.
]==]
function Family:getCode()
return self._code
end
--[==[
Return the canonical name of the family. This is the name used to represent that language family on Wiktionary,
and is guaranteed to be unique to that family alone. Example: {"Indo-European"} for the Indo-European languages.
]==]
function Family:getCanonicalName()
local name = self._name
if name == nil then
name = self._data[1]
self._name = name
end
return name
end
--[==[
Return the display form of the family. For families, this is the same as the value returned by
{getCategoryName("nocap")}, i.e. it reads <code>"<var>name</var> languages"</code> (e.g.
{"Indo-Iranian languages"}). For full and etymology-only languages, this is the same as the canonical name, and
for scripts, it reads <code>"<var>name</var> script"</code> (e.g. {"Arabic script"}). The displayed text used in
{makeCategoryLink()} is always the same as the display form.
]==]
function Family:getDisplayForm()
return self:getCategoryName("nocap")
end
function Family:getAliases()
Family.getAliases = require(language_like_module).getAliases
return self:getAliases()
end
function Family:getVarieties(flatten)
Family.getVarieties = require(language_like_module).getVarieties
return self:getVarieties(flatten)
end
function Family:getOtherNames()
Family.getOtherNames = require(language_like_module).getOtherNames
return self:getOtherNames()
end
function Family:getAllNames()
Family.getAllNames = require(language_like_module).getAllNames
return self:getAllNames()
end
--[==[Returns a table of types as a lookup table (with the types as keys).
The possible types are
* {family}: This object is a family.
* {full}: This object is a "full" family. This includes all families but a couple of etymology-only
families for Old and Middle Iranian languages.
* {etymology-only}: This object is an etymology-only family, similar to etymology-only languages. There
are currently only two such families, for Old Iranian languages and Middle Iranian
languages (which do not represent proper clades and have no proto-languages, hence
cannot be full families).
]==]
function Family:getTypes()
local types = self._types
if types == nil then
types = {family = true}
if self:getFullCode() == self:getCode() then
types.full = true
else
types["etymology-only"] = true
end
local rawtypes = self._data.type
if rawtypes then
for t in gmatch(rawtypes, "[^,]+") do
types[t] = true
end
end
self._types = types
end
return types
end
--[==[Given a list of types as strings, returns true if the family has all of them.]==]
function Family:hasType(...)
Family.hasType = require(language_like_module).hasType
return self:hasType(...)
end
--[==[Returns a {Family} object for the superfamily that the family belongs to.]==]
function Family:getFamily()
if self._familyObject == nil then
local familyCode = self:getFamilyCode()
if familyCode then
self._familyObject = get_by_code(familyCode)
else
self._familyObject = false
end
end
return self._familyObject or nil
end
--[==[Returns the code of the family's superfamily.]==]
function Family:getFamilyCode()
if not self._familyCode then
self._familyCode = self._data[3]
end
return self._familyCode
end
--[==[Returns the canonical name of the family's superfamily.]==]
function Family:getFamilyName()
if self._familyName == nil then
local family = self:getFamily()
if family then
self._familyName = family:getCanonicalName()
else
self._familyName = false
end
end
return self._familyName or nil
end
--[==[Check whether the family belongs to {superfamily} (which can be a family code or object), and returns a boolean. If more than one is given, returns {true} if the family belongs to any of them. A family is '''not''' considered to belong to itself.]==]
function Family:inFamily(...)
for _, superfamily in ipairs{...} do
if type(superfamily) == "table" then
superfamily = superfamily:getCode()
end
local family, code = self:getFamily()
while family do
code = family:getCode()
if code == superfamily then
return true
end
family = family:getFamily()
-- If family is parent to itself, return false.
if family and family:getCode() == code then
return false
end
end
return false
end
end
function Family:getParent()
if self._parentObject == nil then
local parentCode = self:getParentCode()
if parentCode then
self._parentObject = get_lang(parentCode, nil, true, true)
else
self._parentObject = false
end
end
return self._parentObject or nil
end
function Family:getParentCode()
if not self._parentCode then
self._parentCode = self._data.parent
end
return self._parentCode
end
function Family:getParentName()
if self._parentName == nil then
local parent = self:getParent()
if parent then
self._parentName = parent:getCanonicalName()
else
self._parentName = false
end
end
return self._parentName or nil
end
function Family:getParentChain()
if not self._parentChain then
self._parentChain = {}
local parent = self:getParent()
while parent do
insert(self._parentChain, parent)
parent = parent:getParent()
end
end
return self._parentChain
end
function Family:hasParent(...)
--checkObject("family", nil, ...)
for _, other_family in ipairs{...} do
for _, parent in ipairs(self:getParentChain()) do
if type(other_family) == "string" then
if other_family == parent:getCode() then return true end
else
if other_family:getCode() == parent:getCode() then return true end
end
end
end
return false
end
--[==[
If the family is etymology-only, this iterates through its parents until a full family is found, and the
corresponding object is returned. If the family is a full family, then it simply returns itself.
]==]
function Family:getFull()
if not self._fullObject then
local fullCode = self:getFullCode()
if fullCode ~= self:getCode() then
self._fullObject = get_lang(fullCode, nil, nil, true)
else
self._fullObject = self
end
end
return self._fullObject
end
--[==[
If the family is etymology-only, this iterates through its parents until a full family is found, and the
corresponding code is returned. If the family is a full family, then it simply returns the family code.
]==]
function Family:getFullCode()
return self._fullCode or self:getCode()
end
--[==[
If the family is etymology-only, this iterates through its parents until a full family is found, and the
corresponding canonical name is returned. If the family is a full family, then it simply returns the canonical name
of the family.
]==]
function Family:getFullName()
if self._fullName == nil then
local full = self:getFull()
if full then
self._fullName = full:getCanonicalName()
else
self._fullName = false
end
end
return self._fullName or nil
end
--[==[
Return a {Language} object (see [[Module:languages]]) for the proto-language of this family, if one exists.
Otherwise, return {nil}.
]==]
function Family:getProtoLanguage()
if self._protoLanguageObject == nil then
self._protoLanguageObject = get_lang(self._data.protoLanguage or self:getCode() .. "-pro", nil, true) or false
end
return self._protoLanguageObject or nil
end
function Family:getProtoLanguageCode()
if self._protoLanguageCode == nil then
local protoLanguage = self:getProtoLanguage()
self._protoLanguageCode = protoLanguage and protoLanguage:getCode() or false
end
return self._protoLanguageCode or nil
end
function Family:getProtoLanguageName()
if not self._protoLanguageName then
self._protoLanguageName = self:getProtoLanguage():getCanonicalName()
end
return self._protoLanguageName
end
function Family:hasAncestor(...)
-- Go up the family tree until a protolanguage is found.
local family = self
local protolang = family:getProtoLanguage()
while not protolang do
family = family:getFamily()
protolang = family:getProtoLanguage()
-- Return false if the family is its own family, to avoid an infinite loop.
if family:getFamilyCode() == family:getCode() then
return false
end
end
-- If the protolanguage is not in the family, it must therefore be ancestral to it. Check if it is a match.
for _, otherlang in ipairs{...} do
if (
type(otherlang) == "string" and protolang:getCode() == otherlang or
type(otherlang) == "table" and protolang:getCode() == otherlang:getCode()
) and not protolang:inFamily(self) then
return true
end
end
-- If not, check the protolanguage's ancestry.
return protolang:hasAncestor(...)
end
local function fetch_descendants(self, format)
local 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")
local descendants = {}
-- Iterate over all three datasets.
for _, data in ipairs{languages, etymology_languages, families} do
for code in pairs(data) do
local lang = get_lang(code, nil, true, true)
if lang:inFamily(self) then
if format == "object" then
insert(descendants, lang)
elseif format == "code" then
insert(descendants, code)
elseif format == "name" then
insert(descendants, lang:getCanonicalName())
end
end
end
end
return descendants
end
function Family:getDescendants()
if not self._descendantObjects then
self._descendantObjects = fetch_descendants(self, "object")
end
return self._descendantObjects
end
function Family:getDescendantCodes()
if not self._descendantCodes then
self._descendantCodes = fetch_descendants(self, "code")
end
return self._descendantCodes
end
function Family:getDescendantNames()
if not self._descendantNames then
self._descendantNames = fetch_descendants(self, "name")
end
return self._descendantNames
end
function Family:hasDescendant(...)
for _, lang in ipairs{...} do
if type(lang) == "string" then
lang = get_lang(lang, nil, true)
end
if lang:inFamily(self) then
return true
end
end
return false
end
--[==[
Return the name of the main category of that family. Example: {"Germanic languages"} for the Germanic languages,
whose category is at [[:Category:Germanic languages]].
Unless optional argument `nocap` is given, the family name at the beginning of the returned value will be
capitalized. This capitalization is correct for category names, but not if the family name is lowercase and
the returned value of this function is used in the middle of a sentence. (For example, the pseudo-family with
the code {qfa-mix} has the name {"mixed"}, which should remain lowercase when used as part of the category name
[[:Category:Terms derived from mixed languages]] but should be capitalized in [[:Category:Mixed languages]].)
If you are considering using {getCategoryName("nocap")}, use {getDisplayForm()} instead.
]==]
function Family:getCategoryName(nocap)
local name = self._data[1]
if category_name_has_suffix(name, families_suffixes or get_families_suffixes()) then
name = name .. " languages"
end
if not nocap then
name = mw.getContentLanguage():ucfirst(name)
end
return name
end
function Family:makeCategoryLink()
return "[[:Category:" .. self:getCategoryName() .. "|" .. self:getDisplayForm() .. "]]"
end
--[==[Returns the Wikidata item id for the family or <code>nil</code>. This corresponds to the the second field in the data modules.]==]
function Family:getWikidataItem()
Family.getWikidataItem = require(language_like_module).getWikidataItem
return self:getWikidataItem()
end
--[==[
Returns the name of the Wikipedia article for the family. `project` specifies the language and project to retrieve
the article from, defaulting to {"enwiki"} for the English Wikipedia. Normally if specified it should be the project
code for a specific-language Wikipedia e.g. "zhwiki" for the Chinese Wikipedia, but it can be any project, including
non-Wikipedia ones. If the project is the English Wikipedia and the property {wikipedia_article} is present in the data
module it will be used first. In all other cases, a sitelink will be generated from {:getWikidataItem} (if set). The
resulting value (or lack of value) is cached so that subsequent calls are fast. If no value could be determined, and
`noCategoryFallback` is {false}, {:getCategoryName} is used as fallback; otherwise, {nil} is returned. Note that if
`noCategoryFallback` is {nil} or omitted, it defaults to {false} if the project is the English Wikipedia, otherwise
to {true}. In other words, under normal circumstances, if the English Wikipedia article couldn't be retrieved, the
return value will fall back to a link to the family's category, but this won't normally happen for any other project.
]==]
function Family:getWikipediaArticle(noCategoryFallback, project)
Family.getWikipediaArticle = require(language_like_module).getWikipediaArticle
return self:getWikipediaArticle(noCategoryFallback, project)
end
function Family:makeWikipediaLink()
return "[[w:" .. self:getWikipediaArticle() .. "|" .. self:getCanonicalName() .. "]]"
end
--[==[Returns the name of the Wikimedia Commons category page for the family.]==]
function Family:getCommonsCategory()
Family.getCommonsCategory = require(language_like_module).getCommonsCategory
return self:getCommonsCategory()
end
function Family:toJSON(opts)
local ret = {
canonicalName = self:getCanonicalName(),
categoryName = self:getCategoryName("nocap"),
code = self:getCode(),
parent = self:getParentCode(),
full = self:getFullCode(),
family = self:getFamilyCode(),
protoLanguage = self:getProtoLanguageCode(),
aliases = self:getAliases(),
varieties = self:getVarieties(),
otherNames = self:getOtherNames(),
type = keys_to_list(self:getTypes()),
wikidataItem = self:getWikidataItem(),
wikipediaArticle = self:getWikipediaArticle(true),
}
-- Use `deep_copy` when returning a table, so that there are no editing restrictions imposed by `mw.loadData`.
return opts and opts.lua_table and deep_copy(ret) or to_json(ret, opts)
end
function Family:getData()
return self._data
end
function export.makeObject(code, data)
local data_type = type(data)
if data_type ~= "table" then
error(("bad argument #2 to 'makeObject' (table expected, got %s)"):format(data_type))
end
return setmetatable({_data = data, _code = code, _fullCode = code}, Family)
end
make_object = export.makeObject
--[==[
Finds the family whose code matches the one provided. If it exists, it returns a {Family} object representing the
family. Otherwise, it returns {nil}.]==]
function export.getByCode(code)
local data = (families_data or get_families_data())[code]
if data == nil then
return nil
elseif data.parent == nil then
return make_object(code, data)
end
return make_lang_object(code, data)
end
get_by_code = export.getByCode
--[==[
Look for the family whose canonical name (the name used to represent that family on Wiktionary) matches the one
provided. If it exists, it returns a {Family} object representing the family. Otherwise, it returns {nil}. The
canonical name of families should always be unique (it is an error for two families on Wiktionary to share the same
canonical name), so this is guaranteed to give at most one result.]==]
function export.getByCanonicalName(name)
if name == nil then
return nil
end
local code = (families_by_name or get_families_by_name())[name]
if code == nil then
return nil
end
return get_by_code(code)
end
--[==[
Look for the family whose category name (the name used in categories for that family) matches the one provided.
If it exists, it returns a {Family} object representing the family. Otherwise, it returns {nil}. In almost all cases,
the category name for a family is its canonical name plus the word "languages", e.g. "Indo-European" has the category
name "Indo-European languages". Where a canonical name ends with "languages" or "lects", the category name is identical
to the canonical name.]==]
function export.getByCategoryName(name)
if name == nil then
return nil
end
local code = category_name_to_code(
name,
" languages",
families_by_name or get_families_by_name(),
families_suffixes or get_families_suffixes()
)
if code == nil then
return nil
end
return get_by_code(code)
end
return export
fghmplf4bs9ps1pal2p2xqhxeaofioy
Modul:aksara
828
6778
26529
2025-11-18T08:00:56Z
id>Swarabakti
0
Swarabakti memindahkan halaman [[Modul:Sandbox/Swarabakti/scripts]] ke [[Modul:aksara]]
26529
Scribunto
text/plain
local M = {}
local function in_ranges(cp, ranges)
for i = 1, #ranges do
local r = ranges[i]
if cp >= r[1] and cp <= r[2] then
return true
end
end
return false
end
-- Ignore combining diacritical marks
local IGNORE_COMBINING = {
{0x0300, 0x036F}, {0x1AB0, 0x1AFF}, {0x1DC0, 0x1DFF},
{0x20D0, 0x20FF}, {0xFE20, 0xFE2F}
}
local function is_ignorable(cp)
return in_ranges(cp, IGNORE_COMBINING)
end
-- Script data
M.scripts = {
Arab = { name = "Arabic", class = "Arab", ranges = { {0x0600,0x06FF},{0x0750,0x077F},{0x08A0,0x08FF},{0xFB50,0xFDFF},{0xFE70,0xFEFF},{0x1EE00,0x1EEFF} } },
Armn = { name = "Armenian", class = "Armn", ranges = { {0x0530,0x058F},{0xFB13,0xFB17} } },
Bali = { name = "Balinese", class = "Bali", ranges = { {0x1B00,0x1B7F} } },
Batk = { name = "Batak", class = "Batk", ranges = { {0x1BC0,0x1BFF} } },
Beng = { name = "Bengali", class = "Beng", ranges = { {0x0980,0x09FF} } },
Bopo = { name = "Bopomofo", class = "Bopo", ranges = { {0x3100,0x312F},{0x31A0,0x31BF} } },
Brai = { name = "Braille", class = "Brai", ranges = { {0x2800,0x28FF} } },
Bugi = { name = "Buginese", class = "Bugi", ranges = { {0x1A00,0x1A1F} } },
Buhd = { name = "Buhid", class = "Buhd", ranges = { {0x1740,0x175F} } },
Cham = { name = "Cham", class = "Cham", ranges = { {0xAA00,0xAA5F} } },
Copt = { name = "Coptic", class = "Copt", ranges = { {0x2C80,0x2CFF},{0x03E2,0x03EF} } },
Cyrl = { name = "Cyrillic", class = "Cyrl", ranges = { {0x0400,0x04FF},{0x0500,0x052F},{0x2DE0,0x2DFF},{0xA640,0xA69F},{0x1C80,0x1C8F} } },
Deva = { name = "Devanagari", class = "Deva", ranges = { {0x0900,0x097F},{0xA8E0,0xA8FF} } },
Dsrt = { name = "Deseret", class = "Dsrt", ranges = { {0x10400,0x1044F} } },
Egyp = { name = "Egyptian Hieroglyphs", class = "Egyp", ranges = { {0x13000,0x1342F} } },
Ethi = { name = "Ethiopic", class = "Ethi", ranges = { {0x1200,0x137F},{0x1380,0x139F},{0x2D80,0x2DDF},{0xAB00,0xAB2F} } },
Geor = { name = "Georgian", class = "Geor", ranges = { {0x10A0,0x10FF},{0x2D00,0x2D2F},{0x1C90,0x1CBF} } },
Glag = { name = "Glagolitic", class = "Glag", ranges = { {0x2C00,0x2C5F},{0x1E000,0x1E02F} } },
Goth = { name = "Gothic", class = "Goth", ranges = { {0x10330,0x1034F} } },
Grek = { name = "Greek", class = "Grek", ranges = { {0x0370,0x03FF},{0x1F00,0x1FFF} } },
Gujr = { name = "Gujarati", class = "Gujr", ranges = { {0x0A80,0x0AFF} } },
Guru = { name = "Gurmukhi", class = "Guru", ranges = { {0x0A00,0x0A7F} } },
Hang = { name = "Hangul", class = "Hang", ranges = { {0x1100,0x11FF},{0x3130,0x318F},{0xAC00,0xD7AF},{0xA960,0xA97F},{0xD7B0,0xD7FF} } },
Hani = { name = "Han", class = "Hani", ranges = { {0x4E00,0x9FFF},{0x3400,0x4DBF} } },
Hano = { name = "Hanunoo", class = "Hano", ranges = { {0x1720,0x173F} } },
Hebr = { name = "Hebrew", class = "Hebr", ranges = { {0x0590,0x05FF},{0xFB1D,0xFB4F} } },
Hira = { name = "Hiragana", class = "Hira", ranges = { {0x3040,0x309F} } },
Ital = { name = "Old Italic", class = "Ital", ranges = { {0x10300,0x1032F} } },
Java = { name = "Javanese", class = "Java", ranges = { {0xA980,0xA9DF} } },
Kana = { name = "Katakana", class = "Kana", ranges = { {0x30A0,0x30FF},{0x31F0,0x31FF},{0xFF66,0xFF9D} } },
Khmr = { name = "Khmer", class = "Khmr", ranges = { {0x1780,0x17FF},{0x19E0,0x19FF} } },
Knda = { name = "Kannada", class = "Knda", ranges = { {0x0C80,0x0CFF} } },
Lana = { name = "Tai Tham (Lanna)", class = "Lana", ranges = { {0x1A20,0x1AAF} } },
Laoo = { name = "Lao", class = "Laoo", ranges = { {0x0E80,0x0EFF} } },
Latn = { name = "Latin", class = "Latn", ranges = { {0x0041,0x005A},{0x0061,0x007A},{0x00C0,0x00FF},{0x0100,0x017F},{0x0180,0x024F},{0x0250,0x02AF},{0x02B0,0x02FF},{0x1D00,0x1D7F},{0x1D80,0x1DBF},{0x1E00,0x1EFF},{0x2C60,0x2C7F},{0xA720,0xA7FF},{0xAB30,0xAB6F} } },
Limb = { name = "Limbu", class = "Limb", ranges = { {0x1900,0x194F} }},
Linb = { name = "Linear B", class = "Linb", ranges = { {0x10000,0x1007F},{0x10080,0x100FF} }},
Maka = { name = "Makasar", class = "Maka", ranges = { {0x11EE0,0x11EFF} }},
Mlym = { name = "Malayalam", class = "Mlym", ranges = { {0x0D00,0x0D7F} }},
Mong = { name = "Mongolian", class = "Mong", ranges = { {0x1800,0x18AF},{0x11660,0x1167F},{0x18B0,0x18FF} }},
Mymr = { name = "Myanmar", class = "Mymr", ranges = { {0x1000,0x109F},{0xAA60,0xAA7F},{0xA9E0,0xA9FF} }},
Nkoo = { name = "N’Ko", class = "Nkoo", ranges = { {0x07C0,0x07FF} }},
Ogam = { name = "Ogham", class = "Ogam", ranges = { {0x1680,0x169F} }},
Orya = { name = "Oriya", class = "Orya", ranges = { {0x0B00,0x0B7F} }},
Phnx = { name = "Phoenician", class = "Phnx", ranges = { {0x10900,0x1091F} }},
Rjng = { name = "Rejang", class = "Rjng", ranges = { {0xA930,0xA95F} }},
Runr = { name = "Runic", class = "Runr", ranges = { {0x16A0,0x16FF} }},
Sinh = { name = "Sinhala", class = "Sinh", ranges = { {0x0D80,0x0DFF} }},
Sund = { name = "Sundanese", class = "Sund", ranges = { {0x1B80,0x1BBF},{0x1CC0,0x1CCF} }},
Syrc = { name = "Syriac", class = "Syrc", ranges = { {0x0700,0x074F},{0x0860,0x086F} }},
Tagb = { name = "Tagbanwa", class = "Tagb", ranges = { {0x1760,0x177F} }},
Tale = { name = "Tai Le", class = "Tale", ranges = { {0x1950,0x197F} }},
Talu = { name = "New Tai Lue", class = "Talu", ranges = { {0x1980,0x19DF} }},
Taml = { name = "Tamil", class = "Taml", ranges = { {0x0B80,0x0BFF} }},
Tavt = { name = "Tai Viet", class = "Tavt", ranges = { {0xAA80,0xAADF} }},
Telu = { name = "Telugu", class = "Telu", ranges = { {0x0C00,0x0C7F} }},
Thaa = { name = "Thaana", class = "Thaa", ranges = { {0x0780,0x07BF} }},
Thai = { name = "Thai", class = "Thai", ranges = { {0x0E00,0x0E7F} }},
Tfng = { name = "Tifinagh", class = "Tfng", ranges = { {0x2D30,0x2D7F} }},
Tglg = { name = "Tagalog", class = "Tglg", ranges = { {0x1700,0x171F},{0x1730,0x173F} }},
Tibt = { name = "Tibetan", class = "Tibt", ranges = { {0x0F00,0x0FFF} }},
Ugar = { name = "Ugaritic", class = "Ugar", ranges = { {0x10380,0x1039F} }},
Vaii = { name = "Vai", class = "Vaii", ranges = { {0xA500,0xA63F} }},
Xpeo = { name = "Old Persian", class = "Xpeo", ranges = { {0x103A0,0x103DF} }},
Xsux = { name = "Cuneiform", class = "Xsux", ranges = { {0x12000,0x123FF},{0x12400,0x1247F},{0x12480,0x1254F} }},
}
-- Alphabetical detection order
M.order = {}
for code, _ in pairs(M.scripts) do
table.insert(M.order, code)
end
table.sort(M.order)
-- Detect script
function M.detect(text)
if not text or text == "" then return "Latn" end
local cps = { mw.ustring.codepoint(text, 1, -1) }
for i = 1, #cps do
local cp = cps[i]
if not is_ignorable(cp) then
for j = 1, #M.order do
local code = M.order[j]
if in_ranges(cp, M.scripts[code].ranges) then
return code
end
end
end
end
return "Latn"
end
-- Get CSS class
function M.getClass(code)
if code and M.scripts[code] then
return M.scripts[code].class
end
return nil
end
-- Wrap text with a <span> only if script is non-Latin
function M.wrap(text, sc)
if not text or not sc then return text end
if sc == "Latn" then
return text -- don't wrap Latin
end
local scClass = M.getClass(sc)
if scClass then
return string.format('<span class="%s">%s</span>', scClass, text)
else
return text -- no wrapping if unknown
end
end
-- Wrapper for template use: detect script and wrap text if non-Latin
function M.detectWrap(frame)
local text = frame.args["text"]
if not text or text == "" then return "" end
local script = M.detect(text)
return M.wrap(text, script)
end
return M
bky9u0oajggmj1e73l0231khjkvfbjs
26530
17472
2026-07-07T09:55:58Z
Sibiru45
115
1 ralatan matan [[:id:Modul:aksara]]
17472
Scribunto
text/plain
local M = {}
local function in_ranges(cp, ranges)
for i = 1, #ranges do
local r = ranges[i]
if cp >= r[1] and cp <= r[2] then
return true
end
end
return false
end
-- Ignore combining diacritical marks
local IGNORE_COMBINING = {
{0x0300, 0x036F}, {0x1AB0, 0x1AFF}, {0x1DC0, 0x1DFF},
{0x20D0, 0x20FF}, {0xFE20, 0xFE2F}
}
local function is_ignorable(cp)
return in_ranges(cp, IGNORE_COMBINING)
end
-- Script data
M.scripts = {
Arab = { name = "Arabic", class = "Arab", ranges = { {0x0600,0x06FF},{0x0750,0x077F},{0x08A0,0x08FF},{0xFB50,0xFDFF},{0xFE70,0xFEFF},{0x1EE00,0x1EEFF} } },
Armn = { name = "Armenian", class = "Armn", ranges = { {0x0530,0x058F},{0xFB13,0xFB17} } },
Bali = { name = "Balinese", class = "Bali", ranges = { {0x1B00,0x1B7F} } },
Batk = { name = "Batak", class = "Batk", ranges = { {0x1BC0,0x1BFF} } },
Beng = { name = "Bengali", class = "Beng", ranges = { {0x0980,0x09FF} } },
Bopo = { name = "Bopomofo", class = "Bopo", ranges = { {0x3100,0x312F},{0x31A0,0x31BF} } },
Brai = { name = "Braille", class = "Brai", ranges = { {0x2800,0x28FF} } },
Bugi = { name = "Buginese", class = "Bugi", ranges = { {0x1A00,0x1A1F} } },
Buhd = { name = "Buhid", class = "Buhd", ranges = { {0x1740,0x175F} } },
Cham = { name = "Cham", class = "Cham", ranges = { {0xAA00,0xAA5F} } },
Copt = { name = "Coptic", class = "Copt", ranges = { {0x2C80,0x2CFF},{0x03E2,0x03EF} } },
Cyrl = { name = "Cyrillic", class = "Cyrl", ranges = { {0x0400,0x04FF},{0x0500,0x052F},{0x2DE0,0x2DFF},{0xA640,0xA69F},{0x1C80,0x1C8F} } },
Deva = { name = "Devanagari", class = "Deva", ranges = { {0x0900,0x097F},{0xA8E0,0xA8FF} } },
Dsrt = { name = "Deseret", class = "Dsrt", ranges = { {0x10400,0x1044F} } },
Egyp = { name = "Egyptian Hieroglyphs", class = "Egyp", ranges = { {0x13000,0x1342F} } },
Ethi = { name = "Ethiopic", class = "Ethi", ranges = { {0x1200,0x137F},{0x1380,0x139F},{0x2D80,0x2DDF},{0xAB00,0xAB2F} } },
Geor = { name = "Georgian", class = "Geor", ranges = { {0x10A0,0x10FF},{0x2D00,0x2D2F},{0x1C90,0x1CBF} } },
Glag = { name = "Glagolitic", class = "Glag", ranges = { {0x2C00,0x2C5F},{0x1E000,0x1E02F} } },
Goth = { name = "Gothic", class = "Goth", ranges = { {0x10330,0x1034F} } },
Grek = { name = "Greek", class = "Grek", ranges = { {0x0370,0x03FF},{0x1F00,0x1FFF} } },
Gujr = { name = "Gujarati", class = "Gujr", ranges = { {0x0A80,0x0AFF} } },
Guru = { name = "Gurmukhi", class = "Guru", ranges = { {0x0A00,0x0A7F} } },
Hang = { name = "Hangul", class = "Hang", ranges = { {0x1100,0x11FF},{0x3130,0x318F},{0xAC00,0xD7AF},{0xA960,0xA97F},{0xD7B0,0xD7FF} } },
Hani = { name = "Han", class = "Hani", ranges = { {0x4E00,0x9FFF},{0x3400,0x4DBF} } },
Hano = { name = "Hanunoo", class = "Hano", ranges = { {0x1720,0x173F} } },
Hebr = { name = "Hebrew", class = "Hebr", ranges = { {0x0590,0x05FF},{0xFB1D,0xFB4F} } },
Hira = { name = "Hiragana", class = "Hira", ranges = { {0x3040,0x309F} } },
Ital = { name = "Old Italic", class = "Ital", ranges = { {0x10300,0x1032F} } },
Java = { name = "Javanese", class = "Java", ranges = { {0xA980,0xA9DF} } },
Kana = { name = "Katakana", class = "Kana", ranges = { {0x30A0,0x30FF},{0x31F0,0x31FF},{0xFF66,0xFF9D} } },
Khmr = { name = "Khmer", class = "Khmr", ranges = { {0x1780,0x17FF},{0x19E0,0x19FF} } },
Knda = { name = "Kannada", class = "Knda", ranges = { {0x0C80,0x0CFF} } },
Lana = { name = "Tai Tham (Lanna)", class = "Lana", ranges = { {0x1A20,0x1AAF} } },
Laoo = { name = "Lao", class = "Laoo", ranges = { {0x0E80,0x0EFF} } },
Latn = { name = "Latin", class = "Latn", ranges = { {0x0041,0x005A},{0x0061,0x007A},{0x00C0,0x00FF},{0x0100,0x017F},{0x0180,0x024F},{0x0250,0x02AF},{0x02B0,0x02FF},{0x1D00,0x1D7F},{0x1D80,0x1DBF},{0x1E00,0x1EFF},{0x2C60,0x2C7F},{0xA720,0xA7FF},{0xAB30,0xAB6F} } },
Limb = { name = "Limbu", class = "Limb", ranges = { {0x1900,0x194F} }},
Linb = { name = "Linear B", class = "Linb", ranges = { {0x10000,0x1007F},{0x10080,0x100FF} }},
Maka = { name = "Makasar", class = "Maka", ranges = { {0x11EE0,0x11EFF} }},
Mlym = { name = "Malayalam", class = "Mlym", ranges = { {0x0D00,0x0D7F} }},
Mong = { name = "Mongolian", class = "Mong", ranges = { {0x1800,0x18AF},{0x11660,0x1167F},{0x18B0,0x18FF} }},
Mymr = { name = "Myanmar", class = "Mymr", ranges = { {0x1000,0x109F},{0xAA60,0xAA7F},{0xA9E0,0xA9FF} }},
Nkoo = { name = "N’Ko", class = "Nkoo", ranges = { {0x07C0,0x07FF} }},
Ogam = { name = "Ogham", class = "Ogam", ranges = { {0x1680,0x169F} }},
Orya = { name = "Oriya", class = "Orya", ranges = { {0x0B00,0x0B7F} }},
Phnx = { name = "Phoenician", class = "Phnx", ranges = { {0x10900,0x1091F} }},
Rjng = { name = "Rejang", class = "Rjng", ranges = { {0xA930,0xA95F} }},
Runr = { name = "Runic", class = "Runr", ranges = { {0x16A0,0x16FF} }},
Sinh = { name = "Sinhala", class = "Sinh", ranges = { {0x0D80,0x0DFF} }},
Sund = { name = "Sundanese", class = "Sund", ranges = { {0x1B80,0x1BBF},{0x1CC0,0x1CCF} }},
Syrc = { name = "Syriac", class = "Syrc", ranges = { {0x0700,0x074F},{0x0860,0x086F} }},
Tagb = { name = "Tagbanwa", class = "Tagb", ranges = { {0x1760,0x177F} }},
Tale = { name = "Tai Le", class = "Tale", ranges = { {0x1950,0x197F} }},
Talu = { name = "New Tai Lue", class = "Talu", ranges = { {0x1980,0x19DF} }},
Taml = { name = "Tamil", class = "Taml", ranges = { {0x0B80,0x0BFF} }},
Tavt = { name = "Tai Viet", class = "Tavt", ranges = { {0xAA80,0xAADF} }},
Telu = { name = "Telugu", class = "Telu", ranges = { {0x0C00,0x0C7F} }},
Thaa = { name = "Thaana", class = "Thaa", ranges = { {0x0780,0x07BF} }},
Thai = { name = "Thai", class = "Thai", ranges = { {0x0E00,0x0E7F} }},
Tfng = { name = "Tifinagh", class = "Tfng", ranges = { {0x2D30,0x2D7F} }},
Tglg = { name = "Tagalog", class = "Tglg", ranges = { {0x1700,0x171F},{0x1730,0x173F} }},
Tibt = { name = "Tibetan", class = "Tibt", ranges = { {0x0F00,0x0FFF} }},
Ugar = { name = "Ugaritic", class = "Ugar", ranges = { {0x10380,0x1039F} }},
Vaii = { name = "Vai", class = "Vaii", ranges = { {0xA500,0xA63F} }},
Xpeo = { name = "Old Persian", class = "Xpeo", ranges = { {0x103A0,0x103DF} }},
Xsux = { name = "Cuneiform", class = "Xsux", ranges = { {0x12000,0x123FF},{0x12400,0x1247F},{0x12480,0x1254F} }},
}
-- Alphabetical detection order
M.order = {}
for code, _ in pairs(M.scripts) do
table.insert(M.order, code)
end
table.sort(M.order)
-- Detect script
function M.detect(text)
if not text or text == "" then return "Latn" end
local cps = { mw.ustring.codepoint(text, 1, -1) }
for i = 1, #cps do
local cp = cps[i]
if not is_ignorable(cp) then
for j = 1, #M.order do
local code = M.order[j]
if in_ranges(cp, M.scripts[code].ranges) then
return code
end
end
end
end
return "Latn"
end
-- Get CSS class
function M.getClass(code)
if code and M.scripts[code] then
return M.scripts[code].class
end
return nil
end
-- Wrap text with a <span> only if script is non-Latin
function M.wrap(text, sc)
if not text or not sc then return text end
if sc == "Latn" then
return text -- don't wrap Latin
end
local scClass = M.getClass(sc)
if scClass then
return string.format('<span class="%s">%s</span>', scClass, text)
else
return text -- no wrapping if unknown
end
end
-- Wrapper for template use: detect script and wrap text if non-Latin
function M.detectWrap(frame)
local text = frame.args["text"]
if not text or text == "" then return "" end
local script = M.detect(text)
return M.wrap(text, script)
end
return M
bky9u0oajggmj1e73l0231khjkvfbjs
Modul:pranala
828
6780
26525
20196
2026-02-16T13:55:59Z
id>Bennylin
0
pakai bahasa Inggris supaya tidak galat ketika dikopi ke wikikamus bahasa daerah
26525
Scribunto
text/plain
local p = {}
local langModule = require('Module:bahasa')
local scriptsModule = require('Module:aksara')
-- Style text depending on script/lang
local function wrapText(text, langcode, noitalic, bold)
if not text or text == "" then return "" end
local sc = scriptsModule.detect(text)
local wrapped = scriptsModule.wrap(text, sc)
-- Protolanguage: no italics, bold allowed
if langModule.protoLangs[langcode] then
if sc == "Latn" and bold == "1" then
wrapped = "<b>" .. wrapped .. "</b>"
end
return wrapped
end
-- Normal language: italicize Latin unless noitalic
if sc == "Latn" then
if noitalic ~= "1" then
wrapped = "<i>" .. wrapped .. "</i>"
end
if bold == "1" then
wrapped = "<b>" .. wrapped .. "</b>"
end
end
return wrapped
end
-- Build entry link
local function makeEntryLink(linkTarget, langcode, id, displayEntry, noitalic, bold)
local langName = langModule.getLangName({ args = { langcode } })
local isProto = langModule.protoLangs[langcode]
-- Protolanguage
if isProto then
if mw.ustring.sub(linkTarget, 1, 1) ~= "*" then
return string.format(
"<strong class='error'>Galat: Rekonstruksi bahasa purba “%s” mesti diawali dengan tanda bintang (*)</strong>[[Bangsaan:Pranala rekonstruksi tanpa tanda bintang]]",
linkTarget
)
end
local bareEntry = mw.ustring.sub(linkTarget, 2) -- remove leading *
local protoName = langModule.getLangName({args={langcode, nocap="1"}})
local text = displayEntry and displayEntry ~= "" and displayEntry or linkTarget
text = wrapText(text, langcode, "1", bold) -- force noitalic, bold allowed
return string.format("[[Lampiran:Rekonstruksi %s/%s|%s]]", protoName, bareEntry, text)
end
-- Normal language
local anchor
if id and id ~= "" then
anchor = string.format("#%s:%s", langName, id)
else
anchor = "#" .. langName
end
local text
if displayEntry and displayEntry ~= "" then
text = wrapText(displayEntry, langcode, noitalic, bold)
else
text = wrapText(linkTarget, langcode, noitalic, bold)
end
return string.format("[[%s%s|%s]]", linkTarget, anchor, text)
end
-- Build final display
local function buildDisplay(linkTarget, langcode, id, tr, t, lit, q, displayEntry, class, noitalic, notext, bold)
local parts = {}
if q and q ~= "" then
table.insert(parts, string.format("(<i>%s</i>)", q))
end
if notext ~= "1" then
local langname = langModule.getLangName({args={langcode, nocap="1"}})
table.insert(parts, langname .. " punya setilah")
end
-- Skip linking if entry is just a hyphen
if linkTarget ~= "-" then
local entryPart = makeEntryLink(linkTarget, langcode, id, displayEntry, noitalic, bold)
-- Append class right after entry
if class and class ~= "" then
entryPart = entryPart .. " <span class='gender'>" .. class .. "</span>"
end
table.insert(parts, entryPart)
end
local needParens = (tr and tr ~= "") or (t and t ~= "") or (lit and lit ~= "")
if needParens then
local subparts = {}
if tr and tr ~= "" then
subparts[#subparts+1] = wrapText(tr, langcode, noitalic, "")
end
if t and t ~= "" then
subparts[#subparts+1] = string.format('"%s"', t)
end
if lit and lit ~= "" then
subparts[#subparts+1] = string.format('harfiahnya, "%s"', lit)
end
parts[#parts+1] = "(" .. table.concat(subparts, ", ") .. ")"
end
return table.concat(parts, " ")
end
-- Parse inline <tr:...>, <t:...>, <lit:...>, <id:...>, <entry:...>, <q:...>, <class:...>
local function parseInline(entry, idx, args)
local tr_inline = entry:match("<tr:(.-)>")
local t_inline = entry:match("<t:(.-)>")
local lit_inline = entry:match("<lit:(.-)>")
local id_inline = entry:match("<id:(.-)>")
local display_inline = entry:match("<entry:(.-)>")
local q_inline = entry:match("<q:(.-)>")
local class_inline = entry:match("<class:(.-)>")
local cleaned = entry
:gsub("<tr:.->", "")
:gsub("<t:.->", "")
:gsub("<lit:.->", "")
:gsub("<id:.->", "")
:gsub("<entry:.->", "")
:gsub("<q:.->", "")
:gsub("<class:.->", "")
return {
entry = cleaned,
tr = tr_inline or args["tr"..idx] or args.tr or "",
t = t_inline or args["t"..idx] or args.t or "",
lit = lit_inline or args["lit"..idx] or args.lit or "",
id = id_inline or args["id"..idx] or args.id or "",
display = display_inline and mw.text.trim(display_inline:gsub("<.->", "")) or "",
q = q_inline or args["q"..idx] or args.q or "",
class = class_inline or args["class"..idx] or args.class or "",
}
end
-- Internal core
local function makeMention(args)
local langcode = args[1] or ""
local rawEntry = args[2] or ""
local idx = tonumber(args.idx or 1) or 1
-- Inline parsing
local parsed = parseInline(rawEntry, idx, args)
local linkTarget = parsed.entry
local id = parsed.id
local tr = parsed.tr
local t = parsed.t
local lit = parsed.lit
local q = parsed.q
local class = parsed.class
local noitalic = args.noitalic or ""
local notext = args.notext or ""
local bold = args.bold or ""
-- Display preference
local displayEntry = args.entry or parsed.display
if displayEntry == "" and args[3] then
displayEntry = args[3]
end
if displayEntry == "" then
displayEntry = linkTarget
end
if not linkTarget or linkTarget == "" then
return "<strong class='error'>Galat: Pranala sasaran kosong</strong>"
end
return buildDisplay(linkTarget, langcode, id, tr, t, lit, q, displayEntry, class, noitalic, notext, bold)
end
-- Exports
function p.mention(frame)
return makeMention(frame.args)
end
function p.link(frame)
local args = frame.args
args.noitalic = "1"
return makeMention(args)
end
p.makeMention = makeMention
p.parseInline = parseInline
return p
893yzm9imex03lu9y10wh13wbnjz55m
26526
26525
2026-07-07T09:55:58Z
Sibiru45
115
1 ralatan matan [[:id:Modul:pranala]]
26525
Scribunto
text/plain
local p = {}
local langModule = require('Module:bahasa')
local scriptsModule = require('Module:aksara')
-- Style text depending on script/lang
local function wrapText(text, langcode, noitalic, bold)
if not text or text == "" then return "" end
local sc = scriptsModule.detect(text)
local wrapped = scriptsModule.wrap(text, sc)
-- Protolanguage: no italics, bold allowed
if langModule.protoLangs[langcode] then
if sc == "Latn" and bold == "1" then
wrapped = "<b>" .. wrapped .. "</b>"
end
return wrapped
end
-- Normal language: italicize Latin unless noitalic
if sc == "Latn" then
if noitalic ~= "1" then
wrapped = "<i>" .. wrapped .. "</i>"
end
if bold == "1" then
wrapped = "<b>" .. wrapped .. "</b>"
end
end
return wrapped
end
-- Build entry link
local function makeEntryLink(linkTarget, langcode, id, displayEntry, noitalic, bold)
local langName = langModule.getLangName({ args = { langcode } })
local isProto = langModule.protoLangs[langcode]
-- Protolanguage
if isProto then
if mw.ustring.sub(linkTarget, 1, 1) ~= "*" then
return string.format(
"<strong class='error'>Galat: Rekonstruksi bahasa purba “%s” mesti diawali dengan tanda bintang (*)</strong>[[Bangsaan:Pranala rekonstruksi tanpa tanda bintang]]",
linkTarget
)
end
local bareEntry = mw.ustring.sub(linkTarget, 2) -- remove leading *
local protoName = langModule.getLangName({args={langcode, nocap="1"}})
local text = displayEntry and displayEntry ~= "" and displayEntry or linkTarget
text = wrapText(text, langcode, "1", bold) -- force noitalic, bold allowed
return string.format("[[Lampiran:Rekonstruksi %s/%s|%s]]", protoName, bareEntry, text)
end
-- Normal language
local anchor
if id and id ~= "" then
anchor = string.format("#%s:%s", langName, id)
else
anchor = "#" .. langName
end
local text
if displayEntry and displayEntry ~= "" then
text = wrapText(displayEntry, langcode, noitalic, bold)
else
text = wrapText(linkTarget, langcode, noitalic, bold)
end
return string.format("[[%s%s|%s]]", linkTarget, anchor, text)
end
-- Build final display
local function buildDisplay(linkTarget, langcode, id, tr, t, lit, q, displayEntry, class, noitalic, notext, bold)
local parts = {}
if q and q ~= "" then
table.insert(parts, string.format("(<i>%s</i>)", q))
end
if notext ~= "1" then
local langname = langModule.getLangName({args={langcode, nocap="1"}})
table.insert(parts, langname .. " punya setilah")
end
-- Skip linking if entry is just a hyphen
if linkTarget ~= "-" then
local entryPart = makeEntryLink(linkTarget, langcode, id, displayEntry, noitalic, bold)
-- Append class right after entry
if class and class ~= "" then
entryPart = entryPart .. " <span class='gender'>" .. class .. "</span>"
end
table.insert(parts, entryPart)
end
local needParens = (tr and tr ~= "") or (t and t ~= "") or (lit and lit ~= "")
if needParens then
local subparts = {}
if tr and tr ~= "" then
subparts[#subparts+1] = wrapText(tr, langcode, noitalic, "")
end
if t and t ~= "" then
subparts[#subparts+1] = string.format('"%s"', t)
end
if lit and lit ~= "" then
subparts[#subparts+1] = string.format('harfiahnya, "%s"', lit)
end
parts[#parts+1] = "(" .. table.concat(subparts, ", ") .. ")"
end
return table.concat(parts, " ")
end
-- Parse inline <tr:...>, <t:...>, <lit:...>, <id:...>, <entry:...>, <q:...>, <class:...>
local function parseInline(entry, idx, args)
local tr_inline = entry:match("<tr:(.-)>")
local t_inline = entry:match("<t:(.-)>")
local lit_inline = entry:match("<lit:(.-)>")
local id_inline = entry:match("<id:(.-)>")
local display_inline = entry:match("<entry:(.-)>")
local q_inline = entry:match("<q:(.-)>")
local class_inline = entry:match("<class:(.-)>")
local cleaned = entry
:gsub("<tr:.->", "")
:gsub("<t:.->", "")
:gsub("<lit:.->", "")
:gsub("<id:.->", "")
:gsub("<entry:.->", "")
:gsub("<q:.->", "")
:gsub("<class:.->", "")
return {
entry = cleaned,
tr = tr_inline or args["tr"..idx] or args.tr or "",
t = t_inline or args["t"..idx] or args.t or "",
lit = lit_inline or args["lit"..idx] or args.lit or "",
id = id_inline or args["id"..idx] or args.id or "",
display = display_inline and mw.text.trim(display_inline:gsub("<.->", "")) or "",
q = q_inline or args["q"..idx] or args.q or "",
class = class_inline or args["class"..idx] or args.class or "",
}
end
-- Internal core
local function makeMention(args)
local langcode = args[1] or ""
local rawEntry = args[2] or ""
local idx = tonumber(args.idx or 1) or 1
-- Inline parsing
local parsed = parseInline(rawEntry, idx, args)
local linkTarget = parsed.entry
local id = parsed.id
local tr = parsed.tr
local t = parsed.t
local lit = parsed.lit
local q = parsed.q
local class = parsed.class
local noitalic = args.noitalic or ""
local notext = args.notext or ""
local bold = args.bold or ""
-- Display preference
local displayEntry = args.entry or parsed.display
if displayEntry == "" and args[3] then
displayEntry = args[3]
end
if displayEntry == "" then
displayEntry = linkTarget
end
if not linkTarget or linkTarget == "" then
return "<strong class='error'>Galat: Pranala sasaran kosong</strong>"
end
return buildDisplay(linkTarget, langcode, id, tr, t, lit, q, displayEntry, class, noitalic, notext, bold)
end
-- Exports
function p.mention(frame)
return makeMention(frame.args)
end
function p.link(frame)
local args = frame.args
args.noitalic = "1"
return makeMention(args)
end
p.makeMention = makeMention
p.parseInline = parseInline
return p
893yzm9imex03lu9y10wh13wbnjz55m
Citakan:sebut
10
6793
26523
17511
2026-01-27T15:05:44Z
id>MITGATVM
0
izin untuk bung Swarabakti, ini dipakai khusus di halaman rekonstruksi :v
26523
wikitext
text/x-wiki
<includeonly>{{#invoke:pranala|mention
|1={{{1|}}}
|2={{{2|}}}
|3={{{entry|{{{3|}}}}}}
|class={{{class|}}}
|id={{{id|}}}
|tr={{{tr|}}}
|t={{{t|}}}
|lit={{{lit|}}}
|q={{{q|}}}
|noitalic={{{noitalic|}}}
|notext=1
}}</includeonly><noinclude>
: {{sebut|id|sebut}}
----
Untuk menampilkan penyebutan istilah dalam teks isi, dimiringkan dan dipranalakan ke entri sesuai bahasanya.
<pre>
{{sebut
| 1 = kode bahasa
| 2 = istilahnya
| 3 = istilah yang ditampilkan (jika berbeda)
| class = golongan (misal, gender nomina)
| id = pengenal (identifier) makna yang dituju
| tr = alih aksara (transliterasi)
| t = terjemahan
| lit = harfiahnya
| q = label keterangan
}}
</pre>
Contohnya, teks sumber berikut ini:
<pre>
: {{sebut|id|sebut}}
</pre>
akan ditampilkan sebagai
: {{sebut|id|sebut}}
Setiap parameter juga dapat disisipkan langsung setelah istilah (parameter 2) dengan format <code><parameter: ... ></code>, contoh:
<pre>
: {{sebut|en|mention<t:sebut>}}
</pre>
akan ditampilkan sebagai
: {{sebut|en|mention<t:sebut>}}</noinclude>
bbwcc45f6zfcavq2hgroxiywkc20yrv
26524
26523
2026-07-07T09:55:57Z
Sibiru45
115
1 ralatan matan [[:id:Templat:sebut]]
26523
wikitext
text/x-wiki
<includeonly>{{#invoke:pranala|mention
|1={{{1|}}}
|2={{{2|}}}
|3={{{entry|{{{3|}}}}}}
|class={{{class|}}}
|id={{{id|}}}
|tr={{{tr|}}}
|t={{{t|}}}
|lit={{{lit|}}}
|q={{{q|}}}
|noitalic={{{noitalic|}}}
|notext=1
}}</includeonly><noinclude>
: {{sebut|id|sebut}}
----
Untuk menampilkan penyebutan istilah dalam teks isi, dimiringkan dan dipranalakan ke entri sesuai bahasanya.
<pre>
{{sebut
| 1 = kode bahasa
| 2 = istilahnya
| 3 = istilah yang ditampilkan (jika berbeda)
| class = golongan (misal, gender nomina)
| id = pengenal (identifier) makna yang dituju
| tr = alih aksara (transliterasi)
| t = terjemahan
| lit = harfiahnya
| q = label keterangan
}}
</pre>
Contohnya, teks sumber berikut ini:
<pre>
: {{sebut|id|sebut}}
</pre>
akan ditampilkan sebagai
: {{sebut|id|sebut}}
Setiap parameter juga dapat disisipkan langsung setelah istilah (parameter 2) dengan format <code><parameter: ... ></code>, contoh:
<pre>
: {{sebut|en|mention<t:sebut>}}
</pre>
akan ditampilkan sebagai
: {{sebut|en|mention<t:sebut>}}</noinclude>
bbwcc45f6zfcavq2hgroxiywkc20yrv
Modul:load
828
6935
26515
2025-11-08T16:29:19Z
id>Ekirahardian
0
Salin dari en.wikipedia.org
26515
Scribunto
text/plain
local export = {}
local load_data = mw.loadData
local loaded = package.loaded
local main_loader = package.loaders[2]
local require = require
local setmetatable = setmetatable
local loaders, loaded_data, mt
local function get_mt()
mt, get_mt = {__mode = "kv"}, nil
return mt
end
-- main_loader returns a loader function if the module exists, or nil if it doesn't.
local function get_loader(modname)
if loaders == nil then
local loader = main_loader(modname)
loaders = setmetatable({[modname] = loader or false}, mt or get_mt())
return loader
end
local loader = loaders[modname]
if loader == nil then
loader = main_loader(modname)
loaders[modname] = loader or false
end
return loader or nil
end
local function get_data(modname, loader)
if loaded_data == nil then
local data = load_data(modname)
loaded_data = setmetatable({[loader] = data}, mt or get_mt())
return data
end
local data = loaded_data[loader]
if data == nil then
data = load_data(modname)
loaded_data[loader] = data
end
return data
end
--[==[
Like `require`, but returns `nil` if a module does not exist, instead of throwing an error.
Outputs are cached, which is faster for all modules, but much faster for nonexistent modules, since `require` will attempt to use the full loader each time because loading failures don't get cached.]==]
function export.safe_require(modname)
local mod = loaded[modname]
if mod == nil and get_loader(modname) then
-- Call with require instead of the loader directly, as it protects against infinite loading loops.
return require(modname)
end
return mod
end
--[==[
Like `mw.loadData`, but it does not generate a new table each time the same module is loaded via this function. Instead, it caches the returned data so that the same table can be returned each time, which is more efficient.]==]
function export.load_data(modname)
return get_data(modname, get_loader(modname))
end
--[==[
Like `export.load_data` (itself a variant of `mw.loadData`), but returns `nil` if a module does not exist, instead of throwing an error.
Outputs are cached, which is faster for all modules, but much faster for nonexistent modules, since `mw.loadData` will attempt to use the full loader each time because loading failures don't get cached.]==]
function export.safe_load_data(modname)
local loader = get_loader(modname)
if loader == nil then
return nil
end
return get_data(modname, loader)
end
return export
ane0ji5isx9pytu6xaiacn5a70oo2t2
26516
23971
2026-07-07T09:55:57Z
Sibiru45
115
1 ralatan matan [[:id:Modul:load]]
23971
Scribunto
text/plain
local export = {}
local load_data = mw.loadData
local loaded = package.loaded
local main_loader = package.loaders[2]
local require = require
local setmetatable = setmetatable
local loaders, loaded_data, mt
local function get_mt()
mt, get_mt = {__mode = "kv"}, nil
return mt
end
-- main_loader returns a loader function if the module exists, or nil if it doesn't.
local function get_loader(modname)
if loaders == nil then
local loader = main_loader(modname)
loaders = setmetatable({[modname] = loader or false}, mt or get_mt())
return loader
end
local loader = loaders[modname]
if loader == nil then
loader = main_loader(modname)
loaders[modname] = loader or false
end
return loader or nil
end
local function get_data(modname, loader)
if loaded_data == nil then
local data = load_data(modname)
loaded_data = setmetatable({[loader] = data}, mt or get_mt())
return data
end
local data = loaded_data[loader]
if data == nil then
data = load_data(modname)
loaded_data[loader] = data
end
return data
end
--[==[
Like `require`, but returns `nil` if a module does not exist, instead of throwing an error.
Outputs are cached, which is faster for all modules, but much faster for nonexistent modules, since `require` will attempt to use the full loader each time because loading failures don't get cached.]==]
function export.safe_require(modname)
local mod = loaded[modname]
if mod == nil and get_loader(modname) then
-- Call with require instead of the loader directly, as it protects against infinite loading loops.
return require(modname)
end
return mod
end
--[==[
Like `mw.loadData`, but it does not generate a new table each time the same module is loaded via this function. Instead, it caches the returned data so that the same table can be returned each time, which is more efficient.]==]
function export.load_data(modname)
return get_data(modname, get_loader(modname))
end
--[==[
Like `export.load_data` (itself a variant of `mw.loadData`), but returns `nil` if a module does not exist, instead of throwing an error.
Outputs are cached, which is faster for all modules, but much faster for nonexistent modules, since `mw.loadData` will attempt to use the full loader each time because loading failures don't get cached.]==]
function export.safe_load_data(modname)
local loader = get_loader(modname)
if loader == nil then
return nil
end
return get_data(modname, loader)
end
return export
ane0ji5isx9pytu6xaiacn5a70oo2t2
Modul:Scribunto
828
6944
26519
2025-11-08T21:05:23Z
id>Ekirahardian
0
Salin dari en.wikipedia.org
26519
Scribunto
text/plain
local export = {}
local math_module = "Module:math"
local dump = mw.dumpObject
local format = string.format
local gsub = string.gsub
local match = string.match
local php_trim -- defined below
local sub = string.sub
local tonumber = tonumber
local tostring = tostring
local type = type
do
local php_htmlspecialchars_data
local function get_php_htmlspecialchars_data()
php_htmlspecialchars_data, get_php_htmlspecialchars_data = {
["\""] = """,
["&"] = "&",
["'"] = "'",
["<"] = "<",
[">"] = ">",
}, nil
return php_htmlspecialchars_data
end
--[==[Lua equivalent of PHP's {{code|php|htmlspecialchars($string)}}, which converts the characters `&"'<>` to HTML entities.
If the `quotes` flag is set to {"compat"}, then `'` will not be converted, and if it is set to {"noquotes"}, then neither `"` nor `'` will be converted.]==]
function export.php_htmlspecialchars(str, quotes)
if quotes == nil or quotes == "quotes" then
quotes = "'\""
elseif quotes == "compat" then
quotes = "\""
elseif quotes == "noquotes" then
quotes = ""
else
local quotes_type = type(quotes)
error('`quotes` must be "quotes", "compat", "noquotes" or nil; received ' ..
(quotes_type == "string" and dump(quotes) or "a " .. quotes_type))
end
return (gsub(str, "[&<>" .. quotes .. "]", php_htmlspecialchars_data or get_php_htmlspecialchars_data()))
end
end
do
local function tonumber_extended(...)
tonumber_extended = require(math_module).tonumber_extended
return tonumber_extended(...)
end
-- Normalizes a string for use in comparisons which emulate PHP's equals
-- operator, which coerces certain strings to numbers: those within the
-- range -2^63 to 2^63 - 1 which don't have decimal points or exponents are
-- coerced to integers, while any others are coerced to doubles if possible;
-- otherwise, they remain as strings. PHP and Lua have the same precision
-- for doubles, but Lua's integer precision range is -2^53 + 1 to 2^53 - 1.
-- Any integers within Lua's precision, as well as all doubles, are simply
-- coerced to numbers, but PHP integers outside of Lua's precision are
-- emulated as normalized strings, with leading 0s and any + sign removed.
-- The `not_long` flag is used for the second comparator if the first did
-- not get normalized to a long integer, as PHP will only coerce strings to
-- integers if it's possible for both comparators.
local function php_normalize_string(str, not_long)
local num = tonumber_extended(str, nil, true)
-- Must be a number that isn't ±infinity, NaN or hexadecimal.
if not num or match(str, "^%s*[+-]?0[xX]()") then
return str
-- If `not_long` is set or `num` is within Lua's precision, return as a
-- number.
elseif not_long or num < 9007199254740992 and num > -9007199254740992 then
return num, "number"
end
-- Check if it could be a long integer, and return as a double if not.
local sign, str_no_0 = match(str, "^%s*([+-]?)0*(%d+)$")
if not str_no_0 then
return num, "number"
end
-- Otherwise, check if it's a long integer. 2^63 is 9223372036854775808,
-- so slice off the last 15 digits and deal with the two parts
-- separately. If the integer value would be too high/low, return as a
-- string.
local high = tonumber(sub(str_no_0, 1, -16))
if high > 9223 then
return str
elseif high == 9223 then
local low = tonumber(sub(str_no_0, -15))
-- Range is -2^63 to 2^63 - 1 (not symmetrical).
if low > 372036854775808 or low == 372036854775808 and sign ~= "-" then
return str
end
end
return (sign == "+" and "" or sign) .. str_no_0, "long integer", num
end
--[==[Lua equivalent of PHP's {{code|php|===}} operator for strings.]==]
function export.php_string_equals(str1, str2)
if str1 == str2 then
return true
end
local str1, str1_type, str1_num = php_normalize_string(str1)
if str1 == str2 then
return true
elseif str1_type == "long integer" then
local str2, str2_type = php_normalize_string(str2)
return str2 == (str2_type == "number" and str1_num or str1)
elseif str1_type == "number" then
return str1 == php_normalize_string(str2, true)
end
return false
end
end
--[==[Lua equivalent of PHP's {{code|php|trim($string)}}, which trims {"\0"}, {"\t"}, {"\n"}, {"\v"}, {"\r"} and {" "}. This is useful when dealing with template parameters, since the native parser trims them like this.]==]
function export.php_trim(str)
return match(str, "[^ \t-\v\r%z].*%f[ \t-\v\r%z]") or ""
end
php_trim = export.php_trim
--[==[Lua equivalent of PHP's {{code|php|ltrim($string)}}, which trims {"\0"}, {"\t"}, {"\n"}, {"\v"}, {"\r"} and {" "} from the beginning of the input string.]==]
function export.php_ltrim(str)
return (gsub(str, "^[ \t-\v\r%z]+", ""))
end
--[==[Lua equivalent of PHP's {{code|php|rtrim($string)}}, which trims {"\0"}, {"\t"}, {"\n"}, {"\v"}, {"\r"} and {" "} from the end of the input string.]==]
function export.php_rtrim(str)
return match(str, "^.+%f[ \t-\v\r%z]") or ""
end
--[==[Takes a template or module parameter name as either a string or number, and returns the Scribunto-normalized form (i.e. the key that that parameter would have in a {frame.args} table). For example, {"1"} (a string) is normalized to {1} (a number), {" foo "} is normalized to {"foo"}, and {1.5} (a number) is normalized to {"1.5"} (a string). Inputs which cannot be normalized (e.g. booleans) return {nil}.
Strings are trimmed with {export.php_trim}, unless the `no_trim` flag is set. If it is, then string parameters are not trimmed, but strings may still be converted to numbers if they do not contain whitespace; this is necessary when normalizing keys into the form received by PHP during callbacks, before any trimming occurs (e.g. in the table of arguments when calling {frame:expandTemplates()}).
After trimming (if applicable), keys are then converted to numbers if '''all''' of the following are true:
# They are integers; i.e. no decimals or leading zeroes (e.g. {"2"}, but not {"2.0"} or {"02"}).
# They are ≤ 2{{sup|53}} and ≥ -2{{sup|53}}.
# There is no leading sign unless < 0 (e.g. {"2"} or {"-2"}, but not {"+2"} or {"-0"}).
# They contain no leading or trailing whitespace (which may be present when the `no_trim` flag is set).
Numbers are converted to strings if '''either''':
# They are not integers (e.g. {1.5}).
# They are > 2{{sup|53}} or < -2{{sup|53}}.
When converted to strings, integers ≤ 2{{sup|63}} and ≥ -2{{sup|63}} are formatted as integers (i.e. all digits are given), which is the range of PHP's integer precision, though the actual output may be imprecise since Lua's integer precision is > 2{{sup|53}} to < -2{{sup|53}}. All other numbers use the standard formatting output by {tostring()}.]==]
function export.scribunto_parameter_key(key, no_trim)
local key_type = type(key)
if key_type == "string" then
if not no_trim then
key = php_trim(key)
end
if match(key, "^()-?[1-9]%d*$") then
local num = tonumber(key)
-- Lua integers are only precise to 2^53 - 1, so specifically check
-- for 2^53 and -2^53 as strings, since a numerical comparison won't
-- work as it can't distinguish 2^53 from 2^53 + 1.
return (
num <= 9007199254740991 and num >= -9007199254740991 or
key == "9007199254740992" or
key == "-9007199254740992"
) and num or key
end
return key == "0" and 0 or key
elseif key_type == "number" then
-- No special handling needed for inf or NaN.
return key % 1 == 0 and (
key <= 9007199254740992 and key >= -9007199254740992 and key or
key <= 9223372036854775808 and key >= -9223372036854775808 and format("%d", key)
) or tostring(key)
end
return nil
end
--[==[Takes a template or module parameter value as either a string, number or boolean, and returns the Scribunto-normalized form (i.e. the value that that parameter would have in a {frame.args} table), which is always a string. For example, {"foo"} remains the same, {2} (a number) is normalized to {"2"} (a string), {true} is normalized to {"1"}, and {false} is normalized to {""}. Inputs which cannot be normalized (e.g. tables) return {nil}.
By default, returned values are not trimmed, which matches the treatment of unnamed parameters (e.g. `bar` in {{tl|<nowiki/>foo|bar}}). If the `named` flag is set, then returned values will be trimmed, which matches the treatment of named parameters (e.g. `baz` in {{tl|<nowiki/>foo|bar=baz}}).]==]
function export.scribunto_parameter_value(value, named)
local value_type = type(value)
if value_type == "string" then
return named and php_trim(value) or value
elseif value_type == "number" then
return tostring(value)
elseif value_type == "boolean" then
return value and "1" or ""
end
return nil
end
return export
90dvo9iqmpdordtuzghbnnl9rw4476r
26520
23986
2026-07-07T09:55:57Z
Sibiru45
115
1 ralatan matan [[:id:Modul:Scribunto]]
23986
Scribunto
text/plain
local export = {}
local math_module = "Module:math"
local dump = mw.dumpObject
local format = string.format
local gsub = string.gsub
local match = string.match
local php_trim -- defined below
local sub = string.sub
local tonumber = tonumber
local tostring = tostring
local type = type
do
local php_htmlspecialchars_data
local function get_php_htmlspecialchars_data()
php_htmlspecialchars_data, get_php_htmlspecialchars_data = {
["\""] = """,
["&"] = "&",
["'"] = "'",
["<"] = "<",
[">"] = ">",
}, nil
return php_htmlspecialchars_data
end
--[==[Lua equivalent of PHP's {{code|php|htmlspecialchars($string)}}, which converts the characters `&"'<>` to HTML entities.
If the `quotes` flag is set to {"compat"}, then `'` will not be converted, and if it is set to {"noquotes"}, then neither `"` nor `'` will be converted.]==]
function export.php_htmlspecialchars(str, quotes)
if quotes == nil or quotes == "quotes" then
quotes = "'\""
elseif quotes == "compat" then
quotes = "\""
elseif quotes == "noquotes" then
quotes = ""
else
local quotes_type = type(quotes)
error('`quotes` must be "quotes", "compat", "noquotes" or nil; received ' ..
(quotes_type == "string" and dump(quotes) or "a " .. quotes_type))
end
return (gsub(str, "[&<>" .. quotes .. "]", php_htmlspecialchars_data or get_php_htmlspecialchars_data()))
end
end
do
local function tonumber_extended(...)
tonumber_extended = require(math_module).tonumber_extended
return tonumber_extended(...)
end
-- Normalizes a string for use in comparisons which emulate PHP's equals
-- operator, which coerces certain strings to numbers: those within the
-- range -2^63 to 2^63 - 1 which don't have decimal points or exponents are
-- coerced to integers, while any others are coerced to doubles if possible;
-- otherwise, they remain as strings. PHP and Lua have the same precision
-- for doubles, but Lua's integer precision range is -2^53 + 1 to 2^53 - 1.
-- Any integers within Lua's precision, as well as all doubles, are simply
-- coerced to numbers, but PHP integers outside of Lua's precision are
-- emulated as normalized strings, with leading 0s and any + sign removed.
-- The `not_long` flag is used for the second comparator if the first did
-- not get normalized to a long integer, as PHP will only coerce strings to
-- integers if it's possible for both comparators.
local function php_normalize_string(str, not_long)
local num = tonumber_extended(str, nil, true)
-- Must be a number that isn't ±infinity, NaN or hexadecimal.
if not num or match(str, "^%s*[+-]?0[xX]()") then
return str
-- If `not_long` is set or `num` is within Lua's precision, return as a
-- number.
elseif not_long or num < 9007199254740992 and num > -9007199254740992 then
return num, "number"
end
-- Check if it could be a long integer, and return as a double if not.
local sign, str_no_0 = match(str, "^%s*([+-]?)0*(%d+)$")
if not str_no_0 then
return num, "number"
end
-- Otherwise, check if it's a long integer. 2^63 is 9223372036854775808,
-- so slice off the last 15 digits and deal with the two parts
-- separately. If the integer value would be too high/low, return as a
-- string.
local high = tonumber(sub(str_no_0, 1, -16))
if high > 9223 then
return str
elseif high == 9223 then
local low = tonumber(sub(str_no_0, -15))
-- Range is -2^63 to 2^63 - 1 (not symmetrical).
if low > 372036854775808 or low == 372036854775808 and sign ~= "-" then
return str
end
end
return (sign == "+" and "" or sign) .. str_no_0, "long integer", num
end
--[==[Lua equivalent of PHP's {{code|php|===}} operator for strings.]==]
function export.php_string_equals(str1, str2)
if str1 == str2 then
return true
end
local str1, str1_type, str1_num = php_normalize_string(str1)
if str1 == str2 then
return true
elseif str1_type == "long integer" then
local str2, str2_type = php_normalize_string(str2)
return str2 == (str2_type == "number" and str1_num or str1)
elseif str1_type == "number" then
return str1 == php_normalize_string(str2, true)
end
return false
end
end
--[==[Lua equivalent of PHP's {{code|php|trim($string)}}, which trims {"\0"}, {"\t"}, {"\n"}, {"\v"}, {"\r"} and {" "}. This is useful when dealing with template parameters, since the native parser trims them like this.]==]
function export.php_trim(str)
return match(str, "[^ \t-\v\r%z].*%f[ \t-\v\r%z]") or ""
end
php_trim = export.php_trim
--[==[Lua equivalent of PHP's {{code|php|ltrim($string)}}, which trims {"\0"}, {"\t"}, {"\n"}, {"\v"}, {"\r"} and {" "} from the beginning of the input string.]==]
function export.php_ltrim(str)
return (gsub(str, "^[ \t-\v\r%z]+", ""))
end
--[==[Lua equivalent of PHP's {{code|php|rtrim($string)}}, which trims {"\0"}, {"\t"}, {"\n"}, {"\v"}, {"\r"} and {" "} from the end of the input string.]==]
function export.php_rtrim(str)
return match(str, "^.+%f[ \t-\v\r%z]") or ""
end
--[==[Takes a template or module parameter name as either a string or number, and returns the Scribunto-normalized form (i.e. the key that that parameter would have in a {frame.args} table). For example, {"1"} (a string) is normalized to {1} (a number), {" foo "} is normalized to {"foo"}, and {1.5} (a number) is normalized to {"1.5"} (a string). Inputs which cannot be normalized (e.g. booleans) return {nil}.
Strings are trimmed with {export.php_trim}, unless the `no_trim` flag is set. If it is, then string parameters are not trimmed, but strings may still be converted to numbers if they do not contain whitespace; this is necessary when normalizing keys into the form received by PHP during callbacks, before any trimming occurs (e.g. in the table of arguments when calling {frame:expandTemplates()}).
After trimming (if applicable), keys are then converted to numbers if '''all''' of the following are true:
# They are integers; i.e. no decimals or leading zeroes (e.g. {"2"}, but not {"2.0"} or {"02"}).
# They are ≤ 2{{sup|53}} and ≥ -2{{sup|53}}.
# There is no leading sign unless < 0 (e.g. {"2"} or {"-2"}, but not {"+2"} or {"-0"}).
# They contain no leading or trailing whitespace (which may be present when the `no_trim` flag is set).
Numbers are converted to strings if '''either''':
# They are not integers (e.g. {1.5}).
# They are > 2{{sup|53}} or < -2{{sup|53}}.
When converted to strings, integers ≤ 2{{sup|63}} and ≥ -2{{sup|63}} are formatted as integers (i.e. all digits are given), which is the range of PHP's integer precision, though the actual output may be imprecise since Lua's integer precision is > 2{{sup|53}} to < -2{{sup|53}}. All other numbers use the standard formatting output by {tostring()}.]==]
function export.scribunto_parameter_key(key, no_trim)
local key_type = type(key)
if key_type == "string" then
if not no_trim then
key = php_trim(key)
end
if match(key, "^()-?[1-9]%d*$") then
local num = tonumber(key)
-- Lua integers are only precise to 2^53 - 1, so specifically check
-- for 2^53 and -2^53 as strings, since a numerical comparison won't
-- work as it can't distinguish 2^53 from 2^53 + 1.
return (
num <= 9007199254740991 and num >= -9007199254740991 or
key == "9007199254740992" or
key == "-9007199254740992"
) and num or key
end
return key == "0" and 0 or key
elseif key_type == "number" then
-- No special handling needed for inf or NaN.
return key % 1 == 0 and (
key <= 9007199254740992 and key >= -9007199254740992 and key or
key <= 9223372036854775808 and key >= -9223372036854775808 and format("%d", key)
) or tostring(key)
end
return nil
end
--[==[Takes a template or module parameter value as either a string, number or boolean, and returns the Scribunto-normalized form (i.e. the value that that parameter would have in a {frame.args} table), which is always a string. For example, {"foo"} remains the same, {2} (a number) is normalized to {"2"} (a string), {true} is normalized to {"1"}, and {false} is normalized to {""}. Inputs which cannot be normalized (e.g. tables) return {nil}.
By default, returned values are not trimmed, which matches the treatment of unnamed parameters (e.g. `bar` in {{tl|<nowiki/>foo|bar}}). If the `named` flag is set, then returned values will be trimmed, which matches the treatment of named parameters (e.g. `baz` in {{tl|<nowiki/>foo|bar=baz}}).]==]
function export.scribunto_parameter_value(value, named)
local value_type = type(value)
if value_type == "string" then
return named and php_trim(value) or value
elseif value_type == "number" then
return tostring(value)
elseif value_type == "boolean" then
return value and "1" or ""
end
return nil
end
return export
90dvo9iqmpdordtuzghbnnl9rw4476r
Modul:families/data
828
6970
26511
2025-11-08T17:40:44Z
id>Ekirahardian
0
Perbarui dari en.wikipedia.org
26511
Scribunto
text/plain
--[=[
This module contains definitions for all language family codes on Wiktionary.
]=]--
local m = {}
m["aav"] = {
"Austroasiatic",
33199,
aliases = {"Austro-Asiatic"},
}
m["aav-khs"] = {
"Khasian",
3073734,
"aav",
aliases = {"Khasic"},
}
m["aav-nic"] = {
"Nicobarese",
217380,
"aav",
}
m["aav-pkl"] = {
"Pnar-Khasi-Lyngngam",
nil,
"aav-khs",
}
m["afa"] = {
"Afroasiatic",
25268,
aliases = {"Afro-Asiatic"},
}
m["alg"] = {
"Algonquian",
33392,
"aql",
}
m["alg-abp"] = {
"Abenaki-Penobscot",
197936,
"alg-eas",
}
m["alg-ara"] = {
"Arapahoan",
2153686,
"alg",
}
m["alg-eas"] = {
"Eastern Algonquian",
2257525,
"alg",
}
m["alg-sfk"] = {
"Sac-Fox-Kickapoo",
1440172,
"alg",
}
m["alv"] = {
"Atlantic-Congo",
771124,
"nic",
}
m["alv-aah"] = {
"Ayere-Ahan",
750953,
"alv-von",
}
m["alv-ada"] = {
"Adamawa",
32906,
"alv-sav",
}
m["alv-bag"] = {
"Baga",
2746083,
"alv-mel",
}
m["alv-bak"] = {
"Bak",
1708174,
"alv-sng",
}
m["alv-bam"] = {
"Bambukic",
4853456,
"alv-ada",
aliases = {"Yungur-Jen"},
}
m["alv-bny"] = {
"Banyum",
2892477,
"alv-nyn",
}
m["alv-bua"] = {
"Bua",
4982094,
"alv-mbd",
}
m["alv-bwj"] = {
"Bikwin-Jen",
84542501,
"alv-bam",
}
m["alv-cng"] = {
"Cangin",
1033184,
"alv-fwo",
}
m["alv-ctn"] = {
"Central Tano",
1658486,
"alv-ptn",
aliases = {"Akan"},
}
m["alv-dlt"] = {
"Delta Edoid",
nil,
"alv-edo",
}
m["alv-dur"] = {
"Duru",
5316788,
"alv-lni",
}
m["alv-ede"] = {
"Ede",
35368,
"alv-yor",
}
m["alv-edk"] = {
"Edekiri",
5336735,
"alv-yrd",
}
m["alv-edo"] = {
"Edoid",
1287469,
"alv-von",
}
m["alv-eeo"] = {
"Edo-Esan-Ora",
12630439,
"alv-nce",
}
m["alv-fli"] = {
"Fali",
3450166,
"alv",
}
m["alv-fwo"] = {
"Fula-Wolof",
12631267,
"alv-sng",
}
m["alv-gbe"] = {
"Gbe",
668284,
"alv-von",
}
m["alv-gda"] = {
"Ga-Dangme",
3443338,
"alv-kwa",
}
m["alv-gng"] = {
"Guang",
684009,
"alv-ptn",
}
m["alv-gtm"] = {
"Ghana-Togo Mountain",
493020,
"alv-kwa",
aliases = {"Togo Remnant", "Central Togo"},
}
m["alv-hei"] = {
"Heiban",
108752116,
"alv-the",
}
m["alv-ido"] = {
"Idomoid",
974196,
"alv-von",
}
m["alv-igb"] = {
"Igboid",
1429100,
"alv-von",
}
m["alv-jfe"] = {
"Jola-Felupe",
1708174,
"alv-jol",
aliases = {"Ejamat"},
}
m["alv-jol"] = {
"Jola",
35176,
"alv-bak",
aliases = {"Diola"},
}
m["alv-kim"] = {
"Kim",
6409701,
"alv-mbd",
}
m["alv-kis"] = {
"Kissi",
35696,
"alv-mel",
}
m["alv-krb"] = {
"Karaboro",
4213541,
"alv-snf",
}
m["alv-ktg"] = {
"Ka-Togo",
5972796,
"alv-gtm",
}
m["alv-kul"] = {
"Kulango",
16977424,
"alv-sav",
aliases = {"Kulango-Lorhon", "Kulango-Lorom"},
}
m["alv-kwa"] = {
"Kwa",
33430,
"nic-vco",
}
m["alv-lag"] = {
"Lagoon",
111210042,
"alv-kwa",
}
m["alv-lek"] = {
"Leko",
6520642,
otherNames = {"Sambaic"}, -- appears to be an alias in Glottolog
"alv-lni",
}
m["alv-lim"] = {
"Limba",
35825,
"alv",
}
m["alv-lni"] = {
"Leko-Nimbari",
1708170,
"alv-ada",
otherNames = {"Central Adamawa"},
aliases = {"Chamba-Mumuye"},
}
m["alv-mbd"] = {
"Mbum-Day",
6799816,
"alv-ada",
}
m["alv-mbm"] = {
"Mbum",
6799814,
"alv-mbd",
}
m["alv-mel"] = {
"Mel",
12122355,
"alv",
}
m["alv-mum"] = {
"Mumuye",
84607009,
"alv-mye",
}
m["alv-mye"] = {
"Mumuye-Yendang",
6935539,
"alv-lni",
}
m["alv-nal"] = {
"Nalu",
nil,
"alv-sng",
}
m["alv-nce"] = {
"North-Central Edoid",
16110869,
"alv-edo",
}
m["alv-ngb"] = {
"Nupe-Gbagyi",
12638649,
"alv-nup",
aliases = {"Nupe-Gbari"},
}
m["alv-ntg"] = {
"Na-Togo",
nil,
"alv-gtm",
}
m["alv-nup"] = {
"Nupoid",
1429143,
"alv-von",
}
m["alv-nwd"] = {
"Northwestern Edoid",
16111012,
"alv-edo",
}
m["alv-nyn"] = {
"Nyun",
nil,
"alv-fwo",
}
m["alv-pap"] = {
"Papel",
7132562,
"alv-bak",
}
m["alv-pph"] = {
"Phla-Pherá",
3849625,
"alv-gbe",
}
m["alv-ptn"] = {
"Potou-Tano",
1475003,
"alv-kwa",
}
m["alv-sav"] = {
"Savanna",
4403672,
"nic-vco",
aliases = {"Savannas"},
}
m["alv-sma"] = {
"Suppire-Mamara",
4446348,
"alv-snf",
}
m["alv-snf"] = {
"Senufo",
33795,
"alv",
aliases = {"Senufic", "Senoufo"},
}
m["alv-sng"] = {
"Senegambian",
1708753,
"alv",
}
m["alv-snr"] = {
"Senari",
4416084,
"alv-snf",
}
m["alv-swd"] = {
"Southwestern Edoid",
12633903,
"alv-edo",
}
m["alv-tal"] = {
"Talodi",
12643302,
"alv-the",
}
m["alv-tdj"] = {
"Tagwana-Djimini",
7675362,
"alv-snf",
}
m["alv-ten"] = {
"Tenda",
3217535,
"alv-fwo",
}
m["alv-the"] = {
"Talodi-Heiban",
1521145,
"alv",
}
m["alv-von"] = {
"Volta-Niger",
34177,
"nic-vco",
}
m["alv-wan"] = {
"Wara-Natyoro",
7968830,
"alv-sav",
}
m["alv-wjk"] = {
"Waja-Kam",
nil,
"alv-ada",
}
m["alv-yek"] = {
"Yekhee",
nil,
"alv-nce",
}
m["alv-yor"] = {
"Yoruba",
nil,
"alv-edk",
}
m["alv-yrd"] = {
"Yoruboid",
1789745,
"alv-von",
}
m["alv-yun"] = {
"Yungur",
84601642,
"alv-bam",
aliases = {"Bena-Mboi"},
}
m["apa"] = {
"Apachean",
27758,
"ath",
aliases = {"Southern Athabaskan"},
}
m["aqa"] = {
"Alacalufan",
1288430,
}
m["aql"] = {
"Algic",
721612,
aliases = {"Algonquian-Ritwan", "Algonquian-Wiyot-Yurok"},
}
m["art"] = {
"constructed",
33215,
"qfa-not",
aliases = {"artificial", "planned"},
}
m["ath"] = {
"Athabaskan",
27475,
"xnd",
}
m["ath-nor"] = {
"North Athabaskan",
20738,
"ath",
aliases = {"Northern Athabaskan"},
}
m["ath-pco"] = {
"Pacific Coast Athabaskan",
20654,
"ath",
}
m["auf"] = {
"Arauan",
626772,
aliases = {"Arahuan", "Arauán", "Arawa", "Arawan", "Arawán"},
}
--[=[
Exceptional language and family codes for Australian Aboriginal languages
can use the prefix "aus-", though "aus" is no longer itself a family code.
]=]--
m["aus-arn"] = {
"Arnhem",
2581700,
aliases = {"Gunwinyguan", "Macro-Gunwinyguan"},
}
m["aus-bub"] = {
"Bunuban",
2495148,
aliases = {"Bunaban"},
}
m["aus-cww"] = {
"Central New South Wales",
5061507,
"aus-pam",
}
m["aus-dal"] = {
"Daly",
2478079,
}
m["aus-dyb"] = {
"Dyirbalic",
1850666,
"aus-pam",
}
m["aus-gar"] = {
"Garawan",
5521951,
}
m["aus-gun"] = {
"Gunwinyguan",
2581700,
"aus-arn",
aliases = {"Gunwingguan"},
}
m["aus-jar"] = {
"Jarrakan",
2039423,
}
m["aus-kar"] = {
"Karnic",
4215578,
"aus-pam",
}
m["aus-mir"] = {
"Mirndi",
4294095,
}
m["aus-nga"] = {
"Ngayarda",
16153490,
"aus-psw",
}
m["aus-nyu"] = {
"Nyulnyulan",
2039408,
}
m["aus-pam"] = {
"Pama-Nyungan",
33942,
}
m["aus-pmn"] = {
"Paman",
2640654,
"aus-pam",
}
m["aus-psw"] = {
"Southwest Pama-Nyungan",
2258160,
"aus-pam",
}
m["aus-rnd"] = {
"Arandic",
4784071,
"aus-pam",
}
m["aus-tnk"] = {
"Tangkic",
1823065,
}
m["aus-wdj"] = {
"Iwaidjan",
4196968,
aliases = {"Yiwaidjan"},
}
m["aus-wor"] = {
"Worrorran",
2038619,
}
m["aus-yid"] = {
"Yidinyic",
4205849,
"aus-pam",
}
m["aus-yng"] = {
"Yangmanic",
42727644,
}
m["aus-yol"] = {
"Yolngu",
2511254,
"aus-pam",
aliases = {"Yolŋu", "Yolngu Matha"},
}
m["aus-yuk"] = {
"Yuin-Kuric",
3833021,
"aus-pam",
}
m["awd"] = {
"Arawak",
626753,
aliases = {"Arawakan", "Maipurean", "Maipuran"},
}
m["awd-nwk"] = {
"Nawiki",
nil,
"awd",
aliases = {"Newiki"},
}
m["awd-taa"] = {
"Ta-Arawak",
7672731,
"awd",
aliases = {"Ta-Arawakan", "Ta-Maipurean"},
}
m["azc"] = {
"Uto-Aztecan",
34073,
aliases = {"Uto-Aztekan"},
}
m["azc-cup"] = {
"Cupan",
19866871,
"azc-tak",
}
m["azc-dur"] = {
"Durango Nahuatl",
2386361,
"azc-nah",
aliases = {"Mexicanero"}
}
m["azc-hua"] = {
"Huasteca Nahuatl",
3832950,
"azc-nah",
}
m["azc-nah"] = {
"Nahuan",
11965602,
"azc",
aliases = {"Aztecan"},
}
m["azc-num"] = {
"Numic",
2657541,
"azc",
}
m["azc-pim"] = {
"Piman",
7194600,
"azc",
aliases = {"Tepiman"},
}
m["azc-tak"] = {
"Takic",
1280305,
"azc",
}
m["azc-trc"] = {
"Taracahitic",
4245032,
"azc",
aliases = {"Taracahitan"},
}
m["bad"] = {
"Banda",
806234,
"nic-ubg",
}
m["bad-cnt"] = {
"Central Banda",
3438391,
"bad",
}
m["bai"] = {
"Bamileke",
806005,
"nic-gre",
}
m["bat"] = {
"Baltic",
33136,
"ine-bsl",
}
m["bat-eas"] = {
"East Baltic",
149944,
"bat",
}
m["bat-wes"] = {
"West Baltic",
149946,
"bat",
}
m["ber"] = {
"Berber",
25448,
"afa",
aliases = {"Tamazight"},
}
m["bnt"] = {
"Bantu",
33146,
"nic-bds",
}
m["bnt-baf"] = {
"Bafia",
799784,
"bnt",
}
m["bnt-bbo"] = {
"Bafo-Bonkeng",
nil,
"bnt-saw",
}
m["bnt-bdz"] = {
"Boma-Dzing",
1729203,
"bnt",
}
m["bnt-bek"] = {
"Bekwilic",
nil,
"bnt-ndb",
}
m["bnt-bki"] = {
"Bena-Kinga",
16113307,
"bnt-bne",
}
m["bnt-bmo"] = {
"Bangi-Moi",
nil,
"bnt-bnm",
}
m["bnt-bne"] = {
"Northeast Bantu",
7057832,
"bnt",
}
m["bnt-bnm"] = {
"Bangi-Ntomba",
806477,
"bnt-bte",
}
m["bnt-boa"] = {
"Boan",
4931250,
"bnt",
aliases = {"Buan", "Ababuan"},
}
m["bnt-bot"] = {
"Botatwe",
4948532,
"bnt",
}
m["bnt-bsa"] = {
"Basaa",
809739,
"bnt",
}
m["bnt-bsh"] = {
"Bushoong",
5001551,
"bnt-bte",
}
m["bnt-bso"] = {
"Southern Bantu",
980498,
"bnt",
}
m["bnt-bta"] = {
"Bati-Angba",
4869303,
"bnt-boa",
otherNames = {"Late Bomokandian"},
aliases = {"Bwa"},
}
m["bnt-btb"] = {
"Beti",
35118,
"bnt",
}
m["bnt-bte"] = {
"Bangi-Tetela",
4855181,
"bnt",
}
m["bnt-bun"] = {
"Buja-Ngombe",
4986733,
"bnt-mbb",
}
m["bnt-chg"] = {
"Chaga",
33016,
"bnt-cht",
}
m["bnt-cht"] = {
"Chaga-Taita",
nil,
"bnt-bne",
}
m["bnt-clu"] = {
"Chokwe-Luchazi",
3339273,
"bnt",
}
m["bnt-com"] = {
"Comorian",
33077,
"bnt-sab",
}
m["bnt-glb"] = {
"Great Lakes Bantu",
5599420,
"bnt-bne",
}
m["bnt-haj"] = {
"Haya-Jita",
25502360,
"bnt-glb",
}
m["bnt-kak"] = {
"Kako",
nil,
"bnt-pob",
}
m["bnt-kav"] = {
"Kavango",
116544179,
"bnt-ksb",
}
m["bnt-kbi"] = {
"Komo-Bira",
6428591,
"bnt-boa",
}
m["bnt-kel"] = {
"Kele",
1738162,
"bnt-kts",
aliases = {"Sheke"},
}
m["bnt-kil"] = {
"Kilombero",
6408121,
"bnt",
}
m["bnt-kka"] = {
"Kikuyu-Kamba",
16114410,
"bnt-bne",
aliases = {"Thagiicu"},
}
m["bnt-kmb"] = {
"Kimbundu",
16947687,
"bnt",
}
m["bnt-kng"] = {
"Kongo",
6429214,
"bnt",
}
m["bnt-kpw"] = {
"Kpwe",
36428,
"bnt-saw",
}
m["bnt-ksb"] = {
"Kavango-Southwest Bantu",
6379098,
"bnt",
}
m["bnt-kts"] = {
"Kele-Tsogo",
6385577,
"bnt",
}
m["bnt-lbn"] = {
"Luban",
4536504,
"bnt",
}
m["bnt-leb"] = {
"Lebonya",
6511395,
"bnt",
}
m["bnt-lgb"] = {
"Lega-Binja",
6517694,
"bnt",
}
m["bnt-lok"] = {
"Logooli-Kuria",
nil,
"bnt-glb",
}
m["bnt-lub"] = {
"Luba",
nil,
"bnt-lbn",
}
m["bnt-lun"] = {
"Lunda",
6704091,
"bnt",
}
m["bnt-mak"] = {
"Makua",
6740431,
"bnt-bso",
aliases = {"Makhuwa"},
}
m["bnt-mbb"] = {
"Mboshi-Buja",
6799764,
"bnt",
}
m["bnt-mbe"] = {
"Mbole-Enya",
6799728,
"bnt",
}
m["bnt-mbi"] = {
"Mbinga",
nil,
"bnt-rur",
}
m["bnt-mbo"] = {
"Mboshi",
6799763,
"bnt-mbb",
}
m["bnt-mbt"] = {
"Mbete",
1346910,
"bnt-tmb",
aliases = {"Mbere"},
}
m["bnt-mby"] = {
"Mbeya",
nil,
"bnt-ruk",
}
m["bnt-mij"] = {
"Mijikenda",
6845474,
"bnt-sab",
}
m["bnt-mka"] = {
"Makaa",
nil,
"bnt-ndb",
}
m["bnt-mne"] = {
"Manenguba",
31147471,
"bnt",
aliases = {"Mbo", "Ngoe"},
}
m["bnt-mnj"] = {
"Makaa-Njem",
1603899,
"bnt-pob",
}
m["bnt-mon"] = {
"Mongo",
nil,
"bnt-bnm",
}
m["bnt-mra"] = {
"Mbugwe-Rangi",
6799795,
"bnt",
}
m["bnt-msl"] = {
"Masaba-Luhya",
12636428,
"bnt-glb",
}
m["bnt-mwi"] = {
"Mwika",
nil,
"bnt-ruk",
}
m["bnt-ncb"] = {
"Northeast Coast Bantu",
7057848,
"bnt-bne",
}
m["bnt-ndb"] = {
"Ndzem-Bomwali",
nil,
"bnt-mnj",
}
m["bnt-ngn"] = {
"Ngondi-Ngiri",
7022532,
"bnt-mbb",
}
m["bnt-ngu"] = {
"Nguni",
961559,
"bnt-bso",
aliases = {"Ngoni"},
}
m["bnt-nya"] = {
"Nyali",
7070832,
"bnt-leb",
}
m["bnt-nyb"] = {
"Nyanga-Buyi",
7070882,
"bnt",
}
m["bnt-nyg"] = {
"Nyoro-Ganda",
12638666,
"bnt-glb",
}
m["bnt-nys"] = {
"Nyasa",
7070921,
"bnt",
}
m["bnt-nze"] = {
"Nzebi",
1755498,
"bnt-tmb",
aliases = {"Njebi"},
}
m["bnt-ova"] = {
"Ovambo",
36489,
"bnt-swb",
aliases = {"Oshivambo", "Oshiwambo", "Owambo"},
}
m["bnt-par"] = {
"Pare",
nil,
"bnt-ncb",
}
m["bnt-pen"] = {
"Pende",
7162373,
"bnt",
}
m["bnt-pob"] = {
"Pomo-Bomwali",
nil,
"bnt",
}
m["bnt-ruk"] = {
"Rukwa",
7378902,
"bnt",
}
m["bnt-run"] = {
"Rungwe",
nil,
"bnt-ruk",
}
m["bnt-rur"] = {
"Rufiji-Ruvuma",
7377947,
"bnt",
}
m["bnt-ruv"] = {
"Ruvu",
nil,
"bnt-ncb",
}
m["bnt-rvm"] = {
"Ruvuma",
nil,
"bnt-rur",
}
m["bnt-sab"] = {
"Sabaki",
2209395,
"bnt-ncb",
}
m["bnt-saw"] = {
"Sawabantu",
532003,
"bnt",
}
m["bnt-sbi"] = {
"Sabi",
7396071,
"bnt",
}
m["bnt-seu"] = {
"Seuta",
nil,
"bnt-ncb",
}
m["bnt-shh"] = {
"Shi-Havu",
nil,
"bnt-glb",
}
m["bnt-sho"] = {
"Shona",
2904660,
"bnt",
}
m["bnt-sir"] = {
"Sira",
1436372,
"bnt",
aliases = {"Shira-Punu"},
}
m["bnt-ske"] = {
"Soko-Kele",
nil,
"bnt-bte",
}
m["bnt-sna"] = {
"Sena",
nil,
"bnt-nys",
}
m["bnt-sts"] = {
"Sotho-Tswana",
2038386,
"bnt-bso",
}
m["bnt-swb"] = {
"Southwest Bantu",
116543539,
"bnt-ksb",
}
m["bnt-swh"] = {
"Swahili",
nil,
"bnt-sab",
}
m["bnt-tek"] = {
"Teke",
36528,
"bnt-tmb",
}
m["bnt-tet"] = {
"Tetela",
7706059,
"bnt-bte",
}
m["bnt-tkc"] = {
"Central Teke",
36473,
"bnt-tek",
}
m["bnt-tkm"] = {
"Takama",
nil,
"bnt-bne",
}
m["bnt-tmb"] = {
"Teke-Mbede",
7695332,
"bnt",
aliases = {"Teke-Mbere"},
}
m["bnt-tso"] = {
"Tsogo",
2458420,
otherNames = {"Okani"}, --appears to be an alias in Glottolog
"bnt-kts",
}
m["bnt-tsr"] = {
"Tswa-Ronga",
12643962,
"bnt-bso",
}
m["bnt-yak"] = {
"Yaka",
8047027,
"bnt",
}
m["bnt-yko"] = {
"Yasa-Kombe",
nil,
"bnt-saw",
}
m["bnt-zbi"] = {
"Zamba-Binza",
nil,
"bnt-bnm",
}
m["btk"] = {
"Batak",
1998595,
"poz-nws",
}
--[=[
Exceptional language and family codes for Central American Indian languages
may use the prefix "cai-", though "cai" is no longer itself a family code.
]=]--
--[=[
Exceptional language and family codes for Caucasian languages can use
the prefix "cau-", though "cau" is no longer itself a family code.
]=]--
m["cau-abz"] = {
"Abkhaz-Abaza",
4663617,
"cau-nwc",
otherNames = {"Abkhaz-Tapanta"},
aliases = {"Abazgi"},
}
m["cau-and"] = {
"Andian",
492152,
"cau-ava",
aliases = {"Andic"},
}
m["cau-ava"] = {
"Avaro-Andian",
4055404,
"cau-nec",
aliases = {"Avar-Andian", "Avar-Andi", "Avar-Andic"},
}
m["cau-cir"] = {
"Circassian",
858543,
"cau-nwc",
aliases = {"Cherkess"},
}
m["cau-drg"] = {
"Dargwa",
5222637,
"cau-nec",
otherNames = {"Dargin"},
}
m["cau-esm"] = {
"Eastern Samur",
nil,
"cau-sam",
}
m["cau-ets"] = {
"East Tsezian",
121437666,
"cau-tsz",
aliases = {"East Tsezic", "East Didoic"},
}
m["cau-lzg"] = {
"Lezghian",
2144370,
"cau-nec",
aliases = {"Lezgi", "Lezgian", "Lezgic"},
}
m["cau-nkh"] = {
"Nakh",
24441,
"cau-nec",
aliases = {"North-Central Caucasian"},
}
m["cau-nec"] = {
"Northeast Caucasian",
27387,
aliases = {"Dagestanian", "Nakho-Dagestanian", "Caspian"},
}
m["cau-nwc"] = {
"Northwest Caucasian",
33852,
aliases = {"Abkhazo-Adyghean", "Abkhaz-Adyghe", "Pontic"},
}
m["cau-sam"] = {
"Samur",
15229151,
"cau-lzg",
}
m["cau-ssm"] = {
"Southern Samur",
nil,
"cau-sam",
}
m["cau-tsz"] = {
"Tsezian",
1651530,
"cau-nec",
aliases = {"Tsezic", "Didoic"},
}
m["cau-vay"] = {
"Vainakh",
4102486,
"cau-nkh",
aliases = {"Veinakh", "Vaynakh"},
}
m["cau-wsm"] = {
"Western Samur",
nil,
"cau-sam",
}
m["cau-wts"] = {
"West Tsezian",
121437697,
"cau-tsz",
aliases = {"West Tsezic", "West Didoic"},
}
m["cba"] = {
"Chibchan",
520478,
"qfa-mch", -- or none if Macro-Chibchan is considered undemonstrated
}
m["ccs"] = {
"Kartvelian",
34030,
aliases = {"South Caucasian"},
}
m["ccs-gzn"] = {
"Georgian-Zan",
34030,
"ccs",
aliases = {"Karto-Zan"},
}
m["ccs-zan"] = {
"Zan",
2606912,
"ccs-gzn",
aliases = {"Zanuri", "Colchian"},
}
m["cdc"] = {
"Chadic",
33184,
"afa",
}
m["cdc-cbm"] = {
"Central Chadic",
2251547,
"cdc",
aliases = {"Biu-Mandara"},
}
m["cdc-est"] = {
"East Chadic",
2276221,
"cdc",
}
m["cdc-mas"] = {
"Masa",
2136092,
"cdc",
}
m["cdc-wst"] = {
"West Chadic",
2447774,
"cdc",
}
m["cdd"] = {
"Caddoan",
1025090,
}
m["cel"] = {
"Celtic",
25293,
"ine",
}
m["cel-bry"] = {
"Brythonic",
156877,
"cel-ins",
aliases = {"Brittonic"},
}
m["cel-brs"] = {
"Southwestern Brythonic",
2612853,
"cel-bry",
aliases = {"Southwestern Brittonic"},
}
m["cel-brw"] = {
"Western Brythonic",
593069,
"cel-bry",
aliases = {"Western Brittonic"},
}
m["cel-gae"] = {
"Goidelic",
56433,
"cel-ins",
aliases = {"Gaelic"},
protoLanguage = "pgl",
}
m["cel-his"] = {
"Hispano-Celtic",
4204136,
"cel",
}
m["cel-ins"] = {
"Insular Celtic",
214506,
"cel",
}
m["chi"] = {
"Chimakuan",
1073088,
}
m["chm"] = {
"Mari",
973685,
"urj",
}
m["cmc"] = {
"Chamic",
2997506,
"poz-mcm",
}
m["crp"] = {
"creole or pidgin",
19682167,
"qfa-cnt",
}
m["csu"] = {
"Central Sudanic",
190822,
"ssa",
}
m["csu-bba"] = {
"Bongo-Bagirmi",
3505042,
"csu",
}
m["csu-bbk"] = {
"Bongo-Baka",
4941917,
"csu-bba",
}
m["csu-bgr"] = {
"Bagirmi",
4841948,
"csu-bba",
aliases = {"Bagirmic"},
}
m["csu-bkr"] = {
"Birri-Kresh",
nil,
"csu",
}
m["csu-ecs"] = {
"Eastern Central Sudanic",
16911698,
"csu",
aliases = {"East Central Sudanic", "Central Sudanic East", "Lendu-Mangbetu"},
}
m["csu-kab"] = {
"Kaba",
6343715,
"csu-bba",
}
m["csu-lnd"] = {
"Lendu",
6522357,
"csu-ecs",
aliases = {"Lenduic"},
}
m["csu-maa"] = {
"Mangbetu",
6748874,
"csu-ecs",
aliases = {"Mangbetu-Asoa", "Mangbetu-Asua"},
}
m["csu-mle"] = {
"Mangbutu-Lese",
17009406,
"csu-ecs",
aliases = {"Mangbutu-Efe", "Mangbutu", "Membi-Mangbutu-Efe"},
}
m["csu-mma"] = {
"Moru-Madi",
6915156,
"csu-ecs",
}
m["csu-sar"] = {
"Sara",
2036691,
"csu-bba",
}
m["csu-val"] = {
"Vale",
7909520,
"csu-bba",
}
m["cus"] = {
"Cushitic",
33248,
"afa",
}
m["cus-cen"] = {
"Central Cushitic",
56569,
"cus",
}
m["cus-eas"] = {
"East Cushitic",
56568,
"cus",
}
m["cus-hec"] = {
"Highland East Cushitic",
56524,
"cus-eas",
}
m["cus-som"] = {
"Somaloid",
56774,
"cus-eas",
aliases = {"Sam", "Macro-Somali"},
}
m["cus-sou"] = {
"South Cushitic",
56525,
"cus",
}
m["day"] = {
"Land Dayak",
2760613,
"poz",
}
m["del"] = {
"Lenape",
2665761,
"alg-eas",
aliases = {"Delaware"},
}
m["den"] = {
"Slavey",
13272,
"ath-nor",
aliases = {"Slave", "Slavé"},
}
m["dmn"] = {
"Mande",
33681,
"nic",
}
m["dmn-bbu"] = {
"Bisa-Busa",
12627956,
"dmn-mde",
}
m["dmn-emn"] = {
"East Manding",
nil,
"dmn-man",
}
m["dmn-jje"] = {
"Jogo-Jeri",
nil,
"dmn-mjo",
}
m["dmn-man"] = {
"Manding",
35772,
"dmn-mmo",
}
m["dmn-mda"] = {
"Mano-Dan",
nil,
"dmn-mse",
}
m["dmn-mdc"] = {
"Central Mande",
5972907,
"dmn-mdw",
}
m["dmn-mde"] = {
"Eastern Mande",
12633080,
"dmn",
}
m["dmn-mdw"] = {
"Western Mande",
16113831,
"dmn",
}
m["dmn-mjo"] = {
"Manding-Jogo",
12636153,
"dmn-mdc",
}
m["dmn-mmo"] = {
"Manding-Mokole",
nil,
"dmn-mva",
}
m["dmn-mnk"] = {
"Maninka",
36186,
"dmn-emn",
}
m["dmn-mnw"] = {
"Northwestern Mande",
5972910,
"dmn-mdw",
}
m["dmn-mok"] = {
"Mokole",
16935447,
"dmn-mmo",
}
m["dmn-mse"] = {
"Southeastern Mande",
5972912,
"dmn-mde",
}
m["dmn-msw"] = {
"Southwestern Mande",
12633904,
"dmn-mdw",
}
m["dmn-mva"] = {
"Manding-Vai",
nil,
"dmn-mjo",
}
m["dmn-nbe"] = {
"Nwa-Beng",
nil,
"dmn-mse",
}
m["dmn-sam"] = {
"Samo",
36327,
"dmn-bbu",
aliases = {"Samuic"},
}
m["dmn-smg"] = {
"Samogo",
7410000,
"dmn-mnw",
aliases = {"Duun-Seenku"},
}
m["dmn-snb"] = {
"Soninke-Bobo",
16111680,
"dmn-mnw",
}
m["dmn-sya"] = {
"Susu-Yalunka",
nil,
"dmn-mdc",
}
m["dmn-vak"] = {
"Vai-Kono",
nil,
"dmn-mva",
}
m["dmn-wmn"] = {
"West Manding",
nil,
"dmn-man",
}
m["dra"] = {
"Dravidian",
33311,
}
m["dra-cen"] = {
"Central Dravidian",
12628823,
"dra",
}
m["dra-gki"] = {
"Gondi-Kui",
12631610,
"dra-sdt",
}
m["dra-gon"] = {
"Gondi",
55639812,
"dra-gki",
}
m["dra-imd"] = {
"Irula-Muduga",
nil,
"dra-tkn",
}
m["dra-kan"] = {
"Kannadoid",
6363888,
"dra-tkn",
protoLanguage = "dra-okn",
}
m["dra-kki"] = {
"Konda-Kui",
nil,
"dra-gki",
}
m["dra-kml"] = {
"Kurukh-Malto",
68002822,
"dra-nor",
}
m["dra-knk"] = {
"Kolami-Naiki",
10547037,
"dra-cen",
}
m["dra-kod"] = {
"Kodagu",
67983106,
"dra-tkd",
}
m["dra-kor"] = {
"Koraga",
33394,
"dra-tlk",
}
m["dra-mal"] = {
"Malayalamoid",
6741581,
"dra-tml",
}
m["dra-mdy"] = {
"Madiya",
27602,
"dra-gon",
}
m["dra-mlo"] = {
"Malto",
nil,
"dra-kml",
}
m["dra-mur"] = {
"Muria",
6938499,
"dra-gon",
}
m["dra-nor"] = {
"North Dravidian",
16110967,
"dra",
}
m["dra-pgd"] = {
"Parji-Gadaba",
10620428,
"dra-cen",
}
m["dra-sdo"] = {
"South Dravidian I",
16112843, -- Wikipedia's "South Dravidian" is South Dravidian I in this scheme.
"dra-sou",
aliases = {"South Dravidian"}, -- This is why I and II are used.
}
m["dra-sdt"] = {
"South Dravidian II",
12633975,
"dra-sou",
aliases = {"South-Central Dravidian"},
}
m["dra-sou"] = {
"South Dravidian",
128886618,
"dra",
aliases = {"Southern Dravidian"},
}
m["dra-tam"] = {
"Tamiloid",
7681417,
"dra-tml",
protoLanguage = "oty",
}
m["dra-tel"] = {
"Teluguic",
nil,
"dra-sdt",
protoLanguage = "dra-ote",
}
m["dra-tkd"] = {
"Tamil-Kodagu",
25494510,
"dra-tkn",
}
m["dra-tkn"] = {
"Tamil-Kannada",
6478506,
"dra-sdo",
}
m["dra-tkt"] = {
"Toda-Kota",
67983857,
"dra-tkd",
}
m["dra-tlk"] = {
"Tulu-Koraga",
nil,
"dra-sdo",
}
m["dra-tml"] = {
"Tamil-Malayalam",
10690507,
"dra-tkd",
}
m["egx"] = {
"Egyptian",
50868,
"afa",
protoLanguage = "egy",
}
m["ero"] = {
"Horpa",
56854,
"sit-wgy",
}
m["esx"] = {
"Eskimo-Aleut",
25946,
}
m["esx-esk"] = {
"Eskimo",
25946,
"esx",
}
m["esx-inu"] = {
"Inuit",
27796,
"esx-esk",
}
m["euq"] = {
"Vasconic",
4669240,
}
m["gba"] = {
"Gbaya",
3099986,
"alv-sav",
}
m["gba-eas"] = {
"Eastern Gbaya",
nil,
"gba",
}
m["gba-sou"] = {
"Southern Gbaya",
nil,
"gba",
}
m["gba-wes"] = {
"Western Gbaya",
nil,
"gba",
}
m["gem"] = {
"Germanic",
21200,
"ine",
}
m["gio"] = {
"Gelao",
56401,
"qfa-kra",
}
m["gme"] = {
"East Germanic",
108662,
"gem",
}
m["gmq"] = {
"North Germanic",
106085,
"gem",
}
m["gmq-eas"] = {
"East Scandinavian",
3090263,
"gmq",
protoLanguage = "non-oen",
}
m["gmq-ins"] = {
"Insular Scandinavian",
nil,
"gmq-wes",
}
m["gmq-wes"] = {
"West Scandinavian",
1792570,
"gmq",
protoLanguage = "non-own",
}
m["gmw"] = {
"West Germanic",
26721,
"gem",
}
m["gmw-afr"] = {
"Anglo-Frisian",
5329170,
"gmw-nsg",
}
m["gmw-ang"] = {
"Anglic",
1346342,
"gmw-afr",
protoLanguage = "ang",
}
m["gmw-fri"] = {
"Frisian",
25325,
"gmw-afr",
protoLanguage = "ofs",
}
m["gmw-frk"] = {
"Low Franconian",
153050,
"gmw",
protoLanguage = "frk",
}
m["gmw-hgm"] = {
"High German",
52040,
"gmw",
protoLanguage = "goh",
}
m["gmw-ian"] = {
"Irish Anglo-Norman",
120719384,
"gmw-ang",
protoLanguage = "enm",
}
m["gmw-lgm"] = {
"Low German",
25433,
"gmw-nsg",
protoLanguage = "osx",
}
m["gmw-nsg"] = {
"North Sea Germanic",
30134,
"gmw",
aliases = {"Ingvaeonic"},
}
m["grk"] = {
"Hellenic",
2042538,
"ine",
aliases = {"Greek"},
}
m["him"] = {
"Western Pahari",
10939493,
"inc-pah",
aliases = {"Himachali"},
}
m["hmn"] = {
"Hmong",
3307894,
"hmx",
}
m["hmx"] = {
"Hmong-Mien",
33322,
aliases = {"Miao-Yao"},
}
m["hmx-mie"] = {
"Mien",
7992695,
"hmx",
}
m["hok"] = {
"Hokan",
33406,
}
m["hyx"] = {
"Armenian",
8785,
"ine",
}
m["iir"] = {
"Indo-Iranian",
33514,
"ine",
}
m["iir-nur"] = {
"Nuristani",
161804,
"iir",
}
m["nur-nor"] = {
"Northern Nuristani",
nil,
"iir-nur",
}
m["nur-sou"] = {
"Southern Nuristani",
nil,
"iir-nur",
}
m["ijo"] = {
"Ijoid",
1325759,
"nic",
otherNames = {"Ijaw"}, -- Ijaw may be a subfamily
}
m["inc"] = {
"Indo-Aryan",
33577,
"iir",
aliases = {"Indic"},
}
m["inc-bas"] = {
"Bengali-Assamese",
4179137,
"inc-eas",
aliases = {"Assamese-Bengali", "Gauda-Kamarupa"},
}
m["inc-bhi"] = {
"Bhil",
4901727,
"inc-cen",
}
m["inc-bih"] = {
"Bihari",
135305,
"inc-eas",
}
m["inc-cen"] = {
"Central Indo-Aryan",
10979187,
"inc",
protoLanguage = "inc-asa",
}
m["inc-chi"] = {
"Chitrali",
11732797,
"inc-dar",
}
m["inc-dar"] = {
"Dardic",
161101,
"inc",
protoLanguage = "inc-ash",
}
m["inc-dre"] = {
"Eastern Dardic",
nil,
"inc-dar",
}
m["inc-eas"] = {
"Eastern Indo-Aryan",
12593391,
"inc",
protoLanguage = "inc-aav",
}
m["inc-hal"] = {
"Halbic",
16910593,
"inc-eas",
aliases = {"Halbi"},
}
m["inc-hie"] = {
"Eastern Hindi",
4126648,
"inc-cen",
aliases = {"Purabiyā"},
protoLanguage = "inc-apa",
}
m["inc-hiw"] = {
"Western Hindi",
12600937,
"inc-cen",
protoLanguage = "inc-ohi",
}
m["inc-hnd"] = {
"Hindustani",
11051,
"inc-hiw",
aliases = {"Hindi-Urdu"},
protoLanguage = "hi-mid",
}
m["inc-ins"] = {
"Insular Indo-Aryan",
12179302,
"inc",
protoLanguage = "inc-apa",
}
m["inc-kas"] = {
"Kashmiric",
nil,
"inc-dre",
aliases = {"Kashmiri"},
}
m["inc-koh"] = {
"Kohistani",
13018610,
"inc-dre",
}
m["inc-krd"] = {
"KRDS lects",
6356154,
"inc-eas",
aliases = {"Kamta, Rajbanshi, Deshi and Surjapuri", "KRNB lects", "Kamta, Rajbanshi and Northern Deshi Bangla"},
}
m["inc-kun"] = {
"Kunar",
nil,
"inc-dar",
}
m["inc-mid"] = {
"Middle Indo-Aryan",
3236316,
"inc",
aliases = {"Middle Indic"},
}
m["inc-nwe"] = {
"Northwestern Indo-Aryan",
16111018,
"inc",
protoLanguage = "pra-pai",
}
m["inc-nor"] = {
"Northern Indo-Aryan",
946077,
"inc",
protoLanguage = "inc-aka",
}
m["inc-old"] = {
"Old Indo-Aryan",
118976896,
"inc",
aliases = {"Old Indic"},
}
m["inc-pah"] = {
"Pahari",
946077,
"inc-nor",
aliases = {"Pahadi"},
protoLanguage = "inc-aka",
}
m["inc-pan"] = {
"Punjabic",
2656685,
"inc-nwe",
aliases = {"Greater Punjabic"},
protoLanguage = "inc-ata",
}
m["inc-pas"] = {
"Pashayi",
36670,
"inc-dar",
aliases = {"Pashai"},
}
m["inc-rom"] = {
"Romani",
13201,
"inc-wes",
aliases = {"Romany", "Gypsy", "Gipsy"},
}
m["inc-shn"] = {
"Shinaic",
12646125,
"inc-dre",
}
m["inc-snd"] = {
"Sindhic",
7522212,
"inc-nwe",
protoLanguage = "inc-avr",
}
m["inc-sou"] = {
"Southern Indo-Aryan",
10856062,
"inc",
protoLanguage = "inc-ama",
}
m["inc-tha"] = {
"Tharu",
34035,
"inc-eas",
}
m["inc-wes"] = {
"Western Indo-Aryan",
nil,
"inc",
protoLanguage = "inc-agu",
}
m["ine"] = {
"Indo-European",
19860,
aliases = {"Indo-Germanic"},
}
m["ine-ana"] = {
"Anatolian",
147085,
"ine",
}
m["ine-bsl"] = {
"Balto-Slavic",
147356,
"ine",
}
m["ine-toc"] = {
"Tocharian",
37029,
"ine",
aliases = {"Tokharian"},
}
m["ira"] = {
"Iranian",
33527,
"iir",
}
m["ira-csp"] = {
"Caspian",
5049123,
"ira-mpr",
}
m["ira-cen"] = {
"Central Iranian",
nil,
"ira",
}
m["ira-kms"] = {
"Komisenian",
nil,
"ira-mpr",
aliases = {"Semnani"},
}
m["ine-luw"] = {
"Luwic",
115748615,
"ine-ana",
aliases = {"Luvic"},
}
m["ira-mid"] = {
"Middle Iranian",
6841465,
"ira",
}
m["ira-mny"] = {
"Munji-Yidgha",
nil,
"ira-sym",
aliases = {"Yidgha-Munji"},
}
m["ira-msh"] = {
"Mazanderani-Shahmirzadi",
nil,
"ira-csp",
}
m["ira-nei"] = {
"Northeastern Iranian",
10775567,
"ira",
}
m["ira-nwi"] = {
"Northwestern Iranian",
390576,
"ira-wes",
}
m["ira-old"] = {
"Old Iranian",
23301845,
"ira",
}
m["ira-orp"] = {
"Ormuri-Parachi",
nil,
"ira-sei",
}
m["ira-pat"] = {
"Pathan",
nil,
"ira-sei",
}
m["ira-sbc"] = {
"Sogdo-Bactrian",
nil,
"ira-nei",
}
m["ira-mpr"] = {
"Medo-Parthian",
nil,
"ira-nwi",
aliases = {"Partho-Median"},
}
m["ira-sgi"] = {
"Sanglechi-Ishkashimi",
18711232,
"ira-sei",
}
m["ira-shr"] = {
"Shughni-Roshani",
11732824,
"ira-shy",
}
m["ira-shy"] = {
"Shughni-Yazghulami",
nil,
"ira-sym",
}
m["ira-sgc"] = {
"Sogdic",
nil,
"ira-sbc",
aliases = {"Sogdian"},
}
m["ira-sei"] = {
"Southeastern Iranian",
3833002,
"ira",
}
m["ira-swi"] = {
"Southwestern Iranian",
390424,
"ira-wes",
}
m["ira-sym"] = {
"Shughni-Yazghulami-Munji",
nil,
"ira-sei",
}
m["ira-wes"] = {
"Western Iranian",
129850,
"ira",
}
m["ira-zgr"] = {
"Zaza-Gorani",
167854,
"ira-mpr",
aliases = {"Zaza-Gurani", "Gorani-Zaza"},
}
m["iro"] = {
"Iroquoian",
33623,
}
m["iro-nor"] = {
"North Iroquoian",
nil,
"iro",
}
m["itc"] = {
"Italic",
131848,
"ine",
}
m["itc-laf"] = {
"Latino-Faliscan",
33478,
"itc",
aliases = {"Latinian"},
}
m["itc-sbl"] = {
"Osco-Umbrian",
515194,
"itc",
aliases = {"Sabellic", "Sabellian"},
}
m["jpx"] = {
"Japonic",
33612,
aliases = {"Japanese", "Japanese-Ryukyuan"},
}
m["jpx-nry"] = {
"Northern Ryukyuan",
20862796,
"jpx-ryu",
}
m["jpx-ryu"] = {
"Ryukyuan",
56393,
"jpx",
}
m["jpx-sry"] = {
"Southern Ryukyuan",
18392243,
"jpx-ryu",
}
m["kar"] = {
"Karen",
1364815,
"sit",
}
m["kca"] = {
"Khanty",
33563,
"urj-ugr",
aliases = {"Khantyic", "Khantic"},
}
--[=[
Exceptional language and family codes for Khoisan and Kordofanian languages can use
the prefix "khi-" and "kdo-" respectively, though they are no longer family codes themselves.
]=]--
m["khi-kal"] = {
"Kalahari Khoe",
nil,
"khi-kho",
}
m["khi-khk"] = {
"Khoekhoe",
nil,
"khi-kho",
}
m["khi-kkw"] = {
"Khoe-Kwadi",
60785084,
aliases = {"Kwadi-Khoe"},
}
m["khi-kho"] = {
"Khoe",
2736449,
"khi-kkw",
aliases = {"Central Khoisan"},
}
m["khi-kxa"] = {
"Kx'a",
6450587,
aliases = {"Kxa", "Ju-ǂHoan"},
}
m["khi-tuu"] = {
"Tuu",
631046,
aliases = {"Kwi", "Taa-Kwi", "Southern Khoisan", "Taa-ǃKwi", "Taa-ǃUi", "ǃUi-Taa"},
}
m["kro"] = {
"Kru",
33535,
"nic-vco",
}
m["kro-aiz"] = {
"Aizi",
4699431,
"kro",
}
m["kro-bet"] = {
"Bété",
32956,
"kro-ekr",
}
m["kro-did"] = {
"Dida",
32685,
"kro-ekr",
}
m["kro-ekr"] = {
"Eastern Kru",
5972899,
"kro",
}
m["kro-grb"] = {
"Grebo",
5601537,
"kro-wkr",
}
m["kro-wee"] = {
"Wee",
nil,
"kro-wkr",
}
m["kro-wkr"] = {
"Western Kru",
5972897,
"kro",
}
m["ku"] = {
"Kurdish",
36368,
"ira-nwi",
}
m["map"] = {
"Austronesian",
49228,
}
m["map-ata"] = {
"Atayalic",
716610,
"map",
}
m["mjg"] = {
"Monguor",
34214,
"xgn-shr",
}
m["mkh"] = {
"Mon-Khmer",
33199,
"aav",
}
m["mkh-asl"] = {
"Aslian",
3111082,
"mkh",
}
m["mkh-ban"] = {
"Bahnaric",
56309,
"mkh",
}
m["mkh-kat"] = {
"Katuic",
56697,
"mkh",
}
m["mkh-khm"] = {
"Khmuic",
1323245,
"mkh",
}
m["mkh-kmr"] = {
"Khmeric",
nil,
"mkh",
}
m["mkh-mnc"] = {
"Monic",
3217497,
"mkh",
}
m["mkh-mng"] = {
"Mangic",
3509556,
"mkh",
}
m["mkh-nbn"] = {
"North Bahnaric",
56309,
"mkh-ban",
}
m["mkh-pal"] = {
"Palaungic",
2391173,
"mkh",
}
m["mkh-pea"] = {
"Pearic",
3073022,
"mkh",
}
m["mkh-pkn"] = {
"Pakanic",
nil,
"mkh-mng",
}
m["mkh-vie"] = {
"Vietic",
2355546,
"mkh",
}
m["mno"] = {
"Manobo",
3217483,
"phi",
}
m["mns"] = {
"Mansi",
33759,
"urj-ugr",
aliases = {"Mansic"},
}
m["mun"] = {
"Munda",
33892,
"aav",
}
m["myn"] = {
"Mayan",
33738,
}
--[=[
Exceptional language and family codes for North American Indian languages
can use the prefix "nai-", though "nai" is no longer itself a family code.
]=]--
m["nai-cat"] = {
"Catawban",
3446638,
"nai-sca",
}
m["nai-chu"] = {
"Chumashan",
1288420,
}
m["nai-ckn"] = {
"Chinookan",
610586,
}
m["nai-coo"] = {
"Coosan",
940278,
}
m["nai-jcq"] = {
"Jicaquean",
12179308,
"hok"
}
m["nai-ker"] = {
"Keresan",
35878,
}
m["nai-klp"] = {
"Kalapuyan",
1569040,
}
m["nai-kta"] = {
"Kiowa-Tanoan",
386288,
}
m["nai-len"] = {
"Lencan",
36189,
aliases = {"Lenca"},
}
m["nai-mdu"] = {
"Maiduan",
33502,
}
m["nai-miz"] = {
"Mixe-Zoquean",
954016,
aliases = {"Mixe-Zoque"},
}
m["nai-min"] = {
"Misumalpan",
281693,
"qfa-mch",
aliases = {"Misuluan", "Misumalpa"},
}
m["nai-mus"] = {
"Muskogean",
902978,
aliases = {"Muskhogean"},
}
m["nai-pak"] = {
"Pakawan",
65085487,
"hok",
}
m["nai-pal"] = {
"Palaihnihan",
1288332,
}
m["nai-plp"] = {
"Plateau Penutian",
2307476,
}
m["nai-pom"] = {
"Pomoan",
2618420,
"hok",
aliases = {"Pomo", "Kulanapan"},
}
m["nai-sca"] = {
"Siouan-Catawban",
34181,
}
m["nai-shp"] = {
"Sahaptian",
114782,
"nai-plp",
}
m["nai-shs"] = {
"Shastan",
2991735,
"hok",
}
m["nai-tot"] = {
"Totozoquean",
7828419,
}
m["nai-ttn"] = {
"Totonacan",
34039,
aliases = {"Totonac-Tepehua", "Totonacan-Tepehuan"},
varieties = {"Totonac"},
}
m["nai-tqn"] = {
"Tequistlatecan",
1568317,
"hok",
aliases = {"Tequistlatec", "Chontal", "Chontalan", "Oaxacan Chontal", "Chontal of Oaxaca"},
}
m["nai-tsi"] = {
"Tsimshianic",
34134,
}
m["nai-utn"] = {
"Utian",
13371763,
"nai-you",
aliases = {"Miwok-Costanoan", "Mutsun"},
}
m["nai-wtq"] = {
"Wintuan",
1294259,
aliases = {"Wintun"},
}
m["nai-xin"] = {
"Xincan",
1546494,
aliases = {"Xinca"},
}
m["nai-ykn"] = {
"Yukian",
2406722,
aliases = {"Yuki-Wappo"},
}
m["nai-you"] = {
"Yok-Utian",
2886186,
}
m["nai-yuc"] = {
"Yuman-Cochimí",
579137,
}
m["ngf"] = {
"Trans-New Guinea",
34018,
}
m["ngf-fin"] = {
"Finisterre",
5450373,
"ngf",
}
m["ngf-mad"] = {
"Madang",
11217556,
"ngf",
}
m["ngf-okk"] = {
"Ok",
7081687,
"ngf",
}
m["ngf-sbh"] = {
"South Bird's Head",
7566330,
"ngf",
}
m["nic"] = {
"Niger-Congo",
33838,
aliases = {"Niger-Kordofanian"},
}
m["nic-alu"] = {
"Alumic",
4737355,
"nic-plt",
}
m["nic-bas"] = {
"Basa",
4866154,
"nic-knj",
}
m["nic-bbe"] = {
"Eastern Beboid",
nil,
"nic-beb",
}
m["nic-bco"] = {
"Benue-Congo",
33253,
"nic-vco",
}
m["nic-bcr"] = {
"Bantoid-Cross",
806983,
"nic-bco",
}
m["nic-bdn"] = {
"Northern Bantoid",
nil,
"nic-bod",
aliases = {"North Bantoid"},
}
m["nic-bds"] = {
"Southern Bantoid",
3183152,
"nic-bod",
aliases = {"Wide Bantu", "Bin"},
}
m["nic-beb"] = {
"Beboid",
813549,
"nic-bds",
}
m["nic-ben"] = {
"Bendi",
4887065,
"nic-bcr",
}
m["nic-beo"] = {
"Beromic",
4894642,
"nic-plt",
}
m["nic-bod"] = {
"Bantoid",
806992,
"nic-bcr",
}
m["nic-buk"] = {
"Buli-Koma",
nil,
"nic-ovo",
}
m["nic-bwa"] = {
"Bwa",
12628562,
"nic-gur",
otherNames = {"Bwamu", "Bomu"},
}
m["nic-cde"] = {
"Central Delta",
3813191,
"nic-cri",
}
m["nic-cri"] = {
"Cross River",
1141096,
"nic-bcr",
}
m["nic-dag"] = {
"Dagbani",
nil,
"nic-wov",
}
m["nic-dak"] = {
"Dakoid",
1157745,
"nic-bdn",
}
m["nic-dge"] = {
"Escarpment Dogon",
5397128,
"qfa-dgn",
}
m["nic-dgw"] = {
"West Dogon",
nil,
"qfa-dgn",
}
m["nic-eko"] = {
"Ekoid",
1323395,
"nic-bds",
}
m["nic-eov"] = {
"Eastern Oti-Volta",
nil,
"nic-ovo",
aliases = {"Samba"},
}
m["nic-fru"] = {
"Furu",
5509783,
"nic-bds",
}
m["nic-gne"] = {
"Eastern Gurunsi",
12633072,
"nic-gns",
aliases = {"Eastern Grũsi"},
}
m["nic-gnn"] = {
"Northern Gurunsi",
nil,
"nic-gns",
aliases = {"Northern Grũsi"},
}
m["nic-gnw"] = {
"Western Gurunsi",
nil,
"nic-gns",
aliases = {"Western Grũsi"},
}
m["nic-gns"] = {
"Gurunsi",
721007,
"nic-gur",
aliases = {"Grũsi"},
}
m["nic-gre"] = {
"Eastern Grassfields",
5330160,
"nic-grf",
}
m["nic-grf"] = {
"Grassfields",
750932,
"nic-bds",
aliases = {"Grassfields Bantu", "Wide Grassfields"},
}
m["nic-grm"] = {
"Gurma",
30587833,
"nic-ovo",
}
m["nic-grs"] = {
"Southwest Grassfields",
7571285,
"nic-grf",
}
m["nic-gur"] = {
"Gur",
33536,
"alv-sav",
aliases = {"Voltaic"},
}
m["nic-ief"] = {
"Ibibio-Efik",
2743643,
"nic-lcr",
}
m["nic-jer"] = {
"Jera",
nil,
"nic-kne",
}
m["nic-jkn"] = {
"Jukunoid",
1711622,
"nic-pla",
}
m["nic-jrn"] = {
"Jarawan",
1683430,
"nic-mba",
}
m["nic-jrw"] = {
"Jarawa",
35423,
"nic-jrn",
}
m["nic-kam"] = {
"Kambari",
6356294,
"nic-knj",
}
m["nic-ktl"] = {
"Katloid",
nil,
"nic",
}
m["nic-kau"] = {
"Kauru",
nil,
"nic-kne",
}
m["nic-kmk"] = {
"Kamuku",
6359821,
"nic-knj",
}
m["nic-kne"] = {
"East Kainji",
5328687,
"nic-knj",
}
m["nic-knj"] = {
"Kainji",
681495,
"nic-pla",
}
m["nic-knn"] = {
"Northwest Kainji",
7060098,
"nic-knj",
}
m["nic-ktl"] = {
"Katloid",
6377681,
"nic",
aliases = {"Katla", "Katla-Tima"},
}
m["nic-lcr"] = {
"Lower Cross River",
3813193,
"nic-cri",
}
m["nic-mam"] = {
"Mamfe",
2005898,
"nic-bds",
aliases = {"Nyang"},
}
m["nic-mba"] = {
"Mbam",
687826,
"nic-bds",
}
m["nic-mbc"] = {
"Mba",
6799561,
"nic-ubg",
}
m["nic-mbw"] = {
"West Mbam",
nil,
"nic-mba",
}
m["nic-mmb"] = {
"Mambiloid",
1888151,
otherNames = {"North Bantoid"}, -- per Wikipedia, North Bantoid is the parent family
"nic-bdn",
}
m["nic-mom"] = {
"Momo",
6897393,
"nic-grf",
}
m["nic-mre"] = {
"Moré",
nil,
"nic-wov",
}
m["nic-ngd"] = {
"Ngbandi",
36439,
"nic-ubg",
}
m["nic-nge"] = {
"Ngemba",
7022271,
"nic-gre",
}
m["nic-ngk"] = {
"Ngbaka",
3217499,
"nic-ubg",
}
m["nic-nin"] = {
"Ninzic",
7039282,
"nic-plt",
}
m["nic-nka"] = {
"Nkambe",
7042520,
"nic-gre",
}
m["nic-nkb"] = {
"Baka",
nil,
"nic-nkw",
}
m["nic-nke"] = {
"Eastern Ngbaka",
nil,
"nic-ngk",
}
m["nic-nkg"] = {
"Gbanziri",
nil,
"nic-nkw",
}
m["nic-nkk"] = {
"Kpala",
nil,
"nic-nkw",
}
m["nic-nkm"] = {
"Mbaka",
nil,
"nic-nkw",
}
m["nic-nkw"] = {
"Western Ngbaka",
nil,
"nic-ngk",
}
m["nic-npd"] = {
"North Plateau Dogon",
nil,
"qfa-dgn",
}
m["nic-nun"] = {
"Nun",
13654297,
"nic-gre",
}
m["nic-nwa"] = {
"Nanga-Walo",
nil,
"qfa-dgn",
}
m["nic-ogo"] = {
"Ogoni",
2350726,
"nic-cri",
aliases = {"Ogonoid"},
}
m["nic-ovo"] = {
"Oti-Volta",
1157178,
"nic-gur",
}
m["nic-pla"] = {
"Platoid",
453244,
"nic-bco",
aliases = {"Central Nigerian"},
}
m["nic-plc"] = {
"Central Plateau",
5061668,
"nic-plt",
}
m["nic-pld"] = {
"Plains Dogon",
nil,
"qfa-dgn",
}
m["nic-ple"] = {
"East Plateau",
5329154,
"nic-plt",
}
m["nic-pls"] = {
"South Plateau",
7568236,
"nic-plt",
aliases = {"Jilic-Eggonic"},
}
m["nic-plt"] = {
"Plateau",
1267471,
"nic-pla",
}
m["nic-ras"] = {
"Rashad",
3401986,
"nic",
}
m["nic-rnc"] = {
"Central Ring",
nil,
"nic-rng",
}
m["nic-rng"] = {
"Ring",
2269051,
"nic-grf",
aliases = {"Ring Road"},
}
m["nic-rnn"] = {
"Northern Ring",
nil,
"nic-rng",
}
m["nic-rnw"] = {
"Western Ring",
nil,
"nic-rng",
}
m["nic-ser"] = {
"Sere",
7453058,
"nic-ubg",
}
m["nic-shi"] = {
"Shiroro",
7498953,
"nic-knj",
aliases = {"Pongu"},
}
m["nic-sis"] = {
"Sisaala",
36532,
"nic-gnw",
}
m["nic-tar"] = {
"Tarokoid",
2394472,
"nic-plt",
}
m["nic-tiv"] = {
"Tivoid",
752377,
"nic-bds",
}
m["nic-tvc"] = {
"Central Tivoid",
nil,
"nic-tiv",
}
m["nic-tvn"] = {
"Northern Tivoid",
nil,
"nic-tiv",
}
m["nic-ubg"] = {
"Ubangian",
33932,
"nic-vco", -- or none
}
m["nic-uce"] = {
"East-West Upper Cross River",
nil,
"nic-ucr",
}
m["nic-ucn"] = {
"North-South Upper Cross River",
nil,
"nic-ucr",
}
m["nic-ucr"] = {
"Upper Cross River",
4108624,
"nic-cri",
aliases = {"Upper Cross"},
}
m["nic-vco"] = {
"Volta-Congo",
37228,
"alv",
}
m["nic-wov"] = {
"Western Oti-Volta",
nil,
"nic-ovo",
aliases = {"Moré-Dagbani"}
}
m["nic-ykb"] = {
"Yukubenic",
16909196,
"nic-plt",
aliases = {"Oohum"},
}
m["nic-ymb"] = {
"Yambasa",
nil,
"nic-mba",
}
m["nic-yon"] = {
"Yom-Nawdm",
nil,
"nic-ovo",
aliases = {"Moré-Dagbani"}
}
m["nub"] = {
"Nubian",
1517194,
"sdv-nes",
}
m["nub-hil"] = {
"Hill Nubian",
5762211,
"nub",
aliases = {"Kordofan Nubian"},
}
m["omq"] = {
"Oto-Manguean",
33669,
}
m["omq-cha"] = {
"Chatino",
35111,
"omq-zap",
}
m["omq-chi"] = {
"Chinantecan",
35828,
"omq",
}
m["omq-cui"] = {
"Cuicatec",
616024,
"omq-mix",
}
m["omq-maz"] = {
"Mazatecan",
36230,
"omq",
aliases = {"Mazatec"},
}
m["omq-mix"] = {
"Mixtecan",
21083066,
"omq",
}
m["omq-mxt"] = {
"Mixtec",
36363,
"omq-mix",
}
m["omq-otp"] = {
"Oto-Pamean",
nil,
"omq",
}
m["omq-pop"] = {
"Popolocan",
5132273,
"omq",
}
m["omq-tri"] = {
"Trique",
780200,
"omq-mix",
aliases = {"Triqui"},
}
m["omq-zap"] = {
"Zapotecan",
8066463,
"omq",
}
m["omq-zpc"] = {
"Zapotec",
13214,
"omq-zap",
}
m["omv"] = {
"Omotic",
33860,
"afa",
}
m["omv-aro"] = {
"Aroid",
3699526,
"omv",
aliases = {"Ari-Banna", "South Omotic", "Somotic"},
}
m["omv-diz"] = {
"Dizoid",
430251,
"omv",
aliases = {"Maji", "Majoid"},
}
m["omv-eom"] = {
"East Ometo",
20527288,
"omv-ome",
}
m["omv-gon"] = {
"Gonga",
4143043,
"omv",
aliases = {"Kefoid"},
}
m["omv-mao"] = {
"Mao",
1351495,
"omv",
}
m["omv-nom"] = {
"North Ometo",
nil,
"omv-ome",
}
m["omv-ome"] = {
"Ometo",
36310,
"omv",
}
m["oto"] = {
"Otomian",
1270220,
"omq-otp",
}
m["oto-otm"] = {
"Otomi",
nil,
"oto",
}
m["paa"] = {
"Papuan",
236425,
"qfa-not",
}
m["paa-arf"] = {
"Arafundi",
4783702,
}
m["paa-asa"] = {
"Arai-Samaia",
48803569,
}
m["paa-bng"] = {
"Baining",
748487,
aliases = {"East New Britain"},
}
m["paa-brd"] = {
"Border",
1752158,
aliases = {"Upper Tami"},
}
m["paa-egb"] = {
"East Geelvink Bay",
1497678,
aliases = {"East Cenderawasih"},
}
m["paa-eng"] = {
"Engan",
3217449,
}
m["paa-iwm"] = {
"Iwam",
15147853,
}
m["paa-kag"] = { -- recode as ngf-kag?
"Kainantu-Goroka",
3217463,
"ngf",
}
m["paa-kiw"] = {
"Kiwaian",
338449,
}
m["paa-kut"] = {
"Kutubuan",
48767893,
"paa-pag",
}
m["paa-kwm"] = {
"Kwomtari",
2075415,
}
m["paa-lkp"] = {
"Lakes Plain",
6478969,
}
m["paa-lsp"] = {
"Lower Sepik",
7061700,
aliases = {"Nor-Pondo"},
}
m["paa-mai"] = {
"Mairasi",
6736896,
}
m["paa-msk"] = {
"Sko",
953509,
aliases = {"Skou"},
}
m["paa-nbo"] = {
"North Bougainville",
749496,
}
m["paa-nim"] = {
"Nimboran",
12638426,
}
m["paa-nha"] = {
"North Halmahera",
nil,
"paa-wpa",
}
m["paa-pag"] = {
"Papuan Gulf",
48803685,
}
m["paa-pau"] = {
"Pauwasi",
7155496,
}
m["paa-ram"] = {
"Ramu",
3442808,
}
m["paa-sbo"] = {
"South Bougainville",
3217380,
}
m["paa-sen"] = {
"Sentani",
17044584,
"paa-wpa",
}
m["paa-spk"] = {
"Sepik",
3508772,
}
m["paa-tkw"] = {
"Tor-Kwerba",
7827523,
}
m["paa-wpa"] = {
"West Papuan",
1363026,
}
m["paa-yam"] = {
"Yam",
15062272,
aliases = {"Morehead and Upper Maro River"},
}
m["paa-yua"] = {
"Yuat",
8060096,
}
m["phi"] = {
"Philippine",
947858,
"poz",
}
m["phi-kal"] = {
"Kalamian",
3217466,
"phi",
aliases = {"Calamian"},
}
m["poz"] = {
"Malayo-Polynesian",
143158,
"map",
}
m["poz-aay"] = {
"Admiralty Islands",
2701306,
"poz-oce",
}
m["poz-bnn"] = {
"North Bornean",
1427907,
"poz",
}
m["poz-bre"] = {
"East Barito",
2701314,
"poz",
}
m["poz-brw"] = {
"West Barito",
2761679,
"poz",
}
m["poz-bss"] = {
"Bali-Sasak-Sumbawa",
3396043,
"poz-msa",
}
m["poz-btk"] = {
"Bungku-Tolaki",
3217381,
"poz-clb",
}
m["poz-cet"] = {
"Central-Eastern Malayo-Polynesian",
2269883,
"poz",
}
m["poz-clb"] = {
"Celebic",
1078041,
"poz",
}
m["poz-cln"] = {
"New Caledonian",
3091221,
"poz-ocs",
}
m["poz-cma"] = {
"Central Maluku",
3217479,
"poz-cet",
}
m["poz-hce"] = {
"Halmahera-Cenderawasih",
2526616,
"pqe",
}
m["poz-kal"] = {
"Kaili-Pamona",
3217465,
"poz-clb",
}
m["poz-lgx"] = {
"Lampungic",
49215,
"poz",
}
m["poz-mcm"] = {
"Malayo-Chamic",
nil,
"poz-msa",
}
m["poz-mic"] = {
"Micronesian",
420591,
"poz-occ",
}
m["poz-mly"] = {
"Malayic",
662628,
"poz-mcm",
}
m["poz-msa"] = {
"Malayo-Sumbawan",
1363818,
"poz",
}
m["poz-mun"] = {
"Muna-Buton",
3037924,
"poz-clb",
}
m["poz-nws"] = {
"Northwest Sumatran",
2071308,
"poz",
}
m["poz-occ"] = {
"Central-Eastern Oceanic",
2068435,
"poz-oce",
}
m["poz-oce"] = {
"Oceanic",
324457,
"pqe",
}
m["poz-ocs"] = {
"Southern Oceanic",
3039118,
"poz-occ",
}
m["poz-ocw"] = {
"Western Oceanic",
2701282,
"poz-oce",
}
m["poz-pcc"] = {
"Central Pacific",
3130237,
"poz-occ",
}
m["poz-pep"] = {
"Eastern Polynesian",
390979,
"poz-pnp",
}
m["poz-pnp"] = {
"Nuclear Polynesian",
743851,
"poz-pol",
}
m["poz-pol"] = {
"Polynesian",
390979,
"poz-pcc",
}
m["poz-san"] = {
"Sabahan",
3217517,
"poz-bnn",
}
m["poz-sbj"] = {
"Sama-Bajaw",
2160409,
"poz",
}
m["poz-slb"] = {
"Saluan-Banggai",
3217519,
"poz-clb",
}
m["poz-sls"] = {
"Southeast Solomonic",
3119671,
"poz-occ",
}
m["poz-ssw"] = {
"South Sulawesi",
2778190,
"poz",
}
m["poz-stm"] = {
"St. Matthias",
6484143,
"poz-oce",
aliases = {"St Matthias"},
}
m["poz-swa"] = {
"North Sarawakan",
538569,
"poz-bnn",
}
m["poz-tem"] = {
"Temotu",
3075769,
"poz-oce",
}
m["poz-tim"] = {
"Timoric",
7806987,
"poz-cet",
}
m["poz-ton"] = {
"Tongic",
3397263,
"poz-pol",
}
m["poz-tot"] = {
"Tomini-Tolitoli",
3217541,
"poz-clb",
}
m["poz-vnc"] = {
"Central Vanuatu",
5061988,
"poz-ocs",
}
m["poz-vnn"] = {
"North Vanuatu",
85789650,
"poz-ocs",
}
m["poz-vns"] = {
"South Vanuatu",
3070173,
"poz-ocs",
}
m["poz-wot"] = {
"Wotu-Wolio",
1041317,
"poz-clb",
}
m["pqe"] = {
"Eastern Malayo-Polynesian",
2269883,
"poz-cet",
}
m["qfa-adc"] = {
"Central Great Andamanese",
nil,
"qfa-adm",
}
m["qfa-adm"] = {
"Great Andamanese",
3515103,
}
m["qfa-adn"] = {
"Northern Great Andamanese",
nil,
"qfa-adm",
}
m["qfa-ads"] = {
"Southern Great Andamanese",
nil,
"qfa-adm",
}
m["qfa-ain"] = {
"Ainuic",
50111972,
aliases = {"Ainu"},
}
m["qfa-bej"] = {
"Be-Jizhao",
nil,
"qfa-bet",
}
m["qfa-bet"] = {
"Be-Tai",
12627719,
"qfa-tak",
aliases = {"Tai-Be", "Daic-Beic", "Beic-Daic"},
}
m["qfa-buy"] = {
"Buyang",
1109927,
"qfa-kra",
}
m["qfa-cka"] = {
"Chukotko-Kamchatkan",
33255,
}
m["qfa-cre"] = {
"creole",
33289,
"crp",
}
m["qfa-ckn"] = {
"Chukotkan",
2606732,
"qfa-cka",
}
m["qfa-cnt"] = {
"contact",
133253514,
"qfa-not",
}
m["qfa-dgn"] = {
"Dogon",
1234776,
"nic",
}
m["qfa-dny"] = {
"Dene-Yeniseian",
21103,
aliases = {"Dené-Yeniseian"},
}
m["qfa-hur"] = {
"Hurro-Urartian",
1144159,
}
m["qfa-iso"] = {
"isolate",
33648,
"qfa-not",
}
m["qfa-kad"] = {
"Kadu", -- considered either Nilo-Saharan or independent/none
1720989,
}
m["qfa-kms"] = {
"Kam-Sui",
1023641,
"qfa-tak",
}
m["qfa-kor"] = {
"Koreanic",
11263525,
}
m["qfa-kra"] = {
"Kra",
1022087,
"qfa-tak",
}
m["qfa-lic"] = {
"Hlai",
1023648,
"qfa-tak",
aliases = {"Hlaic"},
}
m["qfa-mal"] = {
"Left May",
614468,
"paa-asa",
}
m["qfa-mch"] = { -- used in both N and S America
"Macro-Chibchan",
3438062,
}
m["qfa-mix"] = {
"mixed",
33694,
"qfa-cnt",
}
m["qfa-not"] = {
"not a family",
nil,
"qfa-not",
}
m["qfa-onb"] = {
"Be",
nil,
"qfa-bej",
aliases = {"Ong-Be", "Beic"},
}
m["qfa-ong"] = {
"Ongan",
2090575,
aliases = {"Angan", "South Andamanese", "Jarawa-Onge"},
}
m["qfa-pid"] = {
"pidgin",
33831,
"crp",
}
m["qfa-sub"] = {
"substrate",
20730913,
"qfa-not",
}
m["qfa-tak"] = {
"Kra-Dai",
34171,
aliases = {"Tai-Kadai", "Kadai"},
}
m["qfa-tap"] = {
"Timor-Alor-Pantar",
16590002,
}
m["qfa-tor"] = {
"Torricelli",
1333831,
}
m["qfa-tyn"] = {
"Tyrsenian",
1344038,
}
m["qfa-xgs"] = {
"Serbi-Mongolic",
108887939,
}
m["qfa-xgx"] = {
"Para-Mongolic",
107619002,
"qfa-xgs",
}
m["qfa-yen"] = {
"Yeniseian",
27639,
"qfa-dny",
aliases = {"Yeniseic", "Yenisei-Ostyak"},
}
m["qfa-yke"] = {
"Ketic",
nil,
"qfa-yen",
}
m["qfa-yko"] = {
"Kottic",
nil,
"qfa-yen",
}
m["qfa-yrn"] = {
"Arinic",
nil,
"qfa-yen",
}
m["qfa-ypm"] = {
"Pumpokolic",
nil,
"qfa-yen",
}
m["qfa-yuk"] = {
"Yukaghir",
34164,
aliases = {"Yukagir", "Jukagir"},
}
m["qwe"] = {
"Quechuan",
5218,
}
m["raj"] = {
"Rajasthani",
13196,
"inc-wes",
protoLanguage = "inc-ogu",
}
m["roa"] = {
"Romance",
19814,
"itc",
aliases = {"Romanic", "Latin", "Neolatin", "Neo-Latin"},
protoLanguage = "la",
}
m["roa-asl"] = {
"Asturleonese",
35390,
"roa-ibe",
protoLanguage = "roa-ole",
}
m["roa-cas"] = {
"Castilian",
71924,
"roa-ibe",
aliases = {"Castillian", "Castilic", "Castillic"},
protoLanguage = "osp",
}
m["roa-dal"] = {
"Dalmatian Romance",
97646077,
"roa-itd",
}
m["roa-eas"] = {
"Eastern Romance",
147576,
"roa",
}
m["roa-emr"] = {
"Emilian-Romagnol",
242648,
"roa-git",
}
m["roa-gap"] = {
"Galician-Portuguese",
9080204,
"roa-ibe",
aliases = {"Galician Romance", "Galaic-Portuguese"},
protoLanguage = "roa-opt",
}
m["roa-gar"] = {
"Gallo-Romance",
500394,
"roa-wes",
}
m["roa-itd"] = {
"Italo-Dalmatian",
3313381,
"roa-iwr",
aliases = {"Central Romance"}
}
m["roa-itr"] = {
"Italo-Romance",
3356483,
"roa-itd",
}
m["roa-iwr"] = {
"Italo-Western Romance",
112608,
"roa",
aliases = {"Italo-Western"},
}
m["roa-git"] = {
"Gallo-Italic",
516074,
"roa-gar",
aliases = {"Gallo-Italian", "Gallo-Cisalpine", "Cisalpine"},
}
m["roa-grh"] = {
"Gallo-Rhaetian",
97646466,
"roa-gar",
}
m["roa-ibe"] = {
"Ibero-Romance",
749533,
"roa-wes",
aliases = {"Iberian Romance", "West Ibero-Romance", "Western Ibero-Romance", "West Iberian Romance", "Western Iberian Romance"}
}
m["roa-nar"] = {
"Navarro-Aragonese",
133252927,
"roa-ibe",
protoLanguage = "roa-ona",
}
m["roa-oil"] = {
"Oïl",
37351,
"roa-grh",
aliases = {"langues d'oïl", "langue d'oïl", "Cisalpine"},
protoLanguage = "fro",
}
m["roa-ocr"] = {
"Occitano-Romance",
599958,
"roa-gar",
aliases = {"Gallo-Narbonnese", "East Iberian", "Eastern Iberian"},
}
m["roa-rhe"] = {
"Rhaeto-Romance",
515593,
"roa-grh",
aliases = {"langues d'oïl", "langue d'oïl", "Cisalpine"},
}
m["roa-sou"] = {
"Southern Romance",
145345,
"roa",
}
m["roa-wes"] = {
"Western Romance",
2714388,
"roa-iwr",
}
--[=[
Exceptional language and family codes for South American Indian languages
can use the prefix "sai-", though "sai" is no longer itself a family code.
]=]--
m["sai-ara"] = {
"Araucanian",
626630,
}
m["sai-aym"] = {
"Aymaran",
33010,
}
m["sai-bar"] = {
"Barbacoan",
807304,
aliases = {"Barbakoan"},
}
m["sai-bor"] = {
"Boran",
5371776,
}
m["sai-cah"] = {
"Cahuapanan",
1025793,
}
m["sai-car"] = {
"Cariban",
33090,
aliases = {"Carib"},
}
m["sai-cer"] = {
"Cerrado",
98078151,
"sai-jee",
aliases = {"Amazonian Jê"},
}
m["sai-chc"] = {
"Chocoan",
1075616,
aliases = {"Choco", "Chocó"},
}
m["sai-cho"] = {
"Chonan",
33019,
aliases = {"Chon"},
}
m["sai-cje"] = {
"Central Jê",
18010843,
"sai-cer",
aliases = {"Akuwẽ"},
}
m["sai-cpc"] = {
"Chapacuran",
1062626,
}
m["sai-crn"] = {
"Charruan",
3112423,
aliases = {"Charrúan"},
}
m["sai-ctc"] = {
"Catacaoan",
5051139,
}
m["sai-guc"] = {
"Guaicuruan",
1974973,
"sai-mgc",
aliases = {"Guaicurú", "Guaycuruana", "Guaikurú", "Guaycuruano", "Guaykuruan", "Waikurúan"},
}
m["sai-guh"] = {
"Guahiban",
944056,
aliases = {"Guahiboan", "Guajiboan", "Wahivoan"},
}
m["sai-gui"] = {
"Guianan",
nil,
"sai-car",
aliases = {"Guianan Carib", "Guiana Carib"},
}
m["sai-har"] = {
"Harákmbut",
1584402,
"sai-hkt",
aliases = {"Harákmbet"},
}
m["sai-hkt"] = {
"Harákmbut-Katukinan",
17107635,
}
m["sai-hrp"] = {
"Huarpean",
1578336,
aliases = {"Warpean", "Huarpe", "Warpe"},
}
m["sai-jee"] = {
"Jê",
1483594,
"sai-mje",
aliases = {"Gê", "Jean", "Gean", "Jê-Kaingang", "Ye"},
}
m["sai-jir"] = {
"Jirajaran",
3028651,
aliases = {"Hiraháran"},
}
m["sai-jiv"] = {
"Jivaroan",
1393074,
aliases = {"Hívaro", "Jibaro", "Jibaroan", "Jibaroana", "Jívaro"},
}
m["sai-ktk"] = {
"Katukinan",
2636000,
"sai-hkt",
aliases = {"Catuquinan"},
}
m["sai-kui"] = {
"Kuikuroan",
nil,
"sai-car",
aliases = {"Kuikuro", "Nahukwa"},
}
m["sai-map"] = {
"Mapoyan",
61096301,
"sai-ven",
aliases = {"Mapoyo", "Mapoyo-Yabarana", "Mapoyo-Yavarana", "Mapoyo-Yawarana"},
}
m["sai-mas"] = {
"Mascoian",
1906952,
aliases = {"Mascoyan", "Maskoian", "Enlhet-Enenlhet"},
}
m["sai-mgc"] = {
"Mataco-Guaicuru",
255512,
}
m["sai-mje"] = {
"Macro-Jê",
887133,
aliases = {"Macro-Gê"},
}
m["sai-mtc"] = {
"Matacoan",
2447424,
"sai-mgc",
}
m["sai-mur"] = {
"Muran",
33826,
aliases = {"Mura"},
}
m["sai-nad"] = {
"Nadahup",
1856439,
aliases = {"Makú", "Macú", "Vaupés-Japurá"},
}
m["sai-nje"] = {
"Northern Jê",
98078225,
"sai-cer",
aliases = {"Core Jê"},
}
m["sai-nmk"] = {
"Nambikwaran",
15548027,
aliases = {"Nambicuaran", "Nambiquaran", "Nambikuaran"},
}
m["sai-otm"] = {
"Otomacoan",
3217503,
aliases = {"Otomákoan", "Otomakoan"},
}
m["sai-pan"] = {
"Panoan",
1544537,
"sai-pat",
aliases = {"Pano"},
}
m["sai-pat"] = {
"Pano-Tacanan",
2475746,
aliases = {"Pano-Tacana", "Pano-Takana", "Páno-Takána", "Pano-Takánan"},
}
m["sai-pek"] = {
"Pekodian",
107451736,
"sai-car",
aliases = {"South Amazonian Carib", "Southern Cariban", "Pekodi"},
}
m["sai-pem"] = {
"Pemongan",
nil,
"sai-ven",
aliases = {"Pemong", "Pemóng", "Purukoto"},
}
m["sai-prk"] = {
"Parukotoan",
107451482,
"sai-car",
aliases = {"Parukoto"},
}
m["sai-sje"] = {
"Southern Jê",
98078245,
"sai-jee",
}
m["sai-tac"] = {
"Tacanan",
3113762,
"sai-pat",
}
m["sai-tar"] = {
"Taranoan",
105097814,
"sai-gui",
aliases = {"Trio", "Tarano"},
}
m["sai-tuc"] = {
"Tucanoan",
788144,
}
m["sai-tyu"] = {
"Ticuna-Yuri",
4467010,
}
m["sai-ucp"] = {
"Uru-Chipaya",
2475488,
aliases = {"Uru-Chipayan"},
}
m["sai-ven"] = {
"Venezuelan Cariban",
nil,
"sai-car",
aliases = {"Venezuelan Carib", "Venezuelan", "Venezuelano"},
}
m["sai-wic"] = {
"Wichí",
3027047,
}
m["sai-wit"] = {
"Witotoan",
43079317,
aliases = {"Huitotoan", "Uitotoan"},
}
m["sai-ynm"] = {
"Yanomami",
nil,
aliases = {"Yanomam", "Shamatari", "Yamomami", "Yanomaman"},
}
m["sai-yuk"] = {
"Yukpan",
nil,
"sai-car",
aliases = {"Yukpa", "Yukpano", "Yukpa-Japreria"},
}
m["sai-zam"] = {
"Zamucoan",
3048461,
aliases = {"Samúkoan"},
}
m["sai-zap"] = {
"Zaparoan",
33911,
aliases = {"Záparoan", "Saparoan", "Sáparoan", "Záparo", "Zaparoano", "Zaparoana"},
}
m["sal"] = {
"Salishan",
33985,
}
m["sdv"] = {
"Eastern Sudanic",
2036148,
"ssa",
}
m["sdv-bri"] = {
"Bari",
nil,
"sdv-nie",
}
m["sdv-daj"] = {
"Daju",
956724,
"sdv",
}
m["sdv-dnu"] = {
"Dinka-Nuer",
nil,
"sdv-niw",
}
m["sdv-eje"] = {
"Eastern Jebel",
3408878,
"sdv",
}
m["sdv-kln"] = {
"Kalenjin",
637228,
"sdv-nis",
}
m["sdv-lma"] = {
"Lotuko-Maa",
nil,
"sdv-nie",
}
m["sdv-lon"] = {
"Northern Luo",
nil,
"sdv-luo",
}
m["sdv-los"] = {
"Southern Luo",
7570103,
"sdv-luo",
}
m["sdv-luo"] = {
"Luo",
nil,
"sdv-niw",
}
m["sdv-nes"] = {
"Northern Eastern Sudanic",
4810496,
"sdv",
aliases = {"Astaboran", "Ek Sudanic"},
}
m["sdv-nie"] = {
"Eastern Nilotic",
153795,
"sdv-nil",
}
m["sdv-nil"] = {
"Nilotic",
513408,
"sdv",
}
m["sdv-nis"] = {
"Southern Nilotic",
1552410,
"sdv-nil",
}
m["sdv-niw"] = {
"Western Nilotic",
3114989,
"sdv-nil",
}
m["sdv-nma"] = {
"Nandi-Markweta",
nil,
"sdv-kln",
}
m["sdv-nyi"] = {
"Nyima",
11688746,
"sdv-nes",
aliases = {"Nyimang"},
}
m["sdv-tmn"] = {
"Taman",
3408873,
"sdv-nes",
aliases = {"Tamaic"},
}
m["sdv-ttu"] = {
"Teso-Turkana",
7705551,
"sdv-nie",
aliases = {"Ateker"},
}
m["sel"] = {
"Selkup",
34008,
"syd",
}
m["sem"] = {
"Semitic",
34049,
"afa",
}
m["sem-ara"] = {
"Aramaic",
28602,
"sem-nwe",
protoLanguage = "arc",
}
m["sem-arb"] = {
"Arabic",
164667,
"sem-cen",
protoLanguage = "ar",
}
m["sem-are"] = {
"Eastern Aramaic",
3410322,
"sem-ara",
}
m["sem-arw"] = {
"Western Aramaic",
3394214,
"sem-ara",
}
m["sem-ase"] = {
"Southeastern Aramaic",
3410322,
"sem-are",
}
m["sem-can"] = {
"Canaanite",
747547,
"sem-nwe",
}
m["sem-cen"] = {
"Central Semitic",
3433228,
"sem-wes",
}
m["sem-cna"] = {
"Central Neo-Aramaic",
3410322,
"sem-are",
}
m["sem-eas"] = {
"East Semitic",
164273,
"sem",
}
m["sem-eth"] = {
"Ethiopian Semitic",
163629,
"sem-wes",
aliases = {"Afro-Semitic", "Ethiopian", "Ethiopic", "Ethiosemitic"},
}
m["sem-nna"] = {
"Northeastern Neo-Aramaic",
2560578,
"sem-are",
}
m["sem-nwe"] = {
"Northwest Semitic",
162996,
"sem-cen",
}
m["sem-osa"] = {
"Old South Arabian",
35025,
"sem-cen",
aliases = {"Epigraphic South Arabian", "Sayhadic"},
}
m["sem-sar"] = {
"Modern South Arabian",
1981908,
"sem-wes",
}
m["sem-wes"] = {
"West Semitic",
124901,
"sem",
}
m["sgn"] = {
"sign",
34228,
"qfa-not",
}
m["sgn-fsl"] = {
"French Sign Languages",
5501921,
"sgn",
}
m["sgn-gsl"] = {
"German Sign Languages",
5551235,
"sgn",
}
m["sgn-jsl"] = {
"Japanese Sign Languages",
11722508,
"sgn",
}
m["sio"] = {
"Siouan",
34181,
"nai-sca",
}
m["sio-dhe"] = {
"Dhegihan",
3217420,
"sio-msv",
}
m["sio-dkt"] = {
"Dakotan",
4154122,
"sio-msv",
}
m["sio-mor"] = {
"Missouri River Siouan",
26807266,
"sio",
}
m["sio-msv"] = {
"Mississippi Valley Siouan",
12637104,
"sio",
}
m["sio-ohv"] = {
"Ohio Valley Siouan",
21070931,
"sio",
}
m["sit"] = {
"Sino-Tibetan",
45961,
aliases = {"Trans-Himalayan"},
}
m["sit-aao"] = {
"Central Naga",
615474,
"sit",
}
m["sit-alm"] = {
"Almora",
nil,
"sit-whm",
}
m["sit-bai"] = {
"Bai",
35103,
"sit-mba",
}
m["sit-bdi"] = {
"Bodish",
1814078,
"sit",
}
m["sit-cln"] = {
"Cai-Long",
107182612,
"sit-mba",
aliases = {"Ta-Li"},
}
m["sit-dhi"] = {
"Dhimalish",
1207648,
"sit",
}
m["sit-ebo"] = {
"East Bodish",
56402,
"sit-bdi",
}
m["sit-egy"] = {
"East rGyalrongic",
832026,
"sit-rgy",
}
m["sit-ers"] = {
"Ersuic",
56335,
"sit",
}
m["sit-gma"] = {
"Greater Magaric",
55612963,
"sit",
}
m["sit-gsi"] = {
"Greater Siangic",
52698851,
"sit",
}
m["sit-hrs"] = {
"Hrusish",
1632501,
"sit",
aliases = {"Southeast Kamengic"},
}
m["sit-jnp"] = {
"Jingphoic",
nil,
"sit-jpl",
aliases = {"Jingpho"},
}
m["sit-jpl"] = {
"Kachin-Luic",
1515454,
"tbq-bkj",
aliases = {"Jingpho-Luish", "Jingpho-Asakian", "Kachinic"},
}
m["sit-kch"] = {
"Konyak-Chang",
nil,
"sit-kon",
}
m["sit-kha"] = {
"Kham",
33305,
"sit-gma",
}
m["sit-khb"] = {
"Kho-Bwa",
6401917,
"sit",
aliases = {"Bugunish", "Kamengic"},
}
m["sit-khw"] = {
"Western Kho-Bwa",
nil,
"sit-khb",
}
m["sit-khc"] = {
"Chug-Lish",
nil,
"sit-khw",
aliases = {"Duhumbi-Khispi"},
}
m["sit-khm"] = {
"Mey-Sartang",
nil,
"sit-khw",
aliases = {"Sartang-Sherdukpen"},
}
m["sit-kic"] = {
"Central Kiranti",
nil,
"sit-kir",
}
m["sit-kie"] = {
"Eastern Kiranti",
nil,
"sit-kir",
}
m["sit-kin"] = {
"Kinnauric",
nil,
"sit-whm",
aliases = {"Kinnauri"},
}
m["sit-kir"] = {
"Kiranti",
922148,
"sit",
}
m["sit-kiw"] = {
"Western Kiranti",
922148,
"sit-kir",
}
m["sit-kon"] = {
"Konyak",
774590,
"tbq-bkj",
aliases = {"Konyakian", "Northern Naga"},
}
m["sit-kyk"] = {
"Kyirong-Kagate",
6450957,
"sit-tib",
}
m["sit-lab"] = {
"Ladakhi-Balti",
6450957,
"sit-tib",
}
m["sit-las"] = {
"Lahuli-Spiti",
6473510,
"sit-tib",
}
m["sit-luu"] = {
"Luish",
55621439,
"sit-jpl",
aliases = {"Asakian", "Sak"},
}
m["sit-mar"] = {
"Maringic",
nil,
"sit-tma",
}
m["sit-mba"] = {
"Macro-Bai",
16963847,
"sit-sba",
aliases = {"Greater Bai"},
}
m["sit-mdz"] = {
"Midzu",
6843504,
"sit",
aliases = {"Geman", "Midzuish", "Miju-Meyor", "Southern Mishmi"},
}
m["sit-mnz"] = {
"Mondzish",
6898839,
"tbq-lob",
aliases = {"Mangish"},
}
m["sit-mru"] = {
"Mruic",
16908870,
"sit",
aliases = {"Mru-Hkongso"},
}
m["sit-nas"] = {
"Naish",
25047956,
"sit-nax",
}
m["sit-nax"] = {
"Naic",
6982999,
"tbq-buq",
aliases = {"Naxish"},
}
m["sit-nba"] = {
"Northern Bai",
122463830,
"sit-bai",
}
m["sit-new"] = {
"Newaric",
55625069,
"sit",
}
m["sit-nng"] = {
"Nungish",
1515482,
"sit",
aliases = {"Nung"},
}
m["sit-qia"] = {
"Qiangic",
1636765,
"tbq-buq",
}
m["sit-rgy"] = {
"Rgyalrongic",
56936,
"sit-qia",
aliases = {"Jiarongic"},
}
m["sit-sba"] = {
"Sino-Bai",
nil,
"sit",
aliases = {"Greater Bai"},
}
m["sit-tam"] = {
"Tamangic",
3309439,
"sit",
aliases = {"West Bodish"},
}
m["sit-tan"] = {
"Tani",
3217538,
"sit",
}
m["sit-tib"] = {
"Tibetic",
1641150,
"sit-bdi",
protoLanguage = "otb",
}
m["sit-tja"] = {
"Tujia",
nil,
"sit",
}
m["sit-tma"] = {
"Tangkhul-Maring",
nil,
"sit",
}
m["sit-tng"] = {
"Tangkhulic",
1516657,
"sit-tma",
aliases = {"Tangkhul"},
}
m["sit-tno"] = {
"Tangsa-Nocte",
nil,
"sit-kon",
}
m["sit-tsk"] = {
"Tshangla",
nil,
"sit",
}
m["sit-wgy"] = {
"West rGyalrongic",
nil,
"sit-rgy"
}
m["sit-whm"] = {
"West Himalayish",
2301695,
"sit",
}
m["sit-zem"] = {
"Zeme",
189291,
"sit",
aliases = {"Zeliangrong", "Zemeic"},
}
m["sla"] = {
"Slavic",
23526,
"ine-bsl",
aliases = {"Slavonic"},
}
m["smi"] = {
"Sami",
56463,
"urj",
aliases = {"Saami", "Samic", "Saamic"},
}
m["son"] = {
"Songhay",
505198,
"ssa",
aliases = {"Songhai"},
}
m["sqj"] = {
"Albanian",
8748,
"ine",
}
m["ssa"] = {
"Nilo-Saharan", -- possibly not a genetic grouping
33705,
}
m["ssa-fur"] = {
"Fur",
2989512,
"ssa",
}
m["ssa-klk"] = {
"Kuliak",
1791476,
"ssa",
aliases = {"Rub"},
}
m["ssa-kom"] = {
"Koman",
1781084,
"ssa",
}
m["ssa-sah"] = {
"Saharan",
1757661,
"ssa",
}
m["syd"] = {
"Samoyedic",
34005,
"urj",
aliases = {"Samoyed", "Samodeic"},
}
m["tai"] = {
"Tai",
749720,
"qfa-bet",
aliases = {"Daic"},
}
m["tai-wen"] = {
"Wenma-Southwestern Tai",
nil,
"tai",
}
m["tai-tay"] = {
"Tày",
nil,
"tai-wen",
}
m["tai-sap"] = {
"Sapa-Southwestern Tai",
nil,
"tai-wen",
aliases = {"Sapa-Thai"},
}
m["tai-swe"] = {
"Southwestern Tai",
10889250,
"tai-sap",
}
m["tai-cho"] = {
"Chongzuo Tai",
13216,
"tai",
}
m["tai-cen"] = {
"Central Tai",
5061891,
"tai",
}
m["tai-nor"] = {
"Northern Tai",
7059014,
"tai",
}
m["tbq"] = {
"Tibeto-Burman",
34064,
"sit",
}
m["tbq-anp"] = {
"Angami-Pochuri",
530460,
"sit",
}
m["tbq-axi"] = {
"Axioid",
nil,
"tbq-sel",
}
m["tbq-bdg"] = {
"Bodo-Garo",
4090000,
"tbq-bkj",
}
m["tbq-bis"] = {
"Bisoid",
48844742,
"tbq-slo",
}
m["tbq-bka"] = {
"Bi-Ka",
12627890,
"tbq-slo",
}
m["tbq-bkj"] = {
"Sal",
889900,
"sit",
-- Brahmaputran appears to be Glottolog's term
aliases = {"Bodo-Konyak-Jinghpaw", "Brahmaputran", "Jingpho-Konyak-Bodo"},
}
m["tbq-brm"] = {
"Burmish",
865713,
"tbq-lob",
}
m["tbq-buq"] = {
"Burmo-Qiangic",
16056278,
"sit",
aliases = {"Eastern Tibeto-Burman"},
}
m["tbq-drp"] = {
"Downriver Phula",
7188378,
"tbq-rph",
}
m["tbq-han"] = {
"Hanoid",
17004185,
"tbq-slo",
}
m["tbq-hph"] = {
"Highland Phula",
nil,
"tbq-sel",
}
m["tbq-jin"] = {
"Jino",
6202716,
"tbq-slo",
}
m["tbq-kzh"] = {
"Kazhuoish",
48834669,
"tbq-lol",
}
m["tbq-kuk"] = {
"Kuki-Chin",
832413,
"sit",
aliases = {"Kukish", "South-Central Tibeto-Burman"},
}
m["tbq-lal"] = {
"Lalo",
56548,
"tbq-lso",
}
m["tbq-lho"] = {
"Lahoish",
nil,
"tbq-lol",
}
m["tbq-llo"] = {
"Lipo-Lolopo",
nil,
"tbq-lso",
}
m["tbq-lob"] = {
"Lolo-Burmese",
1635712,
"tbq-buq",
}
m["tbq-lol"] = {
"Loloish",
37035,
"tbq-lob",
aliases = {"Yi", "Ngwi", "Nisoic"},
}
m["tbq-lso"] = {
"Lisoish",
6559055,
"tbq-lol",
}
m["tbq-lwo"] = {
"Lawoish",
48847673,
"tbq-lol",
}
m["tbq-muj"] = {
"Muji",
11221327,
"tbq-hph",
}
m["tbq-nas"] = {
"Nasoid",
nil,
"tbq-nlo",
}
m["tbq-nis"] = {
"Nisu",
56404,
"tbq-nlo",
}
m["tbq-nlo"] = {
"Northern Loloish",
7058676,
"tbq-nso",
}
m["tbq-nso"] = {
"Nisoish",
56990,
"tbq-lol",
}
m["tbq-nus"] = {
"Nusoish",
114245231,
"tbq-lol",
}
m["tbq-phw"] = {
"Phowa",
7187959,
"tbq-hph",
}
m["tbq-rph"] = {
"Riverine Phula",
nil,
"tbq-sel",
}
m["tbq-sel"] = {
"Southeastern Loloish",
16111894,
"tbq-nso",
}
m["tbq-sil"] = {
"Siloid",
60787071,
"tbq-slo",
}
m["tbq-slo"] = {
"Southern Loloish",
5649340,
"tbq-lol",
}
m["tbq-tal"] = {
"Taloid",
48804018,
"tbq-lso",
}
m["tbq-urp"] = {
"Upriver Phula",
7187058,
"tbq-rph",
}
m["trk"] = {
"Turkic",
34090,
}
m["trk-cmn"] = {
"Common Turkic",
1126028,
"trk",
aliases = {"Shaz Turkic", "Shaz-Turkic"},
}
m["trk-kar"] = {
"Karluk",
703173,
"trk-cmn",
aliases = {"Qarluq", "Uyghur-Uzbek", "Southeastern Turkic"},
}
m["trk-kbu"] = {
"Kipchak-Bulgar",
3512539,
"trk-kip",
aliases = {"Uralian", "Uralo-Caspian"},
}
m["trk-kcu"] = {
"Kipchak-Cuman",
4370412,
"trk-kip",
aliases = {"Ponto-Caspian"},
}
m["trk-kip"] = {
"Kipchak",
1339898,
"trk-cmn",
-- Russian Wikipedia article [[w:ru:Западнотюркские_языки]] says "Western Turkic" is used by N.A. Baskakov and includes Oghuz, Kipchak and Karluk.
-- Azerbaijani Wikipedia article [[w:az:Qərbi_türk_dilləri]] clarifies that "Western Turkic" is not a clade.
otherNames = {"Western Turkic"},
aliases = {"Kypchak", "Qypchaq", "Northwestern Turkic"},
protoLanguage = "qwm",
}
m["trk-kkp"] = {
"Kyrgyz-Kipchak",
4221189,
"trk-kip",
}
m["trk-kno"] = {
"Kipchak-Nogai",
4326954,
"trk-kip",
aliases = {"Aralo-Caspian"},
}
m["trk-nsb"] = {
"North Siberian Turkic",
4537269,
"trk-sib",
aliases = {"Northern Siberian Turkic"},
}
m["trk-ogr"] = {
"Oghur",
1422731,
"trk",
aliases = {"Lir-Turkic", "r-Turkic"},
}
m["trk-ogz"] = {
"Oghuz",
494600,
"trk-cmn",
aliases = {"Southwestern Turkic"},
}
m["trk-sib"] = {
"Siberian Turkic",
354353,
"trk-cmn",
otherNames = {"Northern Turkic"},
-- per [[w:ru:Восточнотюркские_языки]], "Eastern Turkic" is an alias for Siberian Turkic in the work of O.A. Mudrak,
-- but has a different non-clade meaning in the older work of N.A. Baskakov.
aliases = {"Eastern Turkic", "Northeastern Turkic"},
}
m["trk-ssb"] = {
"South Siberian Turkic",
nil,
"trk-sib",
aliases = {"Southern Siberian Turkic"},
}
m["tup"] = {
"Tupian",
34070,
aliases = {"Tupi"},
}
m["tup-gua"] = {
"Tupi-Guarani",
148610,
"tup",
aliases = {"Tupí-Guaraní"},
}
m["tuw"] = {
"Tungusic",
34230,
aliases = {"Manchu-Tungus", "Tungus"},
}
m["tuw-ewe"] = {
"Ewenic",
105889448,
"tuw",
aliases = {"Northern Tungusic"},
}
m["tuw-jrc"] = {
"Jurchenic",
105889432,
"tuw",
aliases = {"Manchuric"},
}
m["tuw-nan"] = {
"Nanaic",
105889264,
"tuw",
}
m["tuw-udg"] = {
"Udegheic",
105889266,
"tuw",
}
m["urj"] = {
"Uralic",
34113,
varieties = {"Finno-Ugric"},
}
m["urj-fin"] = {
"Finnic",
33328,
"urj",
aliases = {"Baltic-Finnic", "Balto-Finnic", "Fennic"},
}
m["urj-mdv"] = {
"Mordvinic",
627313,
"urj",
}
m["urj-prm"] = {
"Permic",
161493,
"urj",
}
m["urj-ugr"] = {
"Ugric",
156631,
"urj",
}
m["wak"] = {
"Wakashan",
60069,
}
m["wen"] = {
"Sorbian",
25442,
"zlw",
aliases = {"Lusatian", "Wendish"},
}
m["xgn"] = {
"Mongolic",
33750,
"qfa-xgs",
aliases = {"Mongolian"},
}
m["xgn-cen"] = {
"Central Mongolic",
28719447,
"xgn",
protoLanguage = "xng-lat",
}
m["xgn-sou"] = {
"Southern Mongolic",
nil,
"xgn",
protoLanguage = "xng-ear",
}
m["xgn-shr"] = {
"Shirongolic",
107539435,
"xgn-sou",
}
m["xme"] = {
"Median",
nil,
"ira-mpr",
protoLanguage = "xme-old",
}
m["xme-ttc"] = {
"Tatic",
nil,
"xme",
}
m["xnd"] = {
"Na-Dene",
26986,
"qfa-dny",
aliases = {"Na-Dené"},
}
m["xsc"] = {
"Scythian",
nil,
"ira-nei",
}
m["xsc-sak"] = {
"Sakan",
nil,
"xsc-skw",
aliases = {"Saka"},
}
m["xsc-sar"] = {
"Sarmatian",
nil,
"xsc",
}
m["xsc-skw"] = {
"Saka-Wakhi",
nil,
"xsc",
}
m["yok"] = {
"Yokuts",
34249,
"nai-you",
aliases = {"Yokutsan", "Mariposan", "Mariposa"},
}
m["ypk"] = {
"Yupik",
27970,
"esx-esk",
aliases = {"Yup'ik", "Yuit"},
}
m["zhx"] = {
"Sinitic",
33857,
"sit-sba",
aliases = {"Chinese"},
protoLanguage = "och",
}
m["zhx-com"] = {
"Coastal Min",
20667215,
"zhx-min",
}
m["zhx-inm"] = {
"Inland Min",
20667237,
"zhx-min",
}
m["zhx-man"] = {
"Mandarinic",
nil,
"zhx",
protoLanguage = "cmn-ear",
}
m["zhx-min"] = {
"Min",
56504,
"zhx",
}
m["zhx-nan"] = {
"Southern Min",
36495,
"zhx-com",
}
m["zhx-pin"] = {
"Pinghua",
2735715,
"zhx",
protoLanguage = "ltc",
}
m["zhx-yue"] = {
"Yue",
7033959,
"zhx",
protoLanguage = "ltc",
}
m["zle"] = {
"East Slavic",
144713,
"sla",
}
m["zls"] = {
"South Slavic",
146665,
"sla",
}
m["zlw"] = {
"West Slavic",
145852,
"sla",
}
m["zlw-lch"] = {
"Lechitic",
742782,
"zlw",
aliases = {"Lekhitic"},
}
m["zlw-pom"] = {
"Pomeranian",
nil,
"zlw-lch",
}
m["znd"] = {
"Zande",
8066072,
"nic-ubg",
}
return require("Module:languages").finalizeData(m, "family")
sbmt7qv4sep2gmtuytgzwkday1nftl0
26512
24013
2026-07-07T09:55:57Z
Sibiru45
115
1 ralatan matan [[:id:Modul:families/data]]
24013
Scribunto
text/plain
-- Imported from enwiktionary
-- Source: https://en.wiktionary.org/wiki/Module:families/data
-- License: CC BY-SA
--[=[
This module contains definitions for all language family codes on Wiktionary.
]=]--
local m = {}
m["aav"] = {
"Austroasiatic",
33199,
aliases = {"Austro-Asiatic"},
}
m["aav-khs"] = {
"Khasian",
3073734,
"aav",
aliases = {"Khasic"},
}
m["aav-nic"] = {
"Nicobarese",
217380,
"aav",
}
m["aav-pkl"] = {
"Pnar-Khasi-Lyngngam",
nil,
"aav-khs",
}
m["afa"] = {
"Afroasiatic",
25268,
aliases = {"Afro-Asiatic"},
}
m["alg"] = {
"Algonquian",
33392,
"aql",
}
m["alg-abp"] = {
"Abenaki-Penobscot",
197936,
"alg-eas",
}
m["alg-ara"] = {
"Arapahoan",
2153686,
"alg",
}
m["alg-eas"] = {
"Eastern Algonquian",
2257525,
"alg",
}
m["alg-sfk"] = {
"Sac-Fox-Kickapoo",
1440172,
"alg",
}
m["alv"] = {
"Atlantic-Congo",
771124,
"nic",
}
m["alv-aah"] = {
"Ayere-Ahan",
750953,
"alv-von",
}
m["alv-ada"] = {
"Adamawa",
32906,
"alv-sav",
}
m["alv-bag"] = {
"Baga",
2746083,
"alv-mel",
}
m["alv-bak"] = {
"Bak",
1708174,
"alv-sng",
}
m["alv-bam"] = {
"Bambukic",
4853456,
"alv-ada",
aliases = {"Yungur-Jen"},
}
m["alv-bny"] = {
"Banyum",
2892477,
"alv-nyn",
}
m["alv-bua"] = {
"Bua",
4982094,
"alv-mbd",
}
m["alv-bwj"] = {
"Bikwin-Jen",
84542501,
"alv-bam",
}
m["alv-cng"] = {
"Cangin",
1033184,
"alv-fwo",
}
m["alv-ctn"] = {
"Central Tano",
1658486,
"alv-ptn",
aliases = {"Akan"},
}
m["alv-dlt"] = {
"Delta Edoid",
nil,
"alv-edo",
}
m["alv-dur"] = {
"Duru",
5316788,
"alv-lni",
}
m["alv-ede"] = {
"Ede",
35368,
"alv-yor",
}
m["alv-edk"] = {
"Edekiri",
5336735,
"alv-yrd",
}
m["alv-edo"] = {
"Edoid",
1287469,
"alv-von",
}
m["alv-eeo"] = {
"Edo-Esan-Ora",
12630439,
"alv-nce",
}
m["alv-fli"] = {
"Fali",
3450166,
"alv",
}
m["alv-fwo"] = {
"Fula-Wolof",
12631267,
"alv-sng",
}
m["alv-gbe"] = {
"Gbe",
668284,
"alv-von",
}
m["alv-gda"] = {
"Ga-Dangme",
3443338,
"alv-kwa",
}
m["alv-gng"] = {
"Guang",
684009,
"alv-ptn",
}
m["alv-gtm"] = {
"Ghana-Togo Mountain",
493020,
"alv-kwa",
aliases = {"Togo Remnant", "Central Togo"},
}
m["alv-hei"] = {
"Heiban",
108752116,
"alv-the",
}
m["alv-ido"] = {
"Idomoid",
974196,
"alv-von",
}
m["alv-igb"] = {
"Igboid",
1429100,
"alv-von",
}
m["alv-jfe"] = {
"Jola-Felupe",
1708174,
"alv-jol",
aliases = {"Ejamat"},
}
m["alv-jol"] = {
"Jola",
35176,
"alv-bak",
aliases = {"Diola"},
}
m["alv-kim"] = {
"Kim",
6409701,
"alv-mbd",
}
m["alv-kis"] = {
"Kissi",
35696,
"alv-mel",
}
m["alv-krb"] = {
"Karaboro",
4213541,
"alv-snf",
}
m["alv-ktg"] = {
"Ka-Togo",
5972796,
"alv-gtm",
}
m["alv-kul"] = {
"Kulango",
16977424,
"alv-sav",
aliases = {"Kulango-Lorhon", "Kulango-Lorom"},
}
m["alv-kwa"] = {
"Kwa",
33430,
"nic-vco",
}
m["alv-lag"] = {
"Lagoon",
111210042,
"alv-kwa",
}
m["alv-lek"] = {
"Leko",
6520642,
otherNames = {"Sambaic"}, -- appears to be an alias in Glottolog
"alv-lni",
}
m["alv-lim"] = {
"Limba",
35825,
"alv",
}
m["alv-lni"] = {
"Leko-Nimbari",
1708170,
"alv-ada",
otherNames = {"Central Adamawa"},
aliases = {"Chamba-Mumuye"},
}
m["alv-mbd"] = {
"Mbum-Day",
6799816,
"alv-ada",
}
m["alv-mbm"] = {
"Mbum",
6799814,
"alv-mbd",
}
m["alv-mel"] = {
"Mel",
12122355,
"alv",
}
m["alv-mum"] = {
"Mumuye",
84607009,
"alv-mye",
}
m["alv-mye"] = {
"Mumuye-Yendang",
6935539,
"alv-lni",
}
m["alv-nal"] = {
"Nalu",
nil,
"alv-sng",
}
m["alv-nce"] = {
"North-Central Edoid",
16110869,
"alv-edo",
}
m["alv-ngb"] = {
"Nupe-Gbagyi",
12638649,
"alv-nup",
aliases = {"Nupe-Gbari"},
}
m["alv-ntg"] = {
"Na-Togo",
nil,
"alv-gtm",
}
m["alv-nup"] = {
"Nupoid",
1429143,
"alv-von",
}
m["alv-nwd"] = {
"Northwestern Edoid",
16111012,
"alv-edo",
}
m["alv-nyn"] = {
"Nyun",
nil,
"alv-fwo",
}
m["alv-pap"] = {
"Papel",
7132562,
"alv-bak",
}
m["alv-pph"] = {
"Phla-Pherá",
3849625,
"alv-gbe",
}
m["alv-ptn"] = {
"Potou-Tano",
1475003,
"alv-kwa",
}
m["alv-sav"] = {
"Savanna",
4403672,
"nic-vco",
aliases = {"Savannas"},
}
m["alv-sma"] = {
"Suppire-Mamara",
4446348,
"alv-snf",
}
m["alv-snf"] = {
"Senufo",
33795,
"alv",
aliases = {"Senufic", "Senoufo"},
}
m["alv-sng"] = {
"Senegambian",
1708753,
"alv",
}
m["alv-snr"] = {
"Senari",
4416084,
"alv-snf",
}
m["alv-swd"] = {
"Southwestern Edoid",
12633903,
"alv-edo",
}
m["alv-tal"] = {
"Talodi",
12643302,
"alv-the",
}
m["alv-tdj"] = {
"Tagwana-Djimini",
7675362,
"alv-snf",
}
m["alv-ten"] = {
"Tenda",
3217535,
"alv-fwo",
}
m["alv-the"] = {
"Talodi-Heiban",
1521145,
"alv",
}
m["alv-von"] = {
"Volta-Niger",
34177,
"nic-vco",
}
m["alv-wan"] = {
"Wara-Natyoro",
7968830,
"alv-sav",
}
m["alv-wjk"] = {
"Waja-Kam",
nil,
"alv-ada",
}
m["alv-yek"] = {
"Yekhee",
nil,
"alv-nce",
}
m["alv-yor"] = {
"Yoruba",
nil,
"alv-edk",
}
m["alv-yrd"] = {
"Yoruboid",
1789745,
"alv-von",
}
m["alv-yun"] = {
"Yungur",
84601642,
"alv-bam",
aliases = {"Bena-Mboi"},
}
m["apa"] = {
"Apachean",
27758,
"ath",
aliases = {"Southern Athabaskan"},
}
m["aqa"] = {
"Alacalufan",
1288430,
}
m["aql"] = {
"Algic",
721612,
aliases = {"Algonquian-Ritwan", "Algonquian-Wiyot-Yurok"},
}
m["art"] = {
"constructed",
33215,
"qfa-not",
aliases = {"artificial", "planned"},
}
m["ath"] = {
"Athabaskan",
27475,
"xnd",
}
m["ath-nor"] = {
"North Athabaskan",
20738,
"ath",
aliases = {"Northern Athabaskan"},
}
m["ath-pco"] = {
"Pacific Coast Athabaskan",
20654,
"ath",
}
m["auf"] = {
"Arauan",
626772,
aliases = {"Arahuan", "Arauán", "Arawa", "Arawan", "Arawán"},
}
--[=[
Exceptional language and family codes for Australian Aboriginal languages
can use the prefix "aus-", though "aus" is no longer itself a family code.
]=]--
m["aus-arn"] = {
"Arnhem",
2581700,
aliases = {"Gunwinyguan", "Macro-Gunwinyguan"},
}
m["aus-bub"] = {
"Bunuban",
2495148,
aliases = {"Bunaban"},
}
m["aus-cww"] = {
"Central New South Wales",
5061507,
"aus-pam",
}
m["aus-dal"] = {
"Daly",
2478079,
}
m["aus-dyb"] = {
"Dyirbalic",
1850666,
"aus-pam",
}
m["aus-gar"] = {
"Garawan",
5521951,
}
m["aus-gun"] = {
"Gunwinyguan",
2581700,
"aus-arn",
aliases = {"Gunwingguan"},
}
m["aus-jar"] = {
"Jarrakan",
2039423,
}
m["aus-kar"] = {
"Karnic",
4215578,
"aus-pam",
}
m["aus-mir"] = {
"Mirndi",
4294095,
}
m["aus-nga"] = {
"Ngayarda",
16153490,
"aus-psw",
}
m["aus-nyu"] = {
"Nyulnyulan",
2039408,
}
m["aus-pam"] = {
"Pama-Nyungan",
33942,
}
m["aus-pmn"] = {
"Paman",
2640654,
"aus-pam",
}
m["aus-psw"] = {
"Southwest Pama-Nyungan",
2258160,
"aus-pam",
}
m["aus-rnd"] = {
"Arandic",
4784071,
"aus-pam",
}
m["aus-tnk"] = {
"Tangkic",
1823065,
}
m["aus-wdj"] = {
"Iwaidjan",
4196968,
aliases = {"Yiwaidjan"},
}
m["aus-wor"] = {
"Worrorran",
2038619,
}
m["aus-yid"] = {
"Yidinyic",
4205849,
"aus-pam",
}
m["aus-yng"] = {
"Yangmanic",
42727644,
}
m["aus-yol"] = {
"Yolngu",
2511254,
"aus-pam",
aliases = {"Yolŋu", "Yolngu Matha"},
}
m["aus-yuk"] = {
"Yuin-Kuric",
3833021,
"aus-pam",
}
m["awd"] = {
"Arawak",
626753,
aliases = {"Arawakan", "Maipurean", "Maipuran"},
}
m["awd-nwk"] = {
"Nawiki",
nil,
"awd",
aliases = {"Newiki"},
}
m["awd-taa"] = {
"Ta-Arawak",
7672731,
"awd",
aliases = {"Ta-Arawakan", "Ta-Maipurean"},
}
m["azc"] = {
"Uto-Aztecan",
34073,
aliases = {"Uto-Aztekan"},
}
m["azc-cup"] = {
"Cupan",
19866871,
"azc-tak",
}
m["azc-dur"] = {
"Durango Nahuatl",
2386361,
"azc-nah",
aliases = {"Mexicanero"}
}
m["azc-hua"] = {
"Huasteca Nahuatl",
3832950,
"azc-nah",
}
m["azc-nah"] = {
"Nahuan",
11965602,
"azc",
aliases = {"Aztecan"},
}
m["azc-num"] = {
"Numic",
2657541,
"azc",
}
m["azc-pim"] = {
"Piman",
7194600,
"azc",
aliases = {"Tepiman"},
}
m["azc-tak"] = {
"Takic",
1280305,
"azc",
}
m["azc-trc"] = {
"Taracahitic",
4245032,
"azc",
aliases = {"Taracahitan"},
}
m["bad"] = {
"Banda",
806234,
"nic-ubg",
}
m["bad-cnt"] = {
"Central Banda",
3438391,
"bad",
}
m["bai"] = {
"Bamileke",
806005,
"nic-gre",
}
m["bat"] = {
"Baltic",
33136,
"ine-bsl",
}
m["bat-eas"] = {
"East Baltic",
149944,
"bat",
}
m["bat-wes"] = {
"West Baltic",
149946,
"bat",
}
m["ber"] = {
"Berber",
25448,
"afa",
aliases = {"Tamazight"},
}
m["bnt"] = {
"Bantu",
33146,
"nic-bds",
}
m["bnt-baf"] = {
"Bafia",
799784,
"bnt",
}
m["bnt-bbo"] = {
"Bafo-Bonkeng",
nil,
"bnt-saw",
}
m["bnt-bdz"] = {
"Boma-Dzing",
1729203,
"bnt",
}
m["bnt-bek"] = {
"Bekwilic",
nil,
"bnt-ndb",
}
m["bnt-bki"] = {
"Bena-Kinga",
16113307,
"bnt-bne",
}
m["bnt-bmo"] = {
"Bangi-Moi",
nil,
"bnt-bnm",
}
m["bnt-bne"] = {
"Northeast Bantu",
7057832,
"bnt",
}
m["bnt-bnm"] = {
"Bangi-Ntomba",
806477,
"bnt-bte",
}
m["bnt-boa"] = {
"Boan",
4931250,
"bnt",
aliases = {"Buan", "Ababuan"},
}
m["bnt-bot"] = {
"Botatwe",
4948532,
"bnt",
}
m["bnt-bsa"] = {
"Basaa",
809739,
"bnt",
}
m["bnt-bsh"] = {
"Bushoong",
5001551,
"bnt-bte",
}
m["bnt-bso"] = {
"Southern Bantu",
980498,
"bnt",
}
m["bnt-bta"] = {
"Bati-Angba",
4869303,
"bnt-boa",
otherNames = {"Late Bomokandian"},
aliases = {"Bwa"},
}
m["bnt-btb"] = {
"Beti",
35118,
"bnt",
}
m["bnt-bte"] = {
"Bangi-Tetela",
4855181,
"bnt",
}
m["bnt-bun"] = {
"Buja-Ngombe",
4986733,
"bnt-mbb",
}
m["bnt-chg"] = {
"Chaga",
33016,
"bnt-cht",
}
m["bnt-cht"] = {
"Chaga-Taita",
nil,
"bnt-bne",
}
m["bnt-clu"] = {
"Chokwe-Luchazi",
3339273,
"bnt",
}
m["bnt-com"] = {
"Comorian",
33077,
"bnt-sab",
}
m["bnt-glb"] = {
"Great Lakes Bantu",
5599420,
"bnt-bne",
}
m["bnt-haj"] = {
"Haya-Jita",
25502360,
"bnt-glb",
}
m["bnt-kak"] = {
"Kako",
nil,
"bnt-pob",
}
m["bnt-kav"] = {
"Kavango",
116544179,
"bnt-ksb",
}
m["bnt-kbi"] = {
"Komo-Bira",
6428591,
"bnt-boa",
}
m["bnt-kel"] = {
"Kele",
1738162,
"bnt-kts",
aliases = {"Sheke"},
}
m["bnt-kil"] = {
"Kilombero",
6408121,
"bnt",
}
m["bnt-kka"] = {
"Kikuyu-Kamba",
16114410,
"bnt-bne",
aliases = {"Thagiicu"},
}
m["bnt-kmb"] = {
"Kimbundu",
16947687,
"bnt",
}
m["bnt-kng"] = {
"Kongo",
6429214,
"bnt",
}
m["bnt-kpw"] = {
"Kpwe",
36428,
"bnt-saw",
}
m["bnt-ksb"] = {
"Kavango-Southwest Bantu",
6379098,
"bnt",
}
m["bnt-kts"] = {
"Kele-Tsogo",
6385577,
"bnt",
}
m["bnt-lbn"] = {
"Luban",
4536504,
"bnt",
}
m["bnt-leb"] = {
"Lebonya",
6511395,
"bnt",
}
m["bnt-lgb"] = {
"Lega-Binja",
6517694,
"bnt",
}
m["bnt-lok"] = {
"Logooli-Kuria",
nil,
"bnt-glb",
}
m["bnt-lub"] = {
"Luba",
nil,
"bnt-lbn",
}
m["bnt-lun"] = {
"Lunda",
6704091,
"bnt",
}
m["bnt-mak"] = {
"Makua",
6740431,
"bnt-bso",
aliases = {"Makhuwa"},
}
m["bnt-mbb"] = {
"Mboshi-Buja",
6799764,
"bnt",
}
m["bnt-mbe"] = {
"Mbole-Enya",
6799728,
"bnt",
}
m["bnt-mbi"] = {
"Mbinga",
nil,
"bnt-rur",
}
m["bnt-mbo"] = {
"Mboshi",
6799763,
"bnt-mbb",
}
m["bnt-mbt"] = {
"Mbete",
1346910,
"bnt-tmb",
aliases = {"Mbere"},
}
m["bnt-mby"] = {
"Mbeya",
nil,
"bnt-ruk",
}
m["bnt-mij"] = {
"Mijikenda",
6845474,
"bnt-sab",
}
m["bnt-mka"] = {
"Makaa",
nil,
"bnt-ndb",
}
m["bnt-mne"] = {
"Manenguba",
31147471,
"bnt",
aliases = {"Mbo", "Ngoe"},
}
m["bnt-mnj"] = {
"Makaa-Njem",
1603899,
"bnt-pob",
}
m["bnt-mon"] = {
"Mongo",
nil,
"bnt-bnm",
}
m["bnt-mra"] = {
"Mbugwe-Rangi",
6799795,
"bnt",
}
m["bnt-msl"] = {
"Masaba-Luhya",
12636428,
"bnt-glb",
}
m["bnt-mwi"] = {
"Mwika",
nil,
"bnt-ruk",
}
m["bnt-ncb"] = {
"Northeast Coast Bantu",
7057848,
"bnt-bne",
}
m["bnt-ndb"] = {
"Ndzem-Bomwali",
nil,
"bnt-mnj",
}
m["bnt-ngn"] = {
"Ngondi-Ngiri",
7022532,
"bnt-mbb",
}
m["bnt-ngu"] = {
"Nguni",
961559,
"bnt-bso",
aliases = {"Ngoni"},
}
m["bnt-nya"] = {
"Nyali",
7070832,
"bnt-leb",
}
m["bnt-nyb"] = {
"Nyanga-Buyi",
7070882,
"bnt",
}
m["bnt-nyg"] = {
"Nyoro-Ganda",
12638666,
"bnt-glb",
}
m["bnt-nys"] = {
"Nyasa",
7070921,
"bnt",
}
m["bnt-nze"] = {
"Nzebi",
1755498,
"bnt-tmb",
aliases = {"Njebi"},
}
m["bnt-ova"] = {
"Ovambo",
36489,
"bnt-swb",
aliases = {"Oshivambo", "Oshiwambo", "Owambo"},
}
m["bnt-par"] = {
"Pare",
nil,
"bnt-ncb",
}
m["bnt-pen"] = {
"Pende",
7162373,
"bnt",
}
m["bnt-pob"] = {
"Pomo-Bomwali",
nil,
"bnt",
}
m["bnt-ruk"] = {
"Rukwa",
7378902,
"bnt",
}
m["bnt-run"] = {
"Rungwe",
nil,
"bnt-ruk",
}
m["bnt-rur"] = {
"Rufiji-Ruvuma",
7377947,
"bnt",
}
m["bnt-ruv"] = {
"Ruvu",
nil,
"bnt-ncb",
}
m["bnt-rvm"] = {
"Ruvuma",
nil,
"bnt-rur",
}
m["bnt-sab"] = {
"Sabaki",
2209395,
"bnt-ncb",
}
m["bnt-saw"] = {
"Sawabantu",
532003,
"bnt",
}
m["bnt-sbi"] = {
"Sabi",
7396071,
"bnt",
}
m["bnt-seu"] = {
"Seuta",
nil,
"bnt-ncb",
}
m["bnt-shh"] = {
"Shi-Havu",
nil,
"bnt-glb",
}
m["bnt-sho"] = {
"Shona",
2904660,
"bnt",
}
m["bnt-sir"] = {
"Sira",
1436372,
"bnt",
aliases = {"Shira-Punu"},
}
m["bnt-ske"] = {
"Soko-Kele",
nil,
"bnt-bte",
}
m["bnt-sna"] = {
"Sena",
nil,
"bnt-nys",
}
m["bnt-sts"] = {
"Sotho-Tswana",
2038386,
"bnt-bso",
}
m["bnt-swb"] = {
"Southwest Bantu",
116543539,
"bnt-ksb",
}
m["bnt-swh"] = {
"Swahili",
nil,
"bnt-sab",
}
m["bnt-tek"] = {
"Teke",
36528,
"bnt-tmb",
}
m["bnt-tet"] = {
"Tetela",
7706059,
"bnt-bte",
}
m["bnt-tkc"] = {
"Central Teke",
36473,
"bnt-tek",
}
m["bnt-tkm"] = {
"Takama",
nil,
"bnt-bne",
}
m["bnt-tmb"] = {
"Teke-Mbede",
7695332,
"bnt",
aliases = {"Teke-Mbere"},
}
m["bnt-tso"] = {
"Tsogo",
2458420,
otherNames = {"Okani"}, --appears to be an alias in Glottolog
"bnt-kts",
}
m["bnt-tsr"] = {
"Tswa-Ronga",
12643962,
"bnt-bso",
}
m["bnt-yak"] = {
"Yaka",
8047027,
"bnt",
}
m["bnt-yko"] = {
"Yasa-Kombe",
nil,
"bnt-saw",
}
m["bnt-zbi"] = {
"Zamba-Binza",
nil,
"bnt-bnm",
}
m["btk"] = {
"Batak",
1998595,
"poz-nws",
}
--[=[
Exceptional language and family codes for Central American Indian languages
may use the prefix "cai-", though "cai" is no longer itself a family code.
]=]--
--[=[
Exceptional language and family codes for Caucasian languages can use
the prefix "cau-", though "cau" is no longer itself a family code.
]=]--
m["cau-abz"] = {
"Abkhaz-Abaza",
4663617,
"cau-nwc",
otherNames = {"Abkhaz-Tapanta"},
aliases = {"Abazgi"},
}
m["cau-and"] = {
"Andian",
492152,
"cau-ava",
aliases = {"Andic"},
}
m["cau-ava"] = {
"Avaro-Andian",
4055404,
"cau-nec",
aliases = {"Avar-Andian", "Avar-Andi", "Avar-Andic"},
}
m["cau-cir"] = {
"Circassian",
858543,
"cau-nwc",
aliases = {"Cherkess"},
}
m["cau-drg"] = {
"Dargwa",
5222637,
"cau-nec",
otherNames = {"Dargin"},
}
m["cau-esm"] = {
"Eastern Samur",
nil,
"cau-sam",
}
m["cau-ets"] = {
"East Tsezian",
121437666,
"cau-tsz",
aliases = {"East Tsezic", "East Didoic"},
}
m["cau-lzg"] = {
"Lezghian",
2144370,
"cau-nec",
aliases = {"Lezgi", "Lezgian", "Lezgic"},
}
m["cau-nkh"] = {
"Nakh",
24441,
"cau-nec",
aliases = {"North-Central Caucasian"},
}
m["cau-nec"] = {
"Northeast Caucasian",
27387,
aliases = {"Dagestanian", "Nakho-Dagestanian", "Caspian"},
}
m["cau-nwc"] = {
"Northwest Caucasian",
33852,
aliases = {"Abkhazo-Adyghean", "Abkhaz-Adyghe", "Pontic"},
}
m["cau-sam"] = {
"Samur",
15229151,
"cau-lzg",
}
m["cau-ssm"] = {
"Southern Samur",
nil,
"cau-sam",
}
m["cau-tsz"] = {
"Tsezian",
1651530,
"cau-nec",
aliases = {"Tsezic", "Didoic"},
}
m["cau-vay"] = {
"Vainakh",
4102486,
"cau-nkh",
aliases = {"Veinakh", "Vaynakh"},
}
m["cau-wsm"] = {
"Western Samur",
nil,
"cau-sam",
}
m["cau-wts"] = {
"West Tsezian",
121437697,
"cau-tsz",
aliases = {"West Tsezic", "West Didoic"},
}
m["cba"] = {
"Chibchan",
520478,
"qfa-mch", -- or none if Macro-Chibchan is considered undemonstrated
}
m["ccs"] = {
"Kartvelian",
34030,
aliases = {"South Caucasian"},
}
m["ccs-gzn"] = {
"Georgian-Zan",
34030,
"ccs",
aliases = {"Karto-Zan"},
}
m["ccs-zan"] = {
"Zan",
2606912,
"ccs-gzn",
aliases = {"Zanuri", "Colchian"},
}
m["cdc"] = {
"Chadic",
33184,
"afa",
}
m["cdc-cbm"] = {
"Central Chadic",
2251547,
"cdc",
aliases = {"Biu-Mandara"},
}
m["cdc-est"] = {
"East Chadic",
2276221,
"cdc",
}
m["cdc-mas"] = {
"Masa",
2136092,
"cdc",
}
m["cdc-wst"] = {
"West Chadic",
2447774,
"cdc",
}
m["cdd"] = {
"Caddoan",
1025090,
}
m["cel"] = {
"Celtic",
25293,
"ine",
}
m["cel-bry"] = {
"Brythonic",
156877,
"cel-ins",
aliases = {"Brittonic"},
}
m["cel-brs"] = {
"Southwestern Brythonic",
2612853,
"cel-bry",
aliases = {"Southwestern Brittonic"},
}
m["cel-brw"] = {
"Western Brythonic",
593069,
"cel-bry",
aliases = {"Western Brittonic"},
}
m["cel-gae"] = {
"Goidelic",
56433,
"cel-ins",
aliases = {"Gaelic"},
protoLanguage = "pgl",
}
m["cel-his"] = {
"Hispano-Celtic",
4204136,
"cel",
}
m["cel-ins"] = {
"Insular Celtic",
214506,
"cel",
}
m["chi"] = {
"Chimakuan",
1073088,
}
m["chm"] = {
"Mari",
973685,
"urj",
}
m["cmc"] = {
"Chamic",
2997506,
"poz-mcm",
}
m["crp"] = {
"creole or pidgin",
19682167,
"qfa-cnt",
}
m["csu"] = {
"Central Sudanic",
190822,
"ssa",
}
m["csu-bba"] = {
"Bongo-Bagirmi",
3505042,
"csu",
}
m["csu-bbk"] = {
"Bongo-Baka",
4941917,
"csu-bba",
}
m["csu-bgr"] = {
"Bagirmi",
4841948,
"csu-bba",
aliases = {"Bagirmic"},
}
m["csu-bkr"] = {
"Birri-Kresh",
nil,
"csu",
}
m["csu-ecs"] = {
"Eastern Central Sudanic",
16911698,
"csu",
aliases = {"East Central Sudanic", "Central Sudanic East", "Lendu-Mangbetu"},
}
m["csu-kab"] = {
"Kaba",
6343715,
"csu-bba",
}
m["csu-lnd"] = {
"Lendu",
6522357,
"csu-ecs",
aliases = {"Lenduic"},
}
m["csu-maa"] = {
"Mangbetu",
6748874,
"csu-ecs",
aliases = {"Mangbetu-Asoa", "Mangbetu-Asua"},
}
m["csu-mle"] = {
"Mangbutu-Lese",
17009406,
"csu-ecs",
aliases = {"Mangbutu-Efe", "Mangbutu", "Membi-Mangbutu-Efe"},
}
m["csu-mma"] = {
"Moru-Madi",
6915156,
"csu-ecs",
}
m["csu-sar"] = {
"Sara",
2036691,
"csu-bba",
}
m["csu-val"] = {
"Vale",
7909520,
"csu-bba",
}
m["cus"] = {
"Cushitic",
33248,
"afa",
}
m["cus-cen"] = {
"Central Cushitic",
56569,
"cus",
}
m["cus-eas"] = {
"East Cushitic",
56568,
"cus",
}
m["cus-hec"] = {
"Highland East Cushitic",
56524,
"cus-eas",
}
m["cus-som"] = {
"Somaloid",
56774,
"cus-eas",
aliases = {"Sam", "Macro-Somali"},
}
m["cus-sou"] = {
"South Cushitic",
56525,
"cus",
}
m["day"] = {
"Land Dayak",
2760613,
"poz",
}
m["del"] = {
"Lenape",
2665761,
"alg-eas",
aliases = {"Delaware"},
}
m["den"] = {
"Slavey",
13272,
"ath-nor",
aliases = {"Slave", "Slavé"},
}
m["dmn"] = {
"Mande",
33681,
"nic",
}
m["dmn-bbu"] = {
"Bisa-Busa",
12627956,
"dmn-mde",
}
m["dmn-emn"] = {
"East Manding",
nil,
"dmn-man",
}
m["dmn-jje"] = {
"Jogo-Jeri",
nil,
"dmn-mjo",
}
m["dmn-man"] = {
"Manding",
35772,
"dmn-mmo",
}
m["dmn-mda"] = {
"Mano-Dan",
nil,
"dmn-mse",
}
m["dmn-mdc"] = {
"Central Mande",
5972907,
"dmn-mdw",
}
m["dmn-mde"] = {
"Eastern Mande",
12633080,
"dmn",
}
m["dmn-mdw"] = {
"Western Mande",
16113831,
"dmn",
}
m["dmn-mjo"] = {
"Manding-Jogo",
12636153,
"dmn-mdc",
}
m["dmn-mmo"] = {
"Manding-Mokole",
nil,
"dmn-mva",
}
m["dmn-mnk"] = {
"Maninka",
36186,
"dmn-emn",
}
m["dmn-mnw"] = {
"Northwestern Mande",
5972910,
"dmn-mdw",
}
m["dmn-mok"] = {
"Mokole",
16935447,
"dmn-mmo",
}
m["dmn-mse"] = {
"Southeastern Mande",
5972912,
"dmn-mde",
}
m["dmn-msw"] = {
"Southwestern Mande",
12633904,
"dmn-mdw",
}
m["dmn-mva"] = {
"Manding-Vai",
nil,
"dmn-mjo",
}
m["dmn-nbe"] = {
"Nwa-Beng",
nil,
"dmn-mse",
}
m["dmn-sam"] = {
"Samo",
36327,
"dmn-bbu",
aliases = {"Samuic"},
}
m["dmn-smg"] = {
"Samogo",
7410000,
"dmn-mnw",
aliases = {"Duun-Seenku"},
}
m["dmn-snb"] = {
"Soninke-Bobo",
16111680,
"dmn-mnw",
}
m["dmn-sya"] = {
"Susu-Yalunka",
nil,
"dmn-mdc",
}
m["dmn-vak"] = {
"Vai-Kono",
nil,
"dmn-mva",
}
m["dmn-wmn"] = {
"West Manding",
nil,
"dmn-man",
}
m["dra"] = {
"Dravidian",
33311,
}
m["dra-cen"] = {
"Central Dravidian",
12628823,
"dra",
}
m["dra-gki"] = {
"Gondi-Kui",
12631610,
"dra-sdt",
}
m["dra-gon"] = {
"Gondi",
55639812,
"dra-gki",
}
m["dra-imd"] = {
"Irula-Muduga",
nil,
"dra-tkn",
}
m["dra-kan"] = {
"Kannadoid",
6363888,
"dra-tkn",
protoLanguage = "dra-okn",
}
m["dra-kki"] = {
"Konda-Kui",
nil,
"dra-gki",
}
m["dra-kml"] = {
"Kurukh-Malto",
68002822,
"dra-nor",
}
m["dra-knk"] = {
"Kolami-Naiki",
10547037,
"dra-cen",
}
m["dra-kod"] = {
"Kodagu",
67983106,
"dra-tkd",
}
m["dra-kor"] = {
"Koraga",
33394,
"dra-tlk",
}
m["dra-mal"] = {
"Malayalamoid",
6741581,
"dra-tml",
}
m["dra-mdy"] = {
"Madiya",
27602,
"dra-gon",
}
m["dra-mlo"] = {
"Malto",
nil,
"dra-kml",
}
m["dra-mur"] = {
"Muria",
6938499,
"dra-gon",
}
m["dra-nor"] = {
"North Dravidian",
16110967,
"dra",
}
m["dra-pgd"] = {
"Parji-Gadaba",
10620428,
"dra-cen",
}
m["dra-sdo"] = {
"South Dravidian I",
16112843, -- Wikipedia's "South Dravidian" is South Dravidian I in this scheme.
"dra-sou",
aliases = {"South Dravidian"}, -- This is why I and II are used.
}
m["dra-sdt"] = {
"South Dravidian II",
12633975,
"dra-sou",
aliases = {"South-Central Dravidian"},
}
m["dra-sou"] = {
"South Dravidian",
128886618,
"dra",
aliases = {"Southern Dravidian"},
}
m["dra-tam"] = {
"Tamiloid",
7681417,
"dra-tml",
protoLanguage = "oty",
}
m["dra-tel"] = {
"Teluguic",
nil,
"dra-sdt",
protoLanguage = "dra-ote",
}
m["dra-tkd"] = {
"Tamil-Kodagu",
25494510,
"dra-tkn",
}
m["dra-tkn"] = {
"Tamil-Kannada",
6478506,
"dra-sdo",
}
m["dra-tkt"] = {
"Toda-Kota",
67983857,
"dra-tkd",
}
m["dra-tlk"] = {
"Tulu-Koraga",
nil,
"dra-sdo",
}
m["dra-tml"] = {
"Tamil-Malayalam",
10690507,
"dra-tkd",
}
m["egx"] = {
"Egyptian",
50868,
"afa",
protoLanguage = "egy",
}
m["ero"] = {
"Horpa",
56854,
"sit-wgy",
}
m["esx"] = {
"Eskimo-Aleut",
25946,
}
m["esx-esk"] = {
"Eskimo",
25946,
"esx",
}
m["esx-inu"] = {
"Inuit",
27796,
"esx-esk",
}
m["euq"] = {
"Vasconic",
4669240,
}
m["gba"] = {
"Gbaya",
3099986,
"alv-sav",
}
m["gba-eas"] = {
"Eastern Gbaya",
nil,
"gba",
}
m["gba-sou"] = {
"Southern Gbaya",
nil,
"gba",
}
m["gba-wes"] = {
"Western Gbaya",
nil,
"gba",
}
m["gem"] = {
"Germanic",
21200,
"ine",
}
m["gio"] = {
"Gelao",
56401,
"qfa-kra",
}
m["gme"] = {
"East Germanic",
108662,
"gem",
}
m["gmq"] = {
"North Germanic",
106085,
"gem",
}
m["gmq-eas"] = {
"East Scandinavian",
3090263,
"gmq",
protoLanguage = "non-oen",
}
m["gmq-ins"] = {
"Insular Scandinavian",
nil,
"gmq-wes",
}
m["gmq-wes"] = {
"West Scandinavian",
1792570,
"gmq",
protoLanguage = "non-own",
}
m["gmw"] = {
"West Germanic",
26721,
"gem",
}
m["gmw-afr"] = {
"Anglo-Frisian",
5329170,
"gmw-nsg",
}
m["gmw-ang"] = {
"Anglic",
1346342,
"gmw-afr",
protoLanguage = "ang",
}
m["gmw-fri"] = {
"Frisian",
25325,
"gmw-afr",
protoLanguage = "ofs",
}
m["gmw-frk"] = {
"Low Franconian",
153050,
"gmw",
protoLanguage = "frk",
}
m["gmw-hgm"] = {
"High German",
52040,
"gmw",
protoLanguage = "goh",
}
m["gmw-ian"] = {
"Irish Anglo-Norman",
120719384,
"gmw-ang",
protoLanguage = "enm",
}
m["gmw-lgm"] = {
"Low German",
25433,
"gmw-nsg",
protoLanguage = "osx",
}
m["gmw-nsg"] = {
"North Sea Germanic",
30134,
"gmw",
aliases = {"Ingvaeonic"},
}
m["gn"] = {
"Guarani",
35876,
"tup-gua",
aliases = {"Guaraní"},
}
m["grk"] = {
"Hellenic",
2042538,
"ine",
aliases = {"Greek"},
}
m["him"] = {
"Western Pahari",
10939493,
"inc-pah",
aliases = {"Himachali"},
}
m["hmn"] = {
"Hmong",
3307894,
"hmx",
}
m["hmx"] = {
"Hmong-Mien",
33322,
aliases = {"Miao-Yao"},
}
m["hmx-mie"] = {
"Mien",
7992695,
"hmx",
}
m["hok"] = {
"Hokan",
33406,
}
m["hyx"] = {
"Armenian",
8785,
"ine",
}
m["iir"] = {
"Indo-Iranian",
33514,
"ine",
}
m["iir-nur"] = {
"Nuristani",
161804,
"iir",
}
m["nur-nor"] = {
"Northern Nuristani",
nil,
"iir-nur",
}
m["nur-sou"] = {
"Southern Nuristani",
nil,
"iir-nur",
}
m["ijo"] = {
"Ijoid",
1325759,
"nic",
otherNames = {"Ijaw"}, -- Ijaw may be a subfamily
}
m["inc"] = {
"Indo-Aryan",
33577,
"iir",
aliases = {"Indic"},
}
m["inc-bas"] = {
"Bengali-Assamese",
4179137,
"inc-eas",
aliases = {"Assamese-Bengali", "Gauda-Kamarupa"},
}
m["inc-bhi"] = {
"Bhil",
4901727,
"inc-cen",
}
m["inc-bih"] = {
"Bihari",
135305,
"inc-eas",
}
m["inc-cen"] = {
"Central Indo-Aryan",
10979187,
"inc",
protoLanguage = "inc-asa",
}
m["inc-chi"] = {
"Chitrali",
11732797,
"inc-dar",
}
m["inc-dar"] = {
"Dardic",
161101,
"inc",
protoLanguage = "inc-ash",
}
m["inc-dre"] = {
"Eastern Dardic",
nil,
"inc-dar",
}
m["inc-dng"] = {
"Dangari",
nil,
"inc-shn",
protoLanguage = "inc-dng-pro",
}
m["inc-eas"] = {
"Eastern Indo-Aryan",
12593391,
"inc",
protoLanguage = "inc-aav",
}
m["inc-hal"] = {
"Halbic",
16910593,
"inc-eas",
aliases = {"Halbi"},
}
m["inc-hie"] = {
"Eastern Hindi",
4126648,
"inc-cen",
aliases = {"Purabiyā"},
protoLanguage = "inc-apa",
}
m["inc-hiw"] = {
"Western Hindi",
12600937,
"inc-cen",
protoLanguage = "inc-ohi",
}
m["inc-hnd"] = {
"Hindustani",
11051,
"inc-hiw",
aliases = {"Hindi-Urdu"},
protoLanguage = "hi-mid",
}
m["inc-ins"] = {
"Insular Indo-Aryan",
12179302,
"inc",
protoLanguage = "inc-apa",
}
m["inc-kas"] = {
"Kashmiric",
nil,
"inc-dre",
aliases = {"Kashmiri"},
}
m["inc-koh"] = {
"Kohistani",
13018610,
"inc-dre",
}
m["inc-krd"] = {
"KRDS lects",
6356154,
"inc-eas",
aliases = {"Kamta, Rajbanshi, Deshi and Surjapuri", "KRNB lects", "Kamta, Rajbanshi and Northern Deshi Bangla"},
}
m["inc-kun"] = {
"Kunar",
nil,
"inc-dar",
}
m["inc-mid"] = {
"Middle Indo-Aryan",
3236316,
"inc",
aliases = {"Middle Indic"},
}
m["inc-nwe"] = {
"Northwestern Indo-Aryan",
16111018,
"inc",
protoLanguage = "pra-pai",
}
m["inc-nor"] = {
"Northern Indo-Aryan",
946077,
"inc",
protoLanguage = "inc-aka",
}
m["inc-old"] = {
"Old Indo-Aryan",
118976896,
"inc",
aliases = {"Old Indic"},
}
m["inc-pah"] = {
"Pahari",
946077,
"inc-nor",
aliases = {"Pahadi"},
protoLanguage = "inc-aka",
}
m["inc-pan"] = {
"Punjabic",
2656685,
"inc-nwe",
aliases = {"Greater Punjabic"},
protoLanguage = "inc-ata",
}
m["inc-pas"] = {
"Pashayi",
36670,
"inc-dar",
aliases = {"Pashai"},
}
m["inc-rom"] = {
"Romani",
13201,
"inc-wes",
aliases = {"Romany", "Gypsy", "Gipsy"},
}
m["inc-shn"] = {
"Shinaic",
12646125,
"inc-dre",
}
m["inc-snd"] = {
"Sindhic",
7522212,
"inc-nwe",
protoLanguage = "inc-avr",
}
m["inc-sou"] = {
"Southern Indo-Aryan",
10856062,
"inc",
protoLanguage = "inc-ama",
}
m["inc-tha"] = {
"Tharu",
34035,
"inc-eas",
}
m["inc-wes"] = {
"Western Indo-Aryan",
nil,
"inc",
protoLanguage = "inc-agu",
}
m["ine"] = {
"Indo-European",
19860,
aliases = {"Indo-Germanic"},
}
m["ine-ana"] = {
"Anatolian",
147085,
"ine",
}
m["ine-bsl"] = {
"Balto-Slavic",
147356,
"ine",
}
m["ine-toc"] = {
"Tocharian",
37029,
"ine",
aliases = {"Tokharian"},
}
m["ira"] = {
"Iranian",
33527,
"iir",
}
m["ira-csp"] = {
"Caspian",
5049123,
"ira-mpr",
}
m["ira-cen"] = {
"Central Iranian",
nil,
"ira",
}
m["ira-kms"] = {
"Komisenian",
nil,
"ira-mpr",
aliases = {"Semnani"},
}
m["ine-luw"] = {
"Luwic",
115748615,
"ine-ana",
aliases = {"Luvic"},
}
m["ira-mid"] = {
"Middle Iranian",
6841465,
"ira",
}
m["ira-mny"] = {
"Munji-Yidgha",
nil,
"ira-sym",
aliases = {"Yidgha-Munji"},
}
m["ira-msh"] = {
"Mazanderani-Shahmirzadi",
nil,
"ira-csp",
}
m["ira-nei"] = {
"Northeastern Iranian",
10775567,
"ira",
}
m["ira-nwi"] = {
"Northwestern Iranian",
390576,
"ira-wes",
}
m["ira-old"] = {
"Old Iranian",
23301845,
"ira",
}
m["ira-orp"] = {
"Ormuri-Parachi",
nil,
"ira-sei",
}
m["ira-pat"] = {
"Pathan",
nil,
"ira-sei",
}
m["ira-sbc"] = {
"Sogdo-Bactrian",
nil,
"ira-nei",
}
m["ira-mpr"] = {
"Medo-Parthian",
nil,
"ira-nwi",
aliases = {"Partho-Median"},
}
m["ira-sgi"] = {
"Sanglechi-Ishkashimi",
18711232,
"ira-sei",
}
m["ira-shr"] = {
"Shughni-Roshani",
11732824,
"ira-shy",
}
m["ira-shy"] = {
"Shughni-Yazghulami",
nil,
"ira-sym",
}
m["ira-sgc"] = {
"Sogdic",
nil,
"ira-sbc",
aliases = {"Sogdian"},
}
m["ira-sei"] = {
"Southeastern Iranian",
3833002,
"ira",
}
m["ira-swi"] = {
"Southwestern Iranian",
390424,
"ira-wes",
}
m["ira-sym"] = {
"Shughni-Yazghulami-Munji",
nil,
"ira-sei",
}
m["ira-wes"] = {
"Western Iranian",
129850,
"ira",
}
m["ira-zgr"] = {
"Zaza-Gorani",
167854,
"ira-mpr",
aliases = {"Zaza-Gurani", "Gorani-Zaza"},
}
m["iro"] = {
"Iroquoian",
33623,
}
m["iro-nor"] = {
"North Iroquoian",
nil,
"iro",
}
m["itc"] = {
"Italic",
131848,
"ine",
}
m["itc-laf"] = {
"Latino-Faliscan",
33478,
"itc",
aliases = {"Latinian"},
}
m["itc-sbl"] = {
"Osco-Umbrian",
515194,
"itc",
aliases = {"Sabellic", "Sabellian"},
}
m["jpx"] = {
"Japonic",
33612,
aliases = {"Japanese", "Japanese-Ryukyuan"},
}
m["jpx-nry"] = {
"Northern Ryukyuan",
20862796,
"jpx-ryu",
}
m["jpx-ryu"] = {
"Ryukyuan",
56393,
"jpx",
}
m["jpx-sry"] = {
"Southern Ryukyuan",
18392243,
"jpx-ryu",
}
m["kar"] = {
"Karen",
1364815,
"sit",
}
m["kca"] = {
"Khanty",
33563,
"urj-ugr",
aliases = {"Khantyic", "Khantic"},
}
--[=[
Exceptional language and family codes for Khoisan and Kordofanian languages can use
the prefix "khi-" and "kdo-" respectively, though they are no longer family codes themselves.
]=]--
m["khi-kal"] = {
"Kalahari Khoe",
nil,
"khi-kho",
}
m["khi-khk"] = {
"Khoekhoe",
nil,
"khi-kho",
}
m["khi-kkw"] = {
"Khoe-Kwadi",
60785084,
aliases = {"Kwadi-Khoe"},
}
m["khi-kho"] = {
"Khoe",
2736449,
"khi-kkw",
aliases = {"Central Khoisan"},
}
m["khi-kxa"] = {
"Kx'a",
6450587,
aliases = {"Kxa", "Ju-ǂHoan"},
}
m["khi-tuu"] = {
"Tuu",
631046,
aliases = {"Kwi", "Taa-Kwi", "Southern Khoisan", "Taa-ǃKwi", "Taa-ǃUi", "ǃUi-Taa"},
}
m["kro"] = {
"Kru",
33535,
"nic-vco",
}
m["kro-aiz"] = {
"Aizi",
4699431,
"kro",
}
m["kro-bet"] = {
"Bété",
32956,
"kro-ekr",
}
m["kro-did"] = {
"Dida",
32685,
"kro-ekr",
}
m["kro-ekr"] = {
"Eastern Kru",
5972899,
"kro",
}
m["kro-grb"] = {
"Grebo",
5601537,
"kro-wkr",
}
m["kro-wee"] = {
"Wee",
nil,
"kro-wkr",
}
m["kro-wkr"] = {
"Western Kru",
5972897,
"kro",
}
m["ku"] = {
"Kurdish",
36368,
"ira-nwi",
}
m["map"] = {
"Austronesian",
49228,
}
m["map-ata"] = {
"Atayalic",
716610,
"map",
}
m["mjg"] = {
"Monguor",
34214,
"xgn-shr",
}
m["mkh"] = {
"Mon-Khmer",
33199,
"aav",
}
m["mkh-asl"] = {
"Aslian",
3111082,
"mkh",
}
m["mkh-ban"] = {
"Bahnaric",
56309,
"mkh",
}
m["mkh-kat"] = {
"Katuic",
56697,
"mkh",
}
m["mkh-khm"] = {
"Khmuic",
1323245,
"mkh",
}
m["mkh-kmr"] = {
"Khmeric",
nil,
"mkh",
}
m["mkh-mnc"] = {
"Monic",
3217497,
"mkh",
}
m["mkh-mng"] = {
"Mangic",
3509556,
"mkh",
}
m["mkh-nbn"] = {
"North Bahnaric",
56309,
"mkh-ban",
}
m["mkh-pal"] = {
"Palaungic",
2391173,
"mkh",
}
m["mkh-pea"] = {
"Pearic",
3073022,
"mkh",
}
m["mkh-pkn"] = {
"Pakanic",
nil,
"mkh-mng",
}
m["mkh-vie"] = {
"Vietic",
2355546,
"mkh",
}
m["mno"] = {
"Manobo",
3217483,
"phi",
}
m["mns"] = {
"Mansi",
33759,
"urj-ugr",
aliases = {"Mansic"},
}
m["mun"] = {
"Munda",
33892,
"aav",
}
m["myn"] = {
"Mayan",
33738,
}
--[=[
Exceptional language and family codes for North American Indian languages
can use the prefix "nai-", though "nai" is no longer itself a family code.
]=]--
m["nai-cat"] = {
"Catawban",
3446638,
"nai-sca",
}
m["nai-chu"] = {
"Chumashan",
1288420,
}
m["nai-ckn"] = {
"Chinookan",
610586,
}
m["nai-coo"] = {
"Coosan",
940278,
}
m["nai-jcq"] = {
"Jicaquean",
12179308,
"hok"
}
m["nai-ker"] = {
"Keresan",
35878,
}
m["nai-klp"] = {
"Kalapuyan",
1569040,
}
m["nai-kta"] = {
"Kiowa-Tanoan",
386288,
}
m["nai-len"] = {
"Lencan",
36189,
aliases = {"Lenca"},
}
m["nai-mdu"] = {
"Maiduan",
33502,
}
m["nai-miz"] = {
"Mixe-Zoquean",
954016,
aliases = {"Mixe-Zoque"},
}
m["nai-min"] = {
"Misumalpan",
281693,
"qfa-mch",
aliases = {"Misuluan", "Misumalpa"},
}
m["nai-mus"] = {
"Muskogean",
902978,
aliases = {"Muskhogean"},
}
m["nai-pak"] = {
"Pakawan",
65085487,
"hok",
}
m["nai-pal"] = {
"Palaihnihan",
1288332,
}
m["nai-plp"] = {
"Plateau Penutian",
2307476,
}
m["nai-pom"] = {
"Pomoan",
2618420,
"hok",
aliases = {"Pomo", "Kulanapan"},
}
m["nai-sca"] = {
"Siouan-Catawban",
34181,
}
m["nai-shp"] = {
"Sahaptian",
114782,
"nai-plp",
}
m["nai-shs"] = {
"Shastan",
2991735,
"hok",
}
m["nai-tot"] = {
"Totozoquean",
7828419,
}
m["nai-ttn"] = {
"Totonacan",
34039,
aliases = {"Totonac-Tepehua", "Totonacan-Tepehuan"},
varieties = {"Totonac"},
}
m["nai-tqn"] = {
"Tequistlatecan",
1568317,
"hok",
aliases = {"Tequistlatec", "Chontal", "Chontalan", "Oaxacan Chontal", "Chontal of Oaxaca"},
}
m["nai-tsi"] = {
"Tsimshianic",
34134,
}
m["nai-utn"] = {
"Utian",
13371763,
"nai-you",
aliases = {"Miwok-Costanoan", "Mutsun"},
}
m["nai-wtq"] = {
"Wintuan",
1294259,
aliases = {"Wintun"},
}
m["nai-xin"] = {
"Xincan",
1546494,
aliases = {"Xinca"},
}
m["nai-ykn"] = {
"Yukian",
2406722,
aliases = {"Yuki-Wappo"},
}
m["nai-you"] = {
"Yok-Utian",
2886186,
}
m["nai-yuc"] = {
"Yuman-Cochimí",
579137,
}
m["ngf"] = {
"Trans-New Guinea",
34018,
}
m["ngf-fin"] = {
"Finisterre",
5450373,
"ngf",
}
m["ngf-mad"] = {
"Madang",
11217556,
"ngf",
}
m["ngf-okk"] = {
"Ok",
7081687,
"ngf",
}
m["ngf-sbh"] = {
"South Bird's Head",
7566330,
"ngf",
}
m["nic"] = {
"Niger-Congo",
33838,
aliases = {"Niger-Kordofanian"},
}
m["nic-alu"] = {
"Alumic",
4737355,
"nic-plt",
}
m["nic-bas"] = {
"Basa",
4866154,
"nic-knj",
}
m["nic-bbe"] = {
"Eastern Beboid",
nil,
"nic-beb",
}
m["nic-bco"] = {
"Benue-Congo",
33253,
"nic-vco",
}
m["nic-bcr"] = {
"Bantoid-Cross",
806983,
"nic-bco",
}
m["nic-bdn"] = {
"Northern Bantoid",
nil,
"nic-bod",
aliases = {"North Bantoid"},
}
m["nic-bds"] = {
"Southern Bantoid",
3183152,
"nic-bod",
aliases = {"Wide Bantu", "Bin"},
}
m["nic-beb"] = {
"Beboid",
813549,
"nic-bds",
}
m["nic-ben"] = {
"Bendi",
4887065,
"nic-bcr",
}
m["nic-beo"] = {
"Beromic",
4894642,
"nic-plt",
}
m["nic-bod"] = {
"Bantoid",
806992,
"nic-bcr",
}
m["nic-buk"] = {
"Buli-Koma",
nil,
"nic-ovo",
}
m["nic-bwa"] = {
"Bwa",
12628562,
"nic-gur",
otherNames = {"Bwamu", "Bomu"},
}
m["nic-cde"] = {
"Central Delta",
3813191,
"nic-cri",
}
m["nic-cri"] = {
"Cross River",
1141096,
"nic-bcr",
}
m["nic-dag"] = {
"Dagbani",
nil,
"nic-wov",
}
m["nic-dak"] = {
"Dakoid",
1157745,
"nic-bdn",
}
m["nic-dge"] = {
"Escarpment Dogon",
5397128,
"qfa-dgn",
}
m["nic-dgw"] = {
"West Dogon",
nil,
"qfa-dgn",
}
m["nic-eko"] = {
"Ekoid",
1323395,
"nic-bds",
}
m["nic-eov"] = {
"Eastern Oti-Volta",
nil,
"nic-ovo",
aliases = {"Samba"},
}
m["nic-fru"] = {
"Furu",
5509783,
"nic-bds",
}
m["nic-gne"] = {
"Eastern Gurunsi",
12633072,
"nic-gns",
aliases = {"Eastern Grũsi"},
}
m["nic-gnn"] = {
"Northern Gurunsi",
nil,
"nic-gns",
aliases = {"Northern Grũsi"},
}
m["nic-gnw"] = {
"Western Gurunsi",
nil,
"nic-gns",
aliases = {"Western Grũsi"},
}
m["nic-gns"] = {
"Gurunsi",
721007,
"nic-gur",
aliases = {"Grũsi"},
}
m["nic-gre"] = {
"Eastern Grassfields",
5330160,
"nic-grf",
}
m["nic-grf"] = {
"Grassfields",
750932,
"nic-bds",
aliases = {"Grassfields Bantu", "Wide Grassfields"},
}
m["nic-grm"] = {
"Gurma",
30587833,
"nic-ovo",
}
m["nic-grs"] = {
"Southwest Grassfields",
7571285,
"nic-grf",
}
m["nic-gur"] = {
"Gur",
33536,
"alv-sav",
aliases = {"Voltaic"},
}
m["nic-ief"] = {
"Ibibio-Efik",
2743643,
"nic-lcr",
}
m["nic-jer"] = {
"Jera",
nil,
"nic-kne",
}
m["nic-jkn"] = {
"Jukunoid",
1711622,
"nic-pla",
}
m["nic-jrn"] = {
"Jarawan",
1683430,
"nic-mba",
}
m["nic-jrw"] = {
"Jarawa",
35423,
"nic-jrn",
}
m["nic-kam"] = {
"Kambari",
6356294,
"nic-knj",
}
m["nic-ktl"] = {
"Katloid",
nil,
"nic",
}
m["nic-kau"] = {
"Kauru",
nil,
"nic-kne",
}
m["nic-kmk"] = {
"Kamuku",
6359821,
"nic-knj",
}
m["nic-kne"] = {
"East Kainji",
5328687,
"nic-knj",
}
m["nic-knj"] = {
"Kainji",
681495,
"nic-pla",
}
m["nic-knn"] = {
"Northwest Kainji",
7060098,
"nic-knj",
}
m["nic-ktl"] = {
"Katloid",
6377681,
"nic",
aliases = {"Katla", "Katla-Tima"},
}
m["nic-lcr"] = {
"Lower Cross River",
3813193,
"nic-cri",
}
m["nic-mam"] = {
"Mamfe",
2005898,
"nic-bds",
aliases = {"Nyang"},
}
m["nic-mba"] = {
"Mbam",
687826,
"nic-bds",
}
m["nic-mbc"] = {
"Mba",
6799561,
"nic-ubg",
}
m["nic-mbw"] = {
"West Mbam",
nil,
"nic-mba",
}
m["nic-mmb"] = {
"Mambiloid",
1888151,
otherNames = {"North Bantoid"}, -- per Wikipedia, North Bantoid is the parent family
"nic-bdn",
}
m["nic-mom"] = {
"Momo",
6897393,
"nic-grf",
}
m["nic-mre"] = {
"Moré",
nil,
"nic-wov",
}
m["nic-ngd"] = {
"Ngbandi",
36439,
"nic-ubg",
}
m["nic-nge"] = {
"Ngemba",
7022271,
"nic-gre",
}
m["nic-ngk"] = {
"Ngbaka",
3217499,
"nic-ubg",
}
m["nic-nin"] = {
"Ninzic",
7039282,
"nic-plt",
}
m["nic-nka"] = {
"Nkambe",
7042520,
"nic-gre",
}
m["nic-nkb"] = {
"Baka",
nil,
"nic-nkw",
}
m["nic-nke"] = {
"Eastern Ngbaka",
nil,
"nic-ngk",
}
m["nic-nkg"] = {
"Gbanziri",
nil,
"nic-nkw",
}
m["nic-nkk"] = {
"Kpala",
nil,
"nic-nkw",
}
m["nic-nkm"] = {
"Mbaka",
nil,
"nic-nkw",
}
m["nic-nkw"] = {
"Western Ngbaka",
nil,
"nic-ngk",
}
m["nic-npd"] = {
"North Plateau Dogon",
nil,
"qfa-dgn",
}
m["nic-nun"] = {
"Nun",
13654297,
"nic-gre",
}
m["nic-nwa"] = {
"Nanga-Walo",
nil,
"qfa-dgn",
}
m["nic-ogo"] = {
"Ogoni",
2350726,
"nic-cri",
aliases = {"Ogonoid"},
}
m["nic-ovo"] = {
"Oti-Volta",
1157178,
"nic-gur",
}
m["nic-pla"] = {
"Platoid",
453244,
"nic-bco",
aliases = {"Central Nigerian"},
}
m["nic-plc"] = {
"Central Plateau",
5061668,
"nic-plt",
}
m["nic-pld"] = {
"Plains Dogon",
nil,
"qfa-dgn",
}
m["nic-ple"] = {
"East Plateau",
5329154,
"nic-plt",
}
m["nic-pls"] = {
"South Plateau",
7568236,
"nic-plt",
aliases = {"Jilic-Eggonic"},
}
m["nic-plt"] = {
"Plateau",
1267471,
"nic-pla",
}
m["nic-ras"] = {
"Rashad",
3401986,
"nic",
}
m["nic-rnc"] = {
"Central Ring",
nil,
"nic-rng",
}
m["nic-rng"] = {
"Ring",
2269051,
"nic-grf",
aliases = {"Ring Road"},
}
m["nic-rnn"] = {
"Northern Ring",
nil,
"nic-rng",
}
m["nic-rnw"] = {
"Western Ring",
nil,
"nic-rng",
}
m["nic-ser"] = {
"Sere",
7453058,
"nic-ubg",
}
m["nic-shi"] = {
"Shiroro",
7498953,
"nic-knj",
aliases = {"Pongu"},
}
m["nic-sis"] = {
"Sisaala",
36532,
"nic-gnw",
}
m["nic-tar"] = {
"Tarokoid",
2394472,
"nic-plt",
}
m["nic-tiv"] = {
"Tivoid",
752377,
"nic-bds",
}
m["nic-tvc"] = {
"Central Tivoid",
nil,
"nic-tiv",
}
m["nic-tvn"] = {
"Northern Tivoid",
nil,
"nic-tiv",
}
m["nic-ubg"] = {
"Ubangian",
33932,
"nic-vco", -- or none
}
m["nic-uce"] = {
"East-West Upper Cross River",
nil,
"nic-ucr",
}
m["nic-ucn"] = {
"North-South Upper Cross River",
nil,
"nic-ucr",
}
m["nic-ucr"] = {
"Upper Cross River",
4108624,
"nic-cri",
aliases = {"Upper Cross"},
}
m["nic-vco"] = {
"Volta-Congo",
37228,
"alv",
}
m["nic-wov"] = {
"Western Oti-Volta",
nil,
"nic-ovo",
aliases = {"Moré-Dagbani"}
}
m["nic-ykb"] = {
"Yukubenic",
16909196,
"nic-plt",
aliases = {"Oohum"},
}
m["nic-ymb"] = {
"Yambasa",
nil,
"nic-mba",
}
m["nic-yon"] = {
"Yom-Nawdm",
nil,
"nic-ovo",
aliases = {"Moré-Dagbani"}
}
m["nub"] = {
"Nubian",
1517194,
"sdv-nes",
}
m["nub-hil"] = {
"Hill Nubian",
5762211,
"nub",
aliases = {"Kordofan Nubian"},
}
m["omq"] = {
"Oto-Manguean",
33669,
}
m["omq-cha"] = {
"Chatino",
35111,
"omq-zap",
}
m["omq-chi"] = {
"Chinantecan",
35828,
"omq",
}
m["omq-cui"] = {
"Cuicatec",
616024,
"omq-mix",
}
m["omq-maz"] = {
"Mazatecan",
36230,
"omq",
aliases = {"Mazatec"},
}
m["omq-mix"] = {
"Mixtecan",
21083066,
"omq",
}
m["omq-mxt"] = {
"Mixtec",
36363,
"omq-mix",
}
m["omq-otp"] = {
"Oto-Pamean",
nil,
"omq",
}
m["omq-pop"] = {
"Popolocan",
5132273,
"omq",
}
m["omq-tri"] = {
"Trique",
780200,
"omq-mix",
aliases = {"Triqui"},
}
m["omq-zap"] = {
"Zapotecan",
8066463,
"omq",
}
m["omq-zpc"] = {
"Zapotec",
13214,
"omq-zap",
}
m["omv"] = {
"Omotic",
33860,
"afa",
}
m["omv-aro"] = {
"Aroid",
3699526,
"omv",
aliases = {"Ari-Banna", "South Omotic", "Somotic"},
}
m["omv-diz"] = {
"Dizoid",
430251,
"omv",
aliases = {"Maji", "Majoid"},
}
m["omv-eom"] = {
"East Ometo",
20527288,
"omv-ome",
}
m["omv-gon"] = {
"Gonga",
4143043,
"omv",
aliases = {"Kefoid"},
}
m["omv-mao"] = {
"Mao",
1351495,
"omv",
}
m["omv-nom"] = {
"North Ometo",
nil,
"omv-ome",
}
m["omv-ome"] = {
"Ometo",
36310,
"omv",
}
m["oto"] = {
"Otomian",
1270220,
"omq-otp",
}
m["oto-otm"] = {
"Otomi",
nil,
"oto",
}
m["paa"] = {
"Papuan",
236425,
"qfa-not",
}
m["paa-arf"] = {
"Arafundi",
4783702,
}
m["paa-asa"] = {
"Arai-Samaia",
48803569,
}
m["paa-bng"] = {
"Baining",
748487,
aliases = {"East New Britain"},
}
m["paa-brd"] = {
"Border",
1752158,
aliases = {"Upper Tami"},
}
m["paa-egb"] = {
"East Geelvink Bay",
1497678,
aliases = {"East Cenderawasih"},
}
m["paa-eng"] = {
"Engan",
3217449,
}
m["paa-iwm"] = {
"Iwam",
15147853,
}
m["paa-kag"] = { -- recode as ngf-kag?
"Kainantu-Goroka",
3217463,
"ngf",
}
m["paa-kiw"] = {
"Kiwaian",
338449,
}
m["paa-kut"] = {
"Kutubuan",
48767893,
"paa-pag",
}
m["paa-kwm"] = {
"Kwomtari",
2075415,
}
m["paa-lkp"] = {
"Lakes Plain",
6478969,
}
m["paa-lsp"] = {
"Lower Sepik",
7061700,
aliases = {"Nor-Pondo"},
}
m["paa-mai"] = {
"Mairasi",
6736896,
}
m["paa-msk"] = {
"Sko",
953509,
aliases = {"Skou"},
}
m["paa-nbo"] = {
"North Bougainville",
749496,
}
m["paa-nim"] = {
"Nimboran",
12638426,
}
m["paa-nha"] = {
"North Halmahera",
nil,
"paa-wpa",
}
m["paa-ori"] = {
"Oriomo",
5330530,
aliases = {"Eastern Trans-Fly"},
}
m["paa-pag"] = {
"Papuan Gulf",
48803685,
}
m["paa-pau"] = {
"Pauwasi",
7155496,
}
m["paa-pht"] = {
"Pahoturi River",
17049141,
aliases = {"Pahoturi"},
}
m["paa-ram"] = {
"Ramu",
3442808,
}
m["paa-sbo"] = {
"South Bougainville",
3217380,
}
m["paa-sen"] = {
"Sentani",
17044584,
"paa-wpa",
}
m["paa-spk"] = {
"Sepik",
3508772,
}
m["paa-tkw"] = {
"Tor-Kwerba",
7827523,
}
m["paa-wpa"] = {
"West Papuan",
1363026,
}
m["paa-yam"] = {
"Yam",
15062272,
aliases = {"Morehead and Upper Maro River"},
}
m["paa-yua"] = {
"Yuat",
8060096,
}
m["phi"] = {
"Philippine",
947858,
"poz",
}
m["phi-kal"] = {
"Kalamian",
3217466,
"phi",
aliases = {"Calamian"},
}
m["poz"] = {
"Malayo-Polynesian",
143158,
"map",
}
m["poz-aay"] = {
"Admiralty Islands",
2701306,
"poz-oce",
}
m["poz-bnn"] = {
"North Bornean",
1427907,
"poz",
}
m["poz-bre"] = {
"East Barito",
2701314,
"poz",
}
m["poz-brw"] = {
"West Barito",
2761679,
"poz",
}
m["poz-bss"] = {
"Bali-Sasak-Sumbawa",
3396043,
"poz-msa",
}
m["poz-btk"] = {
"Bungku-Tolaki",
3217381,
"poz-clb",
}
m["poz-cet"] = {
"Central-Eastern Malayo-Polynesian",
2269883,
"poz",
}
m["poz-clb"] = {
"Celebic",
1078041,
"poz",
}
m["poz-cln"] = {
"New Caledonian",
3091221,
"poz-ocs",
}
m["poz-cma"] = {
"Central Maluku",
3217479,
"poz-cet",
}
m["poz-hce"] = {
"Halmahera-Cenderawasih",
2526616,
"pqe",
}
m["poz-kal"] = {
"Kaili-Pamona",
3217465,
"poz-clb",
}
m["poz-lgx"] = {
"Lampungic",
49215,
"poz",
}
m["poz-mcm"] = {
"Malayo-Chamic",
nil,
"poz-msa",
}
m["poz-mic"] = {
"Micronesian",
420591,
"poz-occ",
}
m["poz-mly"] = {
"Malayic",
662628,
"poz-mcm",
}
m["poz-msa"] = {
"Malayo-Sumbawan",
1363818,
"poz",
}
m["poz-mun"] = {
"Muna-Buton",
3037924,
"poz-clb",
}
m["poz-nws"] = {
"Northwest Sumatran",
2071308,
"poz",
}
m["poz-occ"] = {
"Central-Eastern Oceanic",
2068435,
"poz-oce",
}
m["poz-oce"] = {
"Oceanic",
324457,
"pqe",
}
m["poz-ocs"] = {
"Southern Oceanic",
3039118,
"poz-occ",
}
m["poz-ocw"] = {
"Western Oceanic",
2701282,
"poz-oce",
}
m["poz-pcc"] = {
"Central Pacific",
3130237,
"poz-occ",
}
m["poz-pep"] = {
"Eastern Polynesian",
390979,
"poz-pnp",
}
m["poz-pnp"] = {
"Nuclear Polynesian",
743851,
"poz-pol",
}
m["poz-pol"] = {
"Polynesian",
390979,
"poz-pcc",
}
m["poz-san"] = {
"Sabahan",
3217517,
"poz-bnn",
}
m["poz-sbj"] = {
"Sama-Bajaw",
2160409,
"poz",
}
m["poz-slb"] = {
"Saluan-Banggai",
3217519,
"poz-clb",
}
m["poz-sls"] = {
"Southeast Solomonic",
3119671,
"poz-occ",
}
m["poz-ssw"] = {
"South Sulawesi",
2778190,
"poz",
}
m["poz-stm"] = {
"St. Matthias",
6484143,
"poz-oce",
aliases = {"St Matthias"},
}
m["poz-swa"] = {
"North Sarawakan",
538569,
"poz-bnn",
}
m["poz-tem"] = {
"Temotu",
3075769,
"poz-oce",
}
m["poz-tim"] = {
"Timoric",
7806987,
"poz-cet",
}
m["poz-ton"] = {
"Tongic",
3397263,
"poz-pol",
}
m["poz-tot"] = {
"Tomini-Tolitoli",
3217541,
"poz-clb",
}
m["poz-vnc"] = {
"Central Vanuatu",
5061988,
"poz-ocs",
}
m["poz-vnn"] = {
"North Vanuatu",
85789650,
"poz-ocs",
}
m["poz-vns"] = {
"South Vanuatu",
3070173,
"poz-ocs",
}
m["poz-wot"] = {
"Wotu-Wolio",
1041317,
"poz-clb",
}
m["pqe"] = {
"Eastern Malayo-Polynesian",
2269883,
"poz-cet",
}
m["qfa-adc"] = {
"Central Great Andamanese",
nil,
"qfa-adm",
}
m["qfa-adm"] = {
"Great Andamanese",
3515103,
}
m["qfa-adn"] = {
"Northern Great Andamanese",
nil,
"qfa-adm",
}
m["qfa-ads"] = {
"Southern Great Andamanese",
nil,
"qfa-adm",
}
m["qfa-ain"] = {
"Ainuic",
50111972,
aliases = {"Ainu"},
}
m["qfa-bej"] = {
"Be-Jizhao",
nil,
"qfa-bet",
}
m["qfa-bet"] = {
"Be-Tai",
12627719,
"qfa-tak",
aliases = {"Tai-Be", "Daic-Beic", "Beic-Daic"},
}
m["qfa-buy"] = {
"Buyang",
1109927,
"qfa-kra",
}
m["qfa-cka"] = {
"Chukotko-Kamchatkan",
33255,
}
m["qfa-cre"] = {
"creole",
33289,
"crp",
}
m["qfa-ckn"] = {
"Chukotkan",
2606732,
"qfa-cka",
}
m["qfa-cnt"] = {
"contact",
133253514,
"qfa-not",
}
m["qfa-dgn"] = {
"Dogon",
1234776,
"nic",
}
m["qfa-dny"] = {
"Dene-Yeniseian",
21103,
aliases = {"Dené-Yeniseian"},
}
m["qfa-hur"] = {
"Hurro-Urartian",
1144159,
}
m["qfa-iso"] = {
"isolate",
33648,
"qfa-not",
}
m["qfa-kad"] = {
"Kadu", -- considered either Nilo-Saharan or independent/none
1720989,
}
m["qfa-kms"] = {
"Kam-Sui",
1023641,
"qfa-tak",
}
m["qfa-kor"] = {
"Koreanic",
11263525,
}
m["qfa-kra"] = {
"Kra",
1022087,
"qfa-tak",
}
m["qfa-lic"] = {
"Hlai",
1023648,
"qfa-tak",
aliases = {"Hlaic"},
}
m["qfa-mal"] = {
"Left May",
614468,
"paa-asa",
}
m["qfa-mch"] = { -- used in both N and S America
"Macro-Chibchan",
3438062,
}
m["qfa-mix"] = {
"mixed",
33694,
"qfa-cnt",
}
m["qfa-not"] = {
"not a family",
nil,
"qfa-not",
}
m["qfa-onb"] = {
"Be",
nil,
"qfa-bej",
aliases = {"Ong-Be", "Beic"},
}
m["qfa-ong"] = {
"Ongan",
2090575,
aliases = {"Angan", "South Andamanese", "Jarawa-Onge"},
}
m["qfa-pid"] = {
"pidgin",
33831,
"crp",
}
m["qfa-sub"] = {
"substrate",
20730913,
"qfa-not",
}
m["qfa-tak"] = {
"Kra-Dai",
34171,
aliases = {"Tai-Kadai", "Kadai"},
}
m["qfa-tap"] = {
"Timor-Alor-Pantar",
16590002,
}
m["qfa-tor"] = {
"Torricelli",
1333831,
}
m["qfa-tyn"] = {
"Tyrsenian",
1344038,
}
m["qfa-xgs"] = {
"Serbi-Mongolic",
108887939,
}
m["qfa-xgx"] = {
"Para-Mongolic",
107619002,
"qfa-xgs",
}
m["qfa-yen"] = {
"Yeniseian",
27639,
"qfa-dny",
aliases = {"Yeniseic", "Yenisei-Ostyak"},
}
m["qfa-yke"] = {
"Ketic",
nil,
"qfa-yen",
}
m["qfa-yko"] = {
"Kottic",
nil,
"qfa-yen",
}
m["qfa-yrn"] = {
"Arinic",
nil,
"qfa-yen",
}
m["qfa-ypm"] = {
"Pumpokolic",
nil,
"qfa-yen",
}
m["qfa-yuk"] = {
"Yukaghir",
34164,
aliases = {"Yukagir", "Jukagir"},
}
m["qwe"] = {
"Quechuan",
5218,
}
m["raj"] = {
"Rajasthani",
13196,
"inc-wes",
protoLanguage = "inc-ogu",
}
m["roa"] = {
"Romance",
19814,
"itc",
aliases = {"Romanic", "Latin", "Neolatin", "Neo-Latin"},
protoLanguage = "la",
}
m["roa-asl"] = {
"Asturleonese",
35390,
"roa-ibe",
protoLanguage = "roa-ole",
}
m["roa-cas"] = {
"Castilian",
71924,
"roa-ibe",
aliases = {"Castillian", "Castilic", "Castillic"},
protoLanguage = "osp",
}
m["roa-dal"] = {
"Dalmatian Romance",
97646077,
"roa-itd",
}
m["roa-eas"] = {
"Eastern Romance",
147576,
"roa",
}
m["roa-emr"] = {
"Emilian-Romagnol",
242648,
"roa-git",
}
m["roa-gap"] = {
"Galician-Portuguese",
9080204,
"roa-ibe",
aliases = {"Galician Romance", "Galaic-Portuguese"},
protoLanguage = "roa-opt",
}
m["roa-gar"] = {
"Gallo-Romance",
500394,
"roa-wes",
}
m["roa-itd"] = {
"Italo-Dalmatian",
3313381,
"roa-iwr",
aliases = {"Central Romance"}
}
m["roa-itr"] = {
"Italo-Romance",
3356483,
"roa-itd",
}
m["roa-iwr"] = {
"Italo-Western Romance",
112608,
"roa",
aliases = {"Italo-Western"},
}
m["roa-git"] = {
"Gallo-Italic",
516074,
"roa-gar",
aliases = {"Gallo-Italian", "Gallo-Cisalpine", "Cisalpine"},
}
m["roa-grh"] = {
"Gallo-Rhaetian",
97646466,
"roa-gar",
}
m["roa-ibe"] = {
"Ibero-Romance",
749533,
"roa-wes",
aliases = {"Iberian Romance", "West Ibero-Romance", "Western Ibero-Romance", "West Iberian Romance", "Western Iberian Romance"}
}
m["roa-nar"] = {
"Navarro-Aragonese",
133252927,
"roa-ibe",
protoLanguage = "roa-ona",
}
m["roa-oil"] = {
"Oïl",
37351,
"roa-grh",
aliases = {"langues d'oïl", "langue d'oïl", "Cisalpine"},
protoLanguage = "fro",
}
m["roa-ocr"] = {
"Occitano-Romance",
599958,
"roa-gar",
aliases = {"Gallo-Narbonnese", "East Iberian", "Eastern Iberian"},
}
m["roa-rhe"] = {
"Rhaeto-Romance",
515593,
"roa-grh",
aliases = {"langues d'oïl", "langue d'oïl", "Cisalpine"},
}
m["roa-sou"] = {
"Southern Romance",
145345,
"roa",
}
m["roa-wes"] = {
"Western Romance",
2714388,
"roa-iwr",
}
--[=[
Exceptional language and family codes for South American Indian languages
can use the prefix "sai-", though "sai" is no longer itself a family code.
]=]--
m["sai-ara"] = {
"Araucanian",
626630,
}
m["sai-aym"] = {
"Aymaran",
33010,
}
m["sai-bar"] = {
"Barbacoan",
807304,
aliases = {"Barbakoan"},
}
m["sai-bor"] = {
"Boran",
5371776,
}
m["sai-cah"] = {
"Cahuapanan",
1025793,
}
m["sai-car"] = {
"Cariban",
33090,
aliases = {"Carib"},
}
m["sai-cer"] = {
"Cerrado",
98078151,
"sai-jee",
aliases = {"Amazonian Jê"},
}
m["sai-chc"] = {
"Chocoan",
1075616,
aliases = {"Choco", "Chocó"},
}
m["sai-cho"] = {
"Chonan",
33019,
aliases = {"Chon"},
}
m["sai-cje"] = {
"Central Jê",
18010843,
"sai-cer",
aliases = {"Akuwẽ"},
}
m["sai-cpc"] = {
"Chapacuran",
1062626,
}
m["sai-crn"] = {
"Charruan",
3112423,
aliases = {"Charrúan"},
}
m["sai-ctc"] = {
"Catacaoan",
5051139,
}
m["sai-guc"] = {
"Guaicuruan",
1974973,
"sai-mgc",
aliases = {"Guaicurú", "Guaycuruana", "Guaikurú", "Guaycuruano", "Guaykuruan", "Waikurúan"},
}
m["sai-guh"] = {
"Guahiban",
944056,
aliases = {"Guahiboan", "Guajiboan", "Wahivoan"},
}
m["sai-gui"] = {
"Guianan",
nil,
"sai-car",
aliases = {"Guianan Carib", "Guiana Carib"},
}
m["sai-har"] = {
"Harákmbut",
1584402,
"sai-hkt",
aliases = {"Harákmbet"},
}
m["sai-hkt"] = {
"Harákmbut-Katukinan",
17107635,
}
m["sai-hrp"] = {
"Huarpean",
1578336,
aliases = {"Warpean", "Huarpe", "Warpe"},
}
m["sai-jee"] = {
"Jê",
1483594,
"sai-mje",
aliases = {"Gê", "Jean", "Gean", "Jê-Kaingang", "Ye"},
}
m["sai-jir"] = {
"Jirajaran",
3028651,
aliases = {"Hiraháran"},
}
m["sai-jiv"] = {
"Jivaroan",
1393074,
aliases = {"Hívaro", "Jibaro", "Jibaroan", "Jibaroana", "Jívaro"},
}
m["sai-ktk"] = {
"Katukinan",
2636000,
"sai-hkt",
aliases = {"Catuquinan"},
}
m["sai-kui"] = {
"Kuikuroan",
nil,
"sai-car",
aliases = {"Kuikuro", "Nahukwa"},
}
m["sai-map"] = {
"Mapoyan",
61096301,
"sai-ven",
aliases = {"Mapoyo", "Mapoyo-Yabarana", "Mapoyo-Yavarana", "Mapoyo-Yawarana"},
}
m["sai-mas"] = {
"Mascoian",
1906952,
aliases = {"Mascoyan", "Maskoian", "Enlhet-Enenlhet"},
}
m["sai-mgc"] = {
"Mataco-Guaicuru",
255512,
}
m["sai-mje"] = {
"Macro-Jê",
887133,
aliases = {"Macro-Gê"},
}
m["sai-mtc"] = {
"Matacoan",
2447424,
"sai-mgc",
}
m["sai-mur"] = {
"Muran",
33826,
aliases = {"Mura"},
}
m["sai-nad"] = {
"Nadahup",
1856439,
aliases = {"Makú", "Macú", "Vaupés-Japurá"},
}
m["sai-nje"] = {
"Northern Jê",
98078225,
"sai-cer",
aliases = {"Core Jê"},
}
m["sai-nmk"] = {
"Nambikwaran",
15548027,
aliases = {"Nambicuaran", "Nambiquaran", "Nambikuaran"},
}
m["sai-otm"] = {
"Otomacoan",
3217503,
aliases = {"Otomákoan", "Otomakoan"},
}
m["sai-pan"] = {
"Panoan",
1544537,
"sai-pat",
aliases = {"Pano"},
}
m["sai-pat"] = {
"Pano-Tacanan",
2475746,
aliases = {"Pano-Tacana", "Pano-Takana", "Páno-Takána", "Pano-Takánan"},
}
m["sai-pek"] = {
"Pekodian",
107451736,
"sai-car",
aliases = {"South Amazonian Carib", "Southern Cariban", "Pekodi"},
}
m["sai-pem"] = {
"Pemongan",
nil,
"sai-ven",
aliases = {"Pemong", "Pemóng", "Purukoto"},
}
m["sai-prk"] = {
"Parukotoan",
107451482,
"sai-car",
aliases = {"Parukoto"},
}
m["sai-sje"] = {
"Southern Jê",
98078245,
"sai-jee",
}
m["sai-tac"] = {
"Tacanan",
3113762,
"sai-pat",
}
m["sai-tar"] = {
"Taranoan",
105097814,
"sai-gui",
aliases = {"Trio", "Tarano"},
}
m["sai-tuc"] = {
"Tucanoan",
788144,
}
m["sai-tyu"] = {
"Ticuna-Yuri",
4467010,
}
m["sai-ucp"] = {
"Uru-Chipaya",
2475488,
aliases = {"Uru-Chipayan"},
}
m["sai-ven"] = {
"Venezuelan Cariban",
nil,
"sai-car",
aliases = {"Venezuelan Carib", "Venezuelan", "Venezuelano"},
}
m["sai-wic"] = {
"Wichí",
3027047,
}
m["sai-wit"] = {
"Witotoan",
43079317,
aliases = {"Huitotoan", "Uitotoan"},
}
m["sai-ynm"] = {
"Yanomami",
nil,
aliases = {"Yanomam", "Shamatari", "Yamomami", "Yanomaman"},
}
m["sai-yuk"] = {
"Yukpan",
nil,
"sai-car",
aliases = {"Yukpa", "Yukpano", "Yukpa-Japreria"},
}
m["sai-zam"] = {
"Zamucoan",
3048461,
aliases = {"Samúkoan"},
}
m["sai-zap"] = {
"Zaparoan",
33911,
aliases = {"Záparoan", "Saparoan", "Sáparoan", "Záparo", "Zaparoano", "Zaparoana"},
}
m["sal"] = {
"Salishan",
33985,
}
m["sdv"] = {
"Eastern Sudanic",
2036148,
"ssa",
}
m["sdv-bri"] = {
"Bari",
nil,
"sdv-nie",
}
m["sdv-daj"] = {
"Daju",
956724,
"sdv",
}
m["sdv-dnu"] = {
"Dinka-Nuer",
nil,
"sdv-niw",
}
m["sdv-eje"] = {
"Eastern Jebel",
3408878,
"sdv",
}
m["sdv-kln"] = {
"Kalenjin",
637228,
"sdv-nis",
}
m["sdv-lma"] = {
"Lotuko-Maa",
nil,
"sdv-nie",
}
m["sdv-lon"] = {
"Northern Luo",
nil,
"sdv-luo",
}
m["sdv-los"] = {
"Southern Luo",
7570103,
"sdv-luo",
}
m["sdv-luo"] = {
"Luo",
nil,
"sdv-niw",
}
m["sdv-nes"] = {
"Northern Eastern Sudanic",
4810496,
"sdv",
aliases = {"Astaboran", "Ek Sudanic"},
}
m["sdv-nie"] = {
"Eastern Nilotic",
153795,
"sdv-nil",
}
m["sdv-nil"] = {
"Nilotic",
513408,
"sdv",
}
m["sdv-nis"] = {
"Southern Nilotic",
1552410,
"sdv-nil",
}
m["sdv-niw"] = {
"Western Nilotic",
3114989,
"sdv-nil",
}
m["sdv-nma"] = {
"Nandi-Markweta",
nil,
"sdv-kln",
}
m["sdv-nyi"] = {
"Nyima",
11688746,
"sdv-nes",
aliases = {"Nyimang"},
}
m["sdv-tmn"] = {
"Taman",
3408873,
"sdv-nes",
aliases = {"Tamaic"},
}
m["sdv-ttu"] = {
"Teso-Turkana",
7705551,
"sdv-nie",
aliases = {"Ateker"},
}
m["sel"] = {
"Selkup",
34008,
"syd",
}
m["sem"] = {
"Semitic",
34049,
"afa",
}
m["sem-ara"] = {
"Aramaic",
28602,
"sem-nwe",
protoLanguage = "arc",
}
m["sem-arb"] = {
"Arabic",
164667,
"sem-cen",
protoLanguage = "ar",
}
m["sem-are"] = {
"Eastern Aramaic",
3410322,
"sem-ara",
}
m["sem-arw"] = {
"Western Aramaic",
3394214,
"sem-ara",
}
m["sem-ase"] = {
"Southeastern Aramaic",
3410322,
"sem-are",
}
m["sem-can"] = {
"Canaanite",
747547,
"sem-nwe",
}
m["sem-cen"] = {
"Central Semitic",
3433228,
"sem-wes",
}
m["sem-cna"] = {
"Central Neo-Aramaic",
3410322,
"sem-are",
}
m["sem-eas"] = {
"East Semitic",
164273,
"sem",
}
m["sem-eth"] = {
"Ethiopian Semitic",
163629,
"sem-wes",
aliases = {"Afro-Semitic", "Ethiopian", "Ethiopic", "Ethiosemitic"},
}
m["sem-nna"] = {
"Northeastern Neo-Aramaic",
2560578,
"sem-are",
}
m["sem-nwe"] = {
"Northwest Semitic",
162996,
"sem-cen",
}
m["sem-osa"] = {
"Old South Arabian",
35025,
"sem-cen",
aliases = {"Epigraphic South Arabian", "Sayhadic"},
}
m["sem-sar"] = {
"Modern South Arabian",
1981908,
"sem-wes",
}
m["sem-wes"] = {
"West Semitic",
124901,
"sem",
}
m["sgn"] = {
"sign",
34228,
"qfa-not",
}
m["sgn-fsl"] = {
"French Sign Languages",
5501921,
"sgn",
}
m["sgn-gsl"] = {
"German Sign Languages",
5551235,
"sgn",
}
m["sgn-jsl"] = {
"Japanese Sign Languages",
11722508,
"sgn",
}
m["sio"] = {
"Siouan",
34181,
"nai-sca",
}
m["sio-dhe"] = {
"Dhegihan",
3217420,
"sio-msv",
}
m["sio-dkt"] = {
"Dakotan",
4154122,
"sio-msv",
}
m["sio-mor"] = {
"Missouri River Siouan",
26807266,
"sio",
}
m["sio-msv"] = {
"Mississippi Valley Siouan",
12637104,
"sio",
}
m["sio-ohv"] = {
"Ohio Valley Siouan",
21070931,
"sio",
}
m["sit"] = {
"Sino-Tibetan",
45961,
aliases = {"Trans-Himalayan"},
}
m["sit-aao"] = {
"Central Naga",
615474,
"sit",
}
m["sit-alm"] = {
"Almora",
nil,
"sit-whm",
}
m["sit-bai"] = {
"Bai",
35103,
"sit-mba",
}
m["sit-bdi"] = {
"Bodish",
1814078,
"sit",
}
m["sit-cln"] = {
"Cai-Long",
107182612,
"sit-mba",
aliases = {"Ta-Li"},
}
m["sit-dhi"] = {
"Dhimalish",
1207648,
"sit",
}
m["sit-ebo"] = {
"East Bodish",
56402,
"sit-bdi",
}
m["sit-egy"] = {
"East rGyalrongic",
832026,
"sit-rgy",
}
m["sit-ers"] = {
"Ersuic",
56335,
"sit",
}
m["sit-gma"] = {
"Greater Magaric",
55612963,
"sit",
}
m["sit-gsi"] = {
"Greater Siangic",
52698851,
"sit",
}
m["sit-hrs"] = {
"Hrusish",
1632501,
"sit",
aliases = {"Southeast Kamengic"},
}
m["sit-jnp"] = {
"Jingphoic",
nil,
"sit-jpl",
aliases = {"Jingpho"},
}
m["sit-jpl"] = {
"Kachin-Luic",
1515454,
"tbq-bkj",
aliases = {"Jingpho-Luish", "Jingpho-Asakian", "Kachinic"},
}
m["sit-kch"] = {
"Konyak-Chang",
nil,
"sit-kon",
}
m["sit-kha"] = {
"Kham",
33305,
"sit-gma",
}
m["sit-khb"] = {
"Kho-Bwa",
6401917,
"sit",
aliases = {"Bugunish", "Kamengic"},
}
m["sit-khw"] = {
"Western Kho-Bwa",
nil,
"sit-khb",
}
m["sit-khc"] = {
"Chug-Lish",
nil,
"sit-khw",
aliases = {"Duhumbi-Khispi"},
}
m["sit-khm"] = {
"Mey-Sartang",
nil,
"sit-khw",
aliases = {"Sartang-Sherdukpen"},
}
m["sit-kic"] = {
"Central Kiranti",
nil,
"sit-kir",
}
m["sit-kie"] = {
"Eastern Kiranti",
nil,
"sit-kir",
}
m["sit-kin"] = {
"Kinnauric",
nil,
"sit-whm",
aliases = {"Kinnauri"},
}
m["sit-kir"] = {
"Kiranti",
922148,
"sit",
}
m["sit-kiw"] = {
"Western Kiranti",
922148,
"sit-kir",
}
m["sit-kon"] = {
"Konyak",
774590,
"tbq-bkj",
aliases = {"Konyakian", "Northern Naga"},
}
m["sit-kyk"] = {
"Kyirong-Kagate",
6450957,
"sit-tib",
}
m["sit-lab"] = {
"Ladakhi-Balti",
6450957,
"sit-tib",
}
m["sit-las"] = {
"Lahuli-Spiti",
6473510,
"sit-tib",
}
m["sit-luu"] = {
"Luish",
55621439,
"sit-jpl",
aliases = {"Asakian", "Sak"},
}
m["sit-mar"] = {
"Maringic",
nil,
"sit-tma",
}
m["sit-mba"] = {
"Macro-Bai",
16963847,
"sit-sba",
aliases = {"Greater Bai"},
}
m["sit-mdz"] = {
"Midzu",
6843504,
"sit",
aliases = {"Geman", "Midzuish", "Miju-Meyor", "Southern Mishmi"},
}
m["sit-mnz"] = {
"Mondzish",
6898839,
"tbq-lob",
aliases = {"Mangish"},
}
m["sit-mru"] = {
"Mruic",
16908870,
"sit",
aliases = {"Mru-Hkongso"},
}
m["sit-nas"] = {
"Naish",
25047956,
"sit-nax",
}
m["sit-nax"] = {
"Naic",
6982999,
"tbq-buq",
aliases = {"Naxish"},
}
m["sit-nba"] = {
"Northern Bai",
122463830,
"sit-bai",
}
m["sit-new"] = {
"Newaric",
55625069,
"sit",
}
m["sit-nng"] = {
"Nungish",
1515482,
"sit",
aliases = {"Nung"},
}
m["sit-qia"] = {
"Qiangic",
1636765,
"tbq-buq",
}
m["sit-rgy"] = {
"Rgyalrongic",
56936,
"sit-qia",
aliases = {"Jiarongic"},
}
m["sit-sba"] = {
"Sino-Bai",
nil,
"sit",
aliases = {"Greater Bai"},
}
m["sit-tam"] = {
"Tamangic",
3309439,
"sit",
aliases = {"West Bodish"},
}
m["sit-tan"] = {
"Tani",
3217538,
"sit",
}
m["sit-tib"] = {
"Tibetic",
1641150,
"sit-bdi",
protoLanguage = "otb",
}
m["sit-tja"] = {
"Tujia",
nil,
"sit",
}
m["sit-tma"] = {
"Tangkhul-Maring",
nil,
"sit",
}
m["sit-tng"] = {
"Tangkhulic",
1516657,
"sit-tma",
aliases = {"Tangkhul"},
}
m["sit-tno"] = {
"Tangsa-Nocte",
nil,
"sit-kon",
}
m["sit-tsk"] = {
"Tshangla",
nil,
"sit",
}
m["sit-wgy"] = {
"West rGyalrongic",
nil,
"sit-rgy"
}
m["sit-whm"] = {
"West Himalayish",
2301695,
"sit",
}
m["sit-zem"] = {
"Zeme",
189291,
"sit",
aliases = {"Zeliangrong", "Zemeic"},
}
m["sla"] = {
"Slavic",
23526,
"ine-bsl",
aliases = {"Slavonic"},
}
m["smi"] = {
"Sami",
56463,
"urj",
aliases = {"Saami", "Samic", "Saamic"},
}
m["son"] = {
"Songhay",
505198,
"ssa",
aliases = {"Songhai"},
}
m["sqj"] = {
"Albanian",
8748,
"ine",
}
m["ssa"] = {
"Nilo-Saharan", -- possibly not a genetic grouping
33705,
}
m["ssa-fur"] = {
"Fur",
2989512,
"ssa",
}
m["ssa-klk"] = {
"Kuliak",
1791476,
"ssa",
aliases = {"Rub"},
}
m["ssa-kom"] = {
"Koman",
1781084,
"ssa",
}
m["ssa-sah"] = {
"Saharan",
1757661,
"ssa",
}
m["syd"] = {
"Samoyedic",
34005,
"urj",
aliases = {"Samoyed", "Samodeic"},
}
m["tai"] = {
"Tai",
749720,
"qfa-bet",
aliases = {"Daic"},
}
m["tai-wen"] = {
"Wenma-Southwestern Tai",
nil,
"tai",
}
m["tai-tay"] = {
"Tày",
nil,
"tai-wen",
}
m["tai-sap"] = {
"Sapa-Southwestern Tai",
nil,
"tai-wen",
aliases = {"Sapa-Thai"},
}
m["tai-swe"] = {
"Southwestern Tai",
10889250,
"tai-sap",
}
m["tai-cho"] = {
"Chongzuo Tai",
13216,
"tai",
}
m["tai-cen"] = {
"Central Tai",
5061891,
"tai",
}
m["tai-nor"] = {
"Northern Tai",
7059014,
"tai",
}
m["tbq"] = {
"Tibeto-Burman",
34064,
"sit",
}
m["tbq-anp"] = {
"Angami-Pochuri",
530460,
"sit",
}
m["tbq-axi"] = {
"Axioid",
nil,
"tbq-sel",
}
m["tbq-bdg"] = {
"Bodo-Garo",
4090000,
"tbq-bkj",
}
m["tbq-bis"] = {
"Bisoid",
48844742,
"tbq-slo",
}
m["tbq-bka"] = {
"Bi-Ka",
12627890,
"tbq-slo",
}
m["tbq-bkj"] = {
"Sal",
889900,
"sit",
-- Brahmaputran appears to be Glottolog's term
aliases = {"Bodo-Konyak-Jinghpaw", "Brahmaputran", "Jingpho-Konyak-Bodo"},
}
m["tbq-brm"] = {
"Burmish",
865713,
"tbq-lob",
}
m["tbq-buq"] = {
"Burmo-Qiangic",
16056278,
"sit",
aliases = {"Eastern Tibeto-Burman"},
}
m["tbq-drp"] = {
"Downriver Phula",
7188378,
"tbq-rph",
}
m["tbq-han"] = {
"Hanoid",
17004185,
"tbq-slo",
}
m["tbq-hph"] = {
"Highland Phula",
nil,
"tbq-sel",
}
m["tbq-jin"] = {
"Jino",
6202716,
"tbq-slo",
}
m["tbq-kzh"] = {
"Kazhuoish",
48834669,
"tbq-lol",
}
m["tbq-kuk"] = {
"Kuki-Chin",
832413,
"sit",
aliases = {"Kukish", "South-Central Tibeto-Burman"},
}
m["tbq-lal"] = {
"Lalo",
56548,
"tbq-lso",
}
m["tbq-lho"] = {
"Lahoish",
nil,
"tbq-lol",
}
m["tbq-llo"] = {
"Lipo-Lolopo",
nil,
"tbq-lso",
}
m["tbq-lob"] = {
"Lolo-Burmese",
1635712,
"tbq-buq",
}
m["tbq-lol"] = {
"Loloish",
37035,
"tbq-lob",
aliases = {"Yi", "Ngwi", "Nisoic"},
}
m["tbq-lso"] = {
"Lisoish",
6559055,
"tbq-lol",
}
m["tbq-lwo"] = {
"Lawoish",
48847673,
"tbq-lol",
}
m["tbq-muj"] = {
"Muji",
11221327,
"tbq-hph",
}
m["tbq-nas"] = {
"Nasoid",
nil,
"tbq-nlo",
}
m["tbq-nis"] = {
"Nisu",
56404,
"tbq-nlo",
}
m["tbq-nlo"] = {
"Northern Loloish",
7058676,
"tbq-nso",
}
m["tbq-nso"] = {
"Nisoish",
56990,
"tbq-lol",
}
m["tbq-nus"] = {
"Nusoish",
114245231,
"tbq-lol",
}
m["tbq-phw"] = {
"Phowa",
7187959,
"tbq-hph",
}
m["tbq-rph"] = {
"Riverine Phula",
nil,
"tbq-sel",
}
m["tbq-sel"] = {
"Southeastern Loloish",
16111894,
"tbq-nso",
}
m["tbq-sil"] = {
"Siloid",
60787071,
"tbq-slo",
}
m["tbq-slo"] = {
"Southern Loloish",
5649340,
"tbq-lol",
}
m["tbq-tal"] = {
"Taloid",
48804018,
"tbq-lso",
}
m["tbq-urp"] = {
"Upriver Phula",
7187058,
"tbq-rph",
}
m["trk"] = {
"Turkic",
34090,
}
m["trk-cmn"] = {
"Common Turkic",
1126028,
"trk",
aliases = {"Shaz Turkic", "Shaz-Turkic"},
}
m["trk-kar"] = {
"Karluk",
703173,
"trk-cmn",
aliases = {"Qarluq", "Uyghur-Uzbek", "Southeastern Turkic"},
}
m["trk-kbu"] = {
"Kipchak-Bulgar",
3512539,
"trk-kip",
aliases = {"Uralian", "Uralo-Caspian"},
}
m["trk-kcu"] = {
"Kipchak-Cuman",
4370412,
"trk-kip",
aliases = {"Ponto-Caspian"},
}
m["trk-kip"] = {
"Kipchak",
1339898,
"trk-cmn",
-- Russian Wikipedia article [[w:ru:Западнотюркские_языки]] says "Western Turkic" is used by N.A. Baskakov and includes Oghuz, Kipchak and Karluk.
-- Azerbaijani Wikipedia article [[w:az:Qərbi_türk_dilləri]] clarifies that "Western Turkic" is not a clade.
otherNames = {"Western Turkic"},
aliases = {"Kypchak", "Qypchaq", "Northwestern Turkic"},
protoLanguage = "qwm",
}
m["trk-kkp"] = {
"Kyrgyz-Kipchak",
4221189,
"trk-kip",
}
m["trk-kno"] = {
"Kipchak-Nogai",
4326954,
"trk-kip",
aliases = {"Aralo-Caspian"},
}
m["trk-nsb"] = {
"North Siberian Turkic",
4537269,
"trk-sib",
aliases = {"Northern Siberian Turkic"},
}
m["trk-ogr"] = {
"Oghur",
1422731,
"trk",
aliases = {"Lir-Turkic", "r-Turkic"},
}
m["trk-ogz"] = {
"Oghuz",
494600,
"trk-cmn",
aliases = {"Southwestern Turkic"},
}
m["trk-sib"] = {
"Siberian Turkic",
354353,
"trk-cmn",
otherNames = {"Northern Turkic"},
-- per [[w:ru:Восточнотюркские_языки]], "Eastern Turkic" is an alias for Siberian Turkic in the work of O.A. Mudrak,
-- but has a different non-clade meaning in the older work of N.A. Baskakov.
aliases = {"Eastern Turkic", "Northeastern Turkic"},
}
m["trk-ssb"] = {
"South Siberian Turkic",
nil,
"trk-sib",
aliases = {"Southern Siberian Turkic"},
}
m["tup"] = {
"Tupian",
34070,
aliases = {"Tupi"},
}
m["tup-gua"] = {
"Tupi-Guarani",
148610,
"tup",
aliases = {"Tupí-Guaraní"},
}
m["tuw"] = {
"Tungusic",
34230,
aliases = {"Manchu-Tungus", "Tungus"},
}
m["tuw-ewe"] = {
"Ewenic",
105889448,
"tuw",
aliases = {"Northern Tungusic"},
}
m["tuw-jrc"] = {
"Jurchenic",
105889432,
"tuw",
aliases = {"Manchuric"},
}
m["tuw-nan"] = {
"Nanaic",
105889264,
"tuw",
}
m["tuw-udg"] = {
"Udegheic",
105889266,
"tuw",
}
m["urj"] = {
"Uralic",
34113,
varieties = {"Finno-Ugric"},
}
m["urj-fin"] = {
"Finnic",
33328,
"urj",
aliases = {"Baltic-Finnic", "Balto-Finnic", "Fennic"},
}
m["urj-mdv"] = {
"Mordvinic",
627313,
"urj",
}
m["urj-prm"] = {
"Permic",
161493,
"urj",
}
m["urj-ugr"] = {
"Ugric",
156631,
"urj",
}
m["wak"] = {
"Wakashan",
60069,
}
m["wen"] = {
"Sorbian",
25442,
"zlw",
aliases = {"Lusatian", "Wendish"},
}
m["xgn"] = {
"Mongolic",
33750,
"qfa-xgs",
aliases = {"Mongolian"},
}
m["xgn-cen"] = {
"Central Mongolic",
28719447,
"xgn",
protoLanguage = "xng-lat",
}
m["xgn-sou"] = {
"Southern Mongolic",
nil,
"xgn",
protoLanguage = "xng-ear",
}
m["xgn-shr"] = {
"Shirongolic",
107539435,
"xgn-sou",
}
m["xme"] = {
"Median",
nil,
"ira-mpr",
protoLanguage = "xme-old",
}
m["xme-ttc"] = {
"Tatic",
nil,
"xme",
}
m["xnd"] = {
"Na-Dene",
26986,
"qfa-dny",
aliases = {"Na-Dené"},
}
m["xsc"] = {
"Scythian",
nil,
"ira-nei",
}
m["xsc-sak"] = {
"Sakan",
nil,
"xsc-skw",
aliases = {"Saka"},
}
m["xsc-sar"] = {
"Sarmatian",
nil,
"xsc",
}
m["xsc-skw"] = {
"Saka-Wakhi",
nil,
"xsc",
}
m["yok"] = {
"Yokuts",
34249,
"nai-you",
aliases = {"Yokutsan", "Mariposan", "Mariposa"},
}
m["ypk"] = {
"Yupik",
27970,
"esx-esk",
aliases = {"Yup'ik", "Yuit"},
}
m["zhx"] = {
"Sinitic",
33857,
"sit-sba",
aliases = {"Chinese"},
protoLanguage = "och",
}
m["zhx-com"] = {
"Coastal Min",
20667215,
"zhx-min",
}
m["zhx-inm"] = {
"Inland Min",
20667237,
"zhx-min",
}
m["zhx-man"] = {
"Mandarinic",
nil,
"zhx",
protoLanguage = "cmn-ear",
}
m["zhx-min"] = {
"Min",
56504,
"zhx",
}
m["zhx-nan"] = {
"Southern Min",
36495,
"zhx-com",
}
m["zhx-pin"] = {
"Pinghua",
2735715,
"zhx",
protoLanguage = "ltc",
}
m["zhx-yue"] = {
"Yue",
7033959,
"zhx",
protoLanguage = "ltc",
}
m["zle"] = {
"East Slavic",
144713,
"sla",
}
m["zls"] = {
"South Slavic",
146665,
"sla",
}
m["zlw"] = {
"West Slavic",
145852,
"sla",
}
m["zlw-lch"] = {
"Lechitic",
742782,
"zlw",
aliases = {"Lekhitic"},
}
m["zlw-pom"] = {
"Pomeranian",
nil,
"zlw-lch",
}
m["znd"] = {
"Zande",
8066072,
"nic-ubg",
}
return require("Module:languages").finalizeData(m, "family")
63r93w6fbbog1igyhtvb7s2hfmsacbj
Modul:table/deepCopy
828
7045
26521
2025-11-08T19:30:43Z
id>Ekirahardian
0
Salin dari en.wikipedia.org
26521
Scribunto
text/plain
local debug_track_module = "Module:debug/track"
local dump = mw.dumpObject
local error = error
local getmetatable = getmetatable
local next = next
local pairs = pairs
local rawget = rawget
local type = type
local setmetatable = setmetatable
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local tracked
local function make_copy(orig, seen, mt_flag, keep_loaded_data)
local mt, iter, state, init = getmetatable(orig)
-- If `mt` is nil, just use `next`, as it's faster.
if mt == nil then
iter, state, init = next, orig, nil
-- `mt` could be a non-table if `__metatable` has been used, but discard it in such cases.
elseif type(mt) ~= "table" then
mt, iter, state, init = nil, pairs(orig)
-- Data loaded via `mw.loadData`, which sets the key "mw_loadData" to true in the metatable.
elseif rawget(mt, "mw_loadData") == true then
if keep_loaded_data then
seen[orig] = orig
return orig
-- Track instances of such data being copied, which is very inefficient and usually unnecessary.
elseif not tracked then
debug_track("table/deepCopy/loaded data")
tracked = true
end
-- Discard the metatable and use the `__pairs` metamethod.
mt, iter, state, init = nil, pairs(orig)
-- If `mt_flag` is "none", discard the metatable and use the `__pairs` metamethod.
elseif mt_flag == "none" then
mt, iter, state, init = nil, pairs(orig)
-- Otherwise, keep `mt` and use `next` to copy the raw contents.
else
iter, state, init = next, orig, nil
end
local copy = {}
seen[orig] = copy
for k, v in iter, state, init do
if k and type(k) == "table" then
k = seen[k] or make_copy(k, seen, mt_flag, keep_loaded_data)
end
if v and type(v) == "table" then
v = seen[v] or make_copy(v, seen, mt_flag, keep_loaded_data)
end
copy[k] = v
end
if mt == nil or mt_flag == "none" then
return copy
-- Copy the metatable if `mt_flag` is "copy"; otherwise, it will be "keep", so keep it.
elseif mt_flag == "copy" then
mt = seen[mt] or make_copy(mt, seen, mt_flag, keep_loaded_data)
end
return setmetatable(copy, mt)
end
--[==[
Recursive deep copy function. Preserves copied identities of subtables.
A more powerful version of {mw.clone}, with customizable options.
* `metatableFlag` can be one of three options:
*# "none" (the default): `pairs` will be used to copy the table, meaning that any `__pairs` metamethod will be used to copy the table, if available; the resulting table will not have a metatable.
*# "copy": a raw copy of the table will be made (i.e. any `__pairs` metamethod will be ignored), and the copy will be given a copy of the original table's metatable; this ensures that nothing from the original is retained, but may cause metamethods to behave unexpectedly, depending on their implementation.
*# "keep": a raw copy of the table will be made (i.e. any `__pairs` metamethod will be ignored), and the copy will be given the original table's metatable; this is useful when copying objects that inherit methods from a prototype object (e.g. language objects).
* If `keepLoadedData` is true, then any data loaded via {mw.loadData} will not be copied, and the original will be used instead. This is useful in iterative contexts where it is necessary to copy data being destructively modified, because objects loaded via mw.loadData are immutable.
* Notes:
*# Protected metatables will not be copied (i.e. those hidden behind a `__metatable` metamethod), as they are not accessible by Lua's design. Instead, the output of the `__metatable` method will be used instead.
*# Data loaded via {mw.loadData} is always treated as though the "none" flag is set, because the way it has been implemented causes errors to be thrown if "copy" or "keep" are used with it.]==]
return function(orig, metatableFlag, keepLoadedData)
if metatableFlag == nil then
metatableFlag = "none"
elseif not (metatableFlag == "keep" or metatableFlag == "copy" or metatableFlag == "none") then
error('metatableFlag must be "none", "copy", "keep" or nil; received ' .. dump(metatableFlag))
end
if orig and type(orig) == "table" then
return make_copy(orig, {}, metatableFlag, keepLoadedData)
end
return orig
end
n283xd4cxzrnpyf4zrlt9334gjwqw59
26522
24088
2026-07-07T09:55:57Z
Sibiru45
115
1 ralatan matan [[:id:Modul:table/deepCopy]]
24088
Scribunto
text/plain
-- Imported from enwiktionary
-- Source: https://en.wiktionary.org/wiki/Module:table/deepCopy
-- License: CC BY-SA
local debug_track_module = "Module:debug/track"
local dump = mw.dumpObject
local error = error
local getmetatable = getmetatable
local next = next
local pairs = pairs
local rawget = rawget
local type = type
local setmetatable = setmetatable
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local tracked
local function make_copy(orig, seen, mt_flag, keep_loaded_data)
local mt, iter, state, init = getmetatable(orig)
-- If `mt` is nil, just use `next`, as it's faster.
if mt == nil then
iter, state, init = next, orig, nil
-- `mt` could be a non-table if `__metatable` has been used, but discard it in such cases.
elseif type(mt) ~= "table" then
mt, iter, state, init = nil, pairs(orig)
-- Data loaded via `mw.loadData`, which sets the key "mw_loadData" to true in the metatable.
elseif rawget(mt, "mw_loadData") == true then
if keep_loaded_data then
seen[orig] = orig
return orig
-- Track instances of such data being copied, which is very inefficient and usually unnecessary.
elseif not tracked then
debug_track("table/deepCopy/loaded data")
tracked = true
end
-- Discard the metatable and use the `__pairs` metamethod.
mt, iter, state, init = nil, pairs(orig)
-- If `mt_flag` is "none", discard the metatable and use the `__pairs` metamethod.
elseif mt_flag == "none" then
mt, iter, state, init = nil, pairs(orig)
-- Otherwise, keep `mt` and use `next` to copy the raw contents.
else
iter, state, init = next, orig, nil
end
local copy = {}
seen[orig] = copy
for k, v in iter, state, init do
if k and type(k) == "table" then
k = seen[k] or make_copy(k, seen, mt_flag, keep_loaded_data)
end
if v and type(v) == "table" then
v = seen[v] or make_copy(v, seen, mt_flag, keep_loaded_data)
end
copy[k] = v
end
if mt == nil or mt_flag == "none" then
return copy
-- Copy the metatable if `mt_flag` is "copy"; otherwise, it will be "keep", so keep it.
elseif mt_flag == "copy" then
mt = seen[mt] or make_copy(mt, seen, mt_flag, keep_loaded_data)
end
return setmetatable(copy, mt)
end
--[==[
Recursive deep copy function. Preserves copied identities of subtables.
A more powerful version of {mw.clone}, with customizable options.
* `metatableFlag` can be one of three options:
*# "none" (the default): `pairs` will be used to copy the table, meaning that any `__pairs` metamethod will be used to copy the table, if available; the resulting table will not have a metatable.
*# "copy": a raw copy of the table will be made (i.e. any `__pairs` metamethod will be ignored), and the copy will be given a copy of the original table's metatable; this ensures that nothing from the original is retained, but may cause metamethods to behave unexpectedly, depending on their implementation.
*# "keep": a raw copy of the table will be made (i.e. any `__pairs` metamethod will be ignored), and the copy will be given the original table's metatable; this is useful when copying objects that inherit methods from a prototype object (e.g. language objects).
* If `keepLoadedData` is true, then any data loaded via {mw.loadData} will not be copied, and the original will be used instead. This is useful in iterative contexts where it is necessary to copy data being destructively modified, because objects loaded via mw.loadData are immutable.
* Notes:
*# Protected metatables will not be copied (i.e. those hidden behind a `__metatable` metamethod), as they are not accessible by Lua's design. Instead, the output of the `__metatable` method will be used instead.
*# Data loaded via {mw.loadData} is always treated as though the "none" flag is set, because the way it has been implemented causes errors to be thrown if "copy" or "keep" are used with it.]==]
return function(orig, metatableFlag, keepLoadedData)
if metatableFlag == nil then
metatableFlag = "none"
elseif not (metatableFlag == "keep" or metatableFlag == "copy" or metatableFlag == "none") then
error('metatableFlag must be "none", "copy", "keep" or nil; received ' .. dump(metatableFlag))
end
if orig and type(orig) == "table" then
return make_copy(orig, {}, metatableFlag, keepLoadedData)
end
return orig
end
q4s9qatzubbokb7xt0z8px6mfhnn1q6
Modul:table/getUnprotectedMetatable
828
7054
26517
2025-11-08T16:50:30Z
id>Ekirahardian
0
Salin dari en.wikipedia.org
26517
Scribunto
text/plain
local _getmetatable = debug.getmetatable
-- For testing (and just in case it gets enabled).
if _getmetatable ~= nil then
-- Avoid debug.getmetatable() throwing an error if 0 arguments are passed,
-- for parity with the other function.
return function(t)
return _getmetatable(t)
end
end
_getmetatable = getmetatable
local pcall = pcall
local rawget = rawget
local setmetatable = setmetatable
local type = type
--[==[
Attempts to retrieve the input value's metatable, and returns it if found. If the value does not have a metatable, returns {nil}. If the input value does have a metatable, but that metatable is not possible to retrieve because it is protected with the `__metatable` metamethod, returns {false}.
This is a useful way to ensure that functions can reliably distinguish between objects that do not have metamethods, objects with known metamethods, and objects with unknown metamethods.]==]
return function(t)
local mt = _getmetatable(t)
-- If `mt` is nil, there's no metatable.
if mt == nil then
return nil
-- If `mt` is not a table, the real metatable is protected and there's no
-- way of retrieving it.
elseif type(mt) ~= "table" then
return false
end
-- Try setting `mt` as the metatable with `setmetatable`; if the metatable
-- is protected, this will cause an error to be thrown (revealing it as
-- protected), and if it isn't, then `mt` must be the real metatable anyway,
-- so nothing has changed. Also make a special exception for data loaded via
-- mw.loadData(), which sets each metatable at its own __metatable key as a
-- way to stop the use of setmetatable() without actually hiding it. This is
-- spoofable, but low-risk.
return (pcall(setmetatable, t, mt) or rawget(mt, "mw_loadData") == true) and mt or false
end
oqd72lzzcljldqpmbzxsx5fm947exar
26518
24097
2026-07-07T09:55:57Z
Sibiru45
115
1 ralatan matan [[:id:Modul:table/getUnprotectedMetatable]]
24097
Scribunto
text/plain
-- Imported from enwiktionary
-- Source: https://en.wiktionary.org/wiki/Module:table/getUnprotectedMetatable
-- License: CC BY-SA
local _getmetatable = debug.getmetatable
-- For testing (and just in case it gets enabled).
if _getmetatable ~= nil then
-- Avoid debug.getmetatable() throwing an error if 0 arguments are passed,
-- for parity with the other function.
return function(t)
return _getmetatable(t)
end
end
_getmetatable = getmetatable
local pcall = pcall
local rawget = rawget
local setmetatable = setmetatable
local type = type
--[==[
Attempts to retrieve the input value's metatable, and returns it if found. If the value does not have a metatable, returns {nil}. If the input value does have a metatable, but that metatable is not possible to retrieve because it is protected with the `__metatable` metamethod, returns {false}.
This is a useful way to ensure that functions can reliably distinguish between objects that do not have metamethods, objects with known metamethods, and objects with unknown metamethods.]==]
return function(t)
local mt = _getmetatable(t)
-- If `mt` is nil, there's no metatable.
if mt == nil then
return nil
-- If `mt` is not a table, the real metatable is protected and there's no
-- way of retrieving it.
elseif type(mt) ~= "table" then
return false
end
-- Try setting `mt` as the metatable with `setmetatable`; if the metatable
-- is protected, this will cause an error to be thrown (revealing it as
-- protected), and if it isn't, then `mt` must be the real metatable anyway,
-- so nothing has changed. Also make a special exception for data loaded via
-- mw.loadData(), which sets each metatable at its own __metatable key as a
-- way to stop the use of setmetatable() without actually hiding it. This is
-- spoofable, but low-risk.
return (pcall(setmetatable, t, mt) or rawget(mt, "mw_loadData") == true) and mt or false
end
dq9wymtk5x7eksc903k4f68nvugujf5
Citakan:dokumentasi
10
7476
26505
2024-06-28T16:52:02Z
id>Taylor 49
0
a
26505
wikitext
text/x-wiki
<includeonly>{{#invoke:dokumentasi|show|hr={{{hr|above}}}}}</includeonly><noinclude>
== Ketergantungan ==
{{modu|dokumentasi}}
[[Kategori:Templat umum]]
</noinclude>
qd29u73eak4g675x27m1xcvq4ywn3ku
26506
26177
2026-07-07T09:55:56Z
Sibiru45
115
1 ralatan matan [[:id:Templat:dokumentasi]]
26177
wikitext
text/x-wiki
<includeonly>{{#invoke:dokumentasi|show|hr={{{hr|above}}}}}</includeonly><noinclude>
== Katargantungan ==
{{modu|dokumentasi}}
[[Tumbung:Citakan umum]]
</noinclude>
9ymfvvlq6e9uzm5l7fkskkwp7vw9hby
Modul:dokumentasi
828
7477
26503
2026-04-08T06:25:57Z
id>Swarabakti
0
26503
Scribunto
text/plain
local export = {}
-- it is either here, or in [[Module:ugly hacks]], and it is not in ugly hacks.
function export.CONTENTMODEL()
return mw.title.getCurrentTitle().contentModel
end
local skins = {
["common" ] = "";
["vector" ] = "Vector";
["monobook" ] = "Monobook";
["cologneblue"] = "Cologne Blue";
["modern" ] = "Modern";
}
local Array = require "Module:array"
local function compare_pages(page1, page2, text)
return "[" .. tostring(
mw.uri.fullUrl("Special:ComparePages", { page1 = page1, page2 = page2 }))
.. " " .. text .. "]"
end
local function page_exists(title)
local success, title_obj = pcall(mw.title.new, title)
return success and title_obj.exists
end
-- Avoid transcluding [[Module:languages/cache]] everywhere.
local lang_cache = setmetatable({}, { __index = function (self, k)
return require "Module:languages/cache"[k]
end })
local function zh_link(word)
return require("Module:links").full_link{
lang = lang_cache.zh,
term = word
}
end
local function make_Unicode_data_documentation(title, cats)
local subpage, first_three_of_code_point
= title.fullText:match("^Module:Unicode data/([^/]+)/(%x%x%x)$")
if subpage == "names" or subpage == "images" then
local low, high =
tonumber(first_three_of_code_point .. "000", 16),
tonumber(first_three_of_code_point .. "FFF", 16)
return string.format(
"This data module contains the %s of " ..
"[[Appendix:Unicode|Unicode]] code points within the range U+%04X to U+%04X.",
subpage == "images" and "titles of images" or "names",
low, high)
end
end
-- This provides categories and documentation for various data modules, so that
-- [[Category:Uncategorized modules]] isn’t unnecessarily cluttered.
-- It is a list of tables, each of which have the following possible fields:
-- `regex` (required): A Lua pattern to match the module's title. If it matches, the data in this entry will be used.
-- Any captures in the pattern can by referenced in the `cat` field using %1 for the first capture, %2 for the
-- second, etc. (often used for creating the sortkey for the category). In addition, the captures are passed to the
-- `process` function as the third and subsequent parameters.
-- `process` (optional): This may be a function or a string. If it is a function, it is called as follows:
-- process(TITLE, CATS, CAPTURE1, CAPTURE2, ...)
-- where:
-- * TITLE is a title object describing the module's title; see [https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Title_objects].
-- * CATS is an array object (see [[Module:array]]) of categories that the module will be added to.
-- * CAPTURE1, CAPTURE2, ... contain any captures in the `regex` field.
-- The return value of `process` should be a string and will be used as the module's documentation.
-- If `process` is a string, it is the name of a submodule under 'Module:documentation/functions/' which returns a
-- function, of the same type as described above. If `process` is omitted entirely, the module will have no
-- documentation.
-- `cat` (optional): A string naming the category into which the module should be placed. Captures specified in `regex`
-- may be referenced in this string using %1 for the first capture, %2 for the second, etc. Currently, in order to put
-- the module into multiple categories, you need to write a `process` function that adds categories to the CATS
-- parameter passed in.
local module_regex = {
{
regex = "^Module:languages/.+$",
cat = "Language and script modules",
},
{
regex = "^Module:scripts/.+$",
cat = "Language and script modules",
},
{
regex = "^Module:data tables/data..?.?.?$",
cat = "Reference module sharded data tables",
},
{
regex = "^Module:Quotations/...?.?.?.?.?.?$",
cat = "Quotation data modules",
},
{
regex = "^Module:zh/data/dial%-pron/.+$",
cat = "Chinese dialectal pronunciation data modules",
process = "zh dial or syn",
},
{
regex = "^Module:zh/data/dial%-syn/.+$",
cat = "Chinese dialectal synonyms data modules",
process = "zh dial or syn",
},
{
regex = "^Module:zh/data/glyph%-data/.+$",
cat = "Chinese historical character forms data modules",
process = function(title, cats)
local character = title.fullText:match("^Module:zh/data/glyph%-data/(.+)")
if character then
return ("This module contains data on historical forms of the Chinese character %s.")
:format(zh_link(character))
end
end,
},
{
regex = "^Module:zh/data/ltc%-pron/(.+)$",
cat = "Middle Chinese pronunciation data modules|%1",
process = "zh data",
},
{
regex = "^Module:zh/data/och%-pron%-BS/(.+)$",
cat = "Old Chinese (Baxter-Sagart) pronunciation data modules|%1",
process = "zh data",
},
{
regex = "^Module:zh/data/och%-pron%-ZS/(.+)$",
cat = "Old Chinese (Zhengzhang) pronunciation data modules|%1",
process = "zh data",
},
{
-- capture rest of zh/data submodules
regex = "^Module:zh/data/(.+)$",
cat = "Chinese data modules|%1",
},
{
regex = "^Module:mul/guoxue%-data/cjk%-?(.*)$",
process = "guoxue-data",
},
{
regex = "^Module:Unicode data/(.+)$",
cat = "Unicode data modules|%1",
process = make_Unicode_data_documentation,
},
{
regex = "^Module:number list/data/(.+)$",
process = "number list",
},
{
regex = "^Module:accel/(.+)$",
process = function(title, cats)
local lang_code = title.subpageText
local lang = lang_cache[lang_code]
if lang then
cats:insert(lang:getCanonicalName() .. " modules|accel")
cats:insert(("Accel submodules|%s"):format(lang:getCanonicalName()))
return ("This module contains new entry creation rules for %s; see [[WT:ACCEL]] for an overview, and [[Module:accel]] for information on creating new rules.")
:format(lang:makeCategoryLink())
end
end,
},
{
regex = "^Module:inc%-ash/dial/data/(.+)$",
cat = "Ashokan Prakrit modules|%1",
process = function(title, cats)
local word = title.fullText:match("^Module:inc%-ash/dial/data/(.+)$")
if word then
local lang = lang_cache["inc-ash"]
return ("This module contains data on the pronunciation of %s in dialects of %s.")
:format(require("Module:links").full_link({ term = word, lang = lang }, "term"),
lang:makeCategoryLink())
end
end,
},
{
regex = "^Module:[%l-]+:Dialects$",
process = function(title, cats)
local content = title:getContent()
local has_aliases = content:find("aliases") ~= nil
return mw.getCurrentFrame():expandTemplate {
title = "dialectal data module",
args = { ["labels-aliases"] = has_aliases },
}
end,
},
{
regex = "^.+%-translit$",
process = "translit",
},
{
regex = "^Module:category tree/poscatboiler/data/lang%-specific/(.+)$",
process = function(title, cats, lang_code)
local lang = lang_cache[lang_code]
if lang then
local langname = lang:getCanonicalName()
cats:insert("Category tree data modules/poscatboiler|" .. langname)
cats:insert(langname .. " modules")
cats:insert(langname .. " data modules")
return "This module handles generating the descriptions and categorization for " .. langname .. " category pages "
.. "of the format \"" .. langname .. " LABEL\" where LABEL can be any text. Examples are "
.. "[[:Category:Bulgarian conjugation 2.1 verbs]] and [[:Category:Russian velar-stem neuter-form nouns]]. "
.. "This module is part of the poscatboiler system, which is a general framework for generating the "
.. "descriptions and categorization of category pages.\n\n"
.. "For more information, see [[Module:category tree/poscatboiler/data/lang-specific/documentation]]."
end
end
},
{
regex = "^Module:category tree/poscatboiler/data/(.+)$",
cat = "Category tree data modules/poscatboiler|%1",
},
{
regex = "^Module:ja/data/(.+)$",
cat = "Japanese data modules|%1",
},
{
regex = "^Module:Swadesh/data/(.+)$",
cat = "Swadesh modules|%1",
},
{
regex = "^Module:typing%-aids",
process = function(title, cats)
local data_suffix = title.fullText:match("^Module:typing%-aids/data/(.+)$")
if data_suffix then
cats:insert("Data modules")
if data_suffix:find "^[%l-]+$" then
local lang = require "Module:languages".getByCode(data_suffix)
if lang then
cats:insert(lang:getCanonicalName() .. " modules")
end
elseif data_suffix:find "^%u%l%l%l$" then
local script = require "Module:scripts".getByCode(data_suffix)
if script then
cats:insert(script:getCategoryName())
end
end
end
end,
},
{
regex = "^Module:R:([a-z%-]+):(.+)$",
process = function(title, cats, lang_code, refname)
local lang = lang_cache[lang_code]
if lang then
cats:insert(lang:getCanonicalName() .. " modules|" .. refname)
cats:insert(("Reference modules|%s"):format(lang:getCanonicalName()))
return mw.getCurrentFrame():preprocess("This module implements the reference template {{temp|R:" ..
lang_code .. ":" .. refname .. "}}.")
end
end,
},
}
function export.show(frame)
local params = {
["hr"] = {},
["for"] = {},
["from"] = {},
["notsubpage"] = { type = "boolean", default = false },
["nodoc"] = { type = "boolean", default = false },
}
local args = require("Module:parameters").process(frame.args, params)
local output = Array('\n<div class="documentation" style="display:block; clear:both">\n')
local cats = Array()
local nodoc = args.nodoc
if (not args.hr) or (args.hr == "above") then
output:insert("----\n")
end
local title = ((args['for'] ~= "") and args['for']) and mw.title.new(args['for'])
or mw.title.getCurrentTitle()
local doc_title = mw.title.new((args['from'] ~= "") and args['from']
or (title.fullText .. '/dokumentasi'))
local contentModel = title.contentModel
local pagetype = "Halaman " .. mw.getContentLanguage():lcfirst(title.nsText)
local preload, fallback_docs, doc_content, doc_content_module,
old_doc_title, user_name, skin_name, needs_doc
if contentModel == "javascript" then
pagetype = "script"
if title.nsText == 'MediaWiki' then
if title.text:find('Gadget-') then
preload = 'Template:documentation/preloadGadget'
else
preload = 'Template:documentation/preloadMediaWikiJavaScript'
end
else
preload = 'Template:documentation/preloadTemplate' -- XXX
end
if title.nsText == 'User' then
user_name = title.rootText
end
elseif contentModel == "css" then
pagetype = "style sheet"
preload = 'Template:documentation/preloadTemplate' -- XXX
if title.nsText == 'User' then
user_name = title.rootText
end
elseif contentModel == "Scribunto" then
pagetype = "module"
user_name = title.rootText:match("^[Uu]ser:(.+)")
if user_name then
preload = 'Template:documentation/preloadModuleSandbox'
else
preload = 'Template:documentation/preloadModule'
end
elseif title.nsText == "Template" then
pagetype = "templat"
preload = 'Template:documentation/preloadTemplate'
elseif title.nsText == "Wiktionary" then
pagetype = "project page"
preload = 'Template:documentation/preloadTemplate' -- XXX
end
if doc_title.isRedirect then
old_doc_title = doc_title
doc_title = mw.title.new(string.match(doc_title:getContent(),
"^#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]]-)%]%]"))
end
output:insert("<dl class=\"plainlinks\" style=\"font-size: smaller;\">")
if doc_title.exists then
output:insert(
"<dd><i style=\"font-size: larger;\">Halaman " ..
"[[Bantuan:Dokumentasi templat dan modul|dokumentasi]] ini terletak di [[" ..
doc_title.fullText .. "]]. " ..
"<sup>[[" .. doc_title:fullUrl { action = 'edit' } .. " sunting]]</sup> </i></dd>")
else
if contentModel == "Scribunto" then
local automatic_cats = nil
if user_name then
fallback_docs = "documentation/fallback/user module"
automatic_cats = {"User sandbox modules"}
else
for _, data in ipairs(module_regex) do
local captures = {mw.ustring.match(title.fullText, data.regex)}
if #captures > 0 then
local cat
local process_function
if type(data.process) == "function" then
process_function = data.process
elseif type(data.process) == "string" then
doc_content_module = "Module:documentation/functions/" .. data.process
process_function = require(doc_content_module)
end
if process_function then
doc_content = process_function(title, cats, unpack(captures))
end
cat = data.cat
if cat then
if type(cat) == "string" then
cat = {cat}
end
for _, c in ipairs(cat) do
-- gsub() and Lua :gsub() return two arguments, which causes all sorts of problems.
-- Terrible design, there should have been a separate two-argument function.
local gsub_sucks = mw.ustring.gsub(title.fullText, data.regex, c)
table.insert(cats, gsub_sucks)
end
end
break
end
end
end
if not automatic_cats then
local success, auto_cats =
pcall(require("Module:module categorization").categorize, frame, true)
if success then
for _, category in ipairs(auto_cats) do
cats:insert(category)
end
end
end
if title.subpageText == "templates" then
cats:insert("Template interface modules")
end
if automatic_cats then
for _, c in ipairs(automatic_cats) do
cats:insert(c)
end
end
-- meaning module is not in user’s sandbox or one of many datamodule boring series
needs_doc = not (automatic_cats or doc_content or fallback_docs)
elseif title.nsText == "Template" then
--cats:insert("Uncategorized templates")
needs_doc = not (fallback_docs or nodoc)
elseif (contentModel == "css") or (contentModel == "javascript") then
if user_name then
skin_name = skins[title.text:sub(#title.rootText + 1):match("^/([a-z]+)%.[jc]ss?$")]
if skin_name then
fallback_docs = 'documentation/fallback/user ' .. contentModel
end
end
end
if doc_content then
output:insert(
"<dd><i style=\"font-size: larger;\">Halaman " ..
"[[Help:Documenting templates and modules|dokumentasi]] ini " ..
"dimuat dengan [[" .. (doc_content_module or "Module:documentation") .. "]]. <sup>[[" ..
mw.title.new("Module:documentation"):fullUrl { action = 'edit' } ..
" edit]]</sup> </i></dd>")
elseif not nodoc then
output:insert(
"<dd><i style=\"font-size: larger;\">" .. pagetype ..
" ini belum memiliki [[Bantuan:Dokumentasi templat dan modul|halaman dokumentasi]]. " ..
(fallback_docs and "Silakan " or "Mohon ") ..
"[" .. doc_title:fullUrl { action = 'edit', preload = preload }
.. " dibuat terlebih dahulu].</i></dd>\n")
end
end
if title.fullText:match("^MediaWiki:Gadget%-") then
local is_gadget = false
local gadget_list = mw.title.new("MediaWiki:Gadgets-definition"):getContent()
for line in mw.text.gsplit(gadget_list, "\n") do
local gadget, opts, items = line:match("^%*%s*([A-Za-z][A-Za-z0-9_%-]*)%[(.-)%]|(.+)$") -- opts is unused
if not gadget then
gadget, items = line:match("^%*%s*([A-Za-z][A-Za-z0-9_%-]*)|(.+)$")
end
if gadget then
items = Array(mw.text.split(items, "|"))
for i, item in ipairs(items) do
if title.fullText == ("MediaWiki:Gadget-" .. item) then
is_gadget = true
output:insert("<dd> ''This script is a part of the <code>")
output:insert(gadget)
output:insert("</code> gadget ([")
output:insert(tostring(mw.uri.fullUrl('MediaWiki:Gadgets-definition', 'action=edit')))
output:insert(" edit definitions])'' <dl>")
output:insert("<dd> ''Description ([")
output:insert(tostring(mw.uri.fullUrl('MediaWiki:Gadget-' .. gadget, 'action=edit')))
output:insert(" edit])'': ")
local gadget_description = mw.message.new('Gadget-' .. gadget):plain()
gadget_description = frame:preprocess(gadget_description)
output:insert(gadget_description)
output:insert(" </dd>")
items:remove(i)
if #items > 0 then
for j, item in ipairs(items) do
items[j] = '[[MediaWiki:Gadget-' .. item .. '|' .. item .. ']]'
end
output:insert("<dd> ''Other parts'': ")
output:insert(mw.text.listToText(items))
output:insert("</dd>")
end
output:insert("</dl></dd>")
break
end
end
end
end
if not is_gadget then
output:insert("<dd> ''This script is not a part of any [")
output:insert(tostring(mw.uri.fullUrl('Special:Gadgets', 'uselang=en')))
output:insert(' gadget] ([')
output:insert(tostring(mw.uri.fullUrl('MediaWiki:Gadgets-definition', 'action=edit')))
output:insert(' edit definitions]).</dd>')
-- else
-- cats:insert("Wiktionary gadgets")
end
end
if old_doc_title then
output:insert("<dd> ''Redirected from'' [")
output:insert(old_doc_title:fullUrl { redirect = 'no' })
output:insert(" ")
output:insert(old_doc_title.fullText)
output:insert("] ([")
output:insert(old_doc_title:fullUrl { action = 'edit' })
output:insert(" edit]).</dd>\n")
end
local links = Array()
if title.isSubpage and not args.notsubpage then
links:insert("[[:" .. title.nsText .. ":" .. title.rootText .. "|root page]]")
links:insert("[[Special:PrefixIndex/" .. title.nsText .. ":" .. title.rootText .. "/|root page’s subpages]]")
else
links:insert("[[Special:PrefixIndex/" .. title.fullText .. "/|daftar subhalaman]]")
end
links:insert(
'[' .. tostring(mw.uri.fullUrl('Special:WhatLinksHere/' .. title.fullText,
'hidetrans=1&hideredirs=1')) .. ' pranala balik]')
if contentModel ~= "Scribunto" then
links:insert(
'[' .. tostring(mw.uri.fullUrl('Special:WhatLinksHere/' .. title.fullText,
'hidelinks=1&hidetrans=1')) .. ' pengalihan]')
end
if (contentModel == "javascript") or (contentModel == "css") then
if user_name then
links:insert("[[Special:MyPage" .. title.text:sub(#title.rootText + 1) .. "|your own]]")
end
else
links:insert(
'[' .. tostring(mw.uri.fullUrl('Special:WhatLinksHere/' .. title.fullText,
'hidelinks=1&hideredirs=1')) .. ' transklusi]')
end
if contentModel == "Scribunto" then
local is_testcases = title.isSubpage and title.subpageText == "testcases"
local without_subpage = title.nsText .. ":" .. title.baseText
if is_testcases then
links:insert("[[:" .. without_subpage .. "|tested module]]")
else
links:insert("[[" .. title.fullText .. "/testcases|testcases]]")
end
if user_name then
links:insert("[[User:" .. user_name .. "|user page]]")
links:insert("[[User talk:" .. user_name .. "|user talk page]]")
links:insert("[[Special:PrefixIndex/User:" .. user_name .. "/|userspace]]")
else
-- If sandbox module, add a link to the module that this is a sandbox of.
-- Exclude user sandbox modules like [[User:Dine2016/sandbox]].
if title.text:find("/sandbox%d*%f[/%z]") then
cats:insert("Sandbox modules")
-- Sandbox modules don’t really need documentation.
needs_doc = false
-- Will behave badly if “/sandbox” occurs twice in title!
local sandbox_of = title.fullText:gsub("/sandbox%d*%f[/%z]", "")
local diff
if page_exists(sandbox_of) then
diff = " (" .. compare_pages(title.fullText, sandbox_of, "diff") .. ")"
else
require("Module:debug").track("documentation/no sandbox of")
end
links:insert("[[:" .. sandbox_of .. "|sandbox of]]" .. (diff or ""))
-- If not a sandbox module, add link to sandbox module.
-- Sometimes there are multiple sandboxes for a single module:
-- [[Module:sa-pronunc/sandbox]], [[Module:sa-pronunc/sandbox2]].
-- Occasionally sandbox modules have their own subpages that are also
-- sandboxes: [[Module:grc-decl/sandbox/decl]].
else
local sandbox_title
if title.fullText:find("^Module:grc%-decl/") then
sandbox_title = title.fullText:gsub("^Module:grc%-decl/", "Module:grc-decl/sandbox/")
elseif is_testcases then
sandbox_title = title.fullText:gsub("/testcases", "/sandbox/testcases")
else
sandbox_title = title.fullText .. "/sandbox"
end
local sandbox_link = "[[:" .. sandbox_title .. "|sandbox]]"
local diff
if page_exists(sandbox_title) then
diff = " (" .. compare_pages(title.fullText, sandbox_title, "diff") .. ")"
end
links:insert(sandbox_link .. (diff or ""))
end
end
end
if title.nsText == "Template" then
-- Error search: all(any namespace), hastemplate (show pages using the template), insource (show source code), incategory (any/specific error) -- [[mw:Help:CirrusSearch]], [[w:Help:Searching/Regex]]
-- apparently same with/without: &profile=advanced&fulltext=1
local errorq = 'searchengineselect=mediawiki&search=all: hastemplate:\"'..title.rootText..'\" insource:\"'..title.rootText..'\" incategory:'
local eincategory = "Pages_with_module_errors|ParserFunction_errors|DisplayTitle_errors|Pages_with_ISBN_errors|Pages_with_ISSN_errors|Pages_with_reference_errors|Pages_with_syntax_highlighting_errors|Pages_with_TemplateStyles_errors"
links:insert(
'[' .. tostring(mw.uri.fullUrl('Special:Search', errorq..eincategory )) .. ' errors]'
.. ' (' ..
'[' .. tostring(mw.uri.fullUrl('Special:Search', errorq..'ParserFunction_errors' )) .. ' parser]'
.. '/' ..
'[' .. tostring(mw.uri.fullUrl('Special:Search', errorq..'Pages_with_module_errors' )) .. ' module]'
.. ')'
)
if title.isSubpage and title.text:find("/sandbox%d*%f[/%z]") then -- This is a sandbox template.
-- At the moment there are no user sandbox templates with subpage
-- “/sandbox”.
cats:insert("Sandbox templates")
-- Sandbox templates don’t really need documentation.
needs_doc = false
-- Will behave badly if “/sandbox” occurs twice in title!
local sandbox_of = title.fullText:gsub("/sandbox%d*%f[/%z]", "")
local diff
if page_exists(sandbox_of) then
diff = " (" .. compare_pages(title.fullText, sandbox_of, "diff") .. ")"
else
require("Module:debug").track("documentation/no sandbox of")
end
links:insert("[[:" .. sandbox_of .. "|sandbox of]]" .. (diff or ""))
else -- This is a template that can have a sandbox.
local sandbox_title = title.fullText .. "/sandbox"
local diff
if page_exists(sandbox_title) then
diff = " (" .. compare_pages(title.fullText, sandbox_title, "diff") .. ")"
end
links:insert("[[:" .. sandbox_title .. "|sandbox]]" .. (diff or ""))
end
end
if #links > 0 then
output:insert("<dd> ''Pranala terkait'': " .. links:concat(" • ") .. "</dd>")
end
output:insert("</dl>\n")
-- Show error from [[Module:category tree/topic cat/data]] on its submodules'
-- documentation to, for instance, warn about duplicate labels.
if title.fullText:find("Module:category tree/topic cat/data", 1, true) == 1 then
local ok, err = pcall(require, "Module:category tree/topic cat/data")
if not ok then
output:insert('<span class="error">' .. err .. '</span>\n\n')
end
end
if doc_title.exists then
-- Override automatic documentation, if present.
doc_content = frame:expandTemplate { title = doc_title.fullText }
elseif not doc_content and fallback_docs then
doc_content = frame:expandTemplate {
title = fallback_docs;
args = {
['user'] = user_name;
['page'] = title.fullText;
['skin name'] = skin_name;
}
}
end
if doc_content then
output:insert(doc_content)
end
output:insert(('\n<%s style="clear: both;" />'):format(args.hr == "below" and "hr" or "br"))
if not cats[1] and not doc_content then
if contentModel == "Scribunto" then
cats:insert("Uncategorized modules")
-- elseif title.nsText == "Template" then
-- cats:insert("Uncategorized templates")
end
end
if needs_doc then
cats:insert("Templates and modules needing documentation")
end
for _, cat in ipairs(cats) do
output:insert("[[Category:" .. cat .. "]]")
end
output:insert("</div>\n")
return output:concat()
end
-- Used by {{translit module documentation}}.
function export.translitModuleLangList(frame)
local pagename, subpage
if frame.args[1] then
pagename = frame.args[1]
else
local title = mw.title.getCurrentTitle()
subpage = title.subpageText
pagename = title.text
if subpage ~= pagename then
pagename = title.rootText
end
end
local translitModule = pagename
local languageObjects = require("Module:languages/byTranslitModule")(translitModule)
local codeInPagename = pagename:match("^([%l-]+)%-.*translit$")
local categories = Array()
local codeInPagenameInList = false
if codeInPagename then
if languageObjects[1] and subpage ~= "documentation" then
local agreement = languageObjects[2] and "s" or ""
categories:insert("[[Category:Transliteration modules used by " ..
#languageObjects .. " language" .. agreement .. "]]")
end
languageObjects = Array(languageObjects)
:filter(
function (lang)
local result = lang:getCode() ~= codeInPagename
codeInPagenameInList = codeInPagenameInList or result
return result
end)
end
if subpage ~= "documentation" then
for script_code in pagename:gmatch("%f[^-%z]%u%l%l%l%f[-]") do
local script = require "Module:scripts".getByCode(script_code)
if script then
categories:insert("[[Category:" .. script:getCategoryName() .. "]]")
end
end
end
if subpage ~= "documentation" and not page_exists("Module:" .. pagename .. "/testcases") then
categories:insert("[[Category:Transliteration modules without a testcases subpage]]")
end
if not languageObjects[1] then
return categories:concat()
end
local langs = Array(languageObjects)
:sort(
function(lang1, lang2)
return lang1:getCode() < lang2:getCode()
end)
-- This will not error because languageObjects is not empty.
:map(languageObjects[1].makeCategoryLink)
:serial_comma_join()
return "It is " .. ( codeInPagenameInList and "also" or "" ) ..
" used to transliterate " .. langs .. "." .. categories:concat()
end
return export
8to58jxg88edow7wa4bzkp5tmimt6n6
26504
26178
2026-07-07T09:55:56Z
Sibiru45
115
1 ralatan matan [[:id:Modul:dokumentasi]]
26178
Scribunto
text/plain
local export = {}
-- it is either here, or in [[Module:ugly hacks]], and it is not in ugly hacks.
function export.CONTENTMODEL()
return mw.title.getCurrentTitle().contentModel
end
local skins = {
["common" ] = "";
["vector" ] = "Vector";
["monobook" ] = "Monobook";
["cologneblue"] = "Cologne Blue";
["modern" ] = "Modern";
}
local Array = require "Module:array"
local function compare_pages(page1, page2, text)
return "[" .. tostring(
mw.uri.fullUrl("Special:ComparePages", { page1 = page1, page2 = page2 }))
.. " " .. text .. "]"
end
local function page_exists(title)
local success, title_obj = pcall(mw.title.new, title)
return success and title_obj.exists
end
-- Avoid transcluding [[Module:languages/cache]] everywhere.
local lang_cache = setmetatable({}, { __index = function (self, k)
return require "Module:languages/cache"[k]
end })
local function zh_link(word)
return require("Module:links").full_link{
lang = lang_cache.zh,
term = word
}
end
local function make_Unicode_data_documentation(title, cats)
local subpage, first_three_of_code_point
= title.fullText:match("^Module:Unicode data/([^/]+)/(%x%x%x)$")
if subpage == "names" or subpage == "images" then
local low, high =
tonumber(first_three_of_code_point .. "000", 16),
tonumber(first_three_of_code_point .. "FFF", 16)
return string.format(
"This data module contains the %s of " ..
"[[Appendix:Unicode|Unicode]] code points within the range U+%04X to U+%04X.",
subpage == "images" and "titles of images" or "names",
low, high)
end
end
-- This provides categories and documentation for various data modules, so that
-- [[Category:Uncategorized modules]] isn’t unnecessarily cluttered.
-- It is a list of tables, each of which have the following possible fields:
-- `regex` (required): A Lua pattern to match the module's title. If it matches, the data in this entry will be used.
-- Any captures in the pattern can by referenced in the `cat` field using %1 for the first capture, %2 for the
-- second, etc. (often used for creating the sortkey for the category). In addition, the captures are passed to the
-- `process` function as the third and subsequent parameters.
-- `process` (optional): This may be a function or a string. If it is a function, it is called as follows:
-- process(TITLE, CATS, CAPTURE1, CAPTURE2, ...)
-- where:
-- * TITLE is a title object describing the module's title; see [https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Title_objects].
-- * CATS is an array object (see [[Module:array]]) of categories that the module will be added to.
-- * CAPTURE1, CAPTURE2, ... contain any captures in the `regex` field.
-- The return value of `process` should be a string and will be used as the module's documentation.
-- If `process` is a string, it is the name of a submodule under 'Module:documentation/functions/' which returns a
-- function, of the same type as described above. If `process` is omitted entirely, the module will have no
-- documentation.
-- `cat` (optional): A string naming the category into which the module should be placed. Captures specified in `regex`
-- may be referenced in this string using %1 for the first capture, %2 for the second, etc. Currently, in order to put
-- the module into multiple categories, you need to write a `process` function that adds categories to the CATS
-- parameter passed in.
local module_regex = {
{
regex = "^Module:languages/.+$",
cat = "Language and script modules",
},
{
regex = "^Module:scripts/.+$",
cat = "Language and script modules",
},
{
regex = "^Module:data tables/data..?.?.?$",
cat = "Reference module sharded data tables",
},
{
regex = "^Module:Quotations/...?.?.?.?.?.?$",
cat = "Quotation data modules",
},
{
regex = "^Module:zh/data/dial%-pron/.+$",
cat = "Chinese dialectal pronunciation data modules",
process = "zh dial or syn",
},
{
regex = "^Module:zh/data/dial%-syn/.+$",
cat = "Chinese dialectal synonyms data modules",
process = "zh dial or syn",
},
{
regex = "^Module:zh/data/glyph%-data/.+$",
cat = "Chinese historical character forms data modules",
process = function(title, cats)
local character = title.fullText:match("^Module:zh/data/glyph%-data/(.+)")
if character then
return ("This module contains data on historical forms of the Chinese character %s.")
:format(zh_link(character))
end
end,
},
{
regex = "^Module:zh/data/ltc%-pron/(.+)$",
cat = "Middle Chinese pronunciation data modules|%1",
process = "zh data",
},
{
regex = "^Module:zh/data/och%-pron%-BS/(.+)$",
cat = "Old Chinese (Baxter-Sagart) pronunciation data modules|%1",
process = "zh data",
},
{
regex = "^Module:zh/data/och%-pron%-ZS/(.+)$",
cat = "Old Chinese (Zhengzhang) pronunciation data modules|%1",
process = "zh data",
},
{
-- capture rest of zh/data submodules
regex = "^Module:zh/data/(.+)$",
cat = "Chinese data modules|%1",
},
{
regex = "^Module:mul/guoxue%-data/cjk%-?(.*)$",
process = "guoxue-data",
},
{
regex = "^Module:Unicode data/(.+)$",
cat = "Unicode data modules|%1",
process = make_Unicode_data_documentation,
},
{
regex = "^Module:number list/data/(.+)$",
process = "number list",
},
{
regex = "^Module:accel/(.+)$",
process = function(title, cats)
local lang_code = title.subpageText
local lang = lang_cache[lang_code]
if lang then
cats:insert(lang:getCanonicalName() .. " modules|accel")
cats:insert(("Accel submodules|%s"):format(lang:getCanonicalName()))
return ("This module contains new entry creation rules for %s; see [[WT:ACCEL]] for an overview, and [[Module:accel]] for information on creating new rules.")
:format(lang:makeCategoryLink())
end
end,
},
{
regex = "^Module:inc%-ash/dial/data/(.+)$",
cat = "Ashokan Prakrit modules|%1",
process = function(title, cats)
local word = title.fullText:match("^Module:inc%-ash/dial/data/(.+)$")
if word then
local lang = lang_cache["inc-ash"]
return ("This module contains data on the pronunciation of %s in dialects of %s.")
:format(require("Module:links").full_link({ term = word, lang = lang }, "term"),
lang:makeCategoryLink())
end
end,
},
{
regex = "^Module:[%l-]+:Dialects$",
process = function(title, cats)
local content = title:getContent()
local has_aliases = content:find("aliases") ~= nil
return mw.getCurrentFrame():expandTemplate {
title = "dialectal data module",
args = { ["labels-aliases"] = has_aliases },
}
end,
},
{
regex = "^.+%-translit$",
process = "translit",
},
{
regex = "^Module:category tree/poscatboiler/data/lang%-specific/(.+)$",
process = function(title, cats, lang_code)
local lang = lang_cache[lang_code]
if lang then
local langname = lang:getCanonicalName()
cats:insert("Category tree data modules/poscatboiler|" .. langname)
cats:insert(langname .. " modules")
cats:insert(langname .. " data modules")
return "This module handles generating the descriptions and categorization for " .. langname .. " category pages "
.. "of the format \"" .. langname .. " LABEL\" where LABEL can be any text. Examples are "
.. "[[:Category:Bulgarian conjugation 2.1 verbs]] and [[:Category:Russian velar-stem neuter-form nouns]]. "
.. "This module is part of the poscatboiler system, which is a general framework for generating the "
.. "descriptions and categorization of category pages.\n\n"
.. "For more information, see [[Module:category tree/poscatboiler/data/lang-specific/documentation]]."
end
end
},
{
regex = "^Module:category tree/poscatboiler/data/(.+)$",
cat = "Category tree data modules/poscatboiler|%1",
},
{
regex = "^Module:ja/data/(.+)$",
cat = "Japanese data modules|%1",
},
{
regex = "^Module:Swadesh/data/(.+)$",
cat = "Swadesh modules|%1",
},
{
regex = "^Module:typing%-aids",
process = function(title, cats)
local data_suffix = title.fullText:match("^Module:typing%-aids/data/(.+)$")
if data_suffix then
cats:insert("Data modules")
if data_suffix:find "^[%l-]+$" then
local lang = require "Module:languages".getByCode(data_suffix)
if lang then
cats:insert(lang:getCanonicalName() .. " modules")
end
elseif data_suffix:find "^%u%l%l%l$" then
local script = require "Module:scripts".getByCode(data_suffix)
if script then
cats:insert(script:getCategoryName())
end
end
end
end,
},
{
regex = "^Module:R:([a-z%-]+):(.+)$",
process = function(title, cats, lang_code, refname)
local lang = lang_cache[lang_code]
if lang then
cats:insert(lang:getCanonicalName() .. " modules|" .. refname)
cats:insert(("Reference modules|%s"):format(lang:getCanonicalName()))
return mw.getCurrentFrame():preprocess("This module implements the reference template {{temp|R:" ..
lang_code .. ":" .. refname .. "}}.")
end
end,
},
}
function export.show(frame)
local params = {
["hr"] = {},
["for"] = {},
["from"] = {},
["notsubpage"] = { type = "boolean", default = false },
["nodoc"] = { type = "boolean", default = false },
}
local args = require("Module:parameters").process(frame.args, params)
local output = Array('\n<div class="documentation" style="display:block; clear:both">\n')
local cats = Array()
local nodoc = args.nodoc
if (not args.hr) or (args.hr == "above") then
output:insert("----\n")
end
local title = ((args['for'] ~= "") and args['for']) and mw.title.new(args['for'])
or mw.title.getCurrentTitle()
local doc_title = mw.title.new((args['from'] ~= "") and args['from']
or (title.fullText .. '/dokumentasi'))
local contentModel = title.contentModel
local pagetype = "Halaman " .. mw.getContentLanguage():lcfirst(title.nsText)
local preload, fallback_docs, doc_content, doc_content_module,
old_doc_title, user_name, skin_name, needs_doc
if contentModel == "javascript" then
pagetype = "script"
if title.nsText == 'MediaWiki' then
if title.text:find('Gadget-') then
preload = 'Template:documentation/preloadGadget'
else
preload = 'Template:documentation/preloadMediaWikiJavaScript'
end
else
preload = 'Template:documentation/preloadTemplate' -- XXX
end
if title.nsText == 'User' then
user_name = title.rootText
end
elseif contentModel == "css" then
pagetype = "style sheet"
preload = 'Template:documentation/preloadTemplate' -- XXX
if title.nsText == 'User' then
user_name = title.rootText
end
elseif contentModel == "Scribunto" then
pagetype = "module"
user_name = title.rootText:match("^[Uu]ser:(.+)")
if user_name then
preload = 'Template:documentation/preloadModuleSandbox'
else
preload = 'Template:documentation/preloadModule'
end
elseif title.nsText == "Template" then
pagetype = "templat"
preload = 'Template:documentation/preloadTemplate'
elseif title.nsText == "Wiktionary" then
pagetype = "project page"
preload = 'Template:documentation/preloadTemplate' -- XXX
end
if doc_title.isRedirect then
old_doc_title = doc_title
doc_title = mw.title.new(string.match(doc_title:getContent(),
"^#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]]-)%]%]"))
end
output:insert("<dl class=\"plainlinks\" style=\"font-size: smaller;\">")
if doc_title.exists then
output:insert(
"<dd><i style=\"font-size: larger;\">Halaman " ..
"[[Bantuan:Dokumentasi templat dan modul|dokumentasi]] ini terletak di [[" ..
doc_title.fullText .. "]]. " ..
"<sup>[[" .. doc_title:fullUrl { action = 'edit' } .. " sunting]]</sup> </i></dd>")
else
if contentModel == "Scribunto" then
local automatic_cats = nil
if user_name then
fallback_docs = "documentation/fallback/user module"
automatic_cats = {"User sandbox modules"}
else
for _, data in ipairs(module_regex) do
local captures = {mw.ustring.match(title.fullText, data.regex)}
if #captures > 0 then
local cat
local process_function
if type(data.process) == "function" then
process_function = data.process
elseif type(data.process) == "string" then
doc_content_module = "Module:documentation/functions/" .. data.process
process_function = require(doc_content_module)
end
if process_function then
doc_content = process_function(title, cats, unpack(captures))
end
cat = data.cat
if cat then
if type(cat) == "string" then
cat = {cat}
end
for _, c in ipairs(cat) do
-- gsub() and Lua :gsub() return two arguments, which causes all sorts of problems.
-- Terrible design, there should have been a separate two-argument function.
local gsub_sucks = mw.ustring.gsub(title.fullText, data.regex, c)
table.insert(cats, gsub_sucks)
end
end
break
end
end
end
if not automatic_cats then
local success, auto_cats =
pcall(require("Module:module categorization").categorize, frame, true)
if success then
for _, category in ipairs(auto_cats) do
cats:insert(category)
end
end
end
if title.subpageText == "templates" then
cats:insert("Template interface modules")
end
if automatic_cats then
for _, c in ipairs(automatic_cats) do
cats:insert(c)
end
end
-- meaning module is not in user’s sandbox or one of many datamodule boring series
needs_doc = not (automatic_cats or doc_content or fallback_docs)
elseif title.nsText == "Template" then
--cats:insert("Uncategorized templates")
needs_doc = not (fallback_docs or nodoc)
elseif (contentModel == "css") or (contentModel == "javascript") then
if user_name then
skin_name = skins[title.text:sub(#title.rootText + 1):match("^/([a-z]+)%.[jc]ss?$")]
if skin_name then
fallback_docs = 'documentation/fallback/user ' .. contentModel
end
end
end
if doc_content then
output:insert(
"<dd><i style=\"font-size: larger;\">Halaman " ..
"[[Help:Documenting templates and modules|dokumentasi]] ini " ..
"dimuat dengan [[" .. (doc_content_module or "Module:documentation") .. "]]. <sup>[[" ..
mw.title.new("Module:documentation"):fullUrl { action = 'edit' } ..
" edit]]</sup> </i></dd>")
elseif not nodoc then
output:insert(
"<dd><i style=\"font-size: larger;\">" .. pagetype ..
" ini belum memiliki [[Bantuan:Dokumentasi templat dan modul|halaman dokumentasi]]. " ..
(fallback_docs and "Silakan " or "Mohon ") ..
"[" .. doc_title:fullUrl { action = 'edit', preload = preload }
.. " dibuat terlebih dahulu].</i></dd>\n")
end
end
if title.fullText:match("^MediaWiki:Gadget%-") then
local is_gadget = false
local gadget_list = mw.title.new("MediaWiki:Gadgets-definition"):getContent()
for line in mw.text.gsplit(gadget_list, "\n") do
local gadget, opts, items = line:match("^%*%s*([A-Za-z][A-Za-z0-9_%-]*)%[(.-)%]|(.+)$") -- opts is unused
if not gadget then
gadget, items = line:match("^%*%s*([A-Za-z][A-Za-z0-9_%-]*)|(.+)$")
end
if gadget then
items = Array(mw.text.split(items, "|"))
for i, item in ipairs(items) do
if title.fullText == ("MediaWiki:Gadget-" .. item) then
is_gadget = true
output:insert("<dd> ''This script is a part of the <code>")
output:insert(gadget)
output:insert("</code> gadget ([")
output:insert(tostring(mw.uri.fullUrl('MediaWiki:Gadgets-definition', 'action=edit')))
output:insert(" edit definitions])'' <dl>")
output:insert("<dd> ''Description ([")
output:insert(tostring(mw.uri.fullUrl('MediaWiki:Gadget-' .. gadget, 'action=edit')))
output:insert(" edit])'': ")
local gadget_description = mw.message.new('Gadget-' .. gadget):plain()
gadget_description = frame:preprocess(gadget_description)
output:insert(gadget_description)
output:insert(" </dd>")
items:remove(i)
if #items > 0 then
for j, item in ipairs(items) do
items[j] = '[[MediaWiki:Gadget-' .. item .. '|' .. item .. ']]'
end
output:insert("<dd> ''Other parts'': ")
output:insert(mw.text.listToText(items))
output:insert("</dd>")
end
output:insert("</dl></dd>")
break
end
end
end
end
if not is_gadget then
output:insert("<dd> ''This script is not a part of any [")
output:insert(tostring(mw.uri.fullUrl('Special:Gadgets', 'uselang=en')))
output:insert(' gadget] ([')
output:insert(tostring(mw.uri.fullUrl('MediaWiki:Gadgets-definition', 'action=edit')))
output:insert(' edit definitions]).</dd>')
-- else
-- cats:insert("Wiktionary gadgets")
end
end
if old_doc_title then
output:insert("<dd> ''Redirected from'' [")
output:insert(old_doc_title:fullUrl { redirect = 'no' })
output:insert(" ")
output:insert(old_doc_title.fullText)
output:insert("] ([")
output:insert(old_doc_title:fullUrl { action = 'edit' })
output:insert(" edit]).</dd>\n")
end
local links = Array()
if title.isSubpage and not args.notsubpage then
links:insert("[[:" .. title.nsText .. ":" .. title.rootText .. "|root page]]")
links:insert("[[Special:PrefixIndex/" .. title.nsText .. ":" .. title.rootText .. "/|root page’s subpages]]")
else
links:insert("[[Special:PrefixIndex/" .. title.fullText .. "/|daftar subhalaman]]")
end
links:insert(
'[' .. tostring(mw.uri.fullUrl('Special:WhatLinksHere/' .. title.fullText,
'hidetrans=1&hideredirs=1')) .. ' pranala balik]')
if contentModel ~= "Scribunto" then
links:insert(
'[' .. tostring(mw.uri.fullUrl('Special:WhatLinksHere/' .. title.fullText,
'hidelinks=1&hidetrans=1')) .. ' pengalihan]')
end
if (contentModel == "javascript") or (contentModel == "css") then
if user_name then
links:insert("[[Special:MyPage" .. title.text:sub(#title.rootText + 1) .. "|your own]]")
end
else
links:insert(
'[' .. tostring(mw.uri.fullUrl('Special:WhatLinksHere/' .. title.fullText,
'hidelinks=1&hideredirs=1')) .. ' transklusi]')
end
if contentModel == "Scribunto" then
local is_testcases = title.isSubpage and title.subpageText == "testcases"
local without_subpage = title.nsText .. ":" .. title.baseText
if is_testcases then
links:insert("[[:" .. without_subpage .. "|tested module]]")
else
links:insert("[[" .. title.fullText .. "/testcases|testcases]]")
end
if user_name then
links:insert("[[User:" .. user_name .. "|user page]]")
links:insert("[[User talk:" .. user_name .. "|user talk page]]")
links:insert("[[Special:PrefixIndex/User:" .. user_name .. "/|userspace]]")
else
-- If sandbox module, add a link to the module that this is a sandbox of.
-- Exclude user sandbox modules like [[User:Dine2016/sandbox]].
if title.text:find("/sandbox%d*%f[/%z]") then
cats:insert("Sandbox modules")
-- Sandbox modules don’t really need documentation.
needs_doc = false
-- Will behave badly if “/sandbox” occurs twice in title!
local sandbox_of = title.fullText:gsub("/sandbox%d*%f[/%z]", "")
local diff
if page_exists(sandbox_of) then
diff = " (" .. compare_pages(title.fullText, sandbox_of, "diff") .. ")"
else
require("Module:debug").track("documentation/no sandbox of")
end
links:insert("[[:" .. sandbox_of .. "|sandbox of]]" .. (diff or ""))
-- If not a sandbox module, add link to sandbox module.
-- Sometimes there are multiple sandboxes for a single module:
-- [[Module:sa-pronunc/sandbox]], [[Module:sa-pronunc/sandbox2]].
-- Occasionally sandbox modules have their own subpages that are also
-- sandboxes: [[Module:grc-decl/sandbox/decl]].
else
local sandbox_title
if title.fullText:find("^Module:grc%-decl/") then
sandbox_title = title.fullText:gsub("^Module:grc%-decl/", "Module:grc-decl/sandbox/")
elseif is_testcases then
sandbox_title = title.fullText:gsub("/testcases", "/sandbox/testcases")
else
sandbox_title = title.fullText .. "/sandbox"
end
local sandbox_link = "[[:" .. sandbox_title .. "|sandbox]]"
local diff
if page_exists(sandbox_title) then
diff = " (" .. compare_pages(title.fullText, sandbox_title, "diff") .. ")"
end
links:insert(sandbox_link .. (diff or ""))
end
end
end
if title.nsText == "Template" then
-- Error search: all(any namespace), hastemplate (show pages using the template), insource (show source code), incategory (any/specific error) -- [[mw:Help:CirrusSearch]], [[w:Help:Searching/Regex]]
-- apparently same with/without: &profile=advanced&fulltext=1
local errorq = 'searchengineselect=mediawiki&search=all: hastemplate:\"'..title.rootText..'\" insource:\"'..title.rootText..'\" incategory:'
local eincategory = "Pages_with_module_errors|ParserFunction_errors|DisplayTitle_errors|Pages_with_ISBN_errors|Pages_with_ISSN_errors|Pages_with_reference_errors|Pages_with_syntax_highlighting_errors|Pages_with_TemplateStyles_errors"
links:insert(
'[' .. tostring(mw.uri.fullUrl('Special:Search', errorq..eincategory )) .. ' errors]'
.. ' (' ..
'[' .. tostring(mw.uri.fullUrl('Special:Search', errorq..'ParserFunction_errors' )) .. ' parser]'
.. '/' ..
'[' .. tostring(mw.uri.fullUrl('Special:Search', errorq..'Pages_with_module_errors' )) .. ' module]'
.. ')'
)
if title.isSubpage and title.text:find("/sandbox%d*%f[/%z]") then -- This is a sandbox template.
-- At the moment there are no user sandbox templates with subpage
-- “/sandbox”.
cats:insert("Sandbox templates")
-- Sandbox templates don’t really need documentation.
needs_doc = false
-- Will behave badly if “/sandbox” occurs twice in title!
local sandbox_of = title.fullText:gsub("/sandbox%d*%f[/%z]", "")
local diff
if page_exists(sandbox_of) then
diff = " (" .. compare_pages(title.fullText, sandbox_of, "diff") .. ")"
else
require("Module:debug").track("documentation/no sandbox of")
end
links:insert("[[:" .. sandbox_of .. "|sandbox of]]" .. (diff or ""))
else -- This is a template that can have a sandbox.
local sandbox_title = title.fullText .. "/sandbox"
local diff
if page_exists(sandbox_title) then
diff = " (" .. compare_pages(title.fullText, sandbox_title, "diff") .. ")"
end
links:insert("[[:" .. sandbox_title .. "|sandbox]]" .. (diff or ""))
end
end
if #links > 0 then
output:insert("<dd> ''Pranala terkait'': " .. links:concat(" • ") .. "</dd>")
end
output:insert("</dl>\n")
-- Show error from [[Module:category tree/topic cat/data]] on its submodules'
-- documentation to, for instance, warn about duplicate labels.
if title.fullText:find("Module:category tree/topic cat/data", 1, true) == 1 then
local ok, err = pcall(require, "Module:category tree/topic cat/data")
if not ok then
output:insert('<span class="error">' .. err .. '</span>\n\n')
end
end
if doc_title.exists then
-- Override automatic documentation, if present.
doc_content = frame:expandTemplate { title = doc_title.fullText }
elseif not doc_content and fallback_docs then
doc_content = frame:expandTemplate {
title = fallback_docs;
args = {
['user'] = user_name;
['page'] = title.fullText;
['skin name'] = skin_name;
}
}
end
if doc_content then
output:insert(doc_content)
end
output:insert(('\n<%s style="clear: both;" />'):format(args.hr == "below" and "hr" or "br"))
if not cats[1] and not doc_content then
if contentModel == "Scribunto" then
cats:insert("Uncategorized modules")
-- elseif title.nsText == "Template" then
-- cats:insert("Uncategorized templates")
end
end
if needs_doc then
cats:insert("Templates and modules needing documentation")
end
for _, cat in ipairs(cats) do
output:insert("[[Category:" .. cat .. "]]")
end
output:insert("</div>\n")
return output:concat()
end
-- Used by {{translit module documentation}}.
function export.translitModuleLangList(frame)
local pagename, subpage
if frame.args[1] then
pagename = frame.args[1]
else
local title = mw.title.getCurrentTitle()
subpage = title.subpageText
pagename = title.text
if subpage ~= pagename then
pagename = title.rootText
end
end
local translitModule = pagename
local languageObjects = require("Module:languages/byTranslitModule")(translitModule)
local codeInPagename = pagename:match("^([%l-]+)%-.*translit$")
local categories = Array()
local codeInPagenameInList = false
if codeInPagename then
if languageObjects[1] and subpage ~= "documentation" then
local agreement = languageObjects[2] and "s" or ""
categories:insert("[[Category:Transliteration modules used by " ..
#languageObjects .. " language" .. agreement .. "]]")
end
languageObjects = Array(languageObjects)
:filter(
function (lang)
local result = lang:getCode() ~= codeInPagename
codeInPagenameInList = codeInPagenameInList or result
return result
end)
end
if subpage ~= "documentation" then
for script_code in pagename:gmatch("%f[^-%z]%u%l%l%l%f[-]") do
local script = require "Module:scripts".getByCode(script_code)
if script then
categories:insert("[[Category:" .. script:getCategoryName() .. "]]")
end
end
end
if subpage ~= "documentation" and not page_exists("Module:" .. pagename .. "/testcases") then
categories:insert("[[Category:Transliteration modules without a testcases subpage]]")
end
if not languageObjects[1] then
return categories:concat()
end
local langs = Array(languageObjects)
:sort(
function(lang1, lang2)
return lang1:getCode() < lang2:getCode()
end)
-- This will not error because languageObjects is not empty.
:map(languageObjects[1].makeCategoryLink)
:serial_comma_join()
return "It is " .. ( codeInPagenameInList and "also" or "" ) ..
" used to transliterate " .. langs .. "." .. categories:concat()
end
return export
8to58jxg88edow7wa4bzkp5tmimt6n6
mokondo
0
7573
26489
2026-07-07T07:27:04Z
Sibiru45
115
Maulah laman nang isinya ''=={{bahasa|id}}== {{kepala|id}} {{-adj-|id}} # {{label|id|cakapan|hinaan}} {{akronim dari|id|modal kontol doang}}''
26489
wikitext
text/x-wiki
=={{bahasa|id}}==
{{kepala|id}}
{{-adj-|id}}
# {{label|id|cakapan|hinaan}} {{akronim dari|id|modal kontol doang}}
rtxybopwsklahtr9nx2tejk7ctvjwwf
26490
26489
2026-07-07T07:27:59Z
Sibiru45
115
/* Basa Indunisia */
26490
wikitext
text/x-wiki
=={{bahasa|id}}==
{{kepala|id}}
{{-adj-|id}}
# {{label|id|cakapan|hinaan}} {{akronim dari|id|mudal palir haja}}
r00r2rspnhy1rsplui2362coc4vqzud
Citakan:subhalaman dokumentasi
10
7574
26507
2026-04-08T06:09:05Z
id>Swarabakti
0
26507
wikitext
text/x-wiki
__noeditsection__ __notoc__<includeonly><!-- if not on a /documentation subpage, do nothing -->{{#ifeq:{{FULLPAGENAME}}|Templat:dokumentasi|<{{lc:}}!-- dummy comment to prevent a newline from appearing -->|{{#ifeq:{{SUBPAGENAME}}|dokumentasi|</includeonly><!--
-->{{maintenance box|grey
| documentation
| title = Dokumentasi untuk [[{{SUBJECTSPACE}}:{{BASEPAGENAME}}]]. <sup class="plainlinks">[[{{fullurl:{{SUBJECTSPACE}}:{{BASEPAGENAME}}|action=edit}} sunting]]</sup>
| image = [[File:Edit-copy green.svg|40px]]
| text = Halaman ini memuat [[Bantuan:Dokumentasi templat dan modul|informasi penggunaan]], [[Bantuan:Kategorisasi|kategori]], dan penjabaran lain bagi {{#switch:{{NAMESPACE}}|Module=modul|#default=templat}} yang dimaksud.
}}<!--
--><includeonly><!--
-->{{#ifexist:{{NAMESPACE}}:{{BASEPAGENAME}}|[[Kategori:Subhalaman dokumentasi]]|[[Kategori:Subhalaman dokumentasi yatim]]}}<!--
-->|<{{lc:}}!-- dummy comment to prevent a newline from appearing -->}}}}</includeonly><noinclude>{{dokumentasi}}[[Kategori:Templat dokumentasi]]</noinclude>
7qvbgi2vwol9npx4m3yganwla0rmm5w
26508
26507
2026-07-07T09:55:57Z
Sibiru45
115
1 ralatan matan [[:id:Templat:subhalaman_dokumentasi]]
26507
wikitext
text/x-wiki
__noeditsection__ __notoc__<includeonly><!-- if not on a /documentation subpage, do nothing -->{{#ifeq:{{FULLPAGENAME}}|Templat:dokumentasi|<{{lc:}}!-- dummy comment to prevent a newline from appearing -->|{{#ifeq:{{SUBPAGENAME}}|dokumentasi|</includeonly><!--
-->{{maintenance box|grey
| documentation
| title = Dokumentasi untuk [[{{SUBJECTSPACE}}:{{BASEPAGENAME}}]]. <sup class="plainlinks">[[{{fullurl:{{SUBJECTSPACE}}:{{BASEPAGENAME}}|action=edit}} sunting]]</sup>
| image = [[File:Edit-copy green.svg|40px]]
| text = Halaman ini memuat [[Bantuan:Dokumentasi templat dan modul|informasi penggunaan]], [[Bantuan:Kategorisasi|kategori]], dan penjabaran lain bagi {{#switch:{{NAMESPACE}}|Module=modul|#default=templat}} yang dimaksud.
}}<!--
--><includeonly><!--
-->{{#ifexist:{{NAMESPACE}}:{{BASEPAGENAME}}|[[Kategori:Subhalaman dokumentasi]]|[[Kategori:Subhalaman dokumentasi yatim]]}}<!--
-->|<{{lc:}}!-- dummy comment to prevent a newline from appearing -->}}}}</includeonly><noinclude>{{dokumentasi}}[[Kategori:Templat dokumentasi]]</noinclude>
7qvbgi2vwol9npx4m3yganwla0rmm5w
Citakan:label/dokumentasi
10
7575
26513
2026-04-08T06:24:54Z
id>Swarabakti
0
26513
wikitext
text/x-wiki
{{subhalaman dokumentasi}}
===Kegunaan===
Untuk menampilkan label yang membatasi pemakaian makna pada baris definisi. Batasan yang dimaksud dapat berupa batasan kelaziman, bidang ilmu, ragam dialek, dan sebagainya.
===Contoh pemakaian===
Berikut ini adalah penggunaan label pada entri pertama untuk istilah bahasa Indonesia {{sebut|id|beta}}.
<syntaxhighlight lang="wikitext">
# {{label|id|arkais}} {{bukan glos|pronomina [[persona pertama]] [[tunggal]], digunakan oleh orang [[terpandang]] ketika merujuk pada diri sendiri}}
# {{label|id|sastra|puitis}} {{sinonim dari|id|saya}}
# {{label|id|cakapan|_|Maluku|Timor|dan|_|Larantuka}} {{sinonim dari|id|saya}}
</syntaxhighlight>
<includeonly>[[Kategori:Templat definisi]]
</includeonly>
rnc1z0xsxqsj6kgrzhp2mkbyatf8seg
26514
26513
2026-07-07T09:55:57Z
Sibiru45
115
1 ralatan matan [[:id:Templat:label/dokumentasi]]
26513
wikitext
text/x-wiki
{{subhalaman dokumentasi}}
===Kegunaan===
Untuk menampilkan label yang membatasi pemakaian makna pada baris definisi. Batasan yang dimaksud dapat berupa batasan kelaziman, bidang ilmu, ragam dialek, dan sebagainya.
===Contoh pemakaian===
Berikut ini adalah penggunaan label pada entri pertama untuk istilah bahasa Indonesia {{sebut|id|beta}}.
<syntaxhighlight lang="wikitext">
# {{label|id|arkais}} {{bukan glos|pronomina [[persona pertama]] [[tunggal]], digunakan oleh orang [[terpandang]] ketika merujuk pada diri sendiri}}
# {{label|id|sastra|puitis}} {{sinonim dari|id|saya}}
# {{label|id|cakapan|_|Maluku|Timor|dan|_|Larantuka}} {{sinonim dari|id|saya}}
</syntaxhighlight>
<includeonly>[[Kategori:Templat definisi]]
</includeonly>
rnc1z0xsxqsj6kgrzhp2mkbyatf8seg