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>&amp;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>&amp;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 = { ["\""] = "&quot;", ["&"] = "&amp;", ["'"] = "&#039;", ["<"] = "&lt;", [">"] = "&gt;", }, 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 = { ["\""] = "&quot;", ["&"] = "&amp;", ["'"] = "&#039;", ["<"] = "&lt;", [">"] = "&gt;", }, 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">&#x5b;[{{fullurl:{{SUBJECTSPACE}}:{{BASEPAGENAME}}|action=edit}} sunting]&#x5d;</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">&#x5b;[{{fullurl:{{SUBJECTSPACE}}:{{BASEPAGENAME}}|action=edit}} sunting]&#x5d;</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