Wiktionary
suwiktionary
https://su.wiktionary.org/wiki/Tepas
MediaWiki 1.47.0-wmf.16
case-sensitive
Média
Husus
Obrolan
Pamaké
Obrolan pamaké
Wiktionary
Obrolan Wiktionary
Gambar
Obrolan gambar
MédiaWiki
Obrolan MédiaWiki
Citakan
Obrolan citakan
Pitulung
Obrolan pitulung
Kategori
Obrolan kategori
TimedText
TimedText talk
Modul
Pembicaraan Modul
Acara
Pembicaraan Acara
cai
0
2144
25320
24820
2026-08-19T09:05:45Z
Adhiiik
2885
25320
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-cai.wav}}
{{-k b-|su}}
* barang cair anu nyampak di walungan, situ, sagara, sarta jadi sumber utama kahirupan mahluk hirup.
:* ''Tatangkalan téh kudu disiram ku '''cai''' sangkan subur.''
:* ''Mangga atuh dileueut heula '''cai'''na.''
=== Tingkatan basa ===
* '''cai''' : basa loma
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|air}}
{{)}}
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
ly2mse1icp7ed868yizea770vr2v3kf
lada
0
4248
25325
24827
2026-08-19T09:11:20Z
Adhiiik
2885
25325
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-lada.wav}}
{{-k b-|su}}
* ngaran salahsahiji ngaran bungbu nyaéta pedes.
* rasa anu karasa panas atawa seureud dina létah, kawas rasa cabé atawa céngék.
:* ''Sambel téh meni '''lada''' pisan, nepi ka ngucur késang.''
:* ''Ulah loba teuing ninggalkeun céngék, bisi '''lada''' teuing.''
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|nama rempah yaitu lada, yang berbentuk bulat kecil}}
* {{id}} : {{trad-|id|pedas}}
{{)}}
{{kamus|A|ver=danadibrata}}
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
=={{bahasa|xmm}}==
{{kepala|xmm}}
: {{audio|xmm|LL-Q9240 (ind)-Manadonese-Lada.wav}}
{{nomina|xmm}}
# lada
[[Kategori:WikiMaknyus Manado]]
[[Kategori:WikiMaknyus]]
=={{bahasa|jv}}==
{{kepala|jv}}
: {{audio|jav|LL-Q33549 (jav)-Riana Mulyati-lada.wav}}
{{nomina|jv}}
# lada
[[Kategori:WikiMaknyus Banjarnegara]]
[[Kategori:WikiMaknyus]]
=={{bahasa|bew}}==
{{kepala|bew}}
: {{audio|bew|LL-Q33014 (bew)-Fizzypop21-lada.wav}}
{{nomina|bew}}
# lada
[[category:WikiMaknyus Jakarta]]
[[category:WikiMaknyus]]
26x00dpu3x6o5fqnht1e3a5u3bu4uy2
laja
0
4548
25328
24825
2026-08-19T09:16:40Z
Adhiiik
2885
25328
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-laja.wav}}
{{-k b-|su}}
* beuti (rimpang) anu ilaharna dipaké pikeun bungbu asakan, mibanda seungit anu has.
:* ''Tutuwuhan seungit anu ayana dina jero taneuh diantarana jahé jeung '''laja'''.''
:* '''''Laja''' biasana sok dipaké sambara jang bungbu opor hayam.''
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|lengkuas}}
{{)}}
{{kamus|ver=danadibrata}}
[[Kategori:Beasiswa Daring - Wiktionary Sunda]]
[[Kategori:Beasiswa Daring-Sofi Solihah]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
mssg3818j7885u3dame1wi0ao7v28if
25329
25328
2026-08-19T09:16:52Z
Adhiiik
2885
25329
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-laja.wav}}
{{-k b-|su}}
* beuti (rimpang) anu ilaharna dipaké pikeun bungbu asakan, mibanda seungit anu has.
:* ''Tutuwuhan seungit anu ayana dina jero taneuh diantarana jahé jeung '''laja'''.''
:* '''''Laja''' biasana sok dipaké sambara jang bungbu opor hayam.''
:* ''Asupkeun '''laja''' anu geus digeprék kana sayur asem.''
:* ''Ulah nepi ka poho ngasupkeun salam jeung '''laja''' sangkan seungit.''
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|lengkuas}}
{{)}}
{{kamus|ver=danadibrata}}
[[Kategori:Beasiswa Daring - Wiktionary Sunda]]
[[Kategori:Beasiswa Daring-Sofi Solihah]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
ffh3qvft53b4x67se8p9h0y2zgzwt07
jeruk
0
5027
25330
24823
2026-08-19T09:18:01Z
Adhiiik
2885
25330
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-jeruk.wav}}
{{-k b-|su}}
* ngaran sarupa buah anu rasana aya nu amis atawa haseum, loba ngandung cai, kulitna biasana warna héjo atawa konéng.
:* ''Bapa keur melak '''jeruk''' sugan bisa buahan di téras imah.''
:* ''Di Garut keur usum '''jeruk''' anu sohor kareueut amisna bari gedé buahna.''
=== Tingkatan basa ===
* '''jeruk''' : loma
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|jeruk}}
{{)}}
{{kamus|ver=danadibrata}}
[[Kategori:Beasiswa Daring II - Wiktionary Sunda]]
[[Kategori:Beasiswa Daring II-Sofi Solihah]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
=={{bahasa|jax}}==
{{kepala|jax}}
: {{audio|jax|LL-Q3915769 (jax)-yogi (Pitchrigi)-jeruk.wav}}
{{nomina|jax}}
# jeruk
[[Kategori:WikiMaknyus Jambi]]
[[Kategori:WikiMaknyus]]
=={{bahasa|jv}}==
{{kepala|jv}}
: {{audio|jav|LL-Q33549 (jav)-Ifah36-jeruk.wav}}
{{nomina|jv}}
# jeruk
[[Kategori:WikiMaknyus Banjarnegara]]
[[Kategori:WikiMaknyus]]
=={{bahasa|bew}}==
{{kepala|bew}}
: {{audio|bew|LL-Q33014 (bew)-Fizzypop21-jeruk.wav}}
{{nomina|bew}}
# jeruk
[[category:WikiMaknyus Jakarta]]
[[category:WikiMaknyus]]
gp89mduumrwzpby2wnad7niyfotxbo7
25331
25330
2026-08-19T09:18:15Z
Adhiiik
2885
25331
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-jeruk.wav}}
{{-k b-|su}}
* ngaran sarupa buah anu rasana aya nu amis atawa haseum, loba ngandung cai, kulitna biasana warna héjo atawa konéng.
:* ''Bapa keur melak '''jeruk''' sugan bisa buahan di téras imah.''
:* ''Di Garut keur usum '''jeruk''' anu sohor kareueut amisna bari gedé buahna.''
:* ''Uing meuli buah '''jeruk''' dua kilo ti pasar.''
:* ''Cai '''jeruk''' panas téh genah pisan diinum lamun keur batuk.''
=== Tingkatan basa ===
* '''jeruk''' : loma
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|jeruk}}
{{)}}
{{kamus|ver=danadibrata}}
[[Kategori:Beasiswa Daring II - Wiktionary Sunda]]
[[Kategori:Beasiswa Daring II-Sofi Solihah]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
=={{bahasa|jax}}==
{{kepala|jax}}
: {{audio|jax|LL-Q3915769 (jax)-yogi (Pitchrigi)-jeruk.wav}}
{{nomina|jax}}
# jeruk
[[Kategori:WikiMaknyus Jambi]]
[[Kategori:WikiMaknyus]]
=={{bahasa|jv}}==
{{kepala|jv}}
: {{audio|jav|LL-Q33549 (jav)-Ifah36-jeruk.wav}}
{{nomina|jv}}
# jeruk
[[Kategori:WikiMaknyus Banjarnegara]]
[[Kategori:WikiMaknyus]]
=={{bahasa|bew}}==
{{kepala|bew}}
: {{audio|bew|LL-Q33014 (bew)-Fizzypop21-jeruk.wav}}
{{nomina|bew}}
# jeruk
[[category:WikiMaknyus Jakarta]]
[[category:WikiMaknyus]]
ofb62p6ixr1qk7jruao66lubvtnf0m0
gula
0
5372
25323
24828
2026-08-19T09:08:05Z
Adhiiik
2885
25323
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-gula.wav}}
{{-k b-|su}}
* bahan amis anu biasana dijieun tina cai tiwu atawa lahang kawung, dipaké pikeun pangamis kadaharan atawa inuman.
:* ''Kopi téh '''gulana''' ulah loba teuing sok kareueut teuing.''
:* ''Ki Guru keur ngadahar kulub sampeu dicocolkeun kana '''gula''' bodas.''
=== Tingkatan basa ===
* '''gula''' : basa loma
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|gula}}
{{)}}
{{kamus|ver=Satjadibrata}}
[[Kategori:Beasiswa Daring II-YogiYY]]
[[Kategori:Beasiswa Daring II - Wiktionary Sunda]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
=={{bahasa|bew}}==
{{kepala|bew}}
: {{audio|bew|LL-Q33014 (bew)-Fizzypop21-gula.wav}}
{{nomina|bew}}
# gula
[[category:WikiMaknyus Jakarta]]
[[category:WikiMaknyus]]
affr42yi69ea22o9b2qf02dhlzrsyg7
25324
25323
2026-08-19T09:08:17Z
Adhiiik
2885
25324
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-gula.wav}}
{{-k b-|su}}
* bahan amis anu biasana dijieun tina cai tiwu atawa lahang kawung, dipaké pikeun pangamis kadaharan atawa inuman.
:* ''Kopi téh '''gulana''' ulah loba teuing sok kareueut teuing.''
:* ''Ki Guru keur ngadahar kulub sampeu dicocolkeun kana '''gula''' bodas.''
:* ''Mang Udin keur nyieun '''gula''' beureum di hawu.''
=== Tingkatan basa ===
* '''gula''' : basa loma
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|gula}}
{{)}}
{{kamus|ver=Satjadibrata}}
[[Kategori:Beasiswa Daring II-YogiYY]]
[[Kategori:Beasiswa Daring II - Wiktionary Sunda]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
=={{bahasa|bew}}==
{{kepala|bew}}
: {{audio|bew|LL-Q33014 (bew)-Fizzypop21-gula.wav}}
{{nomina|bew}}
# gula
[[category:WikiMaknyus Jakarta]]
[[category:WikiMaknyus]]
5zp23zcfa7h6wmlxpiesq3yjoihf85j
lisah
0
6018
25321
24821
2026-08-19T09:06:48Z
Adhiiik
2885
25321
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-lisah.wav}}
{{-k b-|su}}
* minyak, bisa nu dipake ngagoréng.
:* ''Pangaos '''lisah''' di supermarket ayeuna geus naek dua kali lipatna.''
:* ''Lamun ngagoréng kurupuk '''lisah''' na kudu ngeuyeumbeu.''
:* ''Urang kudu meuli '''lisah''' keur ngagoréng lauk di dapur.''
=== Tingkatan basa ===
* '''lisah''': basa loma
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|Minyak}}
{{)}}
{{kamus|ver=danadibrata}}
[[Kategori:Beasiswa Daring - Wiktionary Sunda]]
[[Kategori:Beasiswa Daring - RellaSha]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
tml04em0emxws4id3hylwmf8ytij859
25322
25321
2026-08-19T09:07:03Z
Adhiiik
2885
25322
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-lisah.wav}}
{{-k b-|su}}
* minyak, bisa nu dipake ngagoréng.
:* ''Pangaos '''lisah''' di supermarket ayeuna geus naek dua kali lipatna.''
:* ''Lamun ngagoréng kurupuk '''lisah''' na kudu ngeuyeumbeu.''
:* ''Urang kudu meuli '''lisah''' keur ngagoréng lauk di dapur.''
:* ''Mesin motor téh kudu diganti '''lisah'''na sangkan lemes jalanna.''
=== Tingkatan basa ===
* '''lisah''': basa loma
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|Minyak}}
{{)}}
{{kamus|ver=danadibrata}}
[[Kategori:Beasiswa Daring - Wiktionary Sunda]]
[[Kategori:Beasiswa Daring - RellaSha]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
dw2y9jsauxbzcka598ur79561xzalio
Modul:form of/templates
828
7167
25206
22285
2026-08-19T04:49:52Z
Deepturquoise
2456
25206
Scribunto
text/plain
local export = {}
local debug_track_module = "Module:debug/track"
local form_of_module = "Module:form of"
local functions_module = "Module:fun"
local headword_data_module = "Module:headword/data"
local languages_module = "Module:languages"
local load_module = "Module:load"
local parameters_module = "Module:parameters"
local parameter_utilities_module = "Module:parameter utilities"
local parse_interface_module = "Module:parse interface"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local insert = table.insert
local ipairs = ipairs
local pairs = pairs
local require = require
local boolean_param = {type = "boolean"}
-- FIXME: Finish [[Module:format utilities]].
-- local allowed_conj_set = require(format_utilities_module).allowed_conj_set_for_join_segments
local allowed_conj_set = {["and"] = true, ["or"] = true, ["and/or"] = true}
--[==[
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 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 extend(...)
extend = require(table_module).extend
return extend(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_form_of(...)
format_form_of = require(form_of_module).format_form_of
return format_form_of(...)
end
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
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 load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function parse_inline_modifiers(...)
parse_inline_modifiers = require(parse_interface_module).parse_inline_modifiers
return parse_inline_modifiers(...)
end
local function pattern_escape(...)
pattern_escape = require(string_utilities_module).pattern_escape
return pattern_escape(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function safe_load_data(...)
safe_load_data = require(load_module).safe_load_data
return safe_load_data(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function split_tag_set(...)
split_tag_set = require(form_of_module).split_tag_set
return split_tag_set(...)
end
local function tagged_inflections(...)
tagged_inflections = require(form_of_module).tagged_inflections
return tagged_inflections(...)
end
local function trim(...)
trim = require(string_utilities_module).trim
return trim(...)
end
local function ucfirst(...)
ucfirst = require(string_utilities_module).ucfirst
return ucfirst(...)
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 force_cat
local function get_force_cat()
force_cat, get_force_cat = require(form_of_module).force_cat, nil
return force_cat
end
local m_form_of_pos
local function get_m_form_of_pos()
m_form_of_pos, get_m_form_of_pos = load_data(headword_data_module).pos_aliases, nil
return m_form_of_pos
end
local module_prefix
local function get_module_prefix()
module_prefix, get_module_prefix = require(form_of_module).form_of_lang_data_module_prefix, nil
return module_prefix
end
--[==[ intro:
This module contains code that directly implements {{tl|form of}}, {{tl|inflection of}}, and the various other
[[:Category:Form-of templates|form-of templates]]. It is meant to be called directly from templates. See also
[[Module:form of]], which contains the underlying implementing code and is meant to be called from other modules.
]==]
-- Add tracking category for PAGE when called from TEMPLATE. The tracking category linked to is
-- [[Wiktionary:Tracking/form of/TEMPLATE/PAGE]]. If TEMPLATE is omitted, the tracking category is of the form
-- [[Wiktionary:Tracking/form of/PAGE]].
local function track(page, template)
debug_track("form of/" .. (template and template .. "/" or "") .. page)
end
local function get_common_template_params()
return {
-- Named params not controlling link display
["cat"] = {list = true, sublist = "comma without whitespace", flatten = true},
["notext"] = boolean_param,
["sort"] = true,
["enclitic"] = true,
-- FIXME! The following should only be available when withcap=1 in invocation args or when withencap=1 and the
-- language is "en". Before doing that, need to remove all uses of nocap= in other circumstances.
["nocap"] = boolean_param,
["addl"] = true, -- additional text to display at the end, before the closing </span>
["pagename"] = true, -- for testing, etc.
}
end
-- Split TAGSPECS (inflection tag specifications) on SPLIT_REGEX, which
-- may be nil for no splitting.
local function split_inflection_tags(tagspecs, split_regex)
if not split_regex then
return tagspecs
end
local inflection_tags = {}
for _, tagspec in ipairs(tagspecs) do
for tag in gsplit(tagspec, split_regex) do
insert(inflection_tags, tag)
end
end
return inflection_tags
end
local function parse_terms_with_inline_modifiers(paramname, val, param_mods, lang)
local function generate_obj(term)
return {lang = lang, term = decode_entities(term)}
end
return parse_inline_modifiers(val, {
paramname = paramname,
param_mods = param_mods,
generate_obj = generate_obj,
splitchar = ",",
outer_container = {},
})
end
-- Need to do what [[Module:parameters]] does to string arguments from parent_args as we're running this
-- before calling [[Module:parameters]] on parent_args.
local function ine(arg)
if not arg then
return nil
end
arg = trim(arg)
return arg ~= "" and arg or nil
end
local function add_base_lemma_params(parent_args, iargs, params, compat)
-- Check the language-specific data for additional base lemma params. But if there's no language-specific data,
-- attempt any parent varieties as well (i.e. superordinate varieties).
local lang = get_lang(ine(parent_args[compat and "lang" or 1]) or ine(iargs.lang) or "und", nil, true)
while lang do
local langdata = safe_load_data((module_prefix or get_module_prefix()) .. lang:getCode())
if langdata then
local base_lemma_params = langdata.base_lemma_params
if base_lemma_params then
for _, param in ipairs(base_lemma_params) do
params[param.param] = true
end
return base_lemma_params
end
end
lang = lang:getParent()
end
end
--[=[
Modify `params` in-place by adding parameters that control the link to the main entry and any base lemmas. `term_param`
is the number of the param specifying the main entry itself; `term_param` + 1 will be the display text, and `term_param`
+ 2 will be the gloss, unless `no_numbered_gloss` is given. The base lemma parameters are determined by attempting to
load language-specific data for the language of the page; this comes from |lang= if `compat` is given, else from |1=.
]=]
local function add_link_and_base_lemma_params(iargs, parent_args, params, term_param, compat, no_numbered_gloss)
local base_lemma_params
if not iargs.nolink and not iargs.linktext then
-- Numbered params controlling link display
if iargs.with_multiple_parts then
params[term_param] = {list = true, allow_holes = true}
else
params[term_param + 1] = {alias_of = "alt"}
if not no_numbered_gloss then
params[term_param + 2] = {alias_of = "t"}
end
params[term_param] = true
end
base_lemma_params = add_base_lemma_params(parent_args, iargs, params, compat)
end
return base_lemma_params
end
local function handle_withdot_withcap(iargs, params)
local ignored_tracked_params = {}
if iargs.withdot then
params.dot = true
params.nodot = boolean_param
end
if iargs.withcap and iargs.withencap then
error("Internal error: Can specify only one of withcap= and withencap=")
end
if not iargs.withcap then
params.cap = boolean_param
ignored_tracked_params.nocap = iargs.withencap and "non-english" or "always"
end
return ignored_tracked_params
end
--[=[
Construct and return the full definition line for a form-of-type template invocation. `data` is an object with the
following fields:
* `template`: Approximate template name, for debug tracking;
* `iargs`: processed invocation arguments;
* `parent_args`: raw parent args from `frame:getParent().args`;
* `params`: partially constructed params structure of the sort passed to `process()` in [[Module:parameters]], but
without any link params;
* `ignored_tracked_params`: params that are ignored but should be tracked, to be eventually removed;
* `term_param`: the parent argument specifying the main entry;
* `compat`: true if the language code is found in args.lang instead of args[1];
* `base_lemma_params`: if non-nil, a list of base lemma param objects of the sort stored in the language-specific data;
* `do_form_of`: a function of one argument, `lemma_data`, that returns the actual definition-line text and any
language-specific categories. See below.
This function does several things:
# If link parameters are called for (neither `iargs.nolink` nor `iargs.linktext` are given), augment the `params`
structure with separate link parameters.
# Modify the parent args as appropriate if invocation arguments def= or ignore= are given.
# Parse the parent args, both for separate parameter properties and inline modifiers on the term parameter (which may
consist of multiple comma-separated terms).
# Compute categories to add to the page, including language-specific categories and any categories requested by the
invocation or parent args.
# Parse enclitic and extra base lemma parameters.
# Construct the actual text using `do_form_of`.
# Add a terminating period/dot as appropriate, along with the formatted categories.
`do_form_of` takes one argument, `lemma_data`, which looks like this:
{
lang = LANG,
args = {ARG = VALUE, ARG = VALUE, ...},
lemmas = {LEMMA_OBJ, LEMMA_OBJ, ...},
enclitics = {ENCLITIC_OBJ, ENCLITIC_OBJ, ...},
base_lemmas = {BASE_LEMMA_OBJ, BASE_LEMMA_OBJ, ...},
categories = {"CATEGORY", "CATEGORY", ...},
posttext = "POSTTEXT" or nil,
}
where
* LANG is the language code;
* ARGS is the parsed arguments, based on what the user specified;
* LEMMAS is a sequence of objects specifying the main entries/lemmas, as passed to full_link in [[Module:links]];
however, if the invocation argument linktext= is given, it will be a string consisting of that text, and if the
invocation argument nolink= is given, it will be nil;
* ENCLITICS is nil or a sequence of objects specifying the enclitics, as passed to full_link in [[Module:links]];
* BASE_LEMMA_OBJ is a sequence of objects specifying the base lemma(s), which are used when the lemma is itself a
form of another lemma (the base lemma), e.g. a comparative, superlative or participle; each object is of the form
{ paramobj = PARAM_OBJ, lemmas = {LEMMA_OBJ, LEMMA_OBJ, ...} } where PARAM_OBJ describes the properties of the
base lemma parameter (i.e. the relationship between the intermediate and base lemmas) and LEMMA_OBJ is of the same
format of ENCLITIC_OBJ, i.e. an object suitable to be passed to full_link in [[Module:links]]; PARAM_OBJ is of the
format { param = "PARAM", tags = {"TAG", "TAG", ...} } where PARAM is the name of the parameter to
{{inflection of}} etc. that holds the base lemma(s) of the specified relationship and the tags describe the
relationship, such as {"comd"} or {"past", "part"};
* CATEGORIES is the categories to add the page to (consisting of any categories specified in the invocation or
parent args and any tracking categories, but not any additional lang-specific categories that may be added by
{{inflection of}} or similar templates);
* POSTTEXT is text to display at the end of the form-of text, before the final </span> (or at the end of the first
line, before the colon, in a multiline {{infl of}} call).
`do_form_of` should return two arguments:
(1) The actual definition-line text, marked up appropriately with <span>...</span> but without any terminating
period/dot.
(2) Any extra categories to add the page to (other than those that can be derived from parameters specified to the
invocation or parent arguments, which will automatically be added to the page).
]=]
local function construct_form_of_text(data)
local template, iargs, parent_args, params, no_numbered_gloss, do_form_of =
data.template, data.iargs, data.parent_args, data.params, data.no_numbered_gloss, data.do_form_of
local term_param = iargs.term_param
local compat = iargs.lang or parent_args.lang
term_param = term_param or compat and 1 or 2
-- Numbered params
params[compat and "lang" or 1] = {
required = not iargs.lang,
type = "language",
default = iargs.lang or "und"
}
-- Error to catch most uses of old-style parameters for {{contraction of}}. (FIXME: Remove eventually.)
if iargs.with_multiple_parts then
if ine(parent_args[term_param + 2]) and not ine(parent_args[term_param + 1]) and not ine(parent_args.tr2) and not ine(parent_args.ts2)
and not ine(parent_args.t2) and not ine(parent_args.gloss2) and not ine(parent_args.g2)
and not ine(parent_args.alt2) then
error(("You specified a term in %s= and not one in %s=. You probably meant to use t= to specify a gloss instead. "
.. "If you intended to specify two terms, put the second term in %s=."):format(term_param + 2, term_param + 1,
term_param + 1))
end
if not ine(parent_args[term_param + 1]) and not ine(parent_args.alt2) and not ine(parent_args.tr2) and not ine(parent_args.ts2)
and ine(parent_args.g2) then
error(("You specified a gender in g2= but no term in %s=. You were probably trying to specify two genders for "
.. "a single term. To do that, put both genders in g=, comma-separated."):format(term_param + 1))
end
end
local base_lemma_params = add_link_and_base_lemma_params(iargs, parent_args, params, term_param, compat,
no_numbered_gloss)
local ignored_tracked_params = handle_withdot_withcap(iargs, params)
--[=[
Process parent arguments. This is similar to the following:
require("Module:parameters").process(parent_args, params)
but in addition it does the following:
(1) Supplies default values for unspecified parent arguments as specified in DEFAULTS, which consist of specs of the
form "ARG=VALUE". These are added to the parent arguments prior to processing, so boolean and number parameters
will process the value appropriately.
(2) Removes parent arguments specified in IGNORESPECS, which consist either of bare argument names to remove, or
list-argument names to remove of the form "ARG:list".
(3) Tracks the use of any parent arguments specified in TRACKED_PARAMS, which is a set where the keys are arguments
as they exist after processing (hence numeric arguments should be numbers, not strings) and the values should be
boolean true.
]=]--
local defaults = iargs.def
local ignorespecs = iargs.ignore
if defaults[1] or ignorespecs[1] then
local new_parent_args = {}
for _, default in ipairs(defaults) do
local defparam, defval = default:match("^(.-)=(.*)$")
if not defparam then
error("Bad default spec " .. default)
end
new_parent_args[defparam] = defval
end
local params_to_ignore = {}
local numbered_list_params_to_ignore = {}
local named_list_params_to_ignore = {}
for _, ignorespec in ipairs(ignorespecs) do
for ignore in gsplit(ignorespec, ",") do
local param = ignore:match("^(.*):list$")
if param then
if param:match("^%d+$") then
insert(numbered_list_params_to_ignore, tonumber(param))
else
insert(named_list_params_to_ignore, "^" .. pattern_escape(param) .. "%d*$")
end
else
if ignore:match("^%d+$") then
ignore = tonumber(ignore)
end
params_to_ignore[ignore] = true
end
end
end
for k, v in pairs(parent_args) do
if not params_to_ignore[k] then
local ignore_me = false
if type(k) == "number" then
for _, lparam in ipairs(numbered_list_params_to_ignore) do
if k >= lparam then
ignore_me = true
break
end
end
else
for _, lparam in ipairs(named_list_params_to_ignore) do
if k:match(lparam) then
ignore_me = true
break
end
end
end
if not ignore_me then
new_parent_args[k] = v
end
end
end
parent_args = new_parent_args
end
local param_mods_with_conj, param_mods_without_conj
local function get_param_mods(with_conj)
if with_conj then
if not param_mods_with_conj then
param_mods_with_conj = require(parameter_utilities_module).construct_param_mods {
{group = {"link", "q", "l", "ref"}},
{param = "conj", set = allowed_conj_set, overall = true},
}
end
return param_mods_with_conj
else
if not param_mods_without_conj then
param_mods_without_conj = require(parameter_utilities_module).construct_param_mods {
{group = {"link", "q", "l", "ref"}},
-- Override lit= to have a separate overall value
{param = "lit", separate_no_index = true},
}
end
return param_mods_without_conj
end
end
local terms, args
if iargs.nolink or iargs.linktext then
args = process_params(parent_args, params)
else
local m_param_utils = require(parameter_utilities_module)
if iargs.with_multiple_parts then
terms, args = m_param_utils.parse_list_with_inline_modifiers_and_separate_params {
params = params,
param_mods = get_param_mods(false),
raw_args = parent_args,
termarg = term_param,
track_module = "form of" .. (template and "/" .. template or ""),
lang = compat and "lang" or 1,
sc = "sc.default",
parse_lang_prefix = true,
default_separator = " +‎ ",
special_separators = {[";"] = " or "},
}
else
terms, args = m_param_utils.parse_term_with_inline_modifiers_and_separate_params {
params = params,
param_mods = get_param_mods("with conj"),
raw_args = parent_args,
termarg = term_param,
track_module = "form of" .. (template and "/" .. template or ""),
lang = compat and "lang" or 1,
sc = "sc",
parse_lang_prefix = true,
make_separate_g_into_list = true,
splitchar = ",",
subitem_param_handling = "last",
}
end
end
local lang = args[compat and "lang" or 1]
-- Tracking for certain user-specified params. This is generally used for
-- parameters that we accept but ignore, so that we can eventually remove
-- all uses of these params and stop accepting them.
if ignored_tracked_params then
for ignored_tracked_param, condition in pairs(ignored_tracked_params) do
if parent_args[ignored_tracked_param] and (condition ~= "non-english" or lang:getCode() ~= "en") then
track("arg/" .. ignored_tracked_param, template)
track("arg/" .. ignored_tracked_param)
end
end
end
-- Determine categories for the page, including tracking categories
local categories = {}
if not args.nocat then
for _, cat in ipairs(iargs.cat) do
insert(categories, lang:getFullName() .. " " .. cat)
end
end
for _, cat in ipairs(args.cat) do
insert(categories, lang:getFullName() .. " " .. cat)
end
-- Format the link, preceding text and categories
local function add_term_tracking_categories(term)
-- add tracking category if term is same as page title
if term and mw.loadData("Module:headword/data").pagename == lang:stripDiacritics(term) then
insert(categories, "Forms linking to themselves")
end
-- maybe add tracking category if primary entry doesn't exist (this is an
-- expensive call so we don't do it by default)
if iargs.noprimaryentrycat and term and mw.title.getCurrentTitle().nsText == ""
and not mw.title.new(term):getContent() then
insert(categories, lang:getFullName() .. " " .. iargs.noprimaryentrycat)
end
end
local lemmas
if iargs.nolink then
lemmas = nil
elseif iargs.linktext then
lemmas = iargs.linktext
else
if iargs.with_multiple_parts then
lemmas = terms
else
lemmas = terms.terms
end
if not lemmas[1] then
if mw.title.getCurrentTitle().nsText == "Template" then
lemmas[1] = {
lang = lang,
term = "term"
}
else
error("No linked-to term specified")
end
end
for _, termobj in ipairs(lemmas) do
if termobj.term then
add_term_tracking_categories(termobj.term)
end
-- NOTE: Formerly, template arg sc= overrode inline modifier <sc:...>, which seems backwards, so I've
-- changed it. Hopefully nothing depended on the old behavior.
end
end
local enclitics, enclitic_conj
if args.enclitic then
local enclitics_obj = parse_terms_with_inline_modifiers("enclitic", args.enclitic, get_param_mods("with conj"),
lang)
enclitics = enclitics_obj.terms
enclitic_conj = enclitics_obj.conj
end
local base_lemmas = {}
if base_lemma_params then
for _, base_lemma_param_obj in ipairs(base_lemma_params) do
local param = base_lemma_param_obj.param
if args[param] then
local base_lemmas_obj = parse_terms_with_inline_modifiers(param, args[param],
get_param_mods("with conj"), lang)
insert(base_lemmas, {
paramobj = base_lemma_param_obj,
lemmas = base_lemmas_obj.terms,
conj = base_lemmas_obj.conj,
})
end
end
end
local posttext = iargs.posttext
local addl = args.addl
if addl then
posttext = posttext or ""
if addl:find("^[;:]") then
posttext = posttext .. addl
elseif addl:find("^_") then
posttext = posttext .. " " .. addl:sub(2)
else
posttext = posttext .. ", " .. addl
end
end
local conj
if iargs.with_multiple_parts then
conj = false -- signals to use 'separator' field
else
conj = terms and terms.conj or iargs.conj
end
local lemma_data = {
lang = lang,
args = args,
lemmas = lemmas,
conj = conj,
enclitics = enclitics,
enclitic_conj = enclitic_conj,
base_lemmas = base_lemmas,
categories = categories,
posttext = posttext,
lit = iargs.with_multiple_parts and args.lit.default or nil,
}
local form_of_text, lang_cats = do_form_of(lemma_data)
extend(lemma_data.categories, lang_cats)
local text = form_of_text .. (
args.nodot and "" or args.dot or iargs.withdot and "." or ""
)
if not lemma_data.categories[1] then
return text
end
return text .. format_categories(lemma_data.categories, lemma_data.lang, args.sort,
-- If lemma_is_sort_key is given, supply the first lemma term as the sort base if possible. If sort= is given,
-- it will override the base; otherwise, the base will be converted appropriately to a sort key using the
-- same algorithm applied to pagenames.
iargs.lemma_is_sort_key and type(lemma_data.lemmas) == "table" and lemma_data.lemmas[1].term,
-- Supply the first lemma's script for sort key computation.
force_cat or get_force_cat(), type(lemma_data.lemmas) == "table" and lemma_data.lemmas[1].sc)
end
-- Invocation parameters shared between form_of_t(), tagged_form_of_t() and inflection_of_t(). `calling_func` is the
-- invoking function ("form_of_t", "tagged_form_of_t" or "inflection_of_t"), for handling parameters shared by two but
-- not all three invoking functions.
local function get_common_invocation_params(calling_func)
local iparams = {
["term_param"] = {type = "number"},
["lang"] = true, -- To be used as the default code in params.
["sc"] = {type = "script"},
["cat"] = {list = true, sublist = "comma without whitespace", flatten = true},
["ignore"] = {list = true},
["def"] = {list = true},
["conj"] = {set = allowed_conj_set, default = "and"},
["withcap"] = boolean_param,
["withencap"] = boolean_param,
["withdot"] = boolean_param,
["nolink"] = boolean_param,
["linktext"] = true,
["posttext"] = true,
["noprimaryentrycat"] = true,
["lemma_is_sort_key"] = true,
}
if calling_func ~= "inflection_of_t" then
iparams.with_multiple_parts = boolean_param
end
return iparams
end
local function should_ucfirst_text(args, iargs, lang)
local code = lang:getCode()
return args.cap or (iargs.withcap or iargs.withencap and code == "en" or code == "mul") and not args.nocap
end
--[==[
Function that implements {{tl|form of}} and the various more specific form-of templates (but not {{tl|inflection of}}
or templates that take tagged inflection parameters).
Invocation params:
; {{para|1|req=1}}
: Text to display before the link.
; {{para|term_param}}
: Numbered param holding the term linked to. Other numbered params come after. Defaults to 1 if invocation or template
param {{para|lang}} is present, otherwise 2.
; {{para|with_multiple_parts|1}}
: If specified, higher numbered parameters above the numbered param in {{para|term_param}} specify additional parts out
of which the term was constructed, for use by templates like {{tl|contraction of}}. (If not specified, the parameter
at <code><var>term_param</var> + 1</code> is the display form, same as {{para|alt}}, and the parameter at
at <code><var>term_param</var> + 2</code> is the gloss, same as {{para|t}}.)
; {{para|lang}}
: Default language code for language-specific templates. If specified, no language code needs to be specified, and if
specified it needs to be set using {{para|lang}}, not {{para|1}}.
; {{para|sc}}
: Default script code for language-specific templates. The script code can still be overridden using template param
{{para|sc}}.
; {{para|cat}}, {{para|cat2}}, ...:
: Categories to place the page into. The language name will automatically be prepended. Note that there is also a
template param {{para|cat}} to specify categories at the template level. Use of {{para|nocat}} disables categorization
of categories specified using invocation param {{para|cat}}, but not using template param {{para|cat}}. A single param
can specify multiple comma-separated categories if no space follows the comma.
; {{para|ignore}}, {{para|ignore2}}, ...:
: One or more template params to silently accept and ignore. Useful e.g. when the template takes additional parameters
such as {{para|from}} or {{para|POS}}. Each value is a comma-separated list of either bare parameter names or
specifications of the form `PARAM:list` to specify that the parameter is a list parameter.
; {{para|def}}, {{para|def2}}, ...:
: One or more default values to supply for template args. For example, specifying {{para|def|2=tr=-}} causes the default
for template param {{para|tr}} to be `-`. Actual template params override these defaults.
; {{para|withcap|1}}
: Capitalize the first character of the text preceding the link, unless template param {{para|nocap}} is given.
; {{para|withencap|1}}
: Capitalize the first character of the text preceding the link if the language is English and template param
{{para|nocap}} is not given.
; {{para|withdot|1}}
: Add a final period after the link, unless template param {{para|nodot}} is given to suppress the period, or
{{para|dot}} is given to specify an alternative punctuation character.
; {{para|nolink|1}}
: Suppress the display of the link. If specified, none of the template params that control the link
({{para|<var>term_param</var>}}, {{para|<var>term_param</var> + 1}}, {{para|<var>term_param</var> + 2}}, {{para|t}},
{{para|gloss}}, {{para|sc}}, {{para|tr}}, {{para|ts}}, {{para|pos}}, {{para|g}}, {{para|id}}, {{para|lit}}) will be
available. If the calling template uses any of these parameters, they must be ignored using {{para|ignore}}.
{{para|linktext}}
: Override the display of the link with the specified text. This is useful if a custom template is available to format
the link (e.g. in Hebrew, Chinese and Japanese). If specified, none of the template params that control the link
({{para|<var>term_param</var>}}, {{para|<var>term_param</var> + 1}}, {{para|<var>term_param</var> + 2}}, {{para|t}},
{{para|gloss}}, {{para|sc}}, {{para|tr}}, {{para|ts}}, {{para|pos}}, {{para|g}}, {{para|id}}, {{para|lit}}) will be
available. If the calling template uses any of these parameters, they must be ignored using {{para|ignore}}.
; {{para|posttext}}
: Additional text to display directly after the formatted link, before any terminating period/dot and inside of
`<span class='use-with-mention'>`.
; {{para|noprimaryentrycat}}
: Category to add the page to if the primary entry linked to doesn't exist. The language name will automatically be
prepended.
; {{para|lemma_is_sort_key|1}}
: If the user didn't specify a sort key, use the lemma as the sort key (instead of the page itself).
]==]
function export.form_of_t(frame)
local iparams = get_common_invocation_params("form_of_t")
iparams[1] = {required = true}
local iargs = process_params(frame.args, iparams)
local parent_args = frame:getParent().args
local params = get_common_template_params()
if next(iargs.cat) then
params.nocat = boolean_param
end
return construct_form_of_text {
template = "form-of-t",
iargs = iargs,
parent_args = parent_args,
params = params,
do_form_of = function(lemma_data)
local args = lemma_data.args
local text
if args.notext then
text = ""
else
text = iargs[1]
if should_ucfirst_text(args, iargs, lemma_data.lang) then
text = ucfirst(text)
end
end
-- This returns two values, which we pass up to the caller.
return format_form_of {
lang = lemma_data.lang, text = text, lemmas = lemma_data.lemmas, conj = lemma_data.conj,
enclitics = lemma_data.enclitics, base_lemmas = lemma_data.base_lemmas, lemma_face = "term",
lit = lemma_data.lit, posttext = lemma_data.posttext
}
end
}
end
--[=[
Construct and return the full definition line for a form-of-type template invocation that is based on inflection tags.
This is a wrapper around construct_form_of_text() and takes the following arguments: processed invocation arguments
IARGS, processed parent arguments ARGS, TERM_PARAM (the parent argument specifying the main entry), COMPAT (true if the
language code is found in args.lang instead of args[1]), and TAGS, the list of (non-canonicalized) inflection tags.
It returns that actual definition-line text including terminating period/full-stop, formatted categories, etc. and
should be directly returned as the template function's return value.
]=]
local function construct_tagged_form_of_text(data)
local template, iargs, parent_args, params, no_numbered_gloss, tags =
data.template, data.iargs, data.parent_args, data.params, data.no_numbered_gloss, data.tags
-- Named params not controlling link display
-- Always included because lang-specific categories may be added
params.nocat = boolean_param
params.p = true
params.POS = {alias_of = "p"}
return construct_form_of_text {
template = template,
iargs = iargs,
parent_args = parent_args,
params = params,
no_numbered_gloss = no_numbered_gloss,
do_form_of = function(lemma_data)
local args = lemma_data.args
if is_callable(tags) then
tags = tags(args)
end
-- NOTE: tagged_inflections returns two values, so we do too.
return tagged_inflections {
lang = lemma_data.lang,
tags = tags,
lemmas = lemma_data.lemmas,
conj = lemma_data.conj,
enclitics = lemma_data.enclitics,
enclitic_conj = lemma_data.enclitic_conj,
base_lemmas = lemma_data.base_lemmas,
lemma_face = "term",
POS = args.p,
pagename = args.pagename,
-- Set no_format_categories because we do it ourselves in construct_form_of_text().
no_format_categories = true,
nocat = args.nocat,
notext = args.notext,
capfirst = should_ucfirst_text(args, iargs, lemma_data.lang),
posttext = lemma_data.posttext,
}
end
}
end
--[==[
Function that implements form-of templates that are defined by specific tagged inflections (typically a template
referring to a non-lemma inflection, such as {{tl|plural of}}). This works exactly like {form_of_t()} except that the
"form of" text displayed before the link is based off of a pre-specified set of inflection tags (which will be
appropriately linked to the glossary) instead of arbitrary text. From the user's perspective, there is no difference
between templates implemented using {form_of_t()} and {tagged_form_of_t()}; they accept exactly the same parameters and
work the same. See also {inflection_of_t()} below, which is intended for templates with user-specified inflection tags.
Invocation params:
; {{para|1|req=1}}, {{para|2}}, ...
: One or more inflection tags describing the inflection in question.
; {{para|split_tags}}
: If specified, character to split specified inflection tags on. This allows multiple tags to be included in a single
argument, simplifying template code.
; {{para|term_param}}
; {{para|with_multiple_parts|1}}
; {{para|lang}}
; {{para|sc}}
; {{para|cat}}, {{para|cat2}}, ...
; {{para|ignore}}, {{para|ignore2}}, ...
; {{para|def}}, {{para|def2}}, ...
; {{para|withcap|1}}
; {{para|withencap|1}}
; {{para|withdot|1}}
; {{para|nolink|1}}
; {{para|linktext}}
; {{para|posttext}}
; {{para|noprimaryentrycat}}
; {{para|lemma_is_sort_key|1}}
: All of these are the same as in {form_of_t()}.
]==]
function export.tagged_form_of_t(frame)
local iparams = get_common_invocation_params("tagged_form_of_t")
iparams[1] = {list = true, required = true}
iparams.split_tags = true
local iargs = process_params(frame.args, iparams)
local parent_args = frame:getParent().args
local params = get_common_template_params()
return construct_tagged_form_of_text {
template = "tagged-form-of-t",
iargs = iargs,
parent_args = parent_args,
params = params,
tags = split_inflection_tags(iargs[1], iargs.split_tags),
}
end
--[==[
Function that implements {{tl|inflection of}} and certain semi-specific variants, such as {{tl|participle of}} and
{{tl|past participle form of}}. This function is intended for templates that allow the user to specify a set of
inflection tags.
It works similarly to {form_of_t()} and {tagged_form_of_t()} except that the calling convention for the calling
template is
: { {{TEMPLATE|LANG|MAIN_ENTRY_LINK|MAIN_ENTRY_DISPLAY_TEXT|TAG|TAG|...}}}
instead of
: { {{TEMPLATE|LANG|MAIN_ENTRY_LINK|MAIN_ENTRY_DISPLAY_TEXT|GLOSS}}}
Note that there isn't a numbered parameter for the gloss, but it can still be specified using {{para|t}} or
{{para|gloss}}.
Invocation params:
; {{para|preinfl}}, {{para|preinfl2}}, ...
: Extra inflection tags to automatically prepend to the tags specified by the template.
; {{para|postinfl}}, {{para|postinfl2}}, ...
: Extra inflection tags to automatically append to the tags specified by the template. Used for example by
{{tl|past participle form of}} to add the tags `of the|past|p` onto the user-specified tags, which indicate which
past participle form the page refers to.
; {{para|split_tags}}
: If specified, character to split specified inflection tags on. This allows multiple tags to be included in a single
argument, simplifying template code. Note that this applies *ONLY* to inflection tags specified in the invocation
arguments using {{para|preinfl}} or {{para|postinfl}}, not to user-specified inflection tags.
; {{para|term_param}}
; {{para|lang}}
; {{para|sc}}
; {{para|cat}}, {{para|cat2}}, ...
; {{para|ignore}}, {{para|ignore2}}, ...
; {{para|def}}, {{para|def2}}, ...
; {{para|withcap|1}}
; {{para|withencap|1}}
; {{para|withdot|1}}
; {{para|nolink|1}}
; {{para|linktext}}
; {{para|posttext}}
; {{para|noprimaryentrycat}}
; {{para|lemma_is_sort_key|1}}
: All of these are the same as in {form_of_t()}.
]==]
function export.inflection_of_t(frame)
local iparams = get_common_invocation_params("inflection_of_t")
iparams.preinfl = {list = true}
iparams.postinfl = {list = true}
iparams.split_tags = true
local iargs = process_params(frame.args, iparams)
local parent_args = frame:getParent().args
local params = get_common_template_params()
local compat = iargs.lang or parent_args.lang
local tagsind = (iargs.term_param or compat and 1 or 2) + 2
params[tagsind] = {list = true,
-- at least one inflection tag is required unless preinfl or postinfl tags are given
required = #iargs.preinfl == 0 and #iargs.postinfl == 0}
return construct_tagged_form_of_text {
template = "inflection-of-t",
iargs = iargs,
parent_args = parent_args,
params = params,
no_numbered_gloss = true,
tags = function(args)
local infls
if not next(iargs.preinfl) and not next(iargs.postinfl) then
-- If no preinfl or postinfl tags, just use the user-specified tags directly.
infls = args[tagsind]
else
-- Otherwise, we need to prepend the preinfl tags and postpend the postinfl tags. If there's only one tag set
-- (no semicolon), it's easier. Since this is common, we optimize for it.
infls = {}
local saw_semicolon = false
for _, infl in ipairs(args[tagsind]) do
if infl == ";" then
saw_semicolon = true
break
end
end
local split_preinfl = split_inflection_tags(iargs.preinfl, iargs.split_tags)
local split_postinfl = split_inflection_tags(iargs.postinfl, iargs.split_tags)
if not saw_semicolon then
extend(infls, split_preinfl)
extend(infls, args[tagsind])
extend(infls, split_postinfl)
else
local groups = split_tag_set(args[tagsind])
for _, group in ipairs(groups) do
if #infls > 0 then
insert(infls, ";")
end
extend(infls, split_preinfl)
extend(infls, group)
extend(infls, split_postinfl)
end
end
end
return infls
end,
}
end
--[==[
Normalize a part-of-speech tag given a possible abbreviation (passed in as {{para|1}} of the invocation args). If the
abbreviation isn't recognized, the original POS tag is returned. If no POS tag is passed in, return the value of
invocation arg {{para|default}}.
]==]
function export.normalize_pos(frame)
local iparams = {
[1] = true,
["default"] = true,
}
local iargs = process_params(frame.args, iparams)
if not iargs[1] and not iargs.default then
error("Either 1= or default= must be given in the invocation args")
end
if not iargs[1] then
return iargs.default
end
return (m_form_of_pos or get_m_form_of_pos())[iargs[1]] or iargs[1]
end
return export
qngi7g0ngefkunhqwao6b90egp7n7t7
25208
25206
2026-08-19T04:58:29Z
Deepturquoise
2456
25208
Scribunto
text/plain
local export = {}
local debug_track_module = "Module:debug/track"
local form_of_module = "Module:form of"
local functions_module = "Module:fun"
local headword_data_module = "Module:headword/data"
local languages_module = "Module:languages"
local load_module = "Module:load"
local parameters_module = "Module:parameters"
local parameter_utilities_module = "Module:parameter utilities"
local parse_interface_module = "Module:parse interface"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local insert = table.insert
local ipairs = ipairs
local pairs = pairs
local require = require
local boolean_param = {type = "boolean"}
-- FIXME: Finish [[Module:format utilities]].
-- local allowed_conj_set = require(format_utilities_module).allowed_conj_set_for_join_segments
local allowed_conj_set = {["and"] = true, ["or"] = true, ["and/or"] = true}
--[==[
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 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 extend(...)
extend = require(table_module).extend
return extend(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_form_of(...)
format_form_of = require(form_of_module).format_form_of
return format_form_of(...)
end
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
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 load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function parse_inline_modifiers(...)
parse_inline_modifiers = require(parse_interface_module).parse_inline_modifiers
return parse_inline_modifiers(...)
end
local function pattern_escape(...)
pattern_escape = require(string_utilities_module).pattern_escape
return pattern_escape(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function safe_load_data(...)
safe_load_data = require(load_module).safe_load_data
return safe_load_data(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function split_tag_set(...)
split_tag_set = require(form_of_module).split_tag_set
return split_tag_set(...)
end
local function tagged_inflections(...)
tagged_inflections = require(form_of_module).tagged_inflections
return tagged_inflections(...)
end
local function trim(...)
trim = require(string_utilities_module).trim
return trim(...)
end
local function ucfirst(...)
ucfirst = require(string_utilities_module).ucfirst
return ucfirst(...)
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 force_cat
local function get_force_cat()
force_cat, get_force_cat = require(form_of_module).force_cat, nil
return force_cat
end
local m_form_of_pos
local function get_m_form_of_pos()
m_form_of_pos, get_m_form_of_pos = load_data(headword_data_module).pos_aliases, nil
return m_form_of_pos
end
local module_prefix
local function get_module_prefix()
module_prefix, get_module_prefix = require(form_of_module).form_of_lang_data_module_prefix, nil
return module_prefix
end
--[==[ intro:
This module contains code that directly implements {{tl|form of}}, {{tl|inflection of}}, and the various other
[[:Category:Form-of templates|form-of templates]]. It is meant to be called directly from templates. See also
[[Module:form of]], which contains the underlying implementing code and is meant to be called from other modules.
]==]
-- Add tracking category for PAGE when called from TEMPLATE. The tracking category linked to is
-- [[Wiktionary:Tracking/form of/TEMPLATE/PAGE]]. If TEMPLATE is omitted, the tracking category is of the form
-- [[Wiktionary:Tracking/form of/PAGE]].
local function track(page, template)
debug_track("form of/" .. (template and template .. "/" or "") .. page)
end
local function get_common_template_params()
return {
-- Named params not controlling link display
["cat"] = {list = true, sublist = "comma without whitespace", flatten = true},
["notext"] = boolean_param,
["sort"] = true,
["enclitic"] = true,
-- FIXME! The following should only be available when withcap=1 in invocation args or when withencap=1 and the
-- language is "en". Before doing that, need to remove all uses of nocap= in other circumstances.
["nocap"] = boolean_param,
["addl"] = true, -- additional text to display at the end, before the closing </span>
["pagename"] = true, -- for testing, etc.
}
end
-- Split TAGSPECS (inflection tag specifications) on SPLIT_REGEX, which
-- may be nil for no splitting.
local function split_inflection_tags(tagspecs, split_regex)
if not split_regex then
return tagspecs
end
local inflection_tags = {}
for _, tagspec in ipairs(tagspecs) do
for tag in gsplit(tagspec, split_regex) do
insert(inflection_tags, tag)
end
end
return inflection_tags
end
local function parse_terms_with_inline_modifiers(paramname, val, param_mods, lang)
local function generate_obj(term)
return {lang = lang, term = decode_entities(term)}
end
return parse_inline_modifiers(val, {
paramname = paramname,
param_mods = param_mods,
generate_obj = generate_obj,
splitchar = ",",
outer_container = {},
})
end
-- Need to do what [[Module:parameters]] does to string arguments from parent_args as we're running this
-- before calling [[Module:parameters]] on parent_args.
local function ine(arg)
if not arg then
return nil
end
arg = trim(arg)
return arg ~= "" and arg or nil
end
local function add_base_lemma_params(parent_args, iargs, params, compat)
-- Check the language-specific data for additional base lemma params. But if there's no language-specific data,
-- attempt any parent varieties as well (i.e. superordinate varieties).
local lang = get_lang(ine(parent_args[compat and "lang" or 1]) or ine(iargs.lang) or "und", nil, true)
while lang do
local langdata = safe_load_data((module_prefix or get_module_prefix()) .. lang:getCode())
if langdata then
local base_lemma_params = langdata.base_lemma_params
if base_lemma_params then
for _, param in ipairs(base_lemma_params) do
params[param.param] = true
end
return base_lemma_params
end
end
lang = lang:getParent()
end
end
--[=[
Modify `params` in-place by adding parameters that control the link to the main entry and any base lemmas. `term_param`
is the number of the param specifying the main entry itself; `term_param` + 1 will be the display text, and `term_param`
+ 2 will be the gloss, unless `no_numbered_gloss` is given. The base lemma parameters are determined by attempting to
load language-specific data for the language of the page; this comes from |lang= if `compat` is given, else from |1=.
]=]
local function add_link_and_base_lemma_params(iargs, parent_args, params, term_param, compat, no_numbered_gloss)
local base_lemma_params
if not iargs.nolink and not iargs.linktext then
-- Numbered params controlling link display
if iargs.with_multiple_parts then
params[term_param] = {list = true, allow_holes = true}
else
params[term_param + 1] = {alias_of = "alt"}
if not no_numbered_gloss then
params[term_param + 2] = {alias_of = "t"}
end
params[term_param] = true
end
base_lemma_params = add_base_lemma_params(parent_args, iargs, params, compat)
end
return base_lemma_params
end
local function handle_withdot_withcap(iargs, params)
local ignored_tracked_params = {}
if iargs.withdot then
params.dot = true
params.nodot = boolean_param
end
if iargs.withcap and iargs.withencap then
error("Internal error: Can specify only one of withcap= and withencap=")
end
if not iargs.withcap then
params.cap = boolean_param
ignored_tracked_params.nocap = iargs.withencap and "non-english" or "always"
end
return ignored_tracked_params
end
--[=[
Construct and return the full definition line for a form-of-type template invocation. `data` is an object with the
following fields:
* `template`: Approximate template name, for debug tracking;
* `iargs`: processed invocation arguments;
* `parent_args`: raw parent args from `frame:getParent().args`;
* `params`: partially constructed params structure of the sort passed to `process()` in [[Module:parameters]], but
without any link params;
* `ignored_tracked_params`: params that are ignored but should be tracked, to be eventually removed;
* `term_param`: the parent argument specifying the main entry;
* `compat`: true if the language code is found in args.lang instead of args[1];
* `base_lemma_params`: if non-nil, a list of base lemma param objects of the sort stored in the language-specific data;
* `do_form_of`: a function of one argument, `lemma_data`, that returns the actual definition-line text and any
language-specific categories. See below.
This function does several things:
# If link parameters are called for (neither `iargs.nolink` nor `iargs.linktext` are given), augment the `params`
structure with separate link parameters.
# Modify the parent args as appropriate if invocation arguments def= or ignore= are given.
# Parse the parent args, both for separate parameter properties and inline modifiers on the term parameter (which may
consist of multiple comma-separated terms).
# Compute categories to add to the page, including language-specific categories and any categories requested by the
invocation or parent args.
# Parse enclitic and extra base lemma parameters.
# Construct the actual text using `do_form_of`.
# Add a terminating period/dot as appropriate, along with the formatted categories.
`do_form_of` takes one argument, `lemma_data`, which looks like this:
{
lang = LANG,
args = {ARG = VALUE, ARG = VALUE, ...},
lemmas = {LEMMA_OBJ, LEMMA_OBJ, ...},
enclitics = {ENCLITIC_OBJ, ENCLITIC_OBJ, ...},
base_lemmas = {BASE_LEMMA_OBJ, BASE_LEMMA_OBJ, ...},
categories = {"CATEGORY", "CATEGORY", ...},
posttext = "POSTTEXT" or nil,
}
where
* LANG is the language code;
* ARGS is the parsed arguments, based on what the user specified;
* LEMMAS is a sequence of objects specifying the main entries/lemmas, as passed to full_link in [[Module:links]];
however, if the invocation argument linktext= is given, it will be a string consisting of that text, and if the
invocation argument nolink= is given, it will be nil;
* ENCLITICS is nil or a sequence of objects specifying the enclitics, as passed to full_link in [[Module:links]];
* BASE_LEMMA_OBJ is a sequence of objects specifying the base lemma(s), which are used when the lemma is itself a
form of another lemma (the base lemma), e.g. a comparative, superlative or participle; each object is of the form
{ paramobj = PARAM_OBJ, lemmas = {LEMMA_OBJ, LEMMA_OBJ, ...} } where PARAM_OBJ describes the properties of the
base lemma parameter (i.e. the relationship between the intermediate and base lemmas) and LEMMA_OBJ is of the same
format of ENCLITIC_OBJ, i.e. an object suitable to be passed to full_link in [[Module:links]]; PARAM_OBJ is of the
format { param = "PARAM", tags = {"TAG", "TAG", ...} } where PARAM is the name of the parameter to
{{inflection of}} etc. that holds the base lemma(s) of the specified relationship and the tags describe the
relationship, such as {"comd"} or {"past", "part"};
* CATEGORIES is the categories to add the page to (consisting of any categories specified in the invocation or
parent args and any tracking categories, but not any additional lang-specific categories that may be added by
{{inflection of}} or similar templates);
* POSTTEXT is text to display at the end of the form-of text, before the final </span> (or at the end of the first
line, before the colon, in a multiline {{infl of}} call).
`do_form_of` should return two arguments:
(1) The actual definition-line text, marked up appropriately with <span>...</span> but without any terminating
period/dot.
(2) Any extra categories to add the page to (other than those that can be derived from parameters specified to the
invocation or parent arguments, which will automatically be added to the page).
]=]
local function construct_form_of_text(data)
local template, iargs, parent_args, params, no_numbered_gloss, do_form_of =
data.template, data.iargs, data.parent_args, data.params, data.no_numbered_gloss, data.do_form_of
local term_param = iargs.term_param
local compat = iargs.lang or parent_args.lang
term_param = term_param or compat and 1 or 2
-- Numbered params
params[compat and "lang" or 1] = {
required = not iargs.lang,
type = "language",
default = iargs.lang or "und"
}
-- Error to catch most uses of old-style parameters for {{contraction of}}. (FIXME: Remove eventually.)
if iargs.with_multiple_parts then
if ine(parent_args[term_param + 2]) and not ine(parent_args[term_param + 1]) and not ine(parent_args.tr2) and not ine(parent_args.ts2)
and not ine(parent_args.t2) and not ine(parent_args.gloss2) and not ine(parent_args.g2)
and not ine(parent_args.alt2) then
error(("You specified a term in %s= and not one in %s=. You probably meant to use t= to specify a gloss instead. "
.. "If you intended to specify two terms, put the second term in %s=."):format(term_param + 2, term_param + 1,
term_param + 1))
end
if not ine(parent_args[term_param + 1]) and not ine(parent_args.alt2) and not ine(parent_args.tr2) and not ine(parent_args.ts2)
and ine(parent_args.g2) then
error(("You specified a gender in g2= but no term in %s=. You were probably trying to specify two genders for "
.. "a single term. To do that, put both genders in g=, comma-separated."):format(term_param + 1))
end
end
local base_lemma_params = add_link_and_base_lemma_params(iargs, parent_args, params, term_param, compat,
no_numbered_gloss)
local ignored_tracked_params = handle_withdot_withcap(iargs, params)
--[=[
Process parent arguments. This is similar to the following:
require("Module:parameters").process(parent_args, params)
but in addition it does the following:
(1) Supplies default values for unspecified parent arguments as specified in DEFAULTS, which consist of specs of the
form "ARG=VALUE". These are added to the parent arguments prior to processing, so boolean and number parameters
will process the value appropriately.
(2) Removes parent arguments specified in IGNORESPECS, which consist either of bare argument names to remove, or
list-argument names to remove of the form "ARG:list".
(3) Tracks the use of any parent arguments specified in TRACKED_PARAMS, which is a set where the keys are arguments
as they exist after processing (hence numeric arguments should be numbers, not strings) and the values should be
boolean true.
]=]--
local defaults = iargs.def
local ignorespecs = iargs.ignore
if defaults[1] or ignorespecs[1] then
local new_parent_args = {}
for _, default in ipairs(defaults) do
local defparam, defval = default:match("^(.-)=(.*)$")
if not defparam then
error("Bad default spec " .. default)
end
new_parent_args[defparam] = defval
end
local params_to_ignore = {}
local numbered_list_params_to_ignore = {}
local named_list_params_to_ignore = {}
for _, ignorespec in ipairs(ignorespecs) do
for ignore in gsplit(ignorespec, ",") do
local param = ignore:match("^(.*):list$")
if param then
if param:match("^%d+$") then
insert(numbered_list_params_to_ignore, tonumber(param))
else
insert(named_list_params_to_ignore, "^" .. pattern_escape(param) .. "%d*$")
end
else
if ignore:match("^%d+$") then
ignore = tonumber(ignore)
end
params_to_ignore[ignore] = true
end
end
end
for k, v in pairs(parent_args) do
if not params_to_ignore[k] then
local ignore_me = false
if type(k) == "number" then
for _, lparam in ipairs(numbered_list_params_to_ignore) do
if k >= lparam then
ignore_me = true
break
end
end
else
for _, lparam in ipairs(named_list_params_to_ignore) do
if k:match(lparam) then
ignore_me = true
break
end
end
end
if not ignore_me then
new_parent_args[k] = v
end
end
end
parent_args = new_parent_args
end
local param_mods_with_conj, param_mods_without_conj
local function get_param_mods(with_conj)
if with_conj then
if not param_mods_with_conj then
param_mods_with_conj = require(parameter_utilities_module).construct_param_mods {
{group = {"link", "q", "l", "ref"}},
{param = "conj", set = allowed_conj_set, overall = true},
}
end
return param_mods_with_conj
else
if not param_mods_without_conj then
param_mods_without_conj = require(parameter_utilities_module).construct_param_mods {
{group = {"link", "q", "l", "ref"}},
-- Override lit= to have a separate overall value
{param = "lit", separate_no_index = true},
}
end
return param_mods_without_conj
end
end
local terms, args
if iargs.nolink or iargs.linktext then
args = process_params(parent_args, params)
else
local m_param_utils = require(parameter_utilities_module)
if iargs.with_multiple_parts then
terms, args = m_param_utils.parse_list_with_inline_modifiers_and_separate_params {
params = params,
param_mods = get_param_mods(false),
raw_args = parent_args,
termarg = term_param,
track_module = "form of" .. (template and "/" .. template or ""),
lang = compat and "lang" or 1,
sc = "sc.default",
parse_lang_prefix = true,
default_separator = " +‎ ",
special_separators = {[";"] = " or "},
}
else
terms, args = m_param_utils.parse_term_with_inline_modifiers_and_separate_params {
params = params,
param_mods = get_param_mods("with conj"),
raw_args = parent_args,
termarg = term_param,
track_module = "form of" .. (template and "/" .. template or ""),
lang = compat and "lang" or 1,
sc = "sc",
parse_lang_prefix = true,
make_separate_g_into_list = true,
splitchar = ",",
subitem_param_handling = "last",
}
end
end
local lang = args[compat and "lang" or 1]
-- Tracking for certain user-specified params. This is generally used for
-- parameters that we accept but ignore, so that we can eventually remove
-- all uses of these params and stop accepting them.
if ignored_tracked_params then
for ignored_tracked_param, condition in pairs(ignored_tracked_params) do
if parent_args[ignored_tracked_param] and (condition ~= "non-english" or lang:getCode() ~= "en") then
track("arg/" .. ignored_tracked_param, template)
track("arg/" .. ignored_tracked_param)
end
end
end
-- Determine categories for the page, including tracking categories
local categories = {}
if not args.nocat then
for _, cat in ipairs(iargs.cat) do
insert(categories, lang:getFullName() .. " " .. cat)
end
end
for _, cat in ipairs(args.cat) do
insert(categories, lang:getFullName() .. " " .. cat)
end
-- Format the link, preceding text and categories
local function add_term_tracking_categories(term)
-- add tracking category if term is same as page title
if term and mw.loadData("Module:headword/data").pagename == lang:stripDiacritics(term) then
insert(categories, "Forms linking to themselves")
end
-- maybe add tracking category if primary entry doesn't exist (this is an
-- expensive call so we don't do it by default)
if iargs.noprimaryentrycat and term and mw.title.getCurrentTitle().nsText == ""
and not mw.title.new(term):getContent() then
insert(categories, lang:getFullName() .. " " .. iargs.noprimaryentrycat)
end
end
local lemmas
if iargs.nolink then
lemmas = nil
elseif iargs.linktext then
lemmas = iargs.linktext
else
if iargs.with_multiple_parts then
lemmas = terms
else
lemmas = terms.terms
end
if not lemmas[1] then
if mw.title.getCurrentTitle().nsText == "Citakan" then
lemmas[1] = {
lang = lang,
term = "term"
}
else
error("No linked-to term specified")
end
end
for _, termobj in ipairs(lemmas) do
if termobj.term then
add_term_tracking_categories(termobj.term)
end
-- NOTE: Formerly, template arg sc= overrode inline modifier <sc:...>, which seems backwards, so I've
-- changed it. Hopefully nothing depended on the old behavior.
end
end
local enclitics, enclitic_conj
if args.enclitic then
local enclitics_obj = parse_terms_with_inline_modifiers("enclitic", args.enclitic, get_param_mods("with conj"),
lang)
enclitics = enclitics_obj.terms
enclitic_conj = enclitics_obj.conj
end
local base_lemmas = {}
if base_lemma_params then
for _, base_lemma_param_obj in ipairs(base_lemma_params) do
local param = base_lemma_param_obj.param
if args[param] then
local base_lemmas_obj = parse_terms_with_inline_modifiers(param, args[param],
get_param_mods("with conj"), lang)
insert(base_lemmas, {
paramobj = base_lemma_param_obj,
lemmas = base_lemmas_obj.terms,
conj = base_lemmas_obj.conj,
})
end
end
end
local posttext = iargs.posttext
local addl = args.addl
if addl then
posttext = posttext or ""
if addl:find("^[;:]") then
posttext = posttext .. addl
elseif addl:find("^_") then
posttext = posttext .. " " .. addl:sub(2)
else
posttext = posttext .. ", " .. addl
end
end
local conj
if iargs.with_multiple_parts then
conj = false -- signals to use 'separator' field
else
conj = terms and terms.conj or iargs.conj
end
local lemma_data = {
lang = lang,
args = args,
lemmas = lemmas,
conj = conj,
enclitics = enclitics,
enclitic_conj = enclitic_conj,
base_lemmas = base_lemmas,
categories = categories,
posttext = posttext,
lit = iargs.with_multiple_parts and args.lit.default or nil,
}
local form_of_text, lang_cats = do_form_of(lemma_data)
extend(lemma_data.categories, lang_cats)
local text = form_of_text .. (
args.nodot and "" or args.dot or iargs.withdot and "." or ""
)
if not lemma_data.categories[1] then
return text
end
return text .. format_categories(lemma_data.categories, lemma_data.lang, args.sort,
-- If lemma_is_sort_key is given, supply the first lemma term as the sort base if possible. If sort= is given,
-- it will override the base; otherwise, the base will be converted appropriately to a sort key using the
-- same algorithm applied to pagenames.
iargs.lemma_is_sort_key and type(lemma_data.lemmas) == "table" and lemma_data.lemmas[1].term,
-- Supply the first lemma's script for sort key computation.
force_cat or get_force_cat(), type(lemma_data.lemmas) == "table" and lemma_data.lemmas[1].sc)
end
-- Invocation parameters shared between form_of_t(), tagged_form_of_t() and inflection_of_t(). `calling_func` is the
-- invoking function ("form_of_t", "tagged_form_of_t" or "inflection_of_t"), for handling parameters shared by two but
-- not all three invoking functions.
local function get_common_invocation_params(calling_func)
local iparams = {
["term_param"] = {type = "number"},
["lang"] = true, -- To be used as the default code in params.
["sc"] = {type = "script"},
["cat"] = {list = true, sublist = "comma without whitespace", flatten = true},
["ignore"] = {list = true},
["def"] = {list = true},
["conj"] = {set = allowed_conj_set, default = "and"},
["withcap"] = boolean_param,
["withencap"] = boolean_param,
["withdot"] = boolean_param,
["nolink"] = boolean_param,
["linktext"] = true,
["posttext"] = true,
["noprimaryentrycat"] = true,
["lemma_is_sort_key"] = true,
}
if calling_func ~= "inflection_of_t" then
iparams.with_multiple_parts = boolean_param
end
return iparams
end
local function should_ucfirst_text(args, iargs, lang)
local code = lang:getCode()
return args.cap or (iargs.withcap or iargs.withencap and code == "en" or code == "mul") and not args.nocap
end
--[==[
Function that implements {{tl|form of}} and the various more specific form-of templates (but not {{tl|inflection of}}
or templates that take tagged inflection parameters).
Invocation params:
; {{para|1|req=1}}
: Text to display before the link.
; {{para|term_param}}
: Numbered param holding the term linked to. Other numbered params come after. Defaults to 1 if invocation or template
param {{para|lang}} is present, otherwise 2.
; {{para|with_multiple_parts|1}}
: If specified, higher numbered parameters above the numbered param in {{para|term_param}} specify additional parts out
of which the term was constructed, for use by templates like {{tl|contraction of}}. (If not specified, the parameter
at <code><var>term_param</var> + 1</code> is the display form, same as {{para|alt}}, and the parameter at
at <code><var>term_param</var> + 2</code> is the gloss, same as {{para|t}}.)
; {{para|lang}}
: Default language code for language-specific templates. If specified, no language code needs to be specified, and if
specified it needs to be set using {{para|lang}}, not {{para|1}}.
; {{para|sc}}
: Default script code for language-specific templates. The script code can still be overridden using template param
{{para|sc}}.
; {{para|cat}}, {{para|cat2}}, ...:
: Categories to place the page into. The language name will automatically be prepended. Note that there is also a
template param {{para|cat}} to specify categories at the template level. Use of {{para|nocat}} disables categorization
of categories specified using invocation param {{para|cat}}, but not using template param {{para|cat}}. A single param
can specify multiple comma-separated categories if no space follows the comma.
; {{para|ignore}}, {{para|ignore2}}, ...:
: One or more template params to silently accept and ignore. Useful e.g. when the template takes additional parameters
such as {{para|from}} or {{para|POS}}. Each value is a comma-separated list of either bare parameter names or
specifications of the form `PARAM:list` to specify that the parameter is a list parameter.
; {{para|def}}, {{para|def2}}, ...:
: One or more default values to supply for template args. For example, specifying {{para|def|2=tr=-}} causes the default
for template param {{para|tr}} to be `-`. Actual template params override these defaults.
; {{para|withcap|1}}
: Capitalize the first character of the text preceding the link, unless template param {{para|nocap}} is given.
; {{para|withencap|1}}
: Capitalize the first character of the text preceding the link if the language is English and template param
{{para|nocap}} is not given.
; {{para|withdot|1}}
: Add a final period after the link, unless template param {{para|nodot}} is given to suppress the period, or
{{para|dot}} is given to specify an alternative punctuation character.
; {{para|nolink|1}}
: Suppress the display of the link. If specified, none of the template params that control the link
({{para|<var>term_param</var>}}, {{para|<var>term_param</var> + 1}}, {{para|<var>term_param</var> + 2}}, {{para|t}},
{{para|gloss}}, {{para|sc}}, {{para|tr}}, {{para|ts}}, {{para|pos}}, {{para|g}}, {{para|id}}, {{para|lit}}) will be
available. If the calling template uses any of these parameters, they must be ignored using {{para|ignore}}.
{{para|linktext}}
: Override the display of the link with the specified text. This is useful if a custom template is available to format
the link (e.g. in Hebrew, Chinese and Japanese). If specified, none of the template params that control the link
({{para|<var>term_param</var>}}, {{para|<var>term_param</var> + 1}}, {{para|<var>term_param</var> + 2}}, {{para|t}},
{{para|gloss}}, {{para|sc}}, {{para|tr}}, {{para|ts}}, {{para|pos}}, {{para|g}}, {{para|id}}, {{para|lit}}) will be
available. If the calling template uses any of these parameters, they must be ignored using {{para|ignore}}.
; {{para|posttext}}
: Additional text to display directly after the formatted link, before any terminating period/dot and inside of
`<span class='use-with-mention'>`.
; {{para|noprimaryentrycat}}
: Category to add the page to if the primary entry linked to doesn't exist. The language name will automatically be
prepended.
; {{para|lemma_is_sort_key|1}}
: If the user didn't specify a sort key, use the lemma as the sort key (instead of the page itself).
]==]
function export.form_of_t(frame)
local iparams = get_common_invocation_params("form_of_t")
iparams[1] = {required = true}
local iargs = process_params(frame.args, iparams)
local parent_args = frame:getParent().args
local params = get_common_template_params()
if next(iargs.cat) then
params.nocat = boolean_param
end
return construct_form_of_text {
template = "form-of-t",
iargs = iargs,
parent_args = parent_args,
params = params,
do_form_of = function(lemma_data)
local args = lemma_data.args
local text
if args.notext then
text = ""
else
text = iargs[1]
if should_ucfirst_text(args, iargs, lemma_data.lang) then
text = ucfirst(text)
end
end
-- This returns two values, which we pass up to the caller.
return format_form_of {
lang = lemma_data.lang, text = text, lemmas = lemma_data.lemmas, conj = lemma_data.conj,
enclitics = lemma_data.enclitics, base_lemmas = lemma_data.base_lemmas, lemma_face = "term",
lit = lemma_data.lit, posttext = lemma_data.posttext
}
end
}
end
--[=[
Construct and return the full definition line for a form-of-type template invocation that is based on inflection tags.
This is a wrapper around construct_form_of_text() and takes the following arguments: processed invocation arguments
IARGS, processed parent arguments ARGS, TERM_PARAM (the parent argument specifying the main entry), COMPAT (true if the
language code is found in args.lang instead of args[1]), and TAGS, the list of (non-canonicalized) inflection tags.
It returns that actual definition-line text including terminating period/full-stop, formatted categories, etc. and
should be directly returned as the template function's return value.
]=]
local function construct_tagged_form_of_text(data)
local template, iargs, parent_args, params, no_numbered_gloss, tags =
data.template, data.iargs, data.parent_args, data.params, data.no_numbered_gloss, data.tags
-- Named params not controlling link display
-- Always included because lang-specific categories may be added
params.nocat = boolean_param
params.p = true
params.POS = {alias_of = "p"}
return construct_form_of_text {
template = template,
iargs = iargs,
parent_args = parent_args,
params = params,
no_numbered_gloss = no_numbered_gloss,
do_form_of = function(lemma_data)
local args = lemma_data.args
if is_callable(tags) then
tags = tags(args)
end
-- NOTE: tagged_inflections returns two values, so we do too.
return tagged_inflections {
lang = lemma_data.lang,
tags = tags,
lemmas = lemma_data.lemmas,
conj = lemma_data.conj,
enclitics = lemma_data.enclitics,
enclitic_conj = lemma_data.enclitic_conj,
base_lemmas = lemma_data.base_lemmas,
lemma_face = "term",
POS = args.p,
pagename = args.pagename,
-- Set no_format_categories because we do it ourselves in construct_form_of_text().
no_format_categories = true,
nocat = args.nocat,
notext = args.notext,
capfirst = should_ucfirst_text(args, iargs, lemma_data.lang),
posttext = lemma_data.posttext,
}
end
}
end
--[==[
Function that implements form-of templates that are defined by specific tagged inflections (typically a template
referring to a non-lemma inflection, such as {{tl|plural of}}). This works exactly like {form_of_t()} except that the
"form of" text displayed before the link is based off of a pre-specified set of inflection tags (which will be
appropriately linked to the glossary) instead of arbitrary text. From the user's perspective, there is no difference
between templates implemented using {form_of_t()} and {tagged_form_of_t()}; they accept exactly the same parameters and
work the same. See also {inflection_of_t()} below, which is intended for templates with user-specified inflection tags.
Invocation params:
; {{para|1|req=1}}, {{para|2}}, ...
: One or more inflection tags describing the inflection in question.
; {{para|split_tags}}
: If specified, character to split specified inflection tags on. This allows multiple tags to be included in a single
argument, simplifying template code.
; {{para|term_param}}
; {{para|with_multiple_parts|1}}
; {{para|lang}}
; {{para|sc}}
; {{para|cat}}, {{para|cat2}}, ...
; {{para|ignore}}, {{para|ignore2}}, ...
; {{para|def}}, {{para|def2}}, ...
; {{para|withcap|1}}
; {{para|withencap|1}}
; {{para|withdot|1}}
; {{para|nolink|1}}
; {{para|linktext}}
; {{para|posttext}}
; {{para|noprimaryentrycat}}
; {{para|lemma_is_sort_key|1}}
: All of these are the same as in {form_of_t()}.
]==]
function export.tagged_form_of_t(frame)
local iparams = get_common_invocation_params("tagged_form_of_t")
iparams[1] = {list = true, required = true}
iparams.split_tags = true
local iargs = process_params(frame.args, iparams)
local parent_args = frame:getParent().args
local params = get_common_template_params()
return construct_tagged_form_of_text {
template = "tagged-form-of-t",
iargs = iargs,
parent_args = parent_args,
params = params,
tags = split_inflection_tags(iargs[1], iargs.split_tags),
}
end
--[==[
Function that implements {{tl|inflection of}} and certain semi-specific variants, such as {{tl|participle of}} and
{{tl|past participle form of}}. This function is intended for templates that allow the user to specify a set of
inflection tags.
It works similarly to {form_of_t()} and {tagged_form_of_t()} except that the calling convention for the calling
template is
: { {{TEMPLATE|LANG|MAIN_ENTRY_LINK|MAIN_ENTRY_DISPLAY_TEXT|TAG|TAG|...}}}
instead of
: { {{TEMPLATE|LANG|MAIN_ENTRY_LINK|MAIN_ENTRY_DISPLAY_TEXT|GLOSS}}}
Note that there isn't a numbered parameter for the gloss, but it can still be specified using {{para|t}} or
{{para|gloss}}.
Invocation params:
; {{para|preinfl}}, {{para|preinfl2}}, ...
: Extra inflection tags to automatically prepend to the tags specified by the template.
; {{para|postinfl}}, {{para|postinfl2}}, ...
: Extra inflection tags to automatically append to the tags specified by the template. Used for example by
{{tl|past participle form of}} to add the tags `of the|past|p` onto the user-specified tags, which indicate which
past participle form the page refers to.
; {{para|split_tags}}
: If specified, character to split specified inflection tags on. This allows multiple tags to be included in a single
argument, simplifying template code. Note that this applies *ONLY* to inflection tags specified in the invocation
arguments using {{para|preinfl}} or {{para|postinfl}}, not to user-specified inflection tags.
; {{para|term_param}}
; {{para|lang}}
; {{para|sc}}
; {{para|cat}}, {{para|cat2}}, ...
; {{para|ignore}}, {{para|ignore2}}, ...
; {{para|def}}, {{para|def2}}, ...
; {{para|withcap|1}}
; {{para|withencap|1}}
; {{para|withdot|1}}
; {{para|nolink|1}}
; {{para|linktext}}
; {{para|posttext}}
; {{para|noprimaryentrycat}}
; {{para|lemma_is_sort_key|1}}
: All of these are the same as in {form_of_t()}.
]==]
function export.inflection_of_t(frame)
local iparams = get_common_invocation_params("inflection_of_t")
iparams.preinfl = {list = true}
iparams.postinfl = {list = true}
iparams.split_tags = true
local iargs = process_params(frame.args, iparams)
local parent_args = frame:getParent().args
local params = get_common_template_params()
local compat = iargs.lang or parent_args.lang
local tagsind = (iargs.term_param or compat and 1 or 2) + 2
params[tagsind] = {list = true,
-- at least one inflection tag is required unless preinfl or postinfl tags are given
required = #iargs.preinfl == 0 and #iargs.postinfl == 0}
return construct_tagged_form_of_text {
template = "inflection-of-t",
iargs = iargs,
parent_args = parent_args,
params = params,
no_numbered_gloss = true,
tags = function(args)
local infls
if not next(iargs.preinfl) and not next(iargs.postinfl) then
-- If no preinfl or postinfl tags, just use the user-specified tags directly.
infls = args[tagsind]
else
-- Otherwise, we need to prepend the preinfl tags and postpend the postinfl tags. If there's only one tag set
-- (no semicolon), it's easier. Since this is common, we optimize for it.
infls = {}
local saw_semicolon = false
for _, infl in ipairs(args[tagsind]) do
if infl == ";" then
saw_semicolon = true
break
end
end
local split_preinfl = split_inflection_tags(iargs.preinfl, iargs.split_tags)
local split_postinfl = split_inflection_tags(iargs.postinfl, iargs.split_tags)
if not saw_semicolon then
extend(infls, split_preinfl)
extend(infls, args[tagsind])
extend(infls, split_postinfl)
else
local groups = split_tag_set(args[tagsind])
for _, group in ipairs(groups) do
if #infls > 0 then
insert(infls, ";")
end
extend(infls, split_preinfl)
extend(infls, group)
extend(infls, split_postinfl)
end
end
end
return infls
end,
}
end
--[==[
Normalize a part-of-speech tag given a possible abbreviation (passed in as {{para|1}} of the invocation args). If the
abbreviation isn't recognized, the original POS tag is returned. If no POS tag is passed in, return the value of
invocation arg {{para|default}}.
]==]
function export.normalize_pos(frame)
local iparams = {
[1] = true,
["default"] = true,
}
local iargs = process_params(frame.args, iparams)
if not iargs[1] and not iargs.default then
error("Either 1= or default= must be given in the invocation args")
end
if not iargs[1] then
return iargs.default
end
return (m_form_of_pos or get_m_form_of_pos())[iargs[1]] or iargs[1]
end
return export
7z6g2yjudpq6y1fegrs59qknox7coi5
25209
25208
2026-08-19T05:00:04Z
Deepturquoise
2456
-
25209
Scribunto
text/plain
local export = {}
local debug_track_module = "Module:debug/track"
local form_of_module = "Module:form of"
local functions_module = "Module:fun"
local headword_data_module = "Module:headword/data"
local languages_module = "Module:languages"
local load_module = "Module:load"
local parameters_module = "Module:parameters"
local parameter_utilities_module = "Module:parameter utilities"
local parse_interface_module = "Module:parse interface"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local insert = table.insert
local ipairs = ipairs
local pairs = pairs
local require = require
local boolean_param = {type = "boolean"}
-- FIXME: Finish [[Module:format utilities]].
-- local allowed_conj_set = require(format_utilities_module).allowed_conj_set_for_join_segments
local allowed_conj_set = {["and"] = true, ["or"] = true, ["and/or"] = true}
--[==[
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 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 extend(...)
extend = require(table_module).extend
return extend(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_form_of(...)
format_form_of = require(form_of_module).format_form_of
return format_form_of(...)
end
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
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 load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function parse_inline_modifiers(...)
parse_inline_modifiers = require(parse_interface_module).parse_inline_modifiers
return parse_inline_modifiers(...)
end
local function pattern_escape(...)
pattern_escape = require(string_utilities_module).pattern_escape
return pattern_escape(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function safe_load_data(...)
safe_load_data = require(load_module).safe_load_data
return safe_load_data(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function split_tag_set(...)
split_tag_set = require(form_of_module).split_tag_set
return split_tag_set(...)
end
local function tagged_inflections(...)
tagged_inflections = require(form_of_module).tagged_inflections
return tagged_inflections(...)
end
local function trim(...)
trim = require(string_utilities_module).trim
return trim(...)
end
local function ucfirst(...)
ucfirst = require(string_utilities_module).ucfirst
return ucfirst(...)
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 force_cat
local function get_force_cat()
force_cat, get_force_cat = require(form_of_module).force_cat, nil
return force_cat
end
local m_form_of_pos
local function get_m_form_of_pos()
m_form_of_pos, get_m_form_of_pos = load_data(headword_data_module).pos_aliases, nil
return m_form_of_pos
end
local module_prefix
local function get_module_prefix()
module_prefix, get_module_prefix = require(form_of_module).form_of_lang_data_module_prefix, nil
return module_prefix
end
--[==[ intro:
This module contains code that directly implements {{tl|form of}}, {{tl|inflection of}}, and the various other
[[:Category:Form-of templates|form-of templates]]. It is meant to be called directly from templates. See also
[[Module:form of]], which contains the underlying implementing code and is meant to be called from other modules.
]==]
-- Add tracking category for PAGE when called from TEMPLATE. The tracking category linked to is
-- [[Wiktionary:Tracking/form of/TEMPLATE/PAGE]]. If TEMPLATE is omitted, the tracking category is of the form
-- [[Wiktionary:Tracking/form of/PAGE]].
local function track(page, template)
debug_track("form of/" .. (template and template .. "/" or "") .. page)
end
local function get_common_template_params()
return {
-- Named params not controlling link display
["cat"] = {list = true, sublist = "comma without whitespace", flatten = true},
["notext"] = boolean_param,
["sort"] = true,
["enclitic"] = true,
-- FIXME! The following should only be available when withcap=1 in invocation args or when withencap=1 and the
-- language is "en". Before doing that, need to remove all uses of nocap= in other circumstances.
["nocap"] = boolean_param,
["addl"] = true, -- additional text to display at the end, before the closing </span>
["pagename"] = true, -- for testing, etc.
}
end
-- Split TAGSPECS (inflection tag specifications) on SPLIT_REGEX, which
-- may be nil for no splitting.
local function split_inflection_tags(tagspecs, split_regex)
if not split_regex then
return tagspecs
end
local inflection_tags = {}
for _, tagspec in ipairs(tagspecs) do
for tag in gsplit(tagspec, split_regex) do
insert(inflection_tags, tag)
end
end
return inflection_tags
end
local function parse_terms_with_inline_modifiers(paramname, val, param_mods, lang)
local function generate_obj(term)
return {lang = lang, term = decode_entities(term)}
end
return parse_inline_modifiers(val, {
paramname = paramname,
param_mods = param_mods,
generate_obj = generate_obj,
splitchar = ",",
outer_container = {},
})
end
-- Need to do what [[Module:parameters]] does to string arguments from parent_args as we're running this
-- before calling [[Module:parameters]] on parent_args.
local function ine(arg)
if not arg then
return nil
end
arg = trim(arg)
return arg ~= "" and arg or nil
end
local function add_base_lemma_params(parent_args, iargs, params, compat)
-- Check the language-specific data for additional base lemma params. But if there's no language-specific data,
-- attempt any parent varieties as well (i.e. superordinate varieties).
local lang = get_lang(ine(parent_args[compat and "lang" or 1]) or ine(iargs.lang) or "und", nil, true)
while lang do
local langdata = safe_load_data((module_prefix or get_module_prefix()) .. lang:getCode())
if langdata then
local base_lemma_params = langdata.base_lemma_params
if base_lemma_params then
for _, param in ipairs(base_lemma_params) do
params[param.param] = true
end
return base_lemma_params
end
end
lang = lang:getParent()
end
end
--[=[
Modify `params` in-place by adding parameters that control the link to the main entry and any base lemmas. `term_param`
is the number of the param specifying the main entry itself; `term_param` + 1 will be the display text, and `term_param`
+ 2 will be the gloss, unless `no_numbered_gloss` is given. The base lemma parameters are determined by attempting to
load language-specific data for the language of the page; this comes from |lang= if `compat` is given, else from |1=.
]=]
local function add_link_and_base_lemma_params(iargs, parent_args, params, term_param, compat, no_numbered_gloss)
local base_lemma_params
if not iargs.nolink and not iargs.linktext then
-- Numbered params controlling link display
if iargs.with_multiple_parts then
params[term_param] = {list = true, allow_holes = true}
else
params[term_param + 1] = {alias_of = "alt"}
if not no_numbered_gloss then
params[term_param + 2] = {alias_of = "t"}
end
params[term_param] = true
end
base_lemma_params = add_base_lemma_params(parent_args, iargs, params, compat)
end
return base_lemma_params
end
local function handle_withdot_withcap(iargs, params)
local ignored_tracked_params = {}
if iargs.withdot then
params.dot = true
params.nodot = boolean_param
end
if iargs.withcap and iargs.withencap then
error("Internal error: Can specify only one of withcap= and withencap=")
end
if not iargs.withcap then
params.cap = boolean_param
ignored_tracked_params.nocap = iargs.withencap and "non-english" or "always"
end
return ignored_tracked_params
end
--[=[
Construct and return the full definition line for a form-of-type template invocation. `data` is an object with the
following fields:
* `template`: Approximate template name, for debug tracking;
* `iargs`: processed invocation arguments;
* `parent_args`: raw parent args from `frame:getParent().args`;
* `params`: partially constructed params structure of the sort passed to `process()` in [[Module:parameters]], but
without any link params;
* `ignored_tracked_params`: params that are ignored but should be tracked, to be eventually removed;
* `term_param`: the parent argument specifying the main entry;
* `compat`: true if the language code is found in args.lang instead of args[1];
* `base_lemma_params`: if non-nil, a list of base lemma param objects of the sort stored in the language-specific data;
* `do_form_of`: a function of one argument, `lemma_data`, that returns the actual definition-line text and any
language-specific categories. See below.
This function does several things:
# If link parameters are called for (neither `iargs.nolink` nor `iargs.linktext` are given), augment the `params`
structure with separate link parameters.
# Modify the parent args as appropriate if invocation arguments def= or ignore= are given.
# Parse the parent args, both for separate parameter properties and inline modifiers on the term parameter (which may
consist of multiple comma-separated terms).
# Compute categories to add to the page, including language-specific categories and any categories requested by the
invocation or parent args.
# Parse enclitic and extra base lemma parameters.
# Construct the actual text using `do_form_of`.
# Add a terminating period/dot as appropriate, along with the formatted categories.
`do_form_of` takes one argument, `lemma_data`, which looks like this:
{
lang = LANG,
args = {ARG = VALUE, ARG = VALUE, ...},
lemmas = {LEMMA_OBJ, LEMMA_OBJ, ...},
enclitics = {ENCLITIC_OBJ, ENCLITIC_OBJ, ...},
base_lemmas = {BASE_LEMMA_OBJ, BASE_LEMMA_OBJ, ...},
categories = {"CATEGORY", "CATEGORY", ...},
posttext = "POSTTEXT" or nil,
}
where
* LANG is the language code;
* ARGS is the parsed arguments, based on what the user specified;
* LEMMAS is a sequence of objects specifying the main entries/lemmas, as passed to full_link in [[Module:links]];
however, if the invocation argument linktext= is given, it will be a string consisting of that text, and if the
invocation argument nolink= is given, it will be nil;
* ENCLITICS is nil or a sequence of objects specifying the enclitics, as passed to full_link in [[Module:links]];
* BASE_LEMMA_OBJ is a sequence of objects specifying the base lemma(s), which are used when the lemma is itself a
form of another lemma (the base lemma), e.g. a comparative, superlative or participle; each object is of the form
{ paramobj = PARAM_OBJ, lemmas = {LEMMA_OBJ, LEMMA_OBJ, ...} } where PARAM_OBJ describes the properties of the
base lemma parameter (i.e. the relationship between the intermediate and base lemmas) and LEMMA_OBJ is of the same
format of ENCLITIC_OBJ, i.e. an object suitable to be passed to full_link in [[Module:links]]; PARAM_OBJ is of the
format { param = "PARAM", tags = {"TAG", "TAG", ...} } where PARAM is the name of the parameter to
{{inflection of}} etc. that holds the base lemma(s) of the specified relationship and the tags describe the
relationship, such as {"comd"} or {"past", "part"};
* CATEGORIES is the categories to add the page to (consisting of any categories specified in the invocation or
parent args and any tracking categories, but not any additional lang-specific categories that may be added by
{{inflection of}} or similar templates);
* POSTTEXT is text to display at the end of the form-of text, before the final </span> (or at the end of the first
line, before the colon, in a multiline {{infl of}} call).
`do_form_of` should return two arguments:
(1) The actual definition-line text, marked up appropriately with <span>...</span> but without any terminating
period/dot.
(2) Any extra categories to add the page to (other than those that can be derived from parameters specified to the
invocation or parent arguments, which will automatically be added to the page).
]=]
local function construct_form_of_text(data)
local template, iargs, parent_args, params, no_numbered_gloss, do_form_of =
data.template, data.iargs, data.parent_args, data.params, data.no_numbered_gloss, data.do_form_of
local term_param = iargs.term_param
local compat = iargs.lang or parent_args.lang
term_param = term_param or compat and 1 or 2
-- Numbered params
params[compat and "lang" or 1] = {
required = not iargs.lang,
type = "language",
default = iargs.lang or "und"
}
-- Error to catch most uses of old-style parameters for {{contraction of}}. (FIXME: Remove eventually.)
if iargs.with_multiple_parts then
if ine(parent_args[term_param + 2]) and not ine(parent_args[term_param + 1]) and not ine(parent_args.tr2) and not ine(parent_args.ts2)
and not ine(parent_args.t2) and not ine(parent_args.gloss2) and not ine(parent_args.g2)
and not ine(parent_args.alt2) then
error(("You specified a term in %s= and not one in %s=. You probably meant to use t= to specify a gloss instead. "
.. "If you intended to specify two terms, put the second term in %s=."):format(term_param + 2, term_param + 1,
term_param + 1))
end
if not ine(parent_args[term_param + 1]) and not ine(parent_args.alt2) and not ine(parent_args.tr2) and not ine(parent_args.ts2)
and ine(parent_args.g2) then
error(("You specified a gender in g2= but no term in %s=. You were probably trying to specify two genders for "
.. "a single term. To do that, put both genders in g=, comma-separated."):format(term_param + 1))
end
end
local base_lemma_params = add_link_and_base_lemma_params(iargs, parent_args, params, term_param, compat,
no_numbered_gloss)
local ignored_tracked_params = handle_withdot_withcap(iargs, params)
--[=[
Process parent arguments. This is similar to the following:
require("Module:parameters").process(parent_args, params)
but in addition it does the following:
(1) Supplies default values for unspecified parent arguments as specified in DEFAULTS, which consist of specs of the
form "ARG=VALUE". These are added to the parent arguments prior to processing, so boolean and number parameters
will process the value appropriately.
(2) Removes parent arguments specified in IGNORESPECS, which consist either of bare argument names to remove, or
list-argument names to remove of the form "ARG:list".
(3) Tracks the use of any parent arguments specified in TRACKED_PARAMS, which is a set where the keys are arguments
as they exist after processing (hence numeric arguments should be numbers, not strings) and the values should be
boolean true.
]=]--
local defaults = iargs.def
local ignorespecs = iargs.ignore
if defaults[1] or ignorespecs[1] then
local new_parent_args = {}
for _, default in ipairs(defaults) do
local defparam, defval = default:match("^(.-)=(.*)$")
if not defparam then
error("Bad default spec " .. default)
end
new_parent_args[defparam] = defval
end
local params_to_ignore = {}
local numbered_list_params_to_ignore = {}
local named_list_params_to_ignore = {}
for _, ignorespec in ipairs(ignorespecs) do
for ignore in gsplit(ignorespec, ",") do
local param = ignore:match("^(.*):list$")
if param then
if param:match("^%d+$") then
insert(numbered_list_params_to_ignore, tonumber(param))
else
insert(named_list_params_to_ignore, "^" .. pattern_escape(param) .. "%d*$")
end
else
if ignore:match("^%d+$") then
ignore = tonumber(ignore)
end
params_to_ignore[ignore] = true
end
end
end
for k, v in pairs(parent_args) do
if not params_to_ignore[k] then
local ignore_me = false
if type(k) == "number" then
for _, lparam in ipairs(numbered_list_params_to_ignore) do
if k >= lparam then
ignore_me = true
break
end
end
else
for _, lparam in ipairs(named_list_params_to_ignore) do
if k:match(lparam) then
ignore_me = true
break
end
end
end
if not ignore_me then
new_parent_args[k] = v
end
end
end
parent_args = new_parent_args
end
local param_mods_with_conj, param_mods_without_conj
local function get_param_mods(with_conj)
if with_conj then
if not param_mods_with_conj then
param_mods_with_conj = require(parameter_utilities_module).construct_param_mods {
{group = {"link", "q", "l", "ref"}},
{param = "conj", set = allowed_conj_set, overall = true},
}
end
return param_mods_with_conj
else
if not param_mods_without_conj then
param_mods_without_conj = require(parameter_utilities_module).construct_param_mods {
{group = {"link", "q", "l", "ref"}},
-- Override lit= to have a separate overall value
{param = "lit", separate_no_index = true},
}
end
return param_mods_without_conj
end
end
local terms, args
if iargs.nolink or iargs.linktext then
args = process_params(parent_args, params)
else
local m_param_utils = require(parameter_utilities_module)
if iargs.with_multiple_parts then
terms, args = m_param_utils.parse_list_with_inline_modifiers_and_separate_params {
params = params,
param_mods = get_param_mods(false),
raw_args = parent_args,
termarg = term_param,
track_module = "form of" .. (template and "/" .. template or ""),
lang = compat and "lang" or 1,
sc = "sc.default",
parse_lang_prefix = true,
default_separator = " +‎ ",
special_separators = {[";"] = " or "},
}
else
terms, args = m_param_utils.parse_term_with_inline_modifiers_and_separate_params {
params = params,
param_mods = get_param_mods("with conj"),
raw_args = parent_args,
termarg = term_param,
track_module = "form of" .. (template and "/" .. template or ""),
lang = compat and "lang" or 1,
sc = "sc",
parse_lang_prefix = true,
make_separate_g_into_list = true,
splitchar = ",",
subitem_param_handling = "last",
}
end
end
local lang = args[compat and "lang" or 1]
-- Tracking for certain user-specified params. This is generally used for
-- parameters that we accept but ignore, so that we can eventually remove
-- all uses of these params and stop accepting them.
if ignored_tracked_params then
for ignored_tracked_param, condition in pairs(ignored_tracked_params) do
if parent_args[ignored_tracked_param] and (condition ~= "non-english" or lang:getCode() ~= "en") then
track("arg/" .. ignored_tracked_param, template)
track("arg/" .. ignored_tracked_param)
end
end
end
-- Determine categories for the page, including tracking categories
local categories = {}
if not args.nocat then
for _, cat in ipairs(iargs.cat) do
insert(categories, lang:getFullName() .. " " .. cat)
end
end
for _, cat in ipairs(args.cat) do
insert(categories, lang:getFullName() .. " " .. cat)
end
-- Format the link, preceding text and categories
local function add_term_tracking_categories(term)
-- add tracking category if term is same as page title
if term and mw.loadData("Module:headword/data").pagename == lang:stripDiacritics(term) then
insert(categories, "Forms linking to themselves")
end
-- maybe add tracking category if primary entry doesn't exist (this is an
-- expensive call so we don't do it by default)
if iargs.noprimaryentrycat and term and mw.title.getCurrentTitle().nsText == ""
and not mw.title.new(term):getContent() then
insert(categories, lang:getFullName() .. " " .. iargs.noprimaryentrycat)
end
end
local lemmas
if iargs.nolink then
lemmas = nil
elseif iargs.linktext then
lemmas = iargs.linktext
else
if iargs.with_multiple_parts then
lemmas = terms
else
lemmas = terms.terms
end
if not lemmas[1] then
if mw.title.getCurrentTitle().nsText == "Template" then
lemmas[1] = {
lang = lang,
term = "term"
}
else
error("No linked-to term specified")
end
end
for _, termobj in ipairs(lemmas) do
if termobj.term then
add_term_tracking_categories(termobj.term)
end
-- NOTE: Formerly, template arg sc= overrode inline modifier <sc:...>, which seems backwards, so I've
-- changed it. Hopefully nothing depended on the old behavior.
end
end
local enclitics, enclitic_conj
if args.enclitic then
local enclitics_obj = parse_terms_with_inline_modifiers("enclitic", args.enclitic, get_param_mods("with conj"),
lang)
enclitics = enclitics_obj.terms
enclitic_conj = enclitics_obj.conj
end
local base_lemmas = {}
if base_lemma_params then
for _, base_lemma_param_obj in ipairs(base_lemma_params) do
local param = base_lemma_param_obj.param
if args[param] then
local base_lemmas_obj = parse_terms_with_inline_modifiers(param, args[param],
get_param_mods("with conj"), lang)
insert(base_lemmas, {
paramobj = base_lemma_param_obj,
lemmas = base_lemmas_obj.terms,
conj = base_lemmas_obj.conj,
})
end
end
end
local posttext = iargs.posttext
local addl = args.addl
if addl then
posttext = posttext or ""
if addl:find("^[;:]") then
posttext = posttext .. addl
elseif addl:find("^_") then
posttext = posttext .. " " .. addl:sub(2)
else
posttext = posttext .. ", " .. addl
end
end
local conj
if iargs.with_multiple_parts then
conj = false -- signals to use 'separator' field
else
conj = terms and terms.conj or iargs.conj
end
local lemma_data = {
lang = lang,
args = args,
lemmas = lemmas,
conj = conj,
enclitics = enclitics,
enclitic_conj = enclitic_conj,
base_lemmas = base_lemmas,
categories = categories,
posttext = posttext,
lit = iargs.with_multiple_parts and args.lit.default or nil,
}
local form_of_text, lang_cats = do_form_of(lemma_data)
extend(lemma_data.categories, lang_cats)
local text = form_of_text .. (
args.nodot and "" or args.dot or iargs.withdot and "." or ""
)
if not lemma_data.categories[1] then
return text
end
return text .. format_categories(lemma_data.categories, lemma_data.lang, args.sort,
-- If lemma_is_sort_key is given, supply the first lemma term as the sort base if possible. If sort= is given,
-- it will override the base; otherwise, the base will be converted appropriately to a sort key using the
-- same algorithm applied to pagenames.
iargs.lemma_is_sort_key and type(lemma_data.lemmas) == "table" and lemma_data.lemmas[1].term,
-- Supply the first lemma's script for sort key computation.
force_cat or get_force_cat(), type(lemma_data.lemmas) == "table" and lemma_data.lemmas[1].sc)
end
-- Invocation parameters shared between form_of_t(), tagged_form_of_t() and inflection_of_t(). `calling_func` is the
-- invoking function ("form_of_t", "tagged_form_of_t" or "inflection_of_t"), for handling parameters shared by two but
-- not all three invoking functions.
local function get_common_invocation_params(calling_func)
local iparams = {
["term_param"] = {type = "number"},
["lang"] = true, -- To be used as the default code in params.
["sc"] = {type = "script"},
["cat"] = {list = true, sublist = "comma without whitespace", flatten = true},
["ignore"] = {list = true},
["def"] = {list = true},
["conj"] = {set = allowed_conj_set, default = "and"},
["withcap"] = boolean_param,
["withencap"] = boolean_param,
["withdot"] = boolean_param,
["nolink"] = boolean_param,
["linktext"] = true,
["posttext"] = true,
["noprimaryentrycat"] = true,
["lemma_is_sort_key"] = true,
}
if calling_func ~= "inflection_of_t" then
iparams.with_multiple_parts = boolean_param
end
return iparams
end
local function should_ucfirst_text(args, iargs, lang)
local code = lang:getCode()
return args.cap or (iargs.withcap or iargs.withencap and code == "en" or code == "mul") and not args.nocap
end
--[==[
Function that implements {{tl|form of}} and the various more specific form-of templates (but not {{tl|inflection of}}
or templates that take tagged inflection parameters).
Invocation params:
; {{para|1|req=1}}
: Text to display before the link.
; {{para|term_param}}
: Numbered param holding the term linked to. Other numbered params come after. Defaults to 1 if invocation or template
param {{para|lang}} is present, otherwise 2.
; {{para|with_multiple_parts|1}}
: If specified, higher numbered parameters above the numbered param in {{para|term_param}} specify additional parts out
of which the term was constructed, for use by templates like {{tl|contraction of}}. (If not specified, the parameter
at <code><var>term_param</var> + 1</code> is the display form, same as {{para|alt}}, and the parameter at
at <code><var>term_param</var> + 2</code> is the gloss, same as {{para|t}}.)
; {{para|lang}}
: Default language code for language-specific templates. If specified, no language code needs to be specified, and if
specified it needs to be set using {{para|lang}}, not {{para|1}}.
; {{para|sc}}
: Default script code for language-specific templates. The script code can still be overridden using template param
{{para|sc}}.
; {{para|cat}}, {{para|cat2}}, ...:
: Categories to place the page into. The language name will automatically be prepended. Note that there is also a
template param {{para|cat}} to specify categories at the template level. Use of {{para|nocat}} disables categorization
of categories specified using invocation param {{para|cat}}, but not using template param {{para|cat}}. A single param
can specify multiple comma-separated categories if no space follows the comma.
; {{para|ignore}}, {{para|ignore2}}, ...:
: One or more template params to silently accept and ignore. Useful e.g. when the template takes additional parameters
such as {{para|from}} or {{para|POS}}. Each value is a comma-separated list of either bare parameter names or
specifications of the form `PARAM:list` to specify that the parameter is a list parameter.
; {{para|def}}, {{para|def2}}, ...:
: One or more default values to supply for template args. For example, specifying {{para|def|2=tr=-}} causes the default
for template param {{para|tr}} to be `-`. Actual template params override these defaults.
; {{para|withcap|1}}
: Capitalize the first character of the text preceding the link, unless template param {{para|nocap}} is given.
; {{para|withencap|1}}
: Capitalize the first character of the text preceding the link if the language is English and template param
{{para|nocap}} is not given.
; {{para|withdot|1}}
: Add a final period after the link, unless template param {{para|nodot}} is given to suppress the period, or
{{para|dot}} is given to specify an alternative punctuation character.
; {{para|nolink|1}}
: Suppress the display of the link. If specified, none of the template params that control the link
({{para|<var>term_param</var>}}, {{para|<var>term_param</var> + 1}}, {{para|<var>term_param</var> + 2}}, {{para|t}},
{{para|gloss}}, {{para|sc}}, {{para|tr}}, {{para|ts}}, {{para|pos}}, {{para|g}}, {{para|id}}, {{para|lit}}) will be
available. If the calling template uses any of these parameters, they must be ignored using {{para|ignore}}.
{{para|linktext}}
: Override the display of the link with the specified text. This is useful if a custom template is available to format
the link (e.g. in Hebrew, Chinese and Japanese). If specified, none of the template params that control the link
({{para|<var>term_param</var>}}, {{para|<var>term_param</var> + 1}}, {{para|<var>term_param</var> + 2}}, {{para|t}},
{{para|gloss}}, {{para|sc}}, {{para|tr}}, {{para|ts}}, {{para|pos}}, {{para|g}}, {{para|id}}, {{para|lit}}) will be
available. If the calling template uses any of these parameters, they must be ignored using {{para|ignore}}.
; {{para|posttext}}
: Additional text to display directly after the formatted link, before any terminating period/dot and inside of
`<span class='use-with-mention'>`.
; {{para|noprimaryentrycat}}
: Category to add the page to if the primary entry linked to doesn't exist. The language name will automatically be
prepended.
; {{para|lemma_is_sort_key|1}}
: If the user didn't specify a sort key, use the lemma as the sort key (instead of the page itself).
]==]
function export.form_of_t(frame)
local iparams = get_common_invocation_params("form_of_t")
iparams[1] = {required = true}
local iargs = process_params(frame.args, iparams)
local parent_args = frame:getParent().args
local params = get_common_template_params()
if next(iargs.cat) then
params.nocat = boolean_param
end
return construct_form_of_text {
template = "form-of-t",
iargs = iargs,
parent_args = parent_args,
params = params,
do_form_of = function(lemma_data)
local args = lemma_data.args
local text
if args.notext then
text = ""
else
text = iargs[1]
if should_ucfirst_text(args, iargs, lemma_data.lang) then
text = ucfirst(text)
end
end
-- This returns two values, which we pass up to the caller.
return format_form_of {
lang = lemma_data.lang, text = text, lemmas = lemma_data.lemmas, conj = lemma_data.conj,
enclitics = lemma_data.enclitics, base_lemmas = lemma_data.base_lemmas, lemma_face = "term",
lit = lemma_data.lit, posttext = lemma_data.posttext
}
end
}
end
--[=[
Construct and return the full definition line for a form-of-type template invocation that is based on inflection tags.
This is a wrapper around construct_form_of_text() and takes the following arguments: processed invocation arguments
IARGS, processed parent arguments ARGS, TERM_PARAM (the parent argument specifying the main entry), COMPAT (true if the
language code is found in args.lang instead of args[1]), and TAGS, the list of (non-canonicalized) inflection tags.
It returns that actual definition-line text including terminating period/full-stop, formatted categories, etc. and
should be directly returned as the template function's return value.
]=]
local function construct_tagged_form_of_text(data)
local template, iargs, parent_args, params, no_numbered_gloss, tags =
data.template, data.iargs, data.parent_args, data.params, data.no_numbered_gloss, data.tags
-- Named params not controlling link display
-- Always included because lang-specific categories may be added
params.nocat = boolean_param
params.p = true
params.POS = {alias_of = "p"}
return construct_form_of_text {
template = template,
iargs = iargs,
parent_args = parent_args,
params = params,
no_numbered_gloss = no_numbered_gloss,
do_form_of = function(lemma_data)
local args = lemma_data.args
if is_callable(tags) then
tags = tags(args)
end
-- NOTE: tagged_inflections returns two values, so we do too.
return tagged_inflections {
lang = lemma_data.lang,
tags = tags,
lemmas = lemma_data.lemmas,
conj = lemma_data.conj,
enclitics = lemma_data.enclitics,
enclitic_conj = lemma_data.enclitic_conj,
base_lemmas = lemma_data.base_lemmas,
lemma_face = "term",
POS = args.p,
pagename = args.pagename,
-- Set no_format_categories because we do it ourselves in construct_form_of_text().
no_format_categories = true,
nocat = args.nocat,
notext = args.notext,
capfirst = should_ucfirst_text(args, iargs, lemma_data.lang),
posttext = lemma_data.posttext,
}
end
}
end
--[==[
Function that implements form-of templates that are defined by specific tagged inflections (typically a template
referring to a non-lemma inflection, such as {{tl|plural of}}). This works exactly like {form_of_t()} except that the
"form of" text displayed before the link is based off of a pre-specified set of inflection tags (which will be
appropriately linked to the glossary) instead of arbitrary text. From the user's perspective, there is no difference
between templates implemented using {form_of_t()} and {tagged_form_of_t()}; they accept exactly the same parameters and
work the same. See also {inflection_of_t()} below, which is intended for templates with user-specified inflection tags.
Invocation params:
; {{para|1|req=1}}, {{para|2}}, ...
: One or more inflection tags describing the inflection in question.
; {{para|split_tags}}
: If specified, character to split specified inflection tags on. This allows multiple tags to be included in a single
argument, simplifying template code.
; {{para|term_param}}
; {{para|with_multiple_parts|1}}
; {{para|lang}}
; {{para|sc}}
; {{para|cat}}, {{para|cat2}}, ...
; {{para|ignore}}, {{para|ignore2}}, ...
; {{para|def}}, {{para|def2}}, ...
; {{para|withcap|1}}
; {{para|withencap|1}}
; {{para|withdot|1}}
; {{para|nolink|1}}
; {{para|linktext}}
; {{para|posttext}}
; {{para|noprimaryentrycat}}
; {{para|lemma_is_sort_key|1}}
: All of these are the same as in {form_of_t()}.
]==]
function export.tagged_form_of_t(frame)
local iparams = get_common_invocation_params("tagged_form_of_t")
iparams[1] = {list = true, required = true}
iparams.split_tags = true
local iargs = process_params(frame.args, iparams)
local parent_args = frame:getParent().args
local params = get_common_template_params()
return construct_tagged_form_of_text {
template = "tagged-form-of-t",
iargs = iargs,
parent_args = parent_args,
params = params,
tags = split_inflection_tags(iargs[1], iargs.split_tags),
}
end
--[==[
Function that implements {{tl|inflection of}} and certain semi-specific variants, such as {{tl|participle of}} and
{{tl|past participle form of}}. This function is intended for templates that allow the user to specify a set of
inflection tags.
It works similarly to {form_of_t()} and {tagged_form_of_t()} except that the calling convention for the calling
template is
: { {{TEMPLATE|LANG|MAIN_ENTRY_LINK|MAIN_ENTRY_DISPLAY_TEXT|TAG|TAG|...}}}
instead of
: { {{TEMPLATE|LANG|MAIN_ENTRY_LINK|MAIN_ENTRY_DISPLAY_TEXT|GLOSS}}}
Note that there isn't a numbered parameter for the gloss, but it can still be specified using {{para|t}} or
{{para|gloss}}.
Invocation params:
; {{para|preinfl}}, {{para|preinfl2}}, ...
: Extra inflection tags to automatically prepend to the tags specified by the template.
; {{para|postinfl}}, {{para|postinfl2}}, ...
: Extra inflection tags to automatically append to the tags specified by the template. Used for example by
{{tl|past participle form of}} to add the tags `of the|past|p` onto the user-specified tags, which indicate which
past participle form the page refers to.
; {{para|split_tags}}
: If specified, character to split specified inflection tags on. This allows multiple tags to be included in a single
argument, simplifying template code. Note that this applies *ONLY* to inflection tags specified in the invocation
arguments using {{para|preinfl}} or {{para|postinfl}}, not to user-specified inflection tags.
; {{para|term_param}}
; {{para|lang}}
; {{para|sc}}
; {{para|cat}}, {{para|cat2}}, ...
; {{para|ignore}}, {{para|ignore2}}, ...
; {{para|def}}, {{para|def2}}, ...
; {{para|withcap|1}}
; {{para|withencap|1}}
; {{para|withdot|1}}
; {{para|nolink|1}}
; {{para|linktext}}
; {{para|posttext}}
; {{para|noprimaryentrycat}}
; {{para|lemma_is_sort_key|1}}
: All of these are the same as in {form_of_t()}.
]==]
function export.inflection_of_t(frame)
local iparams = get_common_invocation_params("inflection_of_t")
iparams.preinfl = {list = true}
iparams.postinfl = {list = true}
iparams.split_tags = true
local iargs = process_params(frame.args, iparams)
local parent_args = frame:getParent().args
local params = get_common_template_params()
local compat = iargs.lang or parent_args.lang
local tagsind = (iargs.term_param or compat and 1 or 2) + 2
params[tagsind] = {list = true,
-- at least one inflection tag is required unless preinfl or postinfl tags are given
required = #iargs.preinfl == 0 and #iargs.postinfl == 0}
return construct_tagged_form_of_text {
template = "inflection-of-t",
iargs = iargs,
parent_args = parent_args,
params = params,
no_numbered_gloss = true,
tags = function(args)
local infls
if not next(iargs.preinfl) and not next(iargs.postinfl) then
-- If no preinfl or postinfl tags, just use the user-specified tags directly.
infls = args[tagsind]
else
-- Otherwise, we need to prepend the preinfl tags and postpend the postinfl tags. If there's only one tag set
-- (no semicolon), it's easier. Since this is common, we optimize for it.
infls = {}
local saw_semicolon = false
for _, infl in ipairs(args[tagsind]) do
if infl == ";" then
saw_semicolon = true
break
end
end
local split_preinfl = split_inflection_tags(iargs.preinfl, iargs.split_tags)
local split_postinfl = split_inflection_tags(iargs.postinfl, iargs.split_tags)
if not saw_semicolon then
extend(infls, split_preinfl)
extend(infls, args[tagsind])
extend(infls, split_postinfl)
else
local groups = split_tag_set(args[tagsind])
for _, group in ipairs(groups) do
if #infls > 0 then
insert(infls, ";")
end
extend(infls, split_preinfl)
extend(infls, group)
extend(infls, split_postinfl)
end
end
end
return infls
end,
}
end
--[==[
Normalize a part-of-speech tag given a possible abbreviation (passed in as {{para|1}} of the invocation args). If the
abbreviation isn't recognized, the original POS tag is returned. If no POS tag is passed in, return the value of
invocation arg {{para|default}}.
]==]
function export.normalize_pos(frame)
local iparams = {
[1] = true,
["default"] = true,
}
local iargs = process_params(frame.args, iparams)
if not iargs[1] and not iargs.default then
error("Either 1= or default= must be given in the invocation args")
end
if not iargs[1] then
return iargs.default
end
return (m_form_of_pos or get_m_form_of_pos())[iargs[1]] or iargs[1]
end
return export
qngi7g0ngefkunhqwao6b90egp7n7t7
Modul:parameter utilities
828
7187
25207
20364
2026-08-19T04:56:55Z
Deepturquoise
2456
25207
Scribunto
text/plain
local export = {}
local debug_track_module = "Module:debug/track"
local functions_module = "Module:fun"
local parameters_module = "Module:parameters"
local parse_interface_module = "Module:parse interface"
local parse_utilities_module = "Module:parse utilities"
local table_module = "Module:table"
local dump = mw.dumpObject
local error = error
local insert = table.insert
local ipairs = ipairs
local next = next
local pairs = pairs
local require = require
local tonumber = tonumber
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 debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function is_callable(...)
is_callable = require(functions_module).is_callable
return is_callable(...)
end
local function list_to_set(...)
list_to_set = require(table_module).listToSet
return list_to_set(...)
end
local function parse_inline_modifiers(...)
parse_inline_modifiers = require(parse_interface_module).parse_inline_modifiers
return parse_inline_modifiers(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
end
local function table_len(...)
table_len = require(table_module).length
return table_len(...)
end
----------------- end loaders ----------------
local function track(page, track_module)
return debug_track((track_module or "parameter utilities") .. "/" .. page)
end
-- Throw an error prefixed with the words "Internal error" (and suffixed with a dumped version of `spec`, if provided).
-- This is for logic errors in the code itself rather than template user errors.
local function internal_error(msg, spec)
if spec then
msg = ("%s: %s"):format(msg, dump(spec))
end
error(("Internal error: %s"):format(msg))
end
-- Table listing the default recognized special separator arguments and how they display.
export.default_special_separators = {
[";"] = "; ",
["_"] = " ",
["~"] = " ~ ",
["→"] = " → ",
}
-- Table listing how subitem delimiters display. Unlike for `default_special_separators`, the presence of an item in
-- this table does not mean that the delimiter is recognized; only those specified by `data.splitchar` are recognized.
export.default_subitem_separator_map = {
[";"] = "; ",
[","] = ", ",
["/"] = "/",
["_"] = " ",
["~"] = " ~ ",
["→"] = " → ",
}
--[==[ intro:
The purpose of this module is to facilitate implementation of templates that can have arguments specified either through
inline modifiers or separate parameters. There are two types of templates supported: those that take a list of items
with associated properties, which can be specified either through indexed separate parameters (e.g. {{para|t2}},
{{para|pos3}}) or inline modifiers (`<t:...>`, `<pos:...>`, etc.); and those that take a single term, whose properties
can be specified through non-indexed separate parameters (e.g. {{para|t}} or {{para|pos}}) or inline modifiers. Both
types of templates can optionally have subitems in the term parameter(s), where the subitems are typically (but not
necessarily) separated with commas and each subitem can have its own inline modifiers.
Some examples of templates that take a list of items are {{tl|alter}}/{{tl|alt}}; {{tl|synonyms}}/{{tl|syn}},
{{tl|antonyms}}/{{tl|ant}}, and other "nyms" templates; {{tl|col}}, {{tl|col2}}, {{tl|col3}}, {{tl|col4}} and other
column templates; {{tl|descendant}}/{{tl|desc}}; {{tl|affix}}/{{tl|af}}, {{tl|prefix}}/{{tl|pre}} and related *fix
templates; {{tl|affixusex}}/{{tl|afex}} and related templates; {{tl|IPA}}; {{tl|homophones}}; {{tl|rhymes}}; and several
others.
Examples of templates that take a single item are form-of templates ({{tl|inflection of}}/{{tl|infl of}},
{{tl|form of}}, and specific templates such as {{tl|alt form}}/{{tl|alternative form of}},
{{tl|abbr of}}/{{tl|abbreviation of}}, {{tl|clipping of}}, and many others); for etymology templates
({{tl|bor}}/{{tl|borrowed}}, {{tl|der}}/{{tl|derived}}, etc. as well as `misc_variant` templates like {{tl|ellipsis}},
{{tl|abbrev}}, {{tl|clipping}}, {{tl|reduplication}} and the like); and other templates that take an argument structure
similar to {{tl|l}} or {{tl|m}}.
This module can be thought of as a combination of [[Module:parameters]] (which parses template parameters, and in
particular handles the separate parameter versions of the properties) and `parse_inline_modifiers()` in
[[Module:parse utilities]] (which parses inline modifiers).
The two main entry points are `parse_list_with_inline_modifiers_and_separate_params()` (for templates that take a list
of items) and `parse_term_with_inline_modifiers_and_separate_params()` (for templates that take a single item). However,
there are other functions provided, e.g. to initialize the `param_mods` structure that is passed to the two entry
points.
The typical workflow for using `parse_list_with_inline_modifiers_and_separate_params()` looks as follows (a slightly
simplified version of the code in [[Module:nyms]]):
{
local export = {}
local parameter_utilities_module = "Module:parameter utilities"
...
-- Entry point to be invoked from a template.
function export.show(frame)
local parent_args = frame:getParent().args
-- Parameters that don't have corresponding inline modifiers. Note in particular that the parameter corresponding to
-- the items themselves must be specified this way, and must specify either `allow_holes = true` (if the user can
-- omit terms, typically by specifying the term using |altN= or <alt:...> so that they remain unlinked) or
-- `disallow_holes = true` (if omitting terms is not allowed). (If neither `allow_holes` nor `disallow_holes` is
-- specified, an error is thrown in parse_list_with_inline_modifiers_and_separate_params().)
local params = {
[1] = {required = true, type = "language", default = "und"},
[2] = {list = true, allow_holes = true, required = true, default = "term"},
}
local m_param_utils = require(parameter_utilities_module)
-- This constructs the `param_mods` structure by adding well-known groups of parameters (such as all the parameters
-- associated with based on full_link() in [[Module:links]], with default properties that can be overridden. This is
-- easier and less error-prone than manually specifying the `param_mods` structure (see below for how this would
-- look). Here, we specify the group "link" (consisting of all the link parameters for use with full_link()), group
-- "ref" (which adds the "ref" parameter for specifying references), group "l" (which adds the "l" and "ll"
-- parameters for specifying labels) and group "q" (which adds the "q" and "qq" parameters for specifying regular
-- qualifiers). By default, labels and qualifiers have `separate_no_index` set so that e.g. |q1= is distinct from
-- |q=, the former specifying the left qualifier for the first item and the latter specifying the overall left
-- qualifier. For compatibility, we override the `separate_no_index` setting for the group "q", which causes |q= and
-- |q1= to be the same, and likewise for |qq= and |qq1=. Finally, also for compatibility, we add an "lb" parameter
-- that is an alias of "ll" (in all respects; |lb= is the same as |ll=, |lb1= is the same as |ll1=, <lb:...> is the
-- same as <ll:...>, etc.).
local param_mods = m_param_utils.construct_param_mods {
{group = {"link", "ref", "l"}},
{group = "q", separate_no_index = false},
{param = "lb", alias_of = "ll"},
}
-- This processes the raw arguments in `parent_args`, parses inline modifiers and creates corresponding objects
-- containing the property values specified either through inline modifiers or separate parameters.
local items, args = m_param_utils.parse_list_with_inline_modifiers_and_separate_params {
params = params,
param_mods = param_mods,
raw_args = parent_args,
termarg = 2,
parse_lang_prefix = true,
track_module = "nyms",
lang = 1,
sc = "sc.default",
}
local lang = args[1]
-- Now do the actual implementation of the template. Generally this should be split into a separate function, often
-- in a separate module (if the implementation goes in [[Module:foo]], the template interface code goes in
-- [[Module:foo/templates]]).
...
}
The `param_mods` structure controls the properties that can be specified by the user for a given item, and is
conceptually very similar to the `param_mods` structure used by `parse_inline_modifiers()`. The key is the name of the
parameter (e.g. {"t"}, {"pos"}) and the value is a table with optional elements as follows:
* `item_dest`, `store`: Same as the corresponding fields in the `param_mods` structure passed to
`parse_inline_modifiers()`.
* `type`, `set`, `sublist`, `convert` and associated fields such as `family` and `method`: These control parsing and
conversion of the raw values specified by the user and have the same meaning as in [[Module:parameters]] and also in
`parse_inline_modifiers()` (which delegates the actual conversion to [[Module:parameters]]). These fields — and for
that matter, all fields other than `item_dest`, `store` and `overall` — are forwarded to the `process()` function in
[[Module:parameters]].
* `alias_of`: This parameter is an alias of some other parameter. This spec is recognized only by `process()` in
[[Module:parameters]], and not by `parse_inline_modifiers()`; to set up an alias in `parse_inline_modifiers()`, you
need to make sure (using `item_dest`) that both the alias and aliasee modifiers store their values in the same
location, and you need to copy the remaining properties from the aliasee's spec to the aliasing modifier's spec. All
of this happens automatically if you generate the `param_mods` structure using `construct_param_mods()`.
* `require_index`: This means that the non-indexed parameter version of the property is not recognized. E.g. in the
case of the {"sc"} property, use of the {{para|sc}} parameter would result in an error, while {{para|sc1}} is
recognized and specifies the {"sc"} property for the first item. The default, if neither `require_index` nor
`separate_no_index` is given, is for {{para|sc}} and {{para|sc1}} to mean the same thing (both would specify the
{"sc"} property of the first item). Note that `require_index` and `separate_no_index` are mutually exclusive, and if
either one is specified during processing by `construct_param_mods()`, the other one is automaticallly turned off.
* `separate_no_index`: This means that e.g. the {{para|sc}} parameter is distinct from the {{para|sc1}} parameter
(and thus from the `<sc:...>` inline modifier on the first item). This is typically used to distinguish an overall
version of a property from the corresponding item-specific property on the first item. (In this case, for example,
{{para|sc}} overrides the script code for all items, while {{para|sc1}} overrides the script code only for the
first item.) If not given, and if `require_index` is not given, {{para|sc}} and {{para|sc1}} would have the same
meaning and refer to the item-specific property on the first item. When this is given, the overall value can be
accessed using the `.default` field of the property value in `args`, e.g. in this case `args.sc.default`. Note that
(as mentioned above) `require_index` and `separate_no_index` are mutually exclusive, and if either one is specified
during processing by `construct_param_mods()`, the other one is automaticallly turned off.
* `list`, `allow_holes`, `disallow_holes`: These should '''not''' be given. `list` and `allow_holes` are automatically
set for all parameter specs added to the `params` structure used by `process()` in [[Module:parameters]], and
`disallow_holes` clashes with `allow_holes`.
For the above workflow example, the call to `construct_param_mods()` generates the following `param_mods` structure:
{
local param_mods = {
-- the parameters generated by group "link"
alt = {},
t = {
-- [[Module:links]] expects the gloss in "gloss".
item_dest = "gloss",
},
gloss = {
alias_of = "t",
},
tr = {},
ts = {},
g = {
-- [[Module:links]] expects the genders in "genders".
item_dest = "genders",
type = "genders",
},
pos = {},
ng = {},
lit = {},
id = {},
sc = {
separate_no_index = true,
type = "script",
},
-- the parameters generated by group "ref"
ref = {
item_dest = "refs",
type = "references",
},
-- the parameters generated by group "l"
l = {
type = "labels",
separate_no_index = true,
},
ll = {
type = "labels",
separate_no_index = true,
},
-- the parameters generated by group "q"; note that `separate_no_index = true` would be set, but is overridden
-- (specifying `separate_no_index = false` in the `param_mods` structure is equivalent to not specifying it at all)
q = {
type = "qualifier",
separate_no_index = false,
},
qq = {
type = "qualifier",
separate_no_index = false,
},
infl = {
type = "form of tags",
separate_no_index = true,
},
-- the parameter generated by the individual "lb" parameter spec; note that only `alias_of` was explicitly given,
-- while `item_dest` is automatically set so that inline modifier <lb:...> stores into the same place as <ll:...>,
-- and the other specs are copied from the `ll` spec so `lb` works like `ll` in all regards
lb = {
alias_of = "ll",
item_dest = "ll",
type = "labels",
separate_no_index = true,
},
}
}
]==]
local qualifier_spec = {
type = "qualifier",
separate_no_index = true,
}
local label_spec = {
type = "labels",
separate_no_index = true,
}
local form_of_spec = {
type = "form of tags",
separate_no_index = true,
}
local recognized_param_mod_groups = {
link = {
alt = {},
t = {
-- [[Module:links]] expects the gloss in "gloss".
item_dest = "gloss",
},
gloss = {
alias_of = "t",
},
tr = {},
ts = {},
g = {
-- [[Module:links]] expects the genders in "genders".
item_dest = "genders",
type = "genders",
},
pos = {},
ng = {},
lit = {},
id = {},
sc = {
separate_no_index = true,
type = "script",
},
},
lang = {
lang = {
require_index = true,
type = "language",
},
},
q = {
q = qualifier_spec,
qq = qualifier_spec,
},
a = {
a = label_spec,
aa = label_spec,
},
l = {
l = label_spec,
ll = label_spec,
},
infl = {
infl = form_of_spec,
},
ref = {
ref = {
item_dest = "refs",
type = "references",
},
},
}
local function merge_param_mod_settings(orig, additions)
local merged = shallow_copy(orig)
for k, v in pairs(additions) do
merged[k] = v
if k == "require_index" then
merged.separate_no_index = nil
elseif k == "separate_no_index" then
merged.require_index = nil
end
end
merged.default = nil
merged.group = nil
merged.param = nil
merged.exclude = nil
merged.include = nil
return merged
end
local function verify_type(spec, param, typ1, typ2)
if not spec[param] then
return
end
local val = spec[param]
if type(val) ~= typ1 and (not typ2 or type(val) ~= typ2) then
internal_error(("Parameter `%s` must be a %s%s but saw a %s"):format(param, typ1, typ2 and " or " .. typ2 or "",
type(val)), spec)
end
end
local function verify_well_constructed_spec(spec)
local num_control = (spec.default and 1 or 0) + (spec.group and 1 or 0) + (spec.param and 1 or 0)
if num_control == 0 then
internal_error(
"Spec passed to construct_param_mods() must have either the `default`, `group` or `param` keys set", spec)
end
if num_control > 1 then
internal_error(
"Exactly one of `default`, `group` or `param` must be set in construct_param_mods() spec", spec)
end
if spec.list or spec.allow_holes then
-- FIXME: We need to support list = "foo" for list parameters that are stored in e.g. 2=, foo2=, foo3=, etc.
internal_error("`list` and `allow_holes` may not be set; they are automatically set when constructing the " ..
"corresponding spec in the `params` object passed to [[Module:parameters]]", spec)
end
if spec.disallow_holes then
internal_error("`disallow_holes` may not be set; it conflicts with `allow_holes`, which is automatically " ..
"set when constructing the corresponding spec in the `params` object passed to [[Module:parameters]]", spec)
end
if spec.include and spec.exclude then
internal_error("Saw both `include` and `exclude` in the same spec", spec)
end
if (spec.include or spec.exclude) and not spec.group then
internal_error(
"`include` and `exclude` can only be specified along with `group`, not with `default` or `param`", spec)
end
verify_type(spec, "group", "string", "table")
verify_type(spec, "param", "string", "table")
verify_type(spec, "include", "table")
verify_type(spec, "exclude", "table")
end
--[==[
Construct the `param_mods` structure used in parsing arguments and inline modifiers from a list of specifications.
A sample invocation (a slightly simplified version of the actual invocation associated with {{tl|affix}} and related
templates) looks like this:
{
local param_mods = require("Module:parameter utilities").construct_param_mods {
-- We want to require an index for all params (or use separate_no_index, which also requires an index for the
-- param corresponding to the first item).
{default = true, require_index = true},
{group = {"link", "ref", "lang", "q", "l"}},
-- Override these two to have separate_no_index.
{param = {"lit", "pos"}, separate_no_index = true},
}
}
Each specification either sets the default value for further parameter specs or adds one or more parameters. Parameters
can be added directly using `param`, or groups of predefined parameters can be added using `group`. Specifications are
one of three types:
# Those that set the default properties for future-added parameters. These contain {default = true} as one of the
properties of the spec. Specs are processed in order and you can change the defaults mid-way through.
# Those that add the parameters associated with one or more pre-defined groups. These contain {group = "group"} or
{group = {"group1", "group2", ...}}. The pre-defined parameter groups and their associated properties are listed
below. The pre-defined properties of parameters in a group override properties associated with a {default = true}
spec, and are in turn overridden by any properties given directly in the spec itself. Note as well that setting the
`separate_no_index` property will automatically cause the `require_index` property to be unset and vice-versa, as the
two are mutually exclusive. (This happens in the example above, where the {separate_no_index = true} setting
associated with the params {"lit"} and {"pos"} cancels out the {require_index = true} default setting, as well as less
obviously with the pre-defined {"sc"} property of the {"link"} group, the {"q"} and {"qq"} properties of the {"q"}
group, and the {"l"} and {"ll"} properties of the {"l"} group, all of which have an associated pre-defined property
{separate_no_index = true}, which overrides and cancels out the {require_index = true} default setting. Finally, when
adding the parameters of a group, you can request the only a subset of the parameters be added using either the
`include` or `exclude` properties, each of whose values is a list of parameters that specify (respectively) the
parameters to include (all other parameters of the group are excluded) or to exclude (all other parameters of the
group are included). This is used, for example, in [[Module:romance etymology]] and [[Module:it-etymology]], which
specify {group = "link", exclude = {"tr", "ts", "sc"}} to exclude link parameters that aren't relevant to Latin-script
languages such as the Romance languages, and conversely in [[Module:IPA/templates]], which specifies
{group = "link", include = {"t", "gloss", "pos"}} to include only the specified parameters for use with {{tl|IPA}}.
# Those that add individual parameters. These contain {param = "param"} or {param = {"param1", "param2", ...}}, the
latter syntax used to control a set of parameters together. The resulting spec is formed by initializing the
parameter's settings with any previously-specified default properties (using a spec containing {default = true}) if
the parameter hasn't already been initialized, and then overriding the resulting settings with any settings given
directly in the specification. In the above example, the {"lit"} and {"pos"} parameters were previously initialized
through the {"link"} group (specified in the second of the three specifications) but ended up with
{require_index = true} due to the {default = true} spec (the first of the three specifications). We override these
two parameters to have {separate_no_index = true} (which, as mentioned above, cancels out {require_index = true}).
This is done so that {{tl|affix}} and related templates have {{para|pos}} and {{para|lit}} parameters distinct from
{{para|pos1}} and {{para|lit1}}, which are used to specify an overall part of speech (which applies to all parts of
the affix, as opposed to applying to just one element of the expression) or a literal definition for the entire
expression (instead of just for one element of the expression).
The built-in parameter groups are as follows:
{|class="wikitable"
! Group !! Group meaning !! Parameter !! Parameter meaning !! Default properties
|-
| rowspan=11| `link`
| rowspan=11| link parameters; same as those available on {{tl|l}}, {{tl|m}} and other linking templates
| `alt` || display text, overriding the term's display form || —
|-
| `t` || gloss (translation) of a non-English term || {item_dest = "gloss"}
|-
| `gloss` || gloss (translation); same as `t` || {alias_of = "t"}
|-
| `tr` || transliteration of a non-Latin-script term; only needed if the automatic transliteration is incorrect or unavailable (e.g. in Hebrew, which doesn't have automatic transliteration) || —
|-
| `ts` || transcription of a non-Latin-script term, if the transliteration is markedly different from the actual pronunciation; should not be used for IPA pronunciations || —
|-
| `g` || comma-separated list of genders; whitespace may surround the comma and will be ignored || {item_dest = "genders", type = "genders"}
|-
| `pos` || part of speech for the term || —
|-
| `ng` || arbitrary non-gloss descriptive text for the term || —
|-
| `lit` || literal meaning (translation) of the term || —
|-
| `id` || a sense ID for the term, which links to anchors on the page set by the {{tl|senseid}} template || —
|-
| `sc` || the script code (see [[Wiktionary:Scripts]]) for the script that the term is written in; rarely necessary, as the script is autodetected (in most cases, correctly) || {separate_no_index = true, type = "script"}
|-
| rowspan=2| `q`
| rowspan=2| left and right normal qualifiers (as displayed using {{tl|q}})
| `q` || left normal qualifier || {separate_no_index = true, type = "qualifier"}
|-
| `qq` || right normal qualifier || {separate_no_index = true, type = "qualifier"}
|-
| rowspan=2| `a`
| rowspan=2| left and right accent qualifiers (as displayed using {{tl|a}})
| `a` || comma-separated list of left accent qualifiers; whitespace must not surround the comma || {separate_no_index = true, type = "labels"}
|-
| `aa` || comma-separated list of right accent qualifiers; whitespace must not surround the comma || {separate_no_index = true, type = "labels"}
|-
| rowspan=2| `l`
| rowspan=2| left and right labels (as displayed using {{tl|lb}}, but without categorizing)
| `l` || comma-separated list of left labels; whitespace must not surround the comma || {separate_no_index = true, type = "labels"}
|-
| `ll` || comma-separated list of right labels; whitespace must not surround the comma || {separate_no_index = true, type = "labels"}
|-
| `ref`
| reference(s) (in the format accepted by [[Module:references]]; see also the documentation for the {{para|ref}} parameter to {{tl|IPA}})
| `ref` || one or more references, in the format accepted by [[Module:references]] || {item_dest = "refs", type = "references"}
|-
| `lang`
| language for an individual term (provided for compatibility; it is preferred to specify languages for individual terms using language prefixes instead)
| `lang` || language code (see [[Wiktionary:Languages]]) for the term || {require_index = true, type = "language"}
|}
]==]
function export.construct_param_mods(specs)
local param_mods = {}
local default_specs = {}
for _, spec in ipairs(specs) do
verify_well_constructed_spec(spec)
if spec.default then
-- This will have an extra `default` field in it, but it will be erased by merge_param_mod_settings()
default_specs = spec
else
if spec.group then
local groups = spec.group
if type(groups) ~= "table" then
groups = {groups}
end
local include_set
if spec.include then
include_set = list_to_set(spec.include)
end
local exclude_set
if spec.exclude then
exclude_set = list_to_set(spec.exclude)
end
for _, group in ipairs(groups) do
local group_specs = recognized_param_mod_groups[group]
if not group_specs then
internal_error(("Unrecognized built-in param mod group '%s'"):format(group), spec)
end
for group_param, group_param_settings in pairs(group_specs) do
local include_param
if include_set then
include_param = include_set[group_param]
elseif exclude_set then
include_param = not exclude_set[group_param]
else
include_param = true
end
if include_param then
local merged_settings = merge_param_mod_settings(merge_param_mod_settings(
param_mods[group_param] or default_specs, group_param_settings), spec)
param_mods[group_param] = merged_settings
end
end
end
end
if spec.param then
local params = spec.param
if type(params) ~= "table" then
params = {params}
end
for _, param in ipairs(params) do
local settings = merge_param_mod_settings(param_mods[param] or default_specs, spec)
-- If this parameter is an alias of another parameter, we need to copy the specs from the other
-- parameter, since parse_inline_modifiers() doesn't know about `alias_of` and having the specs
-- duplicated won't cause problems for [[Module:parameters]]. We also need to set `item_dest` to
-- point to the `item_dest` of the aliasee (defaulting to the aliasee's value itself), so that
-- both modifiers write to the same location. Note that this works correctly in the common case of
-- <t:...> with `item_dest = "gloss"` and <gloss:...> with `alias_of = "t"`, because both will end
-- up with `item_dest = "gloss"`.
local aliasee = settings.alias_of
if aliasee then
local aliasee_settings = param_mods[aliasee]
if not aliasee_settings then
internal_error(("Undefined aliasee '%s'"):format(aliasee), spec)
end
for k, v in pairs(aliasee_settings) do
if settings[k] == nil then
settings[k] = v
end
end
if settings.item_dest == nil then
settings.item_dest = aliasee
end
end
param_mods[param] = settings
end
end
end
end
return param_mods
end
-- Return true if `k` is a "built-in" (specially recognized) key in a `param_mod` specification. All other keys
-- are forwarded to the structure passed to [[Module:parameters]].
local function param_mod_spec_key_is_builtin(k)
return k == "item_dest" or k == "overall" or k == "store"
end
--[==[
Convert the properties in `param_mods` into the appropriate structures for use by `process()` in [[Module:parameters]]
and store them in `params`. If `overall_only` is given, only store the properties in `param_mods` that correspond to
overall (non-item-specific) parameters. Currently this only happens when `separate_no_index` is specified.
]==]
function export.augment_params_with_modifiers(params, param_mods, overall_only)
if overall_only then
for param_mod, param_mod_spec in pairs(param_mods) do
if overall_only == "always" or param_mod_spec.separate_no_index then
local param_spec = {}
for k, v in pairs(param_mod_spec) do
if k ~= "separate_no_index" and k ~= "require_index" and not param_mod_spec_key_is_builtin(k) then
param_spec[k] = v
end
end
params[param_mod] = param_spec
end
end
else
local list_with_holes
-- Add parameters for each term modifier.
for param_mod, param_mod_spec in pairs(param_mods) do
local param_spec
for k, v in pairs(param_mod_spec) do
if not param_mod_spec_key_is_builtin(k) then
if param_spec == nil then
param_spec = {list = true}
end
param_spec[k] = v
end
end
if param_spec == nil then
if list_with_holes == nil then
list_with_holes = {list = true, allow_holes = true}
end
param_spec = list_with_holes
elseif param_spec.alias_of == nil then
param_spec.allow_holes = true
end
params[param_mod] = param_spec
end
end
end
--[==[
Return true if `k`, a key in an item, refers to a property of the item (is not one of the specially stored values).
Note that `lang` and `sc` are considered properties of the item, although `lang` is set when there's a language
prefix and both `lang` and `sc` may be set from default values specified in the `data` structure passed into
`parse_list_with_inline_modifiers_and_separate_params()` and `parse_term_with_inline_modifiers_and_separate_params()`.
If you don't want these treated as property keys, you need to check for them yourself.
]==]
function export.item_key_is_property(k)
return k ~= "term" and k ~= "termlang" and k ~= "termlangs" and k ~= "itemno" and k ~= "orig_index" and
k ~= "separator"
end
-- Fetch the argument in `args` corresponding to `index_or_value`, which may be a string of the form "foo.default"
-- (requesting the value of `args["foo"].default`); a string or number (requesting the value at that key); a function of
-- one argument (`args`), which returns the argument value; or the value itself. Return the resulting value and the
-- parameter in `args` that the value came from, or nil if unknown (i.e. a function or direct value was specified).
local function fetch_argument(args, index_or_value)
if not index_or_value then
return index_or_value, nil
end
local index_or_value_type = type(index_or_value)
if index_or_value_type == "string" then
if index_or_value:sub(-8) == ".default" then
local index_without_default = index_or_value:sub(1, -9)
local arg_obj = fetch_argument(args, index_without_default)
if type(arg_obj) ~= "table" then
internal_error(("Requested that the '.default' key of argument `%s` be fetched, but argument value is undefined or not a table"):
format(index_without_default), arg_obj)
end
return arg_obj.default, index_without_default
end
if index_or_value:match("^%d+$") then
index_or_value = tonumber(index_or_value)
end
return args[index_or_value], index_or_value
elseif index_or_value_type == "number" then
return args[index_or_value], index_or_value
elseif is_callable(index_or_value) then
return index_or_value(args), nil
end
return index_or_value, nil
end
function export.generate_obj_maybe_parsing_lang_prefix(data)
return require(parse_utilities_module).generate_obj_maybe_parsing_lang_prefix(data)
end
-- Subfunction of parse_list_with_inline_modifiers_and_separate_params() and
-- parse_term_with_inline_modifiers_and_separate_params(), validating certain argument-related fields that are shared
-- among the two functions.
local function validate_argument_related_fields(data)
if not data.termarg then
internal_error("`data.termarg` must be given, indicating which argument contains the terms to be parsed", data)
end
if not data.param_mods then
internal_error("`data.param_mods` must be given, indicating the allowed inline modifiers and separate " ..
"parameters to copy", data)
end
local subitem_param_handling = data.subitem_param_handling or "only"
if subitem_param_handling ~= "only" and subitem_param_handling ~= "first" and subitem_param_handling ~= "last" then
internal_error("Unrecognized value for `data.subitem_param_handling`, should be 'first', 'last' or 'only'",
subitem_param_handling)
end
if data.raw_args then
if data.processed_args then
internal_error("Only one of `data.raw_args` and `data.processed_args` can be specified", data)
end
if not data.params then
internal_error("When `data.raw_args` is specified, so must `data.params`, so that the raw arguments " ..
"can be parsed", data)
end
if data.params[data.termarg] == nil then
internal_error("There must be a spec in `data.params` corresponding to `data.termarg`", data)
end
else
if not data.processed_args then
internal_error("Either `data.raw_args` or `data.processed_args` must be specified", data)
end
if data.params then
internal_error("When `data.processed_args` is specified, `data.params` should not be specified", data)
end
end
end
local function argval_missing(val)
return val == nil or type(val) == "table" and next(val) == nil
end
-- Subfunction of parse_list_with_inline_modifiers_and_separate_params() and
-- parse_term_with_inline_modifiers_and_separate_params(). After parsing inline modifiers, copy the separate parameters
-- to the generated object (or to the appropriate subobject if there are multiple). `data` contains the following
-- fields:
--
-- `args`: The separate-parameter argument structure.
-- `param_mods`: The structure describing the inline modifiers.
-- `itemno`: The logical item number of the term being processed, or nil if there's only a single term.
-- `termobj`: The object to store the inline modifiers into. If there are subitems, they are in the `terms` field;
-- otherwise the properties are stored directly into `termobj`.
-- `has_subitems`: True if there are subitems.
-- `subitem_separator_map`: If `has_subitems` and this is specified, controls the assignment of the `separator` field
-- in subitems. If not specified or a delimiter is not in the map, it is copied unchanged.
-- `lang`: Language object to store into all items.
-- `sc`: Script object to store into all items, or nil.
-- `subitem_param_handling`: "only", "first" or "last", indicating what to do if there are multiple subitems.
-- `allow_conflicting_inline_mods_and_separate_params`: If true, specifying a value for both an inline modifier and
-- corresponding separate parameter is allowed, and the inline modifier takes precedence. Otherwise, an error
-- occurs.
-- `postprocess_termobj`: Optional function called on all items at the end, to do any postprocessing. Called with one
-- argument, the object to postprocess.
local function copy_separate_params_to_termobj_and_postprocess(data)
local args, param_mods, itemno, termobj = data.args, data.param_mods, data.itemno, data.termobj
local function set_lang_and_sc(termobj)
-- Set these after parsing inline modifiers, not in generate_obj(), otherwise we'll get an error in
-- parse_inline_modifiers() if we try to use <lang:...> or <sc:...> as inline modifiers.
termobj.lang = termobj.lang or data.lang
termobj.sc = termobj.sc or data.sc
end
local function fetch_separate_param(args, paramkey, itemno)
local argval = args[paramkey]
-- Careful with argument values that may be `false`.
if argval and itemno then
argval = argval[itemno]
end
return argval
end
-- Copy separate parameters to a given object.
local function copy_separate_params_to_termobj(fetch_destobj)
for param_mod, param_mod_spec in pairs(param_mods) do
local dest = param_mod_spec.item_dest or param_mod
-- Don't do anything with the `sc` param, which will get overwritten below; we don't
-- want it to cause an error if there are multiple subitems.
if dest ~= "sc" then
local argval = fetch_separate_param(args, param_mod, itemno)
if not argval_missing(argval) then
local destobj = fetch_destobj(param_mod, param_mod_spec, dest)
-- Don't overwrite a value already set by an inline modifier.
if argval_missing(destobj[dest]) then
destobj[dest] = argval
elseif not data.allow_conflicting_inline_mods_and_separate_params then
error(("Can't specify a value for separate parameter %s%s= because there is " ..
"already an inline modifier <%s:...> specifying a value for the term"):format(
param_mod, itemno or "", param_mod))
end
end
end
end
end
if data.has_subitems then
-- If there are any separate indexed parameters, we need to copy them to the first, last or only
-- subitem, depending on the value of `data.subitem_param_handling` (which defaults to 'only',
-- meaning it's an error if there are multiple subitems). Do this before calling
-- postprocess_termobj() because the latter sets .lang and .sc and we want the user to be able to
-- set separate langN= and scN= parameters.
-- If there was no term, `termobj.terms` will not exist; make it exist to make the callers' lives easier.
if not termobj.terms then
termobj.terms = {}
end
-- Compute whether any of the separate indexed params exist for this index.
local any_param_at_index
for param_mod in pairs(param_mods) do
local argval = fetch_separate_param(args, param_mod, itemno)
if not argval_missing(argval) then
any_param_at_index = true
break
end
end
-- If there was no term, but there's a separate parameter, we need to create an empty subitem.
if any_param_at_index and not termobj.terms[1] then
termobj.terms[1] = {}
end
local function fetch_destobj(param_mod, param_mod_spec, dest)
if param_mod_spec.overall then
return termobj
end
if data.subitem_param_handling == "only" and termobj.terms[2] then
error(("Can't specify a value for separate parameter %s%s= because there are " ..
"multiple subitems (%s) in the term; use an inline modifier"):format(
param_mod, itemno or "", #termobj.terms))
end
local termind
-- q/a/l need to go at the beginning and qq/aa/ll/refs at the end, regardless; otherwise, respect
-- `data.subitem_param_handling`.
if dest == "q" or dest == "a" or dest == "l" then
termind = 1
elseif dest == "qq" or dest == "aa" or dest == "ll" or dest == "refs" then
termind = #termobj.terms
elseif data.subitem_param_handling == "only" or data.subitem_param_handling == "first" then
termind = 1
else
termind = #termobj.terms
end
return termobj.terms[termind]
end
copy_separate_params_to_termobj(fetch_destobj)
for i, subitem in ipairs(termobj.terms) do
set_lang_and_sc(subitem)
if subitem.delimiter then
subitem.separator = i == 1 and "" or
data.subitem_separator_map and data.subitem_separator_map[subitem.delimiter] or
subitem.delimiter
end
if data.postprocess_termobj then
data.postprocess_termobj(subitem, data)
end
end
else
-- Copy all the parsed term-specific parameters into `termobj`.
copy_separate_params_to_termobj(function(param_mod, dest) return termobj end)
set_lang_and_sc(termobj)
if data.postprocess_termobj then
data.postprocess_termobj(termobj, data)
end
end
end
local function postprocess_termobj(item, data)
if not (data.disallow_custom_separators or data.use_semicolon) then
if data.has_subitems and item.separator and item.separator:find(",", nil, true) then
data.use_semicolon = true
else
-- If the displayed term (from .term/etc. or .alt) has an embedded comma, use a semicolon to
-- join the terms.
local term_text = item[data.term_dest] or item.alt
if term_text and term_text:find(",", nil, true) then
data.use_semicolon = true
end
end
end
end
--[==[
Parse a list of terms, each of which may have properties specified using inline modifiers or separate parameters. This
function is intended for parsing the arguments of templates like {{tl|syn}}, {{tl|ant}} and related ''*nym'' templates;
alternative-form templates {{tl|alt}}/{{tl|alter}}; affix templates like {{tl|af}}/{{tl|affix}},
{{tl|com}}/{{tl|compound}}, etc.; affix usex templates like {{tl|afex}}/{{tl|affixusex}}; name templates like
{{tl|name translit}}; column templates like {{tl|col}}; pronunciation templates like {{tl|rhyme}}/{{tl|rhymes}} and
{{tl|hmp}}/{{tl|homophones}}; etc. In these templates there are one or more terms specified using numeric parameters, and
associated separate parameters specifying per-term properties such as {{para|t1}}, {{para|t2}}, {{para|t3}}, ... for the
gloss of the first, second, third, ... term respectively. All such properties can also be specified through inline
modifiers attached directly to each term (`<t:...>`, `<pos:...>`, etc.). Normally it is an error if both an inline
modifier and separate parameter for the same value are given, but this can be overridden (in which case inline modifiers
take precedence over separate parameters when both occur).
For an example of a typical workflow involving this function, see the comment at the top of this file.
Some notable properties of this function:
# Processing of the raw frame parent args using `process()` in [[Module:parameters]] can occur either inside of this
function (the usual workflow) or outside of this function (for more complex cases). In the former case the raw parent
args are passed in along with a partially built `params` structure of the sort required by [[Module:parameters]],
containing only the term list itself along with any other parameters that are '''not''' term properties (such as
a language code in {{para|1}} and boolean flags like {{para|nocat}}, {{para|nocap}}, etc.). This structure is
''augmented'' with list parameters, one for each per-term property, and [[Module:parameters]] is invoked. In the
latter case where raw argument processing is done by the caller, they must build the partial `params` structure;
augment it themselves using `augment_params_with_modifiers()`; call [[Module:parameters]] themselves; and pass in the
processed arguments. In both cases, the return value of this function contains three values: a list of objects, one
per term, specifying the term and all properties; the processed arguments structure, so that the non-term-property
arguments can be processed as appropriate; and an object containing miscellaneous global computed properties
(currently only `use_semicolon`; see below).
# Optionally, each term can consist of a number of ''subitems'' separated by delimiters (usually a comma, but the
possible delimiter or delimiters are controllable). Each subitem can have its own inline modifiers. This functionality
is used, for example, by {{tl|col}} and variants, which allow each row to have comma-separated or tilde-separated
subitems. When this feature is invoked, the format of the per-term object changes; instead of directly being an object
describing the term and its properties, it is an object with a `terms` field containing a list of per-subitem objects
along with other top-level fields describing per-term properties. By default, if there are separate parameters
specified along with multiple subitems, an error occurs, but this is controllable; currently, you can request that the
parameters be assigned to the first or last subitem.
# By default, special ''separator'' arguments may be present, mixed in among regular term arguments. Examples of such
separator arguments are (by default; this can be overridden) a bare semicolon, specifying that the terms on either
side should be separated by a semicolon instead of a comma (indicating a higher-level grouping); a bare tilde,
replacing the comma separator with a tilde (indicating that the terms on either side are alternants); and a bare
underscore, replacing the comma separator with a space. Separator arguments are ignored when numbering the separate
parameters. You disable the separator argument handling entirely if it doesn't make sense to have this (e.g. in
{{tl|af}}/{{tl|affix}}, where the separator is always a {{cd|+}} sign).
`data` is an object containing several possible fields.
1. Fields that are required or recommended (usually related to argument processing):
* `raw_args` ('''required''' unless `processed_args` is specified): The raw arguments, normally fetched from
{frame:getParent().args}. They are parsed using `process()` in [[Module:parameters]]. Most callers pass in raw
arguments.
* `processed_args`: The object of parsed arguments returned by `process()` in [[Module:parameters]]. One (but not both)
of `raw_args` and `processed_args` must be set.
* `param_mods` ('''required'''): A structure describing the possible inline modifiers and their properties. See the
introductory comment above. Most often, this is generated using `construct_param_mods()` rather than specified
manually.
* `params` ('''required''' unless `processed_args` is specified): A structure describing the possible parameters,
'''other than''' the ones that are separate-parameter equivalents of inline modifiers. This is automatically
"augmented" with the separate-parameter equivalents of the inline modifiers described in `param_mods` prior to parsing
the raw arguments with [[Module:parameters]]. '''WARNING:''' This structure is destructively modified, both by the
"augmentation" process of adding separate-parameter equivalents of inline modifiers, and by the processing done by
[[Module:parameters]] itself. (Nonetheless, substructures can safely be shared in this structure, and will be
correctly handled.)
* `termarg` ('''required'''): The argument containing the first item with attached inline modifiers to be parsed.
Usually a numeric value such as {1} or {2}.
* `track_module` ('''recommended'''): The name of the calling module, for use in adding tracking pages that are used
internally to track pages containing template invocations with certain properties. Example properties tracked are
missing items with corresponding properties as well as missing items without corresponding properties (which are
skipped entirely). To find out the exact properties tracked and the name of the tracking pages, read the code.
* `lang` ('''recommended'''): The language object for the language of the items, or the name of the argument to fetch
the object from. It is not strictly necessary to specify this, as this function only initializes items based on inline
modifiers and separate arguments and doesn't actually format the resulting items. However, if specified, it is used
for certain purposes:
*# It specifies the default for the `lang` property of returned objects if not otherwise set (e.g. by a language
prefix).
*# It is used to initialize an internal cache for speeding up language-code parsing (primarily useful if the same
language code may appear in several items, such as with {{tl|col}} and related templates).
The value of `lang` can be any of the following:
* If a string of the form "foo.default", it is assumed to be requesting the value of `args["foo"].default`.
* Otherwise, if a string or number, it is assumed to be requesting the value of `args` at that key. Note that if the
string is in the form of a number (e.g. "3"), it is normalized to a number prior to fetching (this also happens with
a spec like "2.default").
* Otherwise, if a function, it is assumed to be a function to return the argument value given `args`, which is passed
to the function as its only argument.
* Otherwise, it is used directly.
* `sc` ('''recommended'''): The script object for the items, or the name of the argument to fetch the object from. The
possible values and their handling are the same as with `lang`. In general, as with `lang`, it is not strictly
necessary to specify this. However, if specified, it is used to supply the default for the `sc` property of returned
items if not otherwise set (e.g. by the {{para|sc<var>N</var>}} parameter or `<sc:...>` inline modifier). The most
common value is {"sc.default"}.
2. Other argument-related fields:
* `process_args_before_parsing`: An optional function to apply further processing to the processed `args` structure
returned by [[Module:parameters]], before parsing inline modifiers. This is passed one argument, the processed
arguments. It should make modifications in-place.
* `term_dest`: The field to store the value of the item itself into, after inline modifiers and (if allowed) language
prefixes are stripped off. Defaults to {"term"}.
* `pre_normalize_modifiers`: As in `parse_inline_modifiers()`.
* `allow_conflicting_inline_mods_and_separate_params`: If specified, don't throw an error if a value is specified for
a given property using both an inline modifier and separate param; in this case, the inline modifier takes precedence.
3. Fields related to language prefixes:
* `parse_lang_prefix`: If true, allow and parse off a language code prefix attached to items followed by a colon, such
as {la:minūtia} or {grc:[[σκῶρ|σκατός]]}. Etymology-only languages are allowed. Inline modifiers can be attached to
such items. The exact syntax allowed is as specified in the `parse_term_with_lang()` function in
[[Module:parse utilities]]. If `allow_multiple_lang_prefixes` is given, a {{cd|+}}-sign-separated list of language
prefixes can be attached to an item. The resulting language object is stored into the `termlang` field, and also into
the `lang` field (or in the case of `allow_multiple_lang_prefixes`, the list of language objects is stored into the
`termlangs` field, and the first specified object is stored in the `lang` field).
* `allow_multiple_lang_prefixes`: If given in conjunction with `parse_lang_prefix`, multiple language code prefixes can
be given, separated by a {{cd|+}} sign. See `parse_lang_prefix` above.
* `allow_bad_lang_prefix`: If given in conjunction with `parse_lang_prefix`, unrecognized language prefixes do not
trigger an error, but are simply ignored (and not stripped off the item). Note that, regardless of whether this is
given, prefixes before a colon do not trigger an error if they do not have the form of a language prefix or if a space
follows the colon. It is not recommended that this be given because typos in language prefixes will not trigger an
error and will tend to remain unfixed.
4. Fields related to custom/special separators:
* `disallow_custom_separators`: If specified, disallow specifying custom separators (semicolon, underscore, tilde; see
the internal `default_special_separators` table, or the `special_separators` field) as an item value to override the
default separator. By default, the previous separator of each item is considered to be an empty string (for the first
item) and otherwise the value of the field `default_separator` (normally a comma + space), unless either the preceding
item is one of the values listed in `special_separators`, such as a bare semicolon (which causes the following item's
previous separator to be a semicolon + space) or an item has an embedded comma in it (which causes ''all'' items other
than the first to have their previous separator be a semicolon + space). The previous separator of each item is set on
the item's `separator` property. Bare semicolons and other separator arguments do not count when indexing items using
separate parameters.
For example, the following is correct:
** {{tl|template|lang|item 1|q1=qualifier 1|;|item 2|q2=qualifier 2}}
If `disallow_custom_separators` is specified, however, the `separator` property is not set and separator arguments are
not recognized.
* `default_separator`: Override the default separator (normally {", "}).
* `special_separators`: Table giving the special/custom separators that can be given, and how they should display. If
not specified, the default in `default_special_separators` is used. This is a table mapping separator values (such as
{"~"}) to the corresponding display string (such as {" ~ "}).
5. Fields related to multiple subitems in a given term:
* `splitchar`: A Lua pattern. If specified, each user-specified argument can consist of multiple delimiter-separated
subitems, each of which may be followed by inline modifiers. In this case, each element in the returned list of items
is no longer an object describing an item, but instead an object with a `terms` field, whose value is a list
describing the subitems (whose format is the same as the normal format of an item in the top-level list when
`splitchar` is not specified). Each subitem object will have a `delimiter` field holding the actual delimiter
occurring before the subitem, which is useful in the case where `splitchar` matches multiple possible characters. In
this case, it is possible to specify that a given modifier can only occur after the last subitem and effectively
modifies the whole collection of subitems by setting `overall = true` on the modifier. In this case, the modifier's
value will be stored in the top-level object (the object with the `terms` field specifying the subitems). Note that
splitting on delimiters will not happen in certain protected sequences (by default comma+whitespace; see below). In
addition, the algorithm to split on delimiters is sensitive to inline modifier syntax and will not be confused by
delimiters inside of inline modifiers or inside of square brackets, which do not trigger splitting (whether or not
contained within protected sequences).
* `escape_fun` and `unescape_fun`: As in `split_escaping()` and `split_alternating_runs_escaping()` in
[[Module:parse utilities]]. They control the protected sequences that won't be split when `splitchar` is specified
(see previous item). By default, `escape_comma_whitespace` and `unescape_comma_whitespace` are used, so that
comma+whitespace sequences won't be split.
* `subitem_param_handling`: How to handle separate parameters that are specified in the presence of multiple subitems.
The possible values are {"only"} (only allow separate parameters if there aren't any subitems, otherwise throw an
error), {"first"} (store the separate parameters in the first subitem) and {"last"} (store the separate parameters
in the last subitem). The default is {"only"}. As a special case, an {{para|scN}} separate parameter will be stored
into all subitems.
* `subitem_separator_map`: Table mapping user-specified delimiters to displayed separators, stored in the `separator`
field of the subitem. If not specified, it defaults to `default_subitem_separator_map`. Note that the presence of an
item in this table does not mean that it can be used as a delimiter; only the delimiters specified using `splitchar`
are recognized. Delimiters not in this map display as-is.
6. Other fields:
* `dont_skip_items`: Normally, items that are completely unspecified (have no term and no properties) are skipped and
not inserted into the returned list of items. (Such items cannot occur if `disallow_holes = true` is set on the term
specification in the `params` structure passed to `process()` in [[Module:parameters]]. It is generally recommended
to do so unless a specific meaning is associated the term value being missing.) If `dont_skip_items` is set, however,
items are never skipped, and completely unspecified items will be returned along with others. (They will not have
the term or any properties set, but will have the normal non-property fields set; see below.)
* `stop_when`: If specified, a function to determine when to prematurely stop processing items. It is passed a single
argument, an object containing the following fields:
** `term`: The raw term, prior to parsing off language prefixes and inline modifiers (since the processing of
`stop_when` happens before parsing the term).
** `any_param_at_index`: True if any separate property parameters exist for this item.
** `orig_index`: Same as `orig_index` below.
** `itemno`: Same as `itemno` below.
** `stored_itemno`: The index where this item will be stored into the returned items table. This may differ from
`itemno` due to skipped items (it will never be different if `dont_skip_items` is set).
The function should return true to stop processing items and return the ones processed so far (not including the item
currently being processed). This is used, for example, in [[Module:alternative forms]], where an unspecified item
signal the end of items and the start of labels.
Three values are returned: the list of items; the processed `args` structure; and an object of miscellaneous computed
global values (currently only `use_semicolon`, indicating that commas were found in individual arguments and so the
default separator should be a semicolon). In each returned item, there will be one field set for each specified property
(either through inline modifiers or separate parameters). If subitems are not allowed, each item directly has fields set
on it for the specified properties. If subitems ''are'' allowed, each item contains a `terms` field, which is a list of
subitem objects, each of which has fields set on it for the specified properties of that subitem. In addition, the
following fields may be set on each item or subitem:
* `term`: The term portion of the item (minus inline modifiers and language prefixes). {nil} if no term was given.
* `orig_index`: The original index into the item in the items table returned by `process()` in [[Module:parameters]].
This may differ from `itemno` if there are raw semiclons and `disallow_custom_separators` is not given.
* `itemno`: The logical index of the item. The index of separate parameters corresponds to this index. This may be
different from `orig_index` in the presence of raw semicolons; see above.
* `termlang`: If there is a language prefix, the corresponding language object is stored here (only if
`parse_lang_prefix` is set and `allow_multiple_lang_prefixes` is not set).
* `termlangs`: If there is are language prefixes and both `parse_lang_prefix` and `allow_multiple_lang_prefixes` are
set, the list of corresponding language objects is stored here.
* `lang`: The language object of the item. This is set when either (a) there is a language prefix parsed off (if
multiple prefixes are allowed, this corresponds to the first one); (b) the `lang` property is allowed and specified;
(c) neither (a) nor (b) apply and the `lang` field of the overall `data` object is set, providing a default value.
* `sc`: The script object of the item. This is set when either (a) the `sc` property is allowed and specified; (b)
`sc` isn't otherwise set and the `sc` field of the overall `data` object is set, providing a default value.
* `delimiter`: If subitems are allowed, this is set on subitems and specifies the delimiter used prior to the given
subitem (e.g. {","}).
* `separator`: The separator to display before the item. Always set on subitems, and set on top-level items if
`disallow_custom_separators` is not given. Controlled by `special_separators` (for top-level items) and
`subitem_separator_map` (for subitems).
]==]
function export.parse_list_with_inline_modifiers_and_separate_params(data)
validate_argument_related_fields(data)
local raw_args, termarg, param_mods, args = data.raw_args, data.termarg, data.param_mods
if raw_args then
local params = data.params
local termarg_spec = params[termarg]
if termarg_spec == true or not termarg_spec.list then
internal_error("Term spec in `data.params` must have `list` set", termarg_spec)
end
if termarg_spec == true or not (termarg_spec.allow_holes or termarg_spec.disallow_holes) then
internal_error("Term spec in `data.params` must have either `allow_holes` or `disallow_holes` set",
termarg_spec)
end
export.augment_params_with_modifiers(params, param_mods)
args = process_params(raw_args, params)
else
args = data.processed_args
end
local process_args_before_parsing = data.process_args_before_parsing
if process_args_before_parsing then
process_args_before_parsing(args)
end
-- Find the maximum index among any of the list parameters.
local term_args = args[termarg]
-- As a special case, the term args might not have a `maxindex` field because they might have
-- been declared with `disallow_holes = true`, so fall back to the actual length of the list
-- using the table_len function, since # can be unpredictable with arbitrary tables.
local maxmaxindex = term_args.maxindex or table_len(term_args)
for _, v in pairs(args) do
if type(v) == "table" and v.maxindex and v.maxindex > maxmaxindex then
maxmaxindex = v.maxindex
end
end
local special_separators = data.special_separators or export.default_special_separators
local items, lang_cache, use_semicolon = {}, data.lang_cache or {}
local lang = fetch_argument(args, data.lang)
if lang then
lang_cache[lang:getCode()] = lang
end
local sc = fetch_argument(args, data.sc)
local term_dest = data.term_dest or "term"
-- FIXME: this is vulnerable to abusive inputs like 1000000=.
local itemno = 0
for i = 1, maxmaxindex do
local term = term_args[i]
if data.disallow_custom_separators or not special_separators[term] then
itemno = itemno + 1
-- Compute whether any of the separate indexed params exist for this index.
local any_param_at_index
for param_mod in pairs(param_mods) do
local argval = args[param_mod]
-- Careful with argument values that may be `false`.
if argval then
argval = argval[itemno]
end
if not argval_missing(argval) then
any_param_at_index = true
break
end
end
if data.stop_when and data.stop_when{
term = term,
-- FIXME, we should just pass in `any_param_at_index` directly.
any_param_at_index = term ~= nil or any_param_at_index,
orig_index = i,
itemno = itemno,
stored_itemno = #items + 1,
} then
break
end
-- If any of the params used for formatting this term is present, create a term and add it to the list.
if not data.dont_skip_items and term == nil and not any_param_at_index then
track("skipped-term", data.track_module)
else
if not term then
track("missing-term", data.track_module)
end
local termobj = {
itemno = itemno,
orig_index = i,
}
if not data.disallow_custom_separators then
termobj.separator = i == 1 and "" or special_separators[term_args[i - 1]]
end
-- Add 1 because first term index starts at 2.
local paramname = termarg + i - 1
if term then
local function generate_obj(term, parse_err)
return export.generate_obj_maybe_parsing_lang_prefix {
term = term,
termobj = data.splitchar and {} or termobj,
term_dest = term_dest,
paramname = paramname,
parse_lang_prefix = data.parse_lang_prefix,
parse_err = parse_err,
allow_bad_lang_prefix = data.allow_bad_lang_prefix,
allow_multiple_lang_prefixes = data.allow_multiple_lang_prefixes,
lang_cache = lang_cache,
}
end
parse_inline_modifiers(term, {
paramname = paramname,
param_mods = param_mods,
generate_obj = generate_obj,
splitchar = data.splitchar,
preserve_splitchar = true,
escape_fun = data.escape_fun,
unescape_fun = data.unescape_fun,
outer_container = data.splitchar and termobj or nil,
pre_normalize_modifiers = data.pre_normalize_modifiers,
})
end
local term_data = {
args = args,
param_mods = param_mods,
itemno = itemno,
termobj = termobj,
term_dest = term_dest,
has_subitems = not not data.splitchar,
lang = lang,
-- As a special case, if the caller defined a scN= separate param, set it on all subitems if there
-- are multiple, falling back to the overall sc= param.
sc = args.sc and args.sc[itemno] or sc,
subitem_param_handling = data.subitem_param_handling,
subitem_separator_map = data.subitem_separator_map or export.default_subitem_separator_map,
allow_conflicting_inline_mods_and_separate_params =
data.allow_conflicting_inline_mods_and_separate_params,
postprocess_termobj = postprocess_termobj,
disallow_custom_separators = data.disallow_custom_separators,
use_semicolon = use_semicolon,
}
copy_separate_params_to_termobj_and_postprocess(term_data)
use_semicolon = term_data.use_semicolon
insert(items, termobj)
end
end
end
if not data.disallow_custom_separators then
-- Set the default separator of all those items for which a separator wasn't explicitly given to the default
-- separator, defaulting to comma + space; but if any items have embedded commas, set the separator to
-- semicolon + space.
for _, item in ipairs(items) do
if not item.separator then
item.separator = use_semicolon and "; " or data.default_separator or ", "
end
end
end
return items, args, {use_semicolon = use_semicolon}
end
--[==[
Parse a single term that may have properties specified through inline modifiers or separate parameters. This differs
from `parse_list_with_inline_modifiers_and_separate_params()` in that the latter is for parsing a list of terms, each of
which may have properties specified through inline modifiers or separate parameters. Both functions optionally support
having multiple subitems in a single term. This function is used e.g. for form-of templates
({{tl|inflection of}}/{{tl|infl of}}, {{tl|form of}}, and specific templates such as
{{tl|alt form}}/{{tl|alternative form of}}, {{tl|abbr of}}/{{tl|abbreviation of}}, {{tl|clipping of}}, and many others);
for etymology templates ({{tl|bor}}/{{tl|borrowed}}, {{tl|der}}/{{tl|derived}}, etc. as well as `misc_variant` templates
like {{tl|ellipsis}}, {{tl|abbrev}}, {{tl|clipping}}, {{tl|reduplication}} and the like); and for other templates with
an argument structure similar to {{tl|l}} or {{tl|m}}. In these templates there is a term specified using a numeric
parameter and associated separate parameters specifying term properties such as {{para|t}} for the gloss or {{para|tr}}
for manual transliteration. All such properties can also be specified through inline modifiers attached directly to each
term (`<t:...>`, `<tr:...>`, etc.). Normally it is an error if both an inline modifier and separate parameter for the
same value are given, but this can be overridden (in which case inline modifiers take precedence over separate
parameters when both occur).
Some notable properties of this function:
# Processing of the raw frame parent args using `process()` in [[Module:parameters]] can occur either inside of this
function (the usual workflow) or outside of this function (for more complex cases). In the former case the raw parent
args are passed in along with a partially built `params` structure of the sort required by [[Module:parameters]],
containing only the term list itself along with any other parameters that are '''not''' term properties (such as
a language code in {{para|1}} and boolean flags like {{para|nocat}}, {{para|nocap}}, etc.). This structure is
''augmented'' with parameters, one for each per-term property, and [[Module:parameters]] is invoked. In the latter
case where raw argument processing is done by the caller, they must build the partial `params` structure; augment it
themselves using `augment_params_with_modifiers()`; call [[Module:parameters]] themselves; and pass in the processed
arguments. In both cases, the return value of this function contains two values, an object specifying the term and all
properties; and the processed arguments structure, so that the non-term-property arguments can be processed as
appropriate.
# Optionally, the term can consist of a number of ''subitems'' separated by delimiters (usually a comma, but the
possible delimiter or delimiters are controllable). Each subitem can have its own inline modifiers. This functionality
is used, for example, by form-of templates. When this feature is invoked, the format of the term object changes;
instead of directly being an object describing the term and its properties, it is an object with a `terms` field
containing a list of per-subitem objects along with other top-level fields describing per-term properties. By default,
if there are separate parameters specified along with multiple subitems, an error occurs, but this is controllable;
currently, you can request that the parameters be assigned to the first or last subitem.
`data` is an object containing several possible fields.
1. Fields that are required or recommended (usually related to argument processing):
* `raw_args` ('''required''' unless `processed_args` is specified): The raw arguments, normally fetched from
{frame:getParent().args}. They are parsed using `process()` in [[Module:parameters]]. Most callers pass in raw
arguments.
* `processed_args`: The object of parsed arguments returned by `process()` in [[Module:parameters]]. One (but not both)
of `raw_args` and `processed_args` must be set.
* `param_mods` ('''required'''): A structure describing the possible inline modifiers and their properties. See the
introductory comment above. Most often, this is generated using `construct_param_mods()` rather than specified
manually.
* `params` ('''required''' unless `processed_args` is specified): A structure describing the possible parameters,
'''other than''' the ones that are separate-parameter equivalents of inline modifiers. This is automatically
"augmented" with the separate-parameter equivalents of the inline modifiers described in `param_mods` prior to parsing
the raw arguments with [[Module:parameters]]. '''WARNING:''' This structure is destructively modified, both by the
"augmentation" process of adding separate-parameter equivalents of inline modifiers, and by the processing done by
[[Module:parameters]] itself. (Nonetheless, substructures can safely be shared in this structure, and will be
correctly handled.)
* `termarg` ('''required'''): The argument containing the item with attached inline modifiers to be parsed. Usually a
numeric value such as {1} or {2}.
* `track_module` ('''recommended'''): The name of the calling module, for use in adding tracking pages that are used
internally to track pages containing template invocations with certain properties.
* `lang` ('''recommended'''): The language object for the language of the item or subitems, or the name of the argument
to fetch the object from. It is not strictly necessary to specify this, as this function only initializes items based
on inline modifiers and separate arguments and doesn't actually format the resulting items. However, if specified, it
is used for certain purposes:
*# It specifies the default for the `lang` property of returned objects if not otherwise set (e.g. by a language
prefix).
*# It is used to initialize an internal cache for speeding up language-code parsing (primarily useful if the same
language code may appear in several subitems).
The value of `lang` can be any of the following:
* If a string or number, it is assumed to be requesting the value of `args` at that key. Note that if the string is in
the form of a number (e.g. "3"), it is normalized to a number prior to fetching.
* Otherwise, if a function, it is assumed to be a function to return the argument value given `args`, which is passed
to the function as its only argument.
* Otherwise, it is used directly.
* `sc` ('''recommended'''): The script object for the item or subitems, or the name of the argument to fetch the object
from. The possible values and their handling are the same as with `lang`. In general, as with `lang`, it is not
strictly necessary to specify this. However, if specified, it is used to supply the default for the `sc` property of
returned items if not otherwise set (e.g. by the {{para|sc}} parameter or `<sc:...>` inline modifier). The most common
value is {"sc"}.
* `make_separate_g_into_list`: Set this to {true} if separate gender parameters exist are are specified using
{{para|g}}, {{para|g2}}, etc. instead of using a single comma-separated {{para|g}} field.
2. Other argument-related fields:
* `adjust_params_before_arg_processing`: An optional function to further adjust the `params` structure prior to
calling `process()` in [[Module:parameters]]. This should be used when there are mismatches between the format of a
given property as an inline modifier and the corresponding property as a separate parameter (as with the {{para|g}}
parameter and {{cd|<g:...>}} modifier, but this particular case is handled by the `make_separate_g_into_list` field).
* `process_args_before_parsing`: An optional function to apply further processing to the processed `args` structure
returned by [[Module:parameters]], before parsing inline modifiers. This is passed one argument, the processed
arguments. It should make modifications in-place.
* `term_dest`: The field to store the value of the item itself into, after inline modifiers and (if allowed) language
prefixes are stripped off. Defaults to {"term"}.
* `pre_normalize_modifiers`: As in `parse_inline_modifiers()`.
* `allow_conflicting_inline_mods_and_separate_params`: If specified, don't throw an error if a value is specified for
a given property using both an inline modifier and separate param; in this case, the inline modifier takes precedence.
3. Fields related to language prefixes:
* `parse_lang_prefix`: If true, allow and parse off a language code prefix attached to items followed by a colon, such
as {la:minūtia} or {grc:[[σκῶρ|σκατός]]}. Etymology-only languages are allowed. Inline modifiers can be attached to
such items. The exact syntax allowed is as specified in the `parse_term_with_lang()` function in
[[Module:parse utilities]]. If `allow_multiple_lang_prefixes` is given, a {{cd|+}}-sign-separated list of language
prefixes can be attached to an item. The resulting language object is stored into the `termlang` field, and also into
the `lang` field (or in the case of `allow_multiple_lang_prefixes`, the list of language objects is stored into the
`termlangs` field, and the first specified object is stored in the `lang` field).
* `allow_multiple_lang_prefixes`: If given in conjunction with `parse_lang_prefix`, multiple language code prefixes can
be given, separated by a {{cd|+}} sign. See `parse_lang_prefix` above.
* `allow_bad_lang_prefix`: If given in conjunction with `parse_lang_prefix`, unrecognized language prefixes do not
trigger an error, but are simply ignored (and not stripped off the item). Note that, regardless of whether this is
given, prefixes before a colon do not trigger an error if they do not have the form of a language prefix or if a space
follows the colon. It is not recommended that this be given because typos in language prefixes will not trigger an
error and will tend to remain unfixed.
4. Fields related to multiple subitems in the term:
* `splitchar`: A Lua pattern. If specified, the user-specified argument can consist of multiple delimiter-separated
subitems, each of which may be followed by inline modifiers. In this case, the first returned value is no longer an
object describing the item, but instead an object with a `terms` field, whose value is a list describing the subitems
(whose format is the same as the normal format of the item when `splitchar` is not specified). Each subitem object
will have a `delimiter` field holding the actual delimiter occurring before the subitem, which is useful in the case
where `splitchar` matches multiple possible characters. In this case, it is possible to specify that a given modifier
can only occur after the last subitem and effectively modifies the whole collection of subitems by setting
`overall = true` on the modifier. In this case, the modifier's value will be stored in the top-level object (the
object with the `terms` field specifying the subitems). Note that splitting on delimiters will not happen in certain
protected sequences (by default comma+whitespace; see below). In addition, the algorithm to split on delimiters is
sensitive to inline modifier syntax and will not be confused by delimiters inside of inline modifiers or inside of
square brackets, which do not trigger splitting (whether or not contained within protected sequences).
* `escape_fun` and `unescape_fun`: As in `split_escaping()` and `split_alternating_runs_escaping()` in
[[Module:parse utilities]]. They control the protected sequences that won't be split when `splitchar` is specified
(see previous item). By default, `escape_comma_whitespace` and `unescape_comma_whitespace` are used, so that
comma+whitespace sequences won't be split.
* `subitem_param_handling`: How to handle separate parameters that are specified in the presence of multiple subitems.
The possible values are {"only"} (only allow separate parameters if there aren't any subitems, otherwise throw an
error), {"first"} (store the separate parameters in the first subitem) and {"last"} (store the separate parameters
in the last subitem). The default is {"only"}. As a special case, an {{para|scN}} separate parameter will be stored
into all subitems.
* `subitem_separator_map`: Table mapping user-specified delimiters to displayed separators, stored in the `separator`
field of the subitem. If not specified, it defaults to `default_subitem_separator_map`. Note that the presence of an
item in this table does not mean that it can be used as a delimiter; only the delimiters specified using `splitchar`
are recognized. Delimiters not in this map display as-is.
Two values are returned, an object describing the item (or subitems) and the processed `args` structure. In the returned
item, there will be one field set for each specified property (either through inline modifiers or separate parameters).
If subitems are not allowed, the item directly has fields set on it for the specified properties. If subitems ''are''
allowed, the item contains a `terms` field, which is a list of subitem objects, each of which has fields set on it for
the specified properties of that subitem. In addition, the following fields may be set on the item or each subitem:
* `term`: The term portion of the item (minus inline modifiers and language prefixes). {nil} if no term was given.
* `termlang`: If there is a language prefix, the corresponding language object is stored here (only if
`parse_lang_prefix` is set and `allow_multiple_lang_prefixes` is not set).
* `termlangs`: If there is are language prefixes and both `parse_lang_prefix` and `allow_multiple_lang_prefixes` are
set, the list of corresponding language objects is stored here.
* `lang`: The language object of the item. This is set when either (a) there is a language prefix parsed off (if
multiple prefixes are allowed, this corresponds to the first one); (b) the `lang` property is allowed and specified;
(c) neither (a) nor (b) apply and the `lang` field of the overall `data` object is set, providing a default value.
* `sc`: The script object of the item. This is set when either (a) the `sc` property is allowed and specified; (b)
`sc` isn't otherwise set and the `sc` field of the overall `data` object is set, providing a default value.
* `delimiter`: If subitems are allowed, this specifies the delimiter used prior to the given subitem (e.g. {","}).
* `separator`: If subitems are allowed, this specifies the displayed form of the delimiter to be shown before a given
subitem. The mapping from user-specified delimiters to displayed separators is handled by `subitem_separator_map`;
see above. The first subitem always has a blank string in the `separator` field.
]==]
function export.parse_term_with_inline_modifiers_and_separate_params(data)
validate_argument_related_fields(data)
local raw_args, termarg, param_mods, args = data.raw_args, data.termarg, data.param_mods
if raw_args then
local params = data.params
local termarg_spec = params[termarg]
if type(termarg_spec) == "table" and termarg_spec.list then
internal_error("Term spec in `data.params` must not have `list` set", termarg_spec)
end
export.augment_params_with_modifiers(params, param_mods, "always")
if data.make_separate_g_into_list then
-- HACK: g= is a list for compatibility, but sublist as an inline parameter.
params.g = {list = true, item_dest = "genders", type = "genders", flatten = true}
end
local adjust_params_before_arg_processing = data.adjust_params_before_arg_processing
if adjust_params_before_arg_processing then
adjust_params_before_arg_processing(params)
end
args = process_params(raw_args, params)
else
args = data.processed_args
end
local process_args_before_parsing = data.process_args_before_parsing
if process_args_before_parsing then
process_args_before_parsing(args)
end
local term, lang_cache = args[termarg], data.lang_cache
local lang = fetch_argument(args, data.lang)
if lang and lang_cache then
lang_cache[lang:getCode()] = lang
end
local sc = fetch_argument(args, data.sc)
local term_dest = data.term_dest or "term"
if not term then
track("missing-term", data.track_module)
end
local termobj, splitchar = {}, data.splitchar
if term then
local function generate_obj(term, parse_err)
return export.generate_obj_maybe_parsing_lang_prefix {
term = term,
termobj = splitchar and {} or termobj,
term_dest = term_dest,
paramname = termarg,
parse_lang_prefix = data.parse_lang_prefix,
parse_err = parse_err,
allow_bad_lang_prefix = data.allow_bad_lang_prefix,
allow_multiple_lang_prefixes = data.allow_multiple_lang_prefixes,
lang_cache = lang_cache,
}
end
parse_inline_modifiers(term, {
paramname = termarg,
param_mods = param_mods,
generate_obj = generate_obj,
splitchar = splitchar,
preserve_splitchar = true,
escape_fun = data.escape_fun,
unescape_fun = data.unescape_fun,
outer_container = splitchar and termobj or nil,
pre_normalize_modifiers = data.pre_normalize_modifiers,
})
end
copy_separate_params_to_termobj_and_postprocess{
args = args,
param_mods = param_mods,
termobj = termobj,
has_subitems = not not splitchar,
lang = lang,
sc = sc,
subitem_param_handling = data.subitem_param_handling,
subitem_separator_map = data.subitem_separator_map or export.default_subitem_separator_map,
allow_conflicting_inline_mods_and_separate_params = data.allow_conflicting_inline_mods_and_separate_params,
}
if splitchar and termobj.terms[2] then
track("parse-term-multiple-subitems", data.track_module)
track("parse-term-multiple-subitems")
end
return termobj, args
end
return export
17j6htwomicae9ker3scwcncfv96kk5
ᮞᮠ
0
7408
25307
23389
2026-08-19T08:22:18Z
Deepturquoise
2456
25307
wikitext
text/x-wiki
=={{sunda}}==
{{-pronomina-|su}}
*{{ka|saha}}
:*''"ᮞᮠ ᮃᮔᮥ ᮙᮩᮔᮀᮊᮩᮔ᮪ ᮅᮛᮀ ᮙᮏᮜᮚ ᮒᮦᮂ?"''
:*''"ᮃᮛᮤ ᮆᮒ ᮠᮚᮙ᮪ ᮙᮩᮔᮀ ᮙᮩᮜᮤ ᮒᮤ ᮞᮠ?"''
[[Kategori:WikiPrestasi]]
5iscluin69pspsrwi7n06qetkx75900
ᮃᮘᮤ
0
7409
25214
22301
2026-08-19T07:21:45Z
Deepturquoise
2456
25214
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
# {{ka|abi}}
:* ''"ᮙᮀ, ᮃᮘᮤ ᮑᮩᮞᮩᮂ ᮠᮩᮜᮑ!"''
:* ''"ᮓᮤ ᮊᮙ᮪ᮕᮥᮞ᮪, ᮃᮘᮤ ᮓᮤᮃᮏᮁ ᮙᮒ ᮊᮥᮜᮤᮃᮂ ᮜᮤᮍᮥᮄᮞ᮪ᮒᮤᮊ᮪"''
[[Kategori:WikiPrestasi]]
qnbyzpx1k6z8f77ioccuwjqpef0yapl
ᮊᮏᮘ
0
7411
25253
22317
2026-08-19T08:01:47Z
Deepturquoise
2456
25253
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|kajaba}}
:* '' "ᮠᮚᮀ ᮄᮔ᮪ᮓᮤᮒ᮪ ᮊ ᮏᮊᮁᮒ ᮃᮚᮩᮔ ᮊᮨᮔᮨᮂ ᮙᮂ ᮙᮧᮃᮜ᮪ [[ᮘᮤᮞ ᮌᮔ᮪ᮎᮀ]], ᮊᮏᮘ ᮙᮥᮔ᮪ ᮔᮆᮊ᮪ ᮊᮕᮜ᮪." ''
:* '' "ᮅᮜᮂ ᮠᮚᮀ ᮙᮩᮜᮤ ᮘᮏᮥ, ᮊᮏᮘ ᮘᮧᮌ ᮓᮥᮄᮒ᮪ᮔ." ''
[[Kategori:WikiPrestasi]]
oivyyjk6ynhb29yjet8o0jnaf7t30vc
ᮊᮊᮛ
0
7421
25252
22316
2026-08-19T08:01:27Z
Deepturquoise
2456
25252
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|kakara}}
:* '' "ᮅᮛᮀ ᮙᮂ ᮊᮊᮛ ᮓᮒᮀ ᮒᮦᮂ ᮜᮀᮞᮥᮀ ᮓᮤᮒᮤᮒᮂ ᮄᮔ᮪ᮓᮤᮒ᮪ ᮓᮩᮄ."
:* '' "ᮔᮦᮀ ᮒᮤᮃ ᮙᮂ ᮊᮊᮛ [[ᮍᮤᮜᮥᮃᮔ᮪]] ᮞᮊᮜᮤ ᮌᮩᮞ᮪ ᮊᮕᮧᮊ᮪ ᮓᮩᮄ."''
[[Kategori:WikiPrestasi]]
qkfbti6ys6qf009xztqf8bj8zlylinb
ᮃᮒᮝ
0
7424
25219
22300
2026-08-19T07:30:34Z
Deepturquoise
2456
25219
wikitext
text/x-wiki
=={{sunda}}==
{{-konjungsi-|su}}
* {{ka|atawa}}
:* ''"ᮙᮀ ᮈᮕᮥᮜ᮪ ᮘᮤᮍᮥᮀ ᮙᮤᮜᮤᮂ ᮞᮙᮀᮊ ᮃᮒᮝ ᮏᮨᮛᮥᮊ᮪"''
:* ''"ᮃᮛᮤ ᮃᮚᮩᮔ ᮒᮦᮂ ᮠᮥᮏᮔ᮪ ᮃᮒᮝ ᮠᮨᮔ᮪ᮒᮩ?"''
[[Kategori:WikiPrestasi]]
ew748zxv5om1fdx72ku0vonv3pjlhfp
ᮃᮎᮔ᮪
0
7431
25217
22296
2026-08-19T07:29:47Z
Deepturquoise
2456
25217
wikitext
text/x-wiki
=={{sunda}}==
{{-adverb-|su|num= anteb}}
* {{ka|acan}}
:* ''"ᮃᮘᮤ ᮃᮎᮔ᮪ ᮍᮨᮁᮏᮊᮩᮔ᮪ ᮕᮔ᮪ᮎᮦᮔ᮪ ᮘᮞ ᮞᮥᮔ᮪ᮓ"''
:* ''"ᮙᮙᮂ ᮃᮎᮔ᮪ ᮅᮄᮂ ᮒᮤ ᮕᮞᮁ"''
[[Kategori:WikiPrestasi]]
ocwt413s0noatnmns7kzvgvf8zlw3ao
ᮞᮤᮉᮔ᮪
0
7432
25306
23817
2026-08-19T08:22:02Z
Deepturquoise
2456
25306
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|sieun}}
:*''"ᮞᮤᮙ᮪ᮊᮥᮛᮤᮀ ᮞᮤᮉᮔ᮪ ᮊᮥ ᮙᮅᮀ, ᮊᮥᮞᮘᮘ᮪ ᮙᮅᮀᮔ ᮜᮩᮝᮤᮂ ᮌᮨᮓᮨ ᮒᮤ ᮞᮤᮊᮥᮛᮤᮀ."''
:*''"ᮙᮤᮅᮔ᮪ ᮔᮠ ᮒᮩ ᮍᮤᮜᮥ ᮊ ᮘᮔ᮪ᮓᮥᮀ, ᮞᮤᮉᮔ᮪ ᮓᮤᮎᮛᮨᮊᮔ᮪ ᮊᮥ ᮄᮔ᮪ᮓᮥᮀ ᮑ?"''
[[Kategori:WikiPrestasi]]
ol3sdrpbvmbrsst1piz9efcxn0so9ax
ᮞᮌᮜ
0
7436
25317
23820
2026-08-19T08:24:45Z
Deepturquoise
2456
25317
wikitext
text/x-wiki
=={{sunda}}==
{{-k bl-|su}}
*{{ka|sagala}}
:* ''"ᮞᮌᮜ ᮊᮠᮚᮀ ᮘᮥᮓᮊ᮪ ᮊᮥᮓᮥ ᮓᮤᮎᮥᮙ᮪ᮕᮧᮔᮔ᮪."''
:* ''"ᮎᮩ ᮄᮙᮞ᮪ ᮙᮂ ᮘᮜᮤᮊ᮪ ᮌᮝᮦ ᮏᮓᮤ ᮒ᮪ᮊ᮪ᮝ᮪ ᮓᮤ ᮒᮄᮝᮔ᮪ ᮏᮓᮤ ᮞᮌᮜ ᮘᮧᮌ ᮓᮤᮄᮙᮂᮔ ᮒᮦᮂ."''
[[Kategori:WikiPrestasi]]
druvxhpwyanushegbd3beb4ggxubk7a
ᮉᮛᮤᮂ
0
7438
25233
22312
2026-08-19T07:50:51Z
Deepturquoise
2456
25233
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
* {{ka|eurih}}
:* ''"ᮊᮥᮛᮤᮀ ᮊ ᮊᮨᮘᮧᮔ᮪ ᮍᮜ ᮉᮛᮤᮂ."''
:* ''"ᮓᮅᮔ᮪ ᮉᮛᮤᮂ ᮞᮧᮊ᮪ ᮓᮤᮏᮓᮤᮊᮩᮔ᮪ ᮠᮒᮩᮕ᮪."''
[[Kategori:WikiPrestasi]]
8qrfhh2fl30qg5kbtd8p04mu6iqaw9v
ᮠᮦᮆᮞ᮪
0
7441
25302
22298
2026-08-19T08:18:50Z
Deepturquoise
2456
25302
wikitext
text/x-wiki
=={{sunda}}==
{{-k k-|su}}
*{{ka|héés}}
:* ''"ᮙᮦᮔᮂ ᮙᮂ ᮦᮠᮆᮞ᮪ ᮦᮝ ᮠᮚᮧᮂ ᮌᮩᮞ᮪ ᮘᮩᮛᮀ ᮦᮌ."''
:* ''"ᮕᮩᮒᮤᮀ ᮊᮥᮛᮤᮀ ᮦᮠᮆᮞ᮪ ᮓᮤ ᮄᮙᮂ ᮞᮧᮘᮢᮤ."''
[[Kategori:WikiPrestasi]]
afb7evj40v8tvphqk43z6uisb1eyxwp
ᮃᮎᮤᮞ᮪
0
7447
25218
22299
2026-08-19T07:30:12Z
Deepturquoise
2456
25218
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
* {{ka|acis}}
:* ''"ᮃᮎᮤᮞ᮪ᮔ ᮎᮔ᮪ ᮓᮤᮒᮘᮥᮀ"''
:* ''"ᮃᮎᮤᮞ᮪ ᮃᮘᮤ ᮓᮤᮕᮜᮤᮀ"''
[[Kategori:WikiPrestasi]]
ggrye1evl0kquvwzr589ur8bmujvdjl
ᮊᮔ᮪ᮎᮢ
0
7450
25259
22333
2026-08-19T08:03:25Z
Deepturquoise
2456
25259
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|kancra}}
:*''"ᮊᮥᮛᮤᮀ ᮔᮥᮏᮥ ᮔᮥᮃᮀ ᮕᮄᮞ᮪ ᮊᮔ᮪ᮎᮢ.''"
:*''"ᮕᮥᮔ᮪ ᮘᮕ ᮔᮥᮏᮥ ᮍᮜ ᮊᮔ᮪ᮎᮢ ᮓᮤ ᮝᮜᮥᮍᮔ᮪.''"
[[Kategori:WikiPrestasi]]
5ugz2qtcobvw13b33mt5faqvcm0om00
ᮊᮒᮥᮒ᮪
0
7458
25257
22321
2026-08-19T08:02:51Z
Deepturquoise
2456
25257
wikitext
text/x-wiki
=={{sunda}}==
{{-k k-|su}}
* {{ka|katut}}
:* ''" ᮊᮥᮛᮤᮀ ᮊ ᮕᮨᮁᮕᮥᮞ᮪ᮒᮊᮃᮔ᮪ ᮊᮒᮥᮒ᮪ ᮙᮝ ᮃᮜᮒ᮪ ᮔᮥᮜᮤᮞ᮪"''
:* ''" ᮊᮜᮥᮃᮁ ᮒᮤᮔ ᮠᮤᮛᮥᮕ᮪ ᮃᮔᮥ ᮠᮨᮘᮩᮜ᮪ ᮊᮒᮥᮒ᮪ ᮊᮘᮤᮃᮞᮃᮔ᮪ᮔ"''
[[Kategori:WikiPrestasi]]
6rfqp6f7pazdiwmymyygjdyrq6op130
ᮊᮥᮓᮥ
0
7459
25267
23544
2026-08-19T08:05:59Z
Deepturquoise
2456
25267
wikitext
text/x-wiki
=={{sunda}}==
{{-adverb-|su|num= anteb}}}
*{{ka|kudu}}
:* ''"ᮄᮞᮥᮊᮔ᮪ ᮊᮘᮦᮂ ᮙᮠᮞᮤᮞ᮪ᮝ ᮕᮢᮧᮓᮤ ᮕᮨᮔ᮪ᮓᮤᮓᮤᮊᮔ᮪ ᮘᮞ ᮞᮥᮔ᮪ᮓ ᮊᮥᮓᮥ ᮍᮤᮜᮥ ᮙᮕᮌ᮪ ᮝᮤᮞᮥᮓ."''
:* ''"ᮙᮠᮞᮤᮞ᮪ᮝ ᮏᮩᮀ ᮓᮧᮞᮦᮔ᮪ ᮊᮥᮓᮥ ᮠᮓᮤᮁ ᮒᮨᮕᮒ᮪ ᮝᮊ᮪ᮒᮥ ᮔᮜᮤᮊ ᮊᮥᮜᮤᮃᮂ."''
[[Kategori:WikiPrestasi]]
sduvs8fl8dm8jqw5gh1aflr8m95yp85
ᮘᮘᮊᮔ᮪
0
7461
25283
22358
2026-08-19T08:13:18Z
Deepturquoise
2456
25283
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
* {{ka|babakan}}
:* ''"ᮃᮘᮤ ᮌᮩᮞ᮪ ᮒᮤ ᮘᮘᮊᮔ᮪ ᮎᮅ"''
:* ''"ᮙᮀ ᮈᮓᮧᮓ᮪ ᮒᮦᮂ ᮃᮞᮣᮤ ᮅᮛᮀ ᮘᮘᮊᮔ᮪ ᮎᮅ"''
[[Kategori:WikiPrestasi]]
exjfyzwz1l43fhodwqimwt7bara4lj7
ᮅᮞᮥᮙ᮪
0
7474
25230
22306
2026-08-19T07:49:23Z
Deepturquoise
2456
25230
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|usum}}
:* ''"ᮘᮥᮜᮔ᮪ ᮠᮛᮩᮕ᮪ ᮕᮞ᮪ᮒᮤ ᮅᮞᮥᮙ᮪ ᮊᮒᮤᮌ ᮓᮤ ᮜᮨᮙ᮪ᮘᮥᮁ."''
:* ''"ᮓᮤ ᮘᮔ᮪ᮓᮥᮀ ᮙᮂ ᮃᮚᮩᮔ ᮊᮩᮁ ᮅᮞᮥᮙ᮪ ᮛᮙ᮪ᮘᮥᮒᮔ᮪."''
[[Kategori:WikiPrestasi]]
bpoyzcd742je0omgzf7s7xv1dvfl5bm
ᮊᮒᮀᮒᮥᮃᮔ᮪
0
7480
25255
22319
2026-08-19T08:02:19Z
Deepturquoise
2456
25255
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|katangtuan}}
:*''" ᮍᮨᮁᮏᮊᮩᮔ᮪ ᮕᮔ᮪ᮎᮦᮔ᮪ ᮒᮦᮂ ᮊᮥᮓᮥ ᮞᮜᮥᮚᮥ ᮏᮩᮀ ᮊᮒᮀᮒᮥᮃᮔ᮪ ᮃᮔᮥ ᮌᮩᮞ᮪ ᮓᮤᮏᮤᮉᮔ᮪ ᮊᮥ ᮓᮧᮞᮦᮔ᮪."''
:*''" ᮙᮊᮦ ᮘᮏᮥ ᮒᮦᮂ ᮊᮥᮓᮥ ᮞᮜᮥᮚᮥ ᮏᮩᮀ ᮊᮒᮀᮒᮥᮃᮔ᮪ ᮇᮌᮦ ᮆᮒᮤᮊ ᮙᮊᮦ ᮛᮊ᮪ᮞᮥᮊᮔ᮪."''
[[Kategori:WikiPrestasi]]
9ephlrznruq1cxu3tzhmd30l1p0tvyn
ᮅᮜᮂ
0
7482
25229
22307
2026-08-19T07:48:19Z
Deepturquoise
2456
25229
wikitext
text/x-wiki
=={{sunda}}==
{{-adverb-|su|num= anteb}}
*{{ka|ulah}}
:* ''"ᮃᮘᮥᮚ᮪, ᮅᮜᮂ ᮓᮠᮁ ᮝᮆ!"''
:* ''"ᮎᮩᮊ᮪ ᮄᮄᮞ᮪ ᮅᮜᮂ ᮍᮜᮤᮝᮒ᮪ ᮊ ᮝᮨᮒᮔ᮪ ᮞᮘᮘ᮪ ᮏᮜᮔ᮪ᮔ ᮊᮩᮁ ᮓᮤᮘᮨᮔᮨᮁᮊᮩᮔ᮪."''
[[Kategori:WikiPrestasi]]
gvqk182ttw494a9eerkiqyo3c3ws6yb
ᮅᮀᮌᮜ᮪
0
7486
25225
22311
2026-08-19T07:46:32Z
Deepturquoise
2456
25225
wikitext
text/x-wiki
=={{sunda}}==
{{-k bl-|su}}
*{{ka|unggal}}
:* ''"ᮅᮀᮌᮜ᮪ ᮞᮨᮔᮦᮔ᮪ ᮘᮛᮥᮓᮊ᮪ ᮞᮊᮧᮜ ᮅᮕᮎᮛ ᮓᮤ ᮜᮕᮀ."''
:* ''"ᮉᮜᮤᮞ᮪ ᮅᮀᮌᮜ᮪ ᮕᮧᮆ ᮙᮝ ᮘᮥᮊᮥ ᮔᮥ ᮝᮁᮔ ᮊᮚᮞ᮪."''
[[Kategori:WikiPrestasi]]
efgc97cpyqpr1l0br3vgddp222z0z7b
ᮅᮛᮀ
0
7489
25228
22308
2026-08-19T07:47:54Z
Deepturquoise
2456
25228
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|urang}}
:* ''" ᮅᮛᮀ ᮊᮥᮔᮤᮍᮔ᮪ ᮙᮂ ᮊᮞᮧᮠᮧᮁ ᮊᮥ ᮒᮢᮓᮤᮞᮤ ᮞᮨᮛᮨᮔ᮪ ᮒᮅᮔ᮪ᮔ "''
:* ''" ᮅᮛᮀ ᮞᮜᮊᮥ ᮙᮠᮞᮤᮞ᮪ᮝ ᮞᮥᮔ᮪ᮓ ᮊᮥᮓᮥ ᮒᮤᮃᮞ ᮍᮙᮥᮙᮥᮜᮦ ᮘᮥᮓᮚ ᮞᮥᮔ᮪ᮓ"''
[[Kategori:WikiPrestasi]]
mgvtg6dr6czej4d2d3unfg48rfexwnp
ᮅᮕᮙ
0
7491
25227
22309
2026-08-19T07:47:33Z
Deepturquoise
2456
25227
wikitext
text/x-wiki
=={{sunda}}==
{{-konjungsi-|su}}
*{{ka|upama}}
:* ''"ᮊᮥᮛᮤᮀ ᮞᮧᮊ᮪ ᮍᮤᮙ᮪ᮕᮣᮨᮀ, ᮅᮕᮙ ᮒᮩ ᮙᮊ᮪ᮞᮊᮩᮔ᮪ ᮒᮀᮒᮥ ᮃᮚᮩᮔ ᮙᮧᮃᮜ᮪ ᮏᮓᮤ ᮓᮧᮞᮦᮔ᮪"''
:* ''"ᮅᮕᮙ ᮍᮛᮩᮙ᮪ᮕᮊ᮪, ᮊᮥᮛᮤᮀ ᮙᮩᮔᮀ ᮞᮀᮞᮤ |᮳| ᮘᮥᮜᮔ᮪ ᮒᮩ ᮙᮩᮔᮀ ᮏᮏᮔ᮪"''
[[Kategori:WikiPrestasi]]
764pd98jmnyydg1u8mj42kp8ilhwdr7
ᮘᮘᮒᮧᮊ᮪
0
7503
25269
22359
2026-08-19T08:07:32Z
Deepturquoise
2456
25269
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
* {{ka|babatok}}
:* ''"ᮔ ᮊᮥᮓᮥ ᮓᮤᮕᮦᮕᮢᮦᮊ᮪ ᮘᮘᮒᮧᮊ᮪ ᮞᮤ ᮅᮞ᮪ᮙᮔ᮪."''
:* ''"ᮅᮜᮂ ᮞᮧᮊ᮪ ᮕᮤᮊᮞᮨᮘᮩᮜᮩᮔ᮪ ᮞᮤ ᮅᮞ᮪ᮙᮔ᮪ ᮘᮤᮞᮤ ᮓᮤᮌᮨᮒᮧᮊ᮪ ᮘᮘᮒᮧᮊ᮪."''
[[Kategori:WikiPrestasi]]
swgnijog5lvjstazuj65bs2xpb3hufw
ᮆᮛᮧᮕ
0
7529
25231
22314
2026-08-19T07:49:51Z
Deepturquoise
2456
25231
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
{{ka|Éropa}}
:* ᮔᮌᮛ [[ᮝᮜᮔ᮪ᮓ]] ᮒᮦᮂ ᮃᮚ ᮓᮤ ᮘᮥᮃᮔ ᮆᮛᮧᮕ
:* ᮕᮓᮥᮙᮥᮊ᮪ ᮃᮞ᮪ᮜᮤ ᮘᮥᮃᮔ ᮆᮛᮧᮕ ᮒᮦᮂ ᮞᮜᮂᮞᮠᮤᮏᮤᮔ ᮘᮀᮞ [[ᮊᮅᮊᮞᮧᮄᮓ]]
[[Kategori:WikiPrestasi]]
a0gm2oh08j8znce629buijv2ilqd453
ᮃᮝᮦᮒ᮪
0
7537
25223
22294
2026-08-19T07:32:16Z
Deepturquoise
2456
25223
wikitext
text/x-wiki
== {{sunda}} ==
{{-k s-|su}}
* {{ka|awét}}
:* ''ᮊᮥ ᮙᮔᮦᮂ ᮊᮥᮓᮥ ᮓᮤᮕᮤᮊᮤᮛ᮪, ᮃᮔᮥ ᮃᮝᮒ᮪ ᮊᮕᮊᮦᮔ, ᮞᮥᮕᮚ ᮏᮓᮤ ᮕᮦᮕᮦᮜᮤᮍ᮪''
[[Kategori:WikiPrestasi]]
3hmf5q3n4b7m6jeighqx550yzgswx8h
ᮝᮝᮎᮔ᮪
0
7551
25295
23540
2026-08-19T08:17:21Z
Deepturquoise
2456
25295
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|wawacan}}
:*''“ᮊᮙᮛᮤ ᮊᮥᮛᮤᮀ ᮙᮎ ᮝᮝᮎᮔ᮪ ᮝᮥᮜᮀ ᮒᮔᮤ, ᮉᮞᮤᮔ ᮍᮩᮔᮃᮔ᮪ ᮒᮒᮎᮛ ᮒᮔᮤ."''
:*''“ᮝᮝᮎᮔ᮪ ᮘᮁᮏᮂ ᮒᮦᮂ ᮘᮎᮃᮔ᮪ ᮃᮔᮥ ᮕᮤᮊᮛᮨᮞᮨᮕᮩᮔ᮪ ᮕᮤᮞᮔ᮪!"''
[[Kategori:WikiPrestasi]]
nobdez924xvu4bs0t62rp49qsp9pzo0
ᮃᮛᮤ
0
7559
25222
22303
2026-08-19T07:31:57Z
Deepturquoise
2456
25222
wikitext
text/x-wiki
=={{sunda}}==
{{-konjungsi-|su}}
* {{ka|ari}}
:* ''“'''ᮃᮛᮤ''' ᮕᮢᮧᮖ᮪ ᮓᮨᮓᮤ ᮙᮂ ᮔᮥ ᮊᮘᮨᮔᮨᮛᮔ᮪ ᮙᮞᮤᮂ ᮊᮥᮜᮝᮁᮌᮔ ᮄᮙᮔ᮪ ᮞᮄᮙᮔ᮪"''
:* ''“'''ᮃᮛᮤ''' ᮠᮒᮩᮕ᮪ ᮊᮤᮛᮚ᮪ ᮆᮒ, ᮃᮝᮦᮒ᮪ ᮙᮔᮔ᮪ ᮠᮒᮩᮕ᮪ ᮉᮛᮤᮂ (ᮝᮝᮎᮔ᮪ ᮝᮥᮜᮀ ᮒᮔᮤ, |᮱᮸᮶᮲|)"''
[[Kategori:WikiPrestasi]]
js02sn5e7od35img4un1bcvi7qvevpr
ᮃᮀᮌᮀ
0
7568
25216
22295
2026-08-19T07:29:24Z
Deepturquoise
2456
25216
wikitext
text/x-wiki
== {{sunda}} ==
{{-k s-|su}}
* {{ka|anggang}}
:* "ᮏᮅᮂ ᮓᮤᮏᮥᮌ᮪ᮏᮥᮌ᮪" ᮓᮔ᮪ " '''ᮃᮀᮌᮀ''' ᮓᮤᮒᮨᮃᮀ" (ᮕᮛᮤᮘᮞ)
[[Kategori:WikiPrestasi]]
pg8l6meu6qgnya64miq38jeg8xhf5c2
ᮃᮛᮔᮦᮂ
0
7570
25221
22302
2026-08-19T07:31:24Z
Deepturquoise
2456
25221
wikitext
text/x-wiki
== {{sunda}} ==
{{-k s-|su}}
* {{ka|aranéh}}
:* ᮃᮞ '''ᮃᮛᮔᮦᮂ''' ᮠᮝ ᮃᮔ᮪ᮒᮛ ᮠᮥᮏᮔ᮪ ᮜᮩᮒᮤᮊ᮪ ᮙᮀᮞ ᮄᮞᮥᮊ᮪ ᮔᮨᮕᮤᮊ ᮘᮩᮛᮀ
[[Kategori:WikiPrestasi]]
esm6x0ljhmfe3q7sefh92ihz7yqwxgq
ᮊᮛᮦᮞᮤᮓᮨᮔᮔ᮪
0
7575
25263
22324
2026-08-19T08:04:19Z
Deepturquoise
2456
25263
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|karésidenan}}
:* ᮥᮔᮌᮌᮃᮜ ᮙᮤᮔᮌᮌᮥ ᮃᮘᮓᮤ ᮧᮞᮧᮊ ᮜᮃᮛᮤ ᮓᮤ "ᮊᮛᮨᮞᮤᮓᮨᮔᮔ᮪" ᮊᮃᮘᮥᮕᮃᮒᮨᮔ ᮘᮃᮔᮓᮥᮔᮌ
:* "ᮊᮛᮨᮞᮤᮓᮨᮔᮔ᮪" ᮓᮤ ᮊᮃᮘᮥᮕᮃᮒᮨᮔ ᮘᮃᮔᮓᮥᮔᮌ ᮃᮚᮃᮔᮃ ᮓᮤ ᮞᮧᮛᮨᮃᮔᮌ
[[Kategori:WikiPrestasi]]
95yenr9yg6fji6z3cg53dvuul3qvisd
muncang
0
7620
25326
24869
2026-08-19T09:14:01Z
Adhiiik
2885
25326
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-muncang.wav}}
{{-k b-|su}}
*[[tangkal]], biasa sikina dipaké [[samara]]/[[bumbu]].
:* ''“Lamun nyieun sayur sop biasana maké muncang jeung [[pedes]]. "''
:* ''“Tangkal muncang téh biasana [[dipelak]] ku bapa di [[buruan]] "''
[[Kategori:WikiPrestasi]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
mdfseg0szco8a3o1fsdgh3702qz3m39
25327
25326
2026-08-19T09:15:02Z
Adhiiik
2885
25327
wikitext
text/x-wiki
=={{sunda}}==
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-muncang.wav}}
{{-k b-|su}}
* siki tina buah muncang anu cangkangna teuas, eusina bodas tur ngandung minyak, ilaharna sok dipaké pikeun bungbu dapur.
:* ''“Lamun nyieun sayur sop biasana maké muncang jeung [[pedes]]. "''
:* ''“Tangkal muncang téh biasana [[dipelak]] ku bapa di [[buruan]] "''
:* ''Réndos bawang beureum, bawang bodas, jeung '''muncang''' tepi ka lemes.''
:* ''Asakan ieu mah kudu maké '''muncang''' ngarah rasana leuwih gurih.''
[[Kategori:WikiPrestasi]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
92d1i1xd753kz1f0fpn9b8zwi566ns9
ᮕᮤᮔ᮪ᮎᮥᮊ᮪
0
7706
25277
23818
2026-08-19T08:11:51Z
Deepturquoise
2456
25277
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
* {{ka|pincuk}}
:* ''“ᮘᮥ ᮓᮨᮓᮨᮂ ᮍᮓᮙ᮪ᮘᮨᮜ᮪ ᮕᮄᮞ᮪ ᮃᮔᮥ ᮓᮤᮕᮤᮔ᮪ᮎᮥᮊ᮪"''
:* ''“ᮝᮜ᮪ᮓᮤ ᮙᮨᮞᮨᮁ ᮌᮧᮛᮨᮍᮔ᮪ ᮔᮥ ᮓᮤᮘᮥᮀᮊᮥᮞ᮪ ᮊᮥ ᮕᮤᮔ᮪ᮎᮥᮊ᮪"''
[[Kategori:WikiPrestasi]]
hctwi52qpqi69436jqpwaf8wgtid7pu
ᮒᮛᮦᮊᮂ
0
7707
25242
22340
2026-08-19T07:56:11Z
Deepturquoise
2456
25242
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
* {{ka|tarékah}}
:* ''“ᮊᮧᮜᮧᮒ᮪ ᮌᮩᮞ᮪ ᮔᮨᮃᮍᮔ᮪ ᮒᮛᮨᮊᮒ᮪ ᮕᮤᮊᮩᮔ᮪ ᮃᮔᮊ᮪ᮔ ᮊᮩᮁ ᮊᮠᮤᮛᮥᮕᮔᮔ"''
:* ''“ᮞᮃᮎᮔ᮪ ᮙᮤᮜᮤᮂ ᮊᮥᮜᮤᮃᮂ, ᮊᮥᮛᮤᮀ ᮍᮜᮊ᮪ᮞᮔᮊᮩᮔ᮪ ᮒᮛᮨᮊᮒ᮪"''
[[Kategori:WikiPrestasi]]
q1j83oly0548jph1fjpjlz367biia4v
ᮊᮛᮥᮌᮤᮃᮔ᮪
0
7710
25262
22323
2026-08-19T08:04:06Z
Deepturquoise
2456
25262
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|karugian}}
:* "ᮓᮓᮌᮍᮔ᮪ ᮒᮦᮂ ᮍᮜᮙᮔ᮪ ᮊᮛᮥᮌᮤᮃᮔ᮪."
:* "ᮊᮥᮛᮤᮀ ᮒᮦᮂ ᮙᮤᮔᮨᮀ ᮍᮜᮙᮔ᮪ ᮊᮛᮥᮌᮤᮃᮔ᮪."
[[Kategori:WikiPrestasi]]
4h8u9l9m7s5plx5v1wg5w78j7b4qrn4
ᮘᮒᮔ᮪
0
7716
25282
23643
2026-08-19T08:13:00Z
Deepturquoise
2456
25282
wikitext
text/x-wiki
=={{sunda}}==
{{-konjungsi-|su}}
*{{ka|batan}}
:*"ᮒᮤ ᮘᮒᮔ᮪ ᮊᮤᮒᮥ ᮙᮂ, ᮊᮥᮛᮤᮀ ᮙᮨᮔ᮪ᮓᮤᮀ ᮒᮩ ᮕᮥᮛᮥᮔ᮪ ᮄᮔ᮪ᮓᮤᮒ᮪ᮔ."
:*"ᮌᮧᮛᮦᮀ ᮃᮓᮒ᮪ ᮒᮤ ᮘᮒᮔ᮪ ᮏᮩᮀ ᮃᮓᮤ-ᮃᮓᮤᮔ ᮘᮥᮓᮊ᮪ ᮒᮦᮂ. ᮙᮔᮨᮂᮔ ᮒᮩ ᮃᮝᮙ᮪ ᮏᮩᮀ ᮘᮒᮥᮁ."
[[Kategori:WikiPrestasi]]
2o89cr3hw19t5f6quqbu79ryk8dmdyp
ᮍᮤᮃᮀᮊᮩᮔ᮪
0
7719
25236
22341
2026-08-19T07:53:24Z
Deepturquoise
2456
25236
wikitext
text/x-wiki
=={{sunda}}==
{{-k k-|su}}
* {{ka|ngiangkeun}}
:* “ᮕ ᮛᮦᮊ᮪ᮒᮧᮁ ᮍᮤᮃᮀᮊᮩᮔ᮪ ᮙᮠᮞᮤᮞ᮪ᮝ ᮘᮨᮁᮕᮢᮦᮞ᮪ᮒᮞᮤ ᮊ ᮘᮨᮜᮔ᮪ᮓ."
:* “ᮃᮘᮂ ᮒᮒ ᮄᮞᮥᮊ᮪ ᮊᮦᮔᮦᮂ ᮌᮩᮞ᮪ ᮍᮤᮃᮀᮊᮩᮔ᮪ ᮞᮧᮃᮀ ᮊ ᮘᮜᮧᮀ."
[[Kategori:WikiPrestasi]]
fe3s4t98uyzc3uvomlmnodv0nup9y5x
ᮊᮛᮩᮉᮒ᮪
0
7725
25264
22315
2026-08-19T08:04:58Z
Deepturquoise
2456
25264
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|kareueut}}
:* ''“ᮘᮥᮃᮂ ᮃᮛᮧᮙᮔᮤᮞ᮪ ᮒᮦᮂ ᮙᮩᮔᮤ ᮊᮛᮩᮉᮒ᮪"''
:* ''“ᮙᮓᮥ ᮛᮞᮔ ᮊᮛᮩᮉᮒ᮪ ᮕᮤᮞᮔ᮪"''
[[Kategori:WikiPrestasi]]
1sjfqc4xbtzov9ke108k0q25vwdmzvh
ᮊᮒᮕᮀ
0
7732
25256
24778
2026-08-19T08:02:36Z
Deepturquoise
2456
25256
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|katapang}}
:* "ᮞᮤ ᮘᮕ ᮒᮓᮤ ᮔᮥᮃᮁ ᮒᮀᮊᮜ᮪"
:* "ᮘᮥᮃᮂ ᮊᮒᮕᮀ ᮒᮦᮂ ᮒᮩᮃᮞ᮪"
[[Kategori:WikiPrestasi]]
oy24dzqgtfu1aulwincupgwqedygae6
ᮊᮛᮥᮀ
0
7748
25261
22322
2026-08-19T08:03:51Z
Deepturquoise
2456
25261
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|karung}}
:* "ᮕᮀ ᮙᮝᮊᮩᮔ᮪ ᮊᮛᮥᮀ!"
:* "ᮊᮛᮥᮀ ᮒᮦᮂ ᮓᮧᮘᮧᮜ᮪"
[[Kategori:WikiPrestasi]]
rnu5pvl0eqqflfi6qqpfdqcn6h7crds
ᮕᮛᮔ᮪ᮒᮤ
0
7760
25275
23650
2026-08-19T08:11:03Z
Deepturquoise
2456
25275
wikitext
text/x-wiki
=={{sunda}}==
{{-k k-|su}}
*{{ka|paranti}}
:*"ᮞᮤᮙ᮪ᮕᮨᮔ᮪ ᮘᮆ ᮊᮔ ᮏᮨᮛᮧ ᮘᮧᮘᮧᮊᮧ, ᮊᮕᮔ᮪ ᮆᮒ ᮕᮛᮔ᮪ᮒᮤ ᮞᮥᮙ᮪ᮕᮔ᮪-ᮞᮤᮙ᮪ᮕᮨᮔ᮪."
:*"ᮄᮉ ᮕᮔ᮪ᮎᮤ ᮕᮛᮔ᮪ᮒᮤ ᮞᮧᮕ᮪, ᮅᮜᮂ ᮓᮤᮕᮊᮦ ᮊᮩᮁ ᮍᮝᮓᮠᮔ᮪ ᮃᮔᮥ ᮞᮦᮏᮦᮔ᮪."
[[Kategori:WikiPrestasi]]
apoesv2rx31m1d61h0oefb7ba6dwjj3
ᮞᮘᮧᮘᮧᮊᮧ
0
7761
25312
22363
2026-08-19T08:23:44Z
Deepturquoise
2456
25312
wikitext
text/x-wiki
=={{sunda}}==
{{-k bl-|su}}
*{{ka|saboboko}}
:*''"ᮞᮤ ᮅᮓᮤᮔ᮪ ᮃᮛᮤ ᮓᮠᮁ ᮒᮦᮂ ᮞᮧᮊ᮪ ᮙᮦᮃᮊᮩᮔ᮪, ᮔᮨᮕᮤᮊ ᮞᮘᮧᮘᮧᮊᮧ ᮘᮦᮃᮊ᮪."''
:*''"ᮄᮉ ᮞᮍᮥ ᮞᮘᮧᮘᮧᮊᮧ ᮞᮠ ᮔᮥ ᮆᮛᮦᮊ᮪ ᮙᮦᮃᮊᮩᮔ᮪?."''
[[Kategori:WikiPrestasi]]
ef9qnx573uwb6ujkq5r7mb4x4nw5fm0
ᮜᮧᮓᮧᮀ
0
7763
25293
23570
2026-08-19T08:16:52Z
Deepturquoise
2456
25293
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|lodong}}
:* ''“ᮌᮩᮛ ᮝᮓᮠᮔ᮪ ᮆᮒ ᮜᮠᮀ ᮊᮔ ᮜᮧᮓᮧᮀ!"''
:* ''“ᮆᮒ ᮜᮧᮓᮧᮀ ᮒᮦᮂ ᮝᮓᮂ ᮠᮩᮜᮀ?"''
[[Kategori:WikiPrestasi]]
hurs6o662la62t57ti02ka49lx0nwfu
ᮛᮥᮙ᮪ᮘᮊ᮪
0
7774
25289
23388
2026-08-19T08:15:44Z
Deepturquoise
2456
25289
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|rumbak}}
:* ''“ᮒᮀᮊᮜ᮪ ᮎᮛᮤᮍᮤᮔ᮪ ᮃᮔᮥ ᮓᮤ ᮓᮩᮊᮩᮒ᮪ ᮞᮊᮧᮜ ᮒᮦᮂ ᮃᮚᮩᮔ ᮙᮂ ᮌᮩᮞ᮪ ᮜᮤᮜ ᮛᮥᮙ᮪ᮘᮊ᮪"''
:* ''“ᮊᮙᮛᮤ ᮒᮀᮊᮜ᮪ ᮏᮙ᮪ᮘᮥ ᮌᮩᮞ᮪ ᮛᮥᮙ᮪ᮘᮊ᮪ ᮊᮥ ᮃᮍᮤᮔ᮪ ᮌᮨᮓᮦ"''
[[Kategori:WikiPrestasi]]
f5luerho2io1560wpc3h0wsvlo6wg9d
ᮇᮀᮊᮧᮞ᮪
0
7778
25232
22313
2026-08-19T07:50:26Z
Deepturquoise
2456
25232
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|ongkos}}
:* ''“ᮔᮜᮤᮊ ᮘᮜᮤᮊ᮪ ᮊ ᮜᮨᮙ᮪ᮘᮥᮁ ᮒᮨᮂ ᮊᮥᮓᮥ ᮍᮜᮥᮃᮁᮊᮩᮔ᮪ ᮓᮥᮄᮒ᮪ ᮊᮩᮁ ᮇᮀᮊᮧᮞ᮪ ᮙᮧᮘᮤᮜ᮪ ᮒᮢᮗᮨᮜ᮪"''
:* ''“ᮘᮕ ᮔᮙ᮪ᮘᮠᮔ᮪ ᮇᮀᮊᮧᮞ᮪ ᮊᮩᮁ ᮍᮤᮛᮤᮙ᮪ ᮘᮛᮀ"''
[[Kategori:WikiPrestasi]]
te0s05qaw667rdm5o0ykgxi197cdjma
ᮞᮒᮅᮔ᮪
0
7780
25316
23396
2026-08-19T08:24:34Z
Deepturquoise
2456
25316
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|sataun}}
:* ''“ᮌᮩᮞ᮪ ᮞᮒᮅᮔ᮪ ᮔᮘᮤᮜ ᮒᮩ ᮅᮄᮂ ᮊ ᮘᮥᮙᮤᮔ."''
:* ''“ᮞᮒᮅᮔ᮪ ᮓᮩᮄ ᮔᮘᮤᮜ ᮜᮥᮜᮥᮞ᮪ ᮊᮥᮜᮤᮃᮂ ᮞᮁᮏᮔ."''
[[Kategori:WikiPrestasi]]
iah329pyzq6cmb1b2rrrkrz9u18m8jm
ᮊᮏᮩᮔ᮪
0
7783
25254
22318
2026-08-19T08:02:04Z
Deepturquoise
2456
25254
wikitext
text/x-wiki
=={{sunda}}==
{{-konjungsi-|su}}
*{{ka|kajeun}}
:* ''“ᮊᮏᮩᮔ᮪ ᮃᮂ ᮒᮩ ᮓᮤᮘᮦᮛᮦᮞᮔ᮪ ᮌᮨ, ᮊᮦ ᮊᮥ ᮞᮤ ᮘᮤᮘᮤ."
:* ''“ᮊᮏᮩᮔ᮪ ᮏᮅᮂ ᮌᮦ ᮊᮥ ᮊᮥᮛᮤᮀ ᮛᮦᮊ᮪ ᮓᮤᮏᮥᮌ᮪ᮏᮥᮌ᮪."
[[Kategori:WikiPrestasi]]
9bqc9ao0q2mhntrf0f33dn2wfh6ynw3
ᮒᮦᮛᮦᮂ
0
7784
25247
22562
2026-08-19T07:58:31Z
Deepturquoise
2456
25247
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|téréh}}
:*''"ᮃᮜᮥᮞ᮪ ᮉᮚ᮪ ᮞᮤ ᮆᮒ ᮙᮂ ᮒᮦᮛᮦᮂ ᮍᮨᮁᮏᮊᮩᮔ᮪ ᮒᮥᮌᮞ᮪ ᮒᮦᮂ."''
:*''"ᮃᮛᮤ ᮙᮔᮦᮂ ᮞᮧᮜᮒ᮪ ᮒᮦᮂ ᮒᮦᮛᮦᮂ-ᮒᮦᮛᮦᮂ ᮒᮩᮄᮀ."''
[[Kategori:WikiPrestasi]]
0t2e5fuhfu7ymybic6xdmf58mfq7dt4
Citakan:ka
10
7802
25215
24811
2026-08-19T07:26:29Z
Deepturquoise
2456
25215
wikitext
text/x-wiki
<includeonly>''Éjahan [[w:su:Aksara Sunda Baku|aksara Sunda]] tina kecap'' '''[[{{{1}}}]]'''
[[Kategori:Kecap {{su}} dina aksara Sunda]]</includeonly>
<noinclude>
{{documentation}}
[[Kategori:Citakan]]
</noinclude>
962f2n10u2sbzc4kf036tvhbuzm2dac
25303
25215
2026-08-19T08:19:21Z
Deepturquoise
2456
25303
wikitext
text/x-wiki
<includeonly>''Éjahan [[w:su:Aksara Sunda Baku|aksara Sunda]] tina kecap'' '''[[{{{1}}}]]'''
[[Kategori:Kecap dina aksara Sunda]]</includeonly>
<noinclude>
{{documentation}}
[[Kategori:Citakan]]
</noinclude>
e3l18hea2hxyu59gbu828wzx3vnwwnx
ᮞᮤᮙ᮪ᮘᮥᮒ᮪
0
7861
25305
23537
2026-08-19T08:21:32Z
Deepturquoise
2456
25305
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|simbut}}
:* ''ᮄᮞᮥᮊ᮪-ᮞᮥᮊ᮪ ᮎᮩ ᮠᮏᮤ ᮌᮩᮞ᮪ ᮙᮧᮆ ᮞᮤᮙ᮪ᮘᮥᮒ᮪ ᮓᮤ ᮠᮛᮩᮕᮩᮔ᮪ ᮄᮙᮂᮔ''
:* ''ᮞᮤᮙ᮪ᮘᮥᮒ᮪ ᮓᮤᮔ ᮞᮨᮞᮨᮛᮠᮔ᮪ ᮒᮦᮂ ᮓᮤᮏᮤᮉᮔ᮪ ᮎᮤᮌᮂ ᮞᮧᮃᮀ''
{{s|ᮊᮙ᮪ᮕᮥᮂ}}
[[Kategori:WikiPrestasi]]
ephlzkdkwaoj37m303qyfwe8fah5x6v
ᮕᮚᮥ
0
7869
25274
23534
2026-08-19T08:10:43Z
Deepturquoise
2456
25274
wikitext
text/x-wiki
=={{sunda}}==
{{-nomina-|su}}
*{{ka|payu}}
:* ''“ᮃᮛᮤ ᮓᮌᮍᮔ᮪ ᮞᮨᮘᮣᮊ᮪ ᮊᮙᮛᮤ ᮕᮚᮥ ᮜᮧᮘ? "''
:* ''“ᮙᮥᮔ᮪ ᮠᮚᮀ ᮕᮚᮥ ᮜᮧᮘ, ᮊᮥᮓᮥ ᮏᮥᮃᮜᮔ᮪ ᮓᮤ ᮒᮨᮙ᮪ᮕᮒ᮪ ᮔᮥ ᮛᮙᮦ."''
[[Kategori:WikiPrestasi]]
ql1ckuysgrw4rtutrb388izjpiyhptu
ᮎᮤᮜᮩᮔ᮪ᮎᮀ
0
7872
25239
23556
2026-08-19T07:54:33Z
Deepturquoise
2456
25239
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|cileuncang}}
:*''“ᮔᮥ ᮕᮜᮤᮓ᮪ ᮒᮤᮔ ᮅᮞᮥᮙ᮪ ᮠᮥᮏᮔ᮪ ᮒᮤ ᮕᮞᮤᮁ ᮒᮦᮂ ᮃᮚᮩᮔ ᮙᮂ ᮜᮄᮔ᮪ ᮅᮊᮥᮁ ᮎᮤᮜᮩᮔ᮪ᮎᮀ."''
:*''“ᮠᮛᮤᮒ, ᮙᮔᮦᮂᮔ ᮔᮠᮩᮔ᮪ ᮓᮩᮄ ᮘᮥᮘᮥ ᮊᮩᮁ ᮙᮥᮞᮤᮙ᮪ ᮠᮥᮏᮔ᮪, ᮎᮤᮜᮩᮔ᮪ᮎᮀ ᮌᮨᮓᮦ ᮊᮝᮞ᮪ ᮎᮃᮂ."''
[[Kategori:WikiPrestasi]]
bbf78pvgyi0zdw0x9nkcaqek3w0ub60
ᮅᮔ᮪ᮎᮜ᮪
0
7883
25226
22683
2026-08-19T07:47:06Z
Deepturquoise
2456
25226
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
# {{ka|unggal}}
[[Kategori:WikiPrestasi]]
mll9lcqgtfj1f5bno1wecd5vcuazviw
ᮊᮔᮛᮤ
0
7885
25258
22686
2026-08-19T08:03:10Z
Deepturquoise
2456
25258
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
* {{ka|kanari}}
[[Kategori:WikiPrestasi]]
4j9ecp7n0vo0s9zvlfxqo3w7l22zk1f
ᮊᮥᮙᮨᮜᮤ
0
7887
25268
22692
2026-08-19T08:06:16Z
Deepturquoise
2456
25268
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|kumeli}}
[[Kategori:WikiPrestasi]]
g2y6mgjrmnb6yypn828tenvtl96jwex
ᮙᮔ᮪ᮒᮦᮌ
0
7889
25285
22743
2026-08-19T08:15:01Z
Deepturquoise
2456
25285
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|mantéga}}
[[Kategori:WikiPrestasi]]
l2f87dnmh8t1pwarkzlei82v3ezzoh5
ᮙᮥᮍ᮪ᮌᮛᮔ᮪
0
7890
25287
22745
2026-08-19T08:15:18Z
Deepturquoise
2456
25287
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|munggaran}}
[[Kategori:WikiPrestasi]]
sh840sz8834llfp4349dzz8gvywtjlj
ᮓᮤᮌᮥᮛᮤᮒ᮪
0
7906
25249
22714
2026-08-19T07:58:56Z
Deepturquoise
2456
25249
wikitext
text/x-wiki
=={{sunda}}==
{{-k k-|su}}
*{{ka|digurit}}
[[Kategori:WikiPrestasi]]
mwy000832oal0t4b3l4sr7o0zisb0r5
ᮓᮤᮒᮥᮠᮥᮁᮊᮩᮔ᮪
0
7907
25250
22716
2026-08-19T07:59:08Z
Deepturquoise
2456
25250
wikitext
text/x-wiki
=={{sunda}}==
{{-k k-|su}}
*{{ka|dituhurkeun}}
[[Kategori:WikiPrestasi]]
4mcxhhbgfoomqfouxvk8xuc78hlxi6b
ᮠᮒᮥᮁ
0
7908
25300
22765
2026-08-19T08:18:12Z
Deepturquoise
2456
25300
wikitext
text/x-wiki
=={{sunda}}==
{{-pronomina-|su}}
*{{ka|hatur}}
[[Kategori:WikiPrestasi]]
mzv4xs20xfj1ecd5bbq87rwxz00hfcw
ᮊᮧᮕᮤ
0
7909
25251
22693
2026-08-19T08:01:11Z
Deepturquoise
2456
25251
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|kopi}}
[[Kategori:WikiPrestasi]]
f4sbar4ma04atdamm48h3w4jvvmmg1b
ᮊᮥᮓ
0
7910
25266
22691
2026-08-19T08:05:32Z
Deepturquoise
2456
25266
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|kuda}}
[[Kategori:WikiPrestasi]]
ju9tgos54ot7mbpn5x0ozhe0sotisp0
ᮜᮜᮁ
0
7911
25291
22749
2026-08-19T08:16:02Z
Deepturquoise
2456
25291
wikitext
text/x-wiki
=={{sunda}}==
{{-k p-|su}}
*{{ka|lalar}}
[[Kategori:WikiPrestasi]]
oxhhux1h4et2b08emefjg6uth256nez
ᮜᮤᮜᮤᮁ
0
7912
25292
22750
2026-08-19T08:16:29Z
Deepturquoise
2456
25292
wikitext
text/x-wiki
=={{sunda}}==
{{-k p-|su}}
*{{ka|lilir}}
[[Kategori:WikiPrestasi]]
bcu5d6ankvvfk944hh66xbzn098zmod
ᮍᮧᮛᮦᮓ᮪
0
7913
25237
22700
2026-08-19T07:53:42Z
Deepturquoise
2456
25237
wikitext
text/x-wiki
=={{sunda}}==
{{-k p-|su}}
*{{ka|ngoréd}}
[[Kategori:WikiPrestasi]]
cyj5tah4mr8hr3oiqslsfuypoyeml87
ᮕᮢᮤᮘᮥᮙᮤ
0
7914
25276
22725
2026-08-19T08:11:27Z
Deepturquoise
2456
25276
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|pribumi}}
[[Kategori:WikiPrestasi]]
58q2f766ox644kt8e7ctt0dci0mcoa3
ᮕᮥᮕᮥᮂ
0
7915
25279
22729
2026-08-19T08:12:12Z
Deepturquoise
2456
25279
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|pupuh}}
[[Kategori:WikiPrestasi]]
3p5v6p3vxlpooglpko7k6qawf96yh17
ᮞᮊᮥᮁ
0
7916
25318
22754
2026-08-19T08:24:53Z
Deepturquoise
2456
25318
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|sakur}}
[[Kategori:WikiPrestasi]]
jgoiz6ahk3y67f1vzur1wf15mo33frw
ᮞᮙᮤᮀᮌᮥ
0
7917
25311
22758
2026-08-19T08:23:30Z
Deepturquoise
2456
25311
wikitext
text/x-wiki
=={{sunda}}==
{{-k bl-|su}}
*{{ka|saminggu}}
[[Kategori:WikiPrestasi]]
tprcf4xsgqmyci73vk3tajrny9jikdm
ᮞᮕᮤ
0
7918
25315
22755
2026-08-19T08:24:21Z
Deepturquoise
2456
25315
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|sapi}}
[[Kategori:WikiPrestasi]]
4ln93bxel9komwgh9y7clu135kel335
ᮞᮕᮧᮕᮧᮆ
0
7919
25313
22757
2026-08-19T08:23:52Z
Deepturquoise
2456
25313
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|sapopoé}}
[[Kategori:WikiPrestasi]]
so09rspavhol5c9dfjn5n5kzsa7gfej
ᮞᮝᮂ
0
7920
25309
22759
2026-08-19T08:23:15Z
Deepturquoise
2456
25309
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|sawah}}
[[Kategori:WikiPrestasi]]
sp37xon5j4rams5zhq9xwdaluhddrna
ᮞᮝᮛᮦᮂ
0
7921
25308
22760
2026-08-19T08:22:27Z
Deepturquoise
2456
25308
wikitext
text/x-wiki
=={{sunda}}==
{{-k bl-|su}}
*{{ka|sawaréh}}
[[Kategori:WikiPrestasi]]
clfrd3h8ai45hffftstqqyeh521uwk2
ᮒᮦᮙ᮪ᮘᮧᮍ᮪
0
7924
25246
22711
2026-08-19T07:58:13Z
Deepturquoise
2456
25246
wikitext
text/x-wiki
=={{sunda}}==
{{-k p-|su}}
*{{ka|témbong}}
[[Kategori:WikiPrestasi]]
onkambqq5rl37yb3414cw7dl3f8qvxq
ᮒᮧᮠᮌ
0
7925
25248
22712
2026-08-19T07:58:45Z
Deepturquoise
2456
25248
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|tohaga}}
[[Kategori:WikiPrestasi]]
rafwyvzzyxxftelpsyl6cwagipn9t6a
ᮒᮥᮀᮊᮥᮜ᮪
0
7926
25245
22710
2026-08-19T07:57:59Z
Deepturquoise
2456
25245
wikitext
text/x-wiki
=={{sunda}}==
{{-k p-|su}}
*{{ka|tungkul}}
[[Kategori:WikiPrestasi]]
7qwlo809kcd52tvwulcm5vlxneogkor
ᮝᮒᮛ
0
7927
25294
22751
2026-08-19T08:16:59Z
Deepturquoise
2456
25294
wikitext
text/x-wiki
=={{sunda}}==
{{-k bl-|su}}
*{{ka|watara}}
[[Kategori:WikiPrestasi]]
ge8n7ok7eazxnhgsmxpvbhv7q9csx2z
ᮠᮩᮛᮤᮔ᮪
0
7933
25284
23825
2026-08-19T08:14:52Z
Deepturquoise
2456
25284
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|heurin}}
:* ''"ᮏᮜᮔ᮪ ᮊ ᮄᮙᮂ ᮒᮦᮂ ᮠᮩᮛᮤᮔ᮪ ᮕᮤᮞᮔ᮪"''
:* ''“ᮊᮙᮁᮔ ᮠᮩᮛᮤᮔ᮪ ᮏᮓᮤ ᮠᮦᮞᮦ ᮌᮨᮛᮊ᮪"''
[[Kategori:WikiPrestasi]]
axxin7riihjpini7ibcui44d9lsgygr
ᮕᮦᮓᮂ
0
7942
25280
22730
2026-08-19T08:12:26Z
Deepturquoise
2456
25280
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|pédah}}
[[Kategori:WikiPrestasi]]
40bscc5yduhkhop3vwrxcpttidcw6jj
ᮒᮤᮒᮦᮔ᮪
0
7949
25244
22708
2026-08-19T07:57:47Z
Deepturquoise
2456
25244
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|titén}}
[[Kategori:WikiPrestasi]]
rcafdjhr54ygkh5myveuxkgppbjmn43
ᮒᮤᮊᮨᮜ᮪
0
7950
25243
22706
2026-08-19T07:56:22Z
Deepturquoise
2456
25243
wikitext
text/x-wiki
=={{sunda}}==
{{-k bl-|su}}
*{{ka|tikel}}
[[Kategori:WikiPrestasi]]
g1c0e11yoo8ae7bmxkggmy67nrfv5lj
ᮞᮕᮦᮞᮦᮁ
0
7951
25314
22756
2026-08-19T08:24:01Z
Deepturquoise
2456
25314
wikitext
text/x-wiki
=={{sunda}}==
{{-k bl-|su}}
*{{ka|sapésér}}
[[Kategori:WikiPrestasi]]
szu9x17ix2wj1v5ygoi5n78ztus33fa
ᮞᮉᮁ
0
7952
25299
22753
2026-08-19T08:18:00Z
Deepturquoise
2456
25299
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|saeur}}
[[Kategori:WikiPrestasi]]
dvd18weu4r7eowf834hn85m9doelkpe
ᮕᮤᮛᮩ
0
7953
25278
22727
2026-08-19T08:12:02Z
Deepturquoise
2456
25278
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|pireu}}
[[Kategori:WikiPrestasi]]
tc36f35tomr344wp61elq668nnyl5h2
ᮕᮧᮜ᮪ᮙᮊ᮪
0
7954
25281
22731
2026-08-19T08:12:37Z
Deepturquoise
2456
25281
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|polmak}}
[[Kategori:WikiPrestasi]]
d3dabgljaagafx0zdnhxhj770hx3pjl
ᮙᮞᮤᮌᮤᮒ᮪
0
7961
25286
22744
2026-08-19T08:15:10Z
Deepturquoise
2456
25286
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|masigit}}
[[Kategori:WikiPrestasi]]
qiofa4yzxx3tqq6xmj1lsp0bphdnqrb
ᮍᮌᮥᮔ᮪ᮓᮥᮊ᮪
0
7962
25235
22697
2026-08-19T07:52:48Z
Deepturquoise
2456
25235
wikitext
text/x-wiki
=={{sunda}}==
{{-k p-|su}}
* {{ka|ngagunduk}}
[[Kategori:WikiPrestasi]]
tlrvz08j5kwgxpigrcepy8s7nuoc59c
ᮕᮘᮥᮛᮔ᮪ᮒᮊ᮪
0
7963
25273
22721
2026-08-19T08:09:44Z
Deepturquoise
2456
25273
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|paburantak}}
[[Kategori:WikiPrestasi]]
3t57kean4u8fo4afmliyyftlp4p7cqb
ᮕᮊᮚ
0
7964
25271
22719
2026-08-19T08:08:58Z
Deepturquoise
2456
25271
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|pakaya}}
[[Kategori:WikiPrestasi]]
2dy0f8lrx58bk3obxsodqpvea94rjs4
ᮕᮀᮊᮦᮀ
0
7965
25270
22718
2026-08-19T08:08:46Z
Deepturquoise
2456
25270
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|pangkéng}}
[[Kategori:WikiPrestasi]]
pxyfr2u5hdfq5m50q5scxs4glxd1p1e
ᮕᮑᮨᮜᮀ
0
7966
25272
23545
2026-08-19T08:09:33Z
Deepturquoise
2456
25272
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|panyelang}}
:*ᮞᮥᮙᮝᮧᮔ ᮊᮥᮓᮥ ᮍᮌᮨᮓᮦᮊᮩᮔ᮪ ᮙᮨᮜᮊ᮪ ᮊᮎᮀ ᮞᮥᮅᮊ᮪ ᮃᮔᮥ ᮒᮦᮛᮦᮂ ᮊᮃᮜ ᮠᮞᮤᮜ᮪ᮔ, ᮞᮥᮕᮚ ᮘᮩᮔᮀ ᮓᮤᮕᮊᮦ ᮕᮙᮨᮜᮊ᮪ ᮕᮑᮨᮜᮀ ᮓᮤ ᮞᮝᮂ
[[Kategori:WikiPrestasi]]
60gk6gvosp906ix6yy49t8wob1r9brr
ᮜᮔ᮪ᮒᮤᮕ᮪
0
7972
25290
22748
2026-08-19T08:15:53Z
Deepturquoise
2456
25290
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
*{{ka|lantip}}
[[Kategori:WikiPrestasi]]
p7mgpk36lj2jztqzs81ay3pooi8681t
ᮊᮔ᮪ᮒᮥᮔ᮪
0
7973
25260
22687
2026-08-19T08:03:37Z
Deepturquoise
2456
25260
wikitext
text/x-wiki
=={{sunda}}==
{{-adverb-|su|num= anteb}}
*{{ka|kantun}}
[[Kategori:WikiPrestasi]]
le254vw3gkn79zn72gh73y9jck4y9ym
ᮊᮜᮤᮊᮤ
0
7974
25265
22689
2026-08-19T08:05:13Z
Deepturquoise
2456
25265
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|kaliki}}
[[Kategori:WikiPrestasi]]
c9ppnqzv22536xo67el9u64olnl1hfa
ᮏᮊ᮪ᮞᮤ
0
7975
25240
22705
2026-08-19T07:54:49Z
Deepturquoise
2456
25240
wikitext
text/x-wiki
=={{sunda}}==
{{-k b-|su}}
*{{ka|jaksi}}
[[Kategori:WikiPrestasi]]
cf23u90siz1n3aoj9hqnp2fbc4tci65
ᮎᮤᮊ᮪
0
7976
25238
22703
2026-08-19T07:53:55Z
Deepturquoise
2456
25238
wikitext
text/x-wiki
=={{sunda}}==
{{-konjungsi-|su}}
*{{ka|cik}}
[[Kategori:WikiPrestasi]]
2a9wm584c3my5kvrc6ctgxjappki4rg
ᮃᮒᮧᮂ
0
7978
25220
22682
2026-08-19T07:30:55Z
Deepturquoise
2456
25220
wikitext
text/x-wiki
=={{sunda}}==
{{-k s-|su}}
# {{ka|atoh}}
[[Kategori:WikiPrestasi]]
5x7ddmf0cokpqbpl6k1gegrh774wn4j
cengkeh
0
8299
25332
24822
2026-08-19T09:20:00Z
Adhiiik
2885
25332
wikitext
text/x-wiki
=={{bahasa|jax}}==
{{kepala|jax}}
: {{audio|jax|LL-Q3915769 (jax)-YOGI NUGRAHA PUTRA-kayu manis.wav}}
{{nomina|jax}}
# cengkéh
[[Kategori:WikiMaknyus Jambi]]
[[Kategori:WikiMaknyus]]
=={{bahasa|jv}}==
{{kepala|jv}}
: {{audio|jav|LL-Q33549 (jav)-Ifah36-cengkeh.wav}}
{{nomina|jv}}
# cengkeh
=={{bahasa|su}}==
{{kepala|su}}
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-cengkéh.wav}}
{{-k b-|su}}
* kembang tina tangkal cengkéh anu geus digaringkeun, ilaharna sok dipaké pikeun bungbu, ubar, atawa campuran ududeun.
=== Tingkatan basa ===
* '''cengkéh''' : basa loma jeung lemes
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|cengkih}}
{{)}}
[[Kategori:WikiMaknyus Banjarnegara]]
[[Kategori:WikiMaknyus]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
7fpn4dk1pypsd2ogno4ran10gvz4oy0
25333
25332
2026-08-19T09:20:08Z
Adhiiik
2885
25333
wikitext
text/x-wiki
=={{bahasa|jax}}==
{{kepala|jax}}
: {{audio|jax|LL-Q3915769 (jax)-YOGI NUGRAHA PUTRA-kayu manis.wav}}
{{nomina|jax}}
# cengkéh
[[Kategori:WikiMaknyus Jambi]]
[[Kategori:WikiMaknyus]]
=={{bahasa|jv}}==
{{kepala|jv}}
: {{audio|jav|LL-Q33549 (jav)-Ifah36-cengkeh.wav}}
{{nomina|jv}}
# cengkeh
=={{bahasa|su}}==
{{kepala|su}}
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-cengkéh.wav}}
{{-k b-|su}}
* kembang tina tangkal cengkéh anu geus digaringkeun, ilaharna sok dipaké pikeun bungbu, ubar, atawa campuran ududeun.
:* ''Pangmeulikeun '''cengkéh''' ka warung keur campuran nyieun kuéh.''
:* ''Cai wedang téh leuwih haneut kana awak lamun dicampuran ku '''cengkéh'''.''
=== Tingkatan basa ===
* '''cengkéh''' : basa loma jeung lemes
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|cengkih}}
{{)}}
[[Kategori:WikiMaknyus Banjarnegara]]
[[Kategori:WikiMaknyus]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
trpwyvh7ixs65peb4eaury37tn92snp
25334
25333
2026-08-19T09:20:19Z
Adhiiik
2885
25334
wikitext
text/x-wiki
=={{bahasa|jax}}==
{{kepala|jax}}
: {{audio|jax|LL-Q3915769 (jax)-YOGI NUGRAHA PUTRA-kayu manis.wav}}
{{nomina|jax}}
# cengkéh
[[Kategori:WikiMaknyus Jambi]]
[[Kategori:WikiMaknyus]]
=={{bahasa|jv}}==
{{kepala|jv}}
: {{audio|jav|LL-Q33549 (jav)-Ifah36-cengkeh.wav}}
{{nomina|jv}}
# cengkeh
=={{bahasa|su}}==
{{kepala|su}}
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-cengkéh.wav}}
{{-k b-|su}}
* kembang tina tangkal cengkéh anu geus digaringkeun, ilaharna sok dipaké pikeun bungbu, ubar, atawa campuran ududeun.
:* ''Pangmeulikeun '''cengkéh''' ka warung keur campuran nyieun kuéh.''
:* ''Cai wedang téh leuwih haneut kana awak lamun dicampuran ku '''cengkéh'''.''
=== Tingkatan basa ===
* '''cengkéh''' : basa loma jeung lemes
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|cengkih}}
{{)}}
[[Kategori:WikiMaknyus Banjarnegara]]
[[Kategori:WikiMaknyus]]
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
77k3oki8zgod8bryjsaluaa6g7gvhgh
ᮙᮨᮜᮩᮊ᮪ᮙᮩᮊ᮪
0
8392
25288
23569
2026-08-19T08:15:27Z
Deepturquoise
2456
25288
wikitext
text/x-wiki
=={{sunda}}==
{{-nomina-|su}}
*{{ka|meleukmeuk}}
9rnky1hrpz8accw1ehhjn6q68oehtje
tahu
0
8579
25319
24817
2026-08-19T09:04:44Z
Adhiiik
2885
25319
wikitext
text/x-wiki
=={{bahasa|xmm}}==
{{kepala|xmm}}
: {{audio|xmm|LL-Q9240 (ind)-Manadonese-Tahu.wav}}
{{nomina|xmm}}
# tahu
[[Kategori:WikiMaknyus Manado]]
[[Kategori:WikiMaknyus]]
=={{bahasa|jv}}==
{{kepala|jv}}
: {{audio|jav|LL-Q33549 (jav)-Riatunsk-tahu.wav}}
{{verba|jv}}
# tahu
[[Kategori:WikiMaknyus Banjarnegara]]
[[Kategori:WikiMaknyus]]
=={{bahasa|su}}==
{{kepala|su}}
: {{audio|jav|LL-Q34002 (sun)-Adhiiik-tahu.wav}}
{{-k b-|su}}
* kadaharan anu dijieun tina sari kacang kedelé anu diendapkeun sarta dicitak.
:* ''Uing keur ngadahar sangu maké '''tahu'''.''
:* ''Tukang '''tahu''' Sumedang mah biasana loba nu jualan di sisi jalan.''
=== Tingkatan basa ===
* '''tahu''' : basa loma jeung lemes
{{tarjemahan}}
{{(}}
* {{id}} : {{trad-|id|tahu}}
{{)}}
[[Category:WikiRempah]]
[[Category:WikiRempah Bandung]]
tcwhc1zwplitwch8oax5p8pg0r9uxr6
ᮠᮛᮦᮆᮀ
0
8729
25301
24331
2026-08-19T08:18:26Z
Deepturquoise
2456
25301
wikitext
text/x-wiki
=={{sunda}}==
{{-adjektiva-|su}}
*{{ka|harééng}}
om4m762ohx0b49lyhirv80mtye7q6xu
ᮞᮛᮒ᮪
0
8734
25310
24339
2026-08-19T08:23:23Z
Deepturquoise
2456
25310
wikitext
text/x-wiki
=={{sunda}}==
{{-nomina-|su}}
*{{ka|sarat}}
daz93mhjuzo94l10r4jhw9yki0bdxr7
ᮒᮒᮥ
0
8738
25241
24347
2026-08-19T07:55:54Z
Deepturquoise
2456
25241
wikitext
text/x-wiki
=={{sunda}}==
{{-nomina-|su}}
*{{ka|tatu}}
0l8kejxgk4ut6vsycpzvzxhaf26v8ig
ᮝᮩᮒᮩᮂ
0
8745
25298
24355
2026-08-19T08:17:49Z
Deepturquoise
2456
25298
wikitext
text/x-wiki
=={{sunda}}==
{{-adjektiva-|su}}
*{{ka|weuteuh}}
avtjwc909beg2c6lxdqhwgo2rrffi4v
ᮝᮨᮝᮨᮀᮊᮧᮔ᮪
0
8756
25297
24382
2026-08-19T08:17:39Z
Deepturquoise
2456
25297
wikitext
text/x-wiki
=={{sunda}}==
{{-nomina-|su}}
*{{ka|wewengkon}}
7pmh0mfmyd0eyphvr6bxkly8csz5c13
ᮝᮤᮓᮀ
0
8762
25296
24390
2026-08-19T08:17:30Z
Deepturquoise
2456
25296
wikitext
text/x-wiki
=={{sunda}}==
{{-nomina-|su}}
*{{ka|widang}}
d6ft4t79qicvux3frtciimow2dpfezo
ᮞᮥᮌᮔ᮪
0
8763
25304
24392
2026-08-19T08:20:34Z
Deepturquoise
2456
25304
wikitext
text/x-wiki
=={{sunda}}==
{{-adverbia-|su}}
*{{ka|sugan}}
tu8lje6c7nr2tenerca907k4429zfjh
ᮌᮤᮝᮤᮀ
0
8982
25234
24812
2026-08-19T07:52:33Z
Deepturquoise
2456
25234
wikitext
text/x-wiki
=={{su}}==
{{-verba-|su}}
* {{ka|giwing}}
rimwy4bq05bqvr4nxz2s8kbs1thse5b
ModulModule:parser/edithistory
0
9231
25188
2026-08-19T04:22:11Z
Deepturquoise
2456
Memindahkan halaman dari [[en:Module:parser]]
25188
wikitext
text/x-wiki
{| class="wikitable"
! oldid || date/time || username || edit summary
|----
| 84802573 || 2025-05-14T21:53:52Z || Theknightwho || <nowiki>Use [[Module:table/getNested]] and [[Module:table/setNested]].</nowiki>
|----
| 84730669 || 2025-05-05T15:48:44Z || Theknightwho || <nowiki></nowiki>
|----
| 84687818 || 2025-04-30T23:52:48Z || Theknightwho || <nowiki>Add ignore_nonmatch flag to set_pattern.</nowiki>
|----
| 84687682 || 2025-04-30T23:27:02Z || Theknightwho || <nowiki>Remove override + add ignore_nonmatch flag.</nowiki>
|----
| 84628815 || 2025-04-24T12:25:41Z || SurjectionBot || <nowiki>(bot) slight optimization to 5.2 compat: prefer unpack to table.unpack</nowiki>
|----
| 84627773 || 2025-04-24T09:13:01Z || Surjection || <nowiki></nowiki>
|----
| 84467305 || 2025-04-05T01:17:21Z || Theknightwho || <nowiki>Add node_class() local function, and use it with the new iterate_node() option.</nowiki>
|----
| 84467165 || 2025-04-05T00:55:20Z || Theknightwho || <nowiki>Add the option to specify node classes when calling iterate_node().</nowiki>
|----
| 84397813 || 2025-03-28T02:07:36Z || Theknightwho || <nowiki></nowiki>
|----
| 84397799 || 2025-03-28T02:04:33Z || Theknightwho || <nowiki></nowiki>
|----
| 84395340 || 2025-03-27T17:00:10Z || Theknightwho || <nowiki>Optimise.</nowiki>
|----
| 84395316 || 2025-03-27T16:52:56Z || Theknightwho || <nowiki></nowiki>
|----
| 84395299 || 2025-03-27T16:48:23Z || Theknightwho || <nowiki>Also add an ArrayParser class, which works like the previous default parser.</nowiki>
|----
| 84395244 || 2025-03-27T16:38:22Z || Theknightwho || <nowiki>Add a new StringParser subclass of Parser, adapted for string inputs.</nowiki>
|----
| 84395136 || 2025-03-27T16:19:34Z || Theknightwho || <nowiki>Optimise the pop and pop_sublayer methods.</nowiki>
|----
| 84394939 || 2025-03-27T15:40:43Z || Theknightwho || <nowiki>Use the key current_layer instead of -1 for the top layer, which is more intuitive.</nowiki>
|----
| 84394665 || 2025-03-27T14:49:38Z || Theknightwho || <nowiki>Store keys only relevant to parsing in a _parse_data table in a layer, which is deleted when the layer is converted to a node; this avoids having to iterate over a layer deleting certain keys on conversion.</nowiki>
|----
| 84394095 || 2025-03-27T13:05:45Z || Theknightwho || <nowiki>Split export.new() into export.new_parser() and export.new_node().</nowiki>
|----
| 83077956 || 2024-12-19T02:20:14Z || Theknightwho || <nowiki></nowiki>
|----
| 83055366 || 2024-12-16T01:07:14Z || Theknightwho || <nowiki>Use require with get_metamethods, to minimise lookup access times.</nowiki>
|----
| 82792686 || 2024-11-29T11:39:43Z || Theknightwho || <nowiki>Comment.</nowiki>
|----
| 82792584 || 2024-11-29T11:24:25Z || Theknightwho || <nowiki></nowiki>
|----
| 82790606 || 2024-11-29T06:00:56Z || Theknightwho || <nowiki></nowiki>
|----
| 82790596 || 2024-11-29T05:59:03Z || Theknightwho || <nowiki>Change iterate so that it takes a test function which decides whether a given child is returned, instead of specifying the name of a function.</nowiki>
|----
| 82790303 || 2024-11-29T04:41:28Z || Theknightwho || <nowiki>Comment.</nowiki>
|----
| 82790280 || 2024-11-29T04:23:36Z || Theknightwho || <nowiki>Simpler to use a closure than a functor.</nowiki>
|----
| 82790155 || 2024-11-29T03:39:58Z || Theknightwho || <nowiki>Load functions and data from other modules and data on demand, rather than loading everything in advance.</nowiki>
|----
| 82790119 || 2024-11-29T03:27:36Z || Theknightwho || <nowiki>Comments.</nowiki>
|----
| 82790094 || 2024-11-29T03:21:04Z || Theknightwho || <nowiki>Allow a node to be swapped out by the next function during the iteration.</nowiki>
|----
| 82790025 || 2024-11-29T03:06:02Z || Theknightwho || <nowiki>Special keys for the node and key at the top of the stacks, so the stacks only need to be accessed when changing level.</nowiki>
|----
| 82789834 || 2024-11-29T02:12:57Z || Theknightwho || <nowiki>Optimise.</nowiki>
|----
| 82789694 || 2024-11-29T01:17:22Z || Theknightwho || <nowiki>Avoid some unnecessary table accesses.</nowiki>
|----
| 82789445 || 2024-11-29T00:11:08Z || Theknightwho || <nowiki>Use separate stacks for nodes and keys instead of a stack of tuples, which avoids creating a new object for every node that's iterated over.</nowiki>
|----
| 82789148 || 2024-11-28T23:04:01Z || Theknightwho || <nowiki>Use arrays rather than hashmaps for the stack layers.</nowiki>
|----
| 82789053 || 2024-11-28T22:41:11Z || Theknightwho || <nowiki>Optimise the node iterators, to reduce the number of unnecessary function calls.</nowiki>
|----
| 82788777 || 2024-11-28T21:44:49Z || Theknightwho || <nowiki>Remove now-unused __pairs metamethod and unused rawpairs method.</nowiki>
|----
| 82788280 || 2024-11-28T20:21:28Z || Theknightwho || <nowiki>Move away from using __pairs for iterating over nodes, as the iterator doesn't work in the expected way for __pairs metamethods.</nowiki>
|----
| 82264519 || 2024-10-04T13:24:23Z || Theknightwho || <nowiki>Remodel iterators so that it's possible to edit a node tree synchronously with the parse, instead of being committed to a node as soon as it is reached. Also remove the need to call select on each iteration.</nowiki>
|----
| 82263374 || 2024-10-04T09:56:59Z || Theknightwho || <nowiki>Minor optimisation.</nowiki>
|----
| 82131932 || 2024-10-03T20:24:41Z || Theknightwho || <nowiki>Minor optimisation.</nowiki>
|----
| 82131777 || 2024-10-03T20:05:53Z || Theknightwho || <nowiki>Call `get` with `try` + safer handling of false and nil.</nowiki>
|----
| 82120294 || 2024-10-02T16:06:32Z || Theknightwho || <nowiki>Rename the `get` method (which handles backtracking on fails) to `try`, and create a new, simpler `get` method for routes which cannot fail but which still need their own stack layer. Also do minor optimisations.</nowiki>
|----
| 82067074 || 2024-09-28T13:13:36Z || Theknightwho || <nowiki>Remove old alias for `class_else_type`.</nowiki>
|----
| 82066369 || 2024-09-28T11:52:32Z || Theknightwho || <nowiki>Rename `type_or_class` to `class_else_type`, which is more accurate.</nowiki>
|----
| 81575436 || 2024-09-11T20:39:05Z || Theknightwho || <nowiki>Two more.</nowiki>
|----
| 81575204 || 2024-09-11T20:14:45Z || Theknightwho || <nowiki>Allow customisation of the keys to remove when converting a layer into a node.</nowiki>
|----
| 81459989 || 2024-09-01T17:47:39Z || Theknightwho || <nowiki>Move metamethod data to [[Module:data/metamethods]] + minor adjustments to functions using inherit_metamethods, to account for the fact the data no longer excludes __index and __newindex.</nowiki>
|----
| 80884759 || 2024-07-27T00:41:08Z || Theknightwho || <nowiki>Minor optimisation.</nowiki>
|----
| 80848987 || 2024-07-22T22:51:51Z || Theknightwho || <nowiki></nowiki>
|----
| 80793462 || 2024-07-21T13:22:27Z || Theknightwho || <nowiki>Add clone method for nodes.</nowiki>
|----
| 78941248 || 2024-04-20T21:44:22Z || Theknightwho || <nowiki>Marginally faster.</nowiki>
|----
| 78784341 || 2024-04-08T03:03:47Z || Theknightwho || <nowiki>Add inherit parameter to push_sublayer, as it's often not needed.</nowiki>
|----
| 78782638 || 2024-04-07T20:56:17Z || Theknightwho || <nowiki>Contain Proxy in a do block, as it's specific to Node:new_proxy().</nowiki>
|----
| 78782581 || 2024-04-07T20:44:48Z || Theknightwho || <nowiki>No longer necessary to return the original Node and Parser objects.</nowiki>
|----
| 78782508 || 2024-04-07T20:30:15Z || Theknightwho || <nowiki>Remove Wikitext node class, as it's not necessary to define it here, remoe __concat metamethod as it's unused and inefficient, and create export.new() function for generating initial Parser and Node objects.</nowiki>
|----
| 78782289 || 2024-04-07T19:55:22Z || Theknightwho || <nowiki></nowiki>
|----
| 78782280 || 2024-04-07T19:54:12Z || Theknightwho || <nowiki></nowiki>
|----
| 78782244 || 2024-04-07T19:46:11Z || Theknightwho || <nowiki>New inherit_metamethods helper function.</nowiki>
|----
| 78781684 || 2024-04-07T19:21:39Z || Theknightwho || <nowiki>Cleaner code.</nowiki>
|----
| 78781602 || 2024-04-07T19:09:39Z || Theknightwho || <nowiki>Move switch method here from [[Module:template parser]].</nowiki>
|----
| 78703327 || 2024-03-29T01:25:40Z || Theknightwho || <nowiki></nowiki>
|----
| 78703307 || 2024-03-29T01:17:50Z || Theknightwho || <nowiki>Remove unused method.</nowiki>
|----
| 78703008 || 2024-03-29T00:05:24Z || Theknightwho || <nowiki>Use key -1 instead of "n" to access the top layer, which is more intuitive.</nowiki>
|----
| 78702985 || 2024-03-28T23:59:51Z || Theknightwho || <nowiki>Reduce the number of table accesses.</nowiki>
|----
| 78702874 || 2024-03-28T23:27:26Z || Theknightwho || <nowiki>Don't rely on "len" keys, as it's really awkward to ensure they're always correct, and the time saved by using them is negligible.</nowiki>
|----
| 78702458 || 2024-03-28T21:47:32Z || Theknightwho || <nowiki></nowiki>
|----
| 78700818 || 2024-03-28T15:51:04Z || Theknightwho || <nowiki></nowiki>
|----
| 78593784 || 2024-03-25T23:06:28Z || Theknightwho || <nowiki></nowiki>
|----
| 78593721 || 2024-03-25T22:47:29Z || Theknightwho || <nowiki>Use a more sophisticated way to identify nodes that can't be messed up by changing a key value.</nowiki>
|----
| 78593278 || 2024-03-25T21:37:41Z || Theknightwho || <nowiki></nowiki>
|----
| 78593087 || 2024-03-25T20:45:53Z || Theknightwho || <nowiki></nowiki>
|----
| 78553013 || 2024-03-22T21:26:42Z || Theknightwho || <nowiki>Bugfix.</nowiki>
|----
| 78550797 || 2024-03-22T20:34:20Z || Theknightwho || <nowiki>Modify design to as to reduce the number of table accesses when handling bad routes.</nowiki>
|----
| 78541720 || 2024-03-21T21:02:22Z || Theknightwho || <nowiki></nowiki>
|----
| 78541659 || 2024-03-21T20:44:50Z || Theknightwho || <nowiki></nowiki>
|----
| 78541466 || 2024-03-21T19:57:12Z || Theknightwho || <nowiki>Reduce unnecessary use of rawset.</nowiki>
|----
| 78538857 || 2024-03-21T13:39:46Z || Theknightwho || <nowiki>More sophisticated handling of stack layer metatables.</nowiki>
|----
| 78523026 || 2024-03-19T21:36:25Z || Theknightwho || <nowiki></nowiki>
|----
| 78520239 || 2024-03-19T16:39:39Z || Theknightwho || <nowiki></nowiki>
|----
| 78516097 || 2024-03-19T02:36:03Z || Theknightwho || <nowiki></nowiki>
|----
| 78516090 || 2024-03-19T02:34:08Z || Theknightwho || <nowiki></nowiki>
|----
| 78515995 || 2024-03-19T02:04:29Z || Theknightwho || <nowiki></nowiki>
|----
| 78515949 || 2024-03-19T01:46:34Z || Theknightwho || <nowiki></nowiki>
|----
| 78515916 || 2024-03-19T01:41:32Z || Theknightwho || <nowiki></nowiki>
|----
| 78207758 || 2024-02-23T11:44:41Z || Theknightwho || <nowiki></nowiki>
|----
| 78207739 || 2024-02-23T11:41:03Z || Theknightwho || <nowiki>Avoid creating unnecessary objects.</nowiki>
|----
| 78207615 || 2024-02-23T11:11:35Z || Theknightwho || <nowiki>Allow returning of arbitrary additional values from the next function.</nowiki>
|----
| 78119078 || 2024-02-16T00:16:04Z || Theknightwho || <nowiki></nowiki>
|----
| 78118956 || 2024-02-16T00:04:31Z || Theknightwho || <nowiki></nowiki>
|----
| 78068464 || 2024-02-11T19:41:59Z || Theknightwho || <nowiki></nowiki>
|----
| 78068345 || 2024-02-11T19:15:10Z || Theknightwho || <nowiki></nowiki>
|----
| 78035801 || 2024-02-09T14:38:17Z || Theknightwho || <nowiki></nowiki>
|----
| 78035768 || 2024-02-09T14:31:46Z || Theknightwho || <nowiki></nowiki>
|----
| 78035748 || 2024-02-09T14:26:44Z || Theknightwho || <nowiki></nowiki>
|----
| 78030548 || 2024-02-08T22:25:13Z || Theknightwho || <nowiki></nowiki>
|----
| 78030413 || 2024-02-08T22:18:09Z || Theknightwho || <nowiki></nowiki>
|----
| 78030382 || 2024-02-08T22:13:28Z || Theknightwho || <nowiki>Undo revision [[Special:Diff/78030380|78030380]] by [[Special:Contributions/Theknightwho|Theknightwho]] ([[User talk:Theknightwho|talk]])</nowiki>
|----
| 78030380 || 2024-02-08T22:12:44Z || Theknightwho || <nowiki></nowiki>
|----
| 78030344 || 2024-02-08T22:07:22Z || Theknightwho || <nowiki></nowiki>
|----
| 77748978 || 2024-01-27T16:57:57Z || Theknightwho || <nowiki></nowiki>
|----
| 77748932 || 2024-01-27T16:49:19Z || Theknightwho || <nowiki></nowiki>
|----
| 77747952 || 2024-01-27T13:43:03Z || Theknightwho || <nowiki></nowiki>
|----
| 77735956 || 2024-01-25T23:42:34Z || Theknightwho || <nowiki></nowiki>
|----
| 77735899 || 2024-01-25T23:27:08Z || Theknightwho || <nowiki></nowiki>
|----
| 77735732 || 2024-01-25T22:57:11Z || Theknightwho || <nowiki></nowiki>
|----
| 77735374 || 2024-01-25T21:58:56Z || Theknightwho || <nowiki></nowiki>
|----
| 77734812 || 2024-01-25T20:39:24Z || Theknightwho || <nowiki></nowiki>
|----
| 77734707 || 2024-01-25T20:23:58Z || Theknightwho || <nowiki></nowiki>
|----
| 77734544 || 2024-01-25T20:00:36Z || Theknightwho || <nowiki></nowiki>
|----
| 77734428 || 2024-01-25T19:36:00Z || Theknightwho || <nowiki></nowiki>
|----
| 77734265 || 2024-01-25T19:05:52Z || Theknightwho || <nowiki></nowiki>
|----
| 77733998 || 2024-01-25T18:05:48Z || Theknightwho || <nowiki></nowiki>
|----
| 77733894 || 2024-01-25T17:48:56Z || Theknightwho || <nowiki></nowiki>
|----
| 77733874 || 2024-01-25T17:42:52Z || Theknightwho || <nowiki></nowiki>
|----
| 77733816 || 2024-01-25T17:28:40Z || Theknightwho || <nowiki></nowiki>
|----
| 77733640 || 2024-01-25T16:54:15Z || Theknightwho || <nowiki></nowiki>
|----
| 77732699 || 2024-01-25T14:00:20Z || Theknightwho || <nowiki></nowiki>
|----
| 77732663 || 2024-01-25T13:54:18Z || Theknightwho || <nowiki></nowiki>
|----
| 77482731 || 2023-12-31T05:34:11Z || Theknightwho || <nowiki></nowiki>
|----
| 77482714 || 2023-12-31T05:32:34Z || Theknightwho || <nowiki>Undo revision [[Special:Diff/77482698|77482698]] by [[Special:Contributions/Theknightwho|Theknightwho]] ([[User talk:Theknightwho|talk]])</nowiki>
|----
| 77482698 || 2023-12-31T05:31:35Z || Theknightwho || <nowiki></nowiki>
|----
| 77482344 || 2023-12-31T04:43:47Z || Theknightwho || <nowiki></nowiki>
|----
| 77482299 || 2023-12-31T04:37:05Z || Theknightwho || <nowiki>Undo revision [[Special:Diff/77482298|77482298]] by [[Special:Contributions/Theknightwho|Theknightwho]] ([[User talk:Theknightwho|talk]])</nowiki>
|----
| 77482298 || 2023-12-31T04:36:54Z || Theknightwho || <nowiki></nowiki>
|----
| 77481920 || 2023-12-31T03:38:26Z || Theknightwho || <nowiki></nowiki>
|----
| 77480712 || 2023-12-30T23:32:47Z || Theknightwho || <nowiki></nowiki>
|----
| 77480657 || 2023-12-30T23:11:37Z || Theknightwho || <nowiki></nowiki>
|----
| 77480053 || 2023-12-30T21:42:46Z || Theknightwho || <nowiki></nowiki>
|----
| 77479929 || 2023-12-30T21:21:34Z || Theknightwho || <nowiki></nowiki>
|----
| 77466195 || 2023-12-29T13:00:10Z || Theknightwho || <nowiki></nowiki>
|----
| 77427142 || 2023-12-24T14:36:35Z || Theknightwho || <nowiki></nowiki>
|----
| 77427114 || 2023-12-24T14:33:01Z || Theknightwho || <nowiki></nowiki>
|----
| 77427089 || 2023-12-24T14:27:29Z || Theknightwho || <nowiki></nowiki>
|----
| 77425603 || 2023-12-24T07:06:47Z || Theknightwho || <nowiki></nowiki>
|----
| 77425599 || 2023-12-24T07:04:21Z || Theknightwho || <nowiki></nowiki>
|----
| 77422782 || 2023-12-23T18:02:55Z || Theknightwho || <nowiki></nowiki>
|----
| 77422771 || 2023-12-23T18:01:10Z || Theknightwho || <nowiki></nowiki>
|----
| 77422689 || 2023-12-23T17:48:13Z || Theknightwho || <nowiki></nowiki>
|----
| 77422633 || 2023-12-23T17:41:06Z || Theknightwho || <nowiki></nowiki>
|----
| 77422571 || 2023-12-23T17:27:33Z || Theknightwho || <nowiki></nowiki>
|----
| 77403751 || 2023-12-21T23:47:11Z || Theknightwho || <nowiki></nowiki>
|----
| 77403629 || 2023-12-21T23:22:28Z || Theknightwho || <nowiki></nowiki>
|----
| 77355042 || 2023-12-20T18:49:39Z || Theknightwho || <nowiki></nowiki>
|----
| 77354608 || 2023-12-20T17:00:55Z || Theknightwho || <nowiki></nowiki>
|----
| 77350264 || 2023-12-20T09:32:19Z || Theknightwho || <nowiki></nowiki>
|----
| 77349729 || 2023-12-20T07:40:27Z || Theknightwho || <nowiki></nowiki>
|----
| 77349691 || 2023-12-20T07:34:06Z || Theknightwho || <nowiki></nowiki>
|----
| 77349676 || 2023-12-20T07:31:31Z || Theknightwho || <nowiki></nowiki>
|----
| 77349663 || 2023-12-20T07:26:25Z || Theknightwho || <nowiki></nowiki>
|----
| 77349628 || 2023-12-20T07:18:53Z || Theknightwho || <nowiki></nowiki>
|----
| 77349590 || 2023-12-20T07:14:00Z || Theknightwho || <nowiki></nowiki>
|----
| 77349562 || 2023-12-20T07:10:52Z || Theknightwho || <nowiki></nowiki>
|----
| 77349534 || 2023-12-20T07:07:40Z || Theknightwho || <nowiki></nowiki>
|----
| 77348808 || 2023-12-20T05:14:30Z || Theknightwho || <nowiki></nowiki>
|----
| 77347879 || 2023-12-20T03:39:49Z || Theknightwho || <nowiki></nowiki>
|----
| 77347507 || 2023-12-20T02:39:11Z || Theknightwho || <nowiki></nowiki>
|----
| 77347455 || 2023-12-20T02:21:03Z || Theknightwho || <nowiki></nowiki>
|----
| 77346878 || 2023-12-20T00:59:52Z || Theknightwho || <nowiki></nowiki>
|----
| 77346724 || 2023-12-20T00:31:46Z || Theknightwho || <nowiki></nowiki>
|----
| 77344564 || 2023-12-19T17:24:37Z || Theknightwho || <nowiki></nowiki>
|----
| 77344563 || 2023-12-19T17:23:55Z || Theknightwho || <nowiki></nowiki>
|----
| 77344526 || 2023-12-19T17:09:26Z || Theknightwho || <nowiki></nowiki>
|----
| 77242366 || 2023-12-19T01:34:43Z || Theknightwho || <nowiki></nowiki>
|----
| 77242235 || 2023-12-19T01:01:32Z || Theknightwho || <nowiki></nowiki>
|----
| 77242177 || 2023-12-19T00:40:48Z || Theknightwho || <nowiki></nowiki>
|----
| 77241846 || 2023-12-18T23:24:30Z || Theknightwho || <nowiki></nowiki>
|----
| 77241745 || 2023-12-18T22:58:03Z || Theknightwho || <nowiki></nowiki>
|----
| 77241701 || 2023-12-18T22:48:30Z || Theknightwho || <nowiki></nowiki>
|----
| 77218550 || 2023-12-15T23:18:28Z || Theknightwho || <nowiki></nowiki>
|----
| 77218519 || 2023-12-15T23:08:30Z || Theknightwho || <nowiki></nowiki>
|----
| 77216831 || 2023-12-15T16:57:22Z || Theknightwho || <nowiki></nowiki>
|----
| 77216743 || 2023-12-15T16:30:41Z || Theknightwho || <nowiki></nowiki>
|----
| 77216561 || 2023-12-15T15:42:20Z || Theknightwho || <nowiki></nowiki>
|----
| 77216466 || 2023-12-15T15:23:20Z || Theknightwho || <nowiki></nowiki>
|----
| 77213630 || 2023-12-14T23:54:19Z || Theknightwho || <nowiki></nowiki>
|----
| 77212865 || 2023-12-14T21:02:54Z || Theknightwho || <nowiki></nowiki>
|----
| 77205789 || 2023-12-13T20:06:02Z || Theknightwho || <nowiki></nowiki>
|----
| 76897320 || 2023-12-07T15:50:40Z || Theknightwho || <nowiki></nowiki>
|----
| 76897308 || 2023-12-07T15:46:16Z || Theknightwho || <nowiki></nowiki>
|----
| 76848880 || 2023-12-02T03:58:05Z || Theknightwho || <nowiki></nowiki>
|----
| 76848777 || 2023-12-02T03:32:14Z || Theknightwho || <nowiki></nowiki>
|----
| 76848757 || 2023-12-02T03:29:28Z || Theknightwho || <nowiki></nowiki>
|----
| 76848737 || 2023-12-02T03:24:45Z || Theknightwho || <nowiki></nowiki>
|----
| 76848732 || 2023-12-02T03:21:13Z || Theknightwho || <nowiki></nowiki>
|----
| 76831246 || 2023-12-01T15:20:37Z || Theknightwho || <nowiki></nowiki>
|----
| 76821890 || 2023-11-30T05:11:57Z || Theknightwho || <nowiki></nowiki>
|----
| 76821766 || 2023-11-30T04:24:07Z || Theknightwho || <nowiki></nowiki>
|----
| 76770172 || 2023-11-24T13:42:14Z || Theknightwho || <nowiki></nowiki>
|----
| 76770053 || 2023-11-24T13:21:12Z || Theknightwho || <nowiki></nowiki>
|----
| 76769715 || 2023-11-24T12:20:05Z || Theknightwho || <nowiki></nowiki>
|----
| 76769462 || 2023-11-24T11:20:48Z || Theknightwho || <nowiki></nowiki>
|----
| 76769423 || 2023-11-24T11:10:21Z || Theknightwho || <nowiki></nowiki>
|----
| 76769413 || 2023-11-24T11:07:56Z || Theknightwho || <nowiki></nowiki>
|----
| 76769349 || 2023-11-24T10:54:31Z || Theknightwho || <nowiki></nowiki>
|----
| 76769275 || 2023-11-24T10:36:53Z || Theknightwho || <nowiki></nowiki>
|----
| 76766891 || 2023-11-24T04:48:40Z || Theknightwho || <nowiki>Protected "[[Module:parser]]": Highly visible template/module ([Edit=Allow only template editors and administrators] (indefinite) [Move=Allow only template editors and administrators] (indefinite))</nowiki>
|----
| 76766556 || 2023-11-24T02:37:00Z || Theknightwho || <nowiki></nowiki>
|----
| 76766553 || 2023-11-24T02:35:58Z || Theknightwho || <nowiki></nowiki>
|----
| 76766526 || 2023-11-24T02:31:19Z || Theknightwho || <nowiki></nowiki>
|----
| 76766506 || 2023-11-24T02:22:11Z || Theknightwho || <nowiki></nowiki>
|----
| 76766501 || 2023-11-24T02:19:41Z || Theknightwho || <nowiki></nowiki>
|----
| 76766243 || 2023-11-24T01:01:05Z || Theknightwho || <nowiki>Created page with "local concat = table.concat local insert = table.insert local ipairs = ipairs local next = next local pairs = pairs local rawget = rawget local rawset = rawset local remove = table.remove local select = select local setmetatable = setmetatable local type = type -- Recursively calling tostring() adds to the C stack (limit: 200), while calling __tostring metamethods directly does not. Occasionally relevant when dealing with very deep nesting. local tostring_old = tostring..."</nowiki>
|}
bgw1zd6lo1c98zw9bv2cxvwk895buu2
ModulModule:parser
0
9232
25189
2026-08-19T04:22:21Z
Deepturquoise
2456
Memindahkan halaman dari [[en:Module:parser]] ([[ModulModule:parser/edithistory|history]])
25189
wikitext
text/x-wiki
local export = {}
local scribunto_metamethods_module = "Module:Scribunto/metamethods"
local table_deep_copy_module = "Module:table/deepCopy"
local table_get_nested_module = "Module:table/getNested"
local table_set_nested_module = "Module:table/setNested"
local concat = table.concat
local find = string.find
local getmetatable = getmetatable
local insert = table.insert
local next = next
local rawget = rawget
local rawset = rawset
local remove = table.remove
local require = require
local select = select
local setmetatable = setmetatable
local sub = string.sub
local type = type
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local node_classes = {}
local function deep_copy(...)
deep_copy = require(table_deep_copy_module)
return deep_copy(...)
end
local function get_nested(...)
get_nested = require(table_get_nested_module)
return get_nested(...)
end
local function set_nested(...)
set_nested = require(table_set_nested_module)
return set_nested(...)
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 metamethods
local function get_metamethods()
-- Use require, since lookup times are much slower with mw.loadData.
metamethods, get_metamethods = require(scribunto_metamethods_module), nil
return metamethods
end
------------------------------------------------------------------------------------
--
-- Helper functions
--
------------------------------------------------------------------------------------
local function inherit_metamethods(child, parent)
if parent then
for method, value in next, parent do
if child[method] == nil and (metamethods or get_metamethods())[method] ~= nil then
child[method] = value
end
end
end
return child
end
local function signed_index(t, n)
return n and n <= 0 and #t + 1 + n or n
end
local function is_node(value)
if value == nil then
return false
end
local mt = getmetatable(value)
return not (mt == nil or node_classes[mt] == nil)
end
local function node_class(value)
if value == nil then
return nil
end
local mt = getmetatable(value)
if mt == nil then
return nil
end
return mt ~= nil and node_classes[mt] or nil
end
local function class_else_type(value)
if value == nil then
return type(value)
end
local mt = getmetatable(value)
if mt == nil then
return type(value)
end
local class = node_classes[mt]
return class == nil and type(value) or class
end
-- Recursively calling tostring() adds to the C stack (limit: 200), whereas
-- calling __tostring metamethods directly does not. Occasionally relevant when
-- dealing with very deep nesting.
local tostring
do
local _tostring = _G.tostring
function tostring(value)
if is_node(value) then
return value:__tostring(value)
end
return _tostring(value)
end
end
------------------------------------------------------------------------------------
--
-- Nodes
--
------------------------------------------------------------------------------------
local Node = {}
Node.__index = Node
function Node:next(i)
i = i + 1
return self[i], self, i
end
--[==[
Implements recursive iteration over a node tree.
By default, when a node is encountered (which may contain other nodes), it is returned on the first iteration, and then any child nodes are returned on each subsequent iteration; the same process is then followed if any of those children contain nodes themselves. Once a particular node has been fully traversed, the iterator then continues with any sibling nodes. The iterator will use the `next` method of each node to traverse it, which may differ depending on the node class.
Each iteration returns three values: `value`, `node` and `key`. Together, these can be used to manipulate the node tree at any given point without needing to know the full structure. Note that when the input node is returned on the first iteration, `node` and `key` will be nil.
The optional argument `test` can be used to limit the return values. This should be a function that returns a boolean value, where a return value of true means that the child will be returned by the iterator. If a node is not returned by the iterator, it will still be traversed, as it may contain children that should be returned.
The method `iterate_nodes` is provided as a special instance of iterate which uses `is_node` as the test.]==]
function Node:iterate(test)
local node, k, n, nodes, keys, returned_self = self, 0, 0
-- Special case if `test` is `is_node`.
local is_node_is_test = test == is_node
return function()
if not returned_self then
returned_self = true
if test == nil or test(self) then
return self
end
end
-- Get `v`, which is the value at the last-returned key of the current node; if `v` is a node, it will be iterated over (i.e. recursive iteration). By default, `v` will be the last-returned value, but looking it up here means that any modifications made to the node during the loop will be taken into account. This makes it possible to swap one node out for something else (e.g. another node), or to remove it entirely, without being locked into recursively iterating over the old node; instead, the new node (if any) will be iterated over. This means node trees can be modified on-the-fly during the course of a single loop.
local v, node_check = node[k], true
while true do
-- If `v` is a node, memoize the current node and key, then iterate over it.
if node_check and is_node(v) then
-- `n` is the current memo level.
n = n + 1
if nodes then
nodes[n], keys[n] = node, k
else
nodes, keys = {node}, {k}
end
node, k = v, 0
end
v, node, k = node:next(k)
-- If `v` is nil, move down one level, then continue iterating the node on that level (if any), or otherwise terminate the loop.
if v == nil then
if n == 0 then
return nil
end
node, k, n = nodes[n], keys[n], n - 1
elseif test == nil or test(v) then
return v, node, k
-- If `test` is `is_node`, there's no point checking it again on the next loop.
elseif node_check and is_node_is_test then
node_check = false
end
end
end
end
function Node:iterate_nodes(...)
local args_n = select("#", ...)
if args_n == 0 then
return self:iterate(is_node)
elseif args_n == 1 then
local class = ...
return self:iterate(function(value)
return node_class(value) == class
end)
end
local classes = {}
for i = 1, args_n do
classes[select(i, ...)] = true
end
return self:iterate(function(value)
return classes[node_class(value)]
end)
end
function Node:__tostring()
local output = {}
for i = 1, #self do
insert(output, tostring(self[i]))
end
return concat(output)
end
function Node:clone()
return deep_copy(self, "keep", true)
end
function Node:new_class(class)
local t = {type = class}
t.__index = t
t = inherit_metamethods(t, self)
node_classes[t] = class
return setmetatable(t, self)
end
function Node:new(t)
rawset(t, "_parse_data", nil)
return setmetatable(t, self)
end
do
local Proxy = {}
function Proxy:__index(k)
local v = Proxy[k]
if v ~= nil then
return v
end
return self.__chars[k]
end
function Proxy:__newindex(k, v)
local key = self.__keys[k]
if key then
self.__chars[k] = v
self.__parents[key] = v
elseif key == false then
error("Character is immutable.")
else
error("Invalid key.")
end
end
function Proxy:build(a, b, c)
local len = self.__len + 1
self.__chars[len] = a
self.__parents[len] = b
self.__keys[len] = c
self.__len = len
end
function Proxy:iter(i)
i = i + 1
local char = self.__chars[i]
if char ~= nil then
return i, self[i], self, self.__parents[i], self.__keys[i]
end
end
function Node:new_proxy()
return setmetatable({
__node = self,
__chars = {},
__parents = {},
__keys = {},
__len = 0
}, Proxy)
end
end
function export.node()
return Node:new_class("node")
end
------------------------------------------------------------------------------------
--
-- Parser
--
------------------------------------------------------------------------------------
local Parser = {}
Parser.__index = Parser
function Parser:get_layer(n)
if n ~= nil then
return rawget(self, #self + n)
end
return self.current_layer
end
function Parser:emit(a, b)
local layer = self.current_layer
if b ~= nil then
insert(layer, signed_index(layer, a), b)
else
rawset(layer, #layer + 1, a)
end
end
function Parser:emit_tokens(a, b)
local layer = self.current_layer
if b ~= nil then
a = signed_index(layer, a)
for i = 1, #b do
insert(layer, a + i - 1, b[i])
end
else
local len = #layer
for i = 1, #a do
len = len + 1
rawset(layer, len, a[i])
end
end
end
function Parser:remove(n)
local layer = self.current_layer
if n ~= nil then
return remove(layer, signed_index(layer, n))
end
local len = #layer
local token = layer[len]
layer[len] = nil
return token
end
function Parser:replace(a, b)
local layer = self.current_layer
layer[signed_index(layer, a)] = b
end
-- Unlike default table.concat, this respects __tostring metamethods.
function Parser:concat(a, b, c)
if a == nil or a > 0 then
return self:concat(0, a, b)
end
local layer, ret, n = self:get_layer(a), {}, 0
for i = b and signed_index(layer, b) or 1, c and signed_index(layer, c) or #layer do
n = n + 1
ret[n] = tostring(layer[i])
end
return concat(ret)
end
function Parser:emitted(delta)
if delta == nil then
delta = -1
end
local get_layer, i = self.get_layer, 0
while true do
local layer = get_layer(self, i)
if layer == nil then
return nil
end
local layer_len = #layer
if -delta <= layer_len then
return rawget(layer, layer_len + delta + 1)
end
delta = delta + layer_len
i = i - 1
end
end
function Parser:push(route)
local layer = {_parse_data = {
head = self.head,
route = route,
}}
self[#self + 1] = layer
self.current_layer = layer
end
function Parser:push_sublayer(handler, inherit)
local pdata = {
handler = handler,
sublayer = true,
}
local sublayer = {
_parse_data = pdata,
}
if inherit then
local layer_parse_data = self.current_layer._parse_data
setmetatable(pdata, inherit_metamethods({
__index = layer_parse_data,
__newindex = layer_parse_data
}, getmetatable(layer_parse_data)))
end
self[#self + 1] = sublayer
self.current_layer = sublayer
end
function Parser:pop()
local len, layer = #self
while true do
layer = self[len]
self[len] = nil
len = len - 1
if len == 0 then
self.current_layer = self
break
elseif layer._parse_data.sublayer == nil then
self.current_layer = self[len]
break
end
self:emit_tokens(layer)
end
return setmetatable(layer, nil)
end
function Parser:pop_sublayer()
local len, layer = #self, self.current_layer
self[len] = nil
self.current_layer = len == 1 and self or self[len - 1]
return setmetatable(layer, nil)
end
function Parser:get(route, ...)
self:push(route)
local layer = route(self, ...)
if layer == nil then
layer = self:traverse()
end
return layer
end
function Parser:try(route, ...)
local failed_routes = self.failed_routes
if failed_routes ~= nil then
local failed_layer = get_nested(failed_routes, route, self.head)
if failed_layer ~= nil then
return false, failed_layer
end
end
local layer = self:get(route, ...)
return not layer._parse_data.fail, layer
end
function Parser:fail_route()
local layer = self:pop()
local pdata = layer._parse_data
pdata.fail = true
local layer_head = pdata.head
set_nested(self, layer, "failed_routes", pdata.route, layer_head)
self.head = layer_head
return layer
end
function Parser:traverse()
local consume, advance = self.consume, self.advance
while true do
local layer = consume(self)
if layer ~= nil then
return layer
end
advance(self)
end
end
-- Converts a handler into a switch table the first time it's called, which avoids creating unnecessary objects, and prevents any scoping issues caused by parser methods being assigned to table keys before they've been declared.
-- false is used as the default key.
do
local Switch = {}
function Switch:__call(parser, this)
return (self[this] or self[false])(parser, this)
end
function Parser:switch(func, t)
local pdata = self.current_layer._parse_data
-- Point handler to the new switch table if the calling function is the current handler.
if pdata.handler == func then
pdata.handler = t
end
return setmetatable(t, Switch)
end
end
-- Generate a new parser class object, which is used as the template for any parser objects. These should be customized with additional/modified methods as needed.
function Parser:new_class()
local t = {}
t.__index = t
return setmetatable(inherit_metamethods(t, self), self)
end
-- Generate a new parser object, which is used for a specific parse.
function Parser:new(text)
return setmetatable({
text = text,
head = 1
}, self)
end
function Parser:parse(data)
local parser = self:new(data.text)
local success, tokens = parser:try(unpack(data.route))
if #parser > 0 then
-- This shouldn't happen.
error("Parser exited with non-empty stack.")
elseif success then
local node = data.node
return true, node[1]:new(tokens, unpack(node, 2)), parser
elseif data.allow_fail then
return false, nil, parser
end
error("Parser exited with failed route.")
end
export.class_else_type = class_else_type
export.is_node = is_node
export.tostring = tostring
local ArrayParser = Parser:new_class()
function ArrayParser:read(delta)
local v = self.text[self.head + (delta or 0)]
return v == nil and "" or v
end
function ArrayParser:advance(n)
self.head = self.head + (n == nil and 1 or n)
end
function ArrayParser:jump(head)
self.head = head
end
function ArrayParser:consume(this, ...)
if this == nil then
this = self:read()
end
local pdata = self.current_layer._parse_data
return pdata.handler(self, this, ...)
end
function export.array_parser()
return ArrayParser:new_class()
end
local StringParser = Parser:new_class()
function StringParser:read(i, j)
local head, i = self.head, i or 0
return sub(self.text, head + i, head + (j or i))
end
function StringParser:advance(n)
self.head = self.head + (n or self.current_layer._parse_data.step or 1)
end
function StringParser:jump(head)
local pdata = self.current_layer._parse_data
self.head, pdata.next, pdata.next_len = head, nil, nil
end
-- If `ignore_nonmatch` is set, any non-match segment before the match will be ignored.
function StringParser:set_pattern(pattern, ignore_nonmatch)
local pdata = self.current_layer._parse_data
pdata.pattern, pdata.next, pdata.next_len = "(" .. pattern .. ")", nil, nil
if ignore_nonmatch then
pdata.ignore_nonmatch = true
end
end
function StringParser:consume()
local pdata = self.current_layer._parse_data
local this = pdata.next
-- Use `next` and `next_len` from the previous iteration, if available.
if this then
pdata.step, pdata.next, pdata.next_len = pdata.next_len, nil, nil
return pdata.handler(self, this)
end
local text, head, loc1, loc2 = self.text, self.head
loc1, loc2, this = find(text, pdata.pattern, head)
-- If there was no match, default to find(text, "$", head), with `this` as
-- the empty string.
if not loc1 then
this, loc1 = "", #text + 1
loc2 = loc1 - 1 -- zero-length matches cause loc2 to be less than loc1
end
-- If `this` is at `head`, consume it.
if loc1 == head then
pdata.step = loc2 - loc1 + 1
-- If `ignore_nonmatch` is set, ignore everything before `this`, then
-- consume it.
elseif pdata.ignore_nonmatch then
self.head, pdata.step = loc1, loc2 - loc1 + 1
-- Otherwise, consume everything before `this`, and memoize the match and
-- match length; the length is dealt with separately, as it could be 0 if
-- `next` is an index (e.g. if the pattern is the empty string).
else
this, pdata.step, pdata.next, pdata.next_len = sub(text, head, loc1 - 1), loc1 - head, this, loc2 - loc1 + 1
end
return pdata.handler(self, this)
end
function export.string_parser()
return StringParser:new_class()
end
return export<noinclude>
<small>Halaman ini telah dipindahkan dari [[en:Module:parser]]. Sejarah penyuntingannya dapat dilihat di [[ModulModule:parser/edithistory]]</small></noinclude>
jdlxjw6fpzm5gxupcqiatxybx7toqi1
25190
25189
2026-08-19T04:23:22Z
Deepturquoise
2456
Deepturquoise mindahkeun kaca [[ModulModule:parser]] ka [[Modul:parser]]
25189
wikitext
text/x-wiki
local export = {}
local scribunto_metamethods_module = "Module:Scribunto/metamethods"
local table_deep_copy_module = "Module:table/deepCopy"
local table_get_nested_module = "Module:table/getNested"
local table_set_nested_module = "Module:table/setNested"
local concat = table.concat
local find = string.find
local getmetatable = getmetatable
local insert = table.insert
local next = next
local rawget = rawget
local rawset = rawset
local remove = table.remove
local require = require
local select = select
local setmetatable = setmetatable
local sub = string.sub
local type = type
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local node_classes = {}
local function deep_copy(...)
deep_copy = require(table_deep_copy_module)
return deep_copy(...)
end
local function get_nested(...)
get_nested = require(table_get_nested_module)
return get_nested(...)
end
local function set_nested(...)
set_nested = require(table_set_nested_module)
return set_nested(...)
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 metamethods
local function get_metamethods()
-- Use require, since lookup times are much slower with mw.loadData.
metamethods, get_metamethods = require(scribunto_metamethods_module), nil
return metamethods
end
------------------------------------------------------------------------------------
--
-- Helper functions
--
------------------------------------------------------------------------------------
local function inherit_metamethods(child, parent)
if parent then
for method, value in next, parent do
if child[method] == nil and (metamethods or get_metamethods())[method] ~= nil then
child[method] = value
end
end
end
return child
end
local function signed_index(t, n)
return n and n <= 0 and #t + 1 + n or n
end
local function is_node(value)
if value == nil then
return false
end
local mt = getmetatable(value)
return not (mt == nil or node_classes[mt] == nil)
end
local function node_class(value)
if value == nil then
return nil
end
local mt = getmetatable(value)
if mt == nil then
return nil
end
return mt ~= nil and node_classes[mt] or nil
end
local function class_else_type(value)
if value == nil then
return type(value)
end
local mt = getmetatable(value)
if mt == nil then
return type(value)
end
local class = node_classes[mt]
return class == nil and type(value) or class
end
-- Recursively calling tostring() adds to the C stack (limit: 200), whereas
-- calling __tostring metamethods directly does not. Occasionally relevant when
-- dealing with very deep nesting.
local tostring
do
local _tostring = _G.tostring
function tostring(value)
if is_node(value) then
return value:__tostring(value)
end
return _tostring(value)
end
end
------------------------------------------------------------------------------------
--
-- Nodes
--
------------------------------------------------------------------------------------
local Node = {}
Node.__index = Node
function Node:next(i)
i = i + 1
return self[i], self, i
end
--[==[
Implements recursive iteration over a node tree.
By default, when a node is encountered (which may contain other nodes), it is returned on the first iteration, and then any child nodes are returned on each subsequent iteration; the same process is then followed if any of those children contain nodes themselves. Once a particular node has been fully traversed, the iterator then continues with any sibling nodes. The iterator will use the `next` method of each node to traverse it, which may differ depending on the node class.
Each iteration returns three values: `value`, `node` and `key`. Together, these can be used to manipulate the node tree at any given point without needing to know the full structure. Note that when the input node is returned on the first iteration, `node` and `key` will be nil.
The optional argument `test` can be used to limit the return values. This should be a function that returns a boolean value, where a return value of true means that the child will be returned by the iterator. If a node is not returned by the iterator, it will still be traversed, as it may contain children that should be returned.
The method `iterate_nodes` is provided as a special instance of iterate which uses `is_node` as the test.]==]
function Node:iterate(test)
local node, k, n, nodes, keys, returned_self = self, 0, 0
-- Special case if `test` is `is_node`.
local is_node_is_test = test == is_node
return function()
if not returned_self then
returned_self = true
if test == nil or test(self) then
return self
end
end
-- Get `v`, which is the value at the last-returned key of the current node; if `v` is a node, it will be iterated over (i.e. recursive iteration). By default, `v` will be the last-returned value, but looking it up here means that any modifications made to the node during the loop will be taken into account. This makes it possible to swap one node out for something else (e.g. another node), or to remove it entirely, without being locked into recursively iterating over the old node; instead, the new node (if any) will be iterated over. This means node trees can be modified on-the-fly during the course of a single loop.
local v, node_check = node[k], true
while true do
-- If `v` is a node, memoize the current node and key, then iterate over it.
if node_check and is_node(v) then
-- `n` is the current memo level.
n = n + 1
if nodes then
nodes[n], keys[n] = node, k
else
nodes, keys = {node}, {k}
end
node, k = v, 0
end
v, node, k = node:next(k)
-- If `v` is nil, move down one level, then continue iterating the node on that level (if any), or otherwise terminate the loop.
if v == nil then
if n == 0 then
return nil
end
node, k, n = nodes[n], keys[n], n - 1
elseif test == nil or test(v) then
return v, node, k
-- If `test` is `is_node`, there's no point checking it again on the next loop.
elseif node_check and is_node_is_test then
node_check = false
end
end
end
end
function Node:iterate_nodes(...)
local args_n = select("#", ...)
if args_n == 0 then
return self:iterate(is_node)
elseif args_n == 1 then
local class = ...
return self:iterate(function(value)
return node_class(value) == class
end)
end
local classes = {}
for i = 1, args_n do
classes[select(i, ...)] = true
end
return self:iterate(function(value)
return classes[node_class(value)]
end)
end
function Node:__tostring()
local output = {}
for i = 1, #self do
insert(output, tostring(self[i]))
end
return concat(output)
end
function Node:clone()
return deep_copy(self, "keep", true)
end
function Node:new_class(class)
local t = {type = class}
t.__index = t
t = inherit_metamethods(t, self)
node_classes[t] = class
return setmetatable(t, self)
end
function Node:new(t)
rawset(t, "_parse_data", nil)
return setmetatable(t, self)
end
do
local Proxy = {}
function Proxy:__index(k)
local v = Proxy[k]
if v ~= nil then
return v
end
return self.__chars[k]
end
function Proxy:__newindex(k, v)
local key = self.__keys[k]
if key then
self.__chars[k] = v
self.__parents[key] = v
elseif key == false then
error("Character is immutable.")
else
error("Invalid key.")
end
end
function Proxy:build(a, b, c)
local len = self.__len + 1
self.__chars[len] = a
self.__parents[len] = b
self.__keys[len] = c
self.__len = len
end
function Proxy:iter(i)
i = i + 1
local char = self.__chars[i]
if char ~= nil then
return i, self[i], self, self.__parents[i], self.__keys[i]
end
end
function Node:new_proxy()
return setmetatable({
__node = self,
__chars = {},
__parents = {},
__keys = {},
__len = 0
}, Proxy)
end
end
function export.node()
return Node:new_class("node")
end
------------------------------------------------------------------------------------
--
-- Parser
--
------------------------------------------------------------------------------------
local Parser = {}
Parser.__index = Parser
function Parser:get_layer(n)
if n ~= nil then
return rawget(self, #self + n)
end
return self.current_layer
end
function Parser:emit(a, b)
local layer = self.current_layer
if b ~= nil then
insert(layer, signed_index(layer, a), b)
else
rawset(layer, #layer + 1, a)
end
end
function Parser:emit_tokens(a, b)
local layer = self.current_layer
if b ~= nil then
a = signed_index(layer, a)
for i = 1, #b do
insert(layer, a + i - 1, b[i])
end
else
local len = #layer
for i = 1, #a do
len = len + 1
rawset(layer, len, a[i])
end
end
end
function Parser:remove(n)
local layer = self.current_layer
if n ~= nil then
return remove(layer, signed_index(layer, n))
end
local len = #layer
local token = layer[len]
layer[len] = nil
return token
end
function Parser:replace(a, b)
local layer = self.current_layer
layer[signed_index(layer, a)] = b
end
-- Unlike default table.concat, this respects __tostring metamethods.
function Parser:concat(a, b, c)
if a == nil or a > 0 then
return self:concat(0, a, b)
end
local layer, ret, n = self:get_layer(a), {}, 0
for i = b and signed_index(layer, b) or 1, c and signed_index(layer, c) or #layer do
n = n + 1
ret[n] = tostring(layer[i])
end
return concat(ret)
end
function Parser:emitted(delta)
if delta == nil then
delta = -1
end
local get_layer, i = self.get_layer, 0
while true do
local layer = get_layer(self, i)
if layer == nil then
return nil
end
local layer_len = #layer
if -delta <= layer_len then
return rawget(layer, layer_len + delta + 1)
end
delta = delta + layer_len
i = i - 1
end
end
function Parser:push(route)
local layer = {_parse_data = {
head = self.head,
route = route,
}}
self[#self + 1] = layer
self.current_layer = layer
end
function Parser:push_sublayer(handler, inherit)
local pdata = {
handler = handler,
sublayer = true,
}
local sublayer = {
_parse_data = pdata,
}
if inherit then
local layer_parse_data = self.current_layer._parse_data
setmetatable(pdata, inherit_metamethods({
__index = layer_parse_data,
__newindex = layer_parse_data
}, getmetatable(layer_parse_data)))
end
self[#self + 1] = sublayer
self.current_layer = sublayer
end
function Parser:pop()
local len, layer = #self
while true do
layer = self[len]
self[len] = nil
len = len - 1
if len == 0 then
self.current_layer = self
break
elseif layer._parse_data.sublayer == nil then
self.current_layer = self[len]
break
end
self:emit_tokens(layer)
end
return setmetatable(layer, nil)
end
function Parser:pop_sublayer()
local len, layer = #self, self.current_layer
self[len] = nil
self.current_layer = len == 1 and self or self[len - 1]
return setmetatable(layer, nil)
end
function Parser:get(route, ...)
self:push(route)
local layer = route(self, ...)
if layer == nil then
layer = self:traverse()
end
return layer
end
function Parser:try(route, ...)
local failed_routes = self.failed_routes
if failed_routes ~= nil then
local failed_layer = get_nested(failed_routes, route, self.head)
if failed_layer ~= nil then
return false, failed_layer
end
end
local layer = self:get(route, ...)
return not layer._parse_data.fail, layer
end
function Parser:fail_route()
local layer = self:pop()
local pdata = layer._parse_data
pdata.fail = true
local layer_head = pdata.head
set_nested(self, layer, "failed_routes", pdata.route, layer_head)
self.head = layer_head
return layer
end
function Parser:traverse()
local consume, advance = self.consume, self.advance
while true do
local layer = consume(self)
if layer ~= nil then
return layer
end
advance(self)
end
end
-- Converts a handler into a switch table the first time it's called, which avoids creating unnecessary objects, and prevents any scoping issues caused by parser methods being assigned to table keys before they've been declared.
-- false is used as the default key.
do
local Switch = {}
function Switch:__call(parser, this)
return (self[this] or self[false])(parser, this)
end
function Parser:switch(func, t)
local pdata = self.current_layer._parse_data
-- Point handler to the new switch table if the calling function is the current handler.
if pdata.handler == func then
pdata.handler = t
end
return setmetatable(t, Switch)
end
end
-- Generate a new parser class object, which is used as the template for any parser objects. These should be customized with additional/modified methods as needed.
function Parser:new_class()
local t = {}
t.__index = t
return setmetatable(inherit_metamethods(t, self), self)
end
-- Generate a new parser object, which is used for a specific parse.
function Parser:new(text)
return setmetatable({
text = text,
head = 1
}, self)
end
function Parser:parse(data)
local parser = self:new(data.text)
local success, tokens = parser:try(unpack(data.route))
if #parser > 0 then
-- This shouldn't happen.
error("Parser exited with non-empty stack.")
elseif success then
local node = data.node
return true, node[1]:new(tokens, unpack(node, 2)), parser
elseif data.allow_fail then
return false, nil, parser
end
error("Parser exited with failed route.")
end
export.class_else_type = class_else_type
export.is_node = is_node
export.tostring = tostring
local ArrayParser = Parser:new_class()
function ArrayParser:read(delta)
local v = self.text[self.head + (delta or 0)]
return v == nil and "" or v
end
function ArrayParser:advance(n)
self.head = self.head + (n == nil and 1 or n)
end
function ArrayParser:jump(head)
self.head = head
end
function ArrayParser:consume(this, ...)
if this == nil then
this = self:read()
end
local pdata = self.current_layer._parse_data
return pdata.handler(self, this, ...)
end
function export.array_parser()
return ArrayParser:new_class()
end
local StringParser = Parser:new_class()
function StringParser:read(i, j)
local head, i = self.head, i or 0
return sub(self.text, head + i, head + (j or i))
end
function StringParser:advance(n)
self.head = self.head + (n or self.current_layer._parse_data.step or 1)
end
function StringParser:jump(head)
local pdata = self.current_layer._parse_data
self.head, pdata.next, pdata.next_len = head, nil, nil
end
-- If `ignore_nonmatch` is set, any non-match segment before the match will be ignored.
function StringParser:set_pattern(pattern, ignore_nonmatch)
local pdata = self.current_layer._parse_data
pdata.pattern, pdata.next, pdata.next_len = "(" .. pattern .. ")", nil, nil
if ignore_nonmatch then
pdata.ignore_nonmatch = true
end
end
function StringParser:consume()
local pdata = self.current_layer._parse_data
local this = pdata.next
-- Use `next` and `next_len` from the previous iteration, if available.
if this then
pdata.step, pdata.next, pdata.next_len = pdata.next_len, nil, nil
return pdata.handler(self, this)
end
local text, head, loc1, loc2 = self.text, self.head
loc1, loc2, this = find(text, pdata.pattern, head)
-- If there was no match, default to find(text, "$", head), with `this` as
-- the empty string.
if not loc1 then
this, loc1 = "", #text + 1
loc2 = loc1 - 1 -- zero-length matches cause loc2 to be less than loc1
end
-- If `this` is at `head`, consume it.
if loc1 == head then
pdata.step = loc2 - loc1 + 1
-- If `ignore_nonmatch` is set, ignore everything before `this`, then
-- consume it.
elseif pdata.ignore_nonmatch then
self.head, pdata.step = loc1, loc2 - loc1 + 1
-- Otherwise, consume everything before `this`, and memoize the match and
-- match length; the length is dealt with separately, as it could be 0 if
-- `next` is an index (e.g. if the pattern is the empty string).
else
this, pdata.step, pdata.next, pdata.next_len = sub(text, head, loc1 - 1), loc1 - head, this, loc2 - loc1 + 1
end
return pdata.handler(self, this)
end
function export.string_parser()
return StringParser:new_class()
end
return export<noinclude>
<small>Halaman ini telah dipindahkan dari [[en:Module:parser]]. Sejarah penyuntingannya dapat dilihat di [[ModulModule:parser/edithistory]]</small></noinclude>
jdlxjw6fpzm5gxupcqiatxybx7toqi1
25192
25190
2026-08-19T04:24:51Z
Deepturquoise
2456
Deepturquoise mindahkeun kaca [[Modul:parser]] ka [[ModulModule:parser]] maké pindahan: Kembalikan
25189
wikitext
text/x-wiki
local export = {}
local scribunto_metamethods_module = "Module:Scribunto/metamethods"
local table_deep_copy_module = "Module:table/deepCopy"
local table_get_nested_module = "Module:table/getNested"
local table_set_nested_module = "Module:table/setNested"
local concat = table.concat
local find = string.find
local getmetatable = getmetatable
local insert = table.insert
local next = next
local rawget = rawget
local rawset = rawset
local remove = table.remove
local require = require
local select = select
local setmetatable = setmetatable
local sub = string.sub
local type = type
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local node_classes = {}
local function deep_copy(...)
deep_copy = require(table_deep_copy_module)
return deep_copy(...)
end
local function get_nested(...)
get_nested = require(table_get_nested_module)
return get_nested(...)
end
local function set_nested(...)
set_nested = require(table_set_nested_module)
return set_nested(...)
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 metamethods
local function get_metamethods()
-- Use require, since lookup times are much slower with mw.loadData.
metamethods, get_metamethods = require(scribunto_metamethods_module), nil
return metamethods
end
------------------------------------------------------------------------------------
--
-- Helper functions
--
------------------------------------------------------------------------------------
local function inherit_metamethods(child, parent)
if parent then
for method, value in next, parent do
if child[method] == nil and (metamethods or get_metamethods())[method] ~= nil then
child[method] = value
end
end
end
return child
end
local function signed_index(t, n)
return n and n <= 0 and #t + 1 + n or n
end
local function is_node(value)
if value == nil then
return false
end
local mt = getmetatable(value)
return not (mt == nil or node_classes[mt] == nil)
end
local function node_class(value)
if value == nil then
return nil
end
local mt = getmetatable(value)
if mt == nil then
return nil
end
return mt ~= nil and node_classes[mt] or nil
end
local function class_else_type(value)
if value == nil then
return type(value)
end
local mt = getmetatable(value)
if mt == nil then
return type(value)
end
local class = node_classes[mt]
return class == nil and type(value) or class
end
-- Recursively calling tostring() adds to the C stack (limit: 200), whereas
-- calling __tostring metamethods directly does not. Occasionally relevant when
-- dealing with very deep nesting.
local tostring
do
local _tostring = _G.tostring
function tostring(value)
if is_node(value) then
return value:__tostring(value)
end
return _tostring(value)
end
end
------------------------------------------------------------------------------------
--
-- Nodes
--
------------------------------------------------------------------------------------
local Node = {}
Node.__index = Node
function Node:next(i)
i = i + 1
return self[i], self, i
end
--[==[
Implements recursive iteration over a node tree.
By default, when a node is encountered (which may contain other nodes), it is returned on the first iteration, and then any child nodes are returned on each subsequent iteration; the same process is then followed if any of those children contain nodes themselves. Once a particular node has been fully traversed, the iterator then continues with any sibling nodes. The iterator will use the `next` method of each node to traverse it, which may differ depending on the node class.
Each iteration returns three values: `value`, `node` and `key`. Together, these can be used to manipulate the node tree at any given point without needing to know the full structure. Note that when the input node is returned on the first iteration, `node` and `key` will be nil.
The optional argument `test` can be used to limit the return values. This should be a function that returns a boolean value, where a return value of true means that the child will be returned by the iterator. If a node is not returned by the iterator, it will still be traversed, as it may contain children that should be returned.
The method `iterate_nodes` is provided as a special instance of iterate which uses `is_node` as the test.]==]
function Node:iterate(test)
local node, k, n, nodes, keys, returned_self = self, 0, 0
-- Special case if `test` is `is_node`.
local is_node_is_test = test == is_node
return function()
if not returned_self then
returned_self = true
if test == nil or test(self) then
return self
end
end
-- Get `v`, which is the value at the last-returned key of the current node; if `v` is a node, it will be iterated over (i.e. recursive iteration). By default, `v` will be the last-returned value, but looking it up here means that any modifications made to the node during the loop will be taken into account. This makes it possible to swap one node out for something else (e.g. another node), or to remove it entirely, without being locked into recursively iterating over the old node; instead, the new node (if any) will be iterated over. This means node trees can be modified on-the-fly during the course of a single loop.
local v, node_check = node[k], true
while true do
-- If `v` is a node, memoize the current node and key, then iterate over it.
if node_check and is_node(v) then
-- `n` is the current memo level.
n = n + 1
if nodes then
nodes[n], keys[n] = node, k
else
nodes, keys = {node}, {k}
end
node, k = v, 0
end
v, node, k = node:next(k)
-- If `v` is nil, move down one level, then continue iterating the node on that level (if any), or otherwise terminate the loop.
if v == nil then
if n == 0 then
return nil
end
node, k, n = nodes[n], keys[n], n - 1
elseif test == nil or test(v) then
return v, node, k
-- If `test` is `is_node`, there's no point checking it again on the next loop.
elseif node_check and is_node_is_test then
node_check = false
end
end
end
end
function Node:iterate_nodes(...)
local args_n = select("#", ...)
if args_n == 0 then
return self:iterate(is_node)
elseif args_n == 1 then
local class = ...
return self:iterate(function(value)
return node_class(value) == class
end)
end
local classes = {}
for i = 1, args_n do
classes[select(i, ...)] = true
end
return self:iterate(function(value)
return classes[node_class(value)]
end)
end
function Node:__tostring()
local output = {}
for i = 1, #self do
insert(output, tostring(self[i]))
end
return concat(output)
end
function Node:clone()
return deep_copy(self, "keep", true)
end
function Node:new_class(class)
local t = {type = class}
t.__index = t
t = inherit_metamethods(t, self)
node_classes[t] = class
return setmetatable(t, self)
end
function Node:new(t)
rawset(t, "_parse_data", nil)
return setmetatable(t, self)
end
do
local Proxy = {}
function Proxy:__index(k)
local v = Proxy[k]
if v ~= nil then
return v
end
return self.__chars[k]
end
function Proxy:__newindex(k, v)
local key = self.__keys[k]
if key then
self.__chars[k] = v
self.__parents[key] = v
elseif key == false then
error("Character is immutable.")
else
error("Invalid key.")
end
end
function Proxy:build(a, b, c)
local len = self.__len + 1
self.__chars[len] = a
self.__parents[len] = b
self.__keys[len] = c
self.__len = len
end
function Proxy:iter(i)
i = i + 1
local char = self.__chars[i]
if char ~= nil then
return i, self[i], self, self.__parents[i], self.__keys[i]
end
end
function Node:new_proxy()
return setmetatable({
__node = self,
__chars = {},
__parents = {},
__keys = {},
__len = 0
}, Proxy)
end
end
function export.node()
return Node:new_class("node")
end
------------------------------------------------------------------------------------
--
-- Parser
--
------------------------------------------------------------------------------------
local Parser = {}
Parser.__index = Parser
function Parser:get_layer(n)
if n ~= nil then
return rawget(self, #self + n)
end
return self.current_layer
end
function Parser:emit(a, b)
local layer = self.current_layer
if b ~= nil then
insert(layer, signed_index(layer, a), b)
else
rawset(layer, #layer + 1, a)
end
end
function Parser:emit_tokens(a, b)
local layer = self.current_layer
if b ~= nil then
a = signed_index(layer, a)
for i = 1, #b do
insert(layer, a + i - 1, b[i])
end
else
local len = #layer
for i = 1, #a do
len = len + 1
rawset(layer, len, a[i])
end
end
end
function Parser:remove(n)
local layer = self.current_layer
if n ~= nil then
return remove(layer, signed_index(layer, n))
end
local len = #layer
local token = layer[len]
layer[len] = nil
return token
end
function Parser:replace(a, b)
local layer = self.current_layer
layer[signed_index(layer, a)] = b
end
-- Unlike default table.concat, this respects __tostring metamethods.
function Parser:concat(a, b, c)
if a == nil or a > 0 then
return self:concat(0, a, b)
end
local layer, ret, n = self:get_layer(a), {}, 0
for i = b and signed_index(layer, b) or 1, c and signed_index(layer, c) or #layer do
n = n + 1
ret[n] = tostring(layer[i])
end
return concat(ret)
end
function Parser:emitted(delta)
if delta == nil then
delta = -1
end
local get_layer, i = self.get_layer, 0
while true do
local layer = get_layer(self, i)
if layer == nil then
return nil
end
local layer_len = #layer
if -delta <= layer_len then
return rawget(layer, layer_len + delta + 1)
end
delta = delta + layer_len
i = i - 1
end
end
function Parser:push(route)
local layer = {_parse_data = {
head = self.head,
route = route,
}}
self[#self + 1] = layer
self.current_layer = layer
end
function Parser:push_sublayer(handler, inherit)
local pdata = {
handler = handler,
sublayer = true,
}
local sublayer = {
_parse_data = pdata,
}
if inherit then
local layer_parse_data = self.current_layer._parse_data
setmetatable(pdata, inherit_metamethods({
__index = layer_parse_data,
__newindex = layer_parse_data
}, getmetatable(layer_parse_data)))
end
self[#self + 1] = sublayer
self.current_layer = sublayer
end
function Parser:pop()
local len, layer = #self
while true do
layer = self[len]
self[len] = nil
len = len - 1
if len == 0 then
self.current_layer = self
break
elseif layer._parse_data.sublayer == nil then
self.current_layer = self[len]
break
end
self:emit_tokens(layer)
end
return setmetatable(layer, nil)
end
function Parser:pop_sublayer()
local len, layer = #self, self.current_layer
self[len] = nil
self.current_layer = len == 1 and self or self[len - 1]
return setmetatable(layer, nil)
end
function Parser:get(route, ...)
self:push(route)
local layer = route(self, ...)
if layer == nil then
layer = self:traverse()
end
return layer
end
function Parser:try(route, ...)
local failed_routes = self.failed_routes
if failed_routes ~= nil then
local failed_layer = get_nested(failed_routes, route, self.head)
if failed_layer ~= nil then
return false, failed_layer
end
end
local layer = self:get(route, ...)
return not layer._parse_data.fail, layer
end
function Parser:fail_route()
local layer = self:pop()
local pdata = layer._parse_data
pdata.fail = true
local layer_head = pdata.head
set_nested(self, layer, "failed_routes", pdata.route, layer_head)
self.head = layer_head
return layer
end
function Parser:traverse()
local consume, advance = self.consume, self.advance
while true do
local layer = consume(self)
if layer ~= nil then
return layer
end
advance(self)
end
end
-- Converts a handler into a switch table the first time it's called, which avoids creating unnecessary objects, and prevents any scoping issues caused by parser methods being assigned to table keys before they've been declared.
-- false is used as the default key.
do
local Switch = {}
function Switch:__call(parser, this)
return (self[this] or self[false])(parser, this)
end
function Parser:switch(func, t)
local pdata = self.current_layer._parse_data
-- Point handler to the new switch table if the calling function is the current handler.
if pdata.handler == func then
pdata.handler = t
end
return setmetatable(t, Switch)
end
end
-- Generate a new parser class object, which is used as the template for any parser objects. These should be customized with additional/modified methods as needed.
function Parser:new_class()
local t = {}
t.__index = t
return setmetatable(inherit_metamethods(t, self), self)
end
-- Generate a new parser object, which is used for a specific parse.
function Parser:new(text)
return setmetatable({
text = text,
head = 1
}, self)
end
function Parser:parse(data)
local parser = self:new(data.text)
local success, tokens = parser:try(unpack(data.route))
if #parser > 0 then
-- This shouldn't happen.
error("Parser exited with non-empty stack.")
elseif success then
local node = data.node
return true, node[1]:new(tokens, unpack(node, 2)), parser
elseif data.allow_fail then
return false, nil, parser
end
error("Parser exited with failed route.")
end
export.class_else_type = class_else_type
export.is_node = is_node
export.tostring = tostring
local ArrayParser = Parser:new_class()
function ArrayParser:read(delta)
local v = self.text[self.head + (delta or 0)]
return v == nil and "" or v
end
function ArrayParser:advance(n)
self.head = self.head + (n == nil and 1 or n)
end
function ArrayParser:jump(head)
self.head = head
end
function ArrayParser:consume(this, ...)
if this == nil then
this = self:read()
end
local pdata = self.current_layer._parse_data
return pdata.handler(self, this, ...)
end
function export.array_parser()
return ArrayParser:new_class()
end
local StringParser = Parser:new_class()
function StringParser:read(i, j)
local head, i = self.head, i or 0
return sub(self.text, head + i, head + (j or i))
end
function StringParser:advance(n)
self.head = self.head + (n or self.current_layer._parse_data.step or 1)
end
function StringParser:jump(head)
local pdata = self.current_layer._parse_data
self.head, pdata.next, pdata.next_len = head, nil, nil
end
-- If `ignore_nonmatch` is set, any non-match segment before the match will be ignored.
function StringParser:set_pattern(pattern, ignore_nonmatch)
local pdata = self.current_layer._parse_data
pdata.pattern, pdata.next, pdata.next_len = "(" .. pattern .. ")", nil, nil
if ignore_nonmatch then
pdata.ignore_nonmatch = true
end
end
function StringParser:consume()
local pdata = self.current_layer._parse_data
local this = pdata.next
-- Use `next` and `next_len` from the previous iteration, if available.
if this then
pdata.step, pdata.next, pdata.next_len = pdata.next_len, nil, nil
return pdata.handler(self, this)
end
local text, head, loc1, loc2 = self.text, self.head
loc1, loc2, this = find(text, pdata.pattern, head)
-- If there was no match, default to find(text, "$", head), with `this` as
-- the empty string.
if not loc1 then
this, loc1 = "", #text + 1
loc2 = loc1 - 1 -- zero-length matches cause loc2 to be less than loc1
end
-- If `this` is at `head`, consume it.
if loc1 == head then
pdata.step = loc2 - loc1 + 1
-- If `ignore_nonmatch` is set, ignore everything before `this`, then
-- consume it.
elseif pdata.ignore_nonmatch then
self.head, pdata.step = loc1, loc2 - loc1 + 1
-- Otherwise, consume everything before `this`, and memoize the match and
-- match length; the length is dealt with separately, as it could be 0 if
-- `next` is an index (e.g. if the pattern is the empty string).
else
this, pdata.step, pdata.next, pdata.next_len = sub(text, head, loc1 - 1), loc1 - head, this, loc2 - loc1 + 1
end
return pdata.handler(self, this)
end
function export.string_parser()
return StringParser:new_class()
end
return export<noinclude>
<small>Halaman ini telah dipindahkan dari [[en:Module:parser]]. Sejarah penyuntingannya dapat dilihat di [[ModulModule:parser/edithistory]]</small></noinclude>
jdlxjw6fpzm5gxupcqiatxybx7toqi1
25194
25192
2026-08-19T04:33:39Z
Deepturquoise
2456
25194
wikitext
text/x-wiki
{{delete}}
local export = {}
local scribunto_metamethods_module = "Module:Scribunto/metamethods"
local table_deep_copy_module = "Module:table/deepCopy"
local table_get_nested_module = "Module:table/getNested"
local table_set_nested_module = "Module:table/setNested"
local concat = table.concat
local find = string.find
local getmetatable = getmetatable
local insert = table.insert
local next = next
local rawget = rawget
local rawset = rawset
local remove = table.remove
local require = require
local select = select
local setmetatable = setmetatable
local sub = string.sub
local type = type
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local node_classes = {}
local function deep_copy(...)
deep_copy = require(table_deep_copy_module)
return deep_copy(...)
end
local function get_nested(...)
get_nested = require(table_get_nested_module)
return get_nested(...)
end
local function set_nested(...)
set_nested = require(table_set_nested_module)
return set_nested(...)
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 metamethods
local function get_metamethods()
-- Use require, since lookup times are much slower with mw.loadData.
metamethods, get_metamethods = require(scribunto_metamethods_module), nil
return metamethods
end
------------------------------------------------------------------------------------
--
-- Helper functions
--
------------------------------------------------------------------------------------
local function inherit_metamethods(child, parent)
if parent then
for method, value in next, parent do
if child[method] == nil and (metamethods or get_metamethods())[method] ~= nil then
child[method] = value
end
end
end
return child
end
local function signed_index(t, n)
return n and n <= 0 and #t + 1 + n or n
end
local function is_node(value)
if value == nil then
return false
end
local mt = getmetatable(value)
return not (mt == nil or node_classes[mt] == nil)
end
local function node_class(value)
if value == nil then
return nil
end
local mt = getmetatable(value)
if mt == nil then
return nil
end
return mt ~= nil and node_classes[mt] or nil
end
local function class_else_type(value)
if value == nil then
return type(value)
end
local mt = getmetatable(value)
if mt == nil then
return type(value)
end
local class = node_classes[mt]
return class == nil and type(value) or class
end
-- Recursively calling tostring() adds to the C stack (limit: 200), whereas
-- calling __tostring metamethods directly does not. Occasionally relevant when
-- dealing with very deep nesting.
local tostring
do
local _tostring = _G.tostring
function tostring(value)
if is_node(value) then
return value:__tostring(value)
end
return _tostring(value)
end
end
------------------------------------------------------------------------------------
--
-- Nodes
--
------------------------------------------------------------------------------------
local Node = {}
Node.__index = Node
function Node:next(i)
i = i + 1
return self[i], self, i
end
--[==[
Implements recursive iteration over a node tree.
By default, when a node is encountered (which may contain other nodes), it is returned on the first iteration, and then any child nodes are returned on each subsequent iteration; the same process is then followed if any of those children contain nodes themselves. Once a particular node has been fully traversed, the iterator then continues with any sibling nodes. The iterator will use the `next` method of each node to traverse it, which may differ depending on the node class.
Each iteration returns three values: `value`, `node` and `key`. Together, these can be used to manipulate the node tree at any given point without needing to know the full structure. Note that when the input node is returned on the first iteration, `node` and `key` will be nil.
The optional argument `test` can be used to limit the return values. This should be a function that returns a boolean value, where a return value of true means that the child will be returned by the iterator. If a node is not returned by the iterator, it will still be traversed, as it may contain children that should be returned.
The method `iterate_nodes` is provided as a special instance of iterate which uses `is_node` as the test.]==]
function Node:iterate(test)
local node, k, n, nodes, keys, returned_self = self, 0, 0
-- Special case if `test` is `is_node`.
local is_node_is_test = test == is_node
return function()
if not returned_self then
returned_self = true
if test == nil or test(self) then
return self
end
end
-- Get `v`, which is the value at the last-returned key of the current node; if `v` is a node, it will be iterated over (i.e. recursive iteration). By default, `v` will be the last-returned value, but looking it up here means that any modifications made to the node during the loop will be taken into account. This makes it possible to swap one node out for something else (e.g. another node), or to remove it entirely, without being locked into recursively iterating over the old node; instead, the new node (if any) will be iterated over. This means node trees can be modified on-the-fly during the course of a single loop.
local v, node_check = node[k], true
while true do
-- If `v` is a node, memoize the current node and key, then iterate over it.
if node_check and is_node(v) then
-- `n` is the current memo level.
n = n + 1
if nodes then
nodes[n], keys[n] = node, k
else
nodes, keys = {node}, {k}
end
node, k = v, 0
end
v, node, k = node:next(k)
-- If `v` is nil, move down one level, then continue iterating the node on that level (if any), or otherwise terminate the loop.
if v == nil then
if n == 0 then
return nil
end
node, k, n = nodes[n], keys[n], n - 1
elseif test == nil or test(v) then
return v, node, k
-- If `test` is `is_node`, there's no point checking it again on the next loop.
elseif node_check and is_node_is_test then
node_check = false
end
end
end
end
function Node:iterate_nodes(...)
local args_n = select("#", ...)
if args_n == 0 then
return self:iterate(is_node)
elseif args_n == 1 then
local class = ...
return self:iterate(function(value)
return node_class(value) == class
end)
end
local classes = {}
for i = 1, args_n do
classes[select(i, ...)] = true
end
return self:iterate(function(value)
return classes[node_class(value)]
end)
end
function Node:__tostring()
local output = {}
for i = 1, #self do
insert(output, tostring(self[i]))
end
return concat(output)
end
function Node:clone()
return deep_copy(self, "keep", true)
end
function Node:new_class(class)
local t = {type = class}
t.__index = t
t = inherit_metamethods(t, self)
node_classes[t] = class
return setmetatable(t, self)
end
function Node:new(t)
rawset(t, "_parse_data", nil)
return setmetatable(t, self)
end
do
local Proxy = {}
function Proxy:__index(k)
local v = Proxy[k]
if v ~= nil then
return v
end
return self.__chars[k]
end
function Proxy:__newindex(k, v)
local key = self.__keys[k]
if key then
self.__chars[k] = v
self.__parents[key] = v
elseif key == false then
error("Character is immutable.")
else
error("Invalid key.")
end
end
function Proxy:build(a, b, c)
local len = self.__len + 1
self.__chars[len] = a
self.__parents[len] = b
self.__keys[len] = c
self.__len = len
end
function Proxy:iter(i)
i = i + 1
local char = self.__chars[i]
if char ~= nil then
return i, self[i], self, self.__parents[i], self.__keys[i]
end
end
function Node:new_proxy()
return setmetatable({
__node = self,
__chars = {},
__parents = {},
__keys = {},
__len = 0
}, Proxy)
end
end
function export.node()
return Node:new_class("node")
end
------------------------------------------------------------------------------------
--
-- Parser
--
------------------------------------------------------------------------------------
local Parser = {}
Parser.__index = Parser
function Parser:get_layer(n)
if n ~= nil then
return rawget(self, #self + n)
end
return self.current_layer
end
function Parser:emit(a, b)
local layer = self.current_layer
if b ~= nil then
insert(layer, signed_index(layer, a), b)
else
rawset(layer, #layer + 1, a)
end
end
function Parser:emit_tokens(a, b)
local layer = self.current_layer
if b ~= nil then
a = signed_index(layer, a)
for i = 1, #b do
insert(layer, a + i - 1, b[i])
end
else
local len = #layer
for i = 1, #a do
len = len + 1
rawset(layer, len, a[i])
end
end
end
function Parser:remove(n)
local layer = self.current_layer
if n ~= nil then
return remove(layer, signed_index(layer, n))
end
local len = #layer
local token = layer[len]
layer[len] = nil
return token
end
function Parser:replace(a, b)
local layer = self.current_layer
layer[signed_index(layer, a)] = b
end
-- Unlike default table.concat, this respects __tostring metamethods.
function Parser:concat(a, b, c)
if a == nil or a > 0 then
return self:concat(0, a, b)
end
local layer, ret, n = self:get_layer(a), {}, 0
for i = b and signed_index(layer, b) or 1, c and signed_index(layer, c) or #layer do
n = n + 1
ret[n] = tostring(layer[i])
end
return concat(ret)
end
function Parser:emitted(delta)
if delta == nil then
delta = -1
end
local get_layer, i = self.get_layer, 0
while true do
local layer = get_layer(self, i)
if layer == nil then
return nil
end
local layer_len = #layer
if -delta <= layer_len then
return rawget(layer, layer_len + delta + 1)
end
delta = delta + layer_len
i = i - 1
end
end
function Parser:push(route)
local layer = {_parse_data = {
head = self.head,
route = route,
}}
self[#self + 1] = layer
self.current_layer = layer
end
function Parser:push_sublayer(handler, inherit)
local pdata = {
handler = handler,
sublayer = true,
}
local sublayer = {
_parse_data = pdata,
}
if inherit then
local layer_parse_data = self.current_layer._parse_data
setmetatable(pdata, inherit_metamethods({
__index = layer_parse_data,
__newindex = layer_parse_data
}, getmetatable(layer_parse_data)))
end
self[#self + 1] = sublayer
self.current_layer = sublayer
end
function Parser:pop()
local len, layer = #self
while true do
layer = self[len]
self[len] = nil
len = len - 1
if len == 0 then
self.current_layer = self
break
elseif layer._parse_data.sublayer == nil then
self.current_layer = self[len]
break
end
self:emit_tokens(layer)
end
return setmetatable(layer, nil)
end
function Parser:pop_sublayer()
local len, layer = #self, self.current_layer
self[len] = nil
self.current_layer = len == 1 and self or self[len - 1]
return setmetatable(layer, nil)
end
function Parser:get(route, ...)
self:push(route)
local layer = route(self, ...)
if layer == nil then
layer = self:traverse()
end
return layer
end
function Parser:try(route, ...)
local failed_routes = self.failed_routes
if failed_routes ~= nil then
local failed_layer = get_nested(failed_routes, route, self.head)
if failed_layer ~= nil then
return false, failed_layer
end
end
local layer = self:get(route, ...)
return not layer._parse_data.fail, layer
end
function Parser:fail_route()
local layer = self:pop()
local pdata = layer._parse_data
pdata.fail = true
local layer_head = pdata.head
set_nested(self, layer, "failed_routes", pdata.route, layer_head)
self.head = layer_head
return layer
end
function Parser:traverse()
local consume, advance = self.consume, self.advance
while true do
local layer = consume(self)
if layer ~= nil then
return layer
end
advance(self)
end
end
-- Converts a handler into a switch table the first time it's called, which avoids creating unnecessary objects, and prevents any scoping issues caused by parser methods being assigned to table keys before they've been declared.
-- false is used as the default key.
do
local Switch = {}
function Switch:__call(parser, this)
return (self[this] or self[false])(parser, this)
end
function Parser:switch(func, t)
local pdata = self.current_layer._parse_data
-- Point handler to the new switch table if the calling function is the current handler.
if pdata.handler == func then
pdata.handler = t
end
return setmetatable(t, Switch)
end
end
-- Generate a new parser class object, which is used as the template for any parser objects. These should be customized with additional/modified methods as needed.
function Parser:new_class()
local t = {}
t.__index = t
return setmetatable(inherit_metamethods(t, self), self)
end
-- Generate a new parser object, which is used for a specific parse.
function Parser:new(text)
return setmetatable({
text = text,
head = 1
}, self)
end
function Parser:parse(data)
local parser = self:new(data.text)
local success, tokens = parser:try(unpack(data.route))
if #parser > 0 then
-- This shouldn't happen.
error("Parser exited with non-empty stack.")
elseif success then
local node = data.node
return true, node[1]:new(tokens, unpack(node, 2)), parser
elseif data.allow_fail then
return false, nil, parser
end
error("Parser exited with failed route.")
end
export.class_else_type = class_else_type
export.is_node = is_node
export.tostring = tostring
local ArrayParser = Parser:new_class()
function ArrayParser:read(delta)
local v = self.text[self.head + (delta or 0)]
return v == nil and "" or v
end
function ArrayParser:advance(n)
self.head = self.head + (n == nil and 1 or n)
end
function ArrayParser:jump(head)
self.head = head
end
function ArrayParser:consume(this, ...)
if this == nil then
this = self:read()
end
local pdata = self.current_layer._parse_data
return pdata.handler(self, this, ...)
end
function export.array_parser()
return ArrayParser:new_class()
end
local StringParser = Parser:new_class()
function StringParser:read(i, j)
local head, i = self.head, i or 0
return sub(self.text, head + i, head + (j or i))
end
function StringParser:advance(n)
self.head = self.head + (n or self.current_layer._parse_data.step or 1)
end
function StringParser:jump(head)
local pdata = self.current_layer._parse_data
self.head, pdata.next, pdata.next_len = head, nil, nil
end
-- If `ignore_nonmatch` is set, any non-match segment before the match will be ignored.
function StringParser:set_pattern(pattern, ignore_nonmatch)
local pdata = self.current_layer._parse_data
pdata.pattern, pdata.next, pdata.next_len = "(" .. pattern .. ")", nil, nil
if ignore_nonmatch then
pdata.ignore_nonmatch = true
end
end
function StringParser:consume()
local pdata = self.current_layer._parse_data
local this = pdata.next
-- Use `next` and `next_len` from the previous iteration, if available.
if this then
pdata.step, pdata.next, pdata.next_len = pdata.next_len, nil, nil
return pdata.handler(self, this)
end
local text, head, loc1, loc2 = self.text, self.head
loc1, loc2, this = find(text, pdata.pattern, head)
-- If there was no match, default to find(text, "$", head), with `this` as
-- the empty string.
if not loc1 then
this, loc1 = "", #text + 1
loc2 = loc1 - 1 -- zero-length matches cause loc2 to be less than loc1
end
-- If `this` is at `head`, consume it.
if loc1 == head then
pdata.step = loc2 - loc1 + 1
-- If `ignore_nonmatch` is set, ignore everything before `this`, then
-- consume it.
elseif pdata.ignore_nonmatch then
self.head, pdata.step = loc1, loc2 - loc1 + 1
-- Otherwise, consume everything before `this`, and memoize the match and
-- match length; the length is dealt with separately, as it could be 0 if
-- `next` is an index (e.g. if the pattern is the empty string).
else
this, pdata.step, pdata.next, pdata.next_len = sub(text, head, loc1 - 1), loc1 - head, this, loc2 - loc1 + 1
end
return pdata.handler(self, this)
end
function export.string_parser()
return StringParser:new_class()
end
return export<noinclude>
<small>Halaman ini telah dipindahkan dari [[en:Module:parser]]. Sejarah penyuntingannya dapat dilihat di [[ModulModule:parser/edithistory]]</small></noinclude>
ghyr4bt7o6yhjxqvan59xqpxkl4e9al
Modul:parser
828
9234
25193
2026-08-19T04:24:51Z
Deepturquoise
2456
Deepturquoise mindahkeun kaca [[Modul:parser]] ka [[ModulModule:parser]] maké pindahan: Kembalikan
25193
wikitext
text/x-wiki
#ALIH [[ModulModule:parser]]
3hkrg3we9kszjwv41g5ppau7feyu1qe
25205
25193
2026-08-19T04:48:50Z
Deepturquoise
2456
Menghapus pengalihan ke [[ModulModule:parser]]
25205
wikitext
text/x-wiki
{{delete}}
#ALIH [[ModulModule:parser]]
8n51dly4hntgpi5vcz6mbx2s8ydiz5u
Modul:Scribunto/metamethods
828
9235
25195
2026-08-19T04:37:10Z
Deepturquoise
2456
+ ti enwikt
25195
Scribunto
text/plain
return {
__add = true,
__call = true,
__concat = true,
__div = true,
__eq = true,
__gc = true,
__index = true,
__ipairs = true,
__le = true,
__len = true,
__lt = true,
__metatable = true,
__mod = true,
__mode = true,
__mul = true,
__newindex = true,
__pairs = true,
__pow = true,
__sub = true,
__tostring = true,
__unm = true,
}
9ldqvu9rhlfkuksyro1b52m6ychbevm
Modul:data/magic words
828
9236
25196
2026-08-19T04:38:05Z
Deepturquoise
2456
+ ti enwikt
25196
Scribunto
text/plain
local next = next
local date_and_time = "mw:Help:Magic words#Date and time"
local escaped_characters = "mw:Help:Magic words#Escaped characters"
local formatting = "mw:Help:Magic words#Formatting"
local labeled_section_transclusion = "mw:Extension:Labeled Section Transclusion"
local liquidthreads = "mw:Extension:LiquidThreads"
local localization_functions = "mw:Help:Magic words#Localization functions"
local localization_variables = "mw:Help:Magic words#Localization variables"
local miscellaneous = "mw:Help:Magic words#Miscellaneous"
local namespaces = "mw:Help:Magic words#Namespaces"
local namespaces_2 = "mw:Help:Magic words#Namespaces 2"
local noexternallanglinks = "mw:Wikibase/Installation/Advanced configuration#noexternallanglinks"
local page_names = "mw:Help:Magic words#Page names"
local parser_functions_ext = "mw:Help:Extension:ParserFunctions##" -- ## is not a typo
local statistics = "mw:Help:Magic words#Statistics"
local substitution = "mw:Manual:Substitution"
local technical_metadata = "mw:Help:Magic words#Technical metadata"
local technical_metadata_of_another_page = "mw:Help:Magic words#Technical metadata of another page"
local transclusion_modifiers = "mw:Help:Magic words#Transclusion modifiers"
local url_data = "mw:Help:Magic words#URL data"
local data = {}
for k, v in next, {
["!"] = {
parser_variable = escaped_characters,
case_sensitive = false
},
["#BABEL"] = {
parser_function = "mw:Extension:Babel#Usage",
case_sensitive = false
},
["#bcp47"] = { -- Case-sensitive lowercase.
parser_function = localization_functions,
parser_variable = localization_functions, -- Not a typo.
case_sensitive = true
},
["#CATEGORYTREE"] = {
parser_function = "mw:Extension:CategoryTree#The {{#categorytree}} parser function",
case_sensitive = false
},
["#COMMASEPARATEDLIST"] = {
parser_function = formatting,
case_sensitive = false
},
["#dir"] = { -- Case-sensitive lowercase.
parser_function = localization_functions,
parser_variable = localization_functions, -- Not a typo.
case_sensitive = true
},
["#EXPR"] = {
parser_function = parser_functions_ext .. "expr",
case_sensitive = false
},
["#FORMAL"] = {
parser_function = localization_functions,
case_sensitive = true
},
["#FORMATDATE"] = {
aliases = {"#DATEFORMAT"},
parser_function = formatting,
case_sensitive = false
},
["#IF"] = {
parser_function = parser_functions_ext .. "if",
case_sensitive = false
},
["#IFEQ"] = {
parser_function = parser_functions_ext .. "ifeq",
case_sensitive = false
},
["#IFERROR"] = {
parser_function = parser_functions_ext .. "iferror",
case_sensitive = false
},
["#IFEXIST"] = {
parser_function = parser_functions_ext .. "ifexist",
case_sensitive = false
},
["#IFEXPR"] = {
parser_function = parser_functions_ext .. "ifexpr",
case_sensitive = false
},
["#interlanguagelink"] = { -- Case-sensitive lowercase.
parser_function = miscellaneous,
case_sensitive = true
},
["#interwikilink"] = { -- Case-sensitive lowercase.
parser_function = miscellaneous,
case_sensitive = true
},
["#INVOKE"] = {
parser_function = "mw:Extension:Scribunto#Usage",
case_sensitive = false
},
["#LANGUAGE"] = {
parser_function = localization_functions,
parser_variable = localization_functions, -- Not a typo.
case_sensitive = false
},
["#LQTPAGELIMIT"] = {
parser_function = liquidthreads,
case_sensitive = false
},
["#LST"] = {
aliases = {"#SECTION"},
parser_function = labeled_section_transclusion,
case_sensitive = false
},
["#LSTH"] = {
aliases = {"#SECTION-H"},
parser_function = labeled_section_transclusion,
case_sensitive = false
},
["#LSTX"] = {
aliases = {"#SECTION-X"},
parser_function = labeled_section_transclusion,
case_sensitive = false
},
["#PROPERTY"] = {
parser_function = "m:Wikidata/Notes/Inclusion syntax",
case_sensitive = false
},
["#REL2ABS"] = {
parser_function = parser_functions_ext .. "rel2abs",
case_sensitive = false
},
["#SPECIAL"] = {
parser_function = miscellaneous,
case_sensitive = false
},
["#SPECIALE"] = {
parser_function = miscellaneous,
case_sensitive = false
},
["#STATEMENTS"] = {
parser_function = "d:WD:How to use data on Wikimedia projects#Parser function",
case_sensitive = false
},
["#SWITCH"] = {
parser_function = parser_functions_ext .. "switch",
case_sensitive = false
},
["#TAG"] = {
parser_function = miscellaneous,
case_sensitive = false
},
["#TARGET"] = {
parser_function = "mw:Extension:MassMessage#Parser function delivery lists",
case_sensitive = false
},
["#TIME"] = {
parser_function = parser_functions_ext .. "time",
case_sensitive = false
},
["#timef"] = { -- Case-sensitive lowercase.
parser_function = parser_functions_ext,
case_sensitive = true
},
["#timefl"] = { -- Case-sensitive lowercase.
parser_function = parser_functions_ext,
case_sensitive = true
},
["#TIMEL"] = {
parser_function = parser_functions_ext .. "timel",
case_sensitive = false
},
["#TITLEPARTS"] = {
parser_function = parser_functions_ext .. "titleparts",
case_sensitive = false
},
["#USELIQUIDTHREADS"] = {
parser_function = liquidthreads,
case_sensitive = false
},
["="] = {
parser_variable = escaped_characters,
case_sensitive = false
},
["ANCHORENCODE"] = {
parser_function = url_data,
case_sensitive = false
},
["ARTICLEPATH"] = {
parser_variable = technical_metadata,
case_sensitive = false
},
["BASEPAGENAME"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["BASEPAGENAMEE"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["BIDI"] = {
parser_function = formatting,
case_sensitive = false
},
["CANONICALURL"] = {
parser_function = url_data,
case_sensitive = false
},
["CANONICALURLE"] = {
parser_function = url_data,
case_sensitive = false
},
["CASCADINGSOURCES"] = {
parser_function = technical_metadata_of_another_page,
parser_variable = technical_metadata,
case_sensitive = true
},
["CONTENTLANGUAGE"] = {
aliases = {"CONTENTLANG"},
parser_variable = technical_metadata,
case_sensitive = true
},
["CURRENTDAY"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTDAY2"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTDAYNAME"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTDOW"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTHOUR"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTMONTH"] = {
aliases = {"CURRENTMONTH2"},
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTMONTH1"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTMONTHABBREV"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTMONTHNAME"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTMONTHNAMEGEN"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTTIME"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTTIMESTAMP"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTVERSION"] = {
parser_variable = technical_metadata,
case_sensitive = true
},
["CURRENTWEEK"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["CURRENTYEAR"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["DEFAULTSORT"] = {
aliases = {"DEFAULTCATEGORYSORT", "DEFAULTSORTKEY"},
parser_function = technical_metadata,
case_sensitive = true
},
["DIRECTIONMARK"] = {
aliases = {"DIRMARK"},
parser_variable = technical_metadata,
case_sensitive = true
},
["DISPLAYTITLE"] = {
parser_function = technical_metadata,
case_sensitive = true
},
["FILEPATH"] = {
parser_function = url_data,
case_sensitive = false
},
["FORMATNUM"] = {
parser_function = formatting,
case_sensitive = false
},
["FULLPAGENAME"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["FULLPAGENAMEE"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["FULLURL"] = {
parser_function = url_data,
case_sensitive = false
},
["FULLURLE"] = {
parser_function = url_data,
case_sensitive = false
},
["GENDER"] = {
parser_function = localization_functions,
case_sensitive = false
},
["GRAMMAR"] = {
parser_function = localization_functions,
case_sensitive = false
},
["INT"] = {
parser_function = localization_functions,
case_sensitive = false
},
["LC"] = {
parser_function = formatting,
case_sensitive = false
},
["LCFIRST"] = {
parser_function = formatting,
case_sensitive = false
},
["LOCALDAY"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALDAY2"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALDAYNAME"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALDOW"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALHOUR"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALMONTH"] = {
aliases = {"LOCALMONTH2"},
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALMONTH1"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALMONTHABBREV"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALMONTHNAME"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALMONTHNAMEGEN"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALTIME"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALTIMESTAMP"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALURL"] = {
parser_function = url_data,
case_sensitive = false
},
["LOCALURLE"] = {
parser_function = url_data,
case_sensitive = false
},
["LOCALWEEK"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["LOCALYEAR"] = {
parser_variable = date_and_time,
case_sensitive = true
},
["MSG"] = {
transclusion_modifier = transclusion_modifiers,
priority = 2,
case_sensitive = false
},
["MSGNW"] = {
transclusion_modifier = transclusion_modifiers,
priority = 2,
case_sensitive = false
},
["NAMESPACE"] = {
parser_function = namespaces,
parser_variable = namespaces,
case_sensitive = true
},
["NAMESPACEE"] = {
parser_function = namespaces,
parser_variable = namespaces,
case_sensitive = true
},
["NAMESPACENUMBER"] = {
parser_function = namespaces,
parser_variable = namespaces,
case_sensitive = true
},
["NOEXTERNALLANGLINKS"] = {
parser_function = noexternallanglinks,
parser_variable = noexternallanglinks,
case_sensitive = false
},
["NS"] = {
parser_function = namespaces_2,
case_sensitive = false
},
["NSE"] = {
parser_function = namespaces_2,
case_sensitive = false
},
["NUMBERINGROUP"] = {
aliases = {"NUMINGROUP"},
parser_function = statistics,
case_sensitive = true
},
["NUMBEROFACTIVEUSERS"] = {
parser_function = statistics,
parser_variable = statistics,
case_sensitive = true
},
["NUMBEROFADMINS"] = {
parser_function = statistics,
parser_variable = statistics,
case_sensitive = true
},
["NUMBEROFARTICLES"] = {
parser_function = statistics,
parser_variable = statistics,
case_sensitive = true
},
["NUMBEROFEDITS"] = {
parser_function = statistics,
parser_variable = statistics,
case_sensitive = true
},
["NUMBEROFFILES"] = {
parser_function = statistics,
parser_variable = statistics,
case_sensitive = true
},
["NUMBEROFPAGES"] = {
parser_function = statistics,
parser_variable = statistics,
case_sensitive = true
},
["NUMBEROFUSERS"] = {
parser_function = statistics,
parser_variable = statistics,
case_sensitive = true
},
["PADLEFT"] = {
parser_function = formatting,
case_sensitive = false
},
["PADRIGHT"] = {
parser_function = formatting,
case_sensitive = false
},
["PAGEID"] = {
parser_function = technical_metadata_of_another_page,
parser_variable = technical_metadata,
case_sensitive = false
},
["PAGELANGUAGE"] = {
parser_variable = technical_metadata,
case_sensitive = true
},
["PAGENAME"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["PAGENAMEE"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["PAGESINCATEGORY"] = {
aliases = {"PAGESINCAT"},
parser_function = statistics,
case_sensitive = true
},
["PAGESIZE"] = {
parser_function = technical_metadata_of_another_page,
case_sensitive = true
},
["PLURAL"] = {
parser_function = localization_functions,
case_sensitive = false
},
["PROTECTIONEXPIRY"] = {
parser_function = {
technical_metadata,
technical_metadata_of_another_page
},
case_sensitive = true
},
["PROTECTIONLEVEL"] = {
parser_function = {
technical_metadata,
technical_metadata_of_another_page
},
case_sensitive = true
},
["RAW"] = {
transclusion_modifier = transclusion_modifiers,
priority = 3,
case_sensitive = false
},
["REVISIONDAY"] = {
parser_function = technical_metadata_of_another_page,
parser_variable = technical_metadata,
case_sensitive = true
},
["REVISIONDAY2"] = {
parser_function = technical_metadata_of_another_page,
parser_variable = technical_metadata,
case_sensitive = true
},
["REVISIONID"] = {
parser_function = technical_metadata_of_another_page,
parser_variable = technical_metadata,
case_sensitive = true
},
["REVISIONMONTH"] = {
parser_function = technical_metadata_of_another_page,
parser_variable = technical_metadata,
case_sensitive = true
},
["REVISIONMONTH1"] = {
parser_function = technical_metadata_of_another_page,
parser_variable = technical_metadata,
case_sensitive = true
},
["REVISIONSIZE"] = {
parser_variable = technical_metadata,
case_sensitive = true
},
["REVISIONTIMESTAMP"] = {
parser_function = technical_metadata_of_another_page,
parser_variable = technical_metadata,
case_sensitive = true
},
["REVISIONUSER"] = {
parser_function = technical_metadata_of_another_page,
parser_variable = technical_metadata,
case_sensitive = true
},
["REVISIONYEAR"] = {
parser_function = technical_metadata_of_another_page,
parser_variable = technical_metadata,
case_sensitive = true
},
["ROOTPAGENAME"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["ROOTPAGENAMEE"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["SAFESUBST"] = {
transclusion_modifier = substitution,
priority = 1,
case_sensitive = false
},
["SCRIPTPATH"] = {
parser_variable = technical_metadata,
case_sensitive = false
},
["SERVER"] = {
parser_variable = technical_metadata,
case_sensitive = false
},
["SERVERNAME"] = {
parser_variable = technical_metadata,
case_sensitive = false
},
["SITENAME"] = {
parser_variable = technical_metadata,
case_sensitive = true
},
["STYLEPATH"] = {
parser_variable = technical_metadata,
case_sensitive = false
},
["SUBJECTPAGENAME"] = {
aliases = {"ARTICLEPAGENAME"},
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["SUBJECTPAGENAMEE"] = {
aliases = {"ARTICLEPAGENAMEE"},
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["SUBJECTSPACE"] = {
aliases = {"ARTICLESPACE"},
parser_function = namespaces,
parser_variable = namespaces,
case_sensitive = true
},
["SUBJECTSPACEE"] = {
aliases = {"ARTICLESPACEE"},
parser_function = namespaces,
parser_variable = namespaces,
case_sensitive = true
},
["SUBPAGENAME"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["SUBPAGENAMEE"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["SUBST"] = {
transclusion_modifier = substitution,
priority = 1,
case_sensitive = false
},
["TALKPAGENAME"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["TALKPAGENAMEE"] = {
parser_function = page_names,
parser_variable = page_names,
case_sensitive = true
},
["TALKSPACE"] = {
parser_function = namespaces,
parser_variable = namespaces,
case_sensitive = true
},
["TALKSPACEE"] = {
parser_function = namespaces,
parser_variable = namespaces,
case_sensitive = true
},
["UC"] = {
parser_function = formatting,
case_sensitive = false
},
["UCFIRST"] = {
parser_function = formatting,
case_sensitive = false
},
["URLENCODE"] = {
parser_function = url_data,
case_sensitive = false
},
["USERLANGUAGE"] = {
parser_variable = localization_variables,
case_sensitive = true
},
} do
data[k] = v
if not v.name then
v.name = k
end
local aliases = v.aliases
if aliases then
for i = 1, #aliases do
data[aliases[i]] = v
end
v.aliases = nil
end
end
return data
jkwpl1ihlf560owi79olg91zvhvb1xy
Modul:data/parser extension tags
828
9237
25197
2026-08-19T04:39:01Z
Deepturquoise
2456
+ ti enwikt
25197
Scribunto
text/plain
--Note: noinclude, includeonly and onlyinclude are not parser extension tags, as they are handled in a special way by the preprocessor. Among other things, they cannot be used with {{#TAG:}}, for example.
return {
["categorytree"] = "mw:Extension:CategoryTree",
["ce"] = "mw:Extension:Math",
["charinsert"] = "mw:Extension:CharInsert",
["chem"] = "mw:Extension:Math",
["dynamicpagelist"] = "mw:Extension:DynamicPageList (Wikimedia)",
["gallery"] = "mw:Help:Images#Rendering a gallery of images",
["graph"] = "mw:Extension:Graph",
["hiero"] = "mw:Extension:WikiHiero",
["imagemap"] = "mw:Extension:ImageMap",
["indicator"] = "mw:Help:Page status indicators#Adding page status indicators",
["inputbox"] = "mw:Extension:InputBox",
["langconvert"] = "mw:Parser extension tags", -- undocumented
["mapframe"] = "mw:Extension:Kartographer",
["maplink"] = "mw:Extension:Kartographer",
["math"] = "mw:Extension:Math",
["nowiki"] = "mw:Help:Formatting",
["phonos"] = "mw:Extension:Phonos",
["poem"] = "mw:Extension:Poem",
["pre"] = "mw:Help:Formatting",
["ref"] = "mw:Extension:Cite",
["references"] = "mw:Extension:Cite",
["score"] = "mw:Extension:Score",
["section"] = "mw:Extension:Labeled Section Transclusion",
["source"] = "mw:Extension:SyntaxHighlight",
["syntaxhighlight"] = "mw:Extension:SyntaxHighlight",
["talkpage"] = "mw:Extension:LiquidThreads", -- undocumented
["templatedata"] = "mw:Extension:TemplateData",
["templatestyles"] = "mw:Extension:TemplateStyles",
["thread"] = "mw:Extension:LiquidThreads", -- undocumented
["timeline"] = "mw:Extension:EasyTimeline",
}
ofvfawk3x15dsa9oos9tt1283gyzpwv
Modul:languages/canonical names
828
9238
25198
2026-08-19T04:40:48Z
Deepturquoise
2456
ti enwikt
25198
Scribunto
text/plain
return {
["'Are'are"] = "alu",
["A'ou"] = "aou",
["A-Hmao"] = "hmd",
["A-Pucikwar"] = "apq",
["Aari"] = "aiw",
["Aasax"] = "aas",
["Aba"] = "utp",
["Abaga"] = "abg",
["Abai"] = "poz-abi",
["Abai Sungai"] = "abf",
["Abanyom"] = "abm",
["Abau"] = "aau",
["Abaza"] = "abq",
["Abenaki"] = "abe",
["Abenlen Ayta"] = "abp",
["Abidji"] = "abi",
["Abinomn"] = "bsa",
["Abipón"] = "axb",
["Abishira"] = "ash",
["Abkhaz"] = "ab",
["Abom"] = "aob",
["Abon"] = "abo",
["Aborlan Tagbanwa"] = "tbw",
["Abu"] = "ado",
["Abu'"] = "aah",
["Abua"] = "abn",
["Abui"] = "abz",
["Abun"] = "kgr",
["Abung"] = "abl",
["Abure"] = "abu",
["Abureni"] = "mgj",
["Abé"] = "aba",
["Acatepec Me'phaa"] = "tpx",
["Acehnese"] = "ace",
["Achagua"] = "aca",
["Achang"] = "acn",
["Ache"] = "yif",
["Acheron"] = "acz",
["Achi"] = "acr",
["Acholi"] = "ach",
["Achuar"] = "acu",
["Achumawi"] = "acv",
["Aché"] = "guq",
["Acroá"] = "acs",
["Adai"] = "xad",
["Adamorobe Sign Language"] = "ads",
["Adang"] = "adn",
["Adangbe"] = "adq",
["Adangme"] = "ada",
["Adap"] = "adp",
["Adasen"] = "tiu",
["Adele"] = "ade",
["Adhola"] = "adh",
["Adi"] = "adi",
["Adioukrou"] = "adj",
["Adithinngithigh"] = "dth",
["Adivasi Odia"] = "ort",
["Adiwasi Garasia"] = "gas",
["Adnyamathanha"] = "adt",
["Adonara"] = "adr",
["Aduge"] = "adu",
["Adzera"] = "adz",
["Adûni"] = "art-adu",
["Aeka"] = "aez",
["Aekyom"] = "awi",
["Aequian"] = "xae",
["Aer"] = "aeq",
["Afade"] = "aal",
["Afar"] = "aa",
["Afghan Sign Language"] = "afg",
["Afitti"] = "aft",
["Afra"] = "ulf",
["Afrihili"] = "afh",
["Afrikaans"] = "af",
["Afro-Seminole Creole"] = "afs",
["Agarabi"] = "agd",
["Agatu"] = "agc",
["Agavotaguerra"] = "avo",
["Agawam"] = "alg-aga",
["Aghem"] = "agq",
["Aghu"] = "ahh",
["Aghu Tharrnggala"] = "gtu",
["Aghul"] = "agx",
["Aghwan"] = "xag",
["Agi"] = "aif",
["Agob"] = "kit",
["Agoi"] = "ibm",
["Aguacateca"] = "agu",
["Aguano"] = "aga",
["Aguaruna"] = "agr",
["Aguna"] = "aug",
["Agusan Manobo"] = "msm",
["Agutaynen"] = "agn",
["Agwagwune"] = "yay",
["Ahanta"] = "aha",
["Ahirani"] = "ahr",
["Ahom"] = "aho",
["Ahtna"] = "aht",
["Ahwai"] = "nfd",
["Ai-Cham"] = "aih",
["Aighon"] = "aix",
["Aikanã"] = "tba",
["Aiklep"] = "mwg",
["Aimele"] = "ail",
["Aimol"] = "aim",
["Ainbai"] = "aic",
["Ainu"] = "ain",
["Aiome"] = "aki",
["Airoran"] = "air",
["Aisi"] = "mmq",
["Aiton"] = "aio",
["Aja (East Africa)"] = "aja",
["Aja (West Africa)"] = "ajg",
["Ajawa"] = "ajw",
["Ajië"] = "aji",
["Ak"] = "akq",
["Aka (Central Africa)"] = "axk",
["Aka (Sudan)"] = "soh",
["Aka-Bea"] = "abj",
["Aka-Bo"] = "akm",
["Aka-Cari"] = "aci",
["Aka-Kede"] = "akx",
["Aka-Kol"] = "aky",
["Aka-Kora"] = "ack",
["Akan"] = "ak",
["Akar-Bale"] = "acl",
["Akaselem"] = "aks",
["Akatek"] = "knj",
["Akawaio"] = "ake",
["Ake"] = "aik",
["Akebu"] = "keu",
["Akei"] = "tsr",
["Akeu"] = "aeu",
["Akha"] = "ahk",
["Akhvakh"] = "akv",
["Akkadian"] = "akk",
["Akkala Sami"] = "sia",
["Aklanon"] = "akl",
["Akolet"] = "akt",
["Akoose"] = "bss",
["Akoye"] = "miw",
["Akpa"] = "akf",
["Akpes"] = "ibe",
["Akrukay"] = "afi",
["Akuku"] = "ayk",
["Akum"] = "aku",
["Akuntsu"] = "aqz",
["Akurio"] = "ako",
["Akwa"] = "akw",
["Akyaung Ari"] = "nqy",
["Al-Sayyid Bedouin Sign Language"] = "syy",
["Alaba"] = "alw",
["Alabama"] = "akz",
["Alabat Island Agta"] = "dul",
["Alacatlatzala Mixtec"] = "mim",
["Alago"] = "ala",
["Alagwa"] = "wbj",
["Alak"] = "alk",
["Alamblak"] = "amp",
["Alangan"] = "alj",
["Alanic"] = "xln",
["Alapmunte"] = "apv",
["Alas-Kluet Batak"] = "btz",
["Alawa"] = "alh",
["Alazapa"] = "nai-ala",
["Albanian"] = "sq",
["Albanian Sign Language"] = "sqk",
["Alchuka"] = "tuw-alk",
["Alcozauca Mixtec"] = "xta",
["Alege"] = "alf",
["Alekano"] = "gah",
["Alemannic German"] = "gsw",
["Aleut"] = "ale",
["Algerian Arabic"] = "arq",
["Algerian Jewish Sign Language"] = "ajs",
["Algerian Sign Language"] = "asp",
["Algonquin"] = "alq",
["Ali"] = "aiy",
["Alladian"] = "ald",
["Allar"] = "all",
["Allentiac"] = "sai-all",
["Alngith"] = "aid",
["Alo Phola"] = "ypo",
["Alorese"] = "aol",
["Aloápam Zapotec"] = "zaq",
["Alsea"] = "aes",
["Alu"] = "mte",
["Alu Kurumba"] = "xua",
["Alugu"] = "aub",
["Alumu-Tesu"] = "aab",
["Alune"] = "alp",
["Alungul"] = "aus-alu",
["Aluo"] = "yna",
["Alur"] = "alz",
["Alutiiq"] = "ems",
["Alutor"] = "alr",
["Alviri-Vidari"] = "avd",
["Alyawarr"] = "aly",
["Ama"] = "amm",
["Amahai"] = "amq",
["Amahuaca"] = "amc",
["Amaimon"] = "ali",
["Amal"] = "aad",
["Amanab"] = "amn",
["Amanayé"] = "ama",
["Amara"] = "aie",
["Amarakaeri"] = "amr",
["Amarasi"] = "aaz",
["Amarizana"] = "awd-ama",
["Amasi"] = "alv-ama",
["Amatlán Zapotec"] = "zpo",
["Amba"] = "rwm",
["Ambai"] = "amk",
["Ambakich"] = "aew",
["Ambala Ayta"] = "abc",
["Ambelau"] = "amv",
["Ambele"] = "ael",
["Amblong"] = "alm",
["Ambo"] = "amb",
["Ambonese Malay"] = "abs",
["Ambrak"] = "aag",
["Ambul"] = "apo",
["Ambulas"] = "abt",
["Amdang"] = "amj",
["Amele"] = "aey",
["American Sign Language"] = "ase",
["Amganad Ifugao"] = "ifa",
["Amharic"] = "am",
["Ami"] = "amy",
["Amis"] = "ami",
["Ammonite"] = "sem-amm",
["Amo"] = "amo",
["Amol"] = "alx",
["Amoltepec Mixtec"] = "mbz",
["Amondawa"] = "adw",
["Amorite"] = "sem-amo",
["Ampanang"] = "apg",
["Ampari Dogon"] = "aqd",
["Amri Karbi"] = "ajz",
["Amto"] = "amt",
["Amurdag"] = "amg",
["Ana Tinga Dogon"] = "dti",
["Anaang"] = "anw",
["Anakalangu"] = "akg",
["Anam"] = "pda",
["Anambé"] = "aan",
["Anamgura"] = "imi",
["Anasi"] = "bpo",
["Anauyá"] = "awd-ana",
["Ancient Greek"] = "grc",
["Ancient Ligurian"] = "xlg",
["Ancient Macedonian"] = "xmk",
["Ancient North Arabian"] = "xna",
["Ancient Zapotec"] = "xzp",
["Andai"] = "afd",
["Andajin"] = "ajn",
["Andalusian Arabic"] = "xaa",
["Andaman Creole Hindi"] = "hca",
["Andaqui"] = "ana",
["Andarum"] = "aod",
["Andegerebinha"] = "adg",
["Andh"] = "anr",
["Andi"] = "ani",
["Andio"] = "bzb",
["Andjingith"] = "aus-and",
["Andoa"] = "anb",
["Andoque"] = "ano",
["Andoquero"] = "sai-and",
["Andra-Hus"] = "anx",
["Aneityum"] = "aty",
["Anem"] = "anz",
["Aneme Wake"] = "aby",
["Anfillo"] = "myo",
["Angaataha"] = "agm",
["Angaité"] = "aqt",
["Angal"] = "age",
["Angal Enen"] = "aoe",
["Angal Heneng"] = "akh",
["Angami"] = "njm",
["Angevin"] = "roa-ang",
["Angguruk Yali"] = "yli",
["Angika"] = "anp",
["Angkamuthi"] = "avm",
["Angkola Batak"] = "akb",
["Angkula"] = "aus-ang",
["Angloromani"] = "rme",
["Angolar"] = "aoa",
["Angor"] = "agg",
["Angoram"] = "aog",
["Angosturas Tunebo"] = "tnd",
["Anguthimri"] = "awg",
["Ani Phowa"] = "ypn",
["Anii"] = "blo",
["Animere"] = "anf",
["Anindilyakwa"] = "aoi",
["Anjam"] = "boj",
["Ankave"] = "aak",
["Anmatyerre"] = "amx",
["Annobonese"] = "fab",
["Anong"] = "nun",
["Anor"] = "anj",
["Anserma"] = "ans",
["Ansus"] = "and",
["Antakarinya"] = "ant",
["Antigua and Barbuda Creole English"] = "aig",
["Antillean Creole"] = "gcf",
["Anu"] = "anl",
["Anuak"] = "anu",
["Anufo"] = "cko",
["Anuki"] = "aui",
["Anus"] = "auq",
["Anuta"] = "aud",
["Anyi"] = "any",
["Anyin Morofo"] = "mtb",
["Anāl"] = "anm",
["Aoheng"] = "pni",
["Aore"] = "aor",
["Ap Ma"] = "kbx",
["Apabhramsa"] = "inc-apa",
["Apalachee"] = "xap",
["Apalaí"] = "apy",
["Apali"] = "ena",
["Apasco-Apoala Mixtec"] = "mip",
["Apatani"] = "apt",
["Apiaká"] = "api",
["Apinayé"] = "apn",
["Apma"] = "app",
["Apolista"] = "awd-apo",
["Apro"] = "ahp",
["Apurinã"] = "apu",
["Apurucayali Ashéninka"] = "cpc",
["Aputai"] = "apx",
["Arabana"] = "ard",
["Arabela"] = "arl",
["Arabic"] = "ar",
["Aragonese"] = "an",
["Araki"] = "akr",
["Arakwal"] = "rkw",
["Aralle-Tabulahan"] = "atq",
["Aramaic"] = "arc",
["Arammba"] = "stk",
["Aranadan"] = "aaf",
["Aranama-Tamique"] = "xrt",
["Arandai"] = "jbj",
["Araona"] = "aro",
["Arapaho"] = "arp",
["Arapaso"] = "arj",
["Arara-Karo"] = "arr",
["Ararandewára"] = "xaj",
["Araweté"] = "awt",
["Arawum"] = "awm",
["Arbore"] = "arv",
["Archi"] = "aqc",
["Are"] = "mwc",
["Areba"] = "aea",
["Arem"] = "aem",
["Argentine Sign Language"] = "aed",
["Argobba"] = "agj",
["Arguni"] = "agf",
["Arhuaco"] = "arh",
["Arhâ"] = "aqr",
["Arhö"] = "aok",
["Ari"] = "aac",
["Aribwatsa"] = "laz",
["Aribwaung"] = "ylu",
["Arifama-Miniafia"] = "aai",
["Arigidi"] = "aqg",
["Arikapú"] = "ark",
["Arikara"] = "ari",
["Arikem"] = "ait",
["Arin"] = "xrn",
["Aringa"] = "luc",
["Armazic"] = "xrm",
["Armenian"] = "hy",
["Armenian Sign Language"] = "aen",
["Aromanian"] = "rup",
["Arop-Lokep"] = "apr",
["Arop-Sissano"] = "aps",
["Arosi"] = "aia",
["Arritinngithigh"] = "rrt",
["Arta"] = "atz",
["Arua"] = "aru",
["Aruamu"] = "msy",
["Aruek"] = "aur",
["Aruop"] = "lsr",
["Arutani"] = "atx",
["Aruá"] = "arx",
["Arára (Mato Grosso)"] = "axg",
["Arára (Pará)"] = "aap",
["As"] = "asz",
["Asaba"] = "seo",
["Asaro'o"] = "mtv",
["Ashe"] = "ahs",
["Ashkun"] = "ask",
["Asho Chin"] = "csh",
["Ashokan Prakrit"] = "inc-ash",
["Ashraaf"] = "cus-ash",
["Asháninka"] = "cni",
["Asi"] = "bno",
["Asilulu"] = "asl",
["Askopan"] = "eiv",
["Asoa"] = "asv",
["Assamese"] = "as",
["Assan"] = "xss",
["Assangori"] = "sjg",
["Assiniboine"] = "asb",
["Assyrian Neo-Aramaic"] = "aii",
["Asturian"] = "ast",
["Asu"] = "aum",
["Asue Awyu"] = "psa",
["Asumboa"] = "aua",
["Asunción Mixtepec Zapotec"] = "zoo",
["Asuri"] = "asr",
["Ata"] = "atm",
["Ata Manobo"] = "atd",
["Atakapa"] = "aqp",
["Atampaya"] = "amz",
["Atanques"] = "cba-ata",
["Atatláhuca Mixtec"] = "mib",
["Atauran"] = "adb",
["Atayal"] = "tay",
["Atemble"] = "ate",
["Ateso"] = "teo",
["Athpare"] = "aph",
["Ati"] = "atk",
["Atikamekw"] = "atj",
["Atohwaim"] = "aqm",
["Atong (Cameroon)"] = "ato",
["Atong (India)"] = "aot",
["Atorada"] = "aox",
["Atsahuaca"] = "atc",
["Atsam"] = "cch",
["Atsugewi"] = "atw",
["Attapady Kurumba"] = "pkr",
["Attié"] = "ati",
["Au"] = "avt",
["Auhelawa"] = "kud",
["Aukan"] = "djk",
["Aulua"] = "aul",
["Aurá"] = "aux",
["Aushi"] = "auh",
["Aushiri"] = "avs",
["Auslan"] = "asf",
["Austral"] = "aut",
["Australian Aboriginal Sign Language"] = "asw",
["Australian Kriol"] = "rop",
["Austrian Sign Language"] = "asq",
["Auwe"] = "smf",
["Auyana"] = "auy",
["Auye"] = "auu",
["Auyokawa"] = "auo",
["Avar"] = "av",
["Avatime"] = "avn",
["Avau"] = "avb",
["Avava"] = "tmb",
["Avestan"] = "ae",
["Avikam"] = "avi",
["Avokaya"] = "avu",
["Avá-Canoeiro"] = "avv",
["Awa (China)"] = "vwa",
["Awa (New Guinea)"] = "awb",
["Awa-Cuaiquer"] = "kwi",
["Awabakal"] = "awk",
["Awadhi"] = "awa",
["Awak"] = "awo",
["Awar"] = "aya",
["Awara"] = "awx",
["Awbono"] = "awh",
["Aweer"] = "bob",
["Awera"] = "awr",
["Awetí"] = "awe",
["Awing"] = "azo",
["Awjila"] = "auj",
["Awngi"] = "awn",
["Awngthim"] = "gwm",
["Awtuw"] = "kmn",
["Awun"] = "aww",
["Awutu"] = "afu",
["Awyi"] = "auw",
["Axamb"] = "ahb",
["Axi"] = "yix",
["Ayabadhu"] = "ayd",
["Ayautla Mazatec"] = "vmy",
["Ayere"] = "aye",
["Ayerrerenge"] = "axe",
["Ayi"] = "ayq",
["Ayizi"] = "yyz",
["Ayizo"] = "ayb",
["Aymara"] = "ay",
["Ayomán"] = "sai-ayo",
["Ayoquesco Zapotec"] = "zaf",
["Ayoreo"] = "ayo",
["Ayu"] = "ayu",
["Ayutla Mixtec"] = "miy",
["Azerbaijani"] = "az",
["Azha"] = "aza",
["Azhe"] = "yiz",
["Azoyú Me'phaa"] = "tpc",
["Baa"] = "kwb",
["Baagandji"] = "drl",
["Baan"] = "bvj",
["Baangi"] = "bqx",
["Baatonum"] = "bba",
["Baba"] = "bbw",
["Baba Malay"] = "mbf",
["Babango"] = "bbm",
["Babanki"] = "bbk",
["Babatana"] = "baa",
["Babine-Witsuwit'en"] = "bcr",
["Babole"] = "bvx",
["Babungo"] = "bav",
["Babuza"] = "bzg",
["Bacama"] = "bcy",
["Bacanese Malay"] = "btj",
["Bactrian"] = "xbc",
["Bada"] = "bhz",
["Badaga"] = "bfq",
["Badanchi"] = "bau",
["Bade"] = "bde",
["Badeshi"] = "bdz",
["Badimaya"] = "bia",
["Badjiri"] = "jbi",
["Baduy"] = "bac",
["Badyara"] = "pbp",
["Baeggu"] = "bvd",
["Baekje"] = "pkc",
["Baelelea"] = "bvc",
["Baenan"] = "sai-bae",
["Baetora"] = "btr",
["Bafanji"] = "bfj",
["Bafaw"] = "bwt",
["Bafia"] = "ksf",
["Bafut"] = "bfd",
["Baga Kaloum"] = "bqf",
["Baga Koga"] = "bgo",
["Baga Manduri"] = "bmd",
["Baga Pokur"] = "bcg",
["Baga Sitemu"] = "bsp",
["Baga Sobané"] = "bsv",
["Bagheli"] = "bfy",
["Bagirmi"] = "bmi",
["Bago-Kusuntu"] = "bqg",
["Bagri"] = "bgq",
["Bagua"] = "sai-bag",
["Bagupi"] = "bpi",
["Bagusa"] = "bqb",
["Bagvalal"] = "kva",
["Baha"] = "yha",
["Baham"] = "bdw",
["Bahamian Creole"] = "bah",
["Baharna Arabic"] = "abv",
["Bahau"] = "bhv",
["Bahinemo"] = "bjh",
["Bahing"] = "bhj",
["Bahnar"] = "bdq",
["Bahonsuai"] = "bsu",
["Bai (South Sudan)"] = "bdj",
["Baibai"] = "bbf",
["Baikeno"] = "bkx",
["Bailang"] = "tbq-blg",
["Baima"] = "bqh",
["Baimak"] = "bmx",
["Bainouk Gubeeher"] = "alv-bgu",
["Bainouk-Gunyaamolo"] = "bcz",
["Bainouk-Gunyuño"] = "bab",
["Bainouk-Samik"] = "bcb",
["Baiso"] = "bsw",
["Baissa Fali"] = "fah",
["Bajan"] = "bjs",
["Bajelani"] = "bjm",
["Bajjika"] = "vjk",
["Baka"] = "bkc",
["Bakairí"] = "bkq",
["Bakaka"] = "bqz",
["Bakhtiari"] = "bqi",
["Baki"] = "bki",
["Bakoko"] = "bkh",
["Bakole"] = "kme",
["Bakpinka"] = "bbs",
["Bakulung"] = "bbu",
["Bakumpai"] = "bkr",
["Bakung"] = "xkl",
["Bakwé"] = "bjw",
["Bala"] = "tuw-bal",
["Balaesang"] = "bls",
["Balangao"] = "blw",
["Balangingi"] = "sse",
["Balanta-Ganja"] = "bjt",
["Balanta-Kentohe"] = "ble",
["Balantak"] = "blz",
["Balau"] = "blg",
["Baldemu"] = "bdn",
["Bali"] = "bcp",
["Baliledo"] = "poz-bal",
["Balinese"] = "ban",
["Balinese Malay"] = "mhp",
["Balkan Gagauz Turkish"] = "bgx",
["Balkan Romani"] = "rmn",
["Balo"] = "bqo",
["Baloi"] = "biz",
["Balong"] = "bnt-bal",
["Balti"] = "bft",
["Baltic Romani"] = "rml",
["Baluan-Pam"] = "blq",
["Baluchi"] = "bal",
["Bamako Sign Language"] = "bog",
["Bamali"] = "bbq",
["Bambalang"] = "bmo",
["Bambam"] = "ptu",
["Bambara"] = "bm",
["Bambassi"] = "myf",
["Bambili-Bambui"] = "baw",
["Bamenyam"] = "bce",
["Bamu"] = "bcf",
["Bamukumbit"] = "bqt",
["Bamum"] = "bax",
["Bamunka"] = "bvm",
["Bamwe"] = "bmg",
["Ban Khor Sign Language"] = "bfk",
["Bana"] = "bcw",
["Banao Itneg"] = "bjx",
["Banaro"] = "byz",
["Banda"] = "bnd",
["Banda Malay"] = "bpq",
["Banda-Bambari"] = "liy",
["Banda-Banda"] = "bpd",
["Banda-Mbrès"] = "bqk",
["Banda-Ndélé"] = "bfl",
["Banda-Yangere"] = "yaj",
["Bandi"] = "bza",
["Bandial"] = "bqj",
["Bandjalang"] = "bdy",
["Bangala"] = "bxg",
["Bangandu"] = "bgf",
["Bangba"] = "bbe",
["Banggai"] = "bgz",
["Bangi"] = "bni",
["Bangime"] = "dba",
["Bangka"] = "mfb",
["Bangolan"] = "bgj",
["Bangru"] = "sit-ban",
["Bangubangu"] = "bnx",
["Bangwinji"] = "bsj",
["Baniva"] = "bvv",
["Baniwa"] = "bwi",
["Banjarese"] = "bjn",
["Banka"] = "bxw",
["Bankan Tey Dogon"] = "dbw",
["Bankon"] = "abb",
["Banoni"] = "bcm",
["Bantawa"] = "bap",
["Bantayanon"] = "bfx",
["Bantik"] = "bnq",
["Banyumasan"] = "map-bms",
["Baoule"] = "bci",
["Baraamu"] = "brd",
["Barai"] = "bbb",
["Barakai"] = "baj",
["Baram Kayan"] = "kys",
["Barama"] = "bbg",
["Barambu"] = "brm",
["Baramu"] = "bmz",
["Barapasi"] = "brp",
["Baras"] = "brs",
["Barasana"] = "bsn",
["Barbareño"] = "boi",
["Barclayville Grebo"] = "gry",
["Bardi"] = "bcj",
["Barein"] = "bva",
["Bargam"] = "mlp",
["Bari"] = "bfa",
["Bariai"] = "bch",
["Bariji"] = "bjc",
["Barikanchi"] = "bxo",
["Barikewa"] = "jbk",
["Barngarla"] = "bjb",
["Barok"] = "bjk",
["Barombi"] = "bbi",
["Barranbinya"] = "aus-bra",
["Barro Negro Tunebo"] = "tbn",
["Barrow Point"] = "bpt",
["Baruga"] = "bjz",
["Barunggam"] = "aus-brm",
["Baruya"] = "byr",
["Barwe"] = "bwg",
["Barzani Jewish Neo-Aramaic"] = "bjf",
["Baré"] = "bae",
["Barí"] = "mot",
["Basa"] = "bzw",
["Basa-Gumna"] = "bsl",
["Basa-Gurmana"] = "buj",
["Basaa"] = "bas",
["Basap"] = "bdb",
["Basay"] = "byq",
["Bashkardi"] = "bsg",
["Bashkir"] = "ba",
["Basketo"] = "bst",
["Basque"] = "eu",
["Basque-Icelandic Pidgin"] = "crp-bip",
["Bassa"] = "bsq",
["Bassa-Kontagora"] = "bsr",
["Bassari"] = "bsc",
["Bassossi"] = "bsi",
["Bata"] = "bta",
["Bataan Ayta"] = "ayt",
["Batad Ifugao"] = "ifb",
["Batanga"] = "bnm",
["Batek"] = "btq",
["Bateri"] = "btv",
["Bathari"] = "bhm",
["Bati (Cameroon)"] = "btc",
["Bati (Indonesia)"] = "bvt",
["Bats"] = "bbl",
["Batu"] = "btu",
["Batui"] = "zbt",
["Batuley"] = "bay",
["Bau"] = "bbd",
["Bau Bidayuh"] = "sne",
["Bauchi"] = "bsf",
["Bauni"] = "bpe",
["Baure"] = "brg",
["Bauria"] = "bge",
["Bauro"] = "bxa",
["Bauwaki"] = "bwk",
["Bauzi"] = "bvz",
["Bavarian"] = "bar",
["Bawm Chin"] = "bgr",
["Bay Miwok"] = "mkq",
["Bayali"] = "bjy",
["Baybayanon"] = "bvy",
["Baygo"] = "byg",
["Bayogoula"] = "nai-bay",
["Bayono"] = "byl",
["Bayot"] = "bda",
["Bayungu"] = "bxj",
["Bazigar"] = "bfr",
["Beami"] = "beo",
["Beary"] = "dra-bry",
["Beaver"] = "bea",
["Beba"] = "bfp",
["Bebe"] = "bzv",
["Bebele"] = "beb",
["Bebeli"] = "bek",
["Bebil"] = "bxp",
["Bedik"] = "tnr",
["Bedjond"] = "bjv",
["Bedoanas"] = "bed",
["Beeke"] = "bkf",
["Beele"] = "bxq",
["Beembe"] = "beq",
["Beezen"] = "bnz",
["Befang"] = "bby",
["Begbere-Ejar"] = "bqv",
["Beja"] = "bej",
["Bekati'"] = "bei",
["Bekwarra"] = "bkv",
["Bekwel"] = "bkw",
["Belait"] = "beg",
["Belanda Bor"] = "bxb",
["Belanda Viri"] = "bvi",
["Belarusian"] = "be",
["Belhariya"] = "byw",
["Beli (New Guinea)"] = "bey",
["Beli (South Sudan)"] = "blm",
["Belizean Creole"] = "bzj",
["Bella Coola"] = "blc",
["Bellari"] = "brw",
["Belter Creole"] = "art-bel",
["Bemba"] = "bem",
["Bembe"] = "bmb",
["Ben Tey"] = "dbt",
["Bena"] = "yun",
["Benabena"] = "bef",
["Bench"] = "bcq",
["Bende"] = "bdp",
["Bendi"] = "bct",
["Beneraf"] = "bnv",
["Beng"] = "nhb",
["Benga"] = "bng",
["Bengali"] = "bn",
["Benggoi"] = "bgy",
["Bengkala Sign Language"] = "bqy",
["Bentong"] = "bnu",
["Benyadu'"] = "byd",
["Beothuk"] = "bue",
["Bepour"] = "bie",
["Bera"] = "brf",
["Berakou"] = "bxv",
["Berau Malay"] = "bve",
["Berawan"] = "lod",
["Berbice Creole Dutch"] = "brc",
["Bergish"] = "gmw-bgh",
["Berik"] = "bkl",
["Berinomo"] = "bit",
["Berom"] = "bom",
["Berta"] = "wti",
["Berti"] = "byt",
["Besisi"] = "mhe",
["Besme"] = "bes",
["Besoa"] = "bep",
["Betaf"] = "bfe",
["Betawi"] = "bew",
["Bete"] = "byf",
["Bete-Bendi"] = "btt",
["Betoi"] = "sai-bet",
["Betta Kurumba"] = "xub",
["Bezhta"] = "kap",
["Bhadrawahi"] = "bhd",
["Bhalay"] = "bhx",
["Bharia"] = "bha",
["Bhatri"] = "bgw",
["Bhattiyali"] = "bht",
["Bhaya"] = "bhe",
["Bhele"] = "bhy",
["Bhilali"] = "bhi",
["Bhili"] = "bhb",
["Bhojpuri"] = "bho",
["Bhoti Kinnauri"] = "nes",
["Bhunjia"] = "bhu",
["Biafada"] = "bif",
["Biage"] = "bdf",
["Biak"] = "bhw",
["Biali"] = "beh",
["Bian Marind"] = "bpv",
["Biangai"] = "big",
["Biao"] = "byk",
["Biao Mon"] = "bmt",
["Biao-Jiao Mien"] = "bje",
["Biatah Bidayuh"] = "bth",
["Bibaali"] = "bcn",
["Bibbulman"] = "xbp",
["Bidiyo"] = "bid",
["Bidyara"] = "bym",
["Bidyogo"] = "bjg",
["Biem"] = "bmc",
["Bierebo"] = "bnk",
["Bieria"] = "brj",
["Biete"] = "biu",
["Big Nambas"] = "nmb",
["Biga"] = "bhc",
["Bigambal"] = "xbe",
["Bih"] = "ibh",
["Bihari"] = "bh",
["Bijori"] = "bix",
["Bikya"] = "byb",
["Bila"] = "bip",
["Bilaspuri"] = "kfs",
["Bilba"] = "bpz",
["Bilbil"] = "brz",
["Bile"] = "bil",
["Biliau"] = "bcu",
["Biloxi"] = "bll",
["Bilua"] = "blb",
["Bilur"] = "bxf",
["Bima"] = "bhp",
["Bimin"] = "bhl",
["Bimoba"] = "bim",
["Bina"] = "bmn",
["Binahari"] = "bxz",
["Binandere"] = "bhg",
["Binawa"] = "byj",
["Bindal"] = "xbd",
["Bine"] = "bon",
["Binji"] = "bpj",
["Binongan Itneg"] = "itb",
["Bintauna"] = "bne",
["Bintulu"] = "bny",
["Binukid"] = "bkd",
["Binumarien"] = "bjr",
["Bipi"] = "biq",
["Birao"] = "brr",
["Birgid"] = "brk",
["Birgit"] = "btf",
["Birhor"] = "biy",
["Biri"] = "bzr",
["Biritai"] = "bqq",
["Birri"] = "bvq",
["Birrpayi"] = "xbj",
["Birwa"] = "brl",
["Biseni"] = "ije",
["Bishnupriya Manipuri"] = "bpy",
["Bishuo"] = "bwh",
["Bisis"] = "bnw",
["Bislama"] = "bi",
["Bisorio"] = "bir",
["Bissa"] = "bib",
["Bisu"] = "bzi",
["Bit"] = "bgk",
["Bitare"] = "brt",
["Bitur"] = "mcc",
["Biwat"] = "bwm",
["Biyo"] = "byo",
["Biyom"] = "bpm",
["Blablanga"] = "blp",
["Black Speech"] = "art-bsp",
["Blackfoot"] = "bla",
["Blafe"] = "bfh",
["Blagar"] = "beu",
["Blang"] = "blr",
["Blin"] = "byn",
["Bo"] = "bgl",
["Bo-Rukul"] = "mae",
["Bo-Ung"] = "mux",
["Boano (Maluku)"] = "bzn",
["Boano (Sulawesi)"] = "bzl",
["Bobongko"] = "bgb",
["Bobot"] = "bty",
["Bodo (Central Africa)"] = "boy",
["Bodo (India)"] = "brx",
["Bodo Gadaba"] = "gbj",
["Bodo Parja"] = "bdv",
["Bofi"] = "bff",
["Boga"] = "bvw",
["Bogaya"] = "boq",
["Boghom"] = "bux",
["Boguru"] = "bqu",
["Bohtan Neo-Aramaic"] = "bhn",
["Boikin"] = "bzf",
["Bokar"] = "sit-bok",
["Bokha"] = "ybk",
["Boko"] = "bqc",
["Bokobaru"] = "bus",
["Bokoto"] = "bdt",
["Bokyi"] = "bky",
["Bola"] = "bnp",
["Bolak"] = "art-blk",
["Bolango"] = "bld",
["Bole"] = "bol",
["Bolgo"] = "bvo",
["Bolia"] = "bli",
["Bolinao"] = "smk",
["Bolivian Sign Language"] = "bvl",
["Boloki"] = "bkt",
["Bolon"] = "bof",
["Bolondo"] = "bzm",
["Bolyu"] = "ply",
["Bom"] = "bmf",
["Boma Nkuu"] = "bnt-bon",
["Boma Yumu"] = "bnt-boy",
["Bomboli"] = "bml",
["Bomboma"] = "bws",
["Bomitaba"] = "zmx",
["Bomu"] = "bmq",
["Bomwali"] = "bmw",
["Bon Gula"] = "glc",
["Bonan"] = "peh",
["Bondei"] = "bou",
["Bondo"] = "bfw",
["Bondoukou Kulango"] = "kzc",
["Bondum Dom Dogon"] = "dbu",
["Bonerate"] = "bna",
["Bonggi"] = "bdg",
["Bonggo"] = "bpg",
["Bongili"] = "bui",
["Bongo"] = "bot",
["Bongu"] = "bpu",
["Bonjo"] = "bok",
["Bonkeng"] = "bvg",
["Bonkiman"] = "bop",
["Bookan"] = "bnb",
["Boon"] = "bnl",
["Boor"] = "bvf",
["Bora"] = "boa",
["Border Kuna"] = "kvn",
["Borei"] = "gai",
["Boro"] = "xxb",
["Borong"] = "ksr",
["Boruca"] = "brn",
["Borôro"] = "bor",
["Boselewa"] = "bwf",
["Bosngun"] = "bqs",
["Bote-Majhi"] = "bmj",
["Botlikh"] = "bph",
["Botolan Sambal"] = "sbl",
["Bouna Kulango"] = "nku",
["Bouni"] = "suo",
["Bourbonnais-Berrichon"] = "roa-bbn",
["Bourguignon"] = "roa-brg",
["Bouyei"] = "pcc",
["Bozaba"] = "bzo",
["Bragat"] = "aof",
["Brahui"] = "brh",
["Braj"] = "bra",
["Brazilian Sign Language"] = "bzs",
["Brek Karen"] = "kvl",
["Brem"] = "buq",
["Breri"] = "brq",
["Breton"] = "br",
["Bribri"] = "bzd",
["British Sign Language"] = "bfi",
["Brokkat"] = "bro",
["Brokpake"] = "sgt",
["Brokskat"] = "bkk",
["Brooke's Point Palawano"] = "plw",
["Broome Pearling Lugger Pidgin"] = "bpl",
["Brunei Bisaya"] = "bsb",
["Brunei Malay"] = "kxd",
["Bruny Island"] = "xpz",
["Bu"] = "jid",
["Bu-Nao Bunu"] = "bwx",
["Bua"] = "bub",
["Bualkhaw Chin"] = "cbl",
["Buamu"] = "box",
["Bube"] = "bvb",
["Bubi"] = "buw",
["Bubia"] = "bbx",
["Budeh Stieng"] = "stt",
["Budibud"] = "btp",
["Budong-Budong"] = "bdx",
["Budu"] = "buu",
["Budukh"] = "bdk",
["Buduma"] = "bdm",
["Budza"] = "bja",
["Buena Vista Yokuts"] = "yok-bvy",
["Bugan"] = "bbh",
["Bughotu"] = "bgt",
["Buginese"] = "bug",
["Buglere"] = "sab",
["Bugun"] = "bgg",
["Buhi'non Bikol"] = "ubl",
["Buhid"] = "bku",
["Buhutu"] = "bxh",
["Bujhyal"] = "byh",
["Bukar-Sadung Bidayuh"] = "sdo",
["Bukat"] = "bvk",
["Bukawa"] = "buk",
["Bukhari"] = "bhh",
["Bukit Malay"] = "bvu",
["Bukitan"] = "bkn",
["Bukiyip"] = "ape",
["Buksa"] = "tkb",
["Bukusu"] = "bxk",
["Bulgar"] = "xbo",
["Bulgarian"] = "bg",
["Bulgarian Sign Language"] = "bqn",
["Bulgebi"] = "bmp",
["Buli (Ghana)"] = "bwu",
["Buli (Indonesia)"] = "bzq",
["Bulo Stieng"] = "sti",
["Bulu (Cameroon)"] = "bum",
["Bulu (New Guinea)"] = "bjl",
["Bulungan"] = "blj",
["Bum"] = "bmv",
["Bumaji"] = "byp",
["Bumang"] = "bvp",
["Bumbita Arapesh"] = "aon",
["Bumthangkha"] = "kjz",
["Bun"] = "buv",
["Buna"] = "bvn",
["Bunaba"] = "bck",
["Bunak"] = "bfn",
["Bunama"] = "bdd",
["Bundeli"] = "bns",
["Bung"] = "bqd",
["Bungain"] = "but",
["Bunganditj"] = "xbg",
["Bungku"] = "bkz",
["Bungu"] = "wun",
["Bunoge"] = "dgb",
["Bunun"] = "bnn",
["Buol"] = "blf",
["Bura"] = "bwr",
["Bura Mabang"] = "mde",
["Burak"] = "bys",
["Buraka"] = "bkg",
["Burarra"] = "bvr",
["Burate"] = "bti",
["Burduna"] = "bxn",
["Bure"] = "bvh",
["Burgundian"] = "gme-bur",
["Burji"] = "bji",
["Burmbar"] = "vrt",
["Burmese"] = "my",
["Burmeso"] = "bzu",
["Buru (Indonesia)"] = "mhs",
["Buru (Nigeria)"] = "bqw",
["Burui"] = "bry",
["Burumakok"] = "aip",
["Burun"] = "bdi",
["Burundian Sign Language"] = "lsb",
["Burunge"] = "bds",
["Burushaski"] = "bsk",
["Burusu"] = "bqr",
["Buruwai"] = "asi",
["Buryat"] = "bua",
["Busa"] = "bqp",
["Busam"] = "bxs",
["Busami"] = "bsm",
["Busang Kayan"] = "bfg",
["Bushoong"] = "buf",
["Buso"] = "bso",
["Busoa"] = "bup",
["Bussa"] = "dox",
["Busuu"] = "bju",
["Butbut Kalinga"] = "kyb",
["Butchulla"] = "xby",
["Butmas-Tur"] = "bnr",
["Butuanon"] = "btw",
["Buwal"] = "bhs",
["Buyeo"] = "xpy",
["Buyu"] = "byi",
["Buyuan Jino"] = "jiy",
["Bwa"] = "bww",
["Bwaidoka"] = "bwd",
["Bwala"] = "bnt-bwa",
["Bwanabwana"] = "tte",
["Bwatoo"] = "bwa",
["Bwe Karen"] = "bwe",
["Bwela"] = "bwl",
["Bwile"] = "bwc",
["Bwisi"] = "bwz",
["Byangsi"] = "bee",
["Byep"] = "mkk",
["Bädi Kanum"] = "khd",
["Caac"] = "msq",
["Cabiyarí"] = "cbb",
["Cabre"] = "awd-cab",
["Cabécar"] = "cjp",
["Cacaloxtepec Mixtec"] = "miu",
["Cacaopera"] = "ccr",
["Cacgia Roglai"] = "roc",
["Cacua"] = "cbv",
["Cacán"] = "sai-cac",
["Caddo"] = "cad",
["Cafundó"] = "ccd",
["Cahuarano"] = "cah",
["Cahuilla"] = "chl",
["Caijia"] = "sit-cai",
["Cajonos Zapotec"] = "zad",
["Caka"] = "ckx",
["Cakfem-Mushere"] = "cky",
["Calabrian Greek"] = "grk-cal",
["Calamian Tagbanwa"] = "tbk",
["Calusa"] = "nai-cal",
["Caluyanun"] = "clu",
["Caló"] = "rmq",
["Camarines Norte Agta"] = "abd",
["Cambodian Sign Language"] = "csx",
["Cameroon Mambila"] = "mcu",
["Cameroon Pidgin"] = "wes",
["Campalagian"] = "cml",
["Camsá"] = "kbh",
["Camtho"] = "cmt",
["Camunic"] = "xcc",
["Candoshi-Shapra"] = "cbu",
["Canela"] = "ram",
["Canichana"] = "caz",
["Cantabrian"] = "roa-can",
["Cantonese"] = "yue",
["Cao Miao"] = "cov",
["Caolan"] = "mlc",
["Capanahua"] = "kaq",
["Capiznon"] = "cps",
["Cappadocian Greek"] = "cpg",
["Caquinte"] = "cot",
["Car Nicobarese"] = "caq",
["Cara"] = "cfd",
["Carabayo"] = "cby",
["Caramanta"] = "crf",
["Caranqui"] = "sai-caq",
["Carapana"] = "cbc",
["Carian"] = "xcr",
["Cariay"] = "awd-kar",
["Caribbean Hindustani"] = "hns",
["Caribbean Javanese"] = "jvn",
["Carijona"] = "cbd",
["Carolina Algonquian"] = "crr",
["Carolinian"] = "cal",
["Carpathian Romani"] = "rmc",
["Carpathian Rusyn"] = "rue",
["Carrier"] = "crx",
["Cashibo-Cacataibo"] = "cbr",
["Cashinahua"] = "cbs",
["Casiguran Dumagat Agta"] = "dgc",
["Casuarina Coast Asmat"] = "asc",
["Catacao"] = "sai-cat",
["Catalan"] = "ca",
["Catalan Sign Language"] = "csc",
["Catawba"] = "chc",
["Catuquinaru"] = "sai-ctq",
["Catío Chibcha"] = "cba-cat",
["Cavineña"] = "cav",
["Cayubaba"] = "cyb",
["Cayuga"] = "cay",
["Cayuse"] = "xcy",
["Cazcan"] = "azc-caz",
["Cañari"] = "sai-cnr",
["Cebaara"] = "sef",
["Cebuano"] = "ceb",
["Celtiberian"] = "xce",
["Cen"] = "cen",
["Central Asmat"] = "cns",
["Central Atlas Tamazight"] = "tzm",
["Central Awyu"] = "awu",
["Central Bai"] = "bca",
["Central Bikol"] = "bcl",
["Central Bontoc"] = "lbk",
["Central Cagayan Agta"] = "agt",
["Central Dusun"] = "dtp",
["Central Franconian"] = "gmw-cfr",
["Central Grebo"] = "grv",
["Central Huasteca Nahuatl"] = "nch",
["Central Huishui Hmong"] = "hmc",
["Central Kurdish"] = "ckb",
["Central Mahuatlán Zapotec"] = "zam",
["Central Malay"] = "pse",
["Central Mansi"] = "mns-cen",
["Central Masela"] = "mxz",
["Central Mashan Hmong"] = "hmm",
["Central Mazahua"] = "maz",
["Central Melanau"] = "mel",
["Central Min"] = "czo",
["Central Mnong"] = "cmo",
["Central Nahuatl"] = "nhn",
["Central Nicobarese"] = "ncb",
["Central Ojibwa"] = "ojc",
["Central Palawano"] = "plc",
["Central Pame"] = "pbs",
["Central Pomo"] = "poo",
["Central Puebla Nahuatl"] = "ncx",
["Central Sama"] = "sml",
["Central Siberian Yupik"] = "ess",
["Central Sierra Miwok"] = "csm",
["Central Subanen"] = "syb",
["Central Tagbanwa"] = "tgt",
["Central Tarahumara"] = "tar",
["Central Teke"] = "nzu",
["Central Tunebo"] = "tuf",
["Centúúm"] = "cet",
["Cerma"] = "cme",
["Ch'olti'"] = "myn-chl",
["Ch'orti'"] = "caa",
["Chaap Wuurong"] = "tjw",
["Chachi"] = "cbi",
["Chadian Arabic"] = "shu",
["Chadian Sign Language"] = "cds",
["Chadong"] = "cdy",
["Chagatai"] = "chg",
["Chaha"] = "sem-cha",
["Chaima"] = "ciy",
["Chairel"] = "sit-cha",
["Chak"] = "ckh",
["Chakali"] = "cli",
["Chakma"] = "ccp",
["Chala"] = "cll",
["Chaldean Neo-Aramaic"] = "cld",
["Chali"] = "tgf",
["Chamacoco"] = "ceg",
["Chamalal"] = "cji",
["Chamba Daka"] = "ccg",
["Chamba Leko"] = "ndi",
["Chambeali"] = "cdh",
["Chambri"] = "can",
["Chamicuro"] = "ccc",
["Chamling"] = "rab",
["Chamorro"] = "ch",
["Champenois"] = "roa-cha",
["Chang"] = "nbc",
["Changriwa"] = "cga",
["Changthang"] = "cna",
["Chantyal"] = "chx",
["Chaná"] = "sai-chn",
["Chané"] = "caj",
["Chapacura"] = "sai-chp",
["Chara"] = "cra",
["Charrua"] = "sai-chr",
["Chaudangsi"] = "cdn",
["Chaura"] = "crv",
["Chavacano"] = "cbk",
["Chayahuita"] = "cbt",
["Chayuco Mixtec"] = "mih",
["Chazumba Mixtec"] = "xtb",
["Che"] = "ruk",
["Chechen"] = "ce",
["Cheke Holo"] = "mrn",
["Chemakum"] = "xch",
["Chenapian"] = "cjn",
["Chenchu"] = "cde",
["Chenoua"] = "cnu",
["Chepang"] = "cdm",
["Chepya"] = "ycp",
["Cherepon"] = "cpn",
["Cherokee"] = "chr",
["Chesu"] = "ych",
["Chetco-Tolowa"] = "ctc",
["Chewong"] = "cwg",
["Cheyenne"] = "chy",
["Chhattisgarhi"] = "hne",
["Chhintange"] = "ctn",
["Chhulung"] = "cur",
["Chiangmai Sign Language"] = "csd",
["Chiapanec"] = "cip",
["Chibcha"] = "chb",
["Chicahuaxtla Triqui"] = "trs",
["Chichewa"] = "ny",
["Chichicapan Zapotec"] = "zpv",
["Chichimeca-Jonaz"] = "pei",
["Chichonyi-Chidzihana-Chikauma"] = "coh",
["Chickasaw"] = "cic",
["Chicomuceltec"] = "cob",
["Chiduruma"] = "dug",
["Chigmecatitlán Mixtec"] = "mii",
["Chilcotin"] = "clc",
["Chilean Sign Language"] = "csg",
["Chilisso"] = "clh",
["Chiltepec Chinantec"] = "csa",
["Chimalapa Zoque"] = "zoh",
["Chimariko"] = "cid",
["Chimila"] = "cbg",
["Chimwiini"] = "bnt-cmw",
["Chinali"] = "cih",
["Chinbon Chin"] = "cnb",
["Chinese"] = "zh",
["Chinese Pidgin English"] = "cpi",
["Chinese Pidgin Russian"] = "crp-cpr",
["Chinese Sign Language"] = "csl",
["Chinook"] = "chh",
["Chinook Jargon"] = "chn",
["Chipaya"] = "cap",
["Chipewyan"] = "chp",
["Chiquihuitlán Mazatec"] = "maq",
["Chiquimulilla"] = "nai-chi",
["Chiquitano"] = "cax",
["Chiricahua"] = "apm",
["Chirino"] = "sai-chi",
["Chiripá"] = "nhd",
["Chiru"] = "cdf",
["Chitimacha"] = "ctm",
["Chitkuli Kinnauri"] = "cik",
["Chittagonian"] = "ctg",
["Chitwania Tharu"] = "the",
["Chiwere"] = "iow",
["Choapan Zapotec"] = "zpc",
["Chocangaca"] = "cgk",
["Chochotec"] = "coz",
["Choctaw"] = "cho",
["Chodri"] = "cdi",
["Chokri Naga"] = "nri",
["Chokwe"] = "cjk",
["Chol"] = "ctu",
["Cholón"] = "cht",
["Chong"] = "cog",
["Choni"] = "cda",
["Chono"] = "sai-cno",
["Chontal Maya"] = "chf",
["Chopi"] = "cce",
["Chothe Naga"] = "nct",
["Chrau"] = "crw",
["Chru"] = "cje",
["Chuabo"] = "chw",
["Chuanqiandian Cluster Miao"] = "cqd",
["Chuave"] = "cjv",
["Chug"] = "cvg",
["Chuj"] = "cac",
["Chuka"] = "cuh",
["Chukchi"] = "ckt",
["Chukwa"] = "cuw",
["Chulym"] = "clw",
["Chumburung"] = "ncu",
["Chungli Ao"] = "njo-jgl",
["Churahi"] = "cdj",
["Church Slavonic"] = "zls-chs",
["Churuya"] = "sai-chu",
["Chut"] = "scb",
["Chuukese"] = "chk",
["Chuvan"] = "xcv",
["Chuvash"] = "cv",
["Chácobo"] = "cao",
["Ci Gbe"] = "cib",
["Cia-Cia"] = "cia",
["Cibak"] = "ckl",
["Cicipu"] = "awc",
["Ciguayo"] = "nai-cig",
["Cimbrian"] = "cim",
["Cinamiguin Manobo"] = "mkx",
["Cinda-Regi-Tiyal"] = "cdr",
["Cineni"] = "cie",
["Cinta Larga"] = "cin",
["Cishingini"] = "asg",
["Citak"] = "txt",
["Ciwogai"] = "tgd",
["Classical Chinese"] = "lzh",
["Classical Gaelic"] = "ghc",
["Classical Guarani"] = "gn-cls",
["Classical Mandaic"] = "myz",
["Classical Mongolian"] = "cmg",
["Classical Nahuatl"] = "nci",
["Classical Newar"] = "nwc",
["Classical Quechua"] = "qwc",
["Classical Syriac"] = "syc",
["Classical Tibetan"] = "xct",
["Coahuilteco"] = "xcw",
["Coast Miwok"] = "csi",
["Coastal Kadazan"] = "kzj",
["Coastal Konjo"] = "kjc",
["Coatecas Altas Zapotec"] = "zca",
["Coatepec Nahuatl"] = "naz",
["Coatlán Mixe"] = "mco",
["Coatlán Zapotec"] = "zps",
["Coatzospan Mixtec"] = "miz",
["Cocama"] = "cod",
["Cochimi"] = "coj",
["Cocopa"] = "coc",
["Cocos Islands Malay"] = "coa",
["Coeruna"] = "sai-coe",
["Coeur d'Alene"] = "crd",
["Cofán"] = "con",
["Cogui"] = "kog",
["Col"] = "liw",
["Colombian Sign Language"] = "csn",
["Colonia Tovar German"] = "gct",
["Columbia-Wenatchi"] = "col",
["Colán"] = "sai-col",
["Comaltepec Chinantec"] = "cco",
["Comanche"] = "com",
["Comechingon"] = "sai-cmg",
["Comecrudo"] = "xcm",
["Communicationssprache"] = "art-com",
["Como Karim"] = "cfg",
["Comox"] = "coo",
["Con"] = "cno",
["Coos"] = "csz",
["Copainalá Zoque"] = "zoc",
["Copala Triqui"] = "trc",
["Copallén"] = "sai-cop",
["Coptic"] = "cop",
["Coquille"] = "coq",
["Cora"] = "crn",
["Cori"] = "cry",
["Cornish"] = "kw",
["Coroado Puri"] = "sai-crd",
["Corsican"] = "co",
["Cosoleacaque Nahuatl"] = "nhk",
["Costa Rican Sign Language"] = "csr",
["Cotabato Manobo"] = "mta",
["Cotoname"] = "xcn",
["Cowlitz"] = "cow",
["Coyaima"] = "coy",
["Coyotepec Popoloca"] = "pbf",
["Coyutla Totonac"] = "toc",
["Cree"] = "cr",
["Creek"] = "mus",
["Crimean Gothic"] = "gme-cgo",
["Crimean Tatar"] = "crh",
["Croatian Sign Language"] = "csq",
["Cross River Mbembe"] = "mfn",
["Crow"] = "cro",
["Cruzeño"] = "crz",
["Cua"] = "cua",
["Cuban Sign Language"] = "csf",
["Cubeo"] = "cub",
["Cueva"] = "sai-cva",
["Cuiba"] = "cui",
["Cuitlatec"] = "cuy",
["Culina"] = "cul",
["Culli"] = "sai-cul",
["Cumanagoto"] = "cuo",
["Cumbric"] = "xcb",
["Cun"] = "cuq",
["Cung"] = "cug",
["Cupeño"] = "cup",
["Curonian"] = "xcu",
["Curripaco"] = "kpc",
["Cutchi-Swahili"] = "ccl",
["Cuvok"] = "cuv",
["Cuyamecalco Mixtec"] = "xtu",
["Cuyunon"] = "cyo",
["Cwi Bwamu"] = "bwy",
["Cypriot Arabic"] = "acy",
["Czech"] = "cs",
["Czech Sign Language"] = "cse",
["Cèmuhî"] = "cam",
["Cốông"] = "cnc",
["Da'a Kaili"] = "kzf",
["Daai Chin"] = "dao",
["Daakaka"] = "bpa",
["Daantanai'"] = "lni",
["Daasanach"] = "dsh",
["Daba"] = "dbq",
["Dabarre"] = "dbr",
["Dabe"] = "dbe",
["Dacian"] = "xdc",
["Dadanitic"] = "sem-dad",
["Dadi Dadi"] = "dda",
["Dadibi"] = "mps",
["Dadiya"] = "dbd",
["Daga"] = "dgz",
["Dagaari Dioula"] = "dgd",
["Dagba"] = "dgk",
["Dagbani"] = "dag",
["Dagik"] = "dec",
["Dagoman"] = "dgn",
["Dahalik"] = "dlk",
["Dahalo"] = "dal",
["Daho-Doo"] = "das",
["Dai"] = "dij",
["Dair"] = "drb",
["Dairi Batak"] = "btd",
["Dakka"] = "dkk",
["Dakota"] = "dak",
["Dakpa"] = "dka",
["Dalmatian"] = "dlm",
["Daloa Bété"] = "bev",
["Dama (Nigeria)"] = "dmm",
["Dama (Sierra Leone)"] = "dmn-dam",
["Damakawa"] = "dam",
["Damal"] = "uhn",
["Dambi"] = "dac",
["Dameli"] = "dml",
["Dampelas"] = "dms",
["Dan"] = "dnj",
["Danaru"] = "dnr",
["Danau"] = "dnu",
["Dandami Maria"] = "daq",
["Dangaléat"] = "daa",
["Dangaura Tharu"] = "thl",
["Danish"] = "da",
["Danish Sign Language"] = "dsl",
["Dano"] = "aso",
["Danu"] = "dnv",
["Danuwar"] = "dhw",
["Dao"] = "daz",
["Daonda"] = "dnd",
["Dar Daju Daju"] = "djc",
["Dar Fur Daju"] = "daj",
["Dar Sila Daju"] = "dau",
["Darai"] = "dry",
["Dargwa"] = "dar",
["Darkinjung"] = "xda",
["Darlong"] = "dln",
["Darmiya"] = "drd",
["Daro-Matu Melanau"] = "dro",
["Darumbal"] = "xgm",
["Dass"] = "dot",
["Datian Min"] = "nan-dat",
["Datooga"] = "tcc",
["Daungwurrung"] = "dgw",
["Daur"] = "dta",
["Davawenyo"] = "daw",
["Dawawa"] = "dww",
["Dawera-Daweloor"] = "ddw",
["Dawro"] = "dwr",
["Day"] = "dai",
["Dayi"] = "dax",
["Dazaga"] = "dzg",
["Deccani"] = "dcc",
["Dedua"] = "ded",
["Defaka"] = "afn",
["Defi Gbe"] = "gbh",
["Deg"] = "mzw",
["Deg Xinag"] = "ing",
["Degema"] = "deg",
["Degenan"] = "dge",
["Dehwari"] = "deh",
["Dela-Oenale"] = "row",
["Delo"] = "ntr",
["Delta Yokuts"] = "yok-dly",
["Dem"] = "dem",
["Dema"] = "dmx",
["Demisa"] = "dei",
["Demotic Egyptian"] = "egx-dem",
["Demta"] = "dmy",
["Dena'ina"] = "tfn",
["Dendi"] = "ddn",
["Dengese"] = "dez",
["Dengka"] = "dnk",
["Deno"] = "dbb",
["Denya"] = "anv",
["Dení"] = "dny",
["Deori"] = "der",
["Desano"] = "des",
["Desiya"] = "dso",
["Dewas Rai"] = "dwz",
["Dewoin"] = "dee",
["Dezfuli"] = "def",
["Dghwede"] = "dgh",
["Dhaiso"] = "dhs",
["Dhalandji"] = "dhl",
["Dhangu"] = "dhg",
["Dhanki"] = "dhn",
["Dhao"] = "nfa",
["Dharug"] = "xdk",
["Dhatki"] = "mki",
["Dhimal"] = "dhi",
["Dhivehi"] = "dv",
["Dhodia"] = "dho",
["Dhofari Arabic"] = "adf",
["Dhudhuroa"] = "ddr",
["Dhundhari"] = "dhd",
["Dhungaloo"] = "dhx",
["Dhurga"] = "dhu",
["Dhuwal"] = "dwu",
["Dhuwaya"] = "dwy",
["Dia"] = "dia",
["Dibabawon Manobo"] = "mbd",
["Dibiyaso"] = "dby",
["Dibo"] = "dio",
["Dicamay Agta"] = "duy",
["Didinga"] = "did",
["Dieri"] = "dif",
["Digo"] = "dig",
["Dii"] = "dur",
["Dijim-Bwilim"] = "cfa",
["Dilling"] = "dil",
["Dima"] = "jma",
["Dimasa"] = "dis",
["Dimbong"] = "dii",
["Dime"] = "dim",
["Dinapigue Agta"] = "phi-din",
["Dineor"] = "mrx",
["Ding"] = "diz",
["Dinka"] = "din",
["Diodio"] = "ddi",
["Dirasha"] = "gdl",
["Diri"] = "dwa",
["Dirim"] = "dir",
["Disa"] = "dsi",
["Ditammari"] = "tbz",
["Ditidaht"] = "dtd",
["Diuwe"] = "diy",
["Diuxi-Tilantongo Mixtec"] = "xtd",
["Dixon Reef"] = "dix",
["Dizin"] = "mdx",
["Djadjawurrung"] = "dja",
["Djambarrpuyngu"] = "djr",
["Djangun"] = "djf",
["Djauan"] = "djn",
["Djawi"] = "djw",
["Djimini"] = "dyi",
["Djinang"] = "dji",
["Djinba"] = "djb",
["Djiwarli"] = "djl",
["Dobel"] = "kvo",
["Dobu"] = "dob",
["Doe"] = "doe",
["Doga"] = "dgg",
["Doghoro"] = "dgx",
["Dogoso"] = "dgs",
["Dogosé"] = "dos",
["Dogri"] = "doi",
["Dogrib"] = "dgr",
["Dogul Dom"] = "dbg",
["Doka"] = "dbi",
["Doko-Uyanga"] = "uya",
["Dolgan"] = "dlg",
["Dom"] = "doa",
["Domaaki"] = "dmk",
["Domari"] = "rmt",
["Dominican Sign Language"] = "doq",
["Dompo"] = "doy",
["Domu"] = "dof",
["Domung"] = "dev",
["Dondo"] = "dok",
["Dong"] = "doh",
["Dongo"] = "doo",
["Dongolawi"] = "kzh",
["Dongotono"] = "ddd",
["Dongshanba Lalo"] = "yik",
["Dongxiang"] = "sce",
["Donno So Dogon"] = "dds",
["Doondo"] = "dde",
["Dorasque"] = "cba-dor",
["Dori'o"] = "dor",
["Dorig"] = "wwo",
["Doromu-Koki"] = "kqc",
["Dorze"] = "doz",
["Doso"] = "dol",
["Doteli"] = "dty",
["Dothraki"] = "art-dtk",
["Doura"] = "don",
["Doutai"] = "tds",
["Doyayo"] = "dow",
["Drehu"] = "dhv",
["Drung"] = "duu",
["Duala"] = "dua",
["Duano"] = "dup",
["Duau"] = "dva",
["Dubli"] = "dub",
["Dubu"] = "dmu",
["Dugun"] = "ndu",
["Duguri"] = "dbm",
["Dugwor"] = "dme",
["Duhwa"] = "kbz",
["Duit"] = "cba-dui",
["Duke"] = "nke",
["Dukhan"] = "trk-dkh",
["Dulbu"] = "dbo",
["Duli"] = "duz",
["Duma"] = "dma",
["Dumaitic"] = "sem-dum",
["Dumbea"] = "duf",
["Dumi"] = "dus",
["Dumpas"] = "dmv",
["Dumun"] = "dui",
["Duna"] = "duc",
["Dungan"] = "dng",
["Dungmali"] = "raa",
["Dungra Bhil"] = "duh",
["Dungu"] = "dbv",
["Dupaningan Agta"] = "duo",
["Dura"] = "drq",
["Duri"] = "mvp",
["Duriankere"] = "dbn",
["Duruwa"] = "pci",
["Dusner"] = "dsn",
["Dusun Deyah"] = "dun",
["Dusun Malang"] = "duq",
["Dusun Witu"] = "duw",
["Dutch"] = "nl",
["Dutch Sign Language"] = "dse",
["Duun"] = "dux",
["Duupa"] = "dae",
["Duvle"] = "duv",
["Duwai"] = "dbp",
["Duwet"] = "gve",
["Dwang"] = "nnu",
["Dyaabugay"] = "dyy",
["Dyaberdyaber"] = "dyb",
["Dyan"] = "dya",
["Dyangadi"] = "dyn",
["Dyirbal"] = "dbl",
["Dyugun"] = "dyd",
["Dyula"] = "dyu",
["Dza"] = "jen",
["Dzala"] = "dzl",
["Dzando"] = "dzn",
["Dzao Min"] = "bpn",
["Dzodinka"] = "add",
["Dzongkha"] = "dz",
["Dzuun"] = "dnn",
["Dâw"] = "kwa",
["E"] = "eee",
["E'ma Buyang"] = "yzg",
["Early Assamese"] = "inc-oas",
["Early Modern Korean"] = "ko-ear",
["Early Old Oghuz"] = "trk-eog",
["Early Tripuri"] = "xtr",
["East Central German"] = "gmw-ecg",
["East Circassian"] = "kbd",
["East Damar"] = "dmr",
["East Franconian"] = "vmf",
["East Futuna"] = "fud",
["East Kewa"] = "kjs",
["East Limba"] = "lma",
["East Masela"] = "vme",
["East Miraya Bikol"] = "rbl",
["East Nyala"] = "nle",
["East Tarangan"] = "tre",
["East Yugur"] = "yuy",
["Eastern Acipa"] = "acp",
["Eastern Arrernte"] = "aer",
["Eastern Bolivian Guarani"] = "gui",
["Eastern Bontoc"] = "ebk",
["Eastern Bru"] = "bru",
["Eastern Canadian Inuktitut"] = "ike",
["Eastern Cham"] = "cjm",
["Eastern Durango Nahuatl"] = "azd",
["Eastern Gorkha Tamang"] = "tge",
["Eastern Highland Chatino"] = "cly",
["Eastern Highland Otomi"] = "otm",
["Eastern Huasteca Nahuatl"] = "nhe",
["Eastern Huishui Hmong"] = "hme",
["Eastern Karaboro"] = "xrb",
["Eastern Katu"] = "ktv",
["Eastern Kayah"] = "eky",
["Eastern Keres"] = "kee",
["Eastern Khanty"] = "kca-eas",
["Eastern Krahn"] = "kqo",
["Eastern Lalu"] = "yit",
["Eastern Lawa"] = "lwl",
["Eastern Magar"] = "mgp",
["Eastern Maninkakan"] = "emk",
["Eastern Mari"] = "mhr",
["Eastern Meohang"] = "emg",
["Eastern Min"] = "cdo",
["Eastern Mnong"] = "mng",
["Eastern Muria"] = "emu",
["Eastern Ngad'a"] = "nea",
["Eastern Nisu"] = "nos",
["Eastern Ojibwa"] = "ojg",
["Eastern Parbate Kham"] = "kif",
["Eastern Penan"] = "pez",
["Eastern Pomo"] = "peb",
["Eastern Pwo"] = "kjp",
["Eastern Qiandong Miao"] = "hmq",
["Eastern Subanun"] = "sfe",
["Eastern Tamang"] = "taj",
["Eastern Tawbuid"] = "bnj",
["Eastern Xiangxi Miao"] = "muq",
["Eastern Xwla Gbe"] = "gbx",
["Ebira"] = "igb",
["Eblaite"] = "xeb",
["Ebrié"] = "ebr",
["Ebughu"] = "ebg",
["Ecuadorian Sign Language"] = "ecs",
["Ede Cabe"] = "cbj",
["Ede Ica"] = "ica",
["Ede Idaca"] = "idd",
["Ede Ije"] = "ijj",
["Ede Nago"] = "nqg",
["Edera Awyu"] = "awy",
["Edo"] = "bin",
["Edolo"] = "etr",
["Edomite"] = "xdm",
["Edopi"] = "dbf",
["Efai"] = "efa",
["Efe"] = "efe",
["Efik"] = "efi",
["Efutop"] = "ofu",
["Ega"] = "ega",
["Eggon"] = "ego",
["Egyptian"] = "egy",
["Egyptian Arabic"] = "arz",
["Egyptian Sign Language"] = "esl",
["Ehueun"] = "ehu",
["Eipomek"] = "eip",
["Eitiep"] = "eit",
["Ejagham"] = "etu",
["Ejamat"] = "eja",
["Ekajuk"] = "eka",
["Ekari"] = "ekg",
["Ekele"] = "khy",
["Eki"] = "eki",
["Ekit"] = "eke",
["Ekpeye"] = "ekp",
["El Alto Zapotec"] = "zpp",
["El Hugeirat"] = "elh",
["El Molo"] = "elo",
["Elamite"] = "elx",
["Eleme"] = "elm",
["Elepi"] = "ele",
["Elfdalian"] = "ovd",
["Elip"] = "ekm",
["Elkei"] = "elk",
["Eloi"] = "art-elo",
["Elotepec Zapotec"] = "zte",
["Eloyi"] = "afo",
["Elseng"] = "mrf",
["Elu"] = "elu",
["Elymian"] = "xly",
["Emae"] = "mmw",
["Emai"] = "ema",
["Eman"] = "emn",
["Embaloh"] = "emb",
["Emberá-Baudó"] = "bdc",
["Emberá-Catío"] = "cto",
["Emberá-Chamí"] = "cmi",
["Emberá-Tadó"] = "tdc",
["Embu"] = "ebu",
["Emem"] = "enr",
["Emerillon"] = "eme",
["Emilian"] = "egl",
["Emplawas"] = "emw",
["En"] = "enc",
["Enawené-Nawé"] = "unk",
["Ende"] = "end",
["Enga"] = "enq",
["Engenni"] = "enn",
["Enggano"] = "eno",
["English"] = "en",
["Enlhet"] = "enl",
["Enrekang"] = "ptt",
["Enu"] = "enu",
["Enwan"] = "env",
["Enwang"] = "enw",
["Enxet"] = "enx",
["Enya"] = "gey",
["Eotile"] = "eot",
["Epena"] = "sja",
["Epi-Olmec"] = "xep",
["Epie"] = "epi",
["Epigraphic Mayan"] = "emy",
["Eravallan"] = "era",
["Erave"] = "kjy",
["Ere"] = "twp",
["Erie"] = "iro-ere",
["Eritai"] = "ert",
["Erokwanas"] = "erw",
["Erre"] = "err",
["Erromintxela"] = "emx",
["Ersu"] = "ers",
["Eruwa"] = "erh",
["Erzya"] = "myv",
["Esan"] = "ish",
["Ese"] = "mcq",
["Ese Ejja"] = "ese",
["Eshtehardi"] = "esh",
["Esimbi"] = "ags",
["Eskayan"] = "esy",
["Esmeralda"] = "sai-esm",
["Esperanto"] = "eo",
["Esselen"] = "esq",
["Estado de México Otomi"] = "ots",
["Estonian"] = "et",
["Estonian Sign Language"] = "eso",
["Esuma"] = "esm",
["Etchemin"] = "etc",
["Etebi"] = "etb",
["Eten"] = "etx",
["Eteocretan"] = "ecr",
["Eteocypriot"] = "ecy",
["Ethiopian Sign Language"] = "eth",
["Etkywan"] = "ich",
["Eton (Cameroon)"] = "eto",
["Eton (Vanuatu)"] = "etn",
["Etruscan"] = "ett",
["Etulo"] = "utr",
["Evant"] = "bzz",
["Even"] = "eve",
["Evenki"] = "evn",
["Ewage-Notu"] = "nou",
["Ewarhuyana"] = "sai-ewa",
["Ewe"] = "ee",
["Ewondo"] = "ewo",
["Extremaduran"] = "ext",
["Eyak"] = "eya",
["Ezaa"] = "eza",
["Fagani"] = "faf",
["Faifi"] = "fif",
["Faire Atta"] = "azt",
["Faiwol"] = "fai",
["Fakkanci"] = "gel",
["Fala"] = "fax",
["Falam Chin"] = "cfm",
["Fali"] = "fli",
["Faliscan"] = "xfa",
["Fam"] = "fam",
["Fanagalo"] = "fng",
["Fanamaket"] = "bjp",
["Fang (Bantu)"] = "fan",
["Fang (Beboid)"] = "fak",
["Fania"] = "fni",
["Far Western Muria"] = "fmu",
["Farefare"] = "gur",
["Faroese"] = "fo",
["Fas"] = "fqs",
["Fasu"] = "faa",
["Fataleka"] = "far",
["Fataluku"] = "ddg",
["Fayu"] = "fau",
["Fe'fe'"] = "fmp",
["Fedan"] = "pdn",
["Fembe"] = "agl",
["Fer"] = "kah",
["Feroge"] = "fer",
["Fiji Hindi"] = "hif",
["Fijian"] = "fj",
["Filomena Mata-Coahuitlán Totonac"] = "tlp",
["Fingallian"] = "gmw-fin",
["Finnish"] = "fi",
["Finnish Sign Language"] = "fse",
["Finnish-Swedish Sign Language"] = "fss",
["Finongan"] = "fag",
["Fipa"] = "fip",
["Firan"] = "fir",
["Fiwaga"] = "fiw",
["Flemish Sign Language"] = "vgt",
["Flinders Island"] = "fln",
["Foau"] = "flh",
["Fogaha"] = "ber-fog",
["Foi"] = "foi",
["Foia Foia"] = "ffi",
["Folopa"] = "ppo",
["Foma"] = "fom",
["Fon"] = "fon",
["Fongoro"] = "fgr",
["Foodo"] = "fod",
["Forak"] = "frq",
["Fordata"] = "frd",
["Fore"] = "for",
["Forest Enets"] = "enf",
["Forest Nenets"] = "yrk-for",
["Fortsenal"] = "frt",
["Fox"] = "sac",
["Franc-Comtois"] = "roa-fcm",
["Francisco León Zoque"] = "zos",
["Franco-Provençal"] = "frp",
["French"] = "fr",
["French Belgian Sign Language"] = "sfb",
["French Sign Language"] = "fsl",
["Friulian"] = "fur",
["Fula"] = "ff",
["Fuliiru"] = "flr",
["Fulniô"] = "fun",
["Fum"] = "fum",
["Fungwa"] = "ula",
["Fur"] = "fvr",
["Furu"] = "fuu",
["Futuna-Aniwa"] = "fut",
["Fuyug"] = "fuy",
["Fwe"] = "fwe",
["Fwâi"] = "fwa",
["Fyam"] = "pym",
["Fyer"] = "fie",
["Ga"] = "gaa",
["Ga'anda"] = "gqa",
["Ga'dang"] = "gdg",
["Gaa"] = "ttb",
["Gaam"] = "tbi",
["Gabadi"] = "kbt",
["Gabi"] = "gbw",
["Gabri"] = "gab",
["Gabrielino-Fernandeño"] = "xgf",
["Gadang"] = "gdk",
["Gaddang"] = "gad",
["Gaddi"] = "gbk",
["Gade"] = "ged",
["Gadjerawang"] = "gdh",
["Gadsup"] = "gaj",
["Gafat"] = "gft",
["Gagadu"] = "gbu",
["Gagauz"] = "gag",
["Gagnoa Bété"] = "btg",
["Gahri"] = "bfu",
["Gaikundi"] = "gbf",
["Gaina"] = "gcn",
["Gal"] = "gap",
["Galambu"] = "glo",
["Galatian"] = "xga",
["Galela"] = "gbi",
["Galeya"] = "gar",
["Galice"] = "gce",
["Galician"] = "gl",
["Galindian"] = "xgl",
["Gallaecian"] = "cel-gal",
["Gallo"] = "roa-gal",
["Gallo-Italic of Basilicata"] = "roa-gib",
["Gallo-Italic of Sicily"] = "roa-gis",
["Gallurese"] = "sdn",
["Galo"] = "adl",
["Galoli"] = "gal",
["Gamale Kham"] = "kgj",
["Gambera"] = "gma",
["Gamela"] = "sai-gam",
["Gamilaraay"] = "kld",
["Gamit"] = "gbl",
["Gamkonora"] = "gak",
["Gamo"] = "gmv",
["Gamo-Ningi"] = "bte",
["Gan"] = "gan",
["Gana"] = "gnq",
["Ganang"] = "gne",
["Gandhari"] = "pgd",
["Gane"] = "gzn",
["Ganggalida"] = "gcd",
["Ganglau"] = "ggl",
["Gangte"] = "gnb",
["Gangulu"] = "gnl",
["Gants"] = "gao",
["Ganza"] = "gza",
["Ganzi"] = "gnz",
["Gao"] = "gga",
["Gapapaiwa"] = "pwg",
["Garawa"] = "wrk",
["Garhwali"] = "gbm",
["Garifuna"] = "cab",
["Garingbal"] = "xgi",
["Garo"] = "grt",
["Garre"] = "gex",
["Garus"] = "gyb",
["Garza"] = "xgr",
["Gashowu Yokuts"] = "yok-gsy",
["Gata'"] = "gaq",
["Gaulish"] = "cel-gau",
["Gavak"] = "dmc",
["Gavar"] = "gou",
["Gavião do Jiparaná"] = "gvo",
["Gawar-Bati"] = "gwt",
["Gawwada"] = "gwd",
["Gaya"] = "zra",
["Gayil"] = "gyl",
["Gayo"] = "gay",
["Gayón"] = "sai-gay",
["Gbagyi"] = "gbr",
["Gban"] = "ggu",
["Gbanu"] = "gbv",
["Gbanziri"] = "gbg",
["Gbari"] = "gby",
["Gbaya-Bossangoa"] = "gbp",
["Gbaya-Bozoum"] = "gbq",
["Gbaya-Mbodomo"] = "gmm",
["Gbayi"] = "gyg",
["Gbesi Gbe"] = "gbs",
["Gbii"] = "ggb",
["Gbin"] = "xgb",
["Gbiri-Niragu"] = "grh",
["Gboloo Grebo"] = "gec",
["Gciriku"] = "diu",
["Gcwi"] = "gwj",
["Ge"] = "hmj",
["Ge'ez"] = "gez",
["Geba Karen"] = "kvq",
["Gebe"] = "gei",
["Gedaged"] = "gdd",
["Gedeo"] = "drs",
["Geji"] = "gji",
["Geko Karen"] = "ghk",
["Gela"] = "nlg",
["Gele'"] = "sbc",
["Geme"] = "geq",
["Gen"] = "gej",
["Gende"] = "gaf",
["Gengle"] = "geg",
["Georgian"] = "ka",
["Gepo"] = "ygp",
["Gera"] = "gew",
["Gerka"] = "gek",
["German"] = "de",
["German Sign Language"] = "gsg",
["Geruma"] = "gea",
["Geser-Gorom"] = "ges",
["Geshiza"] = "ero-gsz",
["Gey"] = "guv",
["Ghadames"] = "gha",
["Ghanaian Sign Language"] = "gse",
["Ghandruk Sign Language"] = "gds",
["Ghanongga"] = "ghn",
["Ghari"] = "gri",
["Ghayavi"] = "bmk",
["Ghera"] = "ghr",
["Ghomala'"] = "bbj",
["Ghomara"] = "gho",
["Ghotuo"] = "aaa",
["Ghulfan"] = "ghl",
["Giangan"] = "bgi",
["Gibanawa"] = "gib",
["Gidar"] = "gid",
["Gikyode"] = "acd",
["Gilaki"] = "glk",
["Gilbertese"] = "gil",
["Gilima"] = "gix",
["Gimi (Austronesian)"] = "gip",
["Gimi (Papuan)"] = "gim",
["Gimme"] = "kmp",
["Gimnime"] = "gmn",
["Ginuman"] = "gnm",
["Girawa"] = "bbr",
["Girirra"] = "gii",
["Giryama"] = "nyf",
["Githabul"] = "gih",
["Gitua"] = "ggt",
["Gitxsan"] = "git",
["Giyug"] = "giy",
["Gizrra"] = "tof",
["Glaro-Twabo"] = "glr",
["Glavda"] = "glw",
["Glio-Oubi"] = "oub",
["Glosa"] = "igs",
["Gnau"] = "gnu",
["Goa'uld"] = "art-gld",
["Goaria"] = "gig",
["Gobasi"] = "goi",
["Gobu"] = "gox",
["Godié"] = "god",
["Godoberi"] = "gdo",
["Godwari"] = "gdx",
["Goemai"] = "ank",
["Gofa"] = "gof",
["Gogo"] = "gog",
["Gogodala"] = "ggw",
["Goguryeo"] = "zkg",
["Gojri"] = "gju",
["Gokana"] = "gkn",
["Gokhy"] = "tbq-gkh",
["Gola"] = "gol",
["Golin"] = "gvf",
["Golpa"] = "lja",
["Gondi"] = "gon",
["Gone Dau"] = "goo",
["Gong"] = "ugo",
["Gongduk"] = "goe",
["Gonja"] = "gjn",
["Goo"] = "gov",
["Gooniyandi"] = "gni",
["Gor"] = "gqr",
["Gorakor"] = "goc",
["Gorap"] = "goq",
["Goreng"] = "xgg",
["Gorontalo"] = "gor",
["Gorovu"] = "grq",
["Gorwaa"] = "gow",
["Gothic"] = "got",
["Gottscheerish"] = "gmw-gts",
["Goundo"] = "goy",
["Gourmanchéma"] = "gux",
["Gowlan"] = "goj",
["Gowro"] = "gwf",
["Gozarkhani"] = "goz",
["Grangali"] = "nli",
["Grass Koiari"] = "kbk",
["Greek"] = "el",
["Greek Sign Language"] = "gss",
["Green Gelao"] = "giq",
["Green Hmong"] = "hnj",
["Greenlandic"] = "kl",
["Grenadian Creole English"] = "gcl",
["Gresi"] = "grs",
["Groma"] = "gro",
["Gros Ventre"] = "ats",
["Gua"] = "gwx",
["Guachí"] = "sai-gua",
["Guahibo"] = "guh",
["Guajajára"] = "gub",
["Guajá"] = "gvj",
["Guambiano"] = "gum",
["Guamo"] = "sai-gmo",
["Guanano"] = "gvc",
["Guanche"] = "gnc",
["Guarayu"] = "gyr",
["Guatemalan Sign Language"] = "gsm",
["Guató"] = "gta",
["Guayabero"] = "guo",
["Guazacapán"] = "nai-guz",
["Gudang"] = "xgd",
["Gudanji"] = "nji",
["Gude"] = "gde",
["Gudu"] = "gdu",
["Guduf-Gava"] = "gdf",
["Guerrero Amuzgo"] = "amu",
["Guerrero Nahuatl"] = "ngu",
["Guevea de Humboldt Zapotec"] = "zpg",
["Gugadj"] = "ggd",
["Gugu Badhun"] = "gdc",
["Gugu Warra"] = "wrw",
["Guhu-Samane"] = "ghs",
["Guianese Creole"] = "gcr",
["Guiberoua Bété"] = "bet",
["Guinau"] = "awd-gnu",
["Guinea Kpelle"] = "gkp",
["Guinea-Bissau Creole"] = "pov",
["Guinea-Bissau Sign Language"] = "lgs",
["Guinean Sign Language"] = "gus",
["Guiqiong"] = "gqi",
["Gujarati"] = "gu",
["Gula"] = "glu",
["Gula'alaa"] = "gmb",
["Gulay"] = "gvl",
["Gule"] = "gly",
["Gulf Arabic"] = "afb",
["Gullah"] = "gul",
["Gumalu"] = "gmu",
["Gumatj"] = "gnn",
["Gumawana"] = "gvs",
["Gumuz"] = "guk",
["Gun"] = "guw",
["Gundi"] = "gdi",
["Gunditjmara"] = "gjm",
["Gundungurra"] = "xrd",
["Gungabula"] = "gyf",
["Gungu"] = "rub",
["Guntai"] = "gnt",
["Gunu"] = "yas",
["Gunwinggu"] = "gup",
["Gunya"] = "gyy",
["Gupa-Abawa"] = "gpa",
["Gupapuyngu"] = "guf",
["Gur Lama"] = "las",
["Guragone"] = "gge",
["Guramalum"] = "grz",
["Gurani"] = "hac",
["Gureng Gureng"] = "gnr",
["Gurgula"] = "ggg",
["Guriaso"] = "grx",
["Gurindji"] = "gue",
["Gurindji Kriol"] = "gjr",
["Gurmana"] = "gvm",
["Guro"] = "goa",
["Gurung"] = "gvr",
["Guruntum"] = "grd",
["Gusan"] = "gsn",
["Gusii"] = "guz",
["Gusilay"] = "gsl",
["Gutnish"] = "gmq-gut",
["Guugu Yimidhirr"] = "kky",
["Guwa"] = "xgw",
["Guwamu"] = "gwu",
["Guwar"] = "aus-guw",
["Guya"] = "gka",
["Guyanese Creole English"] = "gyn",
["Guyani"] = "gvy",
["Guébie"] = "gie",
["Gvoko"] = "ngs",
["Gwa"] = "gwb",
["Gwahatike"] = "dah",
["Gwak"] = "jgk",
["Gwamhi-Wuri"] = "bga",
["Gwandara"] = "gwn",
["Gwara"] = "alv-gwa",
["Gweda"] = "grw",
["Gweno"] = "gwe",
["Gwere"] = "gwr",
["Gwich'in"] = "gwi",
["Gyalsumdo"] = "gyo",
["Gyele"] = "gyi",
["Gyem"] = "gye",
["Güenoa"] = "sai-gue",
["Habu"] = "hbu",
["Hachijō"] = "jpx-hcj",
["Hadiyya"] = "hdy",
["Hadoti"] = "hoj",
["Hadrami"] = "xhd",
["Hadza"] = "hts",
["Haeke"] = "aek",
["Hahon"] = "hah",
["Haida"] = "hai",
["Haigwai"] = "hgw",
["Hailufeng Min"] = "nan-hlh",
["Hainanese"] = "hnm",
["Hainyaxo Bozo"] = "bzx",
["Haiphong Sign Language"] = "haf",
["Haisla"] = "has",
["Haitian Creole"] = "ht",
["Haitian Vodoun Culture Language"] = "hvc",
["Haiǁom"] = "hgm",
["Haji"] = "hji",
["Hajong"] = "haj",
["Hakka"] = "hak",
["Hakö"] = "hao",
["Halang"] = "hal",
["Halang Doan"] = "hld",
["Halbi"] = "hlb",
["Halia"] = "hla",
["Halkomelem"] = "hur",
["Hamap"] = "hmu",
["Hamba"] = "hba",
["Hamer-Banna"] = "amf",
["Hamtai"] = "hmt",
["Hanga"] = "hag",
["Hanga Hundi"] = "wos",
["Hani"] = "hni",
["Hanoi Sign Language"] = "hab",
["Hanunoo"] = "hnn",
["Harami"] = "xha",
["Harappan"] = "xiv",
["Harari"] = "har",
["Haraza"] = "nub-har",
["Harijan Kinnauri"] = "kjo",
["Haroi"] = "hro",
["Harsusi"] = "hss",
["Haruai"] = "tmd",
["Haruku"] = "hrk",
["Haryanvi"] = "bgc",
["Harzani"] = "hrz",
["Hasaitic"] = "sem-has",
["Hasha"] = "ybj",
["Hassaniya Arabic"] = "mey",
["Hatam"] = "had",
["Hattic"] = "xht",
["Hausa"] = "ha",
["Hausa Sign Language"] = "hsl",
["Haush"] = "sai-hau",
["Havasupai-Walapai-Yavapai"] = "yuf",
["Haveke"] = "hvk",
["Havu"] = "hav",
["Hawai'i Pidgin Sign Language"] = "hps",
["Hawaiian"] = "haw",
["Hawaiian Creole"] = "hwc",
["Haya"] = "hay",
["Hdi"] = "xed",
["Hebrew"] = "he",
["Hehe"] = "heh",
["Heiban"] = "hbn",
["Heiltsuk"] = "hei",
["Helong"] = "heg",
["Hema"] = "nix",
["Hemba"] = "hem",
["Hember Avu"] = "mmi",
["Herdé"] = "hed",
["Herero"] = "hz",
["Hermit"] = "llf",
["Hernican"] = "xhr",
["Hewa"] = "ham",
["Heyo"] = "auk",
["Hibito"] = "hib",
["Hidatsa"] = "hid",
["Higaonon"] = "mba",
["High Valyrian"] = "art-vlh",
["Highland Konjo"] = "kjk",
["Highland Oaxaca Chontal"] = "chd",
["Highland Popoluca"] = "poi",
["Highland Puebla Nahuatl"] = "azz",
["Highland Totonac"] = "tos",
["Hijazi Arabic"] = "acw",
["Hijuk"] = "hij",
["Hiligaynon"] = "hil",
["Hill Maria"] = "mrr",
["Himarimã"] = "hir",
["Hindi"] = "hi",
["Hindi Dogri"] = "dgo",
["Hinduri"] = "hii",
["Hinukh"] = "gin",
["Hiri Motu"] = "ho",
["Hismaic"] = "sem-his",
["Hitchiti"] = "nai-hit",
["Hittite"] = "hit",
["Hitu"] = "htu",
["Hiw"] = "hiw",
["Hixkaryana"] = "hix",
["Hlai"] = "lic",
["Hlepho Phowa"] = "yhl",
["Hlersu"] = "hle",
["Hmar"] = "hmr",
["Hmong Don"] = "hmf",
["Hmong Dô"] = "hmv",
["Hmong Shua"] = "hmz",
["Hmwaveke"] = "mrk",
["Ho"] = "hoc",
["Ho Chi Minh City Sign Language"] = "hos",
["Hoava"] = "hoa",
["Hobyót"] = "hoh",
["Hoia Hoia"] = "hhi",
["Hokkien"] = "nan-hbl",
["Holikachuk"] = "hoi",
["Holiya"] = "hoy",
["Holma"] = "hod",
["Holoholo"] = "hoo",
["Holu"] = "hol",
["Homa"] = "hom",
["Honduran Lenca"] = "len",
["Honduras Sign Language"] = "hds",
["Hone"] = "juh",
["Hong Kong Sign Language"] = "hks",
["Honi"] = "how",
["Hopi"] = "hop",
["Horned Miao"] = "hrm",
["Horo"] = "hor",
["Horom"] = "hoe",
["Hote"] = "hot",
["Hoti"] = "hti",
["Hovongan"] = "hov",
["Hoyahoya"] = "hhy",
["Hozo"] = "hoz",
["Hpon"] = "hpo",
["Hrangkhol"] = "hra",
["Hruso"] = "hru",
["Hrê"] = "hre",
["Hu"] = "huo",
["Huachipaeri"] = "hug",
["Huambisa"] = "hub",
["Huaorani"] = "auc",
["Huarijio"] = "var",
["Huaulu"] = "hud",
["Huautla Mazatec"] = "mau",
["Huave"] = "huv",
["Huaxcaleca Nahuatl"] = "nhq",
["Huba"] = "hbb",
["Huehuetla Tepehua"] = "tee",
["Huetar"] = "cba-hue",
["Huichol"] = "hch",
["Huilliche"] = "huh",
["Huitepec Mixtec"] = "mxs",
["Huizhou"] = "czh",
["Hukumina"] = "huw",
["Hula"] = "hul",
["Hulaulá"] = "huy",
["Huli"] = "hui",
["Hulung"] = "huk",
["Humburi Senni"] = "hmb",
["Humene"] = "huf",
["Hun"] = "uth",
["Hunde"] = "hke",
["Hung"] = "hnu",
["Hungana"] = "hum",
["Hungarian"] = "hu",
["Hungarian Sign Language"] = "hsh",
["Hungworo"] = "nat",
["Hunjara-Kaina Ke"] = "hkk",
["Hunnic"] = "xhc",
["Hunsrik"] = "hrx",
["Hunzib"] = "huz",
["Hupa"] = "hup",
["Hupdë"] = "jup",
["Hupla"] = "hap",
["Hurrian"] = "xhu",
["Hutterisch"] = "geh",
["Hwana"] = "hwo",
["Hya"] = "hya",
["Hyam"] = "jab",
["Hän"] = "haa",
["Hértevin"] = "hrt",
["I-Wak"] = "iwk",
["Iaai"] = "iai",
["Iamalele"] = "yml",
["Iatmul"] = "ian",
["Iau"] = "tmu",
["Ibali Teke"] = "tek",
["Ibaloi"] = "ibl",
["Iban"] = "iba",
["Ibanag"] = "ibg",
["Ibani"] = "iby",
["Ibatan"] = "ivb",
["Iberian"] = "xib",
["Ibibio"] = "ibb",
["Ibino"] = "ibn",
["Iboko"] = "bkp",
["Ibu"] = "ibu",
["Ibuoro"] = "ibr",
["Icelandic"] = "is",
["Icelandic Sign Language"] = "icl",
["Iceve-Maci"] = "bec",
["Ida'an"] = "dbj",
["Idakho-Isukha-Tiriki"] = "ida",
["Idaté"] = "idt",
["Idere"] = "ide",
["Idesa"] = "ids",
["Idi"] = "idi",
["Idiom Neutral"] = "mis-idn",
["Ido"] = "io",
["Idoma"] = "idu",
["Idon"] = "idc",
["Idu"] = "clk",
["Idun"] = "ldb",
["Iduna"] = "viv",
["Ifo"] = "iff",
["Ifè"] = "ife",
["Igala"] = "igl",
["Igana"] = "igg",
["Igbo"] = "ig",
["Igede"] = "ige",
["Ignaciano"] = "ign",
["Igo"] = "ahl",
["Iguta"] = "nar",
["Igwe"] = "igw",
["Iha"] = "ihp",
["Ihievbe"] = "ihi",
["Ija-Zuba"] = "vki",
["Ik"] = "ikx",
["Ika"] = "ikk",
["Ikaranggal"] = "ikr",
["Ikizu"] = "ikz",
["Iko"] = "iki",
["Ikobi-Mena"] = "meb",
["Ikoma"] = "ntk",
["Ikpeng"] = "txi",
["Ikpeshi"] = "ikp",
["Ikposo"] = "kpo",
["Iku-Gora-Ankwa"] = "ikv",
["Ikulu"] = "ikl",
["Ikwere"] = "ikw",
["Ikwo"] = "iqw",
["Ila"] = "ilb",
["Ile Ape"] = "ila",
["Ilgar"] = "ilg",
["Ili Turki"] = "ili",
["Ili'uun"] = "ilu",
["Ilianen Manobo"] = "mbi",
["Illyrian"] = "xil",
["Ilocano"] = "ilo",
["Ilongot"] = "ilk",
["Ilue"] = "ilv",
["Ilwana"] = "mlk",
["Imbongu"] = "imo",
["Imonda"] = "imn",
["Imroing"] = "imr",
["Inabaknon"] = "abx",
["Inapang"] = "mzu",
["Inari Sami"] = "smn",
["Indanga"] = "bnt-ind",
["Indian Sign Language"] = "ins",
["Indo-Portuguese"] = "idb",
["Indonesian"] = "id",
["Indonesian Bajau"] = "bdl",
["Indonesian Sign Language"] = "inl",
["Indri"] = "idr",
["Indus Kohistani"] = "mvy",
["Inebu One"] = "oin",
["Ineseño"] = "inz",
["Inga"] = "inb",
["Ingrian"] = "izh",
["Ingush"] = "inh",
["Inlaod Itneg"] = "iti",
["Inoke-Yate"] = "ino",
["Inonhan"] = "loc",
["Inor"] = "ior",
["Inpui Naga"] = "nkf",
["Interlingua"] = "ia",
["Interlingue"] = "ie",
["International Sign"] = "ils",
["Interslavic"] = "isv",
["Intha"] = "int",
["Inuinnaqtun"] = "esx-inq",
["Inuit Sign Language"] = "iks",
["Inuktitut"] = "iu",
["Inuktun"] = "esx-ink",
["Inupiaq"] = "ik",
["Inuvialuktun"] = "ikt",
["Ipai"] = "nai-ipa",
["Ipalapa Amuzgo"] = "azm",
["Ipiko"] = "ipo",
["Ipili"] = "ipi",
["Ipulo"] = "ass",
["Iquito"] = "iqu",
["Ir"] = "irr",
["Irantxe"] = "irn",
["Iranun"] = "ill",
["Iraqi Arabic"] = "acm",
["Iraqw"] = "irk",
["Irarutu"] = "irh",
["Iraya"] = "iry",
["Iresim"] = "ire",
["Irish"] = "ga",
["Irish Sign Language"] = "isg",
["Irula"] = "iru",
["Isabi"] = "isa",
["Isan"] = "tts",
["Isanzu"] = "isn",
["Isarog Agta"] = "agk",
["Isaurian"] = "mis-isa",
["Isconahua"] = "isc",
["Isebe"] = "igo",
["Ishkashimi"] = "isk",
["Isinai"] = "inn",
["Isirawa"] = "srl",
["Islander Creole English"] = "icr",
["Isnag"] = "isd",
["Isoko"] = "iso",
["Israeli Sign Language"] = "isr",
["Isthmus Mixe"] = "mir",
["Isthmus Zapotec"] = "zai",
["Istriot"] = "ist",
["Istro-Romanian"] = "ruo",
["Isu"] = "isu",
["Isubu"] = "szv",
["Italian"] = "it",
["Italian Sign Language"] = "ise",
["Italiot Greek"] = "grk-ita",
["Itawit"] = "itv",
["Itelmen"] = "itl",
["Itene"] = "ite",
["Iteri"] = "itr",
["Itik"] = "itx",
["Ito"] = "itw",
["Itonama"] = "ito",
["Itsekiri"] = "its",
["Itu Mbon Uzo"] = "itm",
["Itundujia Mixtec"] = "mce",
["Itza'"] = "itz",
["Iu Mien"] = "ium",
["Ivatan"] = "ivv",
["Iwaidja"] = "ibd",
["Iwal"] = "kbm",
["Iwam"] = "iwm",
["Iwur"] = "iwo",
["Ixcatec"] = "ixc",
["Ixcatlán Mazatec"] = "mzi",
["Ixil"] = "ixl",
["Ixtayutla Mixtec"] = "vmj",
["Ixtenco Otomi"] = "otz",
["Iyayu"] = "iya",
["Iyive"] = "uiv",
["Iyo"] = "nca",
["Iyo'wujwa Chorote"] = "crq",
["Iyojwa'ja Chorote"] = "crt",
["Izere"] = "izr",
["Izi"] = "izz",
["Izi-Ezaa-Ikwo-Mgbo"] = "izi",
["Izon"] = "ijc",
["Izora"] = "cbo",
["Iñapari"] = "inp",
["Jabem"] = "jae",
["Jabutí"] = "jbt",
["Jad"] = "jda",
["Jadgali"] = "jdg",
["Jah Hut"] = "jah",
["Jahanka"] = "jad",
["Jair Awyu"] = "awv",
["Jakaltek"] = "jac",
["Jakati"] = "jat",
["Jalapa de Díaz Mazatec"] = "maj",
["Jalkunan"] = "bxl",
["Jamaican Country Sign Language"] = "jcs",
["Jamaican Creole"] = "jam",
["Jamaican Sign Language"] = "jls",
["Jamamadí"] = "jaa",
["Jambi Malay"] = "jax",
["Jamiltepec Mixtec"] = "mxt",
["Jaminjung"] = "djd",
["Jamsay"] = "djm",
["Jamtish"] = "gmq-jmk",
["Jandavra"] = "jnd",
["Janday"] = "jan",
["Jangkang"] = "djo",
["Jangshung"] = "jna",
["Janji"] = "jni",
["Japanese"] = "ja",
["Japanese Sign Language"] = "jsl",
["Japhug"] = "sit-jap",
["Japrería"] = "jru",
["Jaqaru"] = "jqr",
["Jara"] = "jaf",
["Jarai"] = "jra",
["Jarawa"] = "anq",
["Jaru"] = "ddj",
["Jassic"] = "ysc",
["Jaunsari"] = "jns",
["Javanese"] = "jv",
["Javindo"] = "jvd",
["Jawe"] = "jaz",
["Jaya"] = "jyy",
["Jebero"] = "jeb",
["Jeh"] = "jeh",
["Jehai"] = "jhi",
["Jeikó"] = "sai-jko",
["Jeju"] = "jje",
["Jemez"] = "tow",
["Jenaama Bozo"] = "bze",
["Jeng"] = "jeg",
["Jennu Kurumba"] = "xuj",
["Jere"] = "jer",
["Jeri Kuo"] = "jek",
["Jersey Dutch"] = "gmw-jdt",
["Jeru"] = "akj",
["Jerung"] = "jee",
["Jhankot Sign Language"] = "jhs",
["Jiamao"] = "jio",
["Jiba"] = "juo",
["Jibu"] = "jib",
["Jicarilla"] = "apj",
["Jie"] = "mis-jie",
["Jiiddu"] = "jii",
["Jilbe"] = "jie",
["Jili"] = "mgi",
["Jilim"] = "jil",
["Jimi"] = "jmi",
["Jimjimen"] = "jim",
["Jin"] = "cjy",
["Jina"] = "jia",
["Jingpho"] = "kac",
["Jingulu"] = "jig",
["Jiongnai Bunu"] = "pnu",
["Jirajara"] = "sai-jrj",
["Jirel"] = "jul",
["Jiru"] = "jrr",
["Jita"] = "jit",
["Jizhao"] = "mis-jzh",
["Jju"] = "kaj",
["Joba"] = "job",
["Jofotek-Bromnya"] = "jbr",
["Jola-Fonyi"] = "dyo",
["Jola-Kasa"] = "csk",
["Jonkor Bourmataguil"] = "jeu",
["Jordanian Sign Language"] = "jos",
["Jorá"] = "jor",
["Jowulu"] = "jow",
["Ju"] = "juu",
["Juang"] = "jun",
["Juba Arabic"] = "pga",
["Judeo-Italian"] = "itk",
["Judeo-Persian"] = "jpr",
["Judeo-Tat"] = "jdt",
["Jukun Takum"] = "jbu",
["Jumaytepeque"] = "nai-jum",
["Jumjum"] = "jum",
["Jumla Sign Language"] = "jus",
["Jumli"] = "jml",
["Jungle Inga"] = "inj",
["Juquila Mixe"] = "mxq",
["Jur Modo"] = "bex",
["Juray"] = "juy",
["Jurchen"] = "juc",
["Jurúna"] = "jur",
["Jutiapa"] = "nai-jtp",
["Jutish"] = "jut",
["Juwal"] = "mwb",
["Juxtlahuaca Mixtec"] = "vmc",
["Juǀ'hoan"] = "ktz",
["Jwira-Pepesa"] = "jwi",
["Júma"] = "jua",
["K'iche'"] = "quc",
["Kaamba"] = "xku",
["Kaan"] = "ldl",
["Kaang Chin"] = "ckn",
["Kaansa"] = "gna",
["Kaapor Sign Language"] = "uks",
["Kaba"] = "ksp",
["Kabalai"] = "kvf",
["Kabatei"] = "xkp",
["Kabba-Laka"] = "lap",
["Kabishiana"] = "tup-kab",
["Kabiye"] = "kbp",
["Kabola"] = "klz",
["Kabore One"] = "onk",
["Kabras"] = "lkb",
["Kaburi"] = "uka",
["Kabutra"] = "kbu",
["Kabuverdianu"] = "kea",
["Kabwa"] = "cwa",
["Kabwari"] = "kcw",
["Kabyle"] = "kab",
["Kachama-Ganjule"] = "kcx",
["Kachari"] = "xac",
["Kachchi"] = "kfr",
["Kachi Koli"] = "gjk",
["Kacipo-Balesi"] = "koe",
["Kaco'"] = "xkk",
["Kadai"] = "kzd",
["Kadar"] = "kej",
["Kadara"] = "kad",
["Kadaru"] = "kdu",
["Kadiwéu"] = "kbc",
["Kado"] = "kdv",
["Kadu (Myanmar)"] = "zkd",
["Kadugli"] = "xtc",
["Kaduo"] = "ktp",
["Kaera"] = "jka",
["Kafa"] = "kbr",
["Kafoa"] = "kpu",
["Kagan Kalagan"] = "kll",
["Kagate"] = "syw",
["Kagayanen"] = "cgc",
["Kagoma"] = "kdm",
["Kagoro"] = "xkg",
["Kagulu"] = "kki",
["Kahe"] = "hka",
["Kahua"] = "agw",
["Kaian"] = "kct",
["Kaibobo"] = "kzb",
["Kaidipang"] = "kzp",
["Kaiep"] = "kbw",
["Kaikadi"] = "kep",
["Kaike"] = "kzq",
["Kaiku"] = "kkq",
["Kaimbulawa"] = "zka",
["Kaimbé"] = "xai",
["Kaingang"] = "kgp",
["Kairak"] = "ckr",
["Kairiru"] = "kxa",
["Kairui-Midiki"] = "krd",
["Kais"] = "kzm",
["Kaitag"] = "xdq",
["Kaivi"] = "kce",
["Kaiwá"] = "kgk",
["Kaiy"] = "tcq",
["Kajakse"] = "ckq",
["Kajali"] = "xkj",
["Kajaman"] = "kag",
["Kakabai"] = "kqf",
["Kakabe"] = "kke",
["Kakanda"] = "kka",
["Kaki Ae"] = "tbd",
["Kakihum"] = "kxe",
["Kako"] = "kkj",
["Kakwa"] = "keo",
["Kala"] = "kcl",
["Kala Lagaw Ya"] = "mwp",
["Kalaamaya"] = "lkm",
["Kalabakan"] = "kve",
["Kalabari"] = "ijn",
["Kalabra"] = "kzz",
["Kalagan"] = "kqe",
["Kalaktang Monpa"] = "kkf",
["Kalam"] = "kmh",
["Kalami"] = "gwc",
["Kalamsé"] = "knz",
["Kalanadi"] = "wkl",
["Kalanga"] = "kck",
["Kalao"] = "kly",
["Kalapuya"] = "kyl",
["Kalarko"] = "kba",
["Kalasha"] = "kls",
["Kalasuri"] = "xme-kls",
["Kalašma"] = "ine-kal",
["Kalenjin"] = "kln",
["Kalinago"] = "crb",
["Kalkatungu"] = "ktg",
["Kalkoti"] = "xka",
["Kallawaya"] = "caw",
["Kalmyk"] = "xal",
["Kalo Finnish Romani"] = "rmf",
["Kalou"] = "ywa",
["Kaluli"] = "bco",
["Kalumpang"] = "kli",
["Kam"] = "kdx",
["Kamakan"] = "vkm",
["Kamang"] = "woi",
["Kamano"] = "kbq",
["Kamantan"] = "kci",
["Kamar"] = "keq",
["Kamara"] = "jmr",
["Kamarian"] = "kzx",
["Kamaru"] = "kgx",
["Kamarupi Prakrit"] = "inc-kam",
["Kamasa"] = "klp",
["Kamasau"] = "kms",
["Kamassian"] = "xas",
["Kamayo"] = "kyk",
["Kamayurá"] = "kay",
["Kamba"] = "kam",
["Kambaata"] = "ktb",
["Kambaira"] = "kyy",
["Kambera"] = "xbr",
["Kamberataro"] = "kbv",
["Kamberau"] = "irx",
["Kambiwá"] = "xbw",
["Kami"] = "kmi",
["Kamkata-viri"] = "bsh",
["Kamo"] = "kcq",
["Kamoro"] = "kgq",
["Kamta"] = "rkt",
["Kamu"] = "xmu",
["Kamula"] = "xla",
["Kamwe"] = "hig",
["Kanakanabu"] = "xnb",
["Kanakuru"] = "kna",
["Kanamari"] = "knm",
["Kanashi"] = "xns",
["Kanasi"] = "soq",
["Kandas"] = "kqw",
["Kandawo"] = "gam",
["Kande"] = "kbs",
["Kang"] = "kyp",
["Kanga"] = "kcp",
["Kangean"] = "kkv",
["Kanggape"] = "igm",
["Kangjia"] = "kxs",
["Kango"] = "kty",
["Kango-Sua"] = "kzy",
["Kangri"] = "xnr",
["Kaniet"] = "ktk",
["Kanikkaran"] = "kev",
["Kaningdon-Nindem"] = "kdp",
["Kaningi"] = "kzo",
["Kaningra"] = "knr",
["Kaninuwa"] = "wat",
["Kanite"] = "kmu",
["Kanjari"] = "kft",
["Kanju"] = "kbe",
["Kankanaey"] = "kne",
["Kannada"] = "kn",
["Kannada Kurumba"] = "kfi",
["Kannauji"] = "bjj",
["Kanowit"] = "kxn",
["Kanoé"] = "kxo",
["Kansa"] = "ksk",
["Kantosi"] = "xkt",
["Kanu"] = "khx",
["Kanufi"] = "kni",
["Kanuri"] = "kr",
["Kanyok"] = "kny",
["Kao"] = "kax",
["Kaonde"] = "kqn",
["Kap"] = "ykm",
["Kapampangan"] = "pam",
["Kapauri"] = "khp",
["Kapin"] = "tbx",
["Kapinawá"] = "xpn",
["Kapingamarangi"] = "kpg",
["Kapriman"] = "dju",
["Kaptiau"] = "kbi",
["Kapya"] = "klo",
["Kaqchikel"] = "cak",
["Kaqchikel-K'iche' Mixed Language"] = "ckz",
["Kara (New Guinea)"] = "leu",
["Kara (Tanzania)"] = "reg",
["Karachay-Balkar"] = "krc",
["Karadjeri"] = "gbd",
["Karaga Mandaya"] = "mry",
["Karaim"] = "kdr",
["Karajá"] = "kpj",
["Karakalpak"] = "kaa",
["Karakhanid"] = "xqa",
["Karami"] = "xar",
["Karamojong"] = "kdj",
["Karang"] = "kzr",
["Karanga"] = "kth",
["Karankawa"] = "zkk",
["Karao"] = "kyj",
["Karas"] = "kgv",
["Karata"] = "kpt",
["Karawa"] = "xrw",
["Karbi"] = "mjw",
["Kare (Central Africa)"] = "kbn",
["Kare (New Guinea)"] = "kmf",
["Karekare"] = "kai",
["Karelian"] = "krl",
["Karey"] = "kyd",
["Kari"] = "kbj",
["Kari'na"] = "car",
["Karian"] = "bql",
["Karingani"] = "kgn",
["Karipuna"] = "kuq",
["Karipúna Creole French"] = "kmv",
["Kariri"] = "kzw",
["Karitiâna"] = "ktn",
["Kariya"] = "kil",
["Kariyarra"] = "vka",
["Karkar-Yuri"] = "yuj",
["Karkin"] = "krb",
["Karko"] = "kko",
["Karnai"] = "bbv",
["Karo"] = "kxh",
["Karo Batak"] = "btx",
["Karok"] = "kyh",
["Karolanos"] = "kyn",
["Karon"] = "krx",
["Karon Dori"] = "kgw",
["Karore"] = "xkx",
["Karranga"] = "xrq",
["Karuwali"] = "rxw",
["Kasanga"] = "ccj",
["Kasem"] = "xsm",
["Kashaya"] = "kju",
["Kashmiri"] = "ks",
["Kashubian"] = "csb",
["Kasiguranin"] = "ksn",
["Kaska"] = "kkz",
["Kaskean"] = "zsk",
["Kaskihá"] = "gva",
["Kassite"] = "mis-kas",
["Kassonke"] = "kao",
["Kasua"] = "khs",
["Kataang"] = "kgd",
["Katabaga"] = "ktq",
["Katawixi"] = "xat",
["Katembri"] = "sai-kat",
["Kathlamet"] = "nai-kat",
["Kathoriya Tharu"] = "tkt",
["Kathu"] = "ykt",
["Katkari"] = "kfu",
["Katla"] = "kcr",
["Kato"] = "ktw",
["Katso"] = "kaf",
["Katua"] = "kta",
["Katukina"] = "knt",
["Kaulong"] = "pss",
["Kaur"] = "vkk",
["Kaure"] = "bpp",
["Kaurna"] = "zku",
["Kauwera"] = "xau",
["Kavalan"] = "ckv",
["Kavet"] = "krv",
["Kawacha"] = "kcb",
["Kawaiisu"] = "xaw",
["Kawe"] = "kgb",
["Kawishana"] = "awd-kaw",
["Kawésqar"] = "alc",
["Kaxararí"] = "ktx",
["Kaxuyana"] = "kbb",
["Kayabí"] = "kyz",
["Kayagar"] = "kyt",
["Kayan"] = "pdu",
["Kayan Mahakam"] = "xay",
["Kayan River Kayan"] = "xkn",
["Kayapa Kallahan"] = "kak",
["Kayapó"] = "txu",
["Kayardild"] = "gyd",
["Kayeli"] = "kzl",
["Kayong"] = "kxy",
["Kayort"] = "kyv",
["Kaytetye"] = "gbb",
["Kayupulau"] = "kzu",
["Kazakh"] = "kk",
["Kazukuru"] = "kzk",
["Ke'o"] = "xxk",
["Keak"] = "keh",
["Keapara"] = "khz",
["Kedah Malay"] = "meo",
["Kedang"] = "ksx",
["Keder"] = "kdy",
["Kehu"] = "khh",
["Kei"] = "kei",
["Keiga"] = "kec",
["Kein"] = "bmh",
["Keiyo"] = "eyo",
["Kela-Yela"] = "kel",
["Kelabit"] = "kzi",
["Kelantan Peranakan Hokkien"] = "mis-hkl",
["Keley-I Kallahan"] = "ify",
["Keliko"] = "kbo",
["Kelo"] = "xel",
["Kelon"] = "kyo",
["Kemak"] = "kem",
["Kembayan"] = "xem",
["Kemberano"] = "bzp",
["Kembra"] = "xkw",
["Kemezung"] = "dmo",
["Kemi Sami"] = "sjk",
["Kemiehua"] = "kfj",
["Kemtuik"] = "kmt",
["Kenaboi"] = "xbn",
["Kenati"] = "gat",
["Kendayan"] = "knx",
["Kendeje"] = "klf",
["Kendem"] = "kvm",
["Kenga"] = "kyq",
["Keningau Murut"] = "kxi",
["Keninjal"] = "knl",
["Kensiu"] = "kns",
["Kenswei Nsei"] = "ndb",
["Kenyan Sign Language"] = "xki",
["Kenyang"] = "ken",
["Kenyi"] = "lke",
["Keoru-Ahia"] = "xeu",
["Kepkiriwát"] = "kpn",
["Kepo'"] = "kuk",
["Kera"] = "ker",
["Kerak"] = "hhr",
["Kereho"] = "xke",
["Kerek"] = "krk",
["Kerewe"] = "ked",
["Kerewo"] = "kxz",
["Kerinci"] = "kvr",
["Kermanic"] = "xme-ker",
["Ket"] = "ket",
["Ketangalan"] = "kae",
["Kete"] = "kcv",
["Ketengban"] = "xte",
["Ketum"] = "ktt",
["Kewa"] = "kew",
["Keyagana"] = "kyg",
["Kgalagadi"] = "xkv",
["Khakas"] = "kjh",
["Khalaj"] = "klj",
["Khaling"] = "klr",
["Khamnigan Mongol"] = "ykh",
["Khamti"] = "kht",
["Khamyang"] = "ksu",
["Khana"] = "ogo",
["Khandeshi"] = "khn",
["Khao"] = "xao",
["Kharam Naga"] = "kfw",
["Kharia"] = "khr",
["Kharia Thar"] = "ksy",
["Khasi"] = "kha",
["Khayo"] = "lko",
["Khazar"] = "zkz",
["Khe"] = "kqg",
["Khehek"] = "tlx",
["Khengkha"] = "xkf",
["Khetrani"] = "xhe",
["Khezha Naga"] = "nkh",
["Khiamniungan Naga"] = "kix",
["Khinalug"] = "kjj",
["Khirwar"] = "kwx",
["Khisa"] = "kqm",
["Khitan"] = "zkt",
["Khlula"] = "ykl",
["Khmer"] = "km",
["Khmu"] = "kjg",
["Khoekhoe"] = "naq",
["Khoibu Naga"] = "nkb",
["Khoini"] = "xkc",
["Kholok"] = "ktc",
["Kholosi"] = "inc-kho",
["Khorasani Turkish"] = "kmz",
["Khorezmian Turkic"] = "zkh",
["Khotanese"] = "kho",
["Khowar"] = "khw",
["Khroskyabs"] = "jiq",
["Khua"] = "xhv",
["Khuen"] = "khf",
["Khumi Chin"] = "cnk",
["Khvarshi"] = "khv",
["Khwarezmian"] = "xco",
["Khwe"] = "xuu",
["Kháng"] = "kjm",
["Khün"] = "kkh",
["Kiautschou German Pidgin"] = "crp-kia",
["Kibala"] = "blv",
["Kibena"] = "bez",
["Kibet"] = "kie",
["Kibiri"] = "prm",
["Kichwa"] = "qwe-kch",
["Kickapoo"] = "kic",
["Kikai"] = "kzg",
["Kikami"] = "kcu",
["Kikuyu"] = "ki",
["Kildin Sami"] = "sjd",
["Kili"] = "tuw-kli",
["Kilit"] = "xme-klt",
["Kilivila"] = "kij",
["Kiliwa"] = "klb",
["Kilmeri"] = "kih",
["Kim"] = "kia",
["Kim Mun"] = "mji",
["Kimaama"] = "kig",
["Kimaragang"] = "kqr",
["Kimbu"] = "kiv",
["Kimbundu"] = "kmb",
["Kimki"] = "sbt",
["Kimré"] = "kqp",
["Kinabalian"] = "cbw",
["Kinalakna"] = "kco",
["Kinaray-a"] = "krj",
["Kinga"] = "zga",
["Kings River Yokuts"] = "yok-kry",
["Kinikinao"] = "gqn",
["Kinnauri"] = "kfk",
["Kintaq"] = "knq",
["Kinuku"] = "kkd",
["Kioko"] = "ues",
["Kiong"] = "kkm",
["Kiorr"] = "xko",
["Kiowa"] = "kio",
["Kipchak"] = "qwm",
["Kipfokomo"] = "pkb",
["Kipsigis"] = "sgc",
["Kiput"] = "kyi",
["Kir-Balar"] = "kkr",
["Kire"] = "geb",
["Kirfi"] = "kks",
["Kirike"] = "okr",
["Kirikiri"] = "kiy",
["Kirya-Konzel"] = "fkk",
["Kis"] = "kis",
["Kisa"] = "lks",
["Kisan"] = "xis",
["Kisankasa"] = "kqh",
["Kisar"] = "kje",
["Kisi"] = "kiz",
["Kistane"] = "gru",
["Kita Maninkakan"] = "mwk",
["Kitanemuk"] = "azc-ktn",
["Kitembo"] = "tbt",
["Kitja"] = "gia",
["Kitsai"] = "kii",
["Kituba"] = "ktu",
["Kiunum"] = "wei",
["Kla"] = "lda",
["Klallam"] = "clm",
["Klamath-Modoc"] = "kla",
["Klao"] = "klu",
["Klias River Kadazan"] = "kqt",
["Klingon"] = "tlh",
["Knaanic"] = "czk",
["Ko"] = "fuj",
["Koalib"] = "kib",
["Koasati"] = "cku",
["Koba"] = "kpd",
["Kobiana"] = "kcj",
["Kobol"] = "kgu",
["Kobon"] = "kpw",
["Koch"] = "kdq",
["Kochila Tharu"] = "thq",
["Koda"] = "cdz",
["Kodaku"] = "ksz",
["Kodava"] = "kfa",
["Kodeoha"] = "vko",
["Kodi"] = "kod",
["Kodia"] = "kwp",
["Koenoem"] = "kcs",
["Kofa"] = "kso",
["Kofei"] = "kpi",
["Kofyar"] = "kwl",
["Kohin"] = "kkx",
["Kohistani Shina"] = "plk",
["Koho"] = "kpm",
["Kohumono"] = "bcs",
["Koi"] = "kkt",
["Koibal"] = "zkb",
["Koireng"] = "nkd",
["Koitabu"] = "kqi",
["Koiwat"] = "kxt",
["Kok-Nar"] = "gko",
["Kok-Paponk"] = "okg",
["Kokata"] = "ktd",
["Kokborok"] = "trp",
["Koke"] = "kou",
["Koko-Bera"] = "kkp",
["Kokoda"] = "xod",
["Kokola"] = "kzn",
["Kokota"] = "kkk",
["Kol (Cameroon)"] = "biw",
["Kol (New Guinea)"] = "kol",
["Kola"] = "kvv",
["Kolami"] = "kfb",
["Kolbila"] = "klc",
["Kolhe"] = "ekl",
["Kolibugan Subanon"] = "skn",
["Kolom"] = "klm",
["Koluwawa"] = "klx",
["Kom (Cameroon)"] = "bkm",
["Kom (India)"] = "kmm",
["Koma"] = "kmy",
["Komba"] = "kpf",
["Kombai"] = "tyn",
["Kombio"] = "xbi",
["Komering"] = "kge",
["Komi-Permyak"] = "koi",
["Komi-Yazva"] = "urj-kya",
["Komi-Zyrian"] = "kpv",
["Kominimung"] = "xoi",
["Komo"] = "xom",
["Komodo"] = "kvh",
["Kompane"] = "kvp",
["Komyandaret"] = "kzv",
["Kon Keu"] = "kkn",
["Konabéré"] = "bbo",
["Konai"] = "kxw",
["Konda"] = "knd",
["Konda-Dora"] = "kfc",
["Kondekor"] = "gau",
["Koneraw"] = "kdw",
["Kongo"] = "kg",
["Konkani"] = "kok",
["Konkomba"] = "xon",
["Konni"] = "kma",
["Kono (Guinea)"] = "knu",
["Kono (Nigeria)"] = "klk",
["Kono (Sierra Leone)"] = "kno",
["Konomala"] = "koa",
["Konomihu"] = "nai-knm",
["Konongo"] = "kcz",
["Konso"] = "kxc",
["Konyak Naga"] = "nbe",
["Konyanka Maninka"] = "mku",
["Konzo"] = "koo",
["Koonzime"] = "ozm",
["Koorete"] = "kqy",
["Kopar"] = "xop",
["Kopkaka"] = "opk",
["Korafe-Yegha"] = "kpr",
["Korak"] = "koz",
["Korana"] = "kqz",
["Korandje"] = "kcy",
["Korean"] = "ko",
["Korean Sign Language"] = "kvk",
["Koreguaje"] = "coe",
["Koresh-e Rostam"] = "okh",
["Korku"] = "kfq",
["Korlai Creole Portuguese"] = "vkp",
["Koro (India)"] = "jkr",
["Koro (Vanuatu)"] = "krf",
["Koro (West Africa)"] = "kfo",
["Koromfé"] = "kfz",
["Koromira"] = "kqj",
["Koromu"] = "xes",
["Koronadal Blaan"] = "bpr",
["Koroni"] = "xkq",
["Korop"] = "krp",
["Koropó"] = "xxr",
["Koroshi"] = "ktl",
["Korowai"] = "khe",
["Korra Koraga"] = "kfd",
["Korubo"] = "xor",
["Korupun-Sela"] = "kpq",
["Korwa"] = "kfp",
["Koryak"] = "kpy",
["Kosadle"] = "kiq",
["Kosarek Yale"] = "kkl",
["Koshin"] = "kid",
["Kosraean"] = "kos",
["Kota (Gabon)"] = "koq",
["Kota (India)"] = "kfe",
["Kota Bangun Kutai Malay"] = "mqg",
["Kota Marudu Talantang"] = "grm",
["Kotafon Gbe"] = "kqk",
["Kotava"] = "avk",
["Koti"] = "eko",
["Kott"] = "zko",
["Kou"] = "snz",
["Kouya"] = "kyf",
["Kovai"] = "kqb",
["Kove"] = "kvc",
["Kowaki"] = "xow",
["Kowiai"] = "kwh",
["Koy Sanjaq Surat"] = "kqd",
["Koya"] = "kff",
["Koyaga"] = "kga",
["Koyo"] = "koh",
["Koyra Chiini"] = "khq",
["Koyraboro Senni"] = "ses",
["Koyukon"] = "koy",
["Kpagua"] = "kuw",
["Kpala"] = "kpl",
["Kpan"] = "kpk",
["Kpasam"] = "pbn",
["Kpati"] = "koc",
["Kpatili"] = "kym",
["Kpee"] = "cpo",
["Kpelle"] = "kpe",
["Kpessi"] = "kef",
["Kplang"] = "kph",
["Krache"] = "kye",
["Krahô"] = "xra",
["Kraol"] = "rka",
["Krenak"] = "kqq",
["Kresh"] = "krs",
["Krevinian"] = "zkv",
["Kreye"] = "xre",
["Krikati-Timbira"] = "xri",
["Krim"] = "krm",
["Krio"] = "kri",
["Krisa"] = "ksi",
["Kristang"] = "mcm",
["Krobu"] = "kxb",
["Krongo"] = "kgo",
["Kru'ng"] = "krr",
["Krymchak"] = "jct",
["Kryts"] = "kry",
["Ktunaxa"] = "kut",
["Kua"] = "tyu",
["Kua-nsi"] = "ykn",
["Kuamasi"] = "yku",
["Kuan"] = "uan",
["Kuanhua"] = "xnh",
["Kube"] = "kgf",
["Kubi"] = "kof",
["Kubo"] = "jko",
["Kubu"] = "kvb",
["Kucong"] = "lkc",
["Kudiya"] = "kfg",
["Kudmali"] = "kyw",
["Kudu-Camo"] = "kov",
["Kugama"] = "kow",
["Kugbo"] = "kes",
["Kugu-Muminh"] = "xmh",
["Kui (India)"] = "kxu",
["Kui (Indonesia)"] = "kvd",
["Kuijau"] = "dkr",
["Kuikúro"] = "kui",
["Kujarge"] = "vkj",
["Kuk"] = "kfn",
["Kukatja"] = "kux",
["Kukele"] = "kez",
["Kukkuzi"] = "urj-kuk",
["Kukna"] = "kex",
["Kuku-Mangk"] = "xmq",
["Kuku-Mu'inh"] = "xmp",
["Kuku-Thaypan"] = "typ",
["Kuku-Ugbanh"] = "ugb",
["Kuku-Uwanh"] = "uwa",
["Kuku-Yalanji"] = "gvn",
["Kula"] = "tpg",
["Kulaal"] = "glj",
["Kulere"] = "kul",
["Kulfa"] = "kxj",
["Kulina"] = "xpk",
["Kulisusu"] = "vkl",
["Kullu Pahari"] = "kfx",
["Kulon"] = "uon",
["Kulung"] = "kle",
["Kumak"] = "nee",
["Kumalu"] = "ksl",
["Kumam"] = "kdi",
["Kuman"] = "kue",
["Kumaoni"] = "kfy",
["Kumarbhag Paharia"] = "kmj",
["Kumba"] = "ksm",
["Kumbainggar"] = "kgs",
["Kumbaran"] = "wkb",
["Kumbewaha"] = "xks",
["Kumeyaay"] = "nai-kum",
["Kumhali"] = "kra",
["Kumu"] = "kmw",
["Kumukio"] = "kuo",
["Kumyk"] = "kum",
["Kumzari"] = "zum",
["Kuna"] = "cuk",
["Kunama"] = "kun",
["Kunbarlang"] = "wlg",
["Kunda"] = "kdn",
["Kundal Shahi"] = "shd",
["Kunduvadi"] = "wku",
["Kung"] = "kfl",
["Kungarakany"] = "ggk",
["Kungardutyi"] = "gdt",
["Kunggari"] = "kgl",
["Kungkari"] = "lku",
["Kuni"] = "kse",
["Kuni-Boazi"] = "kvg",
["Kunigami"] = "xug",
["Kunimaipa"] = "kup",
["Kunja"] = "pep",
["Kunjen"] = "kjn",
["Kunyi"] = "njx",
["Kunza"] = "kuz",
["Kuo"] = "xuo",
["Kuot"] = "kto",
["Kupa"] = "kug",
["Kupang Malay"] = "mkn",
["Kupia"] = "key",
["Kupsabiny"] = "kpz",
["Kur"] = "kuv",
["Kura Ede Nago"] = "nqk",
["Kurama"] = "krh",
["Kuranko"] = "knk",
["Kuri"] = "nbn",
["Kuria"] = "kuj",
["Kurichiya"] = "kfh",
["Kurmukar"] = "kfv",
["Kurnai"] = "unn",
["Kurrama"] = "vku",
["Kursav"] = "faj",
["Kurti"] = "ktm",
["Kurtjar"] = "gdj",
["Kurtöp"] = "xkz",
["Kurudu"] = "kjr",
["Kurux"] = "kru",
["Kuruáya"] = "kyr",
["Kusaal"] = "kus",
["Kusaghe"] = "ksg",
["Kushi"] = "kuh",
["Kustenau"] = "awd-kus",
["Kusu"] = "ksv",
["Kusunda"] = "kgg",
["Kutang Ghale"] = "ght",
["Kutep"] = "kub",
["Kuthant"] = "xut",
["Kutto"] = "kpa",
["Kutu"] = "kdc",
["Kuturmi"] = "khj",
["Kuuk Thaayorre"] = "thd",
["Kuuk Yak"] = "uky",
["Kuuku-Ya'u"] = "kuy",
["Kuvale"] = "olu",
["Kuvi"] = "kxv",
["Kuwaa"] = "blh",
["Kuwaataay"] = "cwt",
["Kuwani"] = "paa-kwn",
["Kuy"] = "kdt",
["Kven"] = "fkv",
["Kw'adza"] = "wka",
["Kwa'"] = "bko",
["Kwaami"] = "ksq",
["Kwadi"] = "kwz",
["Kwaio"] = "kwd",
["Kwaja"] = "kdz",
["Kwak"] = "kwq",
["Kwak'wala"] = "kwk",
["Kwakum"] = "kwu",
["Kwalhioqua-Tlatskanai"] = "qwt",
["Kwama"] = "kmq",
["Kwambi"] = "kwm",
["Kwamera"] = "tnk",
["Kwami"] = "ktf",
["Kwamtim One"] = "okk",
["Kwang"] = "kvi",
["Kwanga"] = "kwj",
["Kwangali"] = "kwn",
["Kwanja"] = "knp",
["Kwanka"] = "bij",
["Kwanyama"] = "kj",
["Kwara'ae"] = "kwf",
["Kwasio"] = "nmg",
["Kwaya"] = "kya",
["Kwaza"] = "xwa",
["Kwegu"] = "xwg",
["Kwer"] = "kwr",
["Kwerba"] = "kwe",
["Kwerba Mamberamo"] = "xwr",
["Kwere"] = "cwe",
["Kwerisa"] = "kkb",
["Kwese"] = "kws",
["Kwesten"] = "kwt",
["Kwini"] = "gww",
["Kwinsu"] = "kuc",
["Kwinti"] = "kww",
["Kwoma"] = "kmo",
["Kwomtari"] = "kwo",
["Kyak"] = "bka",
["Kyaka"] = "kyc",
["Kyakala"] = "tuw-kkl",
["Kyan-Karyaw Naga"] = "nqq",
["Kyenele"] = "kql",
["Kyenga"] = "tye",
["Kyerung"] = "kgy",
["Kyrgyz"] = "ky",
["Kâte"] = "kmg",
["Kélé"] = "keb",
["Kómnzo"] = "paa-kmn",
["La'bi"] = "lbi",
["Laal"] = "gdm",
["Laalaa"] = "cae",
["Laba"] = "lau",
["Label"] = "lbb",
["Labir"] = "jku",
["Labo"] = "mwi",
["Labo Phowa"] = "ypb",
["Laboya"] = "lmy",
["Labu"] = "lbu",
["Labuk-Kinabatangan Kadazan"] = "dtb",
["Lacandon"] = "lac",
["Lachi"] = "lbt",
["Lachiguiri Zapotec"] = "zpa",
["Lachixío Zapotec"] = "zpl",
["Ladakhi"] = "lbj",
["Ladin"] = "lld",
["Ladino"] = "lad",
["Ladji-Ladji"] = "llj",
["Laeko-Libuat"] = "lkl",
["Lafofa"] = "laf",
["Laghu"] = "lgb",
["Laghuu"] = "lgh",
["Lagwan"] = "kot",
["Laha (Indonesia)"] = "lhh",
["Laha (Vietnam)"] = "lha",
["Lahanan"] = "lhn",
["Lahnda"] = "lah",
["Lahta Karen"] = "kvt",
["Lahu"] = "lhu",
["Lahu Shi"] = "lhi",
["Lahul Lohar"] = "lhl",
["Lai"] = "cnh",
["Laimbue"] = "lmx",
["Laitu Chin"] = "clj",
["Laiyolo"] = "lji",
["Lak"] = "lbe",
["Laka"] = "lak",
["Lakalei"] = "lka",
["Lake Miwok"] = "lmw",
["Lakha"] = "lkh",
["Laki"] = "lki",
["Lakkia"] = "lbc",
["Lakon"] = "lkn",
["Lakondê"] = "lkd",
["Lakota"] = "lkt",
["Lakota Dida"] = "dic",
["Lakurumau"] = "lxm",
["Lala (New Guinea)"] = "nrz",
["Lala (South Africa)"] = "bnt-lal",
["Lala-Bisa"] = "leb",
["Lala-Roba"] = "lla",
["Lalana Chinantec"] = "cnl",
["Lama Bai"] = "lay",
["Lamaholot"] = "slp",
["Lamalera"] = "lmr",
["Lamang"] = "hia",
["Lamatuka"] = "lmq",
["Lamba"] = "lam",
["Lambadi"] = "lmn",
["Lambichhong"] = "lmh",
["Lambya"] = "lai",
["Lame"] = "bma",
["Lamenu"] = "lmu",
["Lamet"] = "lbn",
["Lamja-Dengsa-Tola"] = "ldh",
["Lamkang"] = "lmk",
["Lamma"] = "lev",
["Lamnso'"] = "lns",
["Lamogai"] = "lmg",
["Lampung Api"] = "ljp",
["Lamu"] = "llh",
["Lamu-Lamu"] = "lby",
["Lanas Lobu"] = "ruu",
["Landoma"] = "ldm",
["Lang'e"] = "yne",
["Langbashe"] = "lna",
["Langi"] = "lag",
["Langnian Buyang"] = "yln",
["Lango (Sudan)"] = "lno",
["Lango (Uganda)"] = "laj",
["Lanima"] = "lnw",
["Lanoh"] = "lnh",
["Lao"] = "lo",
["Lao Naga"] = "nlq",
["Laomian"] = "lwm",
["Laopang"] = "lbg",
["Laos Sign Language"] = "lso",
["Lapaguía-Guivini Zapotec"] = "ztl",
["Lapine"] = "art-lap",
["Lapuyan Subanun"] = "laa",
["Laragia"] = "lrg",
["Larantuka Malay"] = "lrt",
["Lardil"] = "lbz",
["Larestani"] = "lrl",
["Larevat"] = "lrv",
["Larike-Wakasihu"] = "alo",
["Laro"] = "lro",
["Larteh"] = "lar",
["Laru"] = "lan",
["Lasalimu"] = "llm",
["Lasgerdi"] = "lsa",
["Lashi"] = "lsi",
["Lasi"] = "lss",
["Latgalian"] = "ltg",
["Latin"] = "la",
["Latu"] = "ltu",
["Latundê"] = "ltn",
["Latvian"] = "lv",
["Latvian Sign Language"] = "lsl",
["Lau"] = "llu",
["Laua"] = "luf",
["Lauan"] = "llx",
["Lauje"] = "law",
["Laura"] = "lur",
["Laurentian"] = "lre",
["Lavatbura-Lamusong"] = "lbv",
["Lave"] = "brb",
["Laven"] = "lbo",
["Lavukaleve"] = "lvk",
["Lawangan"] = "lbx",
["Lawi"] = "lvi",
["Lawu"] = "lwu",
["Lawunuia"] = "tgi",
["Layakha"] = "lya",
["Laz"] = "lzz",
["Laze"] = "tbq-laz",
["Lealao Chinantec"] = "cle",
["Leco"] = "lec",
["Ledo Kaili"] = "lew",
["Leelau"] = "ldk",
["Lefa"] = "lfa",
["Lega-Mwenga"] = "lgm",
["Lega-Shabunda"] = "lea",
["Legbo"] = "agb",
["Legenyem"] = "lcc",
["Lehali"] = "tql",
["Leinong Naga"] = "lzn",
["Leipon"] = "lek",
["Leitre"] = "paa-lei",
["Leizhou Min"] = "luh",
["Lela"] = "dri",
["Lelak"] = "llk",
["Lele (Chad)"] = "lln",
["Lele (Congo)"] = "lel",
["Lele (Guinea)"] = "llc",
["Lele (New Guinea)"] = "lle",
["Lelemi"] = "lef",
["Lelepa"] = "lpa",
["Lembena"] = "leq",
["Lemerig"] = "lrz",
["Lemio"] = "lei",
["Lemnian"] = "xle",
["Lemolang"] = "ley",
["Lemoro"] = "ldj",
["Lenakel"] = "tnl",
["Lendu"] = "led",
["Lengilu"] = "lgi",
["Lengo"] = "lgr",
["Lengola"] = "lej",
["Lenje"] = "leh",
["Lenkau"] = "ler",
["Lenyima"] = "ldg",
["Leonese"] = "roa-leo",
["Lepcha"] = "lep",
["Lepki"] = "lpe",
["Lepontic"] = "xlp",
["Lere"] = "gnh",
["Lese"] = "les",
["Lesing-Gelimi"] = "let",
["Letemboi"] = "nms",
["Leti"] = "lti",
["Levuka"] = "lvu",
["Lewo"] = "lww",
["Lewo Eleng"] = "lwe",
["Lewotobi"] = "lwt",
["Leyigha"] = "ayi",
["Lezgi"] = "lez",
["Lhao Vo"] = "mhx",
["Lhokpu"] = "lhp",
["Li'o"] = "ljl",
["Liabuku"] = "lix",
["Liana-Seti"] = "ste",
["Liangmai Naga"] = "njn",
["Liberia Kpelle"] = "xpe",
["Liberian Kreyol"] = "lir",
["Libido"] = "liq",
["Libinza"] = "liz",
["Libon Bikol"] = "lbl",
["Liburnian"] = "xli",
["Libyan Arabic"] = "ayl",
["Libyan Sign Language"] = "lbs",
["Ligbi"] = "lig",
["Ligenza"] = "lgz",
["Ligurian"] = "lij",
["Lihir"] = "lih",
["Lika"] = "lik",
["Liki"] = "lio",
["Likila"] = "lie",
["Likuba"] = "kxx",
["Likum"] = "lib",
["Likwala"] = "kwc",
["Lilau"] = "lll",
["Lillooet"] = "lil",
["Limassa"] = "bme",
["Limbu"] = "lif",
["Limbum"] = "lmp",
["Limburgish"] = "li",
["Limi"] = "ylm",
["Limilngan"] = "lmc",
["Limos Kalinga"] = "kmk",
["Lindu"] = "klw",
["Linear A"] = "lab",
["Lingala"] = "ln",
["Lingao"] = "onb",
["Lingkhim"] = "lii",
["Lingua Franca Nova"] = "lfn",
["Linngithigh"] = "lnj",
["Lipan"] = "apl",
["Lipo"] = "lpo",
["Lisabata-Nuniali"] = "lcs",
["Lisela"] = "lcl",
["Lish"] = "lsh",
["Lishana Deni"] = "lsd",
["Lishanid Noshan"] = "aij",
["Lishán Didán"] = "trg",
["Lisu"] = "lis",
["Lithuanian"] = "lt",
["Lithuanian Sign Language"] = "lls",
["Little Swanport"] = "aus-lsw",
["Litzlitz"] = "lzl",
["Livonian"] = "liv",
["Livvi"] = "olo",
["Lizu"] = "sit-liz",
["Lo-Toga"] = "lht",
["Loarki"] = "lrk",
["Lobala"] = "loq",
["Lobi"] = "lob",
["Lodhi"] = "lbm",
["Logba"] = "lgq",
["Logo"] = "log",
["Logol"] = "lof",
["Logooli"] = "rag",
["Logorik"] = "liu",
["Lojban"] = "jbo",
["Lokaa"] = "yaz",
["Loko"] = "lok",
["Lokono"] = "arw",
["Lokoya"] = "lky",
["Lola"] = "lcd",
["Lolak"] = "llq",
["Lole"] = "llg",
["Lolo"] = "llb",
["Loloda"] = "loa",
["Lolopo"] = "ycl",
["Loma"] = "lom",
["Lomaiviti"] = "lmv",
["Lomakka"] = "loi",
["Lomavren"] = "rmi",
["Lombard"] = "lmo",
["Lombi"] = "lmi",
["Lombo"] = "loo",
["Lomwe"] = "ngl",
["Loncong"] = "lce",
["Long Phuri Naga"] = "lpn",
["Long Wat"] = "ttw",
["Longgu"] = "lgu",
["Longjia"] = "sit-lnj",
["Longto"] = "wok",
["Longuda"] = "lnu",
["Longyan Min"] = "nan-lnx",
["Loniu"] = "los",
["Lonwolwol"] = "crc",
["Loo"] = "ldo",
["Lopa"] = "lop",
["Lope"] = "yiu",
["Lopi"] = "lov",
["Lopit"] = "lpx",
["Lorang"] = "lrn",
["Lorediakarkar"] = "lnn",
["Lorrain"] = "roa-lor",
["Lote"] = "uvl",
["Lotha Naga"] = "njh",
["Lotud"] = "dtr",
["Lotuko"] = "lot",
["Lou"] = "loj",
["Louisiana Creole"] = "lou",
["Loun"] = "lox",
["Loup A"] = "xlo",
["Loup B"] = "xlb",
["Lovono"] = "vnk",
["Low German"] = "nds",
["Lower Burdekin"] = "xbb",
["Lower Chehalis"] = "cea",
["Lower Grand Valley Dani"] = "dni",
["Lower Mandobo"] = "bwp",
["Lower Nossob"] = "nsb",
["Lower Sorbian"] = "dsb",
["Lower Southern Aranda"] = "axl",
["Lower Ta'oih"] = "tto",
["Lower Tanana"] = "taa",
["Lowland Oaxaca Chontal"] = "clo",
["Lowland Tarahumara"] = "tac",
["Loxicha Zapotec"] = "ztp",
["Lozi"] = "loz",
["Luang"] = "lex",
["Luba-Kasai"] = "lua",
["Luba-Katanga"] = "lu",
["Lubila"] = "kcc",
["Lubu"] = "lcf",
["Lubuagan Kalinga"] = "knb",
["Luchazi"] = "lch",
["Lucumí"] = "luq",
["Ludian"] = "lud",
["Lufu"] = "ldq",
["Luganda"] = "lg",
["Lugbara"] = "lgg",
["Luguru"] = "ruf",
["Luhu"] = "lcq",
["Luhya"] = "luy",
["Luimbi"] = "lum",
["Luiseño"] = "lui",
["Lukpa"] = "dop",
["Lule"] = "ule",
["Lule Sami"] = "smj",
["Lumba-Yakkha"] = "luu",
["Lumbu"] = "lup",
["Lumun"] = "lmd",
["Lun Bawang"] = "lnd",
["Luna"] = "luj",
["Lunanakha"] = "luk",
["Lunda"] = "lun",
["Lungga"] = "lga",
["Luo"] = "luo",
["Luopohe Hmong"] = "hml",
["Luren"] = "sit-lrn",
["Luri (Nigeria)"] = "ldd",
["Lusengo"] = "lse",
["Lushootseed"] = "lut",
["Lusi"] = "khl",
["Lusitanian"] = "xls",
["Lutachoni"] = "lts",
["Lutos"] = "ndy",
["Lutuv"] = "clt",
["Luvale"] = "lue",
["Luwati"] = "luv",
["Luwian"] = "xlu",
["Luwo"] = "lwo",
["Luxembourgish"] = "lb",
["Luyana"] = "lyn",
["Lwalu"] = "lwa",
["Lwel"] = "lvl",
["Lycian"] = "xlc",
["Lydian"] = "xld",
["Lyngngam"] = "lyg",
["Lyélé"] = "lee",
["Láadan"] = "ldn",
["Láá Láá Bwamu"] = "bwj",
["Löyöp"] = "urr",
["Lü"] = "khb",
["Ma"] = "msj",
["Ma Manda"] = "skc",
["Ma'anyan"] = "mhy",
["Ma'di"] = "mhi",
["Ma'ya"] = "slz",
["Maaka"] = "mew",
["Maale"] = "mdy",
["Maasai"] = "mas",
["Maay"] = "ymm",
["Maba"] = "mqa",
["Mabaale"] = "mmz",
["Mabaan"] = "mfz",
["Mabaka Valley Kalinga"] = "kkg",
["Mabire"] = "muj",
["Maca"] = "mca",
["Macaguaje"] = "mcl",
["Macaguán"] = "mbn",
["Macanese"] = "mzs",
["Macau Pidgin Portuguese"] = "crp-mpp",
["Macedonian"] = "mk",
["Machame"] = "jmc",
["Machiguenga"] = "mcb",
["Machinere"] = "mpd",
["Machinga"] = "mvw",
["Macoris"] = "nai-mac",
["Macuna"] = "myy",
["Macushi"] = "mbc",
["Mada (Cameroon)"] = "mxu",
["Mada (Nigeria)"] = "mda",
["Madagascar Sign Language"] = "mzc",
["Madak"] = "mmx",
["Maden"] = "xmx",
["Madhi Madhi"] = "dmd",
["Madi"] = "grg",
["Madngele"] = "zml",
["Madukayang Kalinga"] = "kmd",
["Madurese"] = "mad",
["Maeng Itneg"] = "itt",
["Mafa"] = "maf",
["Mag-Anchi Ayta"] = "sgb",
["Mag-Indi Ayta"] = "blx",
["Magahat"] = "mtw",
["Magahi"] = "mag",
["Magdalena Peñasco Mixtec"] = "xtm",
["Magi"] = "gkd",
["Magiyi"] = "gmg",
["Magoma"] = "gmx",
["Magori"] = "zgr",
["Maguindanao"] = "mdh",
["Mahali"] = "mjx",
["Mahasu Pahari"] = "bfz",
["Mahican"] = "mjy",
["Mahongwe"] = "mhb",
["Mahou"] = "mxx",
["Maia"] = "sks",
["Maiadomu"] = "mzz",
["Maiani"] = "tnh",
["Maii"] = "mmm",
["Mailu"] = "mgu",
["Maindo"] = "cwb",
["Maipure"] = "awd-mpr",
["Mairasi"] = "zrs",
["Maisin"] = "mbq",
["Maithili"] = "mai",
["Maiwa (Indonesia)"] = "wmm",
["Maiwa (New Guinea)"] = "mti",
["Maiwala"] = "mum",
["Majang"] = "mpe",
["Majera"] = "xmj",
["Majhi"] = "mjz",
["Majhwar"] = "mmj",
["Mak (China)"] = "mkg",
["Mak (Nigeria)"] = "pbl",
["Makaa"] = "mcp",
["Makah"] = "myh",
["Makalero"] = "mjb",
["Makasae"] = "mkz",
["Makasar"] = "mak",
["Makassar Malay"] = "mfp",
["Makayam"] = "aup",
["Makhuwa"] = "vmw",
["Makhuwa-Marrevone"] = "xmc",
["Makhuwa-Meetto"] = "mgh",
["Makhuwa-Moniga"] = "mhm",
["Makhuwa-Saka"] = "xsq",
["Makhuwa-Shirima"] = "vmk",
["Maklew"] = "mgf",
["Makolkol"] = "zmh",
["Makonde"] = "kde",
["Maku"] = "xak",
["Maku'a"] = "lva",
["Makuri Naga"] = "jmn",
["Makuráp"] = "mpu",
["Makwe"] = "ymk",
["Makyan Naga"] = "umn",
["Mal"] = "mlf",
["Mal Paharia"] = "mkb",
["Mala (New Guinea)"] = "ped",
["Mala (Nigeria)"] = "ruy",
["Mala Malasar"] = "ima",
["Malaccan Creole Malay"] = "ccm",
["Malagasy"] = "mg",
["Malalamai"] = "mmt",
["Malalí"] = "sai-mal",
["Malango"] = "mln",
["Malankuravan"] = "mjo",
["Malapandaram"] = "mjp",
["Malaryan"] = "mjq",
["Malas"] = "mkr",
["Malasanga"] = "mqz",
["Malasar"] = "ymr",
["Malavedan"] = "mjr",
["Malawi Lomwe"] = "lon",
["Malawian Sign Language"] = "lws",
["Malay"] = "ms",
["Malayalam"] = "ml",
["Malayic Dayak"] = "xdy",
["Malaynon"] = "mlz",
["Malaysian Sign Language"] = "xml",
["Malba Birifor"] = "bfo",
["Male"] = "mdc",
["Malecite-Passamaquoddy"] = "pqm",
["Maleng"] = "pkt",
["Maleu-Kilenge"] = "mgl",
["Malfaxal"] = "mlx",
["Malgana"] = "vml",
["Malgbe"] = "mxf",
["Mali"] = "gcc",
["Malibu"] = "sai-mlb",
["Malila"] = "mgq",
["Malimba"] = "mzd",
["Malimpung"] = "mli",
["Malinaltepec Tlapanec"] = "tcf",
["Malol"] = "mbk",
["Maltese"] = "mt",
["Maltese Sign Language"] = "mdl",
["Malua Bay"] = "mll",
["Malvi"] = "mup",
["Maléku Jaíka"] = "gut",
["Mam"] = "mam",
["Mama"] = "mma",
["Mamaa"] = "mhf",
["Mamaindé"] = "wmd",
["Mamanwa"] = "mmn",
["Mamara"] = "myk",
["Mamasa"] = "mqj",
["Mambae"] = "mgm",
["Mambai"] = "mcs",
["Mamboru"] = "mvd",
["Mambwe-Lungu"] = "mgr",
["Mampruli"] = "maw",
["Mamuju"] = "mqx",
["Mamulique"] = "emm",
["Mamusi"] = "kdf",
["Mamvu"] = "mdi",
["Man Met"] = "mml",
["Manado Malay"] = "xmm",
["Manam"] = "mva",
["Manambu"] = "mle",
["Manangba"] = "nmm",
["Manangkari"] = "znk",
["Manao"] = "awd-man",
["Manat"] = "pmr",
["Manchu"] = "mnc",
["Manda (Australia)"] = "zma",
["Manda (India)"] = "mha",
["Manda (Tanzania)"] = "mgs",
["Mandahuaca"] = "mht",
["Mandaic"] = "mid",
["Mandailing Batak"] = "btm",
["Mandalorian"] = "art-man",
["Mandan"] = "mhq",
["Mandandanyi"] = "zmk",
["Mandar"] = "mdr",
["Mandara"] = "tbf",
["Mandari"] = "mqu",
["Mandarin"] = "cmn",
["Mandeali"] = "mjl",
["Mander"] = "mqr",
["Mandingo"] = "man",
["Mandinka"] = "mnk",
["Mandjak"] = "mfv",
["Manem"] = "jet",
["Mang"] = "zng",
["Mangala"] = "mem",
["Mangarayi"] = "mpc",
["Mangarevan"] = "mrv",
["Mangas"] = "zns",
["Mangayat"] = "myj",
["Mangbetu"] = "mdj",
["Mangbutu"] = "mdk",
["Mangerr"] = "zme",
["Mangga Buang"] = "mmo",
["Manggarai"] = "mqy",
["Mangghuer"] = "mjg-mgr",
["Mango"] = "mge",
["Mangole"] = "mqc",
["Mangseng"] = "mbh",
["Mangue"] = "mom",
["Manigri-Kambolé Ede Nago"] = "xkb",
["Manipa"] = "mqp",
["Manipuri"] = "mni",
["Mankanya"] = "knf",
["Mankiyali"] = "nlm",
["Manna-Dora"] = "mju",
["Mannan"] = "mjv",
["Mano"] = "mev",
["Manombai"] = "woo",
["Mansaka"] = "msk",
["Mansoanka"] = "msw",
["Manta"] = "myg",
["Mantsi"] = "nty",
["Manumanaw Karen"] = "kxf",
["Manus Koro"] = "kxr",
["Manusela"] = "wha",
["Manx"] = "gv",
["Manya"] = "mzj",
["Manyawa"] = "mny",
["Manza"] = "mzv",
["Mao Naga"] = "nbi",
["Maonan"] = "mmd",
["Maore Comorian"] = "swb",
["Mape"] = "mlh",
["Mapena"] = "mnm",
["Mapia"] = "mpy",
["Mapidian"] = "mpw",
["Mapos Buang"] = "bzh",
["Mapoyo"] = "mcg",
["Mapudungun"] = "arn",
["Mapun"] = "sjm",
["Mara"] = "mec",
["Mara Chin"] = "mrh",
["Marachi"] = "lri",
["Maraghei"] = "vmh",
["Maragus"] = "mrs",
["Maram Naga"] = "nma",
["Marama"] = "lrm",
["Maranao"] = "mrw",
["Maranungku"] = "zmr",
["Mararit"] = "mgb",
["Marathi"] = "mr",
["Maratino"] = "sai-mar",
["Marau"] = "mvr",
["Marawan"] = "awd-mar",
["Marba"] = "mpg",
["Marenje"] = "vmr",
["Marfa"] = "mvu",
["Margany"] = "zmc",
["Marghi South"] = "mfm",
["Margi"] = "mrt",
["Mari (Austronesian)"] = "hob",
["Mari (Sepik)"] = "mbx",
["Maria"] = "mds",
["Mariaté"] = "awd-mrt",
["Maricopa"] = "mrc",
["Maridan"] = "zmd",
["Maridjabin"] = "zmj",
["Marik"] = "dad",
["Marimanindji"] = "zmm",
["Marind"] = "mrz",
["Maring"] = "mbw",
["Maring Naga"] = "nng",
["Maringarr"] = "zmt",
["Mariri"] = "mqi",
["Maritime Sign Language"] = "nsr",
["Maritsauá"] = "msp",
["Mariupol Greek"] = "grk-mar",
["Mariyedi"] = "zmy",
["Marka"] = "rkm",
["Markweeta"] = "enb",
["Marma"] = "rmz",
["Maroon Spirit Language"] = "crp-mar",
["Marovo"] = "mvo",
["Marrgu"] = "mhg",
["Marriammu"] = "xru",
["Marrithiyel"] = "mfr",
["Marrucinian"] = "umc",
["Marshallese"] = "mh",
["Marsian"] = "ims",
["Martha's Vineyard Sign Language"] = "mre",
["Marti Ke"] = "zmg",
["Martu Wangka"] = "mpj",
["Martuthunira"] = "vma",
["Marwari"] = "mwr",
["Marúbo"] = "mzr",
["Masaba"] = "myx",
["Masadiit Itneg"] = "tis",
["Masakará"] = "sai-msk",
["Masalit"] = "mls",
["Masana"] = "mcn",
["Masbate Sorsogon"] = "bks",
["Masbatenyo"] = "msb",
["Mashco Piro"] = "cuj",
["Mashi"] = "mho",
["Masimasi"] = "ism",
["Masiwang"] = "bnf",
["Maskelynes"] = "klv",
["Maslam"] = "msv",
["Masmaje"] = "mes",
["Massachusett"] = "wam",
["Massalat"] = "mdg",
["Massep"] = "mvs",
["Matagalpa"] = "mtn",
["Matal"] = "mfh",
["Matanawi"] = "sai-mat",
["Matbat"] = "xmt",
["Matengo"] = "mgv",
["Matepi"] = "mqe",
["Matigsalug Manobo"] = "mbt",
["Matipuhy"] = "mzo",
["Matlatzinca"] = "mat",
["Mato"] = "met",
["Mator"] = "mtm",
["Matsés"] = "mcf",
["Mattole"] = "mvb",
["Matukar"] = "mjk",
["Matumbi"] = "mgw",
["Matya Samo"] = "stj",
["Matís"] = "mpq",
["Maung"] = "mph",
["Mauritian Creole"] = "mfe",
["Mauritian Sign Language"] = "lsy",
["Mauwake"] = "mhl",
["Mav̋ea"] = "mkv",
["Mawa"] = "mcw",
["Mawak"] = "mjj",
["Mawan"] = "mcz",
["Mawayana"] = "mzx",
["Mawchi"] = "mke",
["Mawes"] = "mgk",
["Maxakalí"] = "mbl",
["Maxi Gbe"] = "mxl",
["Maya Samo"] = "sym",
["Mayaguduna"] = "xmy",
["Mayangna"] = "yan",
["Mayawali"] = "yxa",
["Maybrat"] = "ayz",
["Mayeka"] = "myc",
["Mayi-Thakurti"] = "xyt",
["Maykulan"] = "mnt",
["Maynas"] = "sai-mys",
["Mayo"] = "mfy",
["Mayogo"] = "mdm",
["Mayoyao Ifugao"] = "ifu",
["Mazagway"] = "dkx",
["Mazaltepec Zapotec"] = "zpy",
["Mazanderani"] = "mzn",
["Mazatlán Mazatec"] = "vmz",
["Mazatlán Mixe"] = "mzl",
["Mba"] = "mfc",
["Mbabaram"] = "vmb",
["Mbala"] = "mdp",
["Mbalanhu"] = "lnb",
["Mbandja"] = "zmz",
["Mbangala"] = "mxg",
["Mbangi"] = "mgn",
["Mbangwe"] = "zmn",
["Mbara (Australia)"] = "mvl",
["Mbara (Chad)"] = "mpk",
["Mbariman-Gudhinma"] = "zmv",
["Mbati"] = "mdn",
["Mbato"] = "gwa",
["Mbay"] = "myb",
["Mbe"] = "mfo",
["Mbe'"] = "mtk",
["Mbelime"] = "mql",
["Mbere"] = "mdt",
["Mbesa"] = "zms",
["Mbiywom"] = "aus-mbi",
["Mbo (Cameroon)"] = "mbo",
["Mbo (Congo)"] = "zmw",
["Mboi"] = "moi",
["Mboko"] = "mdu",
["Mbole"] = "mdq",
["Mbonga"] = "xmb",
["Mbongno"] = "bgu",
["Mbosi"] = "mdw",
["Mbowe"] = "mxo",
["Mbre"] = "mka",
["Mbu'"] = "muc",
["Mbudum"] = "xmd",
["Mbugu"] = "mhd",
["Mbugwe"] = "mgz",
["Mbuko"] = "mqb",
["Mbukushu"] = "mhw",
["Mbula"] = "mna",
["Mbula-Bwazza"] = "mbu",
["Mbule"] = "mlb",
["Mbulungish"] = "mbv",
["Mbum"] = "mdd",
["Mbunda"] = "mck",
["Mbunga"] = "mgy",
["Mburku"] = "bbt",
["Mbuun"] = "zmp",
["Mbwela"] = "mfu",
["Mbya Guarani"] = "gun",
["Me'en"] = "mym",
["Mebu"] = "mjn",
["Mecayapan Nahuatl"] = "nhx",
["Medebur"] = "mjm",
["Medefaidrin"] = "dmf",
["Media Lengua"] = "mue",
["Mednyj Aleut"] = "mud",
["Medumba"] = "byv",
["Mefele"] = "mfj",
["Megam"] = "mef",
["Megleno-Romanian"] = "ruq",
["Mehek"] = "nux",
["Mehináku"] = "mmh",
["Mehri"] = "gdq",
["Mekeo"] = "mek",
["Mekmek"] = "mvk",
["Mekwei"] = "msf",
["Mekéns"] = "skf",
["Mel-Khaonh"] = "hkn",
["Mele-Fila"] = "mxe",
["Melo"] = "mfx",
["Melpa"] = "med",
["Memoni"] = "mby",
["Mendalam Kayan"] = "xkd",
["Mendankwe-Nkwen"] = "mfd",
["Mende (New Guinea)"] = "sim",
["Mende (Sierra Leone)"] = "men",
["Mengaka"] = "xmg",
["Mengen"] = "mee",
["Mengisa"] = "leo",
["Menien"] = "sai-men",
["Menka"] = "mea",
["Menominee"] = "mez",
["Mentawai"] = "mwv",
["Menya"] = "mcr",
["Meoswar"] = "mvx",
["Mer"] = "mnu",
["Meramera"] = "mxm",
["Merei"] = "lmb",
["Merey"] = "meq",
["Meriam"] = "ulk",
["Meroitic"] = "xmr",
["Meru"] = "mer",
["Mesaka"] = "iyo",
["Mese"] = "mci",
["Mesme"] = "zim",
["Mesmes"] = "mys",
["Mesqan"] = "mvz",
["Messapic"] = "cms",
["Meta'"] = "mgo",
["Metlatónoc Mixtec"] = "mxv",
["Mewari"] = "mtr",
["Mewati"] = "wtm",
["Mexican Sign Language"] = "mfs",
["Meyah"] = "mej",
["Mezontla Popoloca"] = "pbe",
["Mezquital Otomi"] = "ote",
["Meänkieli"] = "fit",
["Mfinu"] = "zmf",
["Mfumte"] = "nfu",
["Mgbo"] = "gmz",
["Mi'kmaq"] = "mic",
["Miami"] = "mia",
["Mian"] = "mpt",
["Miani"] = "pla",
["Micha"] = "yiq",
["Michif"] = "crg",
["Michigamea"] = "cmm",
["Michoacán Mazahua"] = "mmc",
["Michoacán Nahuatl"] = "ncl",
["Mid Grand Valley Dani"] = "dnt",
["Mid-Southern Banda"] = "bjo",
["Middle Armenian"] = "axm",
["Middle Assamese"] = "inc-mas",
["Middle Bengali"] = "inc-mbn",
["Middle Breton"] = "xbm",
["Middle Chinese"] = "ltc",
["Middle Cornish"] = "cnx",
["Middle Dutch"] = "dum",
["Middle English"] = "enm",
["Middle French"] = "frm",
["Middle Gujarati"] = "inc-mgu",
["Middle High German"] = "gmh",
["Middle Irish"] = "mga",
["Middle Kannada"] = "dra-mkn",
["Middle Khmer"] = "xhm",
["Middle Korean"] = "okm",
["Middle Low German"] = "gml",
["Middle Median"] = "xme-mid",
["Middle Mon"] = "mkh-mmn",
["Middle Mongol"] = "xng",
["Middle Newar"] = "nwx",
["Middle Norwegian"] = "gmq-mno",
["Middle Odia"] = "inc-mor",
["Middle Persian"] = "pal",
["Middle Scots"] = "gmw-msc",
["Middle Vietnamese"] = "mkh-mvi",
["Middle Watut"] = "mpl",
["Middle Welsh"] = "wlm",
["Midob"] = "mei",
["Migaama"] = "mmy",
["Migabac"] = "mpp",
["Miji"] = "sjl",
["Miju"] = "mxj",
["Mikasuki"] = "mik",
["Milang"] = "tbq-mil",
["Mili"] = "ymh",
["Millcayac"] = "sai-mil",
["Miltu"] = "mlj",
["Miluk"] = "iml",
["Milyan"] = "imy",
["Mimi of Decorse"] = "mis-mmd",
["Mimi of Nachtigal"] = "mis-mmn",
["Min Nan"] = "nan",
["Mina"] = "hna",
["Minaean"] = "inm",
["Minang"] = "xrg",
["Minangkabau"] = "min",
["Minaveha"] = "mvn",
["Minderico"] = "drc",
["Mindiri"] = "mpn",
["Mingang Doso"] = "mko",
["Mingo"] = "iro-min",
["Mingrelian"] = "xmf",
["Minica Huitoto"] = "hto",
["Minidien"] = "wii",
["Minjungbal"] = "xjb",
["Minkin"] = "xxm",
["Minoan"] = "omn",
["Minokok"] = "mqq",
["Minriq"] = "mnq",
["Mintil"] = "mzt",
["Mirandese"] = "mwl",
["Mire"] = "mvh",
["Mirgan"] = "zrg",
["Miriti"] = "mmv",
["Miriwoong"] = "mep",
["Miriwoong Sign Language"] = "rsm",
["Mirning"] = "gmr",
["Mirpur Panjabi"] = "pmu",
["Misantla Totonac"] = "tlc",
["Miship"] = "mjs",
["Misima-Paneati"] = "mpx",
["Mising"] = "mrg",
["Miskito"] = "miq",
["Mitla Zapotec"] = "zaw",
["Mitlatongo Mixtec"] = "vmm",
["Mittu"] = "mwu",
["Mituku"] = "zmq",
["Miu"] = "mpo",
["Miwa"] = "vmi",
["Mixed Great Andamanese"] = "gac",
["Mixifore"] = "mfg",
["Mixtepec Mixtec"] = "mix",
["Mixtepec Zapotec"] = "zpm",
["Miya"] = "mkf",
["Miyako"] = "mvi",
["Miyobe"] = "soy",
["Mizo"] = "lus",
["Mlabri"] = "mra",
["Mlahsö"] = "lhs",
["Mlap"] = "kja",
["Mlomp"] = "mlo",
["Mmaala"] = "mmu",
["Mmani"] = "buy",
["Mmen"] = "bfm",
["Mo"] = "wkd",
["Mo'da"] = "gbn",
["Moabite"] = "obm",
["Moba"] = "mfq",
["Mobilian"] = "mod",
["Mobu"] = "ahm",
["Mocana"] = "sai-mcn",
["Mochi"] = "old",
["Mochica"] = "omc",
["Mocho"] = "mhc",
["Mocoví"] = "moc",
["Modang"] = "mxd",
["Modole"] = "mqo",
["Moere"] = "mvq",
["Mofu-Gudur"] = "mif",
["Mogholi"] = "mhj",
["Mogum"] = "mou",
["Mohawk"] = "moh",
["Mohegan-Pequot"] = "xpq",
["Moi (Congo)"] = "mow",
["Moi (Indonesia)"] = "mxn",
["Moikodi"] = "mkp",
["Moingi"] = "mwz",
["Mojave"] = "mov",
["Moji"] = "ymi",
["Mok"] = "mqt",
["Mokati"] = "wnb",
["Moken"] = "mwt",
["Mokerang"] = "mft",
["Mokilese"] = "mkj",
["Moklen"] = "mkm",
["Mokole"] = "mkl",
["Mokpwe"] = "bri",
["Moksha"] = "mdf",
["Molale"] = "mbe",
["Molbog"] = "pwm",
["Moldova Sign Language"] = "vsi",
["Molengue"] = "bxc",
["Molima"] = "mox",
["Molmo One"] = "aun",
["Molo"] = "zmo",
["Molof"] = "msl",
["Moloko"] = "mlw",
["Mom Jango"] = "ver",
["Moma"] = "myl",
["Momare"] = "msz",
["Mombo Dogon"] = "dmb",
["Mombum"] = "mso",
["Momina"] = "mmb",
["Momuna"] = "mqf",
["Mon"] = "mnw",
["Monastic Sign Language"] = "mzg",
["Mondropolon"] = "npn",
["Mondé"] = "mnd",
["Mongghul"] = "mjg-mgl",
["Mongo"] = "lol",
["Mongolian"] = "mn",
["Mongolian Sign Language"] = "msr",
["Mongondow"] = "mog",
["Mongsen Ao"] = "njo-mng",
["Moni"] = "mnz",
["Mono (California)"] = "mnr",
["Mono (Cameroon)"] = "mru",
["Mono (Congo)"] = "mnh",
["Monom"] = "moo",
["Monsang Naga"] = "nmh",
["Montagnais"] = "moe",
["Montana Salish"] = "fla",
["Montol"] = "mtl",
["Monumbo"] = "mxk",
["Monzombo"] = "moj",
["Moo"] = "gwg",
["Moore"] = "mos",
["Moose Cree"] = "crm",
["Mopan Maya"] = "mop",
["Mor (Austronesian)"] = "mhz",
["Mor (Papuan)"] = "moq",
["Moraid"] = "msg",
["Moran"] = "tbq-mor",
["Morawa"] = "mze",
["Morelos Nahuatl"] = "nhm",
["Morerebi"] = "xmo",
["Moresada"] = "msx",
["Mori Atas"] = "mzq",
["Mori Bawah"] = "xmz",
["Morigi"] = "mdb",
["Moriori"] = "rrm",
["Moro"] = "mor",
["Moroccan Amazigh"] = "zgh",
["Moroccan Arabic"] = "ary",
["Moroccan Sign Language"] = "xms",
["Morokodo"] = "mgc",
["Morom"] = "bdo",
["Moronene"] = "mqn",
["Morori"] = "mok",
["Morouas"] = "mrp",
["Mortlockese"] = "mrl",
["Moru"] = "mgd",
["Mosimo"] = "mqv",
["Moskona"] = "mtj",
["Mota"] = "mtt",
["Motembo"] = "tmv",
["Motu"] = "meu",
["Mouk-Aria"] = "mwh",
["Mount Iraya Agta"] = "atl",
["Mount Iriga Agta"] = "agz",
["Mountain Koiari"] = "kpx",
["Mouwase"] = "jmw",
["Movima"] = "mzp",
["Moyadan Itneg"] = "ity",
["Moyon Naga"] = "nmo",
["Mozambican Sign Language"] = "mzy",
["Mozarabic"] = "mxi",
["Mpade"] = "mpi",
["Mpalitjanh"] = "xpj",
["Mpi"] = "mpz",
["Mpiemo"] = "mcx",
["Mpiin"] = "bnt-mpi",
["Mpinda"] = "pnd",
["Mpongmpong"] = "mgg",
["Mpoto"] = "mpa",
["Mpotovoro"] = "mvt",
["Mpuono"] = "bnt-mpu",
["Mpur"] = "akc",
["Mro Chin"] = "cmr",
["Mru"] = "mro",
["Mser"] = "kqx",
["Muak Sa-aak"] = "ukk",
["Mualang"] = "mtd",
["Mubami"] = "tsx",
["Mubi"] = "mub",
["Mucuchí"] = "sai-muc",
["Muda"] = "ymd",
["Mudburra"] = "dmw",
["Mudu Koraga"] = "vmd",
["Muduapa"] = "wiv",
["Muduga"] = "udg",
["Muellama"] = "sai-mue",
["Mufian"] = "aoj",
["Muher"] = "sem-mhr",
["Muinane"] = "bmr",
["Mukha-Dora"] = "mmk",
["Mukulu"] = "moz",
["Mulaha"] = "mfw",
["Mulam"] = "mlm",
["Mulao"] = "giu",
["Mullu Kurumba"] = "kpb",
["Mullukmulluk"] = "mpb",
["Muluridyi"] = "vmu",
["Mum"] = "kqa",
["Mumuye"] = "mzm",
["Muna"] = "mnb",
["Munda"] = "unx",
["Mundabli"] = "boe",
["Mundang"] = "mua",
["Mundani"] = "mnf",
["Mundari"] = "unr",
["Mundat"] = "mmf",
["Mundolinco"] = "art-mun",
["Mundurukú"] = "myu",
["Mungaka"] = "mhk",
["Mungbam"] = "mij",
["Munggui"] = "mth",
["Mungkip"] = "mpv",
["Muniche"] = "myr",
["Munit"] = "mtc",
["Munji"] = "mnj",
["Munsee"] = "umu",
["Muong"] = "mtq",
["Mur Pano"] = "tkv",
["Muratayak"] = "asx",
["Murik (Malaysia)"] = "mxr",
["Murik (New Guinea)"] = "mtf",
["Murkim"] = "rmh",
["Murle"] = "mur",
["Murrinh-Patha"] = "mwf",
["Mursi"] = "muz",
["Murui Huitoto"] = "huu",
["Murupi"] = "mqw",
["Muruwari"] = "zmu",
["Musan"] = "mmp",
["Musasa"] = "smm",
["Musey"] = "mse",
["Musgu"] = "mug",
["Musi"] = "mui",
["Muskum"] = "mje",
["Musom"] = "msu",
["Mussau-Emira"] = "emi",
["Muthuvan"] = "muv",
["Mutu"] = "tuc",
["Muya"] = "mvm",
["Muyang"] = "muy",
["Muyuw"] = "myw",
["Muzi"] = "ymz",
["Muzo"] = "sai-muz",
["Mvanip"] = "mcj",
["Mvuba"] = "mxh",
["Mwaghavul"] = "sur",
["Mwakai"] = "mgt",
["Mwali Comorian"] = "wlc",
["Mwan"] = "moa",
["Mwani"] = "wmw",
["Mwatebu"] = "mwa",
["Mwera"] = "mwe",
["Mwerlap"] = "mrm",
["Mwimbi-Muthambi"] = "mws",
["Mwotlap"] = "mlv",
["Mycenaean Greek"] = "gmy",
["Myene"] = "mye",
["Mysian"] = "yms",
["Mzieme Naga"] = "nme",
["Mághdì"] = "gmd",
["Mòcheno"] = "mhn",
["Mün Chin"] = "mwq",
["Mündü"] = "muh",
["Māori"] = "mi",
["Mạ"] = "cma",
["N'Ko"] = "nqo",
["Na"] = "nbt",
["Naaba"] = "nao",
["Naba"] = "mne",
["Nabak"] = "naf",
["Nabi"] = "mty",
["Nachering"] = "ncd",
["Nadruvian"] = "ndf",
["Nadëb"] = "mbj",
["Nafaanra"] = "nfr",
["Nafi"] = "srf",
["Nafri"] = "nxx",
["Naga Pidgin"] = "nag",
["Nagarchal"] = "nbg",
["Nage"] = "nxe",
["Nagtipunan Agta"] = "phi-nag",
["Nagu"] = "ngr",
["Nagumi"] = "ngv",
["Nahali"] = "nlx",
["Nahari"] = "nhh",
["Nahavaq"] = "sns",
["Nahuatl"] = "nah",
["Nai"] = "bio",
["Najdi Arabic"] = "ars",
["Naka'ela"] = "nae",
["Nakai"] = "nkj",
["Nakame"] = "nib",
["Nakanai"] = "nak",
["Nakara"] = "nck",
["Nake"] = "nbk",
["Naki"] = "mff",
["Nakwi"] = "nax",
["Nalca"] = "nlc",
["Nali"] = "nss",
["Nalik"] = "nal",
["Nalu"] = "naj",
["Nalögo"] = "nlz",
["Nama"] = "nmx",
["Namakura"] = "nmk",
["Namat"] = "nkm",
["Nambikwara"] = "nab",
["Nambo"] = "ncm",
["Nambya"] = "nmq",
["Namia"] = "nnm",
["Namiae"] = "nvm",
["Namibian Sign Language"] = "nbs",
["Namla"] = "naa",
["Namo"] = "mxw",
["Namonuito"] = "nmt",
["Namosi-Naitasiri-Serua"] = "bwb",
["Namuyi"] = "nmy",
["Nanai"] = "gld",
["Nancere"] = "nnc",
["Nande"] = "nnb",
["Nandi"] = "niq",
["Nanerige"] = "sen",
["Nanga Dama Dogon"] = "nzz",
["Nankina"] = "nnk",
["Nanti"] = "cox",
["Nanticoke"] = "nnt",
["Nanubae"] = "afk",
["Naolan"] = "nai-nao",
["Napu"] = "npy",
["Nar Phu"] = "npa",
["Nara"] = "nrb",
["Narak"] = "nac",
["Narango"] = "nrg",
["Narim"] = "loh",
["Naro"] = "nhr",
["Narom"] = "nrm",
["Narragansett"] = "xnt",
["Narua"] = "nru",
["Narungga"] = "nnr",
["Naruo"] = "ylo",
["Nasal"] = "nsy",
["Nasarian"] = "nvh",
["Nasioi"] = "nas",
["Naskapi"] = "nsk",
["Nasu"] = "ywq",
["Natagaimas"] = "nts",
["Natchez"] = "ncz",
["Nateni"] = "ntm",
["Natioro"] = "nti",
["Natú"] = "sai-nat",
["Natügu"] = "ntu",
["Nauete"] = "nxa",
["Naukanski"] = "ynk",
["Nauna"] = "ncn",
["Nauo"] = "nwo",
["Nauruan"] = "na",
["Navajo"] = "nv",
["Navut"] = "nsw",
["Nawaru"] = "nwr",
["Nawathinehena"] = "nwa",
["Nawdm"] = "nmz",
["Nawuri"] = "naw",
["Naxi"] = "nxq",
["Nayi"] = "noz",
["Naʼvi"] = "art-nav",
["Ncane"] = "ncr",
["Nchumbulu"] = "nlu",
["Nda'nda'"] = "nnz",
["Ndai"] = "gke",
["Ndaka"] = "ndk",
["Ndali"] = "ndh",
["Ndam"] = "ndm",
["Ndamba"] = "ndj",
["Ndambomo"] = "nxo",
["Ndasa"] = "nda",
["Ndau"] = "ndc",
["Nde-Gbite"] = "ned",
["Nde-Nsele-Nta"] = "ndd",
["Ndemli"] = "nml",
["Ndendeule"] = "dne",
["Ndengereko"] = "ndg",
["Nding"] = "eli",
["Ndjébbana"] = "djj",
["Ndo"] = "ndp",
["Ndobo"] = "ndw",
["Ndoe"] = "nbb",
["Ndogo"] = "ndz",
["Ndolo"] = "ndl",
["Ndom"] = "nqm",
["Ndombe"] = "ndq",
["Ndonga"] = "ng",
["Ndoola"] = "ndr",
["Ndrulo"] = "dno",
["Nduga"] = "ndx",
["Ndumu"] = "nmd",
["Ndunda"] = "nuh",
["Ndunga"] = "ndt",
["Ndut"] = "ndv",
["Ndyuka-Trio Pidgin"] = "njt",
["Ndzwani Comorian"] = "wni",
["Neapolitan"] = "nap",
["Nedebang"] = "nec",
["Nefamese"] = "nef",
["Nefusa"] = "jbn",
["Negerhollands"] = "dcr",
["Negeri Sembilan Malay"] = "zmi",
["Negidal"] = "neg",
["Nehan"] = "nsn",
["Nek"] = "nif",
["Nekgini"] = "nkg",
["Neko"] = "nej",
["Neku"] = "nek",
["Neme"] = "nex",
["Nemi"] = "nem",
["Nen"] = "nqn",
["Nend"] = "anh",
["Nengone"] = "nen",
["Neo"] = "neu",
["Nepalese Sign Language"] = "nsp",
["Nepali"] = "ne",
["Nese"] = "poz-nes",
["Nete"] = "net",
["Neve'ei"] = "vnm",
["Neverver"] = "lgk",
["New Caledonian Javanese"] = "jas",
["New River Shasta"] = "nai-nrs",
["New Zealand Sign Language"] = "nzs",
["Newar"] = "new",
["Neyo"] = "ney",
["Nez Perce"] = "nez",
["Nga La"] = "hlt",
["Ngaanyatjarra"] = "ntj",
["Ngadha"] = "nxg",
["Ngadjunmaya"] = "nju",
["Ngadjuri"] = "jui",
["Ngaiawang"] = "nwg",
["Ngaing"] = "nnf",
["Ngaju"] = "nij",
["Ngala"] = "nud",
["Ngalakan"] = "nig",
["Ngalkbun"] = "ngk",
["Ngalum"] = "szb",
["Ngam"] = "nmc",
["Ngamambo"] = "nbv",
["Ngambay"] = "sba",
["Ngamini"] = "nmv",
["Ngamo"] = "nbh",
["Ngan'gityemerri"] = "nam",
["Nganakarti"] = "xnk",
["Nganasan"] = "nio",
["Ngandi"] = "nid",
["Ngando (Central African Republic)"] = "ngd",
["Ngando (Congo)"] = "nxd",
["Ngandyera"] = "nne",
["Ngangam"] = "gng",
["Ngantangarra"] = "ntg",
["Nganyaywana"] = "nyx",
["Ngardi"] = "rxd",
["Ngarigu"] = "xni",
["Ngarinman"] = "nbj",
["Ngarinyin"] = "ung",
["Ngarla"] = "nrk",
["Ngarluma"] = "nrl",
["Ngarrindjeri"] = "nay",
["Ngas"] = "anc",
["Ngasa"] = "nsg",
["Ngatik Men's Creole"] = "ngm",
["Ngawn Chin"] = "cnw",
["Ngawun"] = "nxn",
["Ngazidja Comorian"] = "zdj",
["Ngbaka"] = "nga",
["Ngbaka Ma'bo"] = "nbm",
["Ngbaka Manza"] = "ngg",
["Ngbee"] = "jgb",
["Ngbinda"] = "nbd",
["Ngbundu"] = "nuu",
["Ngelima"] = "agh",
["Ngemba"] = "nge",
["Ngen of Djonkro"] = "gnj",
["Ngendelengo"] = "nql",
["Ngeq"] = "ngt",
["Ngete"] = "nnn",
["Nggem"] = "nbq",
["Nggwahyi"] = "ngx",
["Ngie"] = "ngj",
["Ngiemboon"] = "nnh",
["Ngile"] = "jle",
["Ngindo"] = "nnq",
["Ngiti"] = "niy",
["Ngiyambaa"] = "wyb",
["Ngizim"] = "ngi",
["Ngkoth"] = "aus-ngk",
["Ngkâlmpw Kanum"] = "kcd",
["Ngochang"] = "tbq-ngo",
["Ngom"] = "nra",
["Ngomba"] = "jgo",
["Ngombale"] = "nla",
["Ngombe (Central African Republic)"] = "nmj",
["Ngombe (Congo)"] = "ngc",
["Ngong"] = "nnx",
["Ngongo"] = "noq",
["Ngoni"] = "ngo",
["Ngoreme"] = "ngq",
["Ngoshie"] = "nsh",
["Ngulu"] = "ngp",
["Nguluwan"] = "nuw",
["Ngumbi"] = "nui",
["Ngunawal"] = "xul",
["Ngundi"] = "ndn",
["Ngundu"] = "nue",
["Ngungwel"] = "ngz",
["Ngurmbur"] = "nrx",
["Nguôn"] = "nuo",
["Ngwaba"] = "ngw",
["Ngwe"] = "nwe",
["Ngwi"] = "nlo",
["Ngwo"] = "ngn",
["Ngäbere"] = "gym",
["Nhanda"] = "nha",
["Nheengatu"] = "yrl",
["Nhirrpi"] = "hrp",
["Nhuwala"] = "nhf",
["Nias"] = "nia",
["Nicaraguan Creole"] = "bzk",
["Nicaraguan Sign Language"] = "ncs",
["Nicola"] = "ath-nic",
["Nicoleño"] = "azc-nic",
["Niellim"] = "nie",
["Nigeria Mambila"] = "mzk",
["Nigerian Pidgin"] = "pcm",
["Nigerian Sign Language"] = "nsi",
["Nihali"] = "nll",
["Nii"] = "nii",
["Niksek"] = "gbe",
["Nila"] = "nil",
["Nilamba"] = "nim",
["Nimadi"] = "noe",
["Nimanbur"] = "nmp",
["Nimbari"] = "nmr",
["Nimboran"] = "nir",
["Nimi"] = "nis",
["Nimo"] = "niw",
["Nimoa"] = "nmw",
["Ninam"] = "shb",
["Nindi"] = "nxi",
["Ningera"] = "nby",
["Ninggerum"] = "nxr",
["Ningil"] = "niz",
["Ninia Yali"] = "nlk",
["Ninzo"] = "nin",
["Nipsan"] = "nps",
["Nisa"] = "njs",
["Nisenan"] = "nsz",
["Nisga'a"] = "ncg",
["Nisi"] = "yso",
["Niuafo'ou"] = "num",
["Niuatoputapu"] = "nkp",
["Niuean"] = "niu",
["Nivaclé"] = "cag",
["Nivkh"] = "niv",
["Niwer Mil"] = "hrc",
["Niya Prakrit"] = "pra-niy",
["Njalgulgule"] = "njl",
["Njebi"] = "nzb",
["Njen"] = "njj",
["Njerep"] = "njr",
["Njyem"] = "njy",
["Nkami"] = "nkq",
["Nkangala"] = "nkn",
["Nkari"] = "nkz",
["Nkem-Nkum"] = "isi",
["Nkhumbi"] = "khu",
["Nkongho"] = "nkc",
["Nkonya"] = "nko",
["Nkoroo"] = "nkx",
["Nkoya"] = "nka",
["Nkukoli"] = "nbo",
["Nkutu"] = "nkw",
["Nnam"] = "nbp",
["Noakhali"] = "oak",
["Nobiin"] = "fia",
["Nobonob"] = "gaw",
["Nocte"] = "njb",
["Nogai"] = "nog",
["Noipä"] = "npx",
["Noiri"] = "noi",
["Nokuku"] = "nkk",
["Nomaande"] = "lem",
["Nomane"] = "nof",
["Nomatsiguenga"] = "not",
["Nomlaki"] = "nol",
["Nomu"] = "noh",
["Nong Zhuang"] = "zhn",
["Nonuya"] = "noj",
["Nooksack"] = "nok",
["Noon"] = "snf",
["Noone"] = "nhu",
["Nootka"] = "nuk",
["Nopala Chatino"] = "cya",
["Noric"] = "nrc",
["Norman"] = "nrf",
["Norn"] = "nrn",
["Norra"] = "nrr",
["North Ambrym"] = "mmg",
["North Asmat"] = "nks",
["North Awyu"] = "yir",
["North Babar"] = "bcd",
["North Boma"] = "boh",
["North Central Mixe"] = "neq",
["North Efate"] = "llp",
["North Fali"] = "fll",
["North Frisian"] = "frr",
["North Giziga"] = "gis",
["North Levantine Arabic"] = "apc",
["North Marquesan"] = "mrq",
["North Mesopotamian Arabic"] = "ayp",
["North Mofu"] = "mfk",
["North Moluccan Malay"] = "max",
["North Muyu"] = "kti",
["North Nuaulu"] = "nni",
["North Picene"] = "nrp",
["North Slavey"] = "scs",
["North Tairora"] = "tbg",
["North Tanna"] = "tnn",
["North Tukang Besi"] = "khc",
["North Wahgi"] = "whg",
["North Watut"] = "una",
["Northeast Kiwai"] = "kiw",
["Northeast Maidu"] = "nmu",
["Northeast Malakula"] = "upv",
["Northeast Pashayi"] = "aee",
["Northeastern Dinka"] = "dip",
["Northeastern Pomo"] = "pef",
["Northern Alta"] = "aqn",
["Northern Altai"] = "atv",
["Northern Amami Ōshima"] = "ryn",
["Northern Bontoc"] = "rbk",
["Northern Catanduanes Bikol"] = "cts",
["Northern Dagara"] = "dgi",
["Northern East Cree"] = "crl",
["Northern Emberá"] = "emp",
["Northern Ghale"] = "ghh",
["Northern Grebo"] = "gbo",
["Northern Guiyang Hmong"] = "huj",
["Northern Haida"] = "hdn",
["Northern Hindko"] = "hno",
["Northern Huishui Hmong"] = "hmi",
["Northern Kalapuya"] = "nrt",
["Northern Kam"] = "doc",
["Northern Khanty"] = "kca-nor",
["Northern Khmer"] = "kxm",
["Northern Kissi"] = "kqs",
["Northern Kurdish"] = "kmr",
["Northern Lorung"] = "lbr",
["Northern Luri"] = "lrc",
["Northern Mansi"] = "mns-nor",
["Northern Mashan Hmong"] = "hmp",
["Northern Min"] = "mnp",
["Northern Muji"] = "ymx",
["Northern Ndebele"] = "nd",
["Northern Ngbandi"] = "ngb",
["Northern Nisu"] = "yiv",
["Northern Nuni"] = "nuv",
["Northern Oaxaca Nahuatl"] = "nhy",
["Northern Ohlone"] = "cst",
["Northern One"] = "onr",
["Northern Paiute"] = "pao",
["Northern Pame"] = "pmq",
["Northern Pinghua"] = "cnp",
["Northern Pomo"] = "pej",
["Northern Puebla Nahuatl"] = "ncj",
["Northern Pumi"] = "pmi",
["Northern Pwo"] = "pww",
["Northern Qiandong Miao"] = "hea",
["Northern Qiang"] = "cng",
["Northern Rengma Naga"] = "nnl",
["Northern Roglai"] = "rog",
["Northern Saharan Berber"] = "mzb",
["Northern Sami"] = "se",
["Northern Selkup"] = "sel-nor",
["Northern Sierra Miwok"] = "nsq",
["Northern Sotho"] = "nso",
["Northern Subanen"] = "stb",
["Northern Tarahumara"] = "thh",
["Northern Tepehuan"] = "ntp",
["Northern Thai"] = "nod",
["Northern Tidung"] = "ntd",
["Northern Tlaxiaco Mixtec"] = "xtn",
["Northern Toussian"] = "tsp",
["Northern Tujia"] = "tji",
["Northern Tutchone"] = "ttm",
["Northern Valley Yokuts"] = "yok-nvy",
["Northern Yukaghir"] = "ykg",
["Northwest Gbaya"] = "gya",
["Northwest Maidu"] = "mjd",
["Northwest Oaxaca Mixtec"] = "mxa",
["Northwest Pashayi"] = "glh",
["Northwestern Dinka"] = "diw",
["Northwestern Fars"] = "faz",
["Northwestern Nisu"] = "nsf",
["Northwestern Ojibwa"] = "ojb",
["Norwegian"] = "no",
["Norwegian Bokmål"] = "nb",
["Norwegian Nynorsk"] = "nn",
["Norwegian Sign Language"] = "nsl",
["Notre"] = "bly",
["Notsi"] = "ncf",
["Nottoway"] = "ntw",
["Nottoway-Meherrin"] = "nwy",
["Novial"] = "nov",
["Noy"] = "noy",
["Nsari"] = "asj",
["Nsenga"] = "nse",
["Nshi"] = "nsc",
["Nsong"] = "soo",
["Nsongo"] = "nsx",
["Ntcham"] = "bud",
["Ntomba"] = "nto",
["Ntra'ngith"] = "dgt",
["Nubaca"] = "baf",
["Nubi"] = "kcn",
["Nuer"] = "nus",
["Nuguria"] = "nur",
["Nuk"] = "noc",
["Nukak Makú"] = "mbr",
["Nukna"] = "klt",
["Nukuini"] = "nuc",
["Nukumanu"] = "nuq",
["Nukunu"] = "nnv",
["Nukunul"] = "xnu",
["Nukuoro"] = "nkr",
["Numana"] = "nbr",
["Numanggang"] = "nop",
["Numbami"] = "sij",
["Nume"] = "tgs",
["Numidian"] = "nxm",
["Numèè"] = "kdk",
["Nungali"] = "nug",
["Nunggubuyu"] = "nuy",
["Nungon"] = "paa-nun",
["Nungu"] = "rin",
["Nuosu"] = "ii",
["Nupbikha"] = "npb",
["Nupe"] = "nup",
["Nusa Laut"] = "nul",
["Nusu"] = "nuf",
["Nutabe"] = "cba-nut",
["Nyabwa"] = "nwb",
["Nyagrong Minyag"] = "ero-nya",
["Nyah Kur"] = "cbn",
["Nyaheun"] = "nev",
["Nyakyusa"] = "nyy",
["Nyali"] = "nlj",
["Nyam"] = "nmi",
["Nyamal"] = "nly",
["Nyambo"] = "now",
["Nyamusa-Molo"] = "nwm",
["Nyamwanga"] = "mwn",
["Nyamwezi"] = "nym",
["Nyaneka"] = "nyk",
["Nyang'i"] = "nyp",
["Nyanga (Congo)"] = "nyj",
["Nyanga (Togo)"] = "ayg",
["Nyanga-li"] = "nyc",
["Nyangatom"] = "nnj",
["Nyangbo"] = "nyb",
["Nyangga"] = "nny",
["Nyangumarta"] = "nna",
["Nyankole"] = "nyn",
["Nyarafolo"] = "sev",
["Nyaturu"] = "rim",
["Nyaw"] = "nyw",
["Nyawaygi"] = "nyt",
["Nyelâyu"] = "yly",
["Nyemba"] = "nba",
["Nyengo"] = "nye",
["Nyenkha"] = "neh",
["Nyeu"] = "nyl",
["Nyigina"] = "nyh",
["Nyiha"] = "nih",
["Nyika"] = "nkt",
["Nyimang"] = "nyi",
["Nyindrou"] = "lid",
["Nyindu"] = "nyg",
["Nyishi"] = "njz",
["Nyiyaparli"] = "xny",
["Nyokon"] = "nvo",
["Nyole (Kenya)"] = "nyd",
["Nyole (Uganda)"] = "nuj",
["Nyong"] = "muo",
["Nyoro"] = "nyo",
["Nyulnyul"] = "nyv",
["Nyunga"] = "nys",
["Nyungwe"] = "nyu",
["Nzadi"] = "nzd",
["Nzakambay"] = "nzy",
["Nzakara"] = "nzk",
["Nzanyi"] = "nja",
["Nzima"] = "nzi",
["Ná-Meo"] = "neo",
["Nùng"] = "nut",
["Nüpode Huitoto"] = "hux",
["Nǀuu"] = "ngh",
["O'chi'chi'"] = "xoc",
["O'du"] = "tyh",
["O'odham"] = "ood",
["Obanliku"] = "bzy",
["Obispeño"] = "obi",
["Oblo"] = "obl",
["Obo Manobo"] = "obo",
["Obokuitai"] = "afz",
["Obolo"] = "ann",
["Obulom"] = "obu",
["Ocaina"] = "oca",
["Occitan"] = "oc",
["Ocotepec Mixtec"] = "mie",
["Ocotlán Zapotec"] = "zac",
["Od"] = "odk",
["Odia"] = "or",
["Odiai"] = "bhf",
["Odoodee"] = "kkc",
["Odual"] = "odu",
["Odut"] = "oda",
["Ofayé"] = "opy",
["Ofo"] = "ofo",
["Ogbah"] = "ogc",
["Ogbia"] = "ogb",
["Ogbogolo"] = "ogg",
["Ogbronuagum"] = "ogu",
["Ogea"] = "eri",
["Oirata"] = "oia",
["Ojibwe"] = "oj",
["Ojitlán Chinantec"] = "chj",
["Okanagan"] = "oka",
["Okiek"] = "oki",
["Okinawan"] = "ryu",
["Okinoerabu"] = "okn",
["Oko-Eni-Osayen"] = "oks",
["Oko-Juwoi"] = "okj",
["Okobo"] = "okb",
["Okodia"] = "okd",
["Okolod"] = "kqv",
["Okpamheri"] = "opa",
["Okpe (Northwestern Edo)"] = "okx",
["Okpe (Southwestern Edo)"] = "oke",
["Okpela"] = "atg",
["Oksapmin"] = "opm",
["Oku"] = "oku",
["Okwanuchu"] = "nai-okw",
["Old Anatolian Turkish"] = "trk-oat",
["Old Armenian"] = "xcl",
["Old Avar"] = "oav",
["Old Awadhi"] = "inc-oaw",
["Old Bengali"] = "inc-obn",
["Old Breton"] = "obt",
["Old Burmese"] = "obr",
["Old Catalan"] = "roa-oca",
["Old Cham"] = "ocm",
["Old Chinese"] = "och",
["Old Church Slavonic"] = "cu",
["Old Cornish"] = "oco",
["Old Czech"] = "zlw-ocs",
["Old Danish"] = "gmq-oda",
["Old Dutch"] = "odt",
["Old East Slavic"] = "orv",
["Old English"] = "ang",
["Old French"] = "fro",
["Old Frisian"] = "ofs",
["Old Galician-Portuguese"] = "roa-opt",
["Old Georgian"] = "oge",
["Old Gujarati"] = "inc-ogu",
["Old Gutnish"] = "gmq-ogt",
["Old High German"] = "goh",
["Old Hindi"] = "inc-ohi",
["Old Hungarian"] = "ohu",
["Old Irish"] = "sga",
["Old Japanese"] = "ojp",
["Old Javanese"] = "kaw",
["Old Kannada"] = "dra-okn",
["Old Kentish Sign Language"] = "okl",
["Old Khmer"] = "okz",
["Old Komi"] = "urj-koo",
["Old Korean"] = "oko",
["Old Leonese"] = "roa-ole",
["Old Lithuanian"] = "olt",
["Old Manipuri"] = "omp",
["Old Marathi"] = "omr",
["Old Median"] = "xme-old",
["Old Mon"] = "omx",
["Old Navarro-Aragonese"] = "roa-ona",
["Old Norse"] = "non",
["Old Novgorodian"] = "zle-ono",
["Old Nubian"] = "onw",
["Old Occitan"] = "pro",
["Old Odia"] = "inc-oor",
["Old Persian"] = "peo",
["Old Polish"] = "zlw-opl",
["Old Prussian"] = "prg",
["Old Punjabi"] = "inc-opa",
["Old Ruthenian"] = "zle-ort",
["Old Saxon"] = "osx",
["Old Slovak"] = "zlw-osk",
["Old South Arabian"] = "sem-srb",
["Old Spanish"] = "osp",
["Old Sundanese"] = "osn",
["Old Swedish"] = "gmq-osw",
["Old Tamil"] = "oty",
["Old Tati"] = "xme-ott",
["Old Telugu"] = "dra-ote",
["Old Tibetan"] = "otb",
["Old Tupi"] = "tpw",
["Old Turkic"] = "otk",
["Old Uyghur"] = "oui",
["Old Welsh"] = "owl",
["Olekha"] = "ole",
["Ollari"] = "gdb",
["Olo"] = "ong",
["Oloma"] = "olm",
["Olrat"] = "olr",
["Olu'bo"] = "lul",
["Olukumi"] = "ulb",
["Olulumo-Ikom"] = "iko",
["Oluta Popoluca"] = "plo",
["Olutsotso"] = "lto",
["Omagua"] = "omg",
["Omaha-Ponca"] = "oma",
["Omani Arabic"] = "acx",
["Omba"] = "omb",
["Ombamba"] = "mbm",
["Ombo"] = "oml",
["Ometepec Nahuatl"] = "nht",
["Omi"] = "omi",
["Omok"] = "omk",
["Omotik"] = "omt",
["Omurano"] = "omu",
["Oneida"] = "one",
["Ong"] = "oog",
["Ongota"] = "bxe",
["Onin"] = "oni",
["Onjob"] = "onj",
["Ono"] = "ons",
["Onobasulu"] = "onn",
["Onondaga"] = "ono",
["Ontong Java"] = "ojv",
["Oorlams"] = "oor",
["Opao"] = "opo",
["Opata"] = "opt",
["Opuuo"] = "lgn",
["Opón"] = "sai-opo",
["Oraon Sadri"] = "sdr",
["Orejón"] = "ore",
["Oring"] = "org",
["Orizaba Nahuatl"] = "nlv",
["Orléanais"] = "roa-orl",
["Ormu"] = "orz",
["Ormuri"] = "oru",
["Oro"] = "orx",
["Oro Win"] = "orw",
["Oroch"] = "oac",
["Oroha"] = "ora",
["Orok"] = "oaa",
["Orokaiva"] = "okv",
["Oroko"] = "bdu",
["Orokolo"] = "oro",
["Oromo"] = "om",
["Oroqen"] = "orh",
["Orowe"] = "bpk",
["Oruma"] = "orr",
["Orya"] = "ury",
["Osage"] = "osa",
["Osamayi"] = "syx",
["Osatu"] = "ost",
["Oscan"] = "osc",
["Osing"] = "osi",
["Ososo"] = "oso",
["Ossetian"] = "os",
["Ot Danum"] = "otd",
["Otank"] = "uta",
["Oti"] = "oti",
["Otomaco"] = "sai-oto",
["Otoro"] = "otr",
["Ottawa"] = "otw",
["Ottoman Turkish"] = "ota",
["Otuke"] = "otu",
["Ouma"] = "oum",
["Oune"] = "oue",
["Owa"] = "stn",
["Owenia"] = "wsr",
["Owiniga"] = "owi",
["Oy"] = "oyb",
["Oya'oya"] = "oyy",
["Oyda"] = "oyd",
["Ozolotepec Zapotec"] = "zao",
["Ozumacín Chinantec"] = "chz",
["Pa"] = "ppt",
["Pa Di"] = "pdi",
["Pa'a"] = "pqa",
["Pa'o Karen"] = "blk",
["Pa-Hng"] = "pha",
["Paamese"] = "pma",
["Paasaal"] = "sig",
["Pacahuara"] = "pcp",
["Pacoh"] = "pac",
["Padoe"] = "pdo",
["Paelignian"] = "pgn",
["Paeonian"] = "ine-pae",
["Pagi"] = "pgi",
["Pagibete"] = "pae",
["Pagu"] = "pgu",
["Pahanan Agta"] = "apf",
["Pahari Newari"] = "phj",
["Pahari-Potwari"] = "phr",
["Pahi"] = "lgt",
["Pahlavani"] = "phv",
["Pai Tavytera"] = "pta",
["Paicî"] = "pri",
["Paikoneka"] = "awd-pai",
["Paipai"] = "ppi",
["Paite"] = "pck",
["Paiwan"] = "pwn",
["Pajapan Nahuatl"] = "nhp",
["Pajonal Ashéninka"] = "cjo",
["Pak-Tong"] = "pkg",
["Pakanha"] = "pkn",
["Pakistan Sign Language"] = "pks",
["Paku"] = "pku",
["Paku Karen"] = "jkp",
["Pal"] = "abw",
["Palaic"] = "plq",
["Palaka"] = "plr",
["Palantla Chinantec"] = "cpa",
["Palauan"] = "pau",
["Palawan Batak"] = "bya",
["Paleni"] = "pnl",
["Palenquero"] = "pln",
["Palewyami Yokuts"] = "yok-ply",
["Pali"] = "pi",
["Palikur"] = "plu",
["Paliyan"] = "pcf",
["Pallanganmiddang"] = "pmd",
["Palor"] = "fap",
["Palta"] = "sai-pal",
["Palu'e"] = "ple",
["Paluan"] = "plz",
["Palula"] = "phl",
["Palya Bareli"] = "bpx",
["Pam"] = "pmn",
["Pambia"] = "pmb",
["Pamigua"] = "sai-pam",
["Pamlico"] = "pmk",
["Pamona"] = "pmf",
["Pamosu"] = "hih",
["Pamplona Atta"] = "att",
["Pana (Central Africa)"] = "pnz",
["Pana (West Africa)"] = "pnq",
["Panamanian Sign Language"] = "lsp",
["Panamint"] = "par",
["Panare"] = "pbh",
["Panará"] = "kre",
["Panasuan"] = "psn",
["Panawa"] = "pwb",
["Pancana"] = "pnp",
["Panchpargania"] = "tdb",
["Pande"] = "bkj",
["Pangasinan"] = "pag",
["Pangseng"] = "pgs",
["Pangutaran Sama"] = "slm",
["Pangwa"] = "pbr",
["Pangwali"] = "pgg",
["Panim"] = "pnr",
["Paniya"] = "pcg",
["Pankararé"] = "pax",
["Pankararú"] = "paz",
["Pankhu"] = "pkh",
["Pannei"] = "pnc",
["Pannonian Rusyn"] = "rsk",
["Panobo"] = "pno",
["Panyi Bai"] = "bfc",
["Panyjima"] = "pnw",
["Panzaleo"] = "sai-pnz",
["Pao"] = "ppa",
["Papantla Totonac"] = "top",
["Papapana"] = "ppn",
["Papar"] = "dpp",
["Papasena"] = "pas",
["Papel"] = "pbo",
["Papi"] = "ppe",
["Papiamentu"] = "pap",
["Papora"] = "ppu",
["Papua New Guinean Sign Language"] = "pgz",
["Papuan Malay"] = "pmy",
["Papuma"] = "ppm",
["Para Naga"] = "pzn",
["Parachi"] = "prc",
["Paraguayan Guarani"] = "gug",
["Paraguayan Sign Language"] = "pys",
["Parakanã"] = "pak",
["Paranan"] = "prf",
["Paranawát"] = "paf",
["Paratió"] = "sai-par",
["Paraujano"] = "pbg",
["Parauk"] = "prk",
["Parawen"] = "prw",
["Pardhan"] = "pch",
["Pardhi"] = "pcl",
["Pare"] = "asa",
["Pareci"] = "pab",
["Paredarerme"] = "xpd",
["Parenga"] = "pcj",
["Parkari Koli"] = "kvx",
["Parthian"] = "xpr",
["Parya"] = "paq",
["Pará Gavião"] = "gvp",
["Pashto"] = "ps",
["Pasi"] = "psq",
["Pass Valley Yali"] = "yac",
["Pasé"] = "awd-pas",
["Patagón"] = "sai-ptg",
["Patamona"] = "pbc",
["Patani"] = "ptn",
["Pataxó Hã-Hã-Hãe"] = "pth",
["Patep"] = "ptp",
["Pathiya"] = "pty",
["Patpatar"] = "gfk",
["Pattani"] = "lae",
["Pattani Malay"] = "mfa",
["Pattapu"] = "ptq",
["Patwin"] = "pwi",
["Paulohi"] = "plh",
["Paumarí"] = "pad",
["Paunaka"] = "pnk",
["Pauri Bareli"] = "bfb",
["Pauserna"] = "psm",
["Pawaia"] = "pwa",
["Pawnee"] = "paw",
["Payaguá"] = "sai-pyg",
["Pazeh"] = "pzh",
["Pe"] = "pai",
["Pear"] = "pcb",
["Peba"] = "sai-peb",
["Pech"] = "pay",
["Pecheneg"] = "xpc",
["Peerapper"] = "xpw",
["Peere"] = "pfe",
["Pei"] = "ppq",
["Pekal"] = "pel",
["Pela"] = "bxd",
["Pele-Ata"] = "ata",
["Pemon"] = "aoc",
["Penang Sign Language"] = "psg",
["Penchal"] = "pek",
["Pendau"] = "ums",
["Pengo"] = "peg",
["Pennsylvania German"] = "pdc",
["Penobscot"] = "aaq",
["Penrhyn"] = "pnh",
["Pentlatch"] = "ptw",
["Perai"] = "wet",
["Peranakan Indonesian"] = "pea",
["Perema"] = "wom",
["Perené Ashéninka"] = "prq",
["Pericú"] = "nai-per",
["Pero"] = "pip",
["Persian"] = "fa",
["Persian Sign Language"] = "psc",
["Peruvian Sign Language"] = "prl",
["Petapa Zapotec"] = "zpe",
["Petats"] = "pex",
["Petjo"] = "pey",
["Peñoles Mixtec"] = "mil",
["Phai"] = "prt",
["Phake"] = "phk",
["Phala"] = "ypa",
["Phana'"] = "phq",
["Phangduwali"] = "phw",
["Phende"] = "pem",
["Philippine Sign Language"] = "psp",
["Philistine"] = "mis-phi",
["Phimbi"] = "phm",
["Phoenician"] = "phn",
["Phola"] = "ypg",
["Pholo"] = "yip",
["Phom"] = "nph",
["Phong-Kniang"] = "pnx",
["Phrae Pwo"] = "kjt",
["Phrygian"] = "xpg",
["Phu Thai"] = "pht",
["Phuan"] = "phu",
["Phudagi"] = "phd",
["Phuie"] = "pug",
["Phukha"] = "phh",
["Phuma"] = "ypm",
["Phunoi"] = "pho",
["Phuong"] = "phg",
["Phupa"] = "ypp",
["Phupha"] = "yph",
["Phuthi"] = "bnt-phu",
["Phuza"] = "ypz",
["Piamatsina"] = "ptr",
["Piame"] = "pin",
["Piapoco"] = "pio",
["Piaroa"] = "pid",
["Picard"] = "pcd",
["Pichinglis"] = "fpe",
["Pichis Ashéninka"] = "cpu",
["Pictish"] = "xpi",
["Picuris"] = "nai-pic",
["Pidgin Delaware"] = "dep",
["Pidgin Iha"] = "ihb",
["Pidgin Onin"] = "onx",
["Piedmontese"] = "pms",
["Pijao"] = "pij",
["Pije"] = "piz",
["Pijin"] = "pis",
["Pilagá"] = "plg",
["Pileni"] = "piv",
["Pima Bajo"] = "pia",
["Pimbwe"] = "piw",
["Pinai-Hagahai"] = "pnn",
["Pingelapese"] = "pif",
["Pinigura"] = "pnv",
["Pinjarup"] = "pnj",
["Pinji"] = "pic",
["Pinotepa Nacional Mixtec"] = "mio",
["Pintiini"] = "pti",
["Pintupi-Luritja"] = "piu",
["Pinyin"] = "pny",
["Pipil"] = "ppl",
["Pirahã"] = "myp",
["Piratapuyo"] = "pir",
["Pirlatapa"] = "bxi",
["Piro"] = "pie",
["Pirriya"] = "xpa",
["Pisabo"] = "pig",
["Pisaflores Tepehua"] = "tpp",
["Piscataway"] = "psy",
["Pisidian"] = "xps",
["Pitcairn-Norfolk"] = "pih",
["Pite Sami"] = "sje",
["Piti"] = "pcn",
["Pitjantjatjara"] = "pjt",
["Pitta-Pitta"] = "pit",
["Piu"] = "pix",
["Piya-Kwonci"] = "piy",
["Plains Apache"] = "apk",
["Plains Cree"] = "crk",
["Plains Indian Sign Language"] = "psd",
["Plains Miwok"] = "pmw",
["Plapo Krumen"] = "ktj",
["Plautdietsch"] = "pdt",
["Playero"] = "gob",
["Pnar"] = "pbv",
["Pochuri Naga"] = "npo",
["Pochutec"] = "xpo",
["Podoko"] = "pbi",
["Pogali"] = "hkh",
["Pogolo"] = "poy",
["Pohnpeian"] = "pon",
["Poitevin-Saintongeais"] = "roa-poi",
["Pokangá"] = "pok",
["Poke"] = "pof",
["Pol"] = "pmm",
["Polabian"] = "pox",
["Polci"] = "plj",
["Polish"] = "pl",
["Polish Sign Language"] = "pso",
["Polonombauk"] = "plb",
["Pom"] = "pmo",
["Ponam"] = "ncc",
["Pondi"] = "lnm",
["Pongu"] = "png",
["Ponosakan"] = "pns",
["Pontic Greek"] = "pnt",
["Ponyo"] = "npg",
["Poqomam"] = "poc",
["Poqomchi'"] = "poh",
["Porohanon"] = "prh",
["Port Sandwich"] = "psw",
["Port Sorell"] = "xpl",
["Port Vato"] = "ptv",
["Portuguese"] = "pt",
["Portuguese Sign Language"] = "psr",
["Potawatomi"] = "pot",
["Potiguára"] = "pog",
["Poumei Naga"] = "pmx",
["Pouye"] = "bye",
["Powari"] = "pwr",
["Powhatan"] = "pim",
["Poyanáwa"] = "pyn",
["Prakrit"] = "pra",
["Prasuni"] = "prn",
["Pre-Samnite"] = "itc-psa",
["Primitive Irish"] = "pgl",
["Principense"] = "pre",
["Proto-Abkhaz-Abaza"] = "cau-abz-pro",
["Proto-Afroasiatic"] = "afa-pro",
["Proto-Albanian"] = "sqj-pro",
["Proto-Algic"] = "aql-pro",
["Proto-Algonquian"] = "alg-pro",
["Proto-Amuesha-Chamicuro"] = "awd-amc-pro",
["Proto-Anatolian"] = "ine-ana-pro",
["Proto-Andian"] = "cau-and-pro",
["Proto-Apachean"] = "apa-pro",
["Proto-Arawa"] = "auf-pro",
["Proto-Arawak"] = "awd-pro",
["Proto-Armenian"] = "hyx-pro",
["Proto-Arnhem"] = "aus-arn-pro",
["Proto-Aroid"] = "omv-aro-pro",
["Proto-Aslian"] = "mkh-asl-pro",
["Proto-Atayalic"] = "map-ata-pro",
["Proto-Athabaskan"] = "ath-pro",
["Proto-Atlantic-Congo"] = "alv-pro",
["Proto-Austroasiatic"] = "aav-pro",
["Proto-Austronesian"] = "map-pro",
["Proto-Avaro-Andian"] = "cau-ava-pro",
["Proto-Bahnaric"] = "mkh-ban-pro",
["Proto-Bai"] = "sit-bai-pro",
["Proto-Balto-Slavic"] = "ine-bsl-pro",
["Proto-Bantoid"] = "nic-bod-pro",
["Proto-Bantu"] = "bnt-pro",
["Proto-Basque"] = "euq-pro",
["Proto-Batak"] = "btk-pro",
["Proto-Be"] = "qfa-onb-pro",
["Proto-Be-Tai"] = "qfa-bet-pro",
["Proto-Benue-Congo"] = "nic-bco-pro",
["Proto-Berber"] = "ber-pro",
["Proto-Binanderean"] = "ngf-bin-pro",
["Proto-Bodish"] = "sit-bdi-pro",
["Proto-Bodo-Garo"] = "tbq-bdg-pro",
["Proto-Bongo-Bagirmi"] = "csu-bba-pro",
["Proto-Boran"] = "sai-bor-pro",
["Proto-Brythonic"] = "cel-bry-pro",
["Proto-Bua"] = "alv-bua-pro",
["Proto-Bungku-Tolaki"] = "poz-btk-pro",
["Proto-Burmish"] = "tbq-brm-pro",
["Proto-Caddoan"] = "cdd-pro",
["Proto-Cangin"] = "alv-cng-pro",
["Proto-Cariban"] = "sai-car-pro",
["Proto-Celtic"] = "cel-pro",
["Proto-Central Chadic"] = "cdc-cbm-pro",
["Proto-Central Dravidian"] = "dra-cen-pro",
["Proto-Central Jê"] = "sai-cje-pro",
["Proto-Central Naga"] = "sit-aao-pro",
["Proto-Central New South Wales"] = "aus-cww-pro",
["Proto-Central Sudanic"] = "csu-pro",
["Proto-Central Togo"] = "alv-gtm-pro",
["Proto-Central-Eastern Malayo-Polynesian"] = "poz-cet-pro",
["Proto-Cerrado"] = "sai-cer-pro",
["Proto-Chadic"] = "cdc-pro",
["Proto-Chamic"] = "cmc-pro",
["Proto-Chatino"] = "omq-cha-pro",
["Proto-Chibchan"] = "cba-pro",
["Proto-Chimakuan"] = "chi-pro",
["Proto-Chinookan"] = "nai-ckn-pro",
["Proto-Chukotko-Kamchatkan"] = "qfa-cka-pro",
["Proto-Chumash"] = "nai-chu-pro",
["Proto-Circassian"] = "cau-cir-pro",
["Proto-Cupan"] = "azc-cup-pro",
["Proto-Cushitic"] = "cus-pro",
["Proto-Daju"] = "sdv-daj-pro",
["Proto-Daly"] = "aus-dal-pro",
["Proto-Dangari"] = "inc-dng-pro",
["Proto-Dargwa"] = "cau-drg-pro",
["Proto-Dizoid"] = "omv-diz-pro",
["Proto-Dravidian"] = "dra-pro",
["Proto-Eastern Jebel"] = "sdv-eje-pro",
["Proto-Eastern Malayo-Polynesian"] = "pqe-pro",
["Proto-Eastern Oti-Volta"] = "nic-eov-pro",
["Proto-Eastern Polynesian"] = "poz-pep-pro",
["Proto-Edekiri"] = "alv-edk-pro",
["Proto-Edoid"] = "alv-edo-pro",
["Proto-Ersuic"] = "sit-ers-pro",
["Proto-Eskimo"] = "esx-esk-pro",
["Proto-Eskimo-Aleut"] = "esx-pro",
["Proto-Fali"] = "alv-fli-pro",
["Proto-Finnic"] = "urj-fin-pro",
["Proto-Gbaya"] = "gba-pro",
["Proto-Gbe"] = "alv-gbe-pro",
["Proto-Georgian-Zan"] = "ccs-gzn-pro",
["Proto-Germanic"] = "gem-pro",
["Proto-Grassfields"] = "nic-grf-pro",
["Proto-Great Andamanese"] = "qfa-adm-pro",
["Proto-Guang"] = "alv-gng-pro",
["Proto-Gur"] = "nic-gur-pro",
["Proto-Gurunsi"] = "nic-gns-pro",
["Proto-Halmahera-Cenderawasih"] = "poz-hce-pro",
["Proto-Heiban"] = "alv-hei-pro",
["Proto-Hellenic"] = "grk-pro",
["Proto-Highland East Cushitic"] = "cus-hec-pro",
["Proto-Hlai"] = "qfa-lic-pro",
["Proto-Hmong-Mien"] = "hmx-pro",
["Proto-Hmongic"] = "hmn-pro",
["Proto-Hrusish"] = "sit-hrs-pro",
["Proto-Hurro-Urartian"] = "qfa-hur-pro",
["Proto-Idomoid"] = "alv-ido-pro",
["Proto-Igboid"] = "alv-igb-pro",
["Proto-Ijoid"] = "ijo-pro",
["Proto-Indo-Aryan"] = "inc-pro",
["Proto-Indo-European"] = "ine-pro",
["Proto-Indo-Iranian"] = "iir-pro",
["Proto-Inuit"] = "esx-inu-pro",
["Proto-Iranian"] = "ira-pro",
["Proto-Iroquoian"] = "iro-pro",
["Proto-Italic"] = "itc-pro",
["Proto-Iwaidjan"] = "aus-wdj-pro",
["Proto-Japonic"] = "jpx-pro",
["Proto-Jukunoid"] = "nic-jkn-pro",
["Proto-Jê"] = "sai-jee-pro",
["Proto-Kadu"] = "qfa-kad-pro",
["Proto-Kalamian"] = "phi-kal-pro",
["Proto-Kalapuyan"] = "nai-klp-pro",
["Proto-Kam-Sui"] = "qfa-kms-pro",
["Proto-Kampa"] = "awd-kmp-pro",
["Proto-Kamta"] = "inc-krd-pro",
["Proto-Karen"] = "kar-pro",
["Proto-Kartvelian"] = "ccs-pro",
["Proto-Katuic"] = "mkh-kat-pro",
["Proto-Kham"] = "sit-kha-pro",
["Proto-Khanty"] = "kca-pro",
["Proto-Khasian"] = "aav-khs-pro",
["Proto-Khmeric"] = "mkh-kmr-pro",
["Proto-Khmuic"] = "mkh-khm-pro",
["Proto-Kho-Bwa"] = "sit-khb-pro",
["Proto-Khoe"] = "khi-kho-pro",
["Proto-Koman"] = "ssa-kom-pro",
["Proto-Komisenian"] = "ira-kms-pro",
["Proto-Koreanic"] = "qfa-kor-pro",
["Proto-Kra"] = "qfa-kra-pro",
["Proto-Kra-Dai"] = "qfa-tak-pro",
["Proto-Kru"] = "kro-pro",
["Proto-Kuki-Chin"] = "tbq-kuk-pro",
["Proto-Kuliak"] = "ssa-klk-pro",
["Proto-Kurdish"] = "ku-pro",
["Proto-Kwa"] = "alv-kwa-pro",
["Proto-Lalo"] = "tbq-lal-pro",
["Proto-Lampungic"] = "poz-lgx-pro",
["Proto-Lezghian"] = "cau-lzg-pro",
["Proto-Lolo-Burmese"] = "tbq-lob-pro",
["Proto-Loloish"] = "tbq-lol-pro",
["Proto-Lower Cross River"] = "nic-lcr-pro",
["Proto-Luish"] = "sit-luu-pro",
["Proto-Maidun"] = "nai-mdu-pro",
["Proto-Malayic"] = "poz-mly-pro",
["Proto-Malayo-Chamic"] = "poz-mcm-pro",
["Proto-Malayo-Polynesian"] = "poz-pro",
["Proto-Malayo-Sumbawan"] = "poz-msa-pro",
["Proto-Mande"] = "dmn-pro",
["Proto-Mangbetu"] = "csu-maa-pro",
["Proto-Mansi"] = "mns-pro",
["Proto-Mari"] = "chm-pro",
["Proto-Masa"] = "cdc-mas-pro",
["Proto-Mayan"] = "myn-pro",
["Proto-Mazatec"] = "omq-maz-pro",
["Proto-Medo-Parthian"] = "ira-mpr-pro",
["Proto-Micronesian"] = "poz-mic-pro",
["Proto-Mienic"] = "hmx-mie-pro",
["Proto-Min"] = "zhx-min-pro",
["Proto-Mixe-Zoque"] = "nai-miz-pro",
["Proto-Mixtec"] = "omq-mxt-pro",
["Proto-Mixtecan"] = "omq-mix-pro",
["Proto-Mon-Khmer"] = "mkh-pro",
["Proto-Mongolic"] = "xgn-pro",
["Proto-Monic"] = "mkh-mnc-pro",
["Proto-Mordvinic"] = "urj-mdv-pro",
["Proto-Mumuye"] = "alv-mum-pro",
["Proto-Munda"] = "mun-pro",
["Proto-Munji-Yidgha"] = "ira-mny-pro",
["Proto-Muskogean"] = "nai-mus-pro",
["Proto-Na-Dene"] = "xnd-pro",
["Proto-Nahuan"] = "azc-nah-pro",
["Proto-Naish"] = "sit-nas-pro",
["Proto-Nakh"] = "cau-nkh-pro",
["Proto-Nawiki"] = "awd-nwk-pro",
["Proto-Nguni"] = "bnt-ngu-pro",
["Proto-Nicobarese"] = "aav-nic-pro",
["Proto-Niger-Congo"] = "nic-pro",
["Proto-Nilo-Saharan"] = "ssa-pro",
["Proto-Nilotic"] = "sdv-nil-pro",
["Proto-Norse"] = "gmq-pro",
["Proto-North Dravidian"] = "dra-nor-pro",
["Proto-North Halmahera"] = "paa-nha-pro",
["Proto-North Iroquoian"] = "iro-nor-pro",
["Proto-North Sarawak"] = "poz-swa-pro",
["Proto-Northeast Caucasian"] = "cau-nec-pro",
["Proto-Northern Jê"] = "sai-nje-pro",
["Proto-Northern Naga"] = "sit-kon-pro",
["Proto-Northwest Caucasian"] = "cau-nwc-pro",
["Proto-Nubian"] = "nub-pro",
["Proto-Nuclear Polynesian"] = "poz-pnp-pro",
["Proto-Numic"] = "azc-num-pro",
["Proto-Nupoid"] = "alv-nup-pro",
["Proto-Nuristani"] = "iir-nur-pro",
["Proto-Nyima"] = "sdv-nyi-pro",
["Proto-Nyulnyulan"] = "aus-nyu-pro",
["Proto-Oceanic"] = "poz-oce-pro",
["Proto-Ogoni"] = "nic-ogo-pro",
["Proto-Omotic"] = "omv-pro",
["Proto-Ongan"] = "qfa-ong-pro",
["Proto-Oti-Volta"] = "nic-ovo-pro",
["Proto-Oto-Manguean"] = "omq-pro",
["Proto-Oto-Pamean"] = "omq-otp-pro",
["Proto-Otomi"] = "oto-otm-pro",
["Proto-Otomian"] = "oto-pro",
["Proto-Pakanic"] = "mkh-pkn-pro",
["Proto-Palaungic"] = "mkh-pal-pro",
["Proto-Pama-Nyungan"] = "aus-pam-pro",
["Proto-Paresi-Waura"] = "awd-prw-pro",
["Proto-Pathan"] = "ira-pat-pro",
["Proto-Pearic"] = "mkh-pea-pro",
["Proto-Permic"] = "urj-prm-pro",
["Proto-Philippine"] = "phi-pro",
["Proto-Plateau"] = "nic-plt-pro",
["Proto-Plateau Penutian"] = "nai-plp-pro",
["Proto-Pnar-Khasi-Lyngngam"] = "aav-pkl-pro",
["Proto-Polynesian"] = "poz-pol-pro",
["Proto-Pomo"] = "nai-pom-pro",
["Proto-Puroik"] = "sit-khp-pro",
["Proto-Quechuan"] = "qwe-pro",
["Proto-Rukai"] = "dru-pro",
["Proto-Ryukyuan"] = "jpx-ryu-pro",
["Proto-Sabaki"] = "bnt-sab-pro",
["Proto-Saka"] = "xsc-sak-pro",
["Proto-Saka-Wakhi"] = "xsc-skw-pro",
["Proto-Salish"] = "sal-pro",
["Proto-Samic"] = "smi-pro",
["Proto-Samoyedic"] = "syd-pro",
["Proto-Sanglechi-Ishkashimi"] = "ira-sgi-pro",
["Proto-Sara"] = "csu-sar-pro",
["Proto-Sarmatian"] = "xsc-sar-pro",
["Proto-Scythian"] = "xsc-pro",
["Proto-Selkup"] = "sel-pro",
["Proto-Semitic"] = "sem-pro",
["Proto-Shughni-Roshani"] = "ira-shr-pro",
["Proto-Shughni-Yazghulami"] = "ira-shy-pro",
["Proto-Shughni-Yazghulami-Munji"] = "ira-sym-pro",
["Proto-Sino-Tibetan"] = "sit-pro",
["Proto-Siouan"] = "sio-pro",
["Proto-Siouan-Catawban"] = "nai-sca-pro",
["Proto-Slavic"] = "sla-pro",
["Proto-Sogdic"] = "ira-sgc-pro",
["Proto-Somaloid"] = "cus-som-pro",
["Proto-Songhay"] = "son-pro",
["Proto-Sotho-Tswana"] = "bnt-sts-pro",
["Proto-South Cushitic"] = "cus-sou-pro",
["Proto-South Dravidian"] = "dra-sou-pro",
["Proto-South Dravidian I"] = "dra-sdo-pro",
["Proto-South Dravidian II"] = "dra-sdt-pro",
["Proto-South Sulawesi"] = "poz-ssw-pro",
["Proto-Southern Jê"] = "sai-sje-pro",
["Proto-Southwestern Tai"] = "tai-swe-pro",
["Proto-Ta-Arawak"] = "awd-taa-pro",
["Proto-Tai"] = "tai-pro",
["Proto-Takic"] = "azc-tak-pro",
["Proto-Taman"] = "sdv-tmn-pro",
["Proto-Tamangic"] = "sit-tam-pro",
["Proto-Tangkhulic"] = "sit-tng-pro",
["Proto-Tani"] = "sit-tan-pro",
["Proto-Taranoan"] = "sai-tar-pro",
["Proto-Tatic"] = "xme-ttc-pro",
["Proto-Tocharian"] = "ine-toc-pro",
["Proto-Totozoquean"] = "nai-tot-pro",
["Proto-Trans-New Guinea"] = "ngf-pro",
["Proto-Triqui"] = "omq-tri-pro",
["Proto-Tsezian"] = "cau-tsz-pro",
["Proto-Tsimshianic"] = "nai-tsi-pro",
["Proto-Tungusic"] = "tuw-pro",
["Proto-Tupi-Guarani"] = "tup-gua-pro",
["Proto-Tupian"] = "tup-pro",
["Proto-Turkic"] = "trk-pro",
["Proto-Ubangian"] = "nic-ubg-pro",
["Proto-Ugric"] = "urj-ugr-pro",
["Proto-Upper Cross River"] = "nic-ucr-pro",
["Proto-Uralic"] = "urj-pro",
["Proto-Utian"] = "nai-utn-pro",
["Proto-Uto-Aztecan"] = "azc-pro",
["Proto-Vietic"] = "mkh-vie-pro",
["Proto-Volta-Congo"] = "nic-vco-pro",
["Proto-Volta-Niger"] = "alv-von-pro",
["Proto-West Germanic"] = "gmw-pro",
["Proto-West Semitic"] = "sem-wes-pro",
["Proto-Western Kho-Bwa"] = "sit-khw-pro",
["Proto-Western Mande"] = "dmn-mdw-pro",
["Proto-Witotoan"] = "sai-wit-pro",
["Proto-Yeniseian"] = "qfa-yen-pro",
["Proto-Yoruba"] = "alv-yor-pro",
["Proto-Yoruboid"] = "alv-yrd-pro",
["Proto-Yukaghir"] = "qfa-yuk-pro",
["Proto-Yupik"] = "ypk-pro",
["Proto-Zapotec"] = "omq-zpc-pro",
["Proto-Zapotecan"] = "omq-zap-pro",
["Proto-Zaza-Gorani"] = "ira-zgr-pro",
["Providencia Sign Language"] = "prz",
["Psikye"] = "kvj",
["Puare"] = "pux",
["Pudtol Atta"] = "atp",
["Puebla Mazatec"] = "pbm",
["Puelche"] = "pue",
["Puerto Rican Sign Language"] = "psl",
["Puimei Naga"] = "npu",
["Puinave"] = "pui",
["Puiron"] = "sit-prn",
["Pukapukan"] = "pkp",
["Pulabu"] = "pup",
["Puluwat"] = "puw",
["Puma"] = "pum",
["Pumpokol"] = "xpm",
["Pumé"] = "yae",
["Punan Aput"] = "pud",
["Punan Bah-Biau"] = "pna",
["Punan Batu"] = "pnm",
["Punan Merah"] = "puf",
["Punan Merap"] = "puc",
["Punan Tubu"] = "puj",
["Punic"] = "xpu",
["Punjabi"] = "pa",
["Punu"] = "puu",
["Puoc"] = "puo",
["Puquina"] = "puq",
["Puragi"] = "pru",
["Purari"] = "iar",
["Purepecha"] = "pua",
["Puri"] = "prr",
["Purik"] = "prx",
["Purisimeño"] = "puy",
["Puroik"] = "suv",
["Puruborá"] = "pur",
["Puruhá"] = "sai-prh",
["Purukotó"] = "sai-pur",
["Purum"] = "pub",
["Putai"] = "mfl",
["Putoh"] = "put",
["Putukwam"] = "afe",
["Puxian Min"] = "cpx",
["Puyo-Paekche"] = "xpp",
["Puyuma"] = "pyu",
["Pwaamèi"] = "pme",
["Pwapwâ"] = "pop",
["Pyapun"] = "pcw",
["Pye Krumen"] = "pye",
["Pyemmairre"] = "xpb",
["Pyen"] = "pyy",
["Pykobjê"] = "sai-pyk",
["Pyu (Myanmar)"] = "pyx",
["Pyu (New Guinea)"] = "pby",
["Páez"] = "pbb",
["Pááfang"] = "pfa",
["Päri"] = "lkr",
["Pémono"] = "pev",
["Pévé"] = "lme",
["Pökoot"] = "pko",
["Q'anjob'al"] = "kjb",
["Q'eqchi"] = "kek",
["Qabiao"] = "laq",
["Qaqet"] = "byx",
["Qatabanian"] = "xqt",
["Qau"] = "gqu",
["Qila Muji"] = "ymq",
["Qimant"] = "ahg",
["Quapaw"] = "qua",
["Quebec Sign Language"] = "fcs",
["Quechua"] = "qu",
["Quenya"] = "qya",
["Querétaro Otomi"] = "otq",
["Quetzaltepec Mixe"] = "pxm",
["Queyu"] = "qvy",
["Quiavicuzas Zapotec"] = "zpj",
["Quileute"] = "qui",
["Quimbaya"] = "sai-qmb",
["Quinault"] = "qun",
["Quinigua"] = "nai-qng",
["Quinqui"] = "quq",
["Quioquitani-Quierí Zapotec"] = "ztq",
["Quiotepec Chinantec"] = "chq",
["Quiripi"] = "qyp",
["Quitemo"] = "sai-qtm",
["Rabha"] = "rah",
["Rabona"] = "sai-rab",
["Rade"] = "rad",
["Raetic"] = "xrr",
["Raga"] = "lml",
["Rahambuu"] = "raz",
["Rajah Kabunsuwan Manobo"] = "mqk",
["Rajbanshi"] = "rjs",
["Raji"] = "rji",
["Rajong"] = "rjg",
["Rajput Garasia"] = "gra",
["Rakahanga-Manihiki"] = "rkh",
["Rakhine"] = "rki",
["Ralte"] = "ral",
["Rama"] = "rma",
["Ramandi"] = "tks",
["Ramanos"] = "sai-ram",
["Ramoaaina"] = "rai",
["Ramopa"] = "kjx",
["Rampi"] = "lje",
["Rana Tharu"] = "thr",
["Rang"] = "rax",
["Rangkas"] = "rgk",
["Ranglong"] = "rnl",
["Rao"] = "rao",
["Rapa"] = "ray",
["Rapa Nui"] = "rap",
["Rapoisi"] = "kyx",
["Rapting"] = "rpt",
["Rara Bakati'"] = "lra",
["Rarotongan"] = "rar",
["Rasawa"] = "rac",
["Ratagnon"] = "btn",
["Ratahan"] = "rth",
["Rathawi"] = "rtw",
["Rathwi Bareli"] = "bgd",
["Raute"] = "rau",
["Ravula"] = "yea",
["Rawa"] = "rwo",
["Rawang"] = "raw",
["Rawat"] = "jnl",
["Rawo"] = "rwa",
["Rayón Zoque"] = "zor",
["Razajerdi"] = "rat",
["Razihi"] = "rzh",
["Reang"] = "ria",
["Red Gelao"] = "gir",
["Reel"] = "atu",
["Rejang"] = "rej",
["Rejang Kayan"] = "ree",
["Reli"] = "rei",
["Rema"] = "bow",
["Rembarunga"] = "rmb",
["Rembong"] = "reb",
["Remo"] = "rem",
["Remontado Agta"] = "agv",
["Rempi"] = "rmp",
["Remun"] = "lkj",
["Rendille"] = "rel",
["Rengao"] = "ren",
["Rennellese"] = "mnv",
["Repanbitip"] = "rpn",
["Rer Bare"] = "rer",
["Rerau"] = "rea",
["Rerep"] = "pgk",
["Reshe"] = "res",
["Resígaro"] = "rgr",
["Retta"] = "ret",
["Reyesano"] = "rey",
["Rhine Franconian"] = "gmw-rfr",
["Riang"] = "ril",
["Riantana"] = "ran",
["Ribun"] = "rir",
["Rigwe"] = "iri",
["Rikbaktsa"] = "rkb",
["Rinconada Bikol"] = "bto",
["Rincón Zapotec"] = "zar",
["Ringgou"] = "rgu",
["Ririo"] = "rri",
["Ritarungo"] = "rit",
["Riung"] = "riu",
["Riverain Sango"] = "snj",
["Rogo"] = "rod",
["Rohingya"] = "rhg",
["Roma"] = "rmm",
["Romagnol"] = "rgn",
["Romam"] = "rmx",
["Romani"] = "rom",
["Romanian"] = "ro",
["Romanian Sign Language"] = "rms",
["Romano-Greek"] = "rge",
["Romano-Serbian"] = "rsb",
["Romanova"] = "rmv",
["Romansh"] = "rm",
["Romblomanon"] = "rol",
["Rombo"] = "rof",
["Romkun"] = "rmk",
["Ron"] = "cla",
["Ronga"] = "rng",
["Rongga"] = "ror",
["Rongmei Naga"] = "nbu",
["Rongpo"] = "rnp",
["Ronji"] = "roe",
["Roon"] = "rnn",
["Roria"] = "rga",
["Roro"] = "rro",
["Rotokas"] = "roo",
["Rotuman"] = "rtm",
["Rouran"] = "mis-rou",
["Roviana"] = "rug",
["Ruching Palaung"] = "pce",
["Rudbari"] = "rdb",
["Rufiji"] = "rui",
["Ruga"] = "ruh",
["Rukai"] = "dru",
["Rukiga"] = "cgg",
["Ruma"] = "ruz",
["Rumai Palaung"] = "rbb",
["Rumu"] = "klq",
["Runga"] = "rou",
["Rungtu"] = "rtc",
["Rungus"] = "drg",
["Rungwa"] = "rnw",
["Russenorsk"] = "crp-rsn",
["Russian"] = "ru",
["Russian Sign Language"] = "rsl",
["Rutul"] = "rut",
["Ruuli"] = "ruc",
["Ruwund"] = "rnd",
["Rwa"] = "rwk",
["Rwanda-Rundi"] = "rw",
["Rwandan Sign Language"] = "rsn",
["Réunion Creole French"] = "rcf",
["S'gaw Karen"] = "ksw",
["Sa"] = "sax",
["Sa'a"] = "apb",
["Sa'ban"] = "snv",
["Sa'och"] = "scq",
["Saafi-Saafi"] = "sav",
["Saam"] = "raq",
["Saamia"] = "lsm",
["Saanich"] = "str",
["Saare"] = "uss",
["Saaroa"] = "sxr",
["Saba"] = "saa",
["Sabaean"] = "xsa",
["Sabah Bisaya"] = "bsy",
["Sabah Malay"] = "msi",
["Sabanê"] = "sae",
["Sabaot"] = "spy",
["Sabine"] = "sbv",
["Sabir"] = "pml",
["Sabu"] = "hvn",
["Sabüm"] = "sbo",
["Sacapulteco"] = "quv",
["Sadri"] = "sck",
["Saek"] = "skb",
["Saep"] = "spd",
["Safaitic"] = "sem-saf",
["Safaliba"] = "saf",
["Safeyoka"] = "apz",
["Safwa"] = "sbk",
["Sagala"] = "sbm",
["Sagalla"] = "tga",
["Sahaptin"] = "nai-spt",
["Saho"] = "ssy",
["Sahu"] = "saj",
["Saisiyat"] = "xsy",
["Sajau Basap"] = "sjb",
["Sakachep"] = "sch",
["Sakam"] = "skm",
["Sakao"] = "sku",
["Sakata"] = "skt",
["Sake"] = "sak",
["Sakizaya"] = "szy",
["Sala"] = "shq",
["Salampasu"] = "slx",
["Salar"] = "slr",
["Salas"] = "sgu",
["Saleman"] = "sau",
["Saliba (Colombia)"] = "slc",
["Saliba (New Guinea)"] = "sbe",
["Salinan"] = "sln",
["Salt-Yui"] = "sll",
["Saluan"] = "loe",
["Salumá"] = "slj",
["Salvadoran Lenca"] = "nai-sln",
["Salvadoran Sign Language"] = "esn",
["Sam"] = "snx",
["Sama"] = "smd",
["Samalian"] = "sem-sam",
["Samaritan Aramaic"] = "sam",
["Samaritan Hebrew"] = "smp",
["Samarokena"] = "tmj",
["Samatao"] = "ysd",
["Samba"] = "smx",
["Sambali"] = "xsb",
["Sambalpuri"] = "spv",
["Sambe"] = "xab",
["Samberigi"] = "ssx",
["Samburu"] = "saq",
["Samei"] = "smh",
["Samo"] = "smq",
["Samoan"] = "sm",
["Samoan Plantation Pidgin"] = "crp-spp",
["Samogitian"] = "sgs",
["Samosa"] = "swm",
["Sampang"] = "rav",
["Samre"] = "sxm",
["Samtao"] = "stu",
["Samvedi"] = "smv",
["San Agustín Mixtepec Zapotec"] = "ztm",
["San Baltazar Loxicha Zapotec"] = "zpx",
["San Felipe Otlaltepec Popoloca"] = "pow",
["San Jerónimo Tecóatl Mazatec"] = "maa",
["San Juan Atzingo Popoloca"] = "poe",
["San Juan Colorado Mixtec"] = "mjc",
["San Juan Guelavía Zapotec"] = "zab",
["San Juan Quiahije Chatino"] = "omq-sjq",
["San Juan Teita Mixtec"] = "xtj",
["San Luís Temalacayuca Popoloca"] = "pps",
["San Marcos Tlalcoyalco Popoloca"] = "pls",
["San Martín Itunyoso Triqui"] = "trq",
["San Miguel Creole French"] = "scf",
["San Miguel Piedras Mixtec"] = "xtp",
["San Miguel el Grande Mixtec"] = "mig",
["San Pablo Güilá Zapotec"] = "ztu",
["San Pedro Amuzgos Amuzgo"] = "azg",
["San Pedro Quiatoni Zapotec"] = "zpf",
["San Vicente Coatlán Zapotec"] = "zpt",
["Sanapaná"] = "spn",
["Sanaviron"] = "sai-san",
["Sandawe"] = "sad",
["Sanga (Congo)"] = "sng",
["Sanga (Nigeria)"] = "xsn",
["Sanggau"] = "scg",
["Sangil"] = "snl",
["Sangir"] = "sxn",
["Sangisari"] = "sgr",
["Sangkong"] = "sgk",
["Sanglechi"] = "sgy",
["Sango"] = "sg",
["Sangtam Naga"] = "nsa",
["Sangu (Gabon)"] = "snq",
["Sangu (Tanzania)"] = "sbp",
["Sani"] = "ysn",
["Sanie"] = "ysy",
["Saniyo-Hiyewe"] = "sny",
["Sankaran Maninka"] = "msc",
["Sansi"] = "ssi",
["Sanskrit"] = "sa",
["Santa Catarina Albarradas Zapotec"] = "ztn",
["Santa Inés Ahuatempan Popoloca"] = "pca",
["Santa Inés Yatzechi Zapotec"] = "zpn",
["Santa Lucía Monteverde Mixtec"] = "mdv",
["Santa María La Alta Nahuatl"] = "nhz",
["Santa María Quiegolani Zapotec"] = "zpi",
["Santa María Zacatepec Mixtec"] = "mza",
["Santa Teresa Cora"] = "cok",
["Santali"] = "sat",
["Santiago Xanica Zapotec"] = "zpr",
["Santo Domingo Albarradas Zapotec"] = "zas",
["Sanumá"] = "xsu",
["Sanxiang Min"] = "nan-zsh",
["Sapa"] = "tys",
["Saparua"] = "spr",
["Sapará"] = "sai-sap",
["Sapo"] = "krn",
["Saponi"] = "spi",
["Saposa"] = "sps",
["Sapuan"] = "spu",
["Sapé"] = "spc",
["Sar"] = "mwm",
["Sara"] = "sre",
["Sara Kaba"] = "sbz",
["Sara Kaba Deme"] = "kwg",
["Sara Kaba Náà"] = "kwv",
["Saraiki"] = "skr",
["Saramaccan"] = "srm",
["Sarangani Blaan"] = "bps",
["Sarangani Manobo"] = "mbs",
["Sarasira"] = "zsa",
["Saraveca"] = "sar",
["Sarawak Malay"] = "poz-sml",
["Sardinian"] = "sc",
["Sarikoli"] = "srh",
["Sarli"] = "sdf",
["Sartang"] = "onp",
["Sarua"] = "swy",
["Sarudu"] = "sdu",
["Saruga"] = "sra",
["Sasak"] = "sas",
["Sasaru"] = "sxs",
["Sassarese"] = "sdc",
["Satawalese"] = "stw",
["Saterland Frisian"] = "stq",
["Sateré-Mawé"] = "mav",
["Sathmar Swabian"] = "gmw-stm",
["Saudi Arabian Sign Language"] = "sdl",
["Saurashtra"] = "saz",
["Sauri"] = "srt",
["Sause"] = "sao",
["Sausi"] = "ssj",
["Savi"] = "sdg",
["Savosavo"] = "svs",
["Sawai"] = "szw",
["Saweru"] = "swr",
["Sawi"] = "saw",
["Sawila"] = "swt",
["Sawriya Paharia"] = "mjt",
["Saxwe Gbe"] = "sxw",
["Saya"] = "say",
["Sayula Popoluca"] = "pos",
["Scanian"] = "gmq-scy",
["Scots"] = "sco",
["Scottish Gaelic"] = "gd",
["Seba"] = "kdg",
["Sebat Bet Gurage"] = "sgw",
["Seberuang"] = "sbx",
["Sebop"] = "sib",
["Sebuyau"] = "snb",
["Sechelt"] = "sec",
["Sechura"] = "sai-sec",
["Secoya"] = "sey",
["Sedang"] = "sed",
["Sedoa"] = "tvw",
["Seenku"] = "sos",
["Segai"] = "sge",
["Segeju"] = "seg",
["Seget"] = "sbg",
["Sehwi"] = "sfw",
["Seimat"] = "ssg",
["Seit-Kaitetu"] = "hik",
["Sekani"] = "sek",
["Sekapan"] = "skp",
["Sekar"] = "skz",
["Seke"] = "skj",
["Sekele"] = "vaj",
["Seki"] = "syi",
["Seko Padang"] = "skx",
["Seko Tengah"] = "sko",
["Sekpele"] = "lip",
["Selangor Sign Language"] = "kgi",
["Selaru"] = "slu",
["Selayar"] = "sly",
["Selee"] = "snw",
["Selepet"] = "spl",
["Selk'nam"] = "ona",
["Selonian"] = "sxl",
["Selungai Murut"] = "slg",
["Seluwasan"] = "sws",
["Sema"] = "nsm",
["Semai"] = "sea",
["Semandang"] = "sdm",
["Semaq Beri"] = "szc",
["Sembakung Murut"] = "sbr",
["Semelai"] = "sza",
["Semigallian"] = "xzm",
["Semimi"] = "etz",
["Semnam"] = "ssm",
["Semnani"] = "smy",
["Sempan"] = "xse",
["Sena"] = "seh",
["Senara"] = "seq",
["Senaya"] = "syn",
["Sene"] = "sej",
["Seneca"] = "see",
["Sengele"] = "szg",
["Senggi"] = "snu",
["Sengo"] = "spk",
["Sengseng"] = "ssz",
["Senhaja de Srair"] = "sjs",
["Sensi"] = "sni",
["Sentani"] = "set",
["Senthang Chin"] = "sez",
["Sentinelese"] = "std",
["Sepa (Indonesia)"] = "spb",
["Sepa (New Guinea)"] = "spe",
["Sepen"] = "spm",
["Sepik Iwam"] = "iws",
["Sera"] = "sry",
["Serbo-Croatian"] = "sh",
["Sere"] = "swf",
["Serer"] = "srr",
["Seri"] = "sei",
["Serili"] = "sve",
["Seroa"] = "kqu",
["Serrano"] = "ser",
["Seru"] = "szd",
["Serua"] = "srw",
["Serudung Murut"] = "srk",
["Serui-Laut"] = "seu",
["Seta"] = "stf",
["Setaman"] = "stm",
["Seti"] = "sbi",
["Severn Ojibwa"] = "ojs",
["Sewa Bay"] = "sew",
["Seychelles Sign Language"] = "lsw",
["Seychellois Creole"] = "crs",
["Seze"] = "sze",
["Sha"] = "scw",
["Shabak"] = "sdb",
["Shabo"] = "sbf",
["Shahmirzadi"] = "srz",
["Shahrudi"] = "shm",
["Shall-Zwall"] = "sha",
["Shama-Sambuga"] = "sqa",
["Shamang"] = "xsh",
["Shambala"] = "ksb",
["Shan"] = "shn",
["Shanenawa"] = "swo",
["Shanga"] = "sho",
["Shangzhai"] = "jih",
["Shaojiang Min"] = "sjc",
["Shaozhou Tuhua"] = "zhx-sht",
["Sharanahua"] = "mcd",
["Shark Bay"] = "ssv",
["Sharwa"] = "swq",
["Shasta"] = "sht",
["Shatt"] = "shj",
["Shau"] = "sqh",
["Shawnee"] = "sjw",
["She"] = "shx",
["Shebayo"] = "awd-she",
["Shehri"] = "shv",
["Shekkacho"] = "moy",
["Sheko"] = "she",
["Shelta"] = "sth",
["Shendu"] = "shl",
["Sheni"] = "scv",
["Sherbro"] = "bun",
["Sherdukpen"] = "sdp",
["Sherpa"] = "xsr",
["Sheshi Kham"] = "kip",
["Shetland"] = "scz",
["Shi"] = "shr",
["Shihhi Arabic"] = "ssh",
["Shiki"] = "gua",
["Shilluk"] = "shk",
["Shina"] = "scl",
["Shinasha"] = "bwo",
["Shipibo-Conibo"] = "shp",
["Shixing"] = "sxg",
["Sholaga"] = "sle",
["Shom Peng"] = "sii",
["Shona"] = "sn",
["Shoo-Minda-Nye"] = "bcv",
["Shor"] = "cjs",
["Shoshone"] = "shh",
["Shua"] = "shg",
["Shuar"] = "jiv",
["Shughni"] = "sgh",
["Shumashti"] = "sts",
["Shumcho"] = "scu",
["Shuswap"] = "shs",
["Shuwa-Zamani"] = "ksa",
["Shwai"] = "shw",
["Shwe Palaung"] = "pll",
["Sialum"] = "slw",
["Siamou"] = "sif",
["Sian"] = "spg",
["Siane"] = "snp",
["Siang"] = "sya",
["Siar-Lak"] = "sjr",
["Sibe"] = "nco",
["Siberian Tatar"] = "sty",
["Sibu Melanau"] = "sdx",
["Sicanian"] = "sxc",
["Sicel"] = "scx",
["Sichuanese"] = "zhx-sic",
["Sicilian"] = "scn",
["Sicite"] = "sep",
["Siculo-Arabic"] = "sqr",
["Sidamo"] = "sid",
["Sidetic"] = "xsd",
["Sie"] = "erg",
["Sierra Leone Sign Language"] = "sgx",
["Sierra Negra Nahuatl"] = "nsu",
["Sierra de Juárez Zapotec"] = "zaa",
["Sighu"] = "sxe",
["Sihan"] = "snr",
["Sika"] = "ski",
["Sikaiana"] = "sky",
["Sikaritai"] = "tty",
["Sikiana"] = "sik",
["Sikkimese"] = "sip",
["Sikule"] = "skh",
["Sila"] = "slt",
["Silacayoapan Mixtec"] = "mks",
["Silesian"] = "szl",
["Silimo"] = "wul",
["Siliput"] = "mkc",
["Silopi"] = "xsp",
["Silt'e"] = "stv",
["Simaa"] = "sie",
["Simalungun Batak"] = "bts",
["Simba"] = "sbw",
["Simbali"] = "smg",
["Simbari"] = "smb",
["Simbo"] = "sbb",
["Simeku"] = "smz",
["Simeulue"] = "smr",
["Simte"] = "smt",
["Sinacantán"] = "nai-sin",
["Sinagen"] = "siu",
["Sinasina"] = "sst",
["Sinaugoro"] = "snc",
["Sindarin"] = "sjn",
["Sindhi"] = "sd",
["Sindhi Bhil"] = "sbn",
["Sindihui Mixtec"] = "xts",
["Singa"] = "sgm",
["Singapore Sign Language"] = "sls",
["Singpho"] = "sgp",
["Sinhalese"] = "si",
["Sinicahua Mixtec"] = "xti",
["Sininkere"] = "skq",
["Sinte Romani"] = "rmo",
["Sinyar"] = "sys",
["Sinúfana"] = "sai-sin",
["Sio"] = "xsi",
["Siona"] = "snn",
["Sipakapense"] = "qum",
["Sira"] = "swj",
["Siraya"] = "fos",
["Sirenik"] = "ysr",
["Siri"] = "sir",
["Siriano"] = "sri",
["Sirionó"] = "srq",
["Sirmauri"] = "srx",
["Siroi"] = "ssd",
["Sirva"] = "sbq",
["Sisaala"] = "sld",
["Sissano"] = "sso",
["Situ"] = "sit-sit",
["Siuslaw"] = "sis",
["Sivandi"] = "siy",
["Sivia Sign Language"] = "lsv",
["Siwai"] = "siw",
["Siwi"] = "siz",
["Siwu"] = "akp",
["Siyin Chin"] = "csy",
["Skalvian"] = "svx",
["Ske"] = "ske",
["Skepi Creole Dutch"] = "skw",
["Skolt Sami"] = "sms",
["Skou"] = "skv",
["Slavomolisano"] = "svm",
["Slovak"] = "sk",
["Slovakian Sign Language"] = "svk",
["Slovene"] = "sl",
["Slovincian"] = "zlw-slv",
["Small Flowery Miao"] = "sfm",
["Smärky Kanum"] = "kxq",
["So'a"] = "ssq",
["Sobei"] = "sob",
["Sochiapam Chinantec"] = "cso",
["Soga"] = "xog",
["Sogdian"] = "sog",
["Sok"] = "skk",
["Sokna"] = "swn",
["Soko"] = "soc",
["Sokoro"] = "sok",
["Solano"] = "xso",
["Soli"] = "sby",
["Solombala English"] = "crp-slb",
["Solomon Islands Sign Language"] = "szs",
["Solon"] = "tuw-sol",
["Solong"] = "aaw",
["Solos"] = "sol",
["Som"] = "smc",
["Somali"] = "so",
["Somba-Siawari"] = "bmu",
["Somra"] = "ntx",
["Somrai"] = "sor",
["Somray"] = "smu",
["Somyev"] = "kgt",
["Sonaga"] = "ysg",
["Sonde"] = "shc",
["Songe"] = "sop",
["Songlai Chin"] = "csj",
["Songomeno"] = "soe",
["Songoora"] = "sod",
["Sonha"] = "soi",
["Sonia"] = "siq",
["Soninke"] = "snk",
["Sonsorolese"] = "sov",
["Soo"] = "teu",
["Sop"] = "urw",
["Soqotri"] = "sqt",
["Sora"] = "srb",
["Sori-Harengan"] = "sbh",
["Sorkhei"] = "sqo",
["Sorothaptic"] = "sxo",
["Sorsogon Ayta"] = "ays",
["Sos Kundi"] = "sdk",
["Sota Kanum"] = "krz",
["Sotho"] = "st",
["Sou"] = "sqq",
["Sougb"] = "mnx",
["South African Sign Language"] = "sfs",
["South Awyu"] = "aws",
["South Boma"] = "bnt-sbo",
["South Central Banda"] = "lnl",
["South Central Dinka"] = "dib",
["South Efate"] = "erk",
["South Fali"] = "fal",
["South Giziga"] = "giz",
["South Lembata"] = "lmf",
["South Levantine Arabic"] = "ajp",
["South Marquesan"] = "mqm",
["South Muyu"] = "kts",
["South Nuaulu"] = "nxl",
["South Picene"] = "spx",
["South Slavey"] = "xsl",
["South Tairora"] = "omw",
["South Tukang Besi"] = "bhq",
["South Ucayali Ashéninka"] = "cpy",
["South Watut"] = "mcy",
["Southeast Ambrym"] = "tvk",
["Southeast Babar"] = "vbb",
["Southeast Ijo"] = "ijs",
["Southeast Pashayi"] = "psi",
["Southeast Tasmanian"] = "xpf",
["Southeastern Dinka"] = "dks",
["Southeastern Ixtlán Zapotec"] = "zpd",
["Southeastern Kolami"] = "nit",
["Southeastern Nochixtlán Mixtec"] = "mxy",
["Southeastern Pomo"] = "pom",
["Southeastern Puebla Nahuatl"] = "npl",
["Southeastern Tarahumara"] = "tcu",
["Southeastern Tepehuan"] = "stp",
["Southern Alta"] = "agy",
["Southern Altai"] = "alt",
["Southern Amami Ōshima"] = "ams",
["Southern Bai"] = "bfs",
["Southern Birifor"] = "biv",
["Southern Bobo"] = "bwq",
["Southern Bontoc"] = "obk",
["Southern Carrier"] = "caf",
["Southern Catanduanes Bikol"] = "bln",
["Southern Dagaare"] = "dga",
["Southern East Cree"] = "crj",
["Southern Ghale"] = "ghe",
["Southern Grebo"] = "grj",
["Southern Guiyang Hmong"] = "hmy",
["Southern Haida"] = "hax",
["Southern Hindko"] = "hnd",
["Southern Kalapuya"] = "sxk",
["Southern Kalinga"] = "ksc",
["Southern Kam"] = "kmc",
["Southern Khanty"] = "kca-sou",
["Southern Kissi"] = "kss",
["Southern Kiwai"] = "kjd",
["Southern Kurdish"] = "sdh",
["Southern Lolopo"] = "ysp",
["Southern Lorung"] = "lrr",
["Southern Luri"] = "luz",
["Southern Ma'di"] = "snm",
["Southern Mansi"] = "mns-sou",
["Southern Mashan Hmong"] = "hma",
["Southern Mnong"] = "mnn",
["Southern Muji"] = "ymc",
["Southern Ndebele"] = "nr",
["Southern Ngbandi"] = "nbw",
["Southern Nicobarese"] = "nik",
["Southern Nisu"] = "nsd",
["Southern Nuni"] = "nnw",
["Southern Ohlone"] = "css",
["Southern One"] = "osu",
["Southern Pame"] = "pmz",
["Southern Pinghua"] = "csp",
["Southern Pomo"] = "peq",
["Southern Puebla Mixtec"] = "mit",
["Southern Pumi"] = "pmj",
["Southern Qiandong Miao"] = "hms",
["Southern Qiang"] = "qxs",
["Southern Rengma Naga"] = "nre",
["Southern Rincon Zapotec"] = "zsr",
["Southern Roglai"] = "rgs",
["Southern Sama"] = "ssb",
["Southern Sami"] = "sma",
["Southern Samo"] = "sbd",
["Southern Selkup"] = "sel-sou",
["Southern Sierra Miwok"] = "skd",
["Southern Thai"] = "sou",
["Southern Tidung"] = "itd",
["Southern Tiwa"] = "tix",
["Southern Toussian"] = "wib",
["Southern Tujia"] = "tjs",
["Southern Tutchone"] = "tce",
["Southern Valley Yokuts"] = "yok-svy",
["Southern Yukaghir"] = "yux",
["Southwest Gbaya"] = "gso",
["Southwest Palawano"] = "plv",
["Southwest Pashayi"] = "psh",
["Southwest Tanna"] = "nwi",
["Southwestern Bontoc"] = "vbk",
["Southwestern Dinka"] = "dik",
["Southwestern Fars"] = "fay",
["Southwestern Guiyang Hmong"] = "hmg",
["Southwestern Huishui Hmong"] = "hmh",
["Southwestern Tarahumara"] = "twr",
["Southwestern Tepehuan"] = "tla",
["Southwestern Tlaxiaco Mixtec"] = "meh",
["Sowa"] = "sww",
["Sowanda"] = "sow",
["Soyaltepec Mazatec"] = "vmp",
["Soyaltepec Mixtec"] = "vmq",
["Spanish"] = "es",
["Spanish Sign Language"] = "ssp",
["Spiti Bhoti"] = "spt",
["Spokane"] = "spo",
["Squamish"] = "squ",
["Sranan Tongo"] = "srn",
["Sri Lankan Creole Malay"] = "sci",
["Sri Lankan Sign Language"] = "sqs",
["Stau"] = "ero-tau",
["Stod Bhoti"] = "sbu",
["Stoney"] = "sto",
["Suabo"] = "szp",
["Suau"] = "swp",
["Suba"] = "sxb",
["Suba-Simbiti"] = "ssc",
["Subi"] = "xsj",
["Subiya"] = "sbs",
["Subtiaba"] = "sut",
["Sudanese Arabic"] = "apd",
["Sudest"] = "tgo",
["Sudovian"] = "xsv",
["Suena"] = "sue",
["Suga"] = "sgi",
["Suganga"] = "sug",
["Sugut Dusun"] = "kzs",
["Sui"] = "swi",
["Suki"] = "sui",
["Suku"] = "sub",
["Sukuma"] = "suk",
["Sukur"] = "syk",
["Sukurum"] = "zsu",
["Sula"] = "szn",
["Sulka"] = "sua",
["Sulod"] = "srg",
["Suma"] = "sqm",
["Sumariup"] = "siv",
["Sumau"] = "six",
["Sumbawa"] = "smw",
["Sumbwa"] = "suw",
["Sumerian"] = "sux",
["Sumtu Chin"] = "csv",
["Sunam"] = "ssk",
["Sundanese"] = "su",
["Sungwadaga"] = "mwo",
["Sungwadia"] = "mrb",
["Sunum"] = "ymn",
["Sunwar"] = "suz",
["Suoy"] = "syo",
["Supyire"] = "spp",
["Sur"] = "tdl",
["Surbakhal"] = "sbj",
["Suri"] = "suq",
["Surigaonon"] = "sgd",
["Surjapuri"] = "sjp",
["Sursurunga"] = "sgz",
["Suruahá"] = "swx",
["Surubu"] = "sde",
["Suruí"] = "sru",
["Suruí Do Pará"] = "mdz",
["Susquehannock"] = "sqn",
["Susu"] = "sus",
["Susuami"] = "ssu",
["Suundi"] = "sdj",
["Suwawa"] = "swu",
["Suyá"] = "suy",
["Svan"] = "sva",
["Swabian"] = "swg",
["Swahili"] = "sw",
["Swampy Cree"] = "csw",
["Swazi"] = "ss",
["Swedish"] = "sv",
["Swedish Sign Language"] = "swl",
["Swiss-French Sign Language"] = "ssr",
["Swiss-German Sign Language"] = "sgg",
["Swiss-Italian Sign Language"] = "slf",
["Swo"] = "sox",
["Syenara"] = "shz",
["Sylheti"] = "syl",
["Sácata"] = "sai-sac",
["São Paulo Kaingáng"] = "zkp",
["Sãotomense"] = "cri",
["Sîshëë"] = "sih",
["Sô"] = "sss",
["T'en"] = "tct",
["Taabwa"] = "tap",
["Taba"] = "mky",
["Tabaa Zapotec"] = "zat",
["Tabancale"] = "sai-tab",
["Tabaru"] = "tby",
["Tabasaran"] = "tab",
["Tabasco Nahuatl"] = "nhc",
["Tabasco Zoque"] = "zoq",
["Tabla"] = "tnm",
["Tabo"] = "knv",
["Tabriak"] = "tzx",
["Tacahua Mixtec"] = "xtt",
["Tacana"] = "tna",
["Tachawit"] = "shy",
["Tadaksahak"] = "dsq",
["Tadyawan"] = "tdy",
["Tae'"] = "rob",
["Tafi"] = "tcd",
["Tafreshi"] = "xme-taf",
["Tagabawa"] = "bgs",
["Tagakaulu Kalagan"] = "klg",
["Tagal Murut"] = "mvv",
["Tagalog"] = "tl",
["Tagbu"] = "tbm",
["Tagdal"] = "tda",
["Tagish"] = "tgx",
["Tagoi"] = "tag",
["Tagwana"] = "tgw",
["Tahitian"] = "ty",
["Tahltan"] = "tht",
["Tai"] = "taw",
["Tai Daeng"] = "tyr",
["Tai Dam"] = "blt",
["Tai Do"] = "tyj",
["Tai Dón"] = "twh",
["Tai Hang Tong"] = "thc",
["Tai Hongjin"] = "tiz",
["Tai Laing"] = "tjl",
["Tai Loi"] = "tlq",
["Tai Long"] = "thi",
["Tai Nüa"] = "tdd",
["Tai Pao"] = "tpo",
["Tai Thanh"] = "tmm",
["Tai Ya"] = "cuu",
["Taiap"] = "gpn",
["Taikat"] = "aos",
["Taimyr Pidgin Russian"] = "crp-tpr",
["Tainae"] = "ago",
["Tairuma"] = "uar",
["Taishanese"] = "zhx-tai",
["Taita"] = "dav",
["Taivoan"] = "tvx",
["Taiwan Sign Language"] = "tss",
["Taje"] = "pee",
["Tajik"] = "tg",
["Tajiki Arabic"] = "abh",
["Tajio"] = "tdj",
["Tajuasohn"] = "tja",
["Takelma"] = "tkm",
["Takia"] = "tbc",
["Takua"] = "tkz",
["Takuu"] = "nho",
["Takwane"] = "tke",
["Tal"] = "tal",
["Tala"] = "tak",
["Talaud"] = "tld",
["Taliabu"] = "tlv",
["Talieng"] = "tdf",
["Talinga-Bwisi"] = "tlj",
["Talise"] = "tlr",
["Tallán"] = "sai-tal",
["Talodi"] = "tlo",
["Taloki"] = "tlk",
["Talondo'"] = "tln",
["Talossan"] = "tzl",
["Talu"] = "yta",
["Talysh"] = "tly",
["Tama (Chad)"] = "tma",
["Tama (Colombia)"] = "ten",
["Tamagario"] = "tcg",
["Tamambo"] = "mla",
["Taman (Indonesia)"] = "tmn",
["Taman (Myanmar)"] = "tcl",
["Tamanaku"] = "tmz",
["Tamazola Mixtec"] = "vmx",
["Tambas"] = "tdk",
["Tambora"] = "xxt",
["Tambotalo"] = "tls",
["Tami"] = "tmy",
["Tamil"] = "ta",
["Tamki"] = "tax",
["Tamnim Citak"] = "tml",
["Tampias Lobu"] = "low",
["Tampuan"] = "tpu",
["Tampulma"] = "tpm",
["Tanacross"] = "tcb",
["Tanah Merah"] = "tcm",
["Tanapag"] = "tpv",
["Tanchangya"] = "tnv",
["Tandaganon"] = "tgn",
["Tandia"] = "tni",
["Tanema"] = "tnx",
["Tangale"] = "tan",
["Tangam"] = "sit-tgm",
["Tanggu"] = "tgu",
["Tangkhul Naga"] = "nmf",
["Tangko"] = "tkx",
["Tangoa"] = "tgp",
["Tangsa"] = "nst",
["Tanguat"] = "tbs",
["Tangut"] = "txg",
["Tangwang"] = "mis-tnw",
["Tanimbili"] = "tbe",
["Tanimuca-Retuarã"] = "tnc",
["Tanjijili"] = "uji",
["Tanudan Kalinga"] = "kml",
["Tanzanian Sign Language"] = "tza",
["Taos"] = "twf",
["Tapachultec"] = "nai-tap",
["Taparita"] = "sai-tpr",
["Tapayuna"] = "sai-tap",
["Tapei"] = "afp",
["Tapieté"] = "tpj",
["Tapirapé"] = "taf",
["Tar Gula"] = "kcm",
["Tara Baka"] = "bdh",
["Tarairiú"] = "sai-trr",
["Tarantino"] = "roa-tar",
["Tarao"] = "tro",
["Taraon"] = "mhu",
["Tareng"] = "tgr",
["Tariana"] = "tae",
["Tarifit"] = "rif",
["Tarjumo"] = "txj",
["Tarok"] = "yer",
["Taroko"] = "trv",
["Tarpia"] = "tpf",
["Tartessian"] = "txr",
["Taruma"] = "tdm",
["Tasawaq"] = "twq",
["Tashelhit"] = "shi",
["Tasmate"] = "tmt",
["Tat"] = "ttt",
["Tataltepec Chatino"] = "cta",
["Tatana"] = "txx",
["Tatar"] = "tt",
["Tataviam"] = "azc-tat",
["Tatuyo"] = "tav",
["Tauade"] = "ttd",
["Taulil"] = "tuh",
["Taungyo"] = "tco",
["Taupota"] = "tpa",
["Tause"] = "tad",
["Taushiro"] = "trr",
["Tausug"] = "tsg",
["Tauya"] = "tya",
["Taveta"] = "tvs",
["Tavoyan"] = "tvn",
["Tavringer Romani"] = "rmu",
["Tawala"] = "tbo",
["Tawandê"] = "xtw",
["Tawang Monpa"] = "twm",
["Tawasa"] = "nai-taw",
["Taworta"] = "tbp",
["Tawoyan"] = "twy",
["Tawr Chin"] = "tcp",
["Tay Khang"] = "tnu",
["Taymanitic"] = "sem-tay",
["Tayo"] = "cks",
["Taíno"] = "tnq",
["Tboli"] = "tbl",
["Tchitchege"] = "tck",
["Tchumbuli"] = "bqa",
["Te'un"] = "tve",
["Teanu"] = "tkw",
["Tebul Sign Language"] = "tsy",
["Tebul Ure Dogon"] = "dtu",
["Tecpatlán Totonac"] = "tcw",
["Tedaga"] = "tuq",
["Tedim Chin"] = "ctd",
["Tee"] = "tkq",
["Tefaro"] = "tfo",
["Tegali"] = "ras",
["Tehit"] = "kps",
["Tehuelche"] = "teh",
["Teiwa"] = "twe",
["Tejalapan Zapotec"] = "ztt",
["Teke-Fuumu"] = "ifm",
["Teke-Kukuya"] = "kkw",
["Teke-Laali"] = "lli",
["Teke-Tege"] = "teg",
["Teke-Tsaayi"] = "tyi",
["Teke-Tyee"] = "tyx",
["Tektiteko"] = "ttc",
["Tela-Masbuar"] = "tvm",
["Telefol"] = "tlf",
["Telugu"] = "te",
["Teluti"] = "tlt",
["Tem"] = "kdh",
["Temascaltepec Nahuatl"] = "nhv",
["Tembé"] = "tqb",
["Teme"] = "tdo",
["Temein"] = "teq",
["Temi"] = "soz",
["Temiar"] = "tea",
["Temne"] = "tem",
["Temoaya Otomi"] = "ott",
["Temoq"] = "tmo",
["Ten'edn"] = "tnz",
["Tenango Otomi"] = "otn",
["Tene Kan Dogon"] = "dtk",
["Tenggarong Kutai Malay"] = "vkt",
["Tengger"] = "tes",
["Tenharim"] = "pah",
["Tenino"] = "tqn",
["Tenis"] = "tns",
["Tennet"] = "tex",
["Teochew"] = "nan-tws",
["Teojomulco Chatino"] = "omq-teo",
["Teop"] = "tio",
["Teor"] = "tev",
["Tepecano"] = "tep",
["Tepetotutla Chinantec"] = "cnt",
["Tepeuxila Cuicatec"] = "cux",
["Tepinapa Chinantec"] = "cte",
["Tepo Krumen"] = "ted",
["Teposcolula Mixtec"] = "omq-tel",
["Tequistlatec"] = "nai-teq",
["Ter Sami"] = "sjt",
["Tera"] = "ttr",
["Terebu"] = "trb",
["Terei"] = "buo",
["Terengganu Malay"] = "poz-ter",
["Tereno"] = "ter",
["Teressa"] = "tef",
["Tereweng"] = "twg",
["Teribe"] = "tfr",
["Terik"] = "tec",
["Termanu"] = "twu",
["Ternate"] = "tft",
["Ternateño"] = "tmg",
["Tese"] = "keg",
["Teshenawa"] = "twc",
["Tetela"] = "tll",
["Tetelcingo Nahuatl"] = "nhg",
["Tetete"] = "teb",
["Tetserret"] = "tez",
["Tetum"] = "tet",
["Tetun Dili"] = "tdt",
["Teushen"] = "sai-teu",
["Teutila Cuicatec"] = "cut",
["Tewa"] = "tew",
["Texcatepec Otomi"] = "otx",
["Texistepec Popoluca"] = "poq",
["Texmelucan Zapotec"] = "zpz",
["Tezoatlán Mixtec"] = "mxb",
["Tha"] = "thy",
["Thachanadan"] = "thn",
["Thado Chin"] = "tcz",
["Thai"] = "th",
["Thai Mon"] = "mnw-tha",
["Thai Sign Language"] = "tsq",
["Thai Song"] = "soa",
["Thaiphum Chin"] = "cth",
["Thakali"] = "ths",
["Thamudic"] = "sem-tha",
["Thangal Naga"] = "nki",
["Thangmi"] = "thf",
["Thao"] = "ssf",
["Tharaka"] = "thk",
["Tharrgari"] = "dhr",
["Thavung"] = "thm",
["Thawa"] = "xtv",
["Tho"] = "tou",
["Thompson"] = "thp",
["Thopho"] = "ytp",
["Thracian"] = "txh",
["Thu Lao"] = "tyl",
["Thulung"] = "tdh",
["Thurawal"] = "tbh",
["Thuri"] = "thu",
["Tiagba"] = "ahi",
["Tiale"] = "mnl",
["Tiang"] = "tbj",
["Tibea"] = "ngy",
["Tibetan"] = "bo",
["Tibetan Sign Language"] = "lsn",
["Ticuna"] = "tca",
["Tidaá Mixtec"] = "mtx",
["Tidore"] = "tvo",
["Tiemacèwè Bozo"] = "boo",
["Tiene"] = "tii",
["Tifal"] = "tif",
["Tigak"] = "tgc",
["Tigon Mbembe"] = "nza",
["Tigre"] = "tig",
["Tigrinya"] = "ti",
["Tii"] = "txq",
["Tijaltepec Mixtec"] = "xtl",
["Tikar"] = "tik",
["Tikopia"] = "tkp",
["Tilapa Otomi"] = "otl",
["Tillamook"] = "til",
["Tilquiapan Zapotec"] = "zts",
["Tilung"] = "tij",
["Tima"] = "tms",
["Timbe"] = "tim",
["Timor Pidgin"] = "tvy",
["Timote"] = "sai-tim",
["Timucua"] = "tjm",
["Timugon Murut"] = "tih",
["Tinani"] = "lbf",
["Tindi"] = "tin",
["Tingui-Boto"] = "tgv",
["Tinigua"] = "tit",
["Tinoc Kallahan"] = "tne",
["Tinputz"] = "tpz",
["Tinrin"] = "cir",
["Tipai"] = "nai-tip",
["Tippera"] = "tpe",
["Tira"] = "tic",
["Tirahi"] = "tra",
["Tiranige Diga Dogon"] = "tde",
["Tirax"] = "mme",
["Tiruray"] = "tiy",
["Tita"] = "tdq",
["Titan"] = "ttv",
["Tiv"] = "tiv",
["Tiwa"] = "lax",
["Tiwi"] = "tiw",
["Tiéfo"] = "tiq",
["Tiéyaxo Bozo"] = "boz",
["Tjurruru"] = "tju",
["Tlachichilco Tepehua"] = "tpt",
["Tlacoapa Me'phaa"] = "tpl",
["Tlacoatzintepec Chinantec"] = "ctl",
["Tlacolulita Zapotec"] = "zpk",
["Tlahuica"] = "ocu",
["Tlahuitoltepec Mixe"] = "mxp",
["Tlamacazapa Nahuatl"] = "nuz",
["Tlazoyaltepec Mixtec"] = "mqh",
["Tlingit"] = "tli",
["To"] = "toz",
["To'abaita"] = "mlu",
["Toaripi"] = "tqo",
["Toba"] = "tob",
["Toba Batak"] = "bbc",
["Toba-Maskoy"] = "tmf",
["Tobagonian Creole English"] = "tgh",
["Tobanga"] = "tng",
["Tobati"] = "tti",
["Tobelo"] = "tlb",
["Tobian"] = "tox",
["Tobilung"] = "tgb",
["Tobo"] = "tbv",
["Tocantins Asurini"] = "asu",
["Tocharian A"] = "xto",
["Tocharian B"] = "txb",
["Tocho"] = "taz",
["Toda"] = "tcx",
["Todrah"] = "tdr",
["Tofa"] = "kim",
["Tofanma"] = "tlg",
["Tofin Gbe"] = "tfi",
["Togbo-Vara Banda"] = "tor",
["Togoyo"] = "tgy",
["Tojolabal"] = "toj",
["Tok Pisin"] = "tpi",
["Toka-Leya"] = "dov",
["Tokano"] = "zuh",
["Tokelauan"] = "tkl",
["Toki Pona"] = "tok",
["Tokunoshima"] = "tkn",
["Tol"] = "jic",
["Tolai"] = "ksd",
["Tolaki"] = "lbw",
["Tolomako"] = "tlm",
["Tolowa"] = "tol",
["Toloza"] = "ytl",
["Toma"] = "tod",
["Tomadino"] = "tdi",
["Tombelala"] = "ttp",
["Tombonuo"] = "txa",
["Tombulu"] = "tom",
["Tomini"] = "txm",
["Tommeginne"] = "xpv",
["Tommo So"] = "dto",
["Tomo Kan Dogon"] = "dtm",
["Tomoip"] = "tqp",
["Tondano"] = "tdn",
["Tonga (Malawi)"] = "tog",
["Tonga (Mozambique)"] = "toh",
["Tonga (Zambia)"] = "toi",
["Tongan"] = "to",
["Tongwe"] = "tny",
["Tonjon"] = "tjn",
["Tonkawa"] = "tqw",
["Tonsawang"] = "tnw",
["Tonsea"] = "txs",
["Tontemboan"] = "tnt",
["Toogee"] = "xpx",
["Tooro"] = "ttj",
["Topoiyo"] = "toy",
["Toposa"] = "toq",
["Toraja-Sa'dan"] = "sda",
["Toram"] = "trj",
["Torau"] = "ttu",
["Toro"] = "tdv",
["Toro So Dogon"] = "dts",
["Toro Tegu Dogon"] = "dtt",
["Toromono"] = "tno",
["Torona"] = "tqr",
["Torres Strait Creole"] = "tcs",
["Torricelli"] = "tei",
["Torwali"] = "trw",
["Torá"] = "trz",
["Tosu"] = "sit-tos",
["Totela"] = "ttl",
["Toto"] = "txo",
["Totoli"] = "txe",
["Totomachapan Zapotec"] = "zph",
["Totontepec Mixe"] = "mto",
["Totoro"] = "ttk",
["Touo"] = "tqu",
["Toura"] = "neb",
["Towei"] = "ttn",
["Translingual"] = "mul",
["Transylvanian Saxon"] = "gmw-tsx",
["Traveller Danish"] = "rmd",
["Traveller Norwegian"] = "rmg",
["Traveller Scottish"] = "trl",
["Tregami"] = "trm",
["Tremembé"] = "tme",
["Trieng"] = "stg",
["Trimuris"] = "tip",
["Tring"] = "tgq",
["Tringgus"] = "trx",
["Trinidad and Tobago Sign Language"] = "lst",
["Trinidadian Creole English"] = "trf",
["Trinitario"] = "trn",
["Trió"] = "tri",
["Truká"] = "tka",
["Trumai"] = "tpy",
["Ts'ün-Lao"] = "tsl",
["Tsaangi"] = "tsa",
["Tsafiki"] = "cof",
["Tsakhur"] = "tkr",
["Tsakonian"] = "tsd",
["Tsakwambo"] = "kvz",
["Tsamai"] = "tsb",
["Tsat"] = "huq",
["Tsetsaut"] = "txc",
["Tsez"] = "ddo",
["Tshangla"] = "tsj",
["Tshobdun"] = "sit-tsh",
["Tshwa"] = "hio",
["Tsikimba"] = "kdl",
["Tsimané"] = "cas",
["Tsimshian"] = "tsi",
["Tsishingini"] = "tsw",
["Tso"] = "ldp",
["Tsogo"] = "tsv",
["Tsonga"] = "ts",
["Tsotsitaal"] = "fly",
["Tsou"] = "tsu",
["Tsucuba"] = "cbq",
["Tsum"] = "ttz",
["Tsuut'ina"] = "srs",
["Tsuvadi"] = "tvd",
["Tsuvan"] = "tsh",
["Tswa"] = "tsc",
["Tswana"] = "tn",
["Tswapong"] = "two",
["Tuamotuan"] = "pmt",
["Tuareg"] = "tmh",
["Tubar"] = "tbu",
["Tucano"] = "tuo",
["Tugen"] = "tuy",
["Tugun"] = "tzn",
["Tugutil"] = "tuj",
["Tuki"] = "bag",
["Tukpa"] = "tpq",
["Tukudede"] = "tkd",
["Tukumanféd"] = "tkf",
["Tula"] = "tul",
["Tule-Kaweah Yokuts"] = "yok-tky",
["Tulehu"] = "tlu",
["Tulishi"] = "tey",
["Tulu"] = "tcy",
["Tulu-Bohuai"] = "rak",
["Tulua"] = "aus-tul",
["Tuma-Irumu"] = "iou",
["Tumak"] = "tmc",
["Tumbuka"] = "tum",
["Tumi"] = "kku",
["Tumleo"] = "tmq",
["Tumshuqese"] = "xtq",
["Tumtum"] = "tbr",
["Tumulung Sisaala"] = "sil",
["Tundra Enets"] = "enh",
["Tundra Nenets"] = "yrk-tun",
["Tunen"] = "tvu",
["Tungag"] = "lcm",
["Tunggare"] = "trt",
["Tunia"] = "tug",
["Tunica"] = "tun",
["Tunisian Arabic"] = "aeb",
["Tunisian Berber"] = "sds",
["Tunisian Sign Language"] = "tse",
["Tunjung"] = "tjg",
["Tunni"] = "tqq",
["Tunumiisut"] = "esx-tut",
["Tunzu"] = "dza",
["Tuoba"] = "mis-tuo",
["Tuotomb"] = "ttf",
["Tuparí"] = "tpr",
["Tupinambá"] = "tpn",
["Tupinikin"] = "tpk",
["Tupuri"] = "tui",
["Turaka"] = "trh",
["Turdetanian"] = "mis-tdt",
["Turdulian"] = "mis-tdl",
["Turi"] = "trd",
["Turiwára"] = "twt",
["Turka"] = "tuz",
["Turkana"] = "tuv",
["Turkish"] = "tr",
["Turkish Sign Language"] = "tsm",
["Turkmen"] = "tk",
["Turks and Caicos Creole English"] = "tch",
["Turoyo"] = "tru",
["Turumsa"] = "tqm",
["Turung"] = "try",
["Tuscarora"] = "tus",
["Tutelo"] = "tta",
["Tutong"] = "ttg",
["Tutsa Naga"] = "tvt",
["Tutuba"] = "tmi",
["Tututepec Mixtec"] = "mtu",
["Tututni"] = "tuu",
["Tuvaluan"] = "tvl",
["Tuvan"] = "tyv",
["Tuwali Ifugao"] = "ifk",
["Tuwari"] = "tww",
["Tuwuli"] = "bov",
["Tuxináwa"] = "tux",
["Tuxá"] = "tud",
["Tuyuca"] = "tue",
["Tuyuhun"] = "mis-tuh",
["Twana"] = "twa",
["Twendi"] = "twn",
["Tyap"] = "kcg",
["Tyaraity"] = "woa",
["Tyerrernotepanner"] = "xph",
["Tz'utujil"] = "tzj",
["Tzeltal"] = "tzh",
["Tzotzil"] = "tzo",
["Tày"] = "tyz",
["Tày Tac"] = "tyt",
["Tây Bồi"] = "tas",
["Téén"] = "lor",
["Tübatulabal"] = "tub",
["U"] = "uuu",
["Uab Meto"] = "aoz",
["Uamué"] = "uam",
["Uare"] = "ksj",
["Ubaghara"] = "byc",
["Ubang"] = "uba",
["Ubi"] = "ubi",
["Ubir"] = "ubr",
["Ubykh"] = "uby",
["Ucayali-Yurúa Ashéninka"] = "cpb",
["Uda"] = "uda",
["Udi"] = "udi",
["Udihe"] = "ude",
["Udmurt"] = "udm",
["Uduk"] = "udu",
["Ufim"] = "ufi",
["Ugandan Sign Language"] = "ugn",
["Ugaritic"] = "uga",
["Ughele"] = "uge",
["Uhami"] = "uha",
["Uisai"] = "uis",
["Ujir"] = "udj",
["Ukaan"] = "kcf",
["Ukhwejo"] = "ukh",
["Ukit"] = "umi",
["Ukpe-Bayobiri"] = "ukp",
["Ukpet-Ehom"] = "akd",
["Ukrainian"] = "uk",
["Ukrainian Sign Language"] = "ukl",
["Ukue"] = "uku",
["Ukuriguma"] = "ukg",
["Ukwa"] = "ukq",
["Ukwuani-Aboh-Ndoni"] = "ukw",
["Ulau-Suain"] = "svb",
["Ulch"] = "ulc",
["Uldeme"] = "udl",
["Ulithian"] = "uli",
["Ullatan"] = "ull",
["Ulumanda'"] = "ulm",
["Ulwa (New Guinea)"] = "yla",
["Ulwa (Nicaragua)"] = "ulw",
["Uma"] = "ppk",
["Uma' Lasan"] = "xky",
["Uma' Lung"] = "ulu",
["Umanakaina"] = "gdn",
["Umatilla"] = "uma",
["Umbindhamu"] = "umd",
["Umbrian"] = "xum",
["Umbu-Ungu"] = "ubu",
["Umbugarla"] = "umr",
["Umbundu"] = "umb",
["Umbuygamu"] = "umg",
["Ume Sami"] = "sju",
["Umeda"] = "upi",
["Umiida"] = "xud",
["Umiray Dumaget Agta"] = "due",
["Umon"] = "umm",
["Umotína"] = "umo",
["Umpila"] = "ump",
["Una"] = "mtg",
["Unami"] = "unm",
["Unde Kaili"] = "unz",
["Undetermined"] = "und",
["Uneapa"] = "bbn",
["Uneme"] = "une",
["Unggaranggu"] = "xun",
["Unggumi"] = "xgu",
["Uni"] = "uni",
["Unserdeutsch"] = "uln",
["Unua"] = "onu",
["Unubahe"] = "unu",
["Uokha"] = "uok",
["Upper Chehalis"] = "cjh",
["Upper Grand Valley Dani"] = "dna",
["Upper Kinabatangan"] = "dmg",
["Upper Kuskokwim"] = "kuu",
["Upper Mandobo"] = "aax",
["Upper Necaxa Totonac"] = "tku",
["Upper Sorbian"] = "hsb",
["Upper Ta'oih"] = "tth",
["Upper Tanana"] = "tau",
["Upper Taromi"] = "tov",
["Upper Umpqua"] = "xup",
["Ura (New Guinea)"] = "uro",
["Ura (Vanuatu)"] = "uur",
["Uradhi"] = "urf",
["Urak Lawoi'"] = "urk",
["Urali"] = "url",
["Urapmin"] = "urm",
["Urarina"] = "ura",
["Urartian"] = "xur",
["Urat"] = "urt",
["Urdu"] = "ur",
["Urhobo"] = "urh",
["Uri"] = "uvh",
["Urigina"] = "urg",
["Urim"] = "uri",
["Urimo"] = "urx",
["Urningangg"] = "urc",
["Uru"] = "ure",
["Uru-Eu-Wau-Wau"] = "urz",
["Uru-Pa-In"] = "urp",
["Uruangnirin"] = "urn",
["Uruava"] = "urv",
["Urubú-Kaapor"] = "urb",
["Uruguayan Sign Language"] = "ugy",
["Urum"] = "uum",
["Urumi"] = "uru",
["Usaghade"] = "usk",
["Usan"] = "wnu",
["Usarufa"] = "usa",
["Ushojo"] = "ush",
["Usila Chinantec"] = "cuc",
["Uspanteco"] = "usp",
["Usui"] = "usi",
["Utarmbung"] = "omo",
["Ute"] = "ute",
["Utu"] = "utu",
["Uvbie"] = "evh",
["Uwinymil"] = "aus-uwi",
["Uya"] = "usu",
["Uyajitaya"] = "duk",
["Uyghur"] = "ug",
["Uzbek"] = "uz",
["Uzbeki Arabic"] = "auz",
["Uzekwe"] = "eze",
["Vaagri Booli"] = "vaa",
["Vaghri"] = "vgr",
["Vaghua"] = "tva",
["Vagla"] = "vag",
["Vai"] = "vai",
["Vaiphei"] = "vap",
["Vale"] = "vae",
["Valencian Sign Language"] = "vsv",
["Valle Nacional Chinantec"] = "cvn",
["Valley Maidu"] = "vmv",
["Valman"] = "van",
["Valpei"] = "vlp",
["Vamale"] = "mkt",
["Vame"] = "mlr",
["Vandalic"] = "xvn",
["Vangunu"] = "mpr",
["Vanimo"] = "vam",
["Vanji"] = "ira-wnj",
["Vanuma"] = "vau",
["Vao"] = "vao",
["Varhadi"] = "vah",
["Varisi"] = "vrs",
["Varli"] = "vav",
["Vasavi"] = "vas",
["Vayu"] = "vay",
["Veddah"] = "ved",
["Vehes"] = "val",
["Vemgo-Mabas"] = "vem",
["Venda"] = "ve",
["Venetan"] = "vec",
["Venetic"] = "xve",
["Venezuelan Sign Language"] = "vsl",
["Ventureño"] = "veo",
["Veps"] = "vep",
["Vera'a"] = "vra",
["Vestinian"] = "xvs",
["Vidunda"] = "vid",
["Viemo"] = "vig",
["Vietnamese"] = "vi",
["Vilamovian"] = "wym",
["Vilela"] = "vil",
["Vili"] = "vif",
["Vincentian Creole English"] = "svc",
["Vinitiri"] = "vmg",
["Virgin Islands Creole"] = "vic",
["Vishavan"] = "vis",
["Viti"] = "vit",
["Vitou"] = "vto",
["Viya"] = "gev",
["Vlax Romani"] = "rmy",
["Volapük"] = "vo",
["Volga German"] = "gmw-vog",
["Volscian"] = "xvo",
["Vono"] = "kch",
["Voro"] = "vor",
["Votic"] = "vot",
["Vumbu"] = "vum",
["Vunapu"] = "vnp",
["Vunjo"] = "vun",
["Vurës"] = "msn",
["Vute"] = "vut",
["Võro"] = "vro",
["Wa"] = "wbm",
["Wa'ema"] = "wag",
["Waama"] = "wwa",
["Waamwang"] = "wmn",
["Wab"] = "wab",
["Wabo"] = "wbb",
["Waboda"] = "kmx",
["Waci Gbe"] = "wci",
["Wadaginam"] = "wdg",
["Waddar"] = "wbq",
["Wadi Wadi"] = "xwd",
["Wadiyara Koli"] = "kxp",
["Wadjabangayi"] = "wdy",
["Wadjiginy"] = "wdj",
["Wadjigu"] = "wdu",
["Wae Rana"] = "wrx",
["Waffa"] = "waj",
["Wagawaga"] = "wgb",
["Wagaya"] = "wga",
["Wagdi"] = "wbr",
["Wageman"] = "waq",
["Wagi"] = "fad",
["Wahau Kayan"] = "whu",
["Wahau Kenyah"] = "whk",
["Wahgi"] = "wgi",
["Waigali"] = "wbk",
["Waigeo"] = "wgo",
["Waikuri"] = "nai-wai",
["Wailaki"] = "wlk",
["Wailapa"] = "wlr",
["Waima'a"] = "wmh",
["Waimaha"] = "bao",
["Waimiri-Atroari"] = "atr",
["Wainumá"] = "awd-wai",
["Waioli"] = "wli",
["Waitaká"] = "sai-wai",
["Waiwai"] = "waw",
["Waja"] = "wja",
["Wajarri"] = "wbv",
["Wajuk"] = "xwj",
["Waka"] = "wav",
["Wakawaka"] = "wkw",
["Wakhi"] = "wbl",
["Wakoná"] = "waf",
["Wala"] = "lgl",
["Walak"] = "wlw",
["Walangama"] = "nlw",
["Wali (Ghana)"] = "wlx",
["Wali (Sudan)"] = "wll",
["Waling"] = "wly",
["Walio"] = "wla",
["Walla Walla"] = "waa",
["Wallisian"] = "wls",
["Walloon"] = "wa",
["Walmajarri"] = "wmt",
["Wam"] = "wmo",
["Wamas"] = "wmc",
["Wambaya"] = "wmb",
["Wambon"] = "wms",
["Wambule"] = "wme",
["Wamey"] = "cou",
["Wamin"] = "wmi",
["Wampar"] = "lbq",
["Wampur"] = "waz",
["Wan"] = "wan",
["Wanap"] = "wnp",
["Wancho"] = "nnp",
["Wanda"] = "wbh",
["Wandala"] = "mfi",
["Wandamen"] = "wad",
["Wandarang"] = "wnd",
["Wandji"] = "wdd",
["Waneci"] = "wne",
["Wanga"] = "lwg",
["Wanggamala"] = "wnm",
["Wangganguru"] = "wgg",
["Wanggom"] = "wng",
["Wangkayutyuru"] = "wky",
["Wangkumara"] = "xwk",
["Wanham"] = "sai-wnm",
["Wanji"] = "wbi",
["Wanman"] = "wbt",
["Wannu"] = "jub",
["Wano"] = "wno",
["Wantoat"] = "wnc",
["Wanukaka"] = "wnk",
["Wanyi"] = "wny",
["Wané"] = "hwa",
["Wapan"] = "juk",
["Wapishana"] = "wap",
["Wappo"] = "wao",
["War-Jaintia"] = "aml",
["Wara"] = "wbf",
["Warao"] = "wba",
["Warapu"] = "wra",
["Waray Sorsogon"] = "srv",
["Waray-Waray"] = "war",
["Wardaman"] = "wrr",
["Wardandi"] = "wxw",
["Warekena"] = "gae",
["Warembori"] = "wsa",
["Wari'"] = "pav",
["Waris"] = "wrs",
["Waritai"] = "wbe",
["Wariyangga"] = "wri",
["Warji"] = "wji",
["Warkay-Bipim"] = "bgv",
["Warlmanpa"] = "wrl",
["Warlpiri"] = "wbp",
["Warluwara"] = "wrb",
["Warnang"] = "wrn",
["Waropen"] = "wrp",
["Warray"] = "wrz",
["Warrgamay"] = "wgy",
["Warrwa"] = "wwr",
["Waru"] = "wru",
["Warumungu"] = "wrm",
["Waruna"] = "wrv",
["Warungu"] = "wrg",
["Warwar Feni"] = "hrw",
["Wasco-Wishram"] = "wac",
["Wasembo"] = "gsp",
["Washo"] = "was",
["Waskia"] = "wsk",
["Wastek"] = "hus",
["Wasu"] = "wsu",
["Watakataui"] = "wtk",
["Watam"] = "wax",
["Wathaurong"] = "wth",
["Watiwa"] = "wtf",
["Watubela"] = "wah",
["Waube"] = "kop",
["Wauja"] = "wau",
["Wauyai"] = "wuy",
["Wawa"] = "www",
["Wawonii"] = "wow",
["Waxiang"] = "wxa",
["Wayampi"] = "oym",
["Wayana"] = "way",
["Wayanad Chetti"] = "ctt",
["Wayoró"] = "wyr",
["Wayumara"] = "sai-way",
["Wayuu"] = "guc",
["Wedau"] = "wed",
["Weh"] = "weh",
["Welaung"] = "weu",
["Weliki"] = "klh",
["Welsh"] = "cy",
["Welsh Romani"] = "rmw",
["Wemale"] = "weo",
["Wemba-Wemba"] = "xww",
["Weme Gbe"] = "wem",
["Wendat"] = "wdt",
["Weri"] = "wer",
["Wersing"] = "kvw",
["West Ambae"] = "nnd",
["West Central Banda"] = "bbp",
["West Circassian"] = "ady",
["West Coast Bajau"] = "bdr",
["West Damar"] = "drn",
["West Flemish"] = "vls",
["West Frisian"] = "fy",
["West Greenlandic Pidgin"] = "crp-gep",
["West Lembata"] = "lmj",
["West Makian"] = "mqs",
["West Masela"] = "mss",
["West Miraya Bikol"] = "fbl",
["West Tarangan"] = "txn",
["West Uvean"] = "uve",
["West-Central Limba"] = "lia",
["Western Apache"] = "apw",
["Western Arrernte"] = "are",
["Western Bolivian Guarani"] = "gnw",
["Western Bru"] = "brv",
["Western Bukidnon Manobo"] = "mbb",
["Western Cham"] = "cja",
["Western Dani"] = "dnw",
["Western Durango Nahuatl"] = "azn",
["Western Fijian"] = "wyy",
["Western Highland Chatino"] = "ctp",
["Western Huasteca Nahuatl"] = "nhw",
["Western Jicaque"] = "nai-wji",
["Western Juxtlahuaca Mixtec"] = "jmx",
["Western Karaboro"] = "kza",
["Western Katu"] = "kuf",
["Western Kayah"] = "kyu",
["Western Keres"] = "kjq",
["Western Krahn"] = "krw",
["Western Lalu"] = "ywl",
["Western Lawa"] = "lcp",
["Western Magar"] = "mrd",
["Western Maninkakan"] = "mlq",
["Western Mari"] = "mrj",
["Western Mashan Hmong"] = "hmw",
["Western Meohang"] = "raf",
["Western Muria"] = "mut",
["Western Neo-Aramaic"] = "amw",
["Western Ojibwa"] = "ojw",
["Western Parbate Kham"] = "kjl",
["Western Penan"] = "pne",
["Western Pwo"] = "pwo",
["Western Sisaala"] = "ssl",
["Western Subanon"] = "suc",
["Western Tamang"] = "tdg",
["Western Tawbuid"] = "twb",
["Western Totonac"] = "tqt",
["Western Tunebo"] = "tnb",
["Western Xiangxi Miao"] = "mmr",
["Western Xwla Gbe"] = "xwl",
["Western Yugur"] = "ybe",
["Wewaw"] = "wea",
["Weyewa"] = "wew",
["Weyto"] = "woy",
["White Gelao"] = "giw",
["White Hmong"] = "mww",
["White Lachi"] = "lwh",
["Whitesands"] = "tnp",
["Wiarumus"] = "tua",
["Wichita"] = "wic",
["Wichí Lhamtés Güisnay"] = "mzh",
["Wichí Lhamtés Nocten"] = "mtp",
["Wichí Lhamtés Vejoz"] = "wlv",
["Wik-Epa"] = "wie",
["Wik-Iiyanh"] = "wij",
["Wik-Keyangan"] = "wif",
["Wik-Me'anha"] = "wih",
["Wik-Mungkan"] = "wim",
["Wik-Ngathana"] = "wig",
["Wikalkan"] = "wik",
["Wikngenchera"] = "wua",
["Wilawila"] = "wil",
["Winnebago"] = "win",
["Wintu"] = "wnw",
["Winyé"] = "kst",
["Wipi"] = "gdr",
["Wiradjuri"] = "wrh",
["Wiraféd"] = "wir",
["Wirangu"] = "wgu",
["Wiru"] = "wiu",
["Wirö"] = "wpc",
["Wiwa"] = "mbp",
["Wiyot"] = "wiy",
["Wobé"] = "wob",
["Woccon"] = "xwc",
["Wogamusin"] = "wog",
["Wogeo"] = "woc",
["Woi"] = "wbw",
["Woiwurrung"] = "wyi",
["Wojenaka"] = "jod",
["Wolane"] = "wle",
["Wolani"] = "wod",
["Wolaytta"] = "wal",
["Woleaian"] = "woe",
["Wolio"] = "wlo",
["Wolof"] = "wo",
["Womo"] = "wmx",
["Wong-gie"] = "aus-won",
["Wongo"] = "won",
["Woods Cree"] = "cwd",
["Woria"] = "wor",
["Worimi"] = "kda",
["Worodougou"] = "jud",
["Worora"] = "wro",
["Wotapuri-Katarqalai"] = "wsv",
["Wotu"] = "wtw",
["Woun Meu"] = "noa",
["Written Oirat"] = "xwo",
["Wu"] = "wuu",
["Wudu"] = "wud",
["Wuhuan"] = "mis-wuh",
["Wulguru"] = "aus-wul",
["Wuliwuli"] = "wlu",
["Wulna"] = "wux",
["Wumboko"] = "bqm",
["Wumbvu"] = "wum",
["Wumeng"] = "ywu",
["Wunai Bunu"] = "bwn",
["Wunambal"] = "wub",
["Wurrugu"] = "wur",
["Wusa"] = "yig",
["Wushi"] = "bse",
["Wusi"] = "wsi",
["Wutung"] = "wut",
["Wutunhua"] = "wuh",
["Wuvulu-Aua"] = "wuv",
["Wyandot"] = "wya",
["Wára"] = "tci",
["Wãpha"] = "juw",
["Wè Southern"] = "gxx",
["Wè Western"] = "wec",
["Xadani Zapotec"] = "zax",
["Xakriabá"] = "xkr",
["Xamtanga"] = "xan",
["Xanaguía Zapotec"] = "ztg",
["Xavante"] = "xav",
["Xerénte"] = "xer",
["Xetá"] = "xet",
["Xhosa"] = "xh",
["Xianbei"] = "mis-xbi",
["Xiang"] = "hsn",
["Xibe"] = "sjo",
["Xicotepec de Juárez Totonac"] = "too",
["Xinca"] = "xin",
["Xingú Asuriní"] = "asn",
["Xiongnu"] = "mis-xnu",
["Xipaya"] = "xiy",
["Xiri"] = "xii",
["Xiriâna"] = "xir",
["Xishanba Lalo"] = "ywt",
["Xocó"] = "sai-xoc",
["Xokleng"] = "xok",
["Xukurú"] = "xoo",
["Xwela Gbe"] = "xwe",
["Xârâcùù"] = "ane",
["Xârâgurè"] = "axx",
["Yaa"] = "iyx",
["Yaaku"] = "muu",
["Yabarana"] = "yar",
["Yabaâna"] = "ybn",
["Yaben"] = "ybm",
["Yabong"] = "ybo",
["Yabula Yabula"] = "yxy",
["Yace"] = "ekr",
["Yaeyama"] = "rys",
["Yafi"] = "wfg",
["Yagara"] = "yxg",
["Yagaria"] = "ygr",
["Yaghnobi"] = "yai",
["Yagomi"] = "ygm",
["Yagua"] = "yad",
["Yagwoia"] = "ygw",
["Yahadian"] = "ner",
["Yahang"] = "rhp",
["Yahuna"] = "ynu",
["Yaka"] = "yaf",
["Yakaikeke"] = "ykk",
["Yakan"] = "yka",
["Yakima"] = "yak",
["Yakkha"] = "ybh",
["Yakoma"] = "yky",
["Yakut"] = "sah",
["Yala"] = "yba",
["Yalahatan"] = "jal",
["Yalakalore"] = "xyl",
["Yalarnnga"] = "ylr",
["Yale"] = "nce",
["Yaleba"] = "ylb",
["Yalunka"] = "yal",
["Yalálag Zapotec"] = "zpu",
["Yamap"] = "ymp",
["Yamba"] = "yam",
["Yamben"] = "ynb",
["Yambes"] = "ymb",
["Yambeta"] = "yat",
["Yamdena"] = "jmd",
["Yameo"] = "yme",
["Yami"] = "tao",
["Yaminahua"] = "yaa",
["Yamongeri"] = "ymg",
["Yamphu"] = "ybi",
["Yan-nhangu"] = "jay",
["Yana"] = "ynn",
["Yanda"] = "yda",
["Yanda Dogon"] = "dym",
["Yandjibara"] = "xyb",
["Yandruwandha"] = "ynd",
["Yanesha'"] = "ame",
["Yangben"] = "yav",
["Yangkaal"] = "aus-ynk",
["Yangkam"] = "bsx",
["Yangman"] = "jng",
["Yango"] = "yng",
["Yangulam"] = "ynl",
["Yangum Dey"] = "yde",
["Yangum Gel"] = "ygl",
["Yangum Mon"] = "ymo",
["Yankunytjatjara"] = "kdd",
["Yanomam"] = "wca",
["Yanomamö"] = "guu",
["Yansi"] = "yns",
["Yanyuwa"] = "jao",
["Yao (Africa)"] = "yao",
["Yao (South America)"] = "sai-yao",
["Yaosakor Asmat"] = "asy",
["Yaouré"] = "yre",
["Yapese"] = "yap",
["Yaqay"] = "jaq",
["Yaqui"] = "yaq",
["Yarawata"] = "yrw",
["Yareba"] = "yrb",
["Yareni Zapotec"] = "zae",
["Yarli"] = "yxl",
["Yarluyandi"] = "yry",
["Yarumá"] = "sai-yar",
["Yarí"] = "yri",
["Yasa"] = "yko",
["Yatay"] = "yty",
["Yatee Zapotec"] = "zty",
["Yatzachi Zapotec"] = "zav",
["Yau (Finisterre)"] = "yuw",
["Yau (Torricelli)"] = "yyu",
["Yaur"] = "jau",
["Yautepec Zapotec"] = "zpb",
["Yavitero"] = "yvt",
["Yawa"] = "yva",
["Yawalapití"] = "yaw",
["Yawanawa"] = "ywn",
["Yawarawarga"] = "yww",
["Yaweyuha"] = "yby",
["Yawijibaya"] = "jbw",
["Yawiyo"] = "ybx",
["Yawuru"] = "ywr",
["Yaygir"] = "xya",
["Yazghulami"] = "yah",
["Ye'kwana"] = "mch",
["Yei"] = "jei",
["Yekhee"] = "ets",
["Yekora"] = "ykr",
["Yele"] = "yle",
["Yelmek"] = "jel",
["Yelogu"] = "ylg",
["Yemaek"] = "hmk",
["Yemba"] = "ybb",
["Yemeni Arabic"] = "ayn",
["Yemsa"] = "jnj",
["Yendang"] = "yen",
["Yeni"] = "yei",
["Yenish"] = "yec",
["Yerakai"] = "yra",
["Yeretuar"] = "gop",
["Yeri"] = "yev",
["Yerong"] = "yrn",
["Yerukula"] = "yeu",
["Yeskwa"] = "yes",
["Yessan-Mayo"] = "yss",
["Yetfa"] = "yet",
["Yevanic"] = "yej",
["Yeyi"] = "yey",
["Yiddish"] = "yi",
["Yidgha"] = "ydg",
["Yidiny"] = "yii",
["Yil"] = "yll",
["Yilan Creole"] = "ycr",
["Yimas"] = "yee",
["Yimchungru Naga"] = "yim",
["Yinbaw Karen"] = "kvu",
["Yinchia"] = "yin",
["Yindjibarndi"] = "yij",
["Yindjilandji"] = "yil",
["Yine"] = "pib",
["Yinggarda"] = "yia",
["Yinhawangka"] = "ywg",
["Yiningayi"] = "ygi",
["Yintale Karen"] = "kvy",
["Yinwum"] = "yxm",
["Yir-Yoront"] = "yiy",
["Yirandali"] = "ljw",
["Yis"] = "yis",
["Yitha Yitha"] = "xth",
["Yoba"] = "yob",
["Yocoboué Dida"] = "gud",
["Yogad"] = "yog",
["Yoidik"] = "ydk",
["Yoke"] = "yki",
["Yola"] = "yol",
["Yolmo"] = "scp",
["Yolngu Sign Language"] = "ygs",
["Yoloxochitl Mixtec"] = "xty",
["Yom"] = "pil",
["Yombe"] = "yom",
["Yonaguni"] = "yoi",
["Yong"] = "yno",
["Yongkom"] = "yon",
["Yopno"] = "yut",
["Yora"] = "mts",
["Yoron"] = "yox",
["Yorta Yorta"] = "xyy",
["Yoruba"] = "yo",
["Yosondúa Mixtec"] = "mpm",
["Youle Jino"] = "jiu",
["Younuo Bunu"] = "buh",
["Yout Wam"] = "ytw",
["Yoy"] = "yoy",
["Yuanga"] = "nua",
["Yucatec Maya"] = "yua",
["Yucatec Maya Sign Language"] = "msd",
["Yuchi"] = "yuc",
["Yucuañe Mixtec"] = "mvg",
["Yucuna"] = "ycn",
["Yug"] = "yug",
["Yugambal"] = "yub",
["Yugoslavian Sign Language"] = "ysl",
["Yugul"] = "ygu",
["Yuhup"] = "yab",
["Yuki"] = "yuk",
["Yukpa"] = "yup",
["Yukuben"] = "ybl",
["Yulu"] = "yul",
["Yuma"] = "yum",
["Yumana"] = "awd-yum",
["Yup'ik"] = "esu",
["Yupiltepeque"] = "nai-yup",
["Yupua"] = "sai-yup",
["Yuqui"] = "yuq",
["Yuracare"] = "yuz",
["Yuri"] = "sai-yri",
["Yurok"] = "yur",
["Yuru"] = "ljx",
["Yurumanguí"] = "sai-yur",
["Yurutí"] = "yui",
["Yutanduchi Mixtec"] = "mab",
["Yuwana"] = "yau",
["Yuyu"] = "yxu",
["Yámana"] = "yag",
["Zaachila Zapotec"] = "ztx",
["Zabana"] = "kji",
["Zacatepec Chatino"] = "ctz",
["Zacatlán-Ahuacatlán-Tepetzintla Nahuatl"] = "nhi",
["Zaghawa"] = "zag",
["Zaiwa"] = "atb",
["Zakhring"] = "zkr",
["Zambian Sign Language"] = "zsl",
["Zan Gula"] = "zna",
["Zanaki"] = "zak",
["Zande"] = "zne",
["Zangskari"] = "zau",
["Zangwal"] = "zah",
["Zaniza Zapotec"] = "zpw",
["Zapotec"] = "zap",
["Zaramo"] = "zaj",
["Zari"] = "zaz",
["Zarma"] = "dje",
["Zauzou"] = "zal",
["Zay"] = "zwa",
["Zayein Karen"] = "kxk",
["Zayse-Zergulla"] = "zay",
["Zazaki"] = "zza",
["Zazao"] = "jaj",
["Zbu"] = "sit-zbu",
["Zealandic"] = "zea",
["Zeem"] = "zua",
["Zemba"] = "dhm",
["Zeme Naga"] = "nzm",
["Zenag"] = "zeg",
["Zenaga"] = "zen",
["Zenzontepec Chatino"] = "czn",
["Zhaba"] = "zhb",
["Zhang-Zhung"] = "xzh",
["Zhenan Min"] = "nan-zhe",
["Zhire"] = "zhi",
["Zhoa"] = "zhw",
["Zhuang"] = "za",
["Zhár"] = "jjr",
["Zia"] = "zia",
["Zialo"] = "zil",
["Zigula"] = "ziw",
["Zimakani"] = "zik",
["Zimba"] = "zmb",
["Zimbabwe Sign Language"] = "zib",
["Zinza"] = "zin",
["Zipser German"] = "gmw-zps",
["Zirenkel"] = "zrn",
["Ziriya"] = "zir",
["Zizilivakan"] = "ziz",
["Zo'é"] = "pto",
["Zokhuo"] = "yzk",
["Zoogocho Zapotec"] = "zpq",
["Zotung Chin"] = "czt",
["Zou"] = "zom",
["Zulgo-Gemzek"] = "gnd",
["Zulu"] = "zu",
["Zumaya"] = "zuy",
["Zumbun"] = "jmb",
["Zuni"] = "zun",
["Zuojiang Zhuang"] = "zzj",
["Zuwara"] = "ber-zuw",
["Zyphe"] = "zyp",
["Záparo"] = "zro",
["Àhàn"] = "ahn",
["Áncá"] = "acb",
["Äiwoo"] = "nfl",
["Äynu"] = "aib",
["Ömie"] = "aom",
["Önge"] = "oon",
["ǀXam"] = "xam",
["ǁAni"] = "hnh",
["ǁGana"] = "gnk",
["ǁXegwi"] = "xeg",
["ǂHoan"] = "huc",
["ǃKung"] = "khi-kun",
["ǃXóõ"] = "nmn",
["Ỹaroamë"] = "yro",
}
0zusgdxgfly6boy9hf89x00c3grbejc
Modul:languages/chars
828
9239
25199
2026-08-19T04:41:44Z
Deepturquoise
2456
+ ti enwikt
25199
Scribunto
text/plain
local export = {}
local table = table
local insert = table.insert
local u = require("Module:string/char")
-- UTF-8 encoded strings for some commonly-used diacritics.
local c = {
prime = u(0x02B9),
grave = u(0x0300),
acute = u(0x0301),
circ = u(0x0302), -- circumflex
tilde = u(0x0303),
macron = u(0x0304),
overline = u(0x0305),
breve = u(0x0306),
dotabove = u(0x0307),
diaer = u(0x0308), -- diaeresis
ringabove = u(0x030A),
dacute = u(0x030B), -- double acute
caron = u(0x030C),
lineabove = u(0x030D),
dgrave = u(0x030F), -- double grave
invbreve = u(0x0311), -- inverted breve
turnedcommaabove = u(0x0312),
commaabove = u(0x0313),
revcommaabove = u(0x0314), -- reversed comma above
dotbelow = u(0x0323),
diaerbelow = u(0x0324), -- diaeresis below
ringbelow = u(0x0325),
cedilla = u(0x0327),
ogonek = u(0x0328),
caronbelow = u(0x032C),
brevebelow = u(0x032E),
macronbelow = u(0x0331),
perispomeni = u(0x0342),
ypogegrammeni = u(0x0345),
CGJ = u(0x034F), -- combining grapheme joiner
zigzag = u(0x035B),
dbrevebelow = u(0x035C), -- double breve below
dmacron = u(0x035E), -- double macron
dtilde = u(0x0360), -- double tilde
dinvbreve = u(0x0361), -- double inverted breve
small_a = u(0x0363),
small_e = u(0x0364),
small_i = u(0x0365),
small_o = u(0x0366),
small_u = u(0x0367),
keraia = u(0x0374),
lowerkeraia = u(0x0375),
tonos = u(0x0384),
palatalization = u(0x0484),
dasiapneumata = u(0x0485),
psilipneumata = u(0x0486),
kashida = u(0x0640),
fathatan = u(0x064B),
dammatan = u(0x064C),
kasratan = u(0x064D),
fatha = u(0x064E),
damma = u(0x064F),
kasra = u(0x0650),
shadda = u(0x0651),
sukun = u(0x0652),
hamzaabove = u(0x0654),
nunghunna = u(0x0658),
zwarakay = u(0x0659),
smallv = u(0x065A),
superalef = u(0x0670),
udatta = u(0x0951),
anudatta = u(0x0952),
tacute = u(0x1ACB), -- triple acute
dsvarita = u(0x1CDA), -- double svarita
tsvarita = u(0x1CDB), -- triple svarita
dottedgrave = u(0x1DC0),
dottedacute = u(0x1DC1),
coronis = u(0x1FBD),
psili = u(0x1FBF),
dasia = u(0x1FEF),
ZWNJ = u(0x200C), -- zero width non-joiner
ZWJ = u(0x200D), -- zero width joiner
RSQuo = u(0x2019), -- right single quote
kavyka = u(0xA67C),
VS01 = u(0xFE00), -- variation selector 1
-- Punctuation for the standard_chars field.
-- Note: characters are literal (i.e. no magic characters).
punc = " ',-‐‑‒–—…∅◌",
-- Range covering all diacritics.
diacritics = u(0x300) .. "-" .. u(0x34E) ..
u(0x350) .. "-" .. u(0x36F) ..
u(0x1AB0) .. "-" .. u(0x1ACE) ..
u(0x1DC0) .. "-" .. u(0x1DFF) ..
u(0x20D0) .. "-" .. u(0x20F0) ..
u(0xFE20) .. "-" .. u(0xFE2F),
}
-- Braille characters for the standard_chars field.
local braille = {}
for i = 0x2800, 0x28FF do
insert(braille, u(i))
end
c.braille = table.concat(braille)
export.chars = c
-- Pre-generate PUA characters, generally used in sortkeys.
-- Note: if changing the amount, use powers of 2 to maximise memory efficiency (due to the way memory is allocated for tables).
local p = {}
for i = 1, 32 do
p[i] = u(0xF000+i-1)
end
export.puaChars = p
local cs = {}
-- Used in the default strip_diacritics and sort_key for Cyrs, but also used directly by Old Ruthenian (zle-ort).
cs["Cyrs_remove_diacritics"] = c.grave .. c.acute .. c.dotabove .. c.diaer .. c.invbreve .. c.palatalization .. c.dasiapneumata .. c.psilipneumata .. c.dottedgrave .. c.dottedacute .. c.kavyka
export.chars_substitutions = cs
return export
fsf6ixs8oigvoxxmoilnwf9c50lo7o0
Modul:maintenance category
828
9240
25200
2026-08-19T04:42:28Z
Deepturquoise
2456
+ ti enwikt
25200
Scribunto
text/plain
local export = {}
local pages_module = "Module:pages"
local parameters_module = "Module:parameters"
local utilities_module = "Module:utilities"
local new_title = mw.title.new
local uses_hidden_category -- 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 format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function is_sandbox(...)
is_sandbox = require(pages_module).is_sandbox
return is_sandbox(...)
end
local function is_testcase_page(...)
is_testcase_page = require(pages_module).is_testcase_page
return is_testcase_page(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
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 current_title
local function get_current_title()
current_title, get_current_title = mw.title.getCurrentTitle(), nil
return current_title
end
function export.uses_hidden_category(title)
local namespace = title.namespace
-- Thread: and Summary: pages are named "Thread:PAGE" or "Summary:PAGE",
-- where PAGE is the page they relate to. How we treat them therefore
-- depends on what that page is.
while namespace == 90 or namespace == 92 do
title = new_title(title.text)
namespace = title.namespace
end
-- User: and all talk namespaces, as well as all sandboxes and testcase pages (including their documentation pages).
return (
namespace == 2 or
title.isTalkPage or
is_sandbox(title, "include documentation") or
is_testcase_page(title, "include documentation")
) and true or false
end
uses_hidden_category = export.uses_hidden_category
function export.get_category(name, cat)
if uses_hidden_category(current_title or get_current_title()) then
name = name .. "/hidden"
end
return cat and format_categories(name, nil, "-", nil, true) or name
end
function export.template(frame)
local args = process_params(frame:getParent().args, {
[1] = {required = true, default = ""},
["cat"] = {type = "boolean", default = false}
})
return export.get_category(args[1], args.cat)
end
return export
0k9xe0i9582irnmc4uhevzdi2o9uso3
Modul:scripts/charToScript
828
9241
25201
2026-08-19T04:43:16Z
Deepturquoise
2456
+ ti enwikt
25201
Scribunto
text/plain
local subexport = {}
local require_when_needed = require("Module:require when needed")
local cp = require_when_needed("Module:string utilities", "codepoint")
local floor = math.floor
local get_plaintext = require_when_needed("Module:utilities", "get_plaintext")
local get_script = require_when_needed("Module:scripts", "getByCode")
local insert = table.insert
local ipairs = ipairs
local min = math.min
local pairs = pairs
local setmetatable = setmetatable
local sort = table.sort
local split = require_when_needed("Module:string utilities", "split")
local table_len = require_when_needed("Module:table", "length")
local type = type
-- Copied from [[Module:Unicode data]].
local function binaryRangeSearch(codepoint, ranges)
local low, mid, high
low, high = 1, ranges.length or table_len(ranges)
while low <= high do
mid = floor((low + high) / 2)
local range = ranges[mid]
if codepoint < range[1] then
high = mid - 1
elseif codepoint <= range[2] then
return range, mid
else
low = mid + 1
end
end
return nil, mid
end
-- Copied from [[Module:Unicode data]].
local function linearRangeSearch(codepoint, ranges)
for i, range in ipairs(ranges) do
if codepoint < range[1] then
break
elseif codepoint <= range[2] then
return range
end
end
end
local function compareRanges(range1, range2)
return range1[1] < range2[1]
end
-- Save previously used codepoint ranges in case another character is in the
-- same range.
local rangesCache = {}
--[=[
Takes a codepoint or a character and finds the script code(s) (if any) that are appropriate for it based on the codepoint, using the data module [[Module:scripts/recognition data]]. The data module was generated from the patterns in [[Module:scripts/data]] using [[Module:User:Erutuon/script recognition]].
By default, it returns only the first script code if there are multiple matches (i.e. the code we take to be the default). If `all_scripts` is set, then a table of all matching codes is returned.
]=]
local charToScriptData
function subexport.charToScript(char, all_scripts)
charToScriptData = charToScriptData or mw.loadData("Module:scripts/recognition data")
local t = type(char)
local codepoint
if t == "string" then
local etc
codepoint, etc = cp(char, 1, 2)
if etc then
error("bad argument #1 to 'charToScript' (expected a single character)")
end
elseif t == "number" then
codepoint = char
else
error(("bad argument #1 to 'charToScript' (expected string or a number, got %s)")
:format(t))
end
local ret = {}
local individualMatch = charToScriptData.individual[codepoint]
if individualMatch then
ret = split(individualMatch, "%s*,%s*", true)
else
local range
if rangesCache[1] then
range = linearRangeSearch(codepoint, rangesCache)
if range then
for i, script in ipairs(range) do
if i > 2 then
insert(ret, script)
if not all_scripts then
break
end
end
end
end
end
if not ret[1] then
local index = floor(codepoint / 0x1000)
range = linearRangeSearch(index, charToScriptData.blocks)
if not range and charToScriptData[index] then
range = binaryRangeSearch(codepoint, charToScriptData[index])
if range then
insert(rangesCache, range)
sort(rangesCache, compareRanges)
end
end
if range then
for i, script in ipairs(range) do
if i > 2 then
insert(ret, script)
if not all_scripts then
break
end
end
end
end
end
end
if not ret[1] then
insert(ret, "None")
end
if all_scripts then
return ret
else
return ret[1]
end
end
--[=[
Finds the best script for a string in a language-agnostic way.
Converts each character to a codepoint. Iterates the counter for the script code if the codepoint is in the list
of individual characters, or if it is in one of the defined ranges in the 4096-character block that it belongs to.
Each script has a two-part counter, for primary and secondary matches. Primary matches are when the script is the
first one listed; otherwise, it's a secondary match. When comparing scripts, first the total of both are compared
(i.e. the overall number of matches). If these are the same, the number of primary and then secondary matches are
used as tiebreakers. For example, this is used to ensure that `Grek` takes priority over `Polyt` if no characters
which exclusively match `Polyt` are found, as `Grek` is a subset of `Polyt`.
If `none_is_last_resort_only` is specified, this will never return None if any characters in `text` belong to a
script. Otherwise, it will return None if there are more characters that don't belong to a script than belong to
any individual script. (FIXME: This behavior is probably wrong, and `none_is_last_resort_only` should probably
become the default.)
]=]
function subexport.findBestScriptWithoutLang(text, none_is_last_resort_only)
-- `scripts` contains counters for any scripts detected so far. Jpan and Kore are handled as special-cases, as they are combinations of other scripts.
local scripts_mt = {Jpan = true, Kore = true}
local weights_mt = {
__lt = function(a, b)
if a[1] + a[2] ~= b[1] + b[2] then
return a[1] + a[2] < b[1] + b[2]
elseif a[1] ~= b[1] then
return a[1] < b[1]
elseif a[2] ~= b[2] then
return a[2] < b[2]
else
return false
end
end
}
scripts_mt.__index = function(t, k)
local ret = {}
if k == "Jpan" and scripts_mt.Jpan then
for i = 1, 2 do
ret[i] = t["Hani"][i] + t["Hira"][i] + t["Kana"][i]
end
elseif k == "Kore" and scripts_mt.Kore then
for i = 1, 2 do
ret[i] = t["Hani"][i] + t["Hang"][i]
end
else
for i = 1, 2 do
insert(ret, 0)
end
end
return setmetatable(ret, weights_mt)
end
local scripts = setmetatable({}, scripts_mt)
text = get_plaintext(text)
local combined_scripts = {
Jpan = {["Hani"] = true, ["Hira"] = true, ["Kana"] = true},
Kore = {["Hani"] = true, ["Hang"] = true}
}
for character in text:gmatch(".[\128-\191]*") do
for i, script in ipairs(subexport.charToScript(character, true)) do
if not none_is_last_resort_only or script ~= "None" then
scripts[script] = scripts[script]
local weight = min(i, 2)
scripts[script][weight] = scripts[script][weight] + 1
end
end
end
-- Check the combined script counts. If a single constituent has the same count (i.e. it's the only one), discard the combined script.
for combined_script, set in pairs(combined_scripts) do
for script in pairs(set) do
scripts[combined_script] = scripts[combined_script]
if (scripts[script][1] + scripts[script][2]) == (scripts[combined_script][1] + scripts[combined_script][2]) then
scripts[combined_script] = nil
break
end
end
end
local bestScript
local greatestCount
for script, count in pairs(scripts) do
if (not greatestCount) or greatestCount < count then
bestScript = script
greatestCount = count
end
end
bestScript = bestScript or "None"
return get_script(bestScript)
end
return subexport
cs19bg8d41yuv7ovit6o3v0kd4ou9kq
Modul:scripts/recognition data
828
9242
25202
2026-08-19T04:44:27Z
Deepturquoise
2456
+ ti enwikt
25202
Scribunto
text/plain
local data = {
[0x00] = {
{ 0x00041, 0x0005A, "Latn"},
{ 0x00061, 0x0007A, "Latn"},
{ 0x000C0, 0x000D6, "Latn"},
{ 0x000D8, 0x000F6, "Latn"},
{ 0x000F8, 0x0024F, "Latn"},
{ 0x00370, 0x003E1, "Grek", "Polyt" },
{ 0x003E2, 0x003EF, "Copt" },
{ 0x003F0, 0x003FF, "Grek", "Polyt" },
{ 0x00400, 0x0045F, "Cyrl" },
{ 0x00460, 0x00469, "Cyrs" },
{ 0x0046A, 0x0046D, "Cyrl" },
{ 0x0046E, 0x00471, "Cyrs" },
{ 0x00472, 0x00475, "Cyrl" },
{ 0x00476, 0x00489, "Cyrs" },
{ 0x0048A, 0x00527, "Cyrl" },
{ 0x00531, 0x0058F, "Armn" },
{ 0x00590, 0x005FF, "Hebr" },
{ 0x00600, 0x006FF, "Arab" },
{ 0x00700, 0x0074F, "Syrc" },
{ 0x00750, 0x0077F, "Arab" },
{ 0x00780, 0x007B1, "Thaa" },
{ 0x007C0, 0x007FF, "Nkoo" },
{ 0x00800, 0x0083E, "Samr" },
{ 0x00840, 0x0085E, "Mand" },
{ 0x00860, 0x0086A, "Syrc" },
{ 0x008A0, 0x008FF, "Arab" },
{ 0x00900, 0x0097F, "Deva" },
{ 0x00980, 0x00983, "Beng" },
{ 0x00985, 0x0098C, "Beng" },
{ 0x00993, 0x009A8, "Beng" },
{ 0x009AA, 0x009B0, "Beng" },
{ 0x009B6, 0x009B9, "Beng" },
{ 0x009BC, 0x009C4, "Beng" },
{ 0x009CB, 0x009CE, "Beng" },
{ 0x009E0, 0x009E3, "Beng" },
{ 0x009E6, 0x009EF, "Beng" },
{ 0x009F0, 0x009F1, "as-Beng" },
{ 0x00A01, 0x00A76, "Guru" },
{ 0x00A81, 0x00AF1, "Gujr" },
{ 0x00B01, 0x00B77, "Orya" },
{ 0x00B82, 0x00BFA, "Taml" },
{ 0x00C00, 0x00C7F, "Telu" },
{ 0x00C80, 0x00CF2, "Knda" },
{ 0x00D02, 0x00D7F, "Mlym" },
{ 0x00D82, 0x00DF4, "Sinh" },
{ 0x00E01, 0x00E5B, "Thai" },
{ 0x00E81, 0x00EDF, "Laoo" },
{ 0x00F00, 0x00FDA, "Tibt" },
},
[0x01] = {
{ 0x01000, 0x0109F, "Mymr" },
{ 0x010A0, 0x010CD, "Geok" },
{ 0x010D0, 0x010FF, "Geor" },
{ 0x01100, 0x011FF, "Hang" },
{ 0x01200, 0x01399, "Ethi" },
{ 0x013A0, 0x013F4, "Cher" },
{ 0x01400, 0x0167F, "Cans" },
{ 0x01680, 0x0169C, "Ogam" },
{ 0x016A0, 0x016F0, "Runr" },
{ 0x01700, 0x01714, "Tglg" },
{ 0x01720, 0x01734, "Hano" },
{ 0x01740, 0x01753, "Buhd" },
{ 0x01760, 0x01773, "Tagb" },
{ 0x01780, 0x017F9, "Khmr" },
{ 0x01800, 0x018AA, "Mong" },
{ 0x01900, 0x0194F, "Limb" },
{ 0x01950, 0x01974, "Tale" },
{ 0x01980, 0x019DF, "Talu" },
{ 0x019E0, 0x019FF, "Khmr" },
{ 0x01A00, 0x01A1F, "Bugi" },
{ 0x01A20, 0x01AAD, "Lana" },
{ 0x01B00, 0x01B7C, "Bali" },
{ 0x01B80, 0x01BBF, "Sund" },
{ 0x01BC0, 0x01BFF, "Batk" },
{ 0x01C00, 0x01C4F, "Lepc" },
{ 0x01C50, 0x01C7F, "Olck" },
{ 0x01C90, 0x01CBF, "Geor" },
{ 0x01E00, 0x01EFF, "Latn" },
{ 0x01F00, 0x01FFE, "Polyt" },
},
[0x02] = {
{ 0x02190, 0x021FF, "Zsym" },
{ 0x02200, 0x022FF, "Zmth" },
{ 0x02300, 0x023FF, "Zsym" },
{ 0x02500, 0x027BF, "Zsym" },
{ 0x027C0, 0x027EF, "Zmth" },
{ 0x02800, 0x028FF, "Brai" },
{ 0x02980, 0x02AFF, "Zmth" },
{ 0x02B00, 0x02BFE, "Zsym" },
{ 0x02C00, 0x02C5E, "Glag" },
{ 0x02C60, 0x02C7F, "Latn" },
{ 0x02C80, 0x02CFF, "Copt" },
{ 0x02D00, 0x02D2D, "Geok" },
{ 0x02D30, 0x02D7F, "Tfng" },
{ 0x02D80, 0x02DDE, "Ethi" },
{ 0x02E80, 0x02FDF, "Hani" },
},
[0x03] = {
{ 0x03001, 0x03002, "Hani", "Bopo", "Hang", "Hira", "Kana", "Yiii" },
{ 0x03003, 0x03007, "Hani" },
{ 0x03008, 0x03011, "Hani", "Bopo", "Hang", "Hira", "Kana", "Yiii" },
{ 0x03012, 0x03013, "Hani" },
{ 0x03014, 0x0301B, "Hani", "Bopo", "Hang", "Hira", "Kana", "Yiii" },
{ 0x0301C, 0x0301F, "Hani", "Bopo", "Hang", "Hira", "Kana" },
{ 0x03020, 0x0303F, "Hani" },
{ 0x03041, 0x0309F, "Hira" },
{ 0x030A0, 0x030FF, "Kana" },
{ 0x03105, 0x0312F, "Bopo" },
{ 0x03131, 0x0318E, "Hang" },
{ 0x031A0, 0x031BA, "Bopo" },
{ 0x031C0, 0x031E3, "Hani" },
{ 0x031F0, 0x031FF, "Kana" },
{ 0x03220, 0x03247, "Hani" },
{ 0x03280, 0x032B0, "Hani" },
{ 0x032C0, 0x032CB, "Hani" },
{ 0x03300, 0x03357, "Kana" },
{ 0x03358, 0x03370, "Hani" },
{ 0x0337B, 0x0337F, "Hani" },
{ 0x033E0, 0x033FE, "Hani" },
{ 0x03400, 0x03FFF, "Hani" },
},
[0x04] = {
{ 0x04000, 0x04DB5, "Hani" },
{ 0x04E00, 0x04FFF, "Hani" },
},
[0x05] = {
{ 0x05000, 0x05FFF, "Hani" },
},
[0x06] = {
{ 0x06000, 0x06FFF, "Hani" },
},
[0x07] = {
{ 0x07000, 0x07FFF, "Hani" },
},
[0x08] = {
{ 0x08000, 0x08FFF, "Hani" },
},
[0x09] = {
{ 0x09000, 0x09FFF, "Hani" },
},
[0x0A] = {
{ 0x0A000, 0x0A4C6, "Yiii" },
{ 0x0A4D0, 0x0A4FF, "Lisu" },
{ 0x0A500, 0x0A62B, "Vaii" },
{ 0x0A640, 0x0A67F, "Cyrs" },
{ 0x0A680, 0x0A697, "Cyrl" },
{ 0x0A6A0, 0x0A6F7, "Bamu" },
{ 0x0A720, 0x0A7FF, "Latn" },
{ 0x0A800, 0x0A82B, "Sylo" },
{ 0x0A830, 0x0A832, "Deva", "Dogr", "Gujr", "Guru", "Khoj", "Knda", "Kthi", "Mahj", "Modi", "Nand", "Sind", "Takr", "Tirh"},
{ 0x0A833, 0x0A835, "Deva", "Dogr", "Gujr", "Guru", "Khoj", "Knda", "Kthi", "Mahj", "Mlym", "Modi", "Nand", "Sind", "Takr", "Tirh"},
{ 0x0A836, 0x0A839, "Deva", "Dogr", "Gujr", "Guru", "Khoj", "Kthi", "Mahj", "Modi", "Sind", "Takr", "Tirh"},
{ 0x0A840, 0x0A877, "Phag" },
{ 0x0A880, 0x0A8D9, "Saur" },
{ 0x0A8E0, 0x0A8FF, "Deva" },
{ 0x0A900, 0x0A92F, "Kali" },
{ 0x0A930, 0x0A95F, "Rjng" },
{ 0x0A980, 0x0A9DF, "Java" },
{ 0x0A9E0, 0x0A9FE, "Mymr" },
{ 0x0AA00, 0x0AA5F, "Cham" },
{ 0x0AA60, 0x0AA7F, "Mymr" },
{ 0x0AA80, 0x0AADF, "Tavt" },
{ 0x0AAE0, 0x0AAFF, "Mtei" },
{ 0x0AB01, 0x0AB2E, "Ethi" },
{ 0x0AB30, 0x0AB65, "Latn" },
{ 0x0AB70, 0x0ABBF, "Cher" },
{ 0x0ABC0, 0x0ABFF, "Mtei" },
{ 0x0AC00, 0x0AFFF, "Hang" },
},
[0x0B] = {
{ 0x0B000, 0x0BFFF, "Hang" },
},
[0x0C] = {
{ 0x0C000, 0x0CFFF, "Hang" },
},
[0x0D] = {
{ 0x0D000, 0x0D7A3, "Hang" },
},
[0x0F] = {
{ 0x0FA27, 0x0FA29, "Hani" },
{ 0x0FB13, 0x0FB17, "Armn" },
{ 0x0FB1D, 0x0FB4F, "Hebr" },
{ 0x0FB50, 0x0FDFD, "Arab" },
{ 0x0FE45, 0x0FE46, "Hani", "Bopo", "Hang", "Hira", "Kana" },
{ 0x0FE70, 0x0FEFC, "Arab" },
{ 0x0FF61, 0x0FF65, "Hani", "Bopo", "Hang", "Hira", "Kana", "Yiii" },
},
[0x10] = {
{ 0x10000, 0x100FA, "Linb" },
{ 0x10280, 0x1029C, "Lyci" },
{ 0x102A0, 0x102D0, "Cari" },
{ 0x102E1, 0x102FB, "Copt" },
{ 0x10300, 0x10323, "Ital" },
{ 0x10330, 0x1034A, "Goth" },
{ 0x10350, 0x1037A, "Perm" },
{ 0x10380, 0x1039F, "Ugar" },
{ 0x103A0, 0x103D5, "Xpeo" },
{ 0x10400, 0x1044F, "Dsrt" },
{ 0x10450, 0x1047F, "Shaw" },
{ 0x10480, 0x104A9, "Osma" },
{ 0x104B0, 0x104FB, "Osge" },
{ 0x10500, 0x10527, "Elba" },
{ 0x10530, 0x10563, "Aghb" },
{ 0x10600, 0x10767, "Lina" },
{ 0x10800, 0x1083F, "Cprt" },
{ 0x10840, 0x1085F, "Armi" },
{ 0x10860, 0x1087F, "Palm" },
{ 0x10880, 0x108AF, "Nbat" },
{ 0x108E0, 0x108FF, "Hatr" },
{ 0x10900, 0x1091F, "Phnx" },
{ 0x10920, 0x1093F, "Lydi" },
{ 0x10980, 0x1099F, "Mero" },
{ 0x109A0, 0x109BF, "Merc" },
{ 0x10A00, 0x10A58, "Khar" },
{ 0x10A60, 0x10A7F, "Sarb" },
{ 0x10A80, 0x10A9F, "Narb" },
{ 0x10AC0, 0x10AF6, "Mani" },
{ 0x10B00, 0x10B3F, "Avst" },
{ 0x10B40, 0x10B5F, "Prti" },
{ 0x10B60, 0x10B7F, "Phli" },
{ 0x10B80, 0x10BAF, "Phlp" },
{ 0x10C00, 0x10C48, "Orkh" },
{ 0x10C80, 0x10CB2, "Hung" },
{ 0x10D00, 0x10D39, "Rohg" },
{ 0x10E60, 0x10E7E, "Rumin" },
{ 0x10F00, 0x10F27, "Sogo" },
{ 0x10F30, 0x10F59, "Sogd" },
{ 0x10F70, 0x10FAF, "Ougr" },
{ 0x10FE0, 0x10FFF, "Elym" },
},
[0x11] = {
{ 0x11000, 0x1107F, "Brah" },
{ 0x11080, 0x110CD, "Kthi" },
{ 0x110D0, 0x110F9, "Sora" },
{ 0x11100, 0x11146, "Cakm" },
{ 0x11150, 0x11176, "Mahj" },
{ 0x11180, 0x111D9, "Shrd" },
{ 0x11200, 0x1123D, "Khoj" },
{ 0x11280, 0x112A9, "Mult" },
{ 0x112B0, 0x112F9, "Sind" },
{ 0x11301, 0x11374, "Gran" },
{ 0x11400, 0x1145E, "Newa" },
{ 0x11480, 0x114D9, "Tirh" },
{ 0x11580, 0x115DD, "Sidd" },
{ 0x11600, 0x11659, "Modi" },
{ 0x11680, 0x116C9, "Takr" },
{ 0x11700, 0x1173F, "Ahom" },
{ 0x11800, 0x1183B, "Dogr" },
{ 0x118A0, 0x118FF, "Wara" },
{ 0x119A0, 0x119FF, "Nand" },
{ 0x11A00, 0x11A47, "Zanb" },
{ 0x11A50, 0x11AA2, "Soyo" },
{ 0x11AC0, 0x11AF8, "Pauc" },
{ 0x11C00, 0x11C6C, "Bhks" },
{ 0x11C70, 0x11CB6, "Marc" },
{ 0x11D00, 0x11D59, "Gonm" },
{ 0x11D60, 0x11DA9, "Gong" },
{ 0x11EE0, 0x11EF8, "Maka" },
},
[0x12] = {
{ 0x12000, 0x1236E, "Xsux" },
{ 0x12400, 0x12473, "Xsux" },
{ 0x12F90, 0x12FFF, "Cpmn" },
},
[0x13] = {
{ 0x13000, 0x1342E, "Egyp" },
},
[0x14] = {
{ 0x14400, 0x14646, "Hluw" },
},
[0x16] = {
{ 0x16800, 0x16A38, "Bamu" },
{ 0x16A40, 0x16A6F, "Mroo" },
{ 0x16AD0, 0x16AF5, "Bass" },
{ 0x16B00, 0x16B8F, "Hmng" },
{ 0x16E40, 0x16E9A, "Medf" },
{ 0x16F00, 0x16F9F, "Plrd" },
},
[0x17] = {
{ 0x17000, 0x17FFF, "Tang" },
},
[0x18] = {
{ 0x18000, 0x18AF2, "Tang" },
},
[0x1B] = {
{ 0x1B001, 0x1B11E, "Hira" },
{ 0x1B170, 0x1B2FB, "Nshu" },
{ 0x1BC00, 0x1BC9F, "Dupl" },
},
[0x1C] = {
{ 0x1CF00, 0x1CFCF, "Zname" },
},
[0x1D] = {
{ 0x1D100, 0x1D1DD, "Music" },
{ 0x1D2E0, 0x1D2F3, "Maya" },
{ 0x1D400, 0x1D7FF, "Zmth" },
{ 0x1D800, 0x1DAAF, "Sgnw" },
},
[0x1E] = {
{ 0x1E000, 0x1E02A, "Glag" },
{ 0x1E800, 0x1E8D6, "Mend" },
{ 0x1E900, 0x1E95F, "Adlm" },
},
[0x1F] = {
{ 0x1F000, 0x1F0F5, "Zsym" },
{ 0x1F300, 0x1FA6D, "Zsym" },
},
[0x20] = {
{ 0x20000, 0x20FFF, "Hani" },
},
[0x21] = {
{ 0x21000, 0x21FFF, "Hani" },
},
[0x22] = {
{ 0x22000, 0x22FFF, "Hani" },
},
[0x23] = {
{ 0x23000, 0x23FFF, "Hani" },
},
[0x24] = {
{ 0x24000, 0x24FFF, "Hani" },
},
[0x25] = {
{ 0x25000, 0x25FFF, "Hani" },
},
[0x26] = {
{ 0x26000, 0x26FFF, "Hani" },
},
[0x27] = {
{ 0x27000, 0x27FFF, "Hani" },
},
[0x28] = {
{ 0x28000, 0x28FFF, "Hani" },
},
[0x29] = {
{ 0x29000, 0x29FFF, "Hani" },
},
[0x2A] = {
{ 0x2A000, 0x2AFFF, "Hani" },
},
[0x2B] = {
{ 0x2B000, 0x2BFFF, "Hani" },
},
[0x2C] = {
{ 0x2C000, 0x2CFFF, "Hani" },
},
[0x2D] = {
{ 0x2D000, 0x2DFFF, "Hani" },
},
[0x2E] = {
{ 0x2E000, 0x2EBE0, "Hani" },
},
[0x30] = {
{ 0x30000, 0x30FFF, "Hani" },
},
[0x31] = {
{ 0x31000, 0x31FFF, "Hani" },
},
[0x32] = {
{ 0x32000, 0x32FFF, "Hani" },
},
[0x33] = {
{ 0x33000, 0x33FFF, "Hani" },
},
}
for _, v in next, data do
v.length = #v
end
data.individual = {
[0x00462] = "Cyrl",
[0x00463] = "Cyrl",
[0x0060C] = "Arab, Nkoo, Rohg, Syrc, Thaa, Yezi",
[0x0061B] = "Arab, Nkoo, Rohg, Syrc, Thaa, Yezi",
[0x0061F] = "Arab, Adlm, Nkoo, Rohg, Syrc, Thaa, Yezi",
[0x00640] = "Arab, Adlm, Mand, Mani, Ougr, Phlp, Rohg, Sogd, Syrc",
[0x00951] = "Deva, Beng, Gran, Gujr, Guru, Knda, Latn, Mlym, Orya, Shrd, Taml, Telu, Tirh",
[0x00952] = "Deva, Beng, Gran, Gujr, Guru, Knda, Latn, Mlym, Orya, Taml, Telu, Tirh",
[0x00964] = "Deva, Beng, Dogr, Gong, Gonm, Gran, Gujr, Guru, Knda, Mahj, Mlym, Nand, Orya, Sind, Sinh, Sylo, Takr, Taml, Telu, Tirh",
[0x00965] = "Deva, Beng, Dogr, Gong, Gonm, Gran, Gujr, Guru, Knda, Limb, Mahj, Mlym, Nand, Orya, Sind, Sinh, Sylo, Takr, Taml, Telu, Tirh",
[0x0098F] = "Beng",
[0x00990] = "Beng",
[0x009A1] = "Beng",
[0x009A2] = "Beng",
[0x009AF] = "Beng",
[0x009B2] = "Beng",
[0x009BC] = "Beng",
[0x009C7] = "Beng",
[0x009C8] = "Beng",
[0x009D7] = "Beng",
[0x01CDA] = "Deva, Knda, Mlym, Orya, Taml, Telu",
[0x01CF2] = "Deva, Beng, Gran, Knda, Nand, Orya, Telu, Tirh",
[0x02135] = "Zmth",
[0x03000] = "Hani",
[0x03003] = "Hani, Bopo, Hang, Hira, Kana",
[0x03013] = "Hani, Bopo, Hang, Hira, Kana",
[0x03030] = "Hani, Bopo, Hang, Hira, Kana",
[0x03037] = "Hani, Bopo, Hang, Hira, Kana",
[0x030FB] = "Kana, Hani, Bopo, Hang, Hira, Yiii",
[0x032FF] = "Hani",
[0x0FA0E] = "Hani",
[0x0FA0F] = "Hani",
[0x0FA11] = "Hani",
[0x0FA13] = "Hani",
[0x0FA14] = "Hani",
[0x0FA1F] = "Hani",
[0x0FA21] = "Hani",
[0x0FA23] = "Hani",
[0x0FA24] = "Hani",
[0x1056F] = "Aghb",
[0x16FE0] = "Tang",
[0x16FE1] = "Nshu",
[0x1B000] = "Kana",
}
data.blocks = {
{ 0x04, 0x09, "Hani" },
{ 0x0B, 0x0D, "Hang" },
{ 0x17, 0x18, "Tang" },
{ 0x20, 0x2E, "Hani" },
}
return data
4m69qs8gnq8knzros5qbkff3yz21cb5
Modul:string/removeComments
828
9243
25203
2026-08-19T04:45:17Z
Deepturquoise
2456
+ ti enwikt
25203
Scribunto
text/plain
local concat = table.concat
local find = string.find
local sub = string.sub
local function remove_comments(str, pre)
local pos1 = find(str, "<!--", nil, true)
if not pos1 then
return str
end
local pos2 = find(str, "-->", pos1 + 4, true)
if not pos2 then
return pre and sub(str, 1, pos1 - 1) or str
end
local ret = sub(str, 1, pos1 - 1)
pos1 = pos2 + 3
pos2 = find(str, "<!--", pos1, true)
if not pos2 then
return ret .. sub(str, pos1)
end
local pos3 = find(str, "-->", pos2 + 4, true)
if not pos3 then
return ret .. sub(str, pos1, pre and pos2 - 1 or nil)
end
ret = {ret, sub(str, pos1, pos2 - 1)}
local n = 2
while true do
pos1 = pos3 + 3
pos2 = find(str, "<!--", pos1, true)
if not pos2 then
return concat(ret) .. sub(str, pos1)
end
pos3 = find(str, "-->", pos2 + 4, true)
if not pos3 then
return concat(ret) .. sub(str, pos1, pre and pos2 - 1 or nil)
end
n = n + 1
ret[n] = sub(str, pos1, pos2 - 1)
end
end
--[==[Removes any HTML comments from the input text. `stage` can be one of three options:
* {"PRE"} (default) applies the method used by MediaWiki's preprocessor: all {{code|html|<nowiki><!-- ... --></nowiki>}} pairs are removed, as well as any text after an unclosed {{code|html|<nowiki><!--</nowiki>}}. This is generally suitable when parsing raw template or [[mw:Parser extension tags|parser extension tag]] code. (Note, however, that the actual method used by the preprocessor is considerably more complex and differs under certain conditions (e.g. comments inside nowiki tags); if full accuracy is absolutely necessary, use [[Module:template parser]] instead).
* {"POST"} applies the method used to generate the final page output once all templates have been expanded: it loops over the text, removing any {{code|html|<nowiki><!-- ... --></nowiki>}} pairs until no more are found (e.g. {{code|html|<nowiki><!-<!-- ... -->- ... --></nowiki>}} would be fully removed), but any unclosed {{code|html|<nowiki><!--</nowiki>}} is ignored. This is suitable for handling links embedded in template inputs, where the {"PRE"} method will have already been applied by the native parser.
* {"BOTH"} applies {"PRE"} then {"POST"}.]==]
return function(str, stage)
if stage == nil or stage == "PRE" then
return remove_comments(str, true)
elseif stage == "BOTH" then
str = remove_comments(str, true)
elseif stage ~= "POST" then
error("bad argument #2 to 'remove_comments' (expected PRE, POST, or BOTH)", 2)
end
while true do
local processed = remove_comments(str)
if processed == str then
return str
end
str = processed
end
end
6q2u94c4jook0g0vegx0uyg6x3jd1ms
Modul:table/getMetamethod
828
9244
25204
2026-08-19T04:45:56Z
Deepturquoise
2456
+ ti enwikt
25204
Scribunto
text/plain
local table_get_unprotected_metatable = "Module:table/getUnprotectedMetatable"
local rawget = rawget
local select = select
local function get_unprotected_metatable(...)
get_unprotected_metatable = require(table_get_unprotected_metatable)
return get_unprotected_metatable(...)
end
local function get_metamethod(n, i, mt, mm, ...)
if mt then
mm = rawget(mt, mm)
else
mm = nil
end
if i == n then
return mm
end
return mm, get_metamethod(n, i + 1, mt, ...)
end
--[==[
Takes an input value and any number of metamethods, and attempts to retrieve the values at those keys in the value's metatable. Returns a boolean stating whether the value's metamethods are findable, followed by a return value for each metamethod.
A value's metamethods are findable if it does not have a protected metatable, so the first return value is {true} if the value either has a metatable which does not contain the {__metatable} metamethod, or it has no metatable at all. If the value does have a protected metatable, the first return value is {false}, and all remaining return values default to {nil}.]==]
return function(t, ...)
local mt, n = get_unprotected_metatable(t), select("#", ...)
-- get_unprotected_metatable() returns the metatable if it's unprotected,
-- false if it's protected, or nil if there is no metatable. It checks
-- whether a metatable is protected by trying pcall(setmetatable, t),
-- so it's always possible to determine accurately.
if n == 0 then
return mt ~= false
end
return mt ~= false, get_metamethod(n, 1, mt, ...)
end
tfl070cq0h5icostaevq3t6kcrhpcyw
Modul:template parser
828
9245
25210
2026-08-19T06:27:47Z
Deepturquoise
2456
+ti enwikt
25210
Scribunto
text/plain
--[[
see:wikt:en:Module:template parser
]]
local export = {}
local data_module = "Module:template parser/data"
local load_module = "Module:load"
local magic_words_data_module = "Module:data/magic words"
local pages_module = "Module:pages"
local parser_extension_tags_data_module = "Module:data/parser extension tags"
local parser_module = "Module:parser"
local scribunto_module = "Module:Scribunto"
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_length_module = "Module:table/length"
local table_shallow_copy_module = "Module:table/shallowCopy"
local table_sorted_pairs_module = "Module:table/sortedPairs"
local title_is_title_module = "Module:title/isTitle"
local title_make_title_module = "Module:title/makeTitle"
local title_new_title_module = "Module:title/newTitle"
local title_redirect_target_module = "Module:title/redirectTarget"
local require = require
local m_parser = require(parser_module)
local mw = mw
local mw_title = mw.title
local mw_uri = mw.uri
local string = string
local table = table
local anchor_encode = mw_uri.anchorEncode
local build_template -- defined as export.buildTemplate below
local class_else_type = m_parser.class_else_type
local concat = table.concat
local encode_uri = mw_uri.encode
local find = string.find
local format = string.format
local gsub = string.gsub
local html_create = mw.html.create
local insert = table.insert
local is_node = m_parser.is_node
local lower = string.lower
local match = string.match
local next = next
local pairs = pairs
local parse -- defined as export.parse below
local parse_template_name -- defined below
local pcall = pcall
local rep = string.rep
local select = select
local sub = string.sub
local title_equals = mw_title.equals
local tostring = m_parser.tostring
local type = type
local umatch = mw.ustring.match
--[==[
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 encode_entities(...)
encode_entities = require(string_utilities_module).encode_entities
return encode_entities(...)
end
local function get_link_target(...)
get_link_target = require(pages_module).get_link_target
return get_link_target(...)
end
local function is_title(...)
is_title = require(title_is_title_module)
return is_title(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function make_title(...)
make_title = require(title_make_title_module)
return make_title(...)
end
local function new_title(...)
new_title = require(title_new_title_module)
return new_title(...)
end
local function pattern_escape(...)
pattern_escape = require(string_pattern_escape_module)
return pattern_escape(...)
end
local function php_htmlspecialchars(...)
php_htmlspecialchars = require(scribunto_module).php_htmlspecialchars
return php_htmlspecialchars(...)
end
local function php_ltrim(...)
php_ltrim = require(scribunto_module).php_ltrim
return php_ltrim(...)
end
local function php_trim(...)
php_trim = require(scribunto_module).php_trim
return php_trim(...)
end
local function redirect_target(...)
redirect_target = require(title_redirect_target_module)
return redirect_target(...)
end
local function replacement_escape(...)
replacement_escape = require(string_replacement_escape_module)
return replacement_escape(...)
end
local function scribunto_parameter_key(...)
scribunto_parameter_key = require(scribunto_module).scribunto_parameter_key
return scribunto_parameter_key(...)
end
local function shallow_copy(...)
shallow_copy = require(table_shallow_copy_module)
return shallow_copy(...)
end
local function sorted_pairs(...)
sorted_pairs = require(table_sorted_pairs_module)
return sorted_pairs(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function table_len(...)
table_len = require(table_length_module)
return table_len(...)
end
local function uupper(...)
uupper = require(string_utilities_module).upper
return uupper(...)
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 data
local function get_data()
data, get_data = load_data(data_module), nil
return data
end
local frame
local function get_frame()
frame, get_frame = mw.getCurrentFrame(), nil
return frame
end
local magic_words
local function get_magic_words()
magic_words, get_magic_words = load_data(magic_words_data_module), nil
return magic_words
end
local parser_extension_tags
local function get_parser_extension_tags()
parser_extension_tags, get_parser_extension_tags = load_data(parser_extension_tags_data_module), nil
return parser_extension_tags
end
------------------------------------------------------------------------------------
--
-- Nodes
--
------------------------------------------------------------------------------------
local Node = m_parser.node()
local new_node = Node.new
local function expand(obj, frame_args)
return is_node(obj) and obj:expand(frame_args) or obj
end
export.expand = expand
function Node:expand(frame_args)
local output = {}
for i = 1, #self do
output[i] = expand(self[i], frame_args)
end
return concat(output)
end
local Wikitext = Node:new_class("wikitext")
-- force_node ensures the output will always be a Wikitext node.
function Wikitext:new(this, force_node)
if type(this) ~= "table" then
return force_node and new_node(self, {this}) or this
elseif #this == 1 then
local this1 = this[1]
return force_node and class_else_type(this1) ~= "wikitext" and new_node(self, this) or this1
end
local success, str = pcall(concat, this)
if success then
return force_node and new_node(self, {str}) or str
end
return new_node(self, this)
end
-- First value is the parameter name.
-- Second value is the parameter's default value.
-- Any additional values are ignored: e.g. "{{{a|b|c}}}" is parameter "a" with default value "b" (*not* "b|c").
local Parameter = Node:new_class("parameter")
function Parameter:new(this)
local this2 = this[2]
if class_else_type(this2) == "argument" then
insert(this2, 2, "=")
this2 = Wikitext:new(this2)
end
if this[3] == nil then
this[2] = this2
else
this = {this[1], this2}
end
return new_node(self, this)
end
function Parameter:__tostring()
local output = {}
for i = 1, #self do
output[i] = tostring(self[i])
end
return "{{{" .. concat(output, "|") .. "}}}"
end
function Parameter:get_name(frame_args)
return scribunto_parameter_key(expand(self[1], frame_args))
end
function Parameter:get_default(frame_args)
local default = self[2]
if default ~= nil then
return expand(default, frame_args)
end
return "{{{" .. expand(self[1], frame_args) .. "}}}"
end
function Parameter:expand(frame_args)
if frame_args == nil then
return self:get_default()
end
local name = expand(self[1], frame_args)
local val = frame_args[scribunto_parameter_key(name)] -- Parameter in use.
if val ~= nil then
return val
end
val = self[2] -- Default.
if val ~= nil then
return expand(val, frame_args)
end
return "{{{" .. name .. "}}}"
end
local Argument = Node:new_class("argument")
function Argument:new(this)
local key = this._parse_data.key
this = Wikitext:new(this)
if key == nil then
return this
end
return new_node(self, {Wikitext:new(key), this})
end
function Argument:__tostring()
return tostring(self[1]) .. "=" .. tostring(self[2])
end
function Argument:expand(frame_args)
return expand(self[1], frame_args) .. "=" .. expand(self[2], frame_args)
end
local Template = Node:new_class("template")
function Template:__tostring()
local output = {}
for i = 1, #self do
output[i] = tostring(self[i])
end
return "{{" .. concat(output, "|") .. "}}"
end
-- Normalize the template name, check it's a valid template, then memoize results (using false for invalid titles).
-- Parser functions (e.g. {{#IF:a|b|c}}) need to have the first argument extracted from the title, as it comes after the colon. Because of this, the parser function and first argument are memoized as a table.
-- FIXME: Some parser functions have special argument handling (e.g. {{#SWITCH:}}).
do
local templates, parser_variables, parser_functions = {}, {}, {}
local function retrieve_magic_word_data(chunk)
local mgw_data = (magic_words or get_magic_words())[chunk]
if mgw_data then
return mgw_data
end
local normalized = uupper(chunk)
mgw_data = magic_words[normalized]
if mgw_data and not mgw_data.case_sensitive then
return mgw_data
end
end
-- Returns the name required to transclude the title object `title` using
-- template {{ }} syntax. If the `shortcut` flag is set, then any calls
-- which require a namespace prefix will use the abbreviated form where one
-- exists (e.g. "Template:PAGENAME" becomes "T:PAGENAME").
local function get_template_invocation_name(title, shortcut)
if not (is_title(title) and not title.isExternal) then
error("Template invocations require a valid page title, which cannot contain an interwiki prefix.")
end
local namespace = title.namespace
-- If not in the template namespace, include the prefix (or ":" if
-- mainspace).
if namespace ~= 10 then
return get_link_target(title, shortcut)
end
-- If in the template namespace and it shares a name with a magic word,
-- it needs the prefix "Template:".
local text, fragment = title.text, title.fragment
if fragment and fragment ~= "" then
text = text .. "#" .. fragment
end
local colon = find(text, ":", nil, true)
if not colon then
local mgw_data = retrieve_magic_word_data(text)
return mgw_data and mgw_data.parser_variable and get_link_target(title, shortcut) or text
end
local mgw_data = retrieve_magic_word_data(sub(text, 1, colon - 1))
if mgw_data and (mgw_data.parser_function or mgw_data.transclusion_modifier) then
return get_link_target(title, shortcut)
end
-- Also if "Template:" is necessary for disambiguation (e.g.
-- "Template:Category:Foo" can't be called with "Category:Foo").
local check = new_title(text, namespace)
return check and title_equals(title, check) and text or get_link_target(title, shortcut)
end
export.getTemplateInvocationName = get_template_invocation_name
function parse_template_name(name, has_args, fragment, force_transclusion)
local chunks, colon, start, n, p = {}, find(name, ":", nil, true), 1, 0, 0
while colon do
local mgw_data = retrieve_magic_word_data(php_ltrim(sub(name, start, colon - 1)))
if not mgw_data then
break
end
local priority = mgw_data.priority
if not (priority and priority > p) then
local pf = mgw_data.parser_function and mgw_data.name or nil
if pf then
n = n + 1
chunks[n] = pf .. ":"
return chunks, "parser function", sub(name, colon + 1)
end
break
end
n = n + 1
chunks[n] = mgw_data.name .. ":"
start, p = colon + 1, priority
colon = find(name, ":", start, true)
end
if start > 1 then
name = sub(name, start)
end
name = php_trim(name)
-- Parser variables can only take SUBST:/SAFESUBST: as modifiers.
if not has_args and p <= 1 then
local mgw_data = retrieve_magic_word_data(name)
local pv = mgw_data and mgw_data.parser_variable and mgw_data.name or nil
if pv then
n = n + 1
chunks[n] = pv
return chunks, "parser variable"
end
end
-- Get the template title with the custom new_title() function in
-- [[Module:title/newTitle]], with `allowOnlyFragment` set to false
-- (e.g. "{{#foo}}" is invalid) and `allowRelative` set to true, for
-- relative links for namespaces with subpages (e.g. "{{/foo}}").
local title = new_title(name, 10, false, true)
if not (title and not title.isExternal) then
return nil
end
if force_transclusion ~= "no_redirect" then
-- Resolve any redirects. If the redirect target is an interwiki link,
-- the template won't fail, but the redirect does not get resolved (i.e.
-- the redirect page itself gets transcluded, so the template name
-- should not be normalized to the target).
local redirect = redirect_target(title, force_transclusion)
if redirect and not redirect.isExternal then
title = redirect
end
end
-- If `fragment` is not true, unset it from the title object to prevent
-- it from being included by get_template_invocation_name.
if not fragment then
title.fragment = ""
end
chunks[n + 1] = get_template_invocation_name(title)
return chunks, "template"
end
-- Note: `force_transclusion` avoids incrementing the expensive parser function count by forcing transclusion
-- instead. This should only be used when there is a real risk that the expensive parser function limit of
-- 500 will be hit. If `force_transclusion` has the value "no_redirect", redirect checking is turned off
-- entirely. This should only be used in very limited circumstances when it is otherwise impossible to avoid
-- hitting the expensive parser limit and we are willing to handle the possible redirects ourselves.
local function process_name(self, frame_args, force_transclusion)
local name = expand(self[1], frame_args)
local has_args, norm = #self > 1
if not has_args then
norm = parser_variables[name]
if norm then
return norm, "parser variable"
end
end
norm = templates[name]
if norm then
local pf_arg1 = parser_functions[name]
return norm, pf_arg1 and "parser function" or "template", pf_arg1
elseif norm == false then
return nil
end
local chunks, subclass, pf_arg1 = parse_template_name(name, has_args, nil, force_transclusion)
-- Fail if invalid.
if not chunks then
templates[name] = false
return nil
end
local chunk1 = chunks[1]
-- Fail on SUBST:.
if chunk1 == "SUBST:" then
templates[name] = false
return nil
-- Any modifiers are ignored.
elseif subclass == "parser function" then
local pf = chunks[#chunks]
templates[name] = pf
parser_functions[name] = pf_arg1
return pf, "parser function", pf_arg1
end
-- Ignore SAFESUBST:, and treat MSGNW: as a parser function with the pagename as its first argument (ignoring any RAW: that comes after).
if chunks[chunk1 == "SAFESUBST:" and 2 or 1] == "MSGNW:" then
pf_arg1 = chunks[#chunks]
local pf = "MSGNW:"
templates[name] = pf
parser_functions[name] = pf_arg1
return pf, "parser function", pf_arg1
end
-- Ignore any remaining modifiers, as they've done their job.
local output = chunks[#chunks]
if subclass == "parser variable" then
parser_variables[name] = output
else
templates[name] = output
end
return output, subclass
end
function Template:get_name(frame_args, force_transclusion)
-- Only return the first return value.
return (process_name(self, frame_args, force_transclusion))
end
function Template:get_arguments(frame_args)
local name, subclass, pf_arg1 = process_name(self, frame_args)
if name == nil then
return nil
elseif subclass == "parser variable" then
return {}
end
local template_args = {}
if subclass == "parser function" then
template_args[1] = pf_arg1
for i = 2, #self do
template_args[i] = expand(self[i], frame_args) -- Not trimmed.
end
return template_args
end
local implicit = 0
for i = 2, #self do
local arg = self[i]
if class_else_type(arg) == "argument" then
template_args[scribunto_parameter_key(expand(arg[1], frame_args))] = php_trim((expand(arg[2], frame_args)))
else
implicit = implicit + 1
template_args[implicit] = expand(arg, frame_args) -- Not trimmed.
end
end
return template_args
end
-- BIG TODO: manual template expansion.
function Template:expand(frame_args)
local name, subclass, pf_arg1 = process_name(self, frame_args)
if name == nil then
local output = {}
for i = 1, #self do
output[i] = expand(self[i], frame_args)
end
return "{{" .. concat(output, "|") .. "}}"
elseif subclass == "parser variable" then
return (frame or get_frame()):preprocess("{{" .. name .. "}}")
elseif subclass == "parser function" then
local f = frame or get_frame()
if frame_args ~= nil then
local success, new_f = pcall(f.newChild, f, {args = frame_args})
if success then
f = new_f
end
end
return f:preprocess(tostring(self))
end
local output = {}
for i = 1, #self do
output[i] = expand(self[i], frame_args)
end
return (frame or get_frame()):preprocess("{{" .. concat(output, "|") .. "}}")
end
end
local Tag = Node:new_class("tag")
function Tag:__tostring()
local open_tag, attributes, n = {"<", self.name}, self:get_attributes(), 2
for attr, value in next, attributes do
n = n + 1
open_tag[n] = " " .. php_htmlspecialchars(attr) .. "=\"" .. php_htmlspecialchars(value, "compat") .. "\""
end
if self.self_closing then
return concat(open_tag) .. "/>"
end
return concat(open_tag) .. ">" .. concat(self) .. "</" .. self.name .. ">"
end
do
local valid_attribute_name
local function get_valid_attribute_name()
valid_attribute_name, get_valid_attribute_name = (data or get_data()).valid_attribute_name, nil
return valid_attribute_name
end
function Tag:get_attributes()
local raw = self.attributes
if not raw then
self.attributes = {}
return self.attributes
elseif type(raw) == "table" then
return raw
end
if sub(raw, -1) == "/" then
raw = sub(raw, 1, -2)
end
local attributes, head = {}, 1
-- Semi-manual implementation of the native regex.
while true do
local name, loc = match(raw, "([^\t\n\f\r />][^\t\n\f\r /=>]*)()", head)
if not name then
break
end
head = loc
local value
loc = match(raw, "^[\t\n\f\r ]*=[\t\n\f\r ]*()", head)
if loc then
head = loc
-- Either "", '' or the value ends on a space/at the end. Missing
-- end quotes are repaired by closing the value at the end.
value, loc = match(raw, "^\"([^\"]*)\"?()", head)
if not value then
value, loc = match(raw, "^'([^']*)'?()", head)
if not value then
value, loc = match(raw, "^([^\t\n\f\r ]*)()", head)
end
end
head = loc
end
-- valid_attribute_name is a pattern matching a valid attribute name.
-- Defined in the data due to its length - see there for more info.
if umatch(name, valid_attribute_name or get_valid_attribute_name()) then
-- Sanitizer applies PHP strtolower (ASCII-only).
attributes[lower(name)] = value and decode_entities(
php_trim((gsub(value, "[\t\n\r ]+", " ")))
) or ""
end
end
self.attributes = attributes
return attributes
end
end
function Tag:expand()
return (frame or get_frame()):preprocess(tostring(self))
end
local Heading = Node:new_class("heading")
function Heading:new(this)
if #this > 1 then
local success, str = pcall(concat, this)
if success then
return new_node(self, {
str,
level = this.level,
section = this.section,
index = this.index
})
end
end
return new_node(self, this)
end
do
local node_tostring = Node.__tostring
function Heading:__tostring()
local eq = rep("=", self.level)
return eq .. node_tostring(self) .. eq
end
end
do
local expand_node = Node.expand
-- Expanded heading names can contain "\n" (e.g. inside nowiki tags), which
-- causes any heading containing them to fail. However, in such cases, the
-- native parser still treats it as a heading for the purpose of section
-- numbers.
local function validate_name(self, frame_args)
local name = expand_node(self, frame_args)
if find(name, "\n", nil, true) then
return nil
end
return name
end
function Heading:get_name(frame_args)
local name = validate_name(self, frame_args)
return name ~= nil and php_trim(name) or nil
end
-- FIXME: account for anchor disambiguation.
function Heading:get_anchor(frame_args)
local name = validate_name(self, frame_args)
return name ~= nil and decode_entities(anchor_encode(name)) or nil
end
function Heading:expand(frame_args)
local eq = rep("=", self.level)
return eq .. expand_node(self, frame_args) .. eq
end
end
------------------------------------------------------------------------------------
--
-- Parser
--
------------------------------------------------------------------------------------
local Parser = m_parser.string_parser()
-- Template or parameter.
-- Parsed by matching the opening braces innermost-to-outermost (ignoring lone closing braces). Parameters {{{ }}} take priority over templates {{ }} where possible, but a double closing brace will always result in a closure, even if there are 3+ opening braces.
-- For example, "{{{{foo}}}}" (4) is parsed as a parameter enclosed by single braces, and "{{{{{foo}}}}}" (5) is a parameter inside a template. However, "{{{{{foo }} }}}" is a template inside a parameter, due to "}}" forcing the closure of the inner node.
do
-- Handlers.
local handle_name
local handle_argument
local handle_value
local function do_template_or_parameter(self, inner_node)
self:push_sublayer(handle_name)
self:set_pattern("[\n<[{|}]")
-- If a node has already been parsed, nest it at the start of the new
-- outer node (e.g. when parsing"{{{{foo}}bar}}", the template "{{foo}}"
-- is parsed first, since it's the innermost, and becomes the first
-- node of the outer template.
if inner_node then
self:emit(inner_node)
end
end
local function pipe(self)
self:emit(Wikitext:new(self:pop_sublayer()))
self:push_sublayer(handle_argument)
self:set_pattern("[\n<=[{|}]")
end
local function rbrace(self, this)
if self:read(1) == "}" then
self:emit(Wikitext:new(self:pop_sublayer()))
return self:pop()
end
self:emit(this)
end
function handle_name(self, ...)
handle_name = self:switch(handle_name, {
["\n"] = Parser.heading_block,
["<"] = Parser.tag,
["["] = Parser.wikilink_block,
["{"] = Parser.braces,
["|"] = pipe,
["}"] = rbrace,
[""] = Parser.fail_route,
[false] = Parser.emit
})
return handle_name(self, ...)
end
function handle_argument(self, ...)
handle_argument = self:switch(handle_argument, {
["\n"] = function(self, this)
return self:heading_block(this, "==")
end,
["<"] = Parser.tag,
["="] = function(self)
local key = self:pop_sublayer()
self:push_sublayer(handle_value)
self:set_pattern("[\n<[{|}]")
self.current_layer._parse_data.key = key
end,
["["] = Parser.wikilink_block,
["{"] = Parser.braces,
["|"] = pipe,
["}"] = rbrace,
[""] = Parser.fail_route,
[false] = Parser.emit
})
return handle_argument(self, ...)
end
function handle_value(self, ...)
handle_value = self:switch(handle_value, {
["\n"] = Parser.heading_block,
["<"] = Parser.tag,
["["] = Parser.wikilink_block,
["{"] = Parser.braces,
["|"] = function(self)
self:emit(Argument:new(self:pop_sublayer()))
self:push_sublayer(handle_argument)
self:set_pattern("[\n<=[{|}]")
end,
["}"] = function(self, this)
if self:read(1) == "}" then
self:emit(Argument:new(self:pop_sublayer()))
return self:pop()
end
self:emit(this)
end,
[""] = Parser.fail_route,
[false] = Parser.emit
})
return handle_value(self, ...)
end
function Parser:template_or_parameter()
local text, head, node_to_emit, failed = self.text, self.head
-- Comments/tags interrupt the brace count.
local braces = match(text, "^{+()", head) - head
self:advance(braces)
while true do
local success, node = self:try(do_template_or_parameter, node_to_emit)
-- Fail means no "}}" or "}}}" was found, so emit any remaining
-- unmatched opening braces before any templates/parameters that
-- were found.
if not success then
self:emit(rep("{", braces))
failed = true
break
-- If there are 3+ opening and closing braces, it's a parameter.
elseif braces >= 3 and self:read(2) == "}" then
self:advance(3)
braces = braces - 3
node = Parameter:new(node)
-- Otherwise, it's a template.
else
self:advance(2)
braces = braces - 2
node = Template:new(node)
end
local index = head + braces
node.index = index
node.raw = sub(text, index, self.head - 1)
node_to_emit = node
-- Terminate once not enough braces remain for further matches.
if braces == 0 then
break
-- Emit any stray opening brace before any matched nodes.
elseif braces == 1 then
self:emit("{")
break
end
end
if node_to_emit then
self:emit(node_to_emit)
end
return braces, failed
end
end
-- Tag.
do
local end_tags
local function get_end_tags()
end_tags, get_end_tags = (data or get_data()).end_tags, nil
return end_tags
end
-- Handlers.
local handle_start
local handle_tag
local function do_tag(self)
local layer = self.current_layer
layer._parse_data.handler, layer.index = handle_start, self.head
self:set_pattern("[%s/>]")
self:advance()
end
local function is_ignored_tag(self, this)
if self.transcluded then
return this == "includeonly"
end
return this == "noinclude" or this == "onlyinclude"
end
local function ignored_tag(self, text, head)
local loc = find(text, ">", head, true)
if not loc then
return self:fail_route()
end
self:jump(loc)
local tag = self:pop()
tag.ignored = true
return tag
end
function handle_start(self, this)
if this == "/" then
local text, head = self.text, self.head + 1
local this = match(text, "^[^%s/>]+", head)
if this and is_ignored_tag(self, lower(this)) then
head = head + #this
if not match(text, "^/[^>]", head) then
return ignored_tag(self, text, head)
end
end
return self:fail_route()
elseif this == "" then
return self:fail_route()
end
-- Tags are only case-insensitive with ASCII characters.
local raw_name = this
this = lower(this)
local end_tag_pattern = (end_tags or get_end_tags())[this]
if not end_tag_pattern then -- Validity check.
return self:fail_route()
end
local layer = self.current_layer
local pdata = layer._parse_data
local text, head = self.text, self.head + pdata.step
if match(text, "^/[^>]", head) then
return self:fail_route()
elseif is_ignored_tag(self, this) then
return ignored_tag(self, text, head)
-- If an onlyinclude tag is not ignored (and cannot be active since it
-- would have triggered special handling earlier), it must be plaintext.
elseif this == "onlyinclude" then
return self:fail_route()
elseif this == "noinclude" or this == "includeonly" then
layer.ignored = true -- Ignored block.
layer.raw_name = raw_name
end
layer.name, pdata.handler, pdata.end_tag_pattern = this, handle_tag, end_tag_pattern
self:set_pattern(">")
end
function handle_tag(self, this)
if this == "" then
return self:fail_route()
end
local layer = self.current_layer
if this ~= ">" then
layer.attributes = this
return
elseif self:read(-1) == "/" then
layer.self_closing = true
return self:pop()
end
local text, head = self.text, self.head + 1
local loc1, loc2 = find(text, layer._parse_data.end_tag_pattern, head)
if loc1 then
if loc1 > head then
self:emit(sub(text, head, loc1 - 1))
end
self:jump(loc2)
return self:pop()
-- noinclude and includeonly will tolerate having no closing tag, but
-- only if given in lowercase. This is due to a preprocessor bug, as
-- it uses a regex with the /i (case-insensitive) flag to check for
-- end tags, but a simple array lookup with lowercase tag names when
-- looking up which tags should tolerate no closing tag (exact match
-- only, so case-sensitive).
elseif layer.ignored then
local raw_name = layer.raw_name
if raw_name == "noinclude" or raw_name == "includeonly" then
self:jump(#text)
return self:pop()
end
end
return self:fail_route()
end
function Parser:tag()
-- HTML comment.
if self:read(1, 3) == "!--" then
local text = self.text
self:jump(select(2, find(text, "-->", self.head + 4, true)) or #text)
-- onlyinclude tags (which must be lowercase with no whitespace).
elseif self.onlyinclude and self:read(1, 13) == "/onlyinclude>" then
local text = self.text
self:jump(select(2, find(text, "<onlyinclude>", self.head + 14, true)) or #text)
else
local success, tag = self:try(do_tag)
if not success then
self:emit("<")
elseif not tag.ignored then
self:emit(Tag:new(tag))
end
end
end
end
-- Heading.
-- The preparser assigns each heading a number, which is used for things like section edit links. The preparser will only do this for heading blocks which aren't nested inside templates, parameters and parser tags. In some cases (e.g. when template blocks contain untrimmed newlines), a preparsed heading may not be treated as a heading in the final output. That does not affect the preparser, however, which will always count sections based on the preparser heading count, since it can't know what a template's final output will be.
do
-- Handlers.
local handle_start
local handle_body
local handle_possible_end
local function do_heading(self)
local layer, head = self.current_layer, self.head
layer._parse_data.handler, layer.index = handle_start, head
self:set_pattern("[\t\n ]")
-- Comments/tags interrupt the equals count.
local eq = match(self.text, "^=+()", head) - head
layer.level = eq
self:advance(eq)
end
local function do_heading_possible_end(self)
self.current_layer._parse_data.handler = handle_possible_end
self:set_pattern("[\n<]")
end
function handle_start(self, ...)
-- ===== is "=" as an L2; ======== is "==" as an L3 etc.
local function newline(self)
local layer = self.current_layer
local eq = layer.level
if eq <= 2 then
return self:fail_route()
end
-- Calculate which equals signs determine the heading level.
local level_eq = eq - (2 - eq % 2)
level_eq = level_eq > 12 and 12 or level_eq
-- Emit the excess.
self:emit(rep("=", eq - level_eq))
layer.level = level_eq / 2
return self:pop()
end
local function whitespace(self)
local success, possible_end = self:try(do_heading_possible_end)
if success then
self:emit(Wikitext:new(possible_end))
self.current_layer._parse_data.handler = handle_body
self:set_pattern("[\n<=[{]")
return self:consume()
end
return newline(self)
end
handle_start = self:switch(handle_start, {
["\t"] = whitespace,
["\n"] = newline,
[" "] = whitespace,
[""] = newline,
[false] = function(self)
-- Emit any excess = signs once we know it's a conventional heading. Up till now, we couldn't know if the heading is just a string of = signs (e.g. ========), so it wasn't guaranteed that the heading text starts after the 6th.
local layer = self.current_layer
local eq = layer.level
if eq > 6 then
self:emit(1, rep("=", eq - 6))
layer.level = 6
end
layer._parse_data.handler = handle_body
self:set_pattern("[\n<=[{]")
return self:consume()
end
})
return handle_start(self, ...)
end
function handle_body(self, ...)
handle_body = self:switch(handle_body, {
["\n"] = Parser.fail_route,
["<"] = Parser.tag,
["="] = function(self)
-- Comments/tags interrupt the equals count.
local eq = match(self.text, "^=+", self.head)
local eq_len = #eq
self:advance(eq_len)
local success, possible_end = self:try(do_heading_possible_end)
if success then
self:emit(eq)
self:emit(Wikitext:new(possible_end))
return self:consume()
end
local layer = self.current_layer
local level = layer.level
if eq_len > level then
self:emit(rep("=", eq_len - level))
elseif level > eq_len then
layer.level = eq_len
self:emit(1, rep("=", level - eq_len))
end
return self:pop()
end,
["["] = Parser.wikilink_block,
["{"] = function(self, this)
return self:braces(this, true)
end,
[""] = Parser.fail_route,
[false] = Parser.emit
})
return handle_body(self, ...)
end
function handle_possible_end(self, ...)
handle_possible_end = self:switch(handle_possible_end, {
["\n"] = Parser.fail_route,
["<"] = function(self)
if self:read(1, 3) ~= "!--" then
return self:pop()
end
local head = select(2, find(self.text, "-->", self.head + 4, true))
if not head then
return self:pop()
end
self:jump(head)
end,
[""] = Parser.fail_route,
[false] = function(self, this)
if not match(this, "^[\t ]+()$") then
return self:pop()
end
self:emit(this)
end
})
return handle_possible_end(self, ...)
end
function Parser:heading()
local success, heading = self:try(do_heading)
if success then
local section = self.section + 1
heading.section = section
self.section = section
self:emit(Heading:new(heading))
return self:consume()
else
self:emit("=")
end
end
end
------------------------------------------------------------------------------------
--
-- Block handlers
--
------------------------------------------------------------------------------------
-- Block handlers.
-- These are blocks which can affect template/parameter parsing, since they're also parsed by Parsoid at the same time (even though they aren't processed until later).
-- All blocks (including templates/parameters) can nest inside each other, but an inner block must be closed before the outer block which contains it. This is why, for example, the wikitext "{{template| [[ }}" will result in an unprocessed template, since the inner "[[" is treated as the opening of a wikilink block, which prevents "}}" from being treated as the closure of the template block. On the other hand, "{{template| [[ ]] }}" will process correctly, since the wikilink block is closed before the template closure. It makes no difference whether the block will be treated as valid or not when it's processed later on, so "{{template| [[ }} ]] }}" would also work, even though "[[ }} ]]" is not a valid wikilink.
-- Note that nesting also affects pipes and equals signs, in addition to block closures.
-- These blocks can be nested to any degree, so "{{template| [[ [[ [[ ]] }}" will not work, since only one of the three wikilink blocks has been closed. On the other hand, "{{template| [[ [[ [[ ]] ]] ]] }}" will work.
-- All blocks are implicitly closed by the end of the text, since their validity is irrelevant at this stage.
-- Language conversion block.
-- Opens with "-{" and closes with "}-". However, templates/parameters take priority, so "-{{" is parsed as "-" followed by the opening of a template/parameter block (depending on what comes after).
-- Note: Language conversion blocks aren't actually enabled on the English Wiktionary, but Parsoid still parses them at this stage, so they can affect the closure of outer blocks: e.g. "[[ -{ ]]" is not a valid wikilink block, since the "]]" falls inside the new language conversion block.
do
--Handler.
local handle_language_conversion_block
local function do_language_conversion_block(self)
self.current_layer._parse_data.handler = handle_language_conversion_block
self:set_pattern("[\n<[{}]")
end
function handle_language_conversion_block(self, ...)
handle_language_conversion_block = self:switch(handle_language_conversion_block, {
["\n"] = Parser.heading_block,
["<"] = Parser.tag,
["["] = Parser.wikilink_block,
["{"] = Parser.braces,
["}"] = function(self, this)
if self:read(1) == "-" then
self:emit("}-")
self:advance()
return self:pop()
end
self:emit(this)
end,
[""] = Parser.pop,
[false] = Parser.emit
})
return handle_language_conversion_block(self, ...)
end
function Parser:braces(this, fail_on_unclosed_braces)
local language_conversion_block = self:read(-1) == "-"
if self:read(1) == "{" then
local braces, failed = self:template_or_parameter()
-- Headings will fail if they contain an unclosed brace block.
if failed and fail_on_unclosed_braces then
return self:fail_route()
-- Language conversion blocks cannot begin "-{{", but can begin
-- "-{{{" iff parsed as "-{" + "{{".
elseif not (language_conversion_block and braces == 1) then
return self:consume()
end
else
self:emit(this)
if not language_conversion_block then
return
end
self:advance()
end
self:emit(Wikitext:new(self:get(do_language_conversion_block)))
end
end
--[==[
Headings
Opens with "\n=" (or "=" at the start of the text), and closes with "\n" or the end of the text. Note that it doesn't matter whether the heading will fail to process due to a premature newline (e.g. if there are no closing signs), so at this stage the only thing that matters for closure is the newline or end of text.
Note: Heading blocks are only parsed like this if they occur inside a template, since they do not iterate the preparser's heading count (i.e. they aren't proper headings).
Note 2: if directly inside a template argument with no previous equals signs, a newline followed by a single equals sign is parsed as an argument equals sign, not the opening of a new L1 heading block. This does not apply to any other heading levels. As such, {{template|key\n=}}, {{template|key\n=value}} or even {{template|\n=}} will successfully close, but {{template|key\n==}}, {{template|key=value\n=more value}}, {{template\n=}} etc. will not, since in the latter cases the "}}" would fall inside the new heading block.
]==]
do
--Handler.
local handle_heading_block
local function do_heading_block(self)
self.current_layer._parse_data.handler = handle_heading_block
self:set_pattern("[\n<[{]")
end
function handle_heading_block(self, ...)
handle_heading_block = self:switch(handle_heading_block, {
["\n"] = function(self)
self:newline()
return self:pop()
end,
["<"] = Parser.tag,
["["] = Parser.wikilink_block,
["{"] = Parser.braces,
[""] = Parser.pop,
[false] = Parser.emit
})
return handle_heading_block(self, ...)
end
function Parser:heading_block(this, nxt)
self:newline()
this = this .. (nxt or "=")
local loc = #this - 1
while self:read(0, loc) == this do
self:advance()
self:emit(Wikitext:new(self:get(do_heading_block)))
end
end
end
-- Wikilink block.
-- Opens with "[[" and closes with "]]".
do
-- Handler.
local handle_wikilink_block
local function do_wikilink_block(self)
self.current_layer._parse_data.handler = handle_wikilink_block
self:set_pattern("[\n<[%]{]")
end
function handle_wikilink_block(self, ...)
handle_wikilink_block = self:switch(handle_wikilink_block, {
["\n"] = Parser.heading_block,
["<"] = Parser.tag,
["["] = Parser.wikilink_block,
["]"] = function(self, this)
if self:read(1) == "]" then
self:emit("]]")
self:advance()
return self:pop()
end
self:emit(this)
end,
["{"] = Parser.braces,
[""] = Parser.pop,
[false] = Parser.emit
})
return handle_wikilink_block(self, ...)
end
function Parser:wikilink_block()
if self:read(1) == "[" then
self:emit("[[")
self:advance(2)
self:emit(Wikitext:new(self:get(do_wikilink_block)))
else
self:emit("[")
end
end
end
-- Lines which only contain comments, " " and "\t" are eaten, so long as
-- they're bookended by "\n" (i.e. not the first or last line).
function Parser:newline()
local text, head = self.text, self.head
while true do
repeat
local loc = match(text, "^[\t ]*<!%-%-()", head + 1)
if not loc then
break
end
loc = select(2, find(text, "-->", loc, true))
head = loc or head
until not loc
-- Fail if no comments found.
if head == self.head then
break
end
head = match(text, "^[\t ]*()\n", head + 1)
if not head then
break
end
self:jump(head)
end
self:emit("\n")
end
do
-- Handlers.
local handle_start
local main_handler
-- If `transcluded` is true, then the text is checked for a pair of
-- onlyinclude tags. If these are found (even if they're in the wrong
-- order), then the start of the page is treated as though it is preceded
-- by a closing onlyinclude tag.
-- Note 1: unlike other parser extension tags, onlyinclude tags are case-
-- sensitive and cannot contain whitespace.
-- Note 2: onlyinclude tags *can* be implicitly closed by the end of the
-- text, but the hard requirement above means this can only happen if
-- either the tags are in the wrong order or there are multiple onlyinclude
-- blocks.
local function do_parse(self, transcluded)
self.current_layer._parse_data.handler = handle_start
self:set_pattern(".")
self.section = 0
if not transcluded then
return
end
self.transcluded = true
local text = self.text
if find(text, "</onlyinclude>", nil, true) then
local head = find(text, "<onlyinclude>", nil, true)
if head then
self.onlyinclude = true
self:jump(head + 13)
end
end
end
-- If the first character is "=", try parsing it as a heading.
function handle_start(self, this)
self.current_layer._parse_data.handler = main_handler
self:set_pattern("[\n<{]")
if this == "=" then
return self:heading()
end
return self:consume()
end
function main_handler(self, ...)
main_handler = self:switch(main_handler, {
["\n"] = function(self)
self:newline()
if self:read(1) == "=" then
self:advance()
return self:heading()
end
end,
["<"] = Parser.tag,
["{"] = function(self, this)
if self:read(1) == "{" then
self:template_or_parameter()
return self:consume()
end
self:emit(this)
end,
[""] = Parser.pop,
[false] = Parser.emit
})
return main_handler(self, ...)
end
function export.parse(text, transcluded)
local text_type = type(text)
return (select(2, Parser:parse{
text = text_type == "string" and text or
text_type == "number" and tostring(text) or
error("bad argument #1 (string expected, got " .. text_type .. ")"),
node = {Wikitext, true},
route = {do_parse, transcluded}
}))
end
parse = export.parse
end
function export.find_templates(text, not_transcluded)
return parse(text, not not_transcluded):iterate_nodes("template")
end
do
local link_parameter_1, link_parameter_2
local function get_link_parameter_1()
link_parameter_1, get_link_parameter_1 = (data or get_data()).template_link_param_1, nil
return link_parameter_1
end
local function get_link_parameter_2()
link_parameter_2, get_link_parameter_2 = (data or get_data()).template_link_param_2, nil
return link_parameter_2
end
-- Generate a link. If the target title doesn't have a fragment, use "#top"
-- (which is an implicit anchor at the top of every page), as this ensures
-- self-links still display as links, since bold display is distracting and
-- unintuitive for template links.
local function link_page(title, display)
local fragment = title.fragment
if fragment == "" then
fragment = "top"
end
return format(
"[[:%s|%s]]",
encode_uri(title.prefixedText .. "#" .. fragment, "WIKI"),
display
)
end
-- pf_arg1 or pf_arg2 may need to be linked if a given parser function
-- treats them as a pagename. If a key exists in `namespace`, the value is
-- the namespace for the page: if not 0, then the namespace prefix will
-- always be added to the input (e.g. {{#invoke:}} can only target the
-- Module: namespace, so inputting "Template:foo" gives
-- "Module:Template:foo", and "Module:foo" gives "Module:Module:foo").
-- However, this isn't possible with mainspace (namespace 0), so prefixes
-- are respected. make_title() handles all of this automatically.
local function finalize_arg(pagename, namespace)
if namespace == nil then
return pagename
end
local title = make_title(namespace, pagename)
return title and not title.isExternal and link_page(title, pagename) or pagename
end
local function render_title(name, args)
-- parse_template_name returns a table of transclusion modifiers plus
-- the normalized template/magic word name, which will be used as link
-- targets. The third return value pf_arg1 is the first argument of a
-- a parser function, which comes after the colon (e.g. "foo" in
-- "{{#IF:foo|bar|baz}}"). This means args[1] (i.e. the first argument
-- that comes after a pipe is actually argument 2, and so on. Note: the
-- second parameter of parse_template_name checks if there are any
-- arguments, since parser variables cannot take arguments (e.g.
-- {{CURRENTYEAR}} is a parser variable, but {{CURRENTYEAR|foo}}
-- transcludes "Template:CURRENTYEAR"). In such cases, the returned
-- table explicitly includes the "Template:" prefix in the template
-- name. The third parameter instructs it to retain any fragment in the
-- template name in the returned table, if present.
local chunks, subclass, pf_arg1 = parse_template_name(
name,
args and pairs(args)(args) ~= nil,
true
)
if chunks == nil then
return name, args
end
local chunks_len = #chunks
-- Additionally, generate the corresponding table `rawchunks`, which
-- is a list of colon-separated chunks in the raw input. This is used
-- to retrieve the display forms for each chunk.
local rawchunks = split(name, ":")
for i = 1, chunks_len - 1 do
chunks[i] = format(
"[[%s|%s]]",
encode_uri((magic_words or get_magic_words())[sub(chunks[i], 1, -2)].transclusion_modifier, "WIKI"),
rawchunks[i]
)
end
local chunk = chunks[chunks_len]
-- If it's a template, return a link to it with link_page, concatenating
-- the remaining chunks in `rawchunks` to form the display text.
-- Use new_title with the default namespace 10 (Template:) to generate
-- a target title, which is the same setting used for retrieving
-- templates (including those in other namespaces, as prefixes override
-- the default).
if subclass == "template" then
chunks[chunks_len] = link_page(
new_title(chunk, 10),
concat(rawchunks, ":", chunks_len) -- :
)
return concat(chunks, ":"), args -- :
elseif subclass == "parser variable" then
chunks[chunks_len] = format(
"[[%s|%s]]",
encode_uri((magic_words or get_magic_words())[chunk].parser_variable, "WIKI"),
rawchunks[chunks_len]
)
return concat(chunks, ":"), args -- :
end
-- Otherwise, it must be a parser function.
local mgw_data = (magic_words or get_magic_words())[sub(chunk, 1, -2)]
local link = mgw_data.parser_function or mgw_data.transclusion_modifier
local pf_arg2 = args and args[1] or nil
-- Some magic words have different links, depending on whether argument
-- 2 is specified (e.g. "baz" in {{foo:bar|baz}}).
if type(link) == "table" then
link = pf_arg2 and link[2] or link[1]
end
chunks[chunks_len] = format(
"[[%s|%s]]",
encode_uri(link, "WIKI"),
rawchunks[chunks_len]
)
-- #TAG: has special handling, because documentation links for parser
-- extension tags come from [[Module:data/parser extension tags]].
if chunk == "#TAG:" then
-- Tags are only case-insensitive with ASCII characters.
local tag = (parser_extension_tags or get_parser_extension_tags())[lower(php_trim(pf_arg1))]
if tag then
pf_arg1 = format(
"[[%s|%s]]",
encode_uri(tag, "WIKI"),
pf_arg1
)
end
-- Otherwise, finalize pf_arg1 and add it to `chunks`.
else
pf_arg1 = finalize_arg(pf_arg1, (link_parameter_1 or get_link_parameter_1())[chunk])
end
chunks[chunks_len + 1] = pf_arg1
-- Finalize pf_arg2 (if applicable), then return.
if pf_arg2 then
args = shallow_copy(args) -- Avoid destructively modifying args.
args[1] = finalize_arg(pf_arg2, (link_parameter_2 or get_link_parameter_2())[chunk])
end
return concat(chunks, ":"), args -- :
end
function export.buildTemplate(title, args)
local output = {title}
if not args then
return output
end
-- Iterate over all numbered parameters in order, followed by any
-- remaining parameters in codepoint order. Implicit parameters are
-- used wherever possible, even if explicit numbers are interpolated
-- between them (e.g. 0 would go before any implicit parameters, and
-- 2.5 between 2 and 3).
-- TODO: handle "=" and "|" in params/values.
local implicit
for k, v in sorted_pairs(args) do
if type(k) == "number" and k >= 1 and k % 1 == 0 then
if implicit == nil then
implicit = table_len(args)
end
insert(output, k <= implicit and v or k .. "=" .. v)
else
insert(output, k .. "=" .. v)
end
end
return output
end
build_template = export.buildTemplate
function export.templateLink(title, args, no_link)
if not no_link then
title, args = render_title(title, args)
end
local output = build_template(title, args)
for i = 1, #output do
output[i] = encode_entities(output[i], "={}", true, true)
end
return tostring(html_create("code")
:css("white-space", "pre-wrap")
:wikitext("{{" .. concat(output, "|") .. "}}") -- {{ | }}
)
end
end
do
function export.find_parameters(text, not_transcluded)
return parse(text, not not_transcluded):iterate_nodes("parameter")
end
function export.displayParameter(name, default)
return tostring(html_create("code")
:css("white-space", "pre-wrap")
:wikitext("{{{" .. concat({name, default}, "|") .. "}}}") -- {{{ | }}}
)
end
end
do
local function check_level(level)
if type(level) ~= "number" then
error("Heading levels must be numbers.")
elseif level < 1 or level > 6 or level % 1 ~= 0 then
error("Heading levels must be integers between 1 and 6.")
end
return level
end
-- FIXME: should headings which contain "\n" be returned? This may depend
-- on variable factors, like template expansion. They iterate the heading
-- count number, but fail on rendering. However, in some cases a different
-- heading might still be rendered due to intermediate equals signs; it
-- may even be of a different heading level: e.g., this is parsed as an
-- L2 heading with a newline (due to the wikilink block), but renders as the
-- L1 heading "=foo[[". Section edit links are sometimes (but not always)
-- present in such cases.
-- ==[[=
-- ]]==
-- TODO: section numbers for edit links seem to also include headings
-- nested inside templates and parameters (but apparently not those in
-- parser extension tags - need to test this more). If we ever want to add
-- section edit links manually, this will need to be accounted for.
function export.find_headings(text, i, j)
local parsed = parse(text)
if i == nil and j == nil then
return parse(text):iterate_nodes("heading")
end
i = i and check_level(i) or 1
j = j and check_level(j) or 6
return parsed:iterate(function(v)
if class_else_type(v) == "heading" then
local level = v.level
return level >= i and level <= j
end
end)
end
end
do
local function make_tag(tag)
return tostring(html_create("code")
:css("white-space", "pre-wrap")
:wikitext("<" .. tag .. ">")
)
end
-- Note: invalid tags are returned without links.
function export.wikitagLink(tag)
-- ">" can't appear in tags (including attributes) since the parser
-- unconditionally treats ">" as the end of a tag.
if find(tag, ">", nil, true) then
return make_tag(tag)
end
-- Tags must start "<tagname..." or "</tagname...", with no whitespace
-- after "<" or "</".
local slash, tagname, remainder = match(tag, "^(/?)([^/%s]+)(.*)$")
if not tagname then
return make_tag(tag)
end
-- Tags are only case-insensitive with ASCII characters.
local link = lower(tagname)
if (
-- onlyinclude tags must be lowercase and are whitespace intolerant.
link == "onlyinclude" and (link ~= tagname or remainder ~= "") or
-- Closing wikitags (except onlyinclude) can only have whitespace
-- after the tag name.
slash == "/" and not match(remainder, "^%s*()$") or
-- Tagnames cannot be followed immediately by "/", unless it comes
-- at the end (e.g. "<nowiki/>", but not "<nowiki/ >").
remainder ~= "/" and sub(remainder, 1, 1) == "/"
) then
-- Output with no link.
return make_tag(tag)
end
-- Partial transclusion tags aren't in the table of parser extension
-- tags.
if link == "noinclude" or link == "includeonly" or link == "onlyinclude" then
link = "mw:Transclusion#Partial transclusion"
else
link = (parser_extension_tags or get_parser_extension_tags())[link]
end
if link then
tag = gsub(tag, pattern_escape(tagname), "[[" .. replacement_escape(encode_uri(link, "WIKI")) .. "|%0]]", 1)
end
return make_tag(tag)
end
end
-- For convenience.
export.class_else_type = class_else_type
return export
8bar8n9ekj2343wewntknhbuylq848v
Modul:template parser/data
828
9246
25211
2026-08-19T06:28:39Z
Deepturquoise
2456
+ ti enwikt
25211
Scribunto
text/plain
local string = string
local case_insensitive_pattern = require("Module:string utilities").case_insensitive_pattern
local gsub = string.gsub
local upper = string.upper
local data = {}
do
local tags = mw.loadData("Module:data/parser extension tags")
local data_end_tags = {}
-- Generates the string pattern for the end tag.
-- The preprocessor uses the regex "/<\/TAG\s*>/i", so only ASCII characters
-- are case-insensitive.
local function end_tag_pattern(tag)
data_end_tags[tag] = "</" .. case_insensitive_pattern(tag, nil, true) .. "%s*>"
end
for tag in pairs(tags) do
end_tag_pattern(tag)
end
end_tag_pattern("includeonly")
end_tag_pattern("noinclude")
data_end_tags["onlyinclude"] = true -- Pattern is not required, but a key is needed for tag validity checks.
data.end_tags = data_end_tags
end
-- The parser's HTML sanitizer validates tag attributes with the regex
-- "/^([:_\p{L}\p{N}][:_\.\-\p{L}\p{N}]*)$/sxu". Ustring's "%w" is defined as
-- "[\p{L}\p{Nd}]", so any characters in \p{N} but not \p{Nd} must be added
-- manually.
-- NOTE: \p{N} *MUST* be defined according to the same version of Unicode that
-- the sanitizer uses in order to remain in sync. As of September 2024, this is
-- version 11.0.
local N_not_Nd = "\194\178" .. -- U+00B2
"\194\179" .. -- U+00B3
"\194\185" .. -- U+00B9
"\194\188-\194\190" .. -- U+00BC-U+00BE
"\224\167\180-\224\167\185" .. -- U+09F4-U+09F9
"\224\173\178-\224\173\183" .. -- U+0B72-U+0B77
"\224\175\176-\224\175\178" .. -- U+0BF0-U+0BF2
"\224\177\184-\224\177\190" .. -- U+0C78-U+0C7E
"\224\181\152-\224\181\158" .. -- U+0D58-U+0D5E
"\224\181\176-\224\181\184" .. -- U+0D70-U+0D78
"\224\188\170-\224\188\179" .. -- U+0F2A-U+0F33
"\225\141\169-\225\141\188" .. -- U+1369-U+137C
"\225\155\174-\225\155\176" .. -- U+16EE-U+16F0
"\225\159\176-\225\159\185" .. -- U+17F0-U+17F9
"\225\167\154" .. -- U+19DA
"\226\129\176" .. -- U+2070
"\226\129\180-\226\129\185" .. -- U+2074-U+2079
"\226\130\128-\226\130\137" .. -- U+2080-U+2089
"\226\133\144-\226\134\130" .. -- U+2150-U+2182
"\226\134\133-\226\134\137" .. -- U+2185-U+2189
"\226\145\160-\226\146\155" .. -- U+2460-U+249B
"\226\147\170-\226\147\191" .. -- U+24EA-U+24FF
"\226\157\182-\226\158\147" .. -- U+2776-U+2793
"\226\179\189" .. -- U+2CFD
"\227\128\135" .. -- U+3007
"\227\128\161-\227\128\169" .. -- U+3021-U+3029
"\227\128\184-\227\128\186" .. -- U+3038-U+303A
"\227\134\146-\227\134\149" .. -- U+3192-U+3195
"\227\136\160-\227\136\169" .. -- U+3220-U+3229
"\227\137\136-\227\137\143" .. -- U+3248-U+324F
"\227\137\145-\227\137\159" .. -- U+3251-U+325F
"\227\138\128-\227\138\137" .. -- U+3280-U+3289
"\227\138\177-\227\138\191" .. -- U+32B1-U+32BF
"\234\155\166-\234\155\175" .. -- U+A6E6-U+A6EF
"\234\160\176-\234\160\181" .. -- U+A830-U+A835
"\240\144\132\135-\240\144\132\179" .. -- U+10107-U+10133
"\240\144\133\128-\240\144\133\184" .. -- U+10140-U+10178
"\240\144\134\138" .. -- U+1018A
"\240\144\134\139" .. -- U+1018B
"\240\144\139\161-\240\144\139\187" .. -- U+102E1-U+102FB
"\240\144\140\160-\240\144\140\163" .. -- U+10320-U+10323
"\240\144\141\129" .. -- U+10341
"\240\144\141\138" .. -- U+1034A
"\240\144\143\145-\240\144\143\149" .. -- U+103D1-U+103D5
"\240\144\161\152-\240\144\161\159" .. -- U+10858-U+1085F
"\240\144\161\185-\240\144\161\191" .. -- U+10879-U+1087F
"\240\144\162\167-\240\144\162\175" .. -- U+108A7-U+108AF
"\240\144\163\187-\240\144\163\191" .. -- U+108FB-U+108FF
"\240\144\164\150-\240\144\164\155" .. -- U+10916-U+1091B
"\240\144\166\188" .. -- U+109BC
"\240\144\166\189" .. -- U+109BD
"\240\144\167\128-\240\144\167\143" .. -- U+109C0-U+109CF
"\240\144\167\146-\240\144\167\191" .. -- U+109D2-U+109FF
"\240\144\169\128-\240\144\169\136" .. -- U+10A40-U+10A48
"\240\144\169\189" .. -- U+10A7D
"\240\144\169\190" .. -- U+10A7E
"\240\144\170\157-\240\144\170\159" .. -- U+10A9D-U+10A9F
"\240\144\171\171-\240\144\171\175" .. -- U+10AEB-U+10AEF
"\240\144\173\152-\240\144\173\159" .. -- U+10B58-U+10B5F
"\240\144\173\184-\240\144\173\191" .. -- U+10B78-U+10B7F
"\240\144\174\169-\240\144\174\175" .. -- U+10BA9-U+10BAF
"\240\144\179\186-\240\144\179\191" .. -- U+10CFA-U+10CFF
"\240\144\185\160-\240\144\185\190" .. -- U+10E60-U+10E7E
"\240\144\188\157-\240\144\188\166" .. -- U+10F1D-U+10F26
"\240\144\189\145-\240\144\189\148" .. -- U+10F51-U+10F54
"\240\145\129\146-\240\145\129\165" .. -- U+11052-U+11065
"\240\145\135\161-\240\145\135\180" .. -- U+111E1-U+111F4
"\240\145\156\186" .. -- U+1173A
"\240\145\156\187" .. -- U+1173B
"\240\145\163\170-\240\145\163\178" .. -- U+118EA-U+118F2
"\240\145\177\154-\240\145\177\172" .. -- U+11C5A-U+11C6C
"\240\146\144\128-\240\146\145\174" .. -- U+12400-U+1246E
"\240\150\173\155-\240\150\173\161" .. -- U+16B5B-U+16B61
"\240\150\186\128-\240\150\186\150" .. -- U+16E80-U+16E96
"\240\157\139\160-\240\157\139\179" .. -- U+1D2E0-U+1D2F3
"\240\157\141\160-\240\157\141\184" .. -- U+1D360-U+1D378
"\240\158\163\135-\240\158\163\143" .. -- U+1E8C7-U+1E8CF
"\240\158\177\177-\240\158\178\171" .. -- U+1EC71-U+1ECAB
"\240\158\178\173-\240\158\178\175" .. -- U+1ECAD-U+1ECAF
"\240\158\178\177-\240\158\178\180" .. -- U+1ECB1-U+1ECB4
"\240\159\132\128-\240\159\132\140" -- U+1F100-U+1F10C
data.valid_attribute_name = "^[:_%w" .. N_not_Nd .."][:_.%-%w" .. N_not_Nd .. "]*$"
-- Value is the namespace number of the linked page at parameter 0, where 0 is mainspace.
-- If the namespace is the mainspace, it can be overridden by an explicitly specified category (e.g. {{PAGENAME:Category:Foo}} refers to "Category:Foo"). This does not apply to any other namespace (e.g. {{#SPECIAL:Category:Foo}} refers to "Special:Category:Foo").
data.template_link_param_1 = {
["#CATEGORYTREE:"] = 14, -- Category:
["#IFEXIST:"] = 0,
["#INVOKE:"] = 828, -- Module:
["#LST:"] = 0,
["#LSTH:"] = 0,
["#LSTX:"] = 0,
["#SPECIAL:"] = -1, -- Special:
["#SPECIALE:"] = -1, -- Special:
["#TITLEPARTS:"] = 0,
["BASEPAGENAME:"] = 0,
["BASEPAGENAMEE:"] = 0,
["CANONICALURL:"] = 0,
["CANONICALURLE:"] = 0,
["CASCADINGSOURCES:"] = 0,
["FILEPATH:"] = 6, -- File:
["FULLPAGENAME:"] = 0,
["FULLPAGENAMEE:"] = 0,
["FULLURL:"] = 0,
["FULLURLE:"] = 0,
["INT:"] = 8, -- MediaWiki:
["LOCALURL:"] = 0,
["LOCALURLE:"] = 0,
["NAMESPACE:"] = 0,
["NAMESPACEE:"] = 0,
["NAMESPACENUMBER:"] = 0,
["PAGEID:"] = 0,
["PAGENAME:"] = 0,
["PAGENAMEE:"] = 0,
["PAGESINCATEGORY:"] = 14, -- Category:
["PAGESIZE:"] = 0,
["REVISIONDAY:"] = 0,
["REVISIONDAY2:"] = 0,
["REVISIONID:"] = 0,
["REVISIONMONTH:"] = 0,
["REVISIONMONTH1:"] = 0,
["REVISIONTIMESTAMP:"] = 0,
["REVISIONUSER:"] = 0,
["REVISIONYEAR:"] = 0,
["ROOTPAGENAME:"] = 0,
["ROOTPAGENAMEE:"] = 0,
["SUBJECTPAGENAME:"] = 0,
["SUBJECTPAGENAMEE:"] = 0,
["SUBJECTSPACE:"] = 0,
["SUBJECTSPACEE:"] = 0,
["SUBPAGENAME:"] = 0,
["SUBPAGENAMEE:"] = 0,
["TALKPAGENAME:"] = 0,
["TALKPAGENAMEE:"] = 0,
["TALKSPACE:"] = 0,
["TALKSPACEE:"] = 0,
}
-- Value is the namespace number of the linked page at parameter 1.
data.template_link_param_2 = {
["PROTECTIONEXPIRY:"] = 0,
["PROTECTIONLEVEL:"] = 0,
}
return data
t4rorng7wydircsbpm0pxhr9wjhuh7e
Modul:title/getCurrentNamespace
828
9247
25212
2026-08-19T06:30:06Z
Deepturquoise
2456
+ ti enwikt
25212
Scribunto
text/plain
--[==[
Returns the data table for the current namespace from {mw.site.namespaces}. This module may be loaded with {mw.loadData}.]==]
return mw.site.namespaces[mw.title.getCurrentTitle().namespace]
2udpe5a40x351nzks01by6n1mixwd3o
Modul:title/isTitle
828
9248
25213
2026-08-19T06:32:57Z
Deepturquoise
2456
+ ti enwikt
25213
Scribunto
text/plain
local table_get_metamethod_module = "Module:table/getMetamethod"
local error = error
local rawequal = rawequal
local type = type
local function get_metamethod(...)
get_metamethod = require(table_get_metamethod_module)
return get_metamethod(...)
end
local title_eq, title_lt
local function get_title_mm()
local success, eq, lt = get_metamethod(mw.title.getCurrentTitle(), "__eq", "__lt")
if not success then
error("Failed to fetch current title") -- this should never happen
end
title_eq, title_lt, get_title_mm = eq, lt, nil
return eq
end
--[==[
Returns {true} if the input is a title object, or {false} if not.]==]
return function(obj)
if not (obj and type(obj) == "table") then
return false
end
local success, eq, lt = get_metamethod(obj, "__eq", "__lt")
-- There's no foolproof method for checking for a title object, but the
-- __eq and __lt metamethods should always be the same. Also discount titles
-- that only have fragments (returned by mw.title.new() and
-- mw.title.makeTitle() if the input starts with "#"), since they cannot
-- represent a valid page, and are broken in various ways (e.g. attempting
-- to access certain keys results in an error); see [[phab:T240678]].
return success and eq ~= nil and lt ~= nil and
rawequal(eq, (title_eq or get_title_mm())) and
rawequal(lt, title_lt) and
obj.prefixedText ~= ""
end
j1ejjc7c8trmnla3tstyr2or7aay9ft
cukup
0
9249
25224
2026-08-19T07:37:10Z
Deepturquoise
2456
Nyieun kaca anyar =={{id}}== {{-adjektiva-|id}} #[[mahi]]
25224
wikitext
text/x-wiki
=={{id}}==
{{-adjektiva-|id}}
#[[mahi]]
5mlbm6hcblbtg9gia7ems9l5g5lmh5z