Wiksiyonaryo tlwiktionary https://tl.wiktionary.org/wiki/Wiksiyonaryo:Unang_Pahina MediaWiki 1.47.0-wmf.20 case-sensitive Midya Natatangi Usapan Tagagamit Usapang tagagamit Wiksiyonaryo Usapang Wiksiyonaryo Talaksan Usapang talaksan MediaWiki Usapang MediaWiki Padron Usapang padron Tulong Usapang tulong Kategorya Usapang kategorya TimedText TimedText talk Module Module talk Event Event talk Padron:Click 10 2463 178027 159539 2026-09-21T16:51:26Z Yivan000 4078 Pinagsanib ang [[:Padron:Click]] sa [[:Padron:mapipindot na boton]]: [[Padron:Click]] is older; merging to preserve history 178027 wikitext text/x-wiki #REDIRECT [[Padron:mapipindot na boton]] 0t3xw2n2ulvog2etcgndq2e31jn4ysf Padron:policy 10 2465 178028 159566 2026-09-21T16:58:33Z Yivan000 4078 Nilipat ni Yivan000 ang pahinang [[Padron:Policy]] sa [[Padron:policy]] mula sa redirect 159566 wikitext text/x-wiki {| style="border:1px solid #aaa; background-color:#F3F9FF; width:100%; text-align:justify; margin-bottom:0.5em" |- | [[Image:Green check.svg|30px]] |align=center| '''Ang pahinang ito ay isang [[Wiktionary:Patakaran|patakaran]] ng Wiktionary.'''<br>Tinatanggap ito ng nakararaming mga manggagamit ng Wiktionary at ay tinatanggap bilang isang pamantayan na dapat sinusundan ng lahat ng mga manggagamit. Dapat hindi ito binabago nang walang pagkakasundo (''consensus''). Maaaring usapan ang patakarang ito sa pahinang usapan nito. |} 2f1226w333nhpseax4u0l40mvdcc5gh pinagbuhatan 0 3261 178031 9482 2026-09-22T04:45:08Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Pinagbuhatan]] sa [[pinagbuhatan]] 9482 wikitext text/x-wiki "PINAGBUHATAN" salitang may dalawang kahulugan, una ay pinagmula o pinaggalingan at ang ikalawa ay sinampal o sinaktan gamit ang kamay.Halimbawa; 1.) Ang mga salitang Tagalog ay may pinagbuhatan sa salitang Dumagat. 2. ) Pinagbuhatan niya ang kabit niya dahil masyadong nagpapahalata kapag nasa harap ng tunay na asawa niya. etxme0036y8gw3syy62tf88xru2nmq3 Module:parameters 828 30841 178035 171248 2026-09-22T05:00:33Z Yivan000 4078 merge changes 178035 Scribunto text/plain --[==[TODO: * Change certain flag names, as some are misnomers: * Change `allow_holes` to `keep_holes`, because it's not the inverse of `disallow_holes`. * Change `allow_empty` to `keep_empty`, as it causes them to be kept as "" instead of deleted. * Sort out all the internal error calls. Manual error(format()) calls are used when certain parameters shouldn't be dumped, so find a way to avoid that. ]==] local export = {} local collation_module = "Module:collation" local families_module = "Module:families" local functions_module = "Module:fun" local gender_and_number_utilities_module = "Module:gender and number utilities" local labels_module = "Module:labels" local languages_module = "Module:languages" local math_module = "Module:math" local pages_module = "Module:pages" local parameters_finalize_set_module = "Module:parameters/finalizeSet" local parameters_track_module = "Module:parameters/track" local parse_utilities_module = "Module:parse utilities" local references_module = "Module:references" local scribunto_module = "Module:Scribunto" local scripts_module = "Module:scripts" local string_utilities_module = "Module:string utilities" local table_module = "Module:table" local wikimedia_languages_module = "Module:wikimedia languages" local yesno_module = "Module:yesno" local mw = mw local mw_title = mw.title local string = string local table = table local dump = mw.dumpObject local find = string.find local format = string.format local gsub = string.gsub local insert = table.insert local ipairs = ipairs local list_to_text = mw.text.listToText local make_title = mw_title.makeTitle local match = string.match local max = math.max local new_title = mw_title.new local next = next local pairs = pairs local pcall = pcall local require = require local sub = string.sub local tonumber = tonumber local type = type local unpack = unpack or table.unpack -- Lua 5.2 compatibility local current_title_text, current_namespace, sets -- Defined when needed. local namespaces = mw.site.namespaces --[==[ Loaders for functions in other modules, which overwrite themselves with the target function when called. This ensures modules are only loaded when needed, retains the speed/convenience of locally-declared pre-loaded functions, and has no overhead after the first call, since the target functions are called directly in any subsequent calls.]==] local function decode_entities(...) decode_entities = require(string_utilities_module).decode_entities return decode_entities(...) end local function extend(...) extend = require(table_module).extend return extend(...) end local function finalize_set(...) finalize_set = require(parameters_finalize_set_module) return finalize_set(...) end local function get_family_by_code(...) get_family_by_code = require(families_module).getByCode return get_family_by_code(...) end local function get_family_by_name(...) get_family_by_name = require(families_module).getByCanonicalName return get_family_by_name(...) end local function get_language_by_code(...) get_language_by_code = require(languages_module).getByCode return get_language_by_code(...) end local function get_language_by_name(...) get_language_by_name = require(languages_module).getByCanonicalName return get_language_by_name(...) end local function get_script_by_code(...) get_script_by_code = require(scripts_module).getByCode return get_script_by_code(...) end local function get_script_by_name(...) get_script_by_name = require(scripts_module).getByCanonicalName return get_script_by_name(...) end local function get_wm_lang_by_code(...) get_wm_lang_by_code = require(wikimedia_languages_module).getByCode return get_wm_lang_by_code(...) end local function get_wm_lang_by_code_with_fallback(...) get_wm_lang_by_code_with_fallback = require(wikimedia_languages_module).getByCodeWithFallback return get_wm_lang_by_code_with_fallback(...) end local function gsplit(...) gsplit = require(string_utilities_module).gsplit return gsplit(...) end local function is_callable(...) is_callable = require(functions_module).is_callable return is_callable(...) end local function is_integer(...) is_integer = require(math_module).is_integer return is_integer(...) end local function is_internal_title(...) is_internal_title = require(pages_module).is_internal_title return is_internal_title(...) end local function is_positive_integer(...) is_positive_integer = require(math_module).is_positive_integer return is_positive_integer(...) end local function iterate_list(...) iterate_list = require(table_module).iterateList return iterate_list(...) end local function num_keys(...) num_keys = require(table_module).numKeys return num_keys(...) end local function parse_gender_and_number_spec(...) parse_gender_and_number_spec = require(gender_and_number_utilities_module).parse_gender_and_number_spec return parse_gender_and_number_spec(...) end local function parse_references(...) parse_references = require(references_module).parse_references return parse_references(...) end local function pattern_escape(...) pattern_escape = require(string_utilities_module).pattern_escape return pattern_escape(...) end local function php_trim(...) php_trim = require(scribunto_module).php_trim return php_trim(...) end local function scribunto_parameter_key(...) scribunto_parameter_key = require(scribunto_module).scribunto_parameter_key return scribunto_parameter_key(...) end local function sort(...) sort = require(collation_module).sort return sort(...) end local function sorted_pairs(...) sorted_pairs = require(table_module).sortedPairs return sorted_pairs(...) end local function split(...) split = require(string_utilities_module).split return split(...) end local function split_labels_on_comma(...) split_labels_on_comma = require(labels_module).split_labels_on_comma return split_labels_on_comma(...) end local function split_on_comma(...) split_on_comma = require(parse_utilities_module).split_on_comma return split_on_comma(...) end local function tonumber_extended(...) tonumber_extended = require(math_module).tonumber_extended return tonumber_extended(...) end local function track(...) track = require(parameters_track_module) return track(...) end local function yesno(...) yesno = require(yesno_module) return yesno(...) end --[==[ intro: This module is used to standardize template argument processing and checking. A typical workflow is as follows (based on [[Module:translations]]): { ... local parent_args = frame:getParent().args local params = { [1] = {required = true, type = "language", default = "und"}, [2] = true, [3] = {list = true}, ["alt"] = true, ["id"] = true, ["sc"] = {type = "script"}, ["tr"] = true, ["ts"] = true, ["lit"] = true, } local args = require("Module:parameters").process(parent_args, params) -- Do further processing of the parsed arguments in `args`. ... } The `params` table should have the parameter names as the keys, and a (possibly empty) table of parameter tags as the value. An empty table as the value merely states that the parameter exists, but should not receive any special treatment; if desired, empty tables can be replaced with the value `true` as a perforamnce optimization. Possible parameter tags are listed below: ; {required = true} : The parameter is required; an error is shown if it is not present. The template's page itself is an exception; no error is shown there. ; {default =} : Specifies a default input value for the parameter, if it is absent or empty. This will be processed as though it were the input instead, so (for example) {default = "und"} with the type {"language"} will return a language object for [[:Category:Undetermined language|Undetermined language]] if no language code is provided. When used on list parameters, this specifies a default value for the first item in the list only. Note that it is not possible to generate a default that depends on the value of other parameters. If used together with {required = true}, the default applies only to template pages (see the following entry), as a side effect of the fact that "required" parameters aren't actually required on template pages. This can be used to show an example of the template in action when the template page is visited; however, it is preferred to use `template_default` for this purpose, for clarity. ; {template_default =} : Specifies a default input value for absent or empty parameters only on the template demo invocation (the invocation of the template that is displayed when the template page that implements the template is viewed). Template pages are pages in template space that invoke (through {{tl|#invoke:}}) the module that implements the template and calls [[Module:parameters]]. For example, the page [[Template:en-noun]] implements the {{tl|en-noun}} template, which in turn invokes [[Module:en-headword]], and is a template page for [[Module:en-headword]]. When the template page [[Template:en-noun]] is visited, the {{tl|#invoke:}} of the template's module is expanded as if the template were called without arguments, and the output is inserted at that point into the processed page. This output serves as a sort of demo of the template's functionality. `template_default` can be used to supply default values for use only in this demo. Since the template page may also contain other invocations of the same template (e.g. on the template's documentation page, which is typically transcluded into the template page itself), `template_default` does not apply if there are any arguments passed to the template or if the template is invoked on any other page but its own template page (which is checked by comparing the name of the invoking template to the current pagename). Both `template_default` and `default` can be specified for the same parameter. If this is done, `template_default` applies for the argumentless template invocation on the template page, and `default` in all other circumstances As an example, {{tl|cs-IPA}} uses the equivalent of {[1] = {default = "+", template_default = "příklad"}} to supply a default of {"+"} for mainspace and documentation pages (which tells the module to use the value of the {{para|pagename}} parameter, falling back to the actual pagename), but {"příklad"} (which means "example"), on [[Template:cs-IPA]]. ; {alias_of =} : Treat the parameter as an alias of another. When arguments are specified for this parameter, they will automatically be renamed and stored under the alias name. This allows for parameters with multiple alternative names, while still treating them as if they had only one name. The conversion-related properties of an aliased parameter (e.g. `type`, `set`, `convert`, `sublist`) are taken from the aliasee, and the corrresponding properties set on the alias itself are ignored; but other properties on the alias are taken from the alias's spec and not from the aliasee's spec. This means, for example, that if you create an alias of a list parameter, the alias must also specify the `list` property or it is not a list. (In such a case, a value specified for the alias goes into the first item of the aliasee's list. You cannot make a list alias of a non-list parameter; this causes an error to be thrown.) Similarly, if you specify `separate_no_index` on an aliasee but not on the alias, uses of the unindexed aliasee parameter are stored into the `.default` key, but uses of the unindexed alias are stored into the first numbered key of the aliasee's list. Aliases cannot be required, as this prevents the other name or names of the parameter from being used. Parameters that are aliases and required at the same time cause an error to be thrown. ; {allow_empty = true} : If the argument is an empty string value, it is not converted to {nil}, but kept as-is. The use of `allow_empty` is disallowed if a type has been specified, and causes an error to be thrown. ; {no_trim = true} : Spacing characters such as spaces and newlines at the beginning and end of a positional parameter are not removed. (MediaWiki itself automatically trims spaces and newlines at the edge of named parameters.) The use of `no_trim` is disallowed if a type has been specified, and causes an error to be thrown. ; {type =} : Specifies what value type to convert the argument into. The default is to leave it as a text string. Alternatives are: :; {type = "boolean"} :: The value is treated as a boolean value, either true or false. No value, the empty string, and the strings {"0"}, {"no"}, {"n"}, {"false"}, {"f"} and {"off"} are treated as {false}, all other values are considered {true}. :; {type = "number"} :: The value is converted into a number, and throws an error if the value is not parsable as a number. Input values may be signed (`+` or `-`), and may contain decimal points and leading zeroes. If {allow_hex = true}, then hexadecimal values in the form {"0x100"} may optionally be used instead, which otherwise have the same syntax restrictions (including signs, decimal digits, and leading zeroes after {"0x"}). Hexadecimal inputs are not case-sensitive. Lua's special number values (`inf` and `nan`) are not possible inputs. :; {type = "range"} :: The value is interpreted as a hyphen-separated range of two numbers (e.g. {"2-4"} is interpreted as the range from {2} to {4}). A number input without a hyphen is interpreted as a range from that number to itself (e.g. the input {"1"} is interpreted as the range from {1} to {1}). Any optional flags which are available for numbers will also work for ranges. :; {type = "language"} :: The value is interpreted as a full or [[Wiktionary:Languages#Etymology-only languages|etymology-only language]] code language code (or name, if {method = "name"}) and converted into the corresponding object (see [[Module:languages]]). If the code or name is invalid, then an error is thrown. The additional setting {family = true} can be given to allow [[Wiktionary:Language families|language family codes]] to be considered valid and the corresponding object returned. Note that to distinguish an etymology-only language object from a full language object, use {object:hasType("language", "etymology-only")}. :; {type = "full language"} :: The value is interpreted as a full language code (or name, if {method = "name"}) and converted into the corresponding object (see [[Module:languages]]). If the code or name is invalid, then an error is thrown. Etymology-only languages are not allowed. The additional setting {family = true} can be given to allow [[Wiktionary:Language families|language family codes]] to be considered valid and the corresponding object returned. :; {type = "Wikimedia language"} :: The value is interpreted as a code and converted into a Wikimedia language object. If the code is invalid, then an error is thrown. If {fallback = true} is specified, conventional language codes which are different from their Wikimedia equivalent will also be accepted as a fallback. :; {type = "family"} :: The value is interpreted as a language family code (or name, if {method = "name"}) and converted into the corresponding object (see [[Module:families]]). If the code or name is invalid, then an error is thrown. :; {type = "script"} :: The value is interpreted as a script code (or name, if {method = "name"}) and converted into the corresponding object (see [[Module:scripts]]). If the code or name is invalid, then an error is thrown. :; {type = "title"} :: The value is interpreted as a page title and converted into the corresponding object (see the [[mw:Extension:Scribunto/Lua_reference_manual#Title_library|Title library]]). If the page title is invalid, then an error is thrown; by default, external titles (i.e. those on other wikis) are not treated as valid. Options are: ::; {namespace = n} ::: The default namespace, where {n} is a namespace number; this is treated as {0} (the mainspace) if not specified. ::; {allow_external = true} ::: External titles are treated as valid. ::; {prefix = "namespace override"} (default) ::: The default namespace prefix will be prefixed to the value is already prefixed by a namespace prefix. For instance, the input {"Foo"} with namespace {10} returns {"Template:Foo"}, {"Wiktionary:Foo"} returns {"Wiktionary:Foo"}, and {"Template:Foo"} returns {"Template:Foo"}. Interwiki prefixes cannot act as overrides, however: the input {"fr:Foo"} returns {"Template:fr:Foo"}. ::; {prefix = "force"} ::: The default namespace prefix will be prefixed unconditionally, even if the value already appears to be prefixed. This is the way that {{tl|#invoke:}} works when calling modules from the module namespace ({828}): the input {"Foo"} returns {"Module:Foo"}, {"Wiktionary:Foo"} returns {"Module:Wiktionary:Foo"}, and {"Module:Foo"} returns {"Module:Module:Foo"}. ::; {prefix = "full override"} ::: The same as {prefix = "namespace override"}, except that interwiki prefixes can also act as overrides. For instance, {"el:All topics"} with namespace {14} returns {"el:Category:All topics"}. Due to the limitations of MediaWiki, only the first prefix in the value may act as an override, so the namespace cannot be overridden if the first prefix is an interwiki prefix: e.g. {"el:Template:All topics"} with namespace {14} returns {"el:Category:Template:All topics"}. :; {type = "parameter"} :: The value is interpreted as the name of a parameter, and will be normalized using the method that Scribunto uses when constructing a {frame.args} table of arguments. This means that integers will be converted to numbers, but all other arguments will remain as strings (e.g. {"1"} will be normalized to {1}, but {"foo"} and {"1.5"} will remain unchanged). Note that Scribunto also trims parameter names, following the same trimming method that this module applies by default to all parameter types. :: This type is useful when one set of input arguments is used to construct a {params} table for use in a subsequent {export.process()} call with another set of input arguments; for instance, the set of valid parameters for a template might be defined as {{tl|#invoke:[some module]|args=}} in the template, where {args} is a sublist of valid parameters for the template. :; {type = "qualifier"} :: The value is interpreted as a qualifier and converted into the correct format for passing into `format_qualifiers()` in [[Module:qualifier]] (which currently just means converting it to a one-item list). :; {type = "labels"} :: The value is interpreted as a comma-separated list of labels and converted into the correct format for passing into `show_labels()` in [[Module:labels]] (which is currently a list of strings). Splitting is done on commas not followed by whitespace, except that commas inside of double angle brackets do not count even if not followed by whitespace. This type should be used by for normal labels (typically specified using {{para|l}} or {{para|ll}}) and accent qualifiers (typically specified using {{para|a}} and {{para|aa}}). :; {type = "references"} :: The value is interpreted as one or more references, in the format prescribed by `parse_references()` in [[Module:references]], and converted into a list of objects of the form accepted by `format_references()` in the same module. If a syntax error is found in the reference format, an error is thrown. :; {type = "genders"} :: The value is interpreted as one or more comma-separated gender/number specs, in the format prescribed by [[Module:gender and number]]. Inline modifiers (`<q:...>`, `<qq:...>`, `<l:...>`, `<ll:...>` or `<ref:...>`) may be attached to a gender/number spec. :; {type = "form of tags"} :: The value is interpreted as an ampersand-separated list of grammar tags and converted into the correct format for passing as `tags` into `tagged_inflections()` in [[Module:form of]] (which is currently a list of strings). Splitting is always done by ampersands. This type should be used by for inflection qualifiers that act as grammar tags (typically specified using {{para|infl}}). :; {type = function(val) ... end} :: `type` may be set to a function (or callable table), which must take the argument value as its sole argument, and must output one of the other recognized types. This is particularly useful for lists (see below), where certain values need to be interpreted differently to others. ; {list =} : Treat the parameter as a list of values, each having its own parameter name, rather than a single value. The parameters will have a number at the end, except optionally for the first (but see also {require_index = true}). For example, {list = true} on a parameter named "head" will include the parameters {{para|head}} (or {{para|head1}}), {{para|head2}}, {{para|head3}} and so on. If the parameter name is a number, another number doesn't get appended, but the counting simply continues, e.g. for parameter {3} the sequence is {{para|3}}, {{para|4}}, {{para|5}} etc. List parameters are returned as numbered lists, so for a template that is given the parameters `|head=a|head2=b|head3=c`, the processed value of the parameter {"head"} will be { { "a", "b", "c" }}}. : The value for {list =} can also be a string. This tells the module that parameters other than the first should have a different name, which is useful when the first parameter in a list is a number, but the remainder is named. An example would be for genders: {list = "g"} on a parameter named {1} would have parameters {{para|1}}, {{para|g2}}, {{para|g3}} etc. : If the number is not located at the end, it can be specified by putting {"\1"} at the number position. For example, parameters {{para|f1accel}}, {{para|f2accel}}, ... can be captured by using the parameter name {"f\1accel"}, as is done in [[Module:headword/templates]]. ; {set =} : Require that the value of the parameter be one of the specified values (or omitted, if {required = true} isn't given). Two formats are allowed; either a list of possible values can be supplied, or a table can be supplied where the keys are allowed values and the values are either `true` or a string naming a value found elsewhere in the table as a key. In the latter case, the key is an alias and the value is the canonical value, and if the user uses the alias, it will automatically be mapped to the canonical value. In such a case, the canonical value cannot itself be an alias. The use of `set` is disallowed if {type = "boolean"} and causes an error to be thrown. ; {sublist =} : The value of the parameter is a delimiter-separated list of individual raw values. The resulting field in `args` will be a Lua list (i.e. a table with numeric indices) of the converted values. If {sublist = true} is given, the values will be split on commas (possibly with whitespace on one or both sides of the comma, which is ignored). If {sublist = "comma without whitespace"} is given, the values will be split on commas which are not followed by whitespace, and which aren't preceded by an escaping backslash. Otherwise, the value of `sublist` should be either a Lua pattern specifying the delimiter(s) to split on or a function (or callable table) to do the splitting, which is passed two values (the value to split and a function to signal an error) and should return a list of the split values. ; {convert =} : If given, this specifies a function (or callable table) to convert the raw parameter value into the Lua object used during further processing. The function is passed two arguments, the raw parameter value itself and a function used to signal an error during parsing or conversion, and should return one value, the converted parameter. The error-signaling function contains the name and raw value of the parameter embedded into the message it generates, so these do not need to specified in the message passed into it. If `type` is specified in conjunction with `convert`, the processing by `type` happens first. If `sublist` is given in conjunction with `convert`, the raw parameter value will be split appropriately and `convert` called on each resulting item. ; {allow_hex = true} : When used in conjunction with {type = "number"}, allows hexadecimal numbers as inputs, in the format {"0x100"} (which is not case-sensitive). ; {family = true} : When used in conjunction with {type = "language"}, allows [[Wiktionary:Language families|language family codes]] to be returned. To check if a given object refers to a language family, use {object:hasType("family")}. ; {method = "name"} : When used in conjunction with {type = "language"}, {type = "family"} or {type = "script"}, checks for and parses a language, family or script name instead of a code. ; {allow_holes = true} : This is used in conjunction with list-type parameters. By default, the values are tightly packed in the resulting list. This means that if, for example, an entry specified `head=a|head3=c` but not {{para|head2}}, the returned list will be { {"a", "c"}}}, with the values stored at the indices {1} and {2}, not {1} and {3}. If it is desirable to keep the numbering intact, for example if the numbers of several list parameters correlate with each other (like those of {{tl|affix}}), then this tag should be specified. : If {allow_holes = true} is given, there may be {nil} values in between two real values, which makes many of Lua's table processing functions no longer work, like {#} or {ipairs()}. To remedy this, the resulting table will contain an additional named value, `maxindex`, which tells you the highest numeric index that is present in the table. In the example above, the resulting table will now be { { "a", nil, "c", maxindex = 3}}}. That way, you can iterate over the values from {1} to `maxindex`, while skipping {nil} values in between. ; {disallow_holes = true} : This is used in conjunction with list-type parameters. As mentioned above, normally if there is a hole in the source arguments, e.g. `head=a|head3=c` but not {{para|head2}}, it will be removed in the returned list. If {disallow_holes = true} is specified, however, an error is thrown in such a case. This should be used whenever there are multiple list-type parameters that need to line up (e.g. both {{para|head}} and {{para|tr}} are available and {{para|head3}} lines up with {{para|tr3}}), unless {allow_holes = true} is given and you are prepared to handle the holes in the returned lists. ; {disallow_missing = true} : This is similar to {disallow_holes = true}, but an error will not be thrown if an argument is blank, rather than completely missing. This may be used to tolerate intermediate blank numerical parameters, which sometimes occur in list templates. For instance, `head=a|head2=|head3=c` will not throw an error, but `head=a|head3=c` will. ; {require_index = true} : This is used in conjunction with list-type parameters. By default, the first parameter can have its index omitted. For example, a list parameter named `head` can have its first parameter specified as either {{para|head}} or {{para|head1}}. If {require_index = true} is specified, however, only {{para|head1}} is recognized, and {{para|head}} will be treated as an unknown parameter. {{tl|affixusex}} (and variants {{tl|suffixusex}}, {{tl|prefixusex}}) use this, for example, on all list parameters. ; {separate_no_index = true} : This is used to distinguish between {{para|head}} and {{para|head1}} as different parameters. For example, in {{tl|affixusex}}, to distinguish between {{para|sc}} (a script code for all elements in the usex's language) and {{para|sc1}} (the script code of the first element, used when the first element is prefixed with a language code to indicate that it is in a different language). When this is used, the resulting table will contain an additional named value, `default`, which contains the value for the indexless argument. ; {flatten = true} : This is used in conjunction with list-type parameters when `sublist` or a list-generating type such as {"labels"} or {"genders"} is also specified, and causes the resulting list to be flattened. Not currently compatible with {allow_holes = true}. ; {replaced_by =} : Specifies that the parameter is no longer valid, and has been replaced by some other mechanism. If the value of `replaced_by` is a string, it is the name of the new parameter to use instead. Use the `reason` tag to specify the reason why this change has been made, e.g. {reason = "for consistency with the corresponding parameter in other Romance-language headword templates"}. If the value of `replaced_by` is {false}, there is no replacement parameter. In this case, `instead` should be supplied with a description of what to do instead, e.g. {instead = "use an inline modifier on |2= such as <q:...>, <qq:...>, <l:...> or <ll:...>"}. You can also supply a justification in `reason` if you feel it is appropriate or necessary to do so. ; {reason =} : When used in conjunction with `replaced_by`, specifies the reason for the parameter replacement. ; {instead =} : When used in conjunction with {replaced_by = false}, specifies what to do instead of using the removed parameter. ; {demo = true} : This is used as a way to ensure that the parameter is only enabled on the template's own page (and its documentation page), and in the User: namespace; otherwise, it will be treated as an unknown parameter. This should only be used if special settings are required to showcase a template in its documentation (e.g. adjusting the pagename or disabling categorization). In most cases, it should be possible to do this without using demo parameters, but they may be required if a template/documentation page also contains real uses of the same template as well (e.g. {{tl|shortcut}}), as a way to distinguish them. ; {deprecated = true} : This is for tracking the use of deprecated parameters, including any aliases that are being brought out of use. See [[Wiktionary:Tracking]] for more information. ]==] -- Returns true if the current page is a template or module containing the current {{#invoke}}. -- If the include_documentation argument is given, also returns true if the current page is either page's documentation page. local own_page, own_page_or_documentation local function is_own_page(include_documentation) if own_page == nil then if current_namespace == nil then local current_title = mw_title.getCurrentTitle() current_title_text, current_namespace = current_title.prefixedText, current_title.namespace end local frame = current_namespace == 828 and mw.getCurrentFrame() or current_namespace == 10 and mw.getCurrentFrame():getParent() if frame then local frame_title_text = frame:getTitle() own_page = current_title_text == frame_title_text own_page_or_documentation = own_page or current_title_text == frame_title_text .. "/documentation" else own_page, own_page_or_documentation = false, false end end return include_documentation and own_page_or_documentation or own_page end -------------------------------------- Some helper functions ----------------------------- -- Convert a list in `list` to a string, separating the final element from the preceding one(s) by `conjunction`. If -- `dump_vals` is given, pass all values in `list` through mw.dumpObject() (WARNING: this destructively modifies -- `list`). This is similar to serialCommaJoin() in [[Module:table]] when used with the `dontTag = true` option, but -- internally uses mw.text.listToText(). local function concat_list(list, conjunction, dump_vals) if dump_vals then for k, v in pairs(list) do list[k] = dump(v) end end return list_to_text(list, nil, conjunction) end -- A helper function for use with generating error-signaling functions in the presence of raw value conversion. Format a -- message `msg`, including the processed value `processed` if it is different from the raw value `rawval`; otherwise, -- just return `msg`. local function msg_with_processed(msg, rawval, processed) if rawval == processed then return msg end local processed_type = type(processed) return format("%s (processed value %s)", msg, (processed_type == "string" or processed_type == "number") and processed or dump(processed) ) end -- Separate form of tags with ampersand (&). local function split_tags_on_ampersand(tags) return split(tags, "&") end -------------------------------------- Error handling ----------------------------- local function process_error(fmt, ...) local args = {...} for i, val in ipairs(args) do args[i] = dump(val) end if type(fmt) == "table" then -- hacky signal that we're called from internal_process_error(), and not to omit stack frames return error(format(fmt[1], unpack(args))) end return error(format(fmt, unpack(args)), 3) end local function internal_process_error(fmt, ...) process_error({"Internal error in `params` table: " .. fmt}, ...) end -- Check that a parameter or argument is in the form form Scribunto normalizes input argument keys into (e.g. 1 not "1", "foo" not " foo "). Otherwise, it won't be possible to normalize inputs in the expected way. Unless is_argument is set, also check that the name only contains one placeholder at most, and that strings don't resolve to numeric keys once the placeholder has been substituted. local function validate_name(name, desc, extra_name, is_argument) local normalized = scribunto_parameter_key(name) if name and name == normalized then if is_argument or type(name) ~= "string" then return end local placeholder = find(name, "\1", nil, true) if not placeholder then return elseif find(name, "\1", placeholder + 1, true) then error(format( "Internal error: expected %s to only contain one placeholder, but saw %s", extra_name and (desc .. dump(extra_name)) or desc, dump(name) )) end local first_name = gsub(name, "\1", "1") normalized = scribunto_parameter_key(first_name) if first_name == normalized then return end error(format( "Internal error: %s cannot resolve to numeric parameters once any placeholder has been substituted, but %s resolves to %s", extra_name and (desc .. dump(extra_name)) or desc, dump(name), dump(normalized) )) elseif normalized == nil then error(format( "Internal error: expected %s to be of type string or number, but saw %s", extra_name and (desc .. dump(extra_name)) or desc, type(name) )) end error(format( "Internal error: expected %s to be Scribunto-compatible: %s (a %s) should be %s (a %s)", extra_name and (desc .. dump(extra_name)) or desc, dump(name), type(name), dump(normalized), type(normalized) )) end local function validate_alias_options(...) local invalid = { required = true, default = true, template_default = true, allow_holes = true, disallow_holes = true, disallow_missing = true, } function validate_alias_options(param, name, main_param, alias_of) for k in pairs(param) do if invalid[k] then track("bad alias option") -- internal_process_error( -- "parameter %s cannot have the option %s, as it is an alias of parameter %s.", -- name, option, alias_of -- ) end end -- Soon, aliases will inherit options from the main parameter via __index. Track cases where this would happen. if main_param ~= true then for k in pairs(main_param) do if param[k] == nil and not invalid[k] then if k == "list" then -- these need to be changed to list = false to retain current behaviour track("mismatched list alias option") elseif not (k == "type" or k == "set" or k == "sublist") then -- rarely specified on aliases, as they're effectively inherited already track("mismatched alias option") end end end end end validate_alias_options(...) end -- TODO: give ranges instead of long lists, if possible. --[==[ func: export.params_list_error(params, msg) Given a key-value table of raw parameters `params`, display an error message about all the parameters seen in the table. The parameter names are displayed in sorted order. `msg` should be e.g. {"required"} or {"not used by this template"}. This is used internally to display error messages about required or invalid parameters, and can be used for the same purpose by code that processes its own parameters (e.g. if the `return_unknown` flag is specified to `process`). ]==] local function params_list_error(params, msg) local list, n = {}, 0 for name in sorted_pairs(params) do n = n + 1 list[n] = name end error(format( "Parameter%s %s.", format(n == 1 and " %s is" or "s %s are", concat_list(list, " and ", true)), msg ), 3) end export.params_list_error = params_list_error -- Helper function for use with convert_val_error(). Format a list of possible choices using `concat_list` and -- conjunction "or", displaying "either " before the choices if there's more than one. local function format_choice_list(valid) return (#valid > 1 and "either " or "") .. concat_list(valid, " or ") end -- Signal an error for a value `val` that is not of the right type `valid` (which is either a string specifying a type, or -- a list of possible values, in the case where `set` was used). `name` is the name of the parameter and can be a -- function to signal an error (which is assumed to automatically display the parameter's name and value). `seetext` is -- an optional additional explanatory link to display (e.g. [[WT:LOL]], the list of possible languages and codes). local function convert_val_error(val, name, valid, seetext) if is_callable(name) then if type(valid) == "table" then valid = "choice, must be " .. format_choice_list(valid) end name(format("Invalid %s; the value %s is not valid%s", valid, val, seetext and "; see " .. seetext or "")) else if type(valid) == "table" then valid = format_choice_list(valid) else valid = "a valid " .. valid end error(format("Parameter %s must be %s; the value %s is not valid.%s", dump(name), valid, dump(val), seetext and " See " .. seetext .. "." or "")) end end -- Generate the appropriate error-signaling function given parameter value `val` and name `name`. If `name` is already -- a function, it is just returned; otherwise a function is generated and returned that displays the passed-in messaeg -- along with the parameter's name and value. local function make_parse_err(val, name) if is_callable(name) then return name end return function(msg) error(format("%s: parameter %s=%s", msg, name, val)) end end -------------------------------------- Value conversion ----------------------------- -- For a list parameter `name` and corresponding value `list_name` of the `list` field (which should have the same value -- as `name` if `list = true` was given), generate a pattern to match parameters of the list and store the pattern as a -- key in `patterns`, with corresponding value set to `name`. For example, if `list_name` is "tr", the pattern will -- match "tr" as well as "tr1", "tr2", ..., "tr10", "tr11", etc. If the `list_name` contains a \1 in it, the numeric -- portion goes in place of the \1. For example, if `list_name` is "f\1accel", the pattern will match "faccel", -- "f1accel", "f2accel", etc. Any \1 in `name` is removed before storing into `patterns`. local function save_pattern(name, list_name, patterns) name = type(name) == "string" and gsub(name, "\1", "") or name if find(list_name, "\1", nil, true) then patterns["^" .. gsub(pattern_escape(list_name), "\1", "([1-9]%%d*)") .. "$"] = name else patterns["^" .. pattern_escape(list_name) .. "([1-9]%d*)$"] = name list_name = list_name .. "\1" end validate_name(list_name, "the list field of parameter ", name) return patterns end -- A helper function for use with `sublist`. It is an iterator function for use in a for-loop that returns split -- elements of `val` using `sublist` (a Lua split pattern; boolean `true` to split on commas optionally surrounded by -- whitespace; "comma without whitespace" to split only on commas not followed by whitespace which have not been escaped -- by a backslash; or a function to do the splitting, which is passed two values, the value to split and a function to -- signal an error, and should return a list of the split elements). `name` is the parameter name or error-signaling -- function passed into convert_val(). local function split_sublist(val, name, sublist) if sublist == true then return gsplit(val, "%s*,%s*") -- Split an argument on comma, but not comma followed by whitespace. elseif sublist == "comma without whitespace" then -- If difficult cases, use split_on_comma. if find(val, "\\", nil, true) or match(val, ",%s") then return iterate_list(split_on_comma(val)) end -- Otherwise, use gsplit. return gsplit(val, ",") elseif type(sublist) == "string" then return gsplit(val, sublist) elseif not is_callable(sublist) then error(format('Internal error: expected `sublist` to be of type "string" or "function" or boolean `true`, but saw %s', dump(sublist))) end return iterate_list(sublist(val, make_parse_err(val, name))) end -- For parameter named `name` with value `val` and param spec `param`, if the `set` field is specified, verify that the -- value is one of the one specified in `set`, and throw an error otherwise. `name` is taken directly from the -- corresponding parameter passed into convert_val() and may be a function to signal an error. Optional `param_type` is -- a string specifying the conversion type of `val` and is used for special-casing: If `param_type` is "boolean", an -- internal error is thrown (since `set` cannot be used in conjunction with booleans) and if `param_type` is "number", -- no checking happens because in this case `set` contains numbers and is checked inside the number conversion function -- itself, after converting `val` to a number. Return the canonical value of `val` (which may be different from `val` -- if an alias map is given). local function check_set(val, name, param, param_type) if param_type == "boolean" then error(format('Internal error: cannot use `set` with `type = "%s"`', param_type)) -- Needs to be special cased because the check happens after conversion to numbers. elseif param_type == "number" then return val end local set, map = param.set if sets == nil then map = finalize_set(set, name) sets = {[set] = map} else map = sets[set] if map == nil then map = finalize_set(set, name) sets[set] = map end end local newval = map[val] if newval == true then return val elseif newval ~= nil then return newval end local list = {} for k, v in sorted_pairs(map) do if v == true then insert(list, dump(k)) else insert(list, ("%s (alias of %s)"):format(dump(k), dump(v))) end end -- If the parameter is not required then put "or empty" at the end of the list, to avoid implying the parameter is actually required. if not param.required then insert(list, "empty") end convert_val_error(val, name, list) end local function convert_language(val, name, param, allow_etym) local method, func = param.method if method == nil or method == "code" then func, method = get_language_by_code, "code" elseif method == "name" then func, method = get_language_by_name, "name" else error(format('Internal error: expected `method` for type `language` to be "code", "name" or undefined, but saw %s', dump(method))) end local lang = func(val, nil, allow_etym, param.family) if lang then return lang end local list, links = {"language"}, {"[[WT:LOL]]"} if allow_etym then insert(list, "etymology language") insert(links, "[[WT:LOL/E]]") end if param.family then insert(list, "family") insert(links, "[[WT:LOF]]") end convert_val_error(val, name, concat_list(list, " or ") .. " " .. (method == "name" and "name" or "code"), concat_list(links, " and ")) end local function convert_number(val, allow_hex) -- Call tonumber_extended with the `real_finite` flag, which filters out ±infinity and NaN. -- By default, specify base 10, which prevents 0x hex inputs from being converted. -- If `allow_hex` is set, then don't give a base, which means 0x hex inputs will work. local num = tonumber_extended(val, not allow_hex and 10 or nil, "finite_real") if not num then return num end if match(val, "[eEpP.]") then -- float track("number not an integer") end if find(val, "+", nil, true) then track("number with +") end -- Track various unusual number inputs to determine if it should be restricted to positive integers by default (possibly including 0). if not is_positive_integer(num) then track("number not a positive integer") if num == 0 then track("number is 0") elseif not is_integer(num) then track("number not an integer") end end return num end -- TODO: validate parameter specs separately, as it's making the handler code really messy at the moment. local type_handlers = setmetatable({ ["boolean"] = function(val) return yesno(val, true) end, ["family"] = function(val, name, param) local method, func = param.method if method == nil or method == "code" then func, method = get_family_by_code, "code" elseif method == "name" then func, method = get_family_by_name, "name" else error(format('Internal error: expected `method` for type `family` to be "code", "name" or undefined, but saw %s', dump(method))) end return func(val) or convert_val_error(val, name, "family " .. method, "[[WT:LOF]]") end, ["labels"] = function(val, name, param) -- FIXME: Should be able to pass in a parse_err function. return split_labels_on_comma(val) end, ["form of tags"] = function(val, name, param) return split_tags_on_ampersand(val) end, ["language"] = function(val, name, param) return convert_language(val, name, param, true) end, ["full language"] = convert_language, ["number"] = function(val, name, param) local allow_hex = param.allow_hex if allow_hex and allow_hex ~= true then error(format( 'Internal error: expected `allow_hex` for type `number` to be of type "boolean" or undefined, but saw %s', dump(allow_hex) )) end local num = convert_number(val, allow_hex) if param.set then -- Don't pass in "number" here; otherwise no checking will happen. num = check_set(num, name, param) end if num then return num end convert_val_error(val, name, (allow_hex and "decimal or hexadecimal " or "") .. "number") end, ["range"] = function(val, name, param) local allow_hex = param.allow_hex if allow_hex and allow_hex ~= true then error(format( 'Internal error: expected `allow_hex` for type `range` to be of type "boolean" or undefined, but saw %s', dump(allow_hex) )) end -- Pattern ensures leading minus signs are accounted for. local m1, m2 = match(val, "^(%s*%S.-)%-(%s*%S.*)") if m1 then m1 = convert_number(m1, allow_hex) if m1 then m2 = convert_number(m2, allow_hex) if m2 then return {m1, m2} end end end -- Try `val` if it couldn't be split into a range, and return a range of `val` to `val` if possible. local num = convert_number(val, allow_hex) if num then return {num, num} end convert_val_error(val, name, (allow_hex and "decimal or hexadecimal " or "") .. "number or a hyphen-separated range of two numbers") end, ["parameter"] = function(val, name, param) -- Use the `no_trim` option, as any trimming will have already been done. return scribunto_parameter_key(val, true) end, ["qualifier"] = function(val, name, param) return {val} end, ["references"] = function(val, name, param) return parse_references(val, make_parse_err(val, name)) end, ["genders"] = function(val, name, param) if not val:find("[,<]") then return {{spec = val}} end -- NOTE: We don't pass in allow_space_around_comma. Consistent with other comma-separated types, there shouldn't -- be spaces around the comma. return parse_gender_and_number_spec { spec = val, parse_err = make_parse_err(val, name), allow_multiple = true, } end, ["script"] = function(val, name, param) local method, func = param.method if method == nil or method == "code" then func, method = get_script_by_code, "code" elseif method == "name" then func, method = get_script_by_name, "name" else error(format('Internal error: expected `method` for type `script` to be "code", "name" or undefined, but saw %s', dump(method))) end return func(val) or convert_val_error(val, name, "script " .. method, "[[WT:LOS]]") end, ["string"] = function(val, name, param) -- To be removed as unnecessary. track("string") return val end, -- TODO: add support for resolving to unsupported titles. -- TODO: split this into "page name" (i.e. internal) and "link target" (i.e. external as well), which is more intuitive. ["title"] = function(val, name, param) local namespace = param.namespace if namespace == nil then namespace = 0 else local valid_type = type(namespace) ~= "number" and 'of type "number" or undefined' or not namespaces[namespace] and "a valid namespace number" or nil if valid_type then error(format('Internal error: expected `namespace` for type `title` to be %s, but saw %s', valid_type, dump(namespace))) end end -- Decode entities. WARNING: mw.title.makeTitle must be called with `decoded` (as it doesn't decode) and mw.title.new must be called with `val` (as it does decode, so double-decoding needs to be avoided). local decoded, prefix, title = decode_entities(val), param.prefix -- If the input is a fragment, treat the title as the current title with the input fragment. if sub(decoded, 1, 1) == "#" then -- If prefix is "force", only get the current title if it's in the specified namespace. current_title includes the namespace prefix. if current_namespace == nil then local current_title = mw_title.getCurrentTitle() current_title_text, current_namespace = current_title.prefixedText, current_title.namespace end if not (prefix == "force" and namespace ~= current_namespace) then title = new_title(current_title_text .. val) end elseif prefix == "force" then -- Unconditionally add the namespace prefix (mw.title.makeTitle). title = make_title(namespace, decoded) elseif prefix == "full override" then -- The first input prefix will be used as an override (mw.title.new). This can be a namespace or interwiki prefix. title = new_title(val, namespace) elseif prefix == nil or prefix == "namespace override" then -- Only allow namespace prefixes to override. Interwiki prefixes therefore need to be treated as plaintext (e.g. "el:All topics" with namespace 14 returns "el:Category:All topics", but we want "Category:el:All topics" instead; if the former is really needed, then the input ":el:Category:All topics" will work, as the initial colon overrides the namespace). mw.title.new can take namespace names as well as numbers in the second argument, and will throw an error if the input isn't a valid namespace, so this can be used to determine if a prefix is for a namespace, since mw.title.new will return successfully only if there's either no prefix or the prefix is for a valid namespace (in which case we want the override). local success success, title = pcall(new_title, val, match(decoded, "^.-%f[:]") or namespace) -- Otherwise, get the title with mw.title.makeTitle, which unconditionally adds the namespace prefix, but behaves like mw.title.new if the namespace is 0. if not success then title = make_title(namespace, decoded) end else error(format('Internal error: expected `prefix` for type `title` to be "force", "full override", "namespace override" or undefined, but saw %s', dump(prefix))) end local allow_external = param.allow_external if allow_external == true then return title or convert_val_error(val, name, "Wiktionary or external page title") elseif not allow_external then return title and is_internal_title(title) and title or convert_val_error(val, name, "Wiktionary page title") end error(format('Internal error: expected `allow_external` for type `title` to be of type "boolean" or undefined, but saw %s', dump(allow_external))) end, ["Wikimedia language"] = function(val, name, param) local fallback = param.fallback if fallback == true then return get_wm_lang_by_code_with_fallback(val) or convert_val_error(val, name, "Wikimedia language or language code") elseif not fallback then return get_wm_lang_by_code(val) or convert_val_error(val, name, "Wikimedia language code") end error(format('Internal error: expected `fallback` for type `Wikimedia language` to be of type "boolean" or undefined, but saw %s', dump(fallback))) end, }, { -- TODO: decode HTML entities in all input values. Non-trivial to implement, because we need to avoid any downstream functions decoding the output from this module, which would be double-decoding. Note that "title" has this implemented already, and it needs to have both the raw input and the decoded input to avoid double-decoding by me.title.new, so any implementation can't be as simple as decoding in __call then passing the result to the handler. __call = function(self, val, name, param, param_type, default) local val_type = type(val) -- TODO: check this for all possible parameter types. if val_type == param_type then return val elseif val_type ~= "string" then local expected = "string" if default and (param_type == "boolean" or param_type == "number") then expected = param_type .. " or " .. expected end error(format( "Internal error: %sargument %s has the type %s; expected a %s.", default and (default .. " for ") or "", name, dump(val_type), expected )) end local func = self[param_type] if func == nil then error(format("Internal error: %s is not a recognized parameter type.", dump(param_type))) end return func(val, name, param) end }) --[==[ func: export.convert_val(val, name, param) Convert a parameter value according to the associated specs listed in the `params` table passed to [[Module:parameters]]. `val` is the value to convert for a parameter whose name is `name` (used only in error messages). `param` is the spec (the value part of the `params` table for the parameter). In place of passing in the parameter name, `name` can be a function that throws an error, displaying the specified message along with the parameter name and value. This function processes all the conversion-related fields in `param`, including `type`, `set`, `sublist`, `convert`, etc. It returns the converted value. ]==] local function convert_val(val, name, param, default) local param_type = param.type or "string" -- If param.type is a function, resolve it to a recognized type. if is_callable(param_type) then param_type = param_type(val) end local convert, sublist = param.convert, param.sublist -- `val` might not be a string if it's the default value. if sublist and type(val) == "string" then local retlist, set = {}, param.set if convert then local thisindex, thisval, insval, parse_err = 0 if is_callable(name) then -- We assume the passed-in error function in `name` already shows the parameter name and raw value. function parse_err(msg) name(format("%s: item #%s=%s", msg_with_processed(msg, thisval, insval), thisindex, thisval) ) end else function parse_err(msg) error(format("%s: item #%s=%s of parameter %s=%s", msg_with_processed(msg, thisval, insval), thisindex, thisval, name, val) ) end end for v in split_sublist(val, name, sublist) do thisindex, thisval = thisindex + 1, v if set then v = check_set(v, name, param, param_type) end insert(retlist, convert(type_handlers(v, name, param, param_type, default), parse_err)) end else for v in split_sublist(val, name, sublist) do if set then v = check_set(v, name, param, param_type) end insert(retlist, type_handlers(v, name, param, param_type, default)) end end return retlist elseif param.set then val = check_set(val, name, param, param_type) end local retval = type_handlers(val, name, param, param_type, default) if convert then local parse_err if is_callable(name) then -- We assume the passed-in error function in `name` already shows the parameter name and raw value. if retval == val then -- This is an optimization to avoid creating a closure. The second arm works correctly even -- when retval == val. parse_err = name else function parse_err(msg) name(msg_with_processed(msg, val, retval)) end end else function parse_err(msg) error(format("%s: parameter %s=%s", msg_with_processed(msg, val, retval), name, val)) end end retval = convert(retval, parse_err) end -- If `sublist` is set but the input wasn't a string, return `retval` as a one-item list. if sublist then retval = {retval} end return retval end export.convert_val = convert_val -- used by [[Module:parameter utilities]] local function unknown_param(name, val, args_unknown) track("unknown parameters") args_unknown[name] = val return args_unknown end local function check_string_param_modifier(param_type, name, tag) if param_type and not (param_type == "string" or param_type == "parameter" or is_callable(param_type)) then internal_process_error( "%s cannot be set unless %s is set to %s (the default), %s or a function: parameter %s has the type %s.", tag, "type", "string", "parameter", name, param_type ) end end local function hole_error(params, name, listname, this, nxt, extra) -- `process_error` calls `dump` on values to be inserted into -- error messages, but with numeric lists this causes "numeric" -- to look like the name of the list rather than a description, -- as `dump` adds quote marks. Insert it early to avoid this, -- but add another %s specifier in all other cases, so that -- actual list names will be displayed properly. local offset, specifier, starting_from = 0, "%s", "" local msg = "Item %%d in the list of %s parameters must be given if item %%d is given, because %sthere shouldn't be any gaps due to missing%s parameters." local specs = {} if type(listname) == "string" then specs[2] = listname elseif type(name) == "number" then offset = name - 1 -- To get the original parameter. specifier = "numeric" -- If the list doesn't start at parameter 1, avoid implying -- there can't be any gaps in the numeric parameters if -- some parameter with a lower key is optional. for j = name - 1, 1, -1 do local _param = params[j] if not (_param and _param.required) then starting_from = format("(starting from parameter %d) ", dump(j + 1)) break end end else specs[2] = name end specs[1] = this + offset -- Absolute index for this item. insert(specs, nxt + offset) -- Absolute index for the next item. process_error(format(msg, specifier, starting_from, extra or ""), unpack(specs)) end local function check_disallow_holes(params, val, name, listname, extra) for i = 1, val.maxindex do if val[i] == nil then hole_error(params, name, listname, i, num_keys(val)[i], extra) end end end local function handle_holes(params, val, name) local param = params[name] local disallow_holes = param.disallow_holes -- Iterate up the list, and throw an error if a hole is found. if disallow_holes then check_disallow_holes(params, val, name, param.list, " or empty") end -- Iterate up the list, and throw an error if a hole is found due to a -- missing parameter, treating empty parameters as part of the list. This -- applies beyond maxindex if blank arguments are supplied beyond it, so -- isn't mutually exclusive with `disallow_holes`. local empty = val.empty if param.disallow_missing then if empty then -- Remove `empty` from `val`, so it doesn't get returned. val.empty = nil for i = 1, max(val.maxindex, empty.maxindex) do if val[i] == nil and not empty[i] then local keys = extend(num_keys(val), num_keys(empty)) sort(keys) hole_error(params, name, param.list, i, keys[i]) end end -- If there's no table of empty parameters, the check is identical to -- `disallow_holes`, except that the error message only refers to -- missing parameters, not missing or empty ones. If `disallow_holes` is -- also set, there's no point checking again. elseif not disallow_holes then check_disallow_holes(params, val, name, param.list) end end -- If `allow_holes` is set, there's nothing left to do. if param.allow_holes then -- do nothing -- Otherwise, remove any holes: `pairs` won't work, as it's unsorted, and -- iterating from 1 to `maxindex` times out with inputs like |100000000000=, -- so use num_keys to get a list of numerical keys sorted from lowest to -- highest, then iterate up the list, moving each value in `val` to the -- lowest unused positive integer key. This also avoids the need to create a -- new table. If `disallow_holes` is specified, then there can't be any -- holes in the list, so there's no reason to check again; this doesn't -- apply to `disallow_missing`, however. else if not disallow_holes then local keys, i = num_keys(val), 0 while true do i = i + 1 local key = keys[i] if key == nil then break elseif i ~= key then track("holes compressed") val[i], val[key] = val[key], nil end end end -- Some code depends on only numeric params being present when no holes are -- allowed (e.g. by checking for the presence of arguments using next()), so -- remove `maxindex`. val.maxindex = nil end end local function maybe_flatten(params, val, name) local param = params[name] if param.flatten then if param.allow_holes then process_error("For parameter %s, can't set both `allow_holes` and `flatten`", name) end if not param.sublist and param.type ~= "genders" and param.type ~= "labels" and param.type ~= "references" and param.type ~= "qualifier" and param.type ~= "form of tags" then process_error("For parameter %s, can only set `flatten` along with `sublist` or a list-generating type", name) end -- Do the flattening ourselves rather than calling flatten() in [[Module:table]], which will attempt to -- flatten non-list objects like title objects, and cause an error in the process. -- FIXME: We should do this in-place if possible. local newlist = {} for _, sublist in ipairs(val) do for _, item in ipairs(sublist) do insert(newlist, item) end end val = newlist end return val end -- If both `template_default` and `default` are given, `template_default` takes precedence, but only on the template or -- module page. This means a different default can be specified for the template or module page example. However, -- `template_default` doesn't apply if any args are set, which helps (somewhat) with examples on documentation pages -- transcluded into the template page. HACK: We still run into problems on documentation pages transcluded into the -- template page when pagename= is set. Check this on the assumption that pagename= is fairly standard. local function convert_default_val(name, param, pagename_set, any_args_set, add_empty_sublist) if not pagename_set then local val = param.template_default if val ~= nil and not any_args_set and is_own_page() then return convert_val(val, name, param, "template default") end end local val = param.default if val ~= nil then return convert_val(val, name, param, "default") -- Sublist parameters should return an empty table if not given, but only do -- this if the parameter isn't also a list (in which case it will already -- be an empty table). -- FIXME: do this once all modules that pass in a sublist parameter treat an empty sublist identically to a nil argument; some currently do things based on the fact an argument exists at all. -- elseif add_empty_sublist and param.sublist then --return {} end end --[==[ Process arguments with a given list of parameters. Return a table containing the processed arguments. The `args` parameter specifies the arguments to be processed; they are the arguments you might retrieve from {frame:getParent().args} (the template arguments) or in some cases {frame.args} (the invocation arguments). The `params` parameter specifies a list of valid parameters, and consists of a table. If an argument is encountered that is not in the parameter table, an error is thrown. The structure of the `params` table is as described above in the intro comment. '''WARNING:''' The `params` table is destructively modified to save memory. Nonetheless, different keys can share the same value objects in memory without causing problems. The `return_unknown` parameter, if set to {true}, prevents the function from triggering an error when it comes across an argument with a name that it doesn't recognise. Instead, the return value is a pair of values: the first is the processed arguments as usual, while the second contains all the unrecognised arguments that were left unprocessed. This allows you to do multi-stage processing, where the entire set of arguments that a template should accept is not known at once. For example, an inflection-table might do some generic processing on some arguments, but then defer processing of the remainder to the function that handles a specific inflectional type. ]==] function export.process(args, params, return_unknown) -- Process parameters for specific properties local args_new, args_unknown, any_args_set, required, patterns, list_args, index_list, args_placeholders, placeholders_n = {} -- TODO: memoize the processing of each unique `param` value, since it's common for the same value to be used for many parameter names. for name, param in pairs(params) do validate_name(name, "parameter names") if param ~= true then local spec_type = type(param) if type(param) ~= "table" then internal_process_error( "spec for parameter %s must be a table of specs or the value true, but found %s.", name, spec_type ~= "boolean" and spec_type or param ) end -- Populate required table, and make sure aliases aren't set to required. if param.required then if required == nil then required = {} end required[name] = true end local listname, alias_of = param.list, param.alias_of if alias_of then validate_name(alias_of, "the alias_of field of parameter ", name) if alias_of == name then internal_process_error( "parameter %s cannot be an alias of itself.", name ) end local main_param = params[alias_of] -- Check that the alias_of is set to a valid parameter. if not (main_param == true or type(main_param) == "table") then internal_process_error( "parameter %s is an alias of an invalid parameter.", name ) end validate_alias_options(param, name, main_param, alias_of) -- Aliases can't be lists unless the canonical parameter is also a list. if listname and (main_param == true or not main_param.list) then internal_process_error( "list parameter %s is set as an alias of %s, which is not a list parameter.", name, alias_of ) -- Can't be an alias of an alias. elseif main_param ~= true then local main_alias_of = main_param.alias_of if main_alias_of ~= nil then internal_process_error( "alias_of cannot be set to another alias: parameter %s is set as an alias of %s, which is in turn an alias of %s. Set alias_of for %s to %s.", name, alias_of, main_alias_of, name, main_alias_of ) end end end local replaced_by = param.replaced_by if replaced_by then -- replaced_by can be `false`, which is OK validate_name(replaced_by, "the replaced_by field of parameter ", name) if replaced_by == name then internal_process_error( "parameter %s cannot be replaced by itself.", name ) end local main_param = params[replaced_by] -- Check that the replaced_by is set to a valid parameter. if not (main_param == true or type(main_param) == "table") then internal_process_error( "parameter %s is set to be replaced by an invalid parameter.", name ) end -- Can't be a replaced-by of a replaced-by. if main_param ~= true then local main_replaced_by = main_param.replaced_by if main_replaced_by ~= nil then internal_process_error( "replaced_by cannot be set to another replaced-by parameter: parameter %s is set as replaced by %s, which is in turn replaced by %s. Set replaced_by for %s to %s.", name, replaced_by, main_replaced_by, name, main_replaced_by ) end end if param.instead ~= nil then internal_process_error("the `instead` tag can only be given when `replaced_by` is set to `false`.") end elseif replaced_by == false then if param.instead ~= nil and type(param.instead) ~= "string" then internal_process_error( "the `instead` tag must be a string, but saw %s.", param.instead ) end end if replaced_by ~= nil then if param.reason ~= nil and type(param.reason) ~= "string" then internal_process_error( "the `reason` tag must be a string, but saw %s.", param.reason ) end end if listname then if not alias_of then local key = name if type(name) == "string" then key = gsub(name, "\1", "") end local list_arg = {maxindex = 0} args_new[key] = list_arg if list_args == nil then list_args = {} end list_args[key] = list_arg end local list_type = type(listname) if list_type == "string" then -- If the list property is a string, then it represents the name -- to be used as the prefix for list items. This is for use with lists -- where the first item is a numbered parameter and the -- subsequent ones are named, such as 1, pl2, pl3. patterns = save_pattern(name, listname, patterns or {}) elseif listname ~= true then internal_process_error( "list field for parameter %s must be a boolean, string or undefined, but saw a %s.", name, list_type ) elseif type(name) == "number" then if index_list ~= nil then internal_process_error( "only one numeric parameter can be a list, unless the list property is a string." ) end -- If the name is a number, then all indexed parameters from -- this number onwards go in the list. index_list = name else patterns = save_pattern(name, name, patterns or {}) end if find(name, "\1", nil, true) then if args_placeholders then placeholders_n = placeholders_n + 1 args_placeholders[placeholders_n] = name else args_placeholders, placeholders_n = {name}, 1 end end end end end --Process required changes to `params`. if args_placeholders then for i = 1, placeholders_n do local name = args_placeholders[i] params[gsub(name, "\1", "")], params[name] = params[name], nil end end -- Process the arguments for name, val in pairs(args) do any_args_set = true validate_name(name, "argument names", nil, true) -- Guaranteeing that all values are strings avoids issues with type coercion being inconsistent between functions. local val_type = type(val) if val_type ~= "string" then internal_process_error( "argument %s has the type %s; all arguments must be strings.", name, val_type ) end local orig_name, raw_type, index, canonical = name, type(name) if raw_type == "number" then if index_list and name >= index_list then index = name - index_list + 1 name = index_list end elseif patterns then -- Does this argument name match a pattern? for pattern, pname in next, patterns do index = match(name, pattern) -- It matches, so store the parameter name and the -- numeric index extracted from the argument name. if index then index = tonumber(index) name = pname break end end end local param = params[name] -- If the argument is not in the list of parameters, store it in a separate list. if not param then args_unknown = unknown_param(name, val, args_unknown or {}) elseif param == true then canonical = orig_name val = php_trim(val) if val ~= "" then -- If the parameter is duplicated, throw an error. if args_new[name] ~= nil then process_error( "Parameter %s has been entered more than once. This is probably because a parameter alias has been used.", canonical ) end args_new[name] = val end else if param.replaced_by == false then process_error( ("Parameter %%s has been removed and is no longer valid%s.%s"):format( param.reason and ", " .. param.reason or "", param.instead and " Instead, " .. param.instead .. "." or ""), name ) elseif param.replaced_by then process_error( ("Parameter %%s has been replaced by %%s%s."):format( param.reason and ", " .. param.reason or ""), name, param.replaced_by ) end if param.deprecated then track("deprecated parameter", name) end if param.require_index then -- Disallow require_index for numeric parameter names, as this doesn't make sense. if raw_type == "number" then internal_process_error( "cannot set require_index for numeric parameter %s.", name ) -- If a parameter without the trailing index was found, and -- require_index is set on the param, treat it -- as if it isn't recognized. elseif not index then args_unknown = unknown_param(name, val, args_unknown or {}) end end -- Check that separate_no_index is not being used with a numeric parameter. if param.separate_no_index then if raw_type == "number" then internal_process_error( "cannot set separate_no_index for numeric parameter %s.", name ) elseif type(param.alias_of) == "number" then internal_process_error( "cannot set separate_no_index for parameter %s, as it is an alias of numeric parameter %s.", name, param.alias_of ) end end -- If no index was found, use 1 as the default index. -- This makes list parameters like g, g2, g3 put g at index 1. -- If `separate_no_index` is set, then use 0 as the default instead. if not index and param.list then index = param.separate_no_index and 0 or 1 end -- Normalize to the canonical parameter name. If it's a list, but the alias is not, then determine the index. local raw_name = param.alias_of if raw_name then raw_type = type(raw_name) if raw_type == "number" then name = raw_name local main_param = params[raw_name] if main_param ~= true and main_param.list then if not index then index = param.separate_no_index and 0 or 1 end canonical = raw_name + index - 1 else canonical = raw_name end else name = gsub(raw_name, "\1", "") local main_param = params[name] if not index and main_param ~= true and main_param.list then index = param.separate_no_index and 0 or 1 end if not index or index == 0 then canonical = name elseif name == raw_name then canonical = name .. index else canonical = gsub(raw_name, "\1", index) end end else canonical = orig_name end -- Only recognize demo parameters if this is the current template or module's -- page, or its documentation page. if param.demo and not is_own_page("include_documentation") then args_unknown = unknown_param(name, val, args_unknown or {}) end -- Remove leading and trailing whitespace unless no_trim is true. if param.no_trim then check_string_param_modifier(param.type, name, "no_trim") else val = php_trim(val) end -- Empty string is equivalent to nil unless allow_empty is true. if param.allow_empty then check_string_param_modifier(param.type, name, "allow_empty") elseif val == "" then -- If `disallow_missing` is set, keep track of empty parameters -- via the `empty` field in `arg`, which will be used by the -- `disallow_missing` check. This will be deleted before -- returning. if index and param.disallow_missing then local arg = args_new[name] local empty = arg.empty if empty == nil then empty = {maxindex = 0} arg.empty = empty end empty[index] = true if index > empty.maxindex then empty.maxindex = index end end val = nil end -- Allow boolean false. if val ~= nil then -- Convert to proper type if necessary. local main_param = params[raw_name] if main_param ~= true then val = convert_val(val, orig_name, main_param or param) end -- Mark it as no longer required, as it is present. if required then required[name] = nil end -- Store the argument value. if index then local arg = args_new[name] -- If the parameter is duplicated, throw an error. if arg[index] ~= nil then process_error( "Parameter %s has been entered more than once. This is probably because a list parameter has been entered without an index and with index 1 at the same time, or because a parameter alias has been used.", canonical ) end arg[index] = val -- Store the highest index we find. local maxindex = arg.maxindex if index > maxindex then maxindex = index end if arg[0] ~= nil then arg.default, arg[0] = arg[0], nil if maxindex < 1 then maxindex = 1 end end arg.maxindex = maxindex if not params[name].list then args_new[name] = val -- Don't store index 0, as it's a proxy for the default. elseif index > 0 then arg[index] = val end else -- If the parameter is duplicated, throw an error. if args_new[name] ~= nil then process_error( "Parameter %s has been entered more than once. This is probably because a parameter alias has been used.", canonical ) end if not raw_name then args_new[name] = val else local main_param = params[raw_name] if main_param ~= true and main_param.list then local main_arg = args_new[raw_name] main_arg[1] = val -- Store the highest index we find. if main_arg.maxindex < 1 then main_arg.maxindex = 1 end else args_new[raw_name] = val end end end end end end -- Remove holes in any list parameters if needed. This must be handled -- straight after the previous loop, as any instances of `empty` need to be -- converted to nil. if list_args then for name, val in next, list_args do handle_holes(params, val, name) end end -- If the current page is the template which invoked this Lua instance, then ignore the `require` flag, as it -- means we're viewing the template directly. Required parameters sometimes have a `template_default` key set, -- which gets used in such cases as a demo. -- Note: this won't work on other pages in the Template: namespace (including the /documentation subpage), -- or if the #invoke: is on a page in another namespace. local pagename_set = args_new.pagename -- Handle defaults. for name, param in pairs(params) do if param ~= true then local arg_new = args_new[name] if arg_new == nil then args_new[name] = convert_default_val(name, param, pagename_set, any_args_set, true) elseif param.list and arg_new[1] == nil then local default_val = convert_default_val(name, param, pagename_set, any_args_set) if default_val ~= nil then arg_new[1] = default_val if arg_new.maxindex == 0 then arg_new.maxindex = 1 end end end end end -- Flatten nested lists if called for. This must come after setting the default. if list_args then for name, val in next, list_args do args_new[name] = maybe_flatten(params, val, name) end end -- The required table should now be empty. -- If any parameters remain, throw an error, unless we're on the current template or module's page. if required and next(required) ~= nil and not is_own_page() then params_list_error(required, "required") -- Return the arguments table. -- If there are any unknown parameters, throw an error, unless return_unknown is set, in which case return args_unknown as a second return value. elseif return_unknown then return args_new, args_unknown or {} elseif args_unknown and next(args_unknown) ~= nil then params_list_error(args_unknown, "not used by this template") end return args_new end return export c23kzesggrlowmn06oii7zu1bbzht4t Padron:tempn 10 31082 178026 155332 2026-09-21T16:42:26Z Yivan000 4078 wtf is this page, hardcoded lua error?! 178026 wikitext text/x-wiki #REDIRECT [[Template:temp]] fpcs31dezxxqooyf29i9shtdyjaue69 Padron:workgroup ping 10 31097 178024 155360 2026-09-21T16:38:19Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Padron:wgping]] sa [[Padron:workgroup ping]] 155360 wikitext text/x-wiki {{safesubst:<noinclude/>#invoke:workgroup ping|ping}}<noinclude>{{documentation}}</noinclude> ib4h6arkzp1nefke7t2s4fwzq56y45q saligang-batas 0 31615 178036 157118 2026-09-22T08:36:58Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Saliga'ng Batas]] sa [[saligang-batas]] nang walang iniwang redirect 157118 wikitext text/x-wiki <span style="font-variant: small-caps;">Saligan Ng Batas</span> o <b><i>Saliga'ng Batas</i></b> ay isa'ng kasulata'ng pormal na nilikha at pinagtibay bilang batayan ng batas kung saan nasasalig ang bawat pananagutan at karapatan.ang 06f4ir0nuxk1fls4tjwo26b17lfquoe Module:languages/data/3/c 828 32632 178030 175572 2026-09-22T01:30:43Z Yivan000 4078 178030 Scribunto text/plain local m_langdata = require("Module:languages/data") -- Loaded on demand, as it may not be needed (depending on the data). local function u(...) u = require("Module:string utilities").char return u(...) end local c = m_langdata.chars local p = m_langdata.puaChars local s = m_langdata.shared local m = {} m["caa"] = { "Ch'orti'", 35177, "myn", "Latn", } m["cab"] = { "Garifuna", 35490, "awd-taa", "Latn", ancestors = "crb", } m["cac"] = { "Chuj", 35233, "myn", "Latn", } m["cad"] = { "Caddo", 56756, "cdd", "Latn", } m["cae"] = { "Laalaa", 35564, "alv-cng", "Latn", } m["caf"] = { "Southern Carrier", 12953426, "ath-nor", "Latn", } m["cag"] = { "Nivaclé", 3182557, "sai-mtc", "Latn", } m["cah"] = { "Cahuarano", 2933175, "sai-zap", "Latn", } m["caj"] = { "Chané", 56721, "awd", "Latn", } m["cak"] = { "Kaqchikel", 35115, "myn", "Latn", } m["cal"] = { "Carolinian", 28427, "poz-mic", "Latn", } m["cam"] = { "Cèmuhî", 3009690, "poz-cln", "Latn", } m["can"] = { "Chambri", 5069707, "paa-lse", "Latn", } m["cao"] = { "Chácobo", 2591202, "sai-pan", "Latn", } m["cap"] = { "Chipaya", 35235, "sai-ucp", "Latn", } m["caq"] = { "Car Nicobarese", 35156, "aav-nic", "Latn, Deva", } m["car"] = { "Karîña", --TLCHANGE use î since it has a glottal stop after it 56611, "sai-gui", "Latn", sort_key = {remove_diacritics = c.grave .. c.acute .. c.circ .. "`" .. "'%-%s"}, strip_diacritics = { remove_diacritics = c.acute, from = {"â", "ê", "î", "ô", "û", "ŷ"}, to = {"à", "è", "ì", "ò", "ù", "ỳ"} }, english_name = "Kari'na", --TLCHANGE spanish_name = "Kariña", --TLCHANGE } m["cas"] = { "Tsimané", 35950, "qfa-dis", -- isolate or in a putative Putative Mosetan-Chonan family "Latn", } m["cav"] = { "Cavineña", 524102, "sai-tac", "Latn", } m["caw"] = { "Kallawaya", 266417, "qfa-mix", "Latn", } m["cax"] = { "Chiquitano", 1844993, "qfa-iso", -- isolate or Macro-Jê "Latn", } m["cay"] = { "Cayuga", 32967, "iro-nor", "Latn", } m["caz"] = { "Canichana", 2936374, "qfa-dis", -- isolate, unclassified or in a putative Tequiraca-Canichana family "Latn", } m["cbb"] = { "Cabiyarí", 3450660, "awd-nwk", "Latn", } m["cbc"] = { "Carapana", 924405, "sai-tuc", "Latn", } m["cbd"] = { "Carijona", 3446655, "sai-tar", "Latn", } m["cbg"] = { "Chimila", 2963680, "cba", "Latn", } m["cbi"] = { "Chachi", 2591329, "sai-bar", "Latn", } m["cbj"] = { "Ede Cabe", 33112829, "alv-ede", "Latn", } m["cbk"] = { "Chabacano", --"Chavacano", 33281, "crp", "Latn", ancestors = "es", strip_diacritics = {remove_diacritics = c.grave .. c.acute .. c.circ .. c.diaer}, sort_key = { from = {"ch", "ll", "ñ", "r"}, to = {"c" .. p[1], "l" .. p[1], "n" .. p[1], "r" .. p[1]} }, standard_chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnÑñOoPpQqRrSsTtUuVvWwXxYyZz" .. c.punc, is_official_kwf_name = "https://kwfwikaatkultura.ph/chabacano/", --TLCHANGE english_name = "Chavacano", --TLCHANGE } m["cbl"] = { "Bualkhaw Chin", 9229830, "tbq-kuk", "Latn", } m["cbn"] = { "Nyah Kur", 116849, "mkh-mnc", "Thai", ancestors = "omx", sort_key = "Thai-sortkey", } m["cbo"] = { "Izora", 3915454, "nic-jer", "Latn", } m["cbq"] = { "Tsucuba", 62603062, "nic-knj", "Latn", } m["cbr"] = { "Cashibo-Cacataibo", 5359560, "sai-pan", "Latn", } m["cbs"] = { "Cashinahua", 2591230, "sai-pan", "Latn", } m["cbt"] = { "Chayahuita", 1526525, "sai-cah", "Latn", } m["cbu"] = { "Candoshi-Shapra", 642843, "qfa-dis", -- isolate or related to extinct Chirino; Kaufman (2007) puts it in Saparo-Yawan, Jolkesky (2016) as -- Macro-Arawakan "Latn", } m["cbv"] = { "Cacua", 3192052, "sai-nad", "Latn", ancestors = "mbr", } m["cbw"] = { "Kabalianon", --"Kinabalian", 6410324, "phi", "Latn", is_official_kwf_name = "https://kwfwikaatkultura.ph/kabalianon/", --TLCHANGE english_name = "Kinabalian" --TLCHANGE } m["cby"] = { "Carabayo", 3441762, "sai-tyu", "Latn", } m["cca"] = { "Cauca", 5054242, "sai-chc", "Latn", } m["ccc"] = { "Chamicuro", 2155119, "awd", "Latn", } m["ccd"] = { "Cafundó", 3331506, "roa-gap", "Latn", ancestors = "pt", } m["cce"] = { "Chopi", 3437616, "bnt-bso", "Latn", } m["ccg"] = { "Chamba Daka", 33120805, "nic-dak", "Latn", } m["cch"] = { "Atsam", 34794, "nic-kne", "Latn", } m["ccj"] = { "Kasanga", 35542, "alv-nyn", "Latn", } m["ccl"] = { "Cutchi-Swahili", 5196729, "crp", "Latn", ancestors = "sw", } m["ccm"] = { "Malaccan Creole Malay", 12636092, "crp", "Latn", ancestors = "ms", } m["cco"] = { "Comaltepec Chinantec", 2963735, "omq-chi", "Latn", } m["ccp"] = { "Chakma", 32952, "inc-bas", "Cakm, Beng, Latn", ancestors = "inc-obn", translit = { Cakm = "Cakm-translit", --Beng = "Beng-translit", }, } m["ccr"] = { "Cacaopera", 3438338, "nai-min", "Latn", } m["cda"] = { "Choni", 2964447, "sit-tib", } m["cde"] = { "Chenchu", 32981, "dra-tel", "Telu", } m["cdf"] = { "Chiru", 5102016, "tbq-kuk", "Latn, Beng", } m["cdh"] = { "Chambeali", 12953424, "him", "Deva, Takr", translit = { Deva = "hi-translit" }, } m["cdi"] = { "Chodri", 5103788, "inc-bhi", "Gujr", } m["cdj"] = { "Churahi", 12629039, "him", "Deva, Takr", translit = { Deva = "hi-translit" }, } m["cdm"] = { "Chepang", 5091700, "sit-gma", "Deva", } m["cdn"] = { "Chaudangsi", 5088056, "sit-alm", } m["cdo"] = { "Silanganang Min", --TLCHANGE 36455, "zhx-com", "Hants", generate_forms = "zh-generateforms", translit = "zh-translit", sort_key = "Hani-sortkey", english_name = "Eastern Min", --TLCHANGE } m["cdr"] = { "Cinda-Regi-Tiyal", 35596, "nic-kmk", "Latn", } m["cds"] = { "Chadian Sign Language", 10322099, "sgn", "Latn", -- when documented } m["cdy"] = { "Chadong", 926742, "qfa-kms", } m["cdz"] = { "Koda", 6425038, "mun", "Beng", } m["cea"] = { "Lower Chehalis", 6693377, "sal", "Latn", } m["ceb"] = { "Sebwano", --"Cebuano", 33239, "phi", "Latn, Tglg", translit = { Tglg = "ceb-translit" }, override_translit = true, strip_diacritics = { Latn = { remove_diacritics = c.grave .. c.acute .. c.circ } }, sort_key = { Latn = "tl-sortkey", }, standard_chars = { Latn = "AaBbKkDdEeGgHhIiLlMmNnOoPpRrSsTtUuWwYy", c.punc }, is_official_kwf_name = "https://kwfwikaatkultura.ph/sebwano-2/", --TLCHANGE english_name = "Cebuano" --TLCHANGE } m["ceg"] = { "Chamacoco", 3436637, "sai-zam", "Latn", } m["cen"] = { "Cen", 12628777, "nic-plc", "Latn", ancestors = "izr", } m["cet"] = { "Centúúm", 33608, "qfa-iso", -- northeastern Nigeria "Latn", } m["cfa"] = { "Dijim-Bwilim", 3438350, "alv-wjk", "Latn", } m["cfd"] = { "Cara", 35048, "nic-beo", "Latn", } m["cfg"] = { "Como Karim", 35304, "nic-jkn", "Latn", } m["cfm"] = { "Falam Chin", 56815, "tbq-kuk", "Beng, Latn", } m["cga"] = { "Changriwa", 5072105, "paa-yua", "Latn", } m["cgc"] = { "Kagayanën", --"Kagayanen", 6346422, "mno", "Latn", is_official_kwf_name = "https://kwfwikaatkultura.ph/kagayanen/", --TLCHANGE english_name = "Kagayanen" --TLCHANGE } m["cgg"] = { "Rukiga", 3270727, "bnt-nyg", "Latn", } m["cgk"] = { "Chocangaca", 56604, "sit-tib", "Tibt", ancestors = "xct", override_translit = true, -- Tibt translit, display_text, strip_diacritics, sort_key in [[Module:scripts/data]] } m["chb"] = { "Chibcha", 2356431, "cba", "Latn", } m["chc"] = { "Catawba", 5051602, "nai-cat", "Latn", } m["chd"] = { "Highland Oaxaca Chontal", 2964457, "nai-tqn", "Latn", } m["chf"] = { "Chontal Maya", 35175, "myn", "Latn", } m["chg"] = { "Chagatai", 36831, "trk-kar", "Arab, Ougr", ancestors = "zkh", strip_diacritics = { remove_diacritics = c.kashida .. c.fathatan .. c.dammatan .. c.kasratan .. c.fatha .. c.damma .. c.kasra .. c.shadda .. c.sukun .. c.superalef, from = {u(0x0671)}, to = {u(0x0627)} }, translit = { Arab = "chg-translit", Ougr = "Ougr-translit", }, } m["chh"] = { "Chinook", 6693380, "nai-ckn", "Latn", } m["chj"] = { "Ojitlán Chinantec", 5100110, "omq-chi", "Latn", } m["chk"] = { "Chuukese", 33161, "poz-mic", "Latn", } m["chl"] = { "Cahuilla", 56438, "azc-cup", "Latn", strip_diacritics = {remove_diacritics = c.acute .. c.macron}, } -- chm "Mari" is not recognized as a language, but it is a family code m["chn"] = { "Chinook Jargon", 35173, "crp", "Latn, Dupl", ancestors = "chh, nuk", } m["cho"] = { "Choctaw", 32979, "nai-mus", "Latn", sort_key = {remove_diacritics = c.macronbelow .. "-"}, strip_diacritics = {remove_diacritics = c.acute .. c.dotbelow}, } m["chp"] = { "Chipewyan", 27692, "ath-nor", "Latn, Cans", } m["chq"] = { "Quiotepec Chinantec", 5758709, "omq-chi", "Latn", } m["chr"] = { "Tseroki", --TLCHANGE 33388, "iro", "Cher", translit = "Cher-translit", english_name = "Cherokee", --TLCHANGE spanish_name = "Cheroqui", --TLCHANGE } m["cht"] = { "Cholón", 2591243, "qfa-unc", -- poorly attested; possibly in a Hibito-Cholon or Cholonan family "Latn", } m["chw"] = { "Chuabo", 5118412, "bnt-mak", "Latn", } m["chx"] = { "Chantyal", 4926344, "sit-tam", "Deva", } m["chy"] = { "Tseyene", --TLCHANGE 33265, "alg", "Latn", sort_key = {remove_diacritics = c.grave .. c.acute .. c.macron .. c.dotabove .. "-"}, standard_chars = "AaÁáÀàĀāȦȧEeÉéÈèĒēĖėHhKkMmNnOoÓóÒòŌōȮȯPpSsŠšTtVvXx" .. c.punc, --umlaut and circumflex not allowed english_name = "Cheyenne", --TLCHANGE spanish_name = "Cheyene", --TLCHANGE } m["chz"] = { "Ozumacín Chinantec", 5100111, "omq-chi", "Latn", } m["cia"] = { "Cia-Cia", 35284, "poz-mun", "Hang, Latn, Arab", } m["cib"] = { "Ci Gbe", 12952445, "alv-gbe", "Latn", } m["cic"] = { "Tsikasaw", --TLCHANGE 33192, "nai-mus", "Latn", english_name = "Chickasaw", --TLCHANGE } m["cid"] = { "Chimariko", 1294251, "qfa-iso", -- possibly Hokan "Latn", } m["cie"] = { "Cineni", 56243, "cdc-cbm", "Latn", } m["cih"] = { "Chinali", 11855245, "inc", "Deva", ancestors = "sa", } m["cik"] = { "Chitkuli Kinnauri", 15615982, "sit-kin", } m["cim"] = { "Simbriyano", --TLCHANGE 37053, "gmw-hgm", "Latn", ancestors = "bar", sort_key = {remove_diacritics = c.grave .. c.acute .. c.circ .. c.diaer .. c.ringabove .. c.caron}, english_name = "Cimbrian", --TLCHANGE spanish_name = "Cimbriano", --TLCHANGE } m["cin"] = { "Cinta Larga", 5121095, "tup", "Latn", } m["cip"] = { "Chiapanec", 3364475, "omq", "Latn", } m["cir"] = { "Tinrin", 7862281, "poz-cln", "Latn", } m["ciy"] = { "Chaima", 12628867, "sai-ven", "Latn", } m["cja"] = { "Western Cham", 12645578, "cmc", "Latn, Arab, Khmr, Cham", -- Western Cham script is not yet available. Also, Arabic script is missing some glyphs. } m["cje"] = { "Chru", 2967321, "cmc", "Latn", } m["cjh"] = { "Upper Chehalis", 2962074, "sal", "Latn", } m["cji"] = { "Chamalal", 56567, "cau-and", "Cyrl", translit = "cau-nec-translit", override_translit = true, display_text = s["cau-Cyrl-displaytext"], strip_diacritics = s["cau-Cyrl-stripdiacritics"], } m["cjk"] = { "Chokwe", 2422065, "bnt-clu", "Latn", } m["cjm"] = { "Eastern Cham", 2948019, "cmc", "Latn, Cham", } m["cjn"] = { "Chenapian", 5091044, "paa-sep", "Latn", } m["cjo"] = { "Pajonal Ashéninka", 3450481, "awd", "Latn", } m["cjp"] = { "Cabécar", 27878, "cba", "Latn", } m["cjs"] = { "Shor", 34139, "trk-ssb", "Cyrl", } m["cjv"] = { "Chuave", 5115226, "ngf-sim", "Latn", } m["cjy"] = { "Jin", 56479, "zhx", "Hants", ancestors = "ltc", generate_forms = "zh-generateforms", translit = "zh-translit", sort_key = "Hani-sortkey", } m["ckb"] = { "Kurdo Sentral", --TLCHANGE 36811, "ku", "ku-Arab", translit = "ckb-translit", strip_diacritics = {remove_diacritics = c.kasra .. c.sukun}, english_name = "Central Kurdish", --TLCHANGE spanish_name = "Kurdo central", --TLCHANGE } m["ckh"] = { "Chak", 12628870, "sit-luu", "Latn", ancestors = "kdv", } m["ckl"] = { "Cibak", 56279, "cdc-cbm", "Latn", } m["ckn"] = { "Kaang Chin", 6343432, "tbq-kuk", "Latn", } m["cko"] = { "Anufo", 34845, "alv-ctn", "Latn", } m["ckq"] = { "Kajakse", 3440422, "cdc-est", "Latn", } m["ckr"] = { "Kairak", 3503002, "paa-bai", "Latn", } m["cks"] = { "Tayo", 1133089, "crp", "Latn", ancestors = "fr", sort_key = s["roa-oil-sortkey"], } m["ckt"] = { "Chukchi", 33170, "qfa-ckn", "Cyrl, Latn", -- Latn is obsolete strip_diacritics = { from = {"['’]"}, to = {"ʼ"} }, sort_key = { from = {"ё", "ӄ", "ԓ", "ӈ"}, to = {"е" .. p[1], "к" .. p[1], "л" .. p[1], "н" .. p[1]} }, } m["cku"] = { "Koasati", 35162, "nai-mus", "Latn", } m["ckv"] = { "Kavalan", 716627, "map", "Latn", } m["ckx"] = { "Caka", 5018037, "nic-tvc", "Latn", } m["cky"] = { "Cakfem-Mushere", 3441199, "cdc-wst", "Latn", } m["ckz"] = { "Kaqchikel-K'iche' Mixed Language", 5054550, "qfa-mix", "Latn", ancestors = "cak, quc" } m["cla"] = { "Ron", 3440432, "cdc-wst", "Latn", } m["clc"] = { "Chilcotin", 28535, "ath-nor", "Latn", } m["cld"] = { "Chaldean Neo-Aramaic", 33236, "sem-are", "Syrc", strip_diacritics = "Syrc-stripdiacritics", } m["cle"] = { "Lealao Chinantec", 6509365, "omq-chi", "Latn", } m["clh"] = { "Chilisso", 3250629, "inc-koh", "ur-Arab", } m["cli"] = { "Chakali", 35206, "nic-gnw", "Latn", } m["clj"] = { "Laitu Chin", 6474196, "tbq-kuk", } m["clk"] = { "Idu", 56412, "sit-gsi", "Tibt, Deva", override_translit = true, -- Tibt translit, display_text, strip_diacritics, sort_key in [[Module:scripts/data]] } m["cll"] = { "Chala", 35190, "nic-gne", "Latn", } m["clm"] = { "Klallam", 33404, "sal", "Latn", } m["clo"] = { "Lowland Oaxaca Chontal", 2964450, "nai-tqn", "Latn", } m["clt"] = { "Lutuv", 6502107, "tbq-kuk", "Latn", } m["clu"] = { "Kaluyanën", --"Caluyanun", 32964, "phi", "Latn", is_official_kwf_name = "https://kwfwikaatkultura.ph/kaluyanen/", --TLCHANGE english_name = "Caluyanun" --TLCHANGE } m["clw"] = { "Chulym", 33125, "trk-ssb", "Latn, Cyrl", } m["cly"] = { "Eastern Highland Chatino", 12642078, "omq-cha", "Latn", } m["cma"] = { "Mạ", 12953680, "mkh-ban", "Latn", } m["cme"] = { "Cerma", 35074, "nic-gur", "Latn", } m["cmg"] = { "Classical Mongolian", 5128303, "xgn-cen", "Mong, Soyo, Zanb", -- Mong translit, display_text and strip_diacritics in [[Module:scripts/data]] } m["cmi"] = { "Emberá-Chamí", 3052042, "sai-chc", "Latn", } m["cml"] = { "Campalagian", 5027893, "poz-ssw", "Latn", } m["cmm"] = { "Michigamea", 12636809, "sio-msv", "Latn", } m["cmn"] = { "Mandarin", 9192, "zhx-man", "Hants, Latn, Bopo, Brai", wikimedia_codes = "zh", generate_forms = "zh-generateforms", translit = { Hani = "zh-translit", Bopo = "zh-translit", }, sort_key = { Hani = "Hani-sortkey", Latn = { from = { -- Sort terms with tone numbers immediately after equivalent terms with diacritics. "[aeiouv][" .. c.circ .. c.diaer .. "]?[nr]?g?[0-5]", -- Add temporary breaks between syllables. "([aeiouvmn][" .. c.circ .. c.diaer .. "]?[" .. c.macron .. c.acute .. c.caron .. c.grave .. "]?n?ŋ?g?r?)([bpmfdtnlgkhjqxzcsywrv']h?[aeiouvmn ])", p[1] .. "([ngr])$", p[1] .. "([ngr][%s%-'" .. p[1] .. "])", -- Substitute diacritics for syllable-final tone numbers, and add tone 0 where necessary. c.macron, c.acute, c.caron, c.grave, "([1-4])([^%s%p" .. p[1] .. "]+)", "([^0-5])%f[%z%s%p" .. p[1] .. "]", -- Substitute "v" shorthand for "ü" for a temporary placeholder, so that the (very rare) "v" initial is not affected by the later shorthand substitutions. "([^ " .. p[1] .. "])v", -- Remove temporary breaks. p[1], -- Substitute shorthands for full forms, and sort them immediately after equivalent terms. "%S*[csz]" .. c.circ .. "%S*", "%S*[ŋ" .. p[2] .. "]%S*", "ĉ", "ŝ", "ŋ", p[2], "ẑ", -- "ê" comes after "e", "ü" comes after "u" and apostrophes are removed (as their function is replaced by tone numbers). "[" .. c.circ .. c.diaer .. "]", "'", -- Sort numbered tone 5 after tone 0. "5!" }, to = { "%0!", "%1" .. p[1] .. "%2", "%1", "%1", "1", "2", "3", "4", "%2%1", "%10", "%1" .. p[2], "", "%0\"", "%0\"", "ch", "sh", "ng", "ü", "zh", p[1], "", "0!!" } }, }, } m["cmo"] = { "Central Mnong", 33369881, "mkh-ban", "Khmr, Latn", } m["cmr"] = { "Mro Chin", 16889978, "tbq-kuk", } m["cms"] = { "Messapic", 36383, "ine", "Ital, Latn, Polyt", -- Ital translit in [[Module:scripts/data]] -- Polyt translit, display_text, strip_diacritics, sort_key in [[Module:scripts/data]] } m["cmt"] = { "Camtho", 10441336, "crp", "Latn", ancestors = "fly, zu" } m["cna"] = { "Changthang", 12952322, "sit-lab", "Tibt", override_translit = true, -- Tibt translit, display_text, strip_diacritics, sort_key in [[Module:scripts/data]] } m["cnb"] = { "Chinbon Chin", 12952327, "tbq-kuk", "Latn", } m["cnc"] = { "Cốông", 5202780, "tbq-bis", "Latn", } m["cng"] = { "Northern Qiang", 56559, "sit-qia", "Latn", } m["cnh"] = { "Lai", 3250286, "tbq-kuk", "Latn, Mymr", } m["cni"] = { "Asháninka", 3437230, "awd", "Latn", } m["cnk"] = { "Khumi Chin", 56308, "tbq-kuk", "Latn", } m["cnl"] = { "Lalana Chinantec", 12953437, "omq-chi", "Latn", } m["cno"] = { "Con", 3440883, "mkh-pal", } m["cnp"] = { "Northern Pinghua", 84302463, "zhx-pin", "Hants", generate_forms = "zh-generateforms", sort_key = "Hani-sortkey", } m["cns"] = { "Central Asmat", 11732048, "ngf-asm", "Latn", } m["cnt"] = { "Tepetotutla Chinantec", 5100113, "omq-chi", "Latn", } m["cnu"] = { "Chenoua", 33276, "ber", "Latn", } m["cnw"] = { "Ngawn Chin", 6583675, "tbq-kuk", } m["cnx"] = { "Middle Cornish", 12642603, "cel-brs", "Latn", ancestors = "oco", } m["coa"] = { "Cocos Islands Malay", 3441699, "crp", "Latn", ancestors = "ms", } m["cob"] = { "Chicomuceltec", 3307204, "myn", "Latn", } m["coc"] = { "Cocopa", 33044, "nai-yuc", "Latn", } m["cod"] = { "Cocama", 33317, "tup", "Latn", } m["coe"] = { "Koreguaje", 3198924, "sai-tuc", "Latn", } m["cof"] = { "Tsafiki", 2567055, "sai-bar", "Latn", } m["cog"] = { "Chong", 3914630, "mkh-pea", "Thai, Khmr", sort_key = { Thai = "Thai-sortkey" }, } m["coh"] = { "Chichonyi-Chidzihana-Chikauma", 12629011, "bnt-mij", "Latn", } m["coj"] = { "Cochimi", 3915551, "nai-yuc", "Latn", } m["cok"] = { "Santa Teresa Cora", 12641754, "azc", "Latn", } m["col"] = { "Columbia-Wenatchi", 3324744, "sal", "Latn", } m["com"] = { "Comanche", 32972, "azc-num", "Latn", } m["con"] = { "Cofán", 2669254, "qfa-iso", "Latn", } m["coo"] = { "Comox", 13583746, "sal", "Latn", } m["cop"] = { "Coptic", 36155, "egx", "Copt", translit = "Copt-translit", ancestors = "egx-dem", strip_diacritics = {remove_diacritics = c.grave .. c.macron .. c.overline .. c.diaer .. "ˋ"}, sort_key = "Copt-sortkey", } m["coq"] = { "Coquille", 12953452, "ath-pco", "Latn", } m["cot"] = { "Caquinte", 3915557, "awd", "Latn", } m["cou"] = { "Wamey", 36935, "alv-ten", "Latn", } m["cov"] = { "Cao Miao", 2936935, "qfa-tak", } m["cow"] = { "Cowlitz", 3001877, "sal", "Latn", } m["cox"] = { "Nanti", 15342275, "awd", "Latn", } m["coy"] = { "Coyaima", 56450, "sai-car", "Latn", } m["coz"] = { "Chochotec", 2964262, "omq-pop", "Latn", } m["cpa"] = { "Palantla Chinantec", 5100112, "omq-chi", "Latn", } m["cpb"] = { "Ucayali-Yurúa Ashéninka", 3501858, "awd", "Latn", } m["cpc"] = { "Apurucayali Ashéninka", 3327405, "awd", "Latn", } m["cpg"] = { "Cappadocian Greek", 853414, "grk", "Grek, fa-Arab", ancestors = "gkm", translit = { Grek = "el-translit", }, -- Grek display_text, strip_diacritics, sort_key in [[Module:scripts/data]] } m["cpi"] = { "Chinese Pidgin English", 3435078, "crp", "Latn, Hant", ancestors = "en", sort_key = { Hant = "Hani-sortkey" }, } m["cpn"] = { "Cherepon", 35181, "alv-gng", "Latn", } m["cpo"] = { "Kpee", 6435722, "dmn-jje", } m["cps"] = { "Capiznon", 2937525, "phi", "Latn", } m["cpu"] = { "Pichis Ashéninka", 7190661, "awd", "Latn", } m["cpx"] = { "Puxian Min", 56583, "zhx-com", "Hants", generate_forms = "zh-generateforms", sort_key = "Hani-sortkey", } m["cpy"] = { "South Ucayali Ashéninka", 3501868, "awd", "Latn", } m["cqd"] = { "Chuanqiandian Cluster Miao", 121627627, "hmn", "Latn, Plrd", } m["cra"] = { "Chara", 5073694, "omv", "Latn", } m["crb"] = { "Kalinago", 3450735, "awd-taa", "Latn", } m["crc"] = { "Lonwolwol", 3259216, "poz-vnc", "Latn", } m["crd"] = { "Coeur d'Alene", 32915, "sal", "Latn", } m["crf"] = { "Caramanta", 3504195, "sai-chc", "Latn", } m["crg"] = { "Michif", 13315, "qfa-mix", "Latn", ancestors = "cr, fr", } m["crh"] = { "Crimean Tatar", 33357, "trk-kcu", "Latn, Cyrl", dotted_dotless_i = true, sort_key = { Latn = { from = { "[ıi]" .. c.breve, -- Convert ĭ into PUA so that the decomposed form does not get caught by the next step. Also cover decomposed forms with ı and i, as decomposed Ĭ is converted to ı + ̆ due to the dotted dotless I logic). "i", -- Ensure "i" comes after "ı". "â", "ç", "ğ", "ı", p[3], "ñ", "ö", "ş", "ü" }, to = { p[3], "i" .. p[1], "a", "c" .. p[1], "g" .. p[1], "i", "i" .. p[2], "n" .. p[1], "o" .. p[1], "s" .. p[1], "u" .. p[1], } }, Cyrl = { from = {"гъ", "ё", "къ", "нъ", "дж"}, to = {"г" .. p[1], "е" .. p[1], "к" .. p[1], "н" .. p[1], "ч" .. p[1]} }, }, } m["cri"] = { "Sãotomense", 36536, "crp", "Latn", ancestors = "pt", } m["crj"] = { "Southern East Cree", 12953464, "alg", "Latn, Cans", ancestors = "cr", translit = { Cans = "cr-translit" }, } m["crk"] = { "Plains Cree", 56699, "alg", "Latn, Cans", ancestors = "cr", } m["crl"] = { "Northern East Cree", 12642195, "alg", "Latn, Cans", ancestors = "cr", translit = { Cans = "cr-translit" }, } m["crm"] = { "Moose Cree", 3446671, "alg", "Latn, Cans", ancestors = "cr", } m["crn"] = { "Cora", 12953454, "azc", "Latn", } m["cro"] = { "Crow", 1207611, "sio-mor", "Latn", } m["crq"] = { "Iyo'wujwa Chorote", 3540927, "sai-mtc", "Latn", } m["crr"] = { "Carolina Algonquian", 16113723, "alg-eas", "Latn", } m["crs"] = { "Seychellois Creole", 34015, "crp", "Latn", ancestors = "fr", sort_key = s["roa-oil-sortkey"], } m["crt"] = { "Chorote Iyojwa'ja", --TLCHANGE 3504118, "sai-mtc", "Latn", english_name = "Iyojwa'ja Chorote", --TLCHANGE } m["crv"] = { "Chaura", 2605680, "aav-nic", "Latn", } m["crw"] = { "Chrau", 5105629, "mkh-ban", "Latn", } m["crx"] = { "Carrier", 12953431, "ath-nor", "Latn, Cans", } m["cry"] = { "Cori", 35204, "nic-plc", "Latn", } m["crz"] = { "Cruzeño", 2967636, "nai-chu", "Latn", } m["csa"] = { "Chiltepec Chinantec", 12953435, "omq-chi", "Latn", } m["csb"] = { "Kashubian", 33690, "zlw-pom", "Latn", } m["csc"] = { "Catalan Sign Language", 35768, "sgn", "Latn", -- when documented } m["csd"] = { "Chiangmai Sign Language", 5095211, "sgn", } m["cse"] = { "Czech Sign Language", 5201809, "sgn", "Latn", -- when documented } m["csf"] = { "Cuban Sign Language", 5192046, "sgn", "Latn", -- when documented } m["csg"] = { "Chilean Sign Language", 3322112, "sgn", "Latn", -- when documented } m["csh"] = { "Asho Chin", 12627282, "tbq-kuk", "Latn, Mymr", } m["csi"] = { "Coast Miwok", 2981109, "nai-utn", "Latn", } m["csj"] = { "Songlai Chin", 7561280, "tbq-kuk", } m["csk"] = { "Jola-Kasa", 3446622, "alv-jol", "Latn", } m["csl"] = { "Chinese Sign Language", 1094190, "sgn", } m["csm"] = { "Central Sierra Miwok", 2944443, "nai-utn", "Latn", } m["csn"] = { "Colombian Sign Language", 2748229, "sgn", "Latn", -- when documented } m["cso"] = { "Sochiapam Chinantec", 7550388, "omq-chi", "Latn", } m["csp"] = { "Katimugang Pinghua", --TLCHANGE 84302019, "zhx-pin", "Hants", generate_forms = "zh-generateforms", translit = "zh-translit", sort_key = "Hani-sortkey", english_name = "Southern Pinghua", --TLCHANGE } m["csq"] = { "Croatian Sign Language", 3507506, "sgn", } m["csr"] = { "Costa Rican Sign Language", 5174901, "sgn", "Latn", -- when documented } m["css"] = { "Southern Ohlone", 25559664, "nai-utn", "Latn", } m["cst"] = { "Northern Ohlone", 25559666, "nai-utn", "Latn", } m["csv"] = { "Sumtu Chin", 7638087, "tbq-kuk", } m["csw"] = { "Swampy Cree", 56696, "alg", "Latn, Cans", ancestors = "cr", } m["csx"] = { "Cambodian Sign Language", 50934287, "sgn", } m["csy"] = { "Siyin Chin", 7533375, "tbq-kuk", } m["csz"] = { "Coos", 3126783, "nai-coo", "Latn", } m["cta"] = { "Tataltepec Chatino", 7687853, "omq-cha", "Latn", } m["ctc"] = { "Chetco-Tolowa", 12628946, "ath-pco", "Latn", } m["ctd"] = { "Tedim Chin", 56357, "tbq-kuk", "Latn, Pauc", } m["cte"] = { "Tepinapa Chinantec", 12953443, "omq-chi", "Latn", } m["ctg"] = { "Chittagonian", 33173, "inc-bas", "Beng", ancestors = "inc-obn", } m["cth"] = { "Thaiphum Chin", 16912048, "tbq-kuk", } m["ctl"] = { "Tlacoatzintepec Chinantec", 12643657, "omq-chi", "Latn", } m["ctm"] = { "Chitimacha", 1294227, "qfa-iso", -- recently proposed to be in the Totozoquean family "Latn", } m["ctn"] = { "Chhintange", 32994, "sit-kie", "Deva", } m["cto"] = { "Emberá-Catío", 3052039, "sai-chc", "Latn", } m["ctp"] = { "Western Highland Chatino", 32861734, "omq-cha", "Latn", strip_diacritics = {remove_diacritics = "¹²³⁴⁵"}, sort_key = {remove_diacritics = c.acute}, } m["cts"] = { "Bikol Kahilagaang Catanduanes", --TLCHANGE 7130477, "phi", "Latn", english_name = "Northern Catanduanes Bikol", --TLCHANGE } m["ctt"] = { "Wayanad Chetti", 7975850, "dra-mal", "Taml", } m["ctu"] = { "Chol", 35179, "myn", "Latn", } m["ctz"] = { "Zacatepec Chatino", 8063754, "omq-cha", "Latn", } m["cua"] = { "Cua", 3441115, "mkh-ban", "Latn", } m["cub"] = { "Cubeo", 3006705, "sai-tuc", "Latn", } m["cuc"] = { "Usila Chinantec", 7901979, "omq-chi", "Latn", } m["cug"] = { "Cung", 35194, "nic-bbe", "Latn", } m["cuh"] = { "Chuka", 12952344, "bnt-kka", "Latn", } m["cui"] = { "Cuiba", 2980421, "sai-guh", "Latn", } m["cuj"] = { "Mashco Piro", 3446596, "awd", "Latn", } m["cuk"] = { "Kuna", 12953659, "cba", "Latn", } m["cul"] = { "Culina", 2475442, "auf", "Latn", } m["cuo"] = { "Cumanagoto", 5193784, "sai-cpc", "Latn", } m["cup"] = { "Cupeño", 143130, "azc-cup", "Latn", } m["cuq"] = { "Cun", 2475478, "qfa-lic", "Latn", } m["cur"] = { "Chhulung", 5116126, "sit-kie", "Deva", } m["cut"] = { "Teutila Cuicatec", 12953453, "omq-cui", "Latn", } m["cuu"] = { "Tai Ya", 3441122, "qfa-tak", "Latn", } m["cuv"] = { "Cuvok", 3515056, "cdc-cbm", "Latn", } m["cuw"] = { "Chukwa", 12629033, "sit-kic", } m["cux"] = { "Tepeuxila Cuicatec", 20527242, "omq-cui", "Latn", } m["cuy"] = { "Cuitlatec", 2030998, "qfa-iso", "Latn", } m["cvg"] = { "Chug", 47683644, "sit-khc", "Tibt, Latn", -- Tibt translit, display_text, strip_diacritics, sort_key in [[Module:scripts/data]] -- (NOTE: formerly not present, probably an accidental omission) } m["cvn"] = { "Valle Nacional Chinantec", 12953442, "omq-chi", "Latn", } m["cwa"] = { "Kabwa", 6344537, "bnt-lok", "Latn", } m["cwb"] = { "Maindo", 11002891, "bnt-mak", "Latn", ancestors = "chw", } m["cwd"] = { "Woods Cree", 56305, "alg", "Latn, Cans", ancestors = "cr", } m["cwe"] = { "Kwere", 779632, "bnt-ruv", "Latn", } m["cwg"] = { "Chewong", 646718, "mkh-asl", "Latn", } m["cwt"] = { "Kuwaataay", 35699, "alv-jol", "Latn", } m["cya"] = { "Nopala Chatino", 15616302, "omq-cha", "Latn", } m["cyb"] = { "Cayubaba", 3183382, "qfa-iso", "Latn", } m["cyo"] = { "Kuyunon", --"Cuyunon", 33153, "phi", "Latn", is_official_kwf_name = "https://kwfwikaatkultura.ph/kuyunon/", --TLCHANGE english_name = "Cuyunon" --TLCHANGE } m["czh"] = { "Huizhou", 56546, "zhx", "Hants", -- ? ancestors = "ltc", generate_forms = "zh-generateforms", sort_key = "Hani-sortkey", } m["czk"] = { "Knaanic", 56384, "zlw", "Hebr", ancestors = "zlw-ocs", -- Hebr display_text, strip_diacritics, sort_key in [[Module:scripts/data]] } m["czn"] = { "Zenzontepec Chatino", 603106, "omq-cha", "Latn", } m["czo"] = { "Min Sentral", --TLCHANGE 56435, "zhx-inm", "Hants", generate_forms = "zh-generateforms", sort_key = "Hani-sortkey", english_name = "Central Min", --TLCHANGE } m["czt"] = { "Zotung Chin", 8074599, "tbq-kuk", "Latn", } return require("Module:languages").finalizeData(m, "language") f6k7layov7hers9ran4y5nswqzwrphq Padron:RQ:ojp:Man'yōshū 10 33064 178017 162423 2026-09-21T16:30:03Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Padron:RQ:Man'yōshū]] sa [[Padron:RQ:ojp:Man'yōshū]] 162423 wikitext text/x-wiki {{#invoke:quote|call_quote_template |ojp |year = c. 759 |author = |title = [[w:Man'yōshū|Man’yōshū]] |section = {{#if: {{{1|}}}|book {{{1}}}{{#if: {{{2|}}}|, [https://oncoj.orinst.ox.ac.uk/cgi-bin/oncoj.sh?tree=MYS.{{{1}}}.{{{2}}}{{#if: {{{3|}}}|{{{3}}}}} poem {{{2}}}]}} {{#if: {{{4|}}}|{{{4}}}}}{{#if: {{{5|}}}|<nowiki>;</nowiki> {{{5}}}}}}} |propagateparams = translation,t,transliteration,tr,url,ref |allowparams=1,2,3,4,5 }}<noinclude>{{documentation}}[[Category:Old Japanese quotation templates|Man'yōshū]][[Category:Japanese quotation templates|Man'yōshū]]</noinclude> 4mrt25zy2h9i3lfh6tvkzmti0v1p3ig Padron:quote-mailing list/documentation 10 33211 178020 162638 2026-09-21T16:33:06Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Padron:quote-mailing list/doc]] sa [[Padron:quote-mailing list/documentation]] nang walang iniwang redirect 162638 wikitext text/x-wiki {{documentation subpage}} {{uses lua|Module:quote}} This template can be used in a dictionary entry to provide a quotation from an {{w|electronic mailing list}}. These are inherently ephemeral, so it's important to link to a durable archive, ideally {{w|Google Groups}} or [[w:MARC (archive)|MARC]]. While both Usenet newsgroups and mailing lists are archived on Google Groups, they're not the same. If the name of the group contains a <kbd>.</kbd>, like <kbd>alt.folklore.urban</kbd>, it's Usenet; please use {{temp|quote-newsgroup}}. ===Sample templates=== ;Most basic parameters for English quotations <syntaxhighlight lang="wikitext"> #* {{quote-mailing list|1=|date=|author=|title=|list=|url=|text=}} </syntaxhighlight> ;Most basic parameters for non-English quotations <syntaxhighlight lang="wikitext"> #* {{quote-mailing list|1=|date=|author=|title=|list=|url=|text=|t=}} </syntaxhighlight> ;Commonly used parameters <syntaxhighlight lang="wikitext"> #* {{quote-mailing list|1=|author=|authorlink=|email=|title=|list=|url=|date=|accessdate=|text=|t=|tr=}} </syntaxhighlight> ;All available parameters <syntaxhighlight lang="wikitext"> #* {{quote-mailing list|1=|indent=|author=|authorlink=|last=|first=|email=|title=|trans-title=|list=|url=|date=|year=|accessdate=|text=|passage=|lang=|brackets=|t=|translation=|lit=|tr=|transliteration=|subst=}} </syntaxhighlight> ===Examples=== '''Wikitext''': <syntaxhighlight lang="wikitext">{{quote-mailing list|en|author=John Naylor|title=Re: [Steam-Scholars] Hello again and a query|list=steam-scholars|url=https://groups.google.com/forum/#!msg/steam-scholars/bdMTIoChWyQ/pz5TAUpNxcYJ|date=24 September 2010|passage=It is extremely rare that you speak to someone who says "I want to be an ...." This would suggest that for the vast majority of '''steampunks''' their choice of outfit (at least intitially) is less a conscious attempt at portrayal and more of a spontaneous and potentially subconscious growth of an idea.}}</syntaxhighlight> '''Output''': * {{quote-mailing list|en|author=John Naylor|title=Re: [Steam-Scholars] Hello again and a query|list=steam-scholars|url=https://groups.google.com/forum/#!msg/steam-scholars/bdMTIoChWyQ/pz5TAUpNxcYJ|date=24 September 2010|passage=It is extremely rare that you speak to someone who says "I want to be an ...." This would suggest that for the vast majority of '''steampunks''' their choice of outfit (at least intitially) is less a conscious attempt at portrayal and more of a spontaneous and potentially subconscious growth of an idea.}} ===Parameters=== All parameters except {{para|1}} are optional, and may contain inline interwiki or external links as needed. {| class="wikitable" !Parameter !Remarks |- style="vertical-align:top;" | style="text-align:center;" | <code>1</code> | A comma-separated list of language codes indicating the language(s) of the quoted text; for a list of the codes, see [[Wiktionary:List of languages]]. If the language is other than English, the template will indicate this fact by displaying "(in [''language''])" (for one language), or "(in [''language''] and [''language''])" (for two languages), or "(in [''language''], [''language''] ... and [''language''])" (for three or more languages). The entry page will also be added to a category in the form "Category:[''Language''] terms with quotations" for the first listed language (unless <code>termlang</code> is specified, in which case that language is used for the category, or <code>nocat</code> is specified, in which case the page will not be added to any category). The first listed language also determines the font to use and the appropriate transliteration to display, if the text is in a non-Latin script. Use {{para|worklang}} to specify the language(s) that the overall posting is written in: see below. |- style="vertical-align:top;" | style="text-align:center;" | <code>author</code><br />or</br ><code>last</code> and <code>first</code> | The name of the author of the newsgroup post quoted. Use either <code>author</code>, or <code>last</code> and <code>first</code> (for the first name, and middle names or initials), not both. |- style="vertical-align:top;" | style="text-align:center;" | <code>authorlink</code> | The name of an [https://en.wikipedia.org English Wikipedia] article about the author, which will be linked to the name(s) specified using <code>author</code>, or <code>last</code> and <code>first</code>. Do not add the prefix "<kbd>:en:</kbd>" or "<kbd>w:</kbd>". (Alternatively, link each person's name directly, like this: "<kbd><nowiki>author=[[w:Kathleen Taylor (biologist)|Kathleen Taylor]]</nowiki></kbd>" or "<kbd><nowiki>author={{w|Samuel Johnson}}</nowiki></kbd>".) |- style="vertical-align:top;" | style="text-align:center;" | <code>email</code> | The author's e-mail address. |- style="vertical-align:top;" | style="text-align:center;" | <code>title</code> | The title of the newsgroup post, typically the "<kbd>Subject:</kbd>" header. |- style="vertical-align:top;" | style="text-align:center;" | <code>trans-title</code> | If the title of the newsgroup post is not in English, this parameter can be used to provide an English translation of the title. |- style="vertical-align:top;" | style="text-align:center;" | <code>list</code> | The mailing list the post was sent to. If it was sent to multiple mailing lists, indicate the main one. |- style="vertical-align:top;" | style="text-align:center;" | <code>id</code> | The message ID from the "<kbd>Message-ID:</kbd>" header of the post. Do not include the [[w:bracket#Angle brackets|angle brackets]] as these will be inserted by the template. Note that [[w:MARC (archive)|MARC]] obfuscates these; replace, e.g., <kbd>20181231222013.GH6707 () atomide ! com</kbd> with <kbd>20181231222013.GH6707@atomide.com</kbd>. |- style="vertical-align:top;" | style="text-align:center;" | <code>url</code> | The [[w:Universal Resource Locator|URL]] or web address of the archived message=, for example, on {{w|Google Groups}} or [[w:MARC (archive)|MARC]]. |- style="vertical-align:top;" | style="text-align:center;" | <code>accessdate</code> | The date when the URL was accessed. |- style="vertical-align:top;" | style="text-align:center;" | <code>date</code><br />or<br /><code>year</code> | The date or year that the message was posted. Use either <code>date</code>, or <code>year</code>, not both. |- style="vertical-align:top;" | style="text-align:center;" | <code>text</code> or <code>passage</code> | The portion of the message being quoted. Highlight the term defined in bold in the quoted text like this: "<kbd><nowiki>'''cyberspace'''</nowiki></kbd>". |- style="vertical-align:top;" | style="text-align:center;" | <code>worklang</code> | A comma-separated list of language codes indicating the language(s) that the overall posting is written in, if different from the quoted text; for a list of the codes, see [[Wiktionary:List of languages]]. |- style="vertical-align:top;" | style="text-align:center;" | <code>termlang</code> | A language code indicating the language of the term being illustrated, if different from the quoted text; for a list of the codes, see [[Wiktionary:List of languages]]. If specified, this language is the one used when adding the page to a category of the form "Category:[''Language''] terms with quotations"; otherwise, the first listed language specified using <code>1</code> is used. Only specify this parameter if the language of the quotation is different from the term's language, e.g. a Middle English quotation used to illustrate a modern English term or an English definition of a Vietnamese term in a Vietnamese-English dictionary. |- style="vertical-align:top;" | style="text-align:center;" | <code>nocat</code> | Use <kbd>nocat=y</kbd> or <kbd>nocat=1</kbd> or <kbd>nocat=on</kbd> to suppress adding the page to a category of the form "Category:[''Language''] terms with quotations". This should not normally be done. |- style="vertical-align:top;" | style="text-align:center;" | <code>brackets</code> | Use "<kbd>brackets=on</kbd>" to surround a quotation with [[bracket]]s. This indicates that the quotation either contains a mere mention of a term (for example, "some people find the word '''''manoeuvre''''' hard to spell") rather than an actual use of it (for example, "we need to '''manoeuvre''' carefully to avoid causing upset"), or does not provide an actual instance of a term but provides information about related terms. |- style="vertical-align:top;" | style="text-align:center;" | <code>t</code> or <code>translation</code> | If the quoted text is not in English, this parameter can be used to provide an English [[translation]] of it. |- style="vertical-align:top;" | style="text-align:center;" | <code>lit</code> | If the quoted text is not in English and the translation supplied using <code>t</code> or <code>translation</code> is idiomatic, this parameter can be used to provide a [[literal]] English [[translation]]. |- style="vertical-align:top;" | style="text-align:center;" | <code>footer</code> | This parameter can be used to specify arbitrary text to insert in a separate line at the bottom, to specify a comment, footnote, etc. |- style="vertical-align:top;" | style="text-align:center;" | <code>tr</code> or <code>transliteration</code> | If the quoted text uses a different {{w|writing system}} from the {{w|Latin alphabet}} (the usual alphabet used in English), this parameter can be used to provide a [[transliteration]] of it into the Latin alphabet. Note that many languages provide an automatic transliteration if this argument is not specified. |- style="vertical-align:top;" | style="text-align:center;" | <code>subst</code> | Phonetic substitutions to be applied to handle irregular transliterations in certain languages with a non-Latin writing system and automatic transliteration (e.g. Russian and Yiddish). If specified, should be one or more substitution expressions separated by commas, where each substitution expression is of the form <code>FROM//TO</code> (<code>FROM/TO</code> is also accepted), where <code>FROM</code> specifies the source text in the source script (e.g. Cyrillic or Hebrew) and <code>TO</code> is the corresponding replacement text, also in the source script. The intent is to respell irregularly-pronounced words phonetically prior to transliteration, so that the transliteration reflects the pronunciation rather than the spelling. The substitutions are applied in order. Note that Lua patterns can be used in <code>FROM</code> and <code>TO</code> in lieu of literal text; see [[WT:LUA]]. See also {{temp|ux}} for an example of using <code>subst</code> (the usage is identical to that template). |- style="vertical-align:top;" | style="text-align:center;" | <code>indent</code> | Instead of using wikitext outside the quotation template to indent it (for example, "<kbd><nowiki>#* {{quote-mailing list|...</nowiki></kbd>"), you can use this parameter to specify the indent inside the template (for example, "<kbd><nowiki>{{quote-mailing list|indent=#*|...</nowiki></kbd>") |} ==See also== * <code><nowiki>{{</nowiki>[[w:Template:Cite mailing list|cite mailing list]]<nowiki>}}</nowiki></code> – the English Wikipedia template that this template was originally based on {{citation templates}} <includeonly> [[Category:Citation templates]] </includeonly> bbdm3lhhm2ofcqy6fu5grko9c6bd7kv Padron:quote-newsgroup/documentation 10 33217 178019 162645 2026-09-21T16:32:31Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Padron:quote-newsgroup/doc]] sa [[Padron:quote-newsgroup/documentation]] nang walang iniwang redirect 162645 wikitext text/x-wiki {{documentation subpage}} {{uses lua|Module:quote}} This template can be used in a dictionary entry to provide a quotation from a {{w|Usenet}} [[w:Usenet newsgroup|newsgroup]]. To create a citation in a "References" section or on a discussion page, use {{temp|cite-newsgroup}}. ===Sample templates=== ;Most basic parameters for English quotations <syntaxhighlight lang="wikitext"> #* {{quote-newsgroup|1=|date=|author=|title=|newsgroup=|url=|text=}} </syntaxhighlight> ;Most basic parameters for non-English quotations <syntaxhighlight lang="wikitext"> #* {{quote-newsgroup|1=|date=|author=|title=|newsgroup=|url=|text=|t=}} </syntaxhighlight> ;Commonly used parameters <syntaxhighlight lang="wikitext"> #* {{quote-newsgroup|1=|author=|authorlink=|email=|title=|newsgroup=|id=|url=|date=|accessdate=|text=|t=|tr=}} </syntaxhighlight> ;All available parameters <syntaxhighlight lang="wikitext"> #* {{quote-newsgroup|1=|indent=|author=|authorlink=|last=|first=|email=|title=|trans-title=|newsgroup=|id=|url=|date=|year=|accessdate=|text=|passage=|lang=|brackets=|t=|translation=|lit=|tr=|transliteration=|subst=}} </syntaxhighlight> ===Examples=== <syntaxhighlight lang="wikitext">{{quote-newsgroup|en|author=Peter da Silva|title=Re:Microsoft versus Digital Equipment Corporation|newsgroup=alt.folklore.computers|id=g0hq1u$2hkn$3@monolith.in.taronga.com|url=http://groups.google.com/group/alt.folklore.computers/msg/032c30495567b213|date=16 March 2008|text={{...}} otherwise the pager needs to start doing a bunch of unnecessary '''yak shaving'''.}}</syntaxhighlight> produces this: :{{quote-newsgroup|en|author=Peter da Silva|title=Re:Microsoft versus Digital Equipment Corporation|newsgroup=alt.folklore.computers|id=g0hq1u$2hkn$3@monolith.in.taronga.com|url=http://groups.google.com/group/alt.folklore.computers/msg/032c30495567b213|date=16 March 2008|text={{...}} otherwise the pager needs to start doing a bunch of unnecessary '''yak shaving'''.}} ===Parameters=== All parameters are optional, and may contain inline interwiki or external links as needed. {| class="wikitable" !Parameter !Remarks |- style="vertical-align:top;" | style="text-align:center;" | <code>1</code> | A comma-separated list of language codes indicating the language(s) of the quoted text; for a list of the codes, see [[Wiktionary:List of languages]]. If the language is other than English, the template will indicate this fact by displaying "(in [''language''])" (for one language), or "(in [''language''] and [''language''])" (for two languages), or "(in [''language''], [''language''] ... and [''language''])" (for three or more languages). The entry page will also be added to a category in the form "Category:[''Language''] terms with quotations" for the first listed language (unless <code>termlang</code> is specified, in which case that language is used for the category, or <code>nocat</code> is specified, in which case the page will not be added to any category). The first listed language also determines the font to use and the appropriate transliteration to display, if the text is in a non-Latin script. Use {{para|worklang}} to specify the language(s) that the overall posting is written in: see below. |- style="vertical-align:top;" | style="text-align:center;" | <code>author</code><br />or</br ><code>last</code> and <code>first</code> | The name of the author of the newsgroup post quoted. Use either <code>author</code>, or <code>last</code> and <code>first</code> (for the first name, and middle names or initials), not both. |- style="vertical-align:top;" | style="text-align:center;" | <code>authorlink</code> | The name of an [https://en.wikipedia.org English Wikipedia] article about the author, which will be linked to the name(s) specified using <code>author</code>, or <code>last</code> and <code>first</code>. Do not add the prefix "<kbd>:en:</kbd>" or "<kbd>w:</kbd>". (Alternatively, link each person's name directly, like this: "<kbd><nowiki>author=[[w:Kathleen Taylor (biologist)|Kathleen Taylor]]</nowiki></kbd>" or "<kbd><nowiki>author={{w|Samuel Johnson}}</nowiki></kbd>".) |- style="vertical-align:top;" | style="text-align:center;" | <code>email</code> | The author's e-mail address. |- style="vertical-align:top;" | style="text-align:center;" | <code>title</code> | The title of the newsgroup post, typically the "<kbd>Subject:</kbd>" header. |- style="vertical-align:top;" | style="text-align:center;" | <code>trans-title</code> | If the title of the newsgroup post is not in English, this parameter can be used to provide an English translation of the title. |- style="vertical-align:top;" | style="text-align:center;" | <code>newsgroup</code> | The newsgroup the post was posted to. If it was posted to multiple newsgroups, indicate the main one. |- style="vertical-align:top;" | style="text-align:center;" | <code>id</code> | The message ID from the "<kbd>Message-ID:</kbd>" header of the post. Do not include the [[w:bracket#Angle brackets|angle brackets]] as these will be inserted by the template. |- style="vertical-align:top;" | style="text-align:center;" | <code>url</code> | The [[w:Universal Resource Locator|URL]] or web address of the newsgroup post, for example, on {{w|Google Groups}}. |- style="vertical-align:top;" | style="text-align:center;" | <code>accessdate</code> | The date when the URL was accessed. |- style="vertical-align:top;" | style="text-align:center;" | <code>date</code><br />or<br /><code>year</code> | The date or year that the newsgroup post was posted. Use either <code>date</code>, or <code>year</code>, not both. |- style="vertical-align:top;" | style="text-align:center;" | <code>text</code> or <code>passage</code> | The portion of the newsgroup post being quoted. Highlight the term defined in bold in the quoted text like this: "<kbd><nowiki>'''cyberspace'''</nowiki></kbd>". |- style="vertical-align:top;" | style="text-align:center;" | <code>worklang</code> | A comma-separated list of language codes indicating the language(s) that the overall posting is written in, if different from the quoted text; for a list of the codes, see [[Wiktionary:List of languages]]. |- style="vertical-align:top;" | style="text-align:center;" | <code>termlang</code> | A language code indicating the language of the term being illustrated, if different from the quoted text; for a list of the codes, see [[Wiktionary:List of languages]]. If specified, this language is the one used when adding the page to a category of the form "Category:[''Language''] terms with quotations"; otherwise, the first listed language specified using <code>1</code> is used. Only specify this parameter if the language of the quotation is different from the term's language, e.g. a Middle English quotation used to illustrate a modern English term or an English definition of a Vietnamese term in a Vietnamese-English dictionary. |- style="vertical-align:top;" | style="text-align:center;" | <code>nocat</code> | Use <kbd>nocat=y</kbd> or <kbd>nocat=1</kbd> or <kbd>nocat=on</kbd> to suppress adding the page to a category of the form "Category:[''Language''] terms with quotations". This should not normally be done. |- style="vertical-align:top;" | style="text-align:center;" | <code>brackets</code> | Use "<kbd>brackets=on</kbd>" to surround a quotation with [[bracket]]s. This indicates that the quotation either contains a mere mention of a term (for example, "some people find the word '''''manoeuvre''''' hard to spell") rather than an actual use of it (for example, "we need to '''manoeuvre''' carefully to avoid causing upset"), or does not provide an actual instance of a term but provides information about related terms. |- style="vertical-align:top;" | style="text-align:center;" | <code>t</code> or <code>translation</code> | If the quoted text is not in English, this parameter can be used to provide an English [[translation]] of it. |- style="vertical-align:top;" | style="text-align:center;" | <code>lit</code> | If the quoted text is not in English and the translation supplied using <code>t</code> or <code>translation</code> is idiomatic, this parameter can be used to provide a [[literal]] English [[translation]]. |- style="vertical-align:top;" | style="text-align:center;" | <code>footer</code> | This parameter can be used to specify arbitrary text to insert in a separate line at the bottom, to specify a comment, footnote, etc. |- style="vertical-align:top;" | style="text-align:center;" | <code>tr</code> or <code>transliteration</code> | If the quoted text uses a different {{w|writing system}} from the {{w|Latin alphabet}} (the usual alphabet used in English), this parameter can be used to provide a [[transliteration]] of it into the Latin alphabet. Note that many languages provide an automatic transliteration if this argument is not specified. |- style="vertical-align:top;" | style="text-align:center;" | <code>subst</code> | Phonetic substitutions to be applied to handle irregular transliterations in certain languages with a non-Latin writing system and automatic transliteration (e.g. Russian and Yiddish). If specified, should be one or more substitution expressions separated by commas, where each substitution expression is of the form <code>FROM//TO</code> (<code>FROM/TO</code> is also accepted), where <code>FROM</code> specifies the source text in the source script (e.g. Cyrillic or Hebrew) and <code>TO</code> is the corresponding replacement text, also in the source script. The intent is to respell irregularly-pronounced words phonetically prior to transliteration, so that the transliteration reflects the pronunciation rather than the spelling. The substitutions are applied in order. Note that Lua patterns can be used in <code>FROM</code> and <code>TO</code> in lieu of literal text; see [[WT:LUA]]. See also {{temp|ux}} for an example of using <code>subst</code> (the usage is identical to that template). |- style="vertical-align:top;" | style="text-align:center;" | <code>indent</code> | Instead of using wikitext outside the quotation template to indent it (for example, "<kbd><nowiki>#* {{quote-newsgroup|...</nowiki></kbd>"), you can use this parameter to specify the indent inside the template (for example, "<kbd><nowiki>{{quote-newsgroup|indent=#*|...</nowiki></kbd>") |} ==TemplateData== {{TemplateData header}} <templatedata> { "description": "This template can be used in a dictionary entry to provide a quotation from a Usenet newsgroup.", "params": { "1": { "label": "Language", "description": "A comma-separated list of language codes indicating the language(s) of the quoted text.", "example": "en", "type": "string", "required": true, "suggested": true }, "url": { "label": "Page URL", "description": "The URL of the newsgroup post, for example, on Google Groups.", "type": "url", "required": false, "example": "http://groups.google.com/group/alt.folklore.computers/msg/032c30495567b213" }, "title": { "label": "Post title", "description": "The title of the newsgroup post, typically the \"Subject\" header.", "type": "string", "aliases": [], "example": "Re:Microsoft versus Digital Equipment", "required": false, "suggested": true }, "date": { "label": "Publication date", "description": "The date or year that the newsgroup post was posted.", "type": "string", "example": "16 March 2008", "required": false, "suggested": true }, "newsgroup": { "label": "Newsgroup", "description": "The newsgroup the post was posted to. If it was posted to multiple newsgroups, indicate the main one.", "type": "string", "example": "alt.folklore.computers", "required": true }, "id": { "label": "Post message ID", "description": "The message ID from the \"Message-ID:\" header of the post. Do not include angle brackets.", "type": "string", "example": "g0hq1u$2hkn$3@monolith.in.taronga.com", "required": false }, "accessdate": { "label": "Access date", "description": "The date when the URL was accessed.", "type": "string", "required": false }, "author": { "label": "Post author", "description": "The name of the author of the newsgroup post quoted.", "type": "string", "example": "Peter da Silva", "required": false }, "email": { "label": "Author's email", "description": "The author's e-mail address.", "type": "string", "example": "peterdasilva@example.com", "required": false }, "passage": { "label": "Quoted text", "description": "The portion of the newsgroup post being quoted. Highlight the term defined in bold.", "aliases": ["text"], "type": "content", "example": "{{...}} otherwise the pager needs to start doing a bunch of unnecessary '''yak shaving'''.", "required": true }, "translation": { "label": "Translation", "description": "If the quoted text is not in English, this parameter can be used to provide an English translation of it.", "aliases": ["t"], "type": "string", "required": false } }, "maps": { "citoid": { } }, "paramOrder": [ "1", "author", "email", "title", "id", "newsgroup", "date", "url", "accessdate", "passage", "translation" ], "format": "inline" } </templatedata> ==See also== * {{temp|cite-newsgroup}} – for citations in "References" sections and discussion pages * <code><nowiki>{{</nowiki>[[w:Template:Cite newsgroup|cite newsgroup]]<nowiki>}}</nowiki></code> – the English Wikipedia template that this template was originally based on {{citation templates}} <includeonly> [[Category:Citation templates]] </includeonly> j8b0n4o3m05nhe1yoq18l7yrp5emcxe Module:headword utilities 828 33386 178034 172555 2026-09-22T04:57:16Z Yivan000 4078 merge changes 178034 Scribunto text/plain local export = {} local require_when_needed = require("Module:utilities/require when needed") local affix_module = "Module:affix" local debug_track_module = "Module:debug/track" local decorations_module = "Module:decorations" local en_utilities_module = "Module:en-utilities" local fun_is_callable_module = "Module:fun/isCallable" local headword_module = "Module:headword" local headword_data_module = "Module:headword/data" local languages_module = "Module:languages" local links_module = "Module:links" local parameters_module = "Module:parameters" local parse_interface_module = "Module:parse interface" local parse_utilities_module = "Module:parse utilities" local string_pattern_escape_module = "Module:string/patternEscape" local string_replacement_escape_module = "Module:string/replacementEscape" local string_utilities_module = "Module:string utilities" local table_module = "Module:table" local yesno_module = "Module:yesno" local dump = mw.dumpObject local unpack = unpack or table.unpack -- Lua 5.2 compatibility local insert = table.insert local concat = table.concat local remove = table.remove local sort = table.sort local deep_equals = require_when_needed(table_module, "deepEquals") local extend = require_when_needed(table_module, "extend") local insert_if_not = require_when_needed(table_module, "insertIfNot") local list_to_set = require_when_needed(table_module, "listToSet") local serial_comma_join = require_when_needed(table_module, "serialCommaJoin") local shallow_copy = require_when_needed(table_module, "shallowCopy") local split = require_when_needed(string_utilities_module, "split") local ugsub = require_when_needed(string_utilities_module, "gsub") local umatch = require_when_needed(string_utilities_module, "match") local pattern_escape = require_when_needed(string_pattern_escape_module) local replacement_escape = require_when_needed(string_replacement_escape_module) local escape_wikicode = require_when_needed(parse_utilities_module, "escape_wikicode") local parse_inline_modifiers = require_when_needed(parse_utilities_module, "parse_inline_modifiers") local term_contains_top_level_html = require_when_needed(parse_utilities_module, "term_contains_top_level_html") local get_lang_by_code = require_when_needed(languages_module, "getByCode") local is_callable = require_when_needed(fun_is_callable_module) local format_decorations = require_when_needed(decorations_module, "format_decorations") local function split_on_comma(val) if val:find(",") then return require(parse_interface_module).split_on_comma(val) else return {val} end end local function ine(val) if val == "" then return nil else return val end end --[=[ Add decorations to a term. `termobj` is the object describing the term, which should optionally contain: * left qualifiers in `q`, an array of strings; * right qualifiers in `qq`, an array of strings; * left labels in `l`, an array of strings; * right labels in `ll`, an array of strings; * references in `refs`, an array either of strings (formatted reference text) or objects containing fields `text` (formatted reference text) and optionally `name` and/or `group`; `text` is the text of the term itself, and `lang` is the language object. ]=] local function add_decorations(text, termobj, lang) local function field_non_empty(field) local list = termobj[field] if not list then return nil end if type(list) ~= "table" then error(("Internal error: Wrong type for `termobj.%s`=%s, should be \"table\""):format( field, mw.dumpObject(list))) end return list[1] end if field_non_empty("q") or field_non_empty("qq") or field_non_empty("l") or field_non_empty("ll") or field_non_empty("refs") then text = format_decorations { lang = lang, text = text, q = termobj.q, qq = termobj.qq, l = termobj.l, ll = termobj.ll, refs = termobj.refs, } end return text end local param_mods = { id = {}, -- disabled when `is_head = true` q = {type = "qualifier"}, qq = {type = "qualifier"}, l = {type = "labels"}, ll = {type = "labels"}, -- [[Module:headword]] expects part references in `.refs`. ref = {item_dest = "refs", type = "references", store = "insert-flattened"}, } local optional_param_mods = { g = {item_dest = "genders", type = "genders"}, alt = {}, lang = {type = "language"}, sc = {type = "script"}, t = {item_dest = "gloss"}, gloss = {}, pos = {}, lit = {}, tr = {}, ts = {}, face = {}, nolinkinfl = {type = "boolean"}, } local optional_headword_param_mods = { sc = {type = "script"}, tr = {}, ts = {}, } --[==[ Parse a single inflection or headword form or list of such forms. In either case, inline modifiers may be attached. `data` is an object with the following fields: * `val`: The raw value to parse. Required. * `paramname`: The name of the parameter from which the value was taken; used in error messages. Required. * `is_head`: We are parsing a headword parameter (a value which goes into the `heads` field of `data`). This changes the allowed modifiers, disabling the `id` modifier and only allowing a subset of optional modifiers. * `frob`: An optional function of one value to apply to the form after inline modifiers have been removed (i.e. to apply to the `.term` field of the returned object). * `include_mods`: List of extra inline modifiers to include, besides the default ones (see below). Each list item is either a string specifying a recognized extra inline modifier (see `optional_param_mods` in the code), or a two-item list of modifier name and modifier spec, where the spec should follow the syntax for modifier specs in `parse_inline_modifiers` in [[Module:parse utilities]]. * `exclude_mods`: List of default inline modifiers to not include. * `splitchar`: If specified, the value in `val` can be a list of forms to parse, separated by the value of `splitchar` (which is a Lua pattern, as in `parse_inline_modifiers` in [[Module:parse utilities]]). Most commonly, `splitchar` is a single comma and the values are comma-separated (in this case, splitting will not happen if a space follows the comma). * `parse_lang_prefix`: If specified, allow a language prefix to precede a form, and if found, store into the `.lang` field of the returned object. * `preserve_splitchar`, `delimiter_key`, `escape_fun`, `unescape_fun`, `pre_normalize_modifiers`: As in `parse_inline_modifiers` in [[Module:parse utilities]]. Returns an object suitable for storing as one element of one of the lists in `headdata.inflections`, where `headdata` is the structure passed to [[Module:headword]]. If `splitchar` is specified, howeve, the return value is a list of such objects. The following default inline modifiers are currently recognized: * `q`: Left qualifier. * `qq`: Right qualifier. * `l`: Comma-separated list of left labels. No space should follow the comma. * `ll`: Comma-separated list of right labels. No space should follow the comma. * `ref`: Reference or references. See {{tl|IPA}} for the syntax. * `id`: Sense ID, in case there are multiple senses. See {{tl|l}}. The following are the recognized additional inline modifiers: * `g`: Comma-separated list of genders. * `alt`: Display text. * `lang`: Language code of language of the form, if different from the language of the headword. * `sc`: Script code of script of the form. Almost never needed. * `t`: Gloss for the form. * `gloss`: Gloss for the form (alias for `t`). * `pos`: Part of speech of the form. * `lit`: Literal meaning of the form. * `tr`: Manual transliteration of the form. * `ts`: Transcription of the form, for languages where the transliteration differs markedly from the pronunciation. * `face`: Face to display the form in, e.g. {"hypothetical"} for a hypothetical form (unlinkable and displayed in italics). * `nolinkinfl`: Make the form unlinkable. ]==] function export.parse_term_with_modifiers(data) local paramname, val, frob = data.paramname, data.val, data.frob local function generate_obj(term, parse_err) if frob then term = frob(term, parse_err) end if data.parse_lang_prefix and term:find(":") then return require(parse_utilities_module).generate_obj_maybe_parsing_lang_prefix { term = term, paramname = paramname, parse_lang_prefix = true, parse_err = parse_err, } else return {term = term} end end -- Check for inline modifier, e.g. מרים<tr:Miryem>. But exclude top-level HTML entry with <span ...>, -- <sup> or similar in it. if (val:find("<", nil, true) or data.splitchar) and not term_contains_top_level_html(val) and -- don't parse inline modifiers if is_head and the value begins with a ~ (link modifier syntax) (not data.is_head or not val:find("^~")) then local param_mods = param_mods if data.is_head then param_mods = shallow_copy(param_mods) param_mods.id = nil end if data.include_mods or data.exclude_mods then if not data.is_head then -- already copied when data.is_head param_mods = shallow_copy(param_mods) end if data.include_mods then local optional_mods = data.is_head and optional_headword_param_mods or optional_param_mods for _, mod in ipairs(data.include_mods) do if type(mod) == "table" then if #mod ~= 2 then error(("Internal error: Modifier spec %s in `include_mods` should be of length 2"):format( dump(mod))) end local modkey, modvalue = unpack(mod) param_mods[modkey] = modvalue elseif not optional_mods[mod] then error(("Internal error: Unrecognized modifier spec %s in `include_mods`"):format( dump(mod))) else param_mods[mod] = optional_mods[mod] end end end if data.exclude_mods then for _, mod in ipairs(data.exclude_mods) do if not param_mods[mod] then error(("Internal error: Modifier spec %s in `exclude_mods` not found among existing modifiers" ):format(dump(mod))) else param_mods[mod] = nil end end end end return parse_inline_modifiers(val, { paramname = paramname, param_mods = param_mods, generate_obj = generate_obj, splitchar = data.splitchar, preserve_splitchar = data.preserve_splitchar, delimiter_key = data.delimiter_key, escape_fun = data.escape_fun, unescape_fun = data.unescape_fun, pre_normalize_modifiers = data.pre_normalize_modifiers, }) else local retval = generate_obj(val) if data.splitchar then retval = {retval} end return retval end end --[==[ Parse a list of inflection forms that may have inline modifiers attached. `data` is an object with the following fields: * `forms`: The list of raw values to parse. Required. * `paramname`: The name of the first parameter from which the value was taken; used in error messages. If this is a two-element list, the first element is the first parameter and the second element is the prefix of the remaining parameters. Parameter names that are numbers are handled correctly, as are those with \1 in it marking where the parameter index goes. Required. * `qualifiers`: If specified, a possibly gappy list of left qualifiers to add to the parsed terms (for compatibility purposes). * `splitchar`: As in `parse_term_with_modifiers()`. The resulting per-term lists will be flattened. * `frob`, `include_mods`, `exclude_mods`, `is_head`, `preserve_splitchar`, `parse_lang_prefix`, `delimiter_key`, `escape_fun`, `unescape_fun`, `pre_normalize_modifiers`: As in `parse_term_with_modifiers()`. Returns a list of objects, suitable for storing as one of the lists in `headdata.inflections` (once a label is added), where `headdata` is the structure passed to [[Module:headword]]. ]==] function export.parse_term_list_with_modifiers(data) local paramname, forms = data.paramname, data.forms local qualifiers = data.qualifiers local first, restpref if type(paramname) == "table" then first = paramname[1] restpref = paramname[2] else first = paramname restpref = paramname end local terms = {} data = shallow_copy(data) for i, val in ipairs(forms) do data.paramname = i == 1 and first or type(restpref) == "number" and restpref + i - 1 or restpref:find("\1", nil, true) and restpref:gsub("\1", tostring(i)) or restpref .. i data.val = val local parsed = export.parse_term_with_modifiers(data) if qualifiers and qualifiers[i] then if data.splitchar then for _, term in ipairs(parsed) do term.q = {qualifiers[i]} end else parsed.q = {qualifiers[i]} end end if data.splitchar then extend(terms, parsed) else terms[i] = parsed end end return terms end --[==[ Construct a link to [[Appendix:Glossary]] for `entry`. If `text` is specified, it is the display text; otherwise, `entry` is used. ]==] function export.glossary_link(entry, text) text = text or entry return "[[Apendise:Glosaryo#" .. entry .. "|" .. text .. "]]" --TLCHANGE Appendix:Glossary end function export.replace_glossary_links_in_label(label) if label:find("<<", nil, true) then label = label:gsub("<<(.-)|(.-)>>", export.glossary_link):gsub("<<(.-)>>", export.glossary_link) end return label end --[==[ Insert a fixed inflection (a label not associated with any inflection values) into an `inflections` field. The `inflections` field will be initialized if needed. `data` is an object with the following fields: * `headdata`: The headword structure passed to [[Module:headword]]. Required. * `inflobj`: The object whose `inflections` field the terms are inserted into. Defaults to `headdata`. Only needs to be set for nested inflections, which are specified for an inflection object rather than the headword data structure as a whole. * `label`: The label that the inflections are given; any parts of the label surrounded in `<<...>>` are linked to the glossary. (If the contents of `<<...>>` contain a `|` in them, they are a two-part link.) Required. * `originating_term`: The term object from which this label is derived. If specified, decorations will be taken from this object. ]==] function export.insert_fixed_inflection(data) local headdata, origterm, label = data.headdata, data.originating_term, data.label local inflobj = data.inflobj or headdata inflobj.inflections = inflobj.inflections or {} if not origterm then insert(inflobj.inflections, { label = export.replace_glossary_links_in_label(label) }) else if origterm.id then error(("It doesn't make sense to pass in an ID '%s' for label '%s' in conjunction with a term value '%s'" ):format(origterm.id, label, origterm.term)) end origterm = shallow_copy(origterm) -- Preserve decorations origterm.term = nil origterm.label = export.replace_glossary_links_in_label(label) insert(inflobj.inflections, origterm) end end --[==[ Insert previously-parsed terms into an `inflections` field. The `inflections` field will be initialized if needed. `data` is an object with the following fields: * `headdata`: The headword structure passed to [[Module:headword]]. Required. * `inflobj`: The object whose `inflections` field the terms are inserted into. Defaults to `headdata`. Only needs to be set for nested inflections, which are specified for an inflection object rather than the headword data structure as a whole. * `terms`: The list of parsed terms. If {nil} or omitted, nothing happens unless `request` is set. * `label`: The label that the inflections are given; any parts of the label surrounded in `<<...>>` are linked to the glossary. (If the contents of `<<...>>` contain a `|` in them, they are a two-part link.) Required. * `no_label`: If the term is {"-"} and there are no other terms, insert a fixed label with this value. Defaults to {"no "} plus the label. * `usually_no_label`: If the term is {"-"} and there are other terms, insert a fixed label with this value. Defaults to {"usually no "} plus the label. * `cats`: List of categories to insert when terms are given that are not {"-"}. Each category is a string naming a full category to insert (including the appropriate language name prefixed). * `no_cats`: List of categories to insert when a term is given as {"-"}. * `usually_no_cats`: List of categories to insert when a term is given as {"-"} and additional terms are specified as well (representing, e.g. for the inflection {"plural"}, a term which usually has no plural but does under some circumstances). If omitted, both the categories in `cats` and `no_cats` are inserted. * `accel`: If specified, a full accelerator object to add to the inflections. * `request`: If specified and no terms are given, insert a label with a request for inflections to be given. * `enable_auto_translit`: If specified and terms are given, display automatic transliteration of the terms. The return value indicates whether the inflection exists and how many terms are in it. It is an object with the following fields: * `exists`: {"yes"} if one or more terms were specified; {"no"} if the value was given as {"-"}; {"usually no"} if the first value was given as {"-"} but additional terms were supplied; otherwise {nil}, indicating that the status is unspecified. * `numterms`: Number of terms in the inflection. Will be 0 unless `exists` has the value {"yes"} or {"usually no"}. * `request`: True if no terms were specified but a term request was inserted into the inflection (because `data.request` was specified). Otherwise {nil}. ]==] function export.insert_inflection(data) local headdata, terms, label = data.headdata, data.terms, data.label local inflobj = data.inflobj or headdata local retval = {} local accel = data.accel if data.accel_form then if accel then error("Internal error: can't specify both data.accel and data.accel_form") end if headdata.heads then local lemmas = {} local lemma_translits = {} for i, headobj in ipairs(headdata.heads) do lemmas[i] = headobj.term if lemmas[i] == "+" then error("Internal error: If you use data.accel_form, you should have resolved all occurrences of + in heads appropriately") end lemma_translits[i] = headobj.tr end accel = { lemma = lemmas, lemma_translit = lemma_translits, form = data.accel_form, } else accel = { form = data.accel_form, } end end local function insert_cats(cats) for _, cat in ipairs(cats) do insert(headdata.categories, cat) end end if terms and terms[1] then terms = shallow_copy(terms) if terms[1].term == "-" then if terms[2] then export.insert_fixed_inflection { headdata = headdata, inflobj = inflobj, originating_term = terms[1], label = data.usually_no_label or "usually no " .. label, } remove(terms, 1) retval.numterms = #terms retval.exists = "usually no" if data.usually_no_cats then insert_cats(data.usually_no_cats) else if data.no_cats then insert_cats(data.no_cats) end if data.cats then insert_cats(data.cats) end end else export.insert_fixed_inflection { headdata = headdata, inflobj = inflobj, originating_term = terms[1], label = data.no_label or "no " .. label, } retval.numterms = 0 retval.exists = "no" if data.no_cats then insert_cats(data.no_cats) end return retval end else retval.numterms = #terms retval.exists = "yes" if data.cats then insert_cats(data.cats) end end if data.check_missing then error("Internal error: check_missing support removed; use checkredlinks=true in [[Module:headword]]") end terms.label = export.replace_glossary_links_in_label(label) if accel then terms.accel = accel end terms.enable_auto_translit = data.enable_auto_translit inflobj.inflections = inflobj.inflections or {} insert(inflobj.inflections, terms) elseif data.request then inflobj.inflections = inflobj.inflections or {} insert(inflobj.inflections, { label = export.replace_glossary_links_in_label(label), request = true, }) retval.numterms = 0 -- retval.exists = nil retval.request = true else retval.numterms = 0 -- retval.exists = nil end return retval end --[==[ Parse raw arguments from `forms` for inline modifiers, and insert the resulting terms (which should not require significant additional processing) into `headdata.inflections`. `data` is an object with the following fields: * `forms`: The list of raw values to parse. If {nil} or omitted, nothing happens. * `headdata`: The headword structure passed to [[Module:headword]]. Required. * `paramname`: As in `parse_term_list_with_modifiers()`. Required. * `label`: As in `insert_inflection()`. Required. * `qualifiers`, `frob`, `include_mods`, `exclude_mods`, `is_head`, `splitchar`, `preserve_splitchar`, `delimiter_key`, `escape_fun`, `unescape_fun`, `pre_normalize_modifiers`: As in `parse_term_list_with_modifiers()`. * `accel`: As in `insert_inflection()`. Return value is as in `insert_inflection()`. ]==] function export.parse_and_insert_inflection(data) local forms = data.forms if forms and forms[1] then data = shallow_copy(data) data.forms = forms data.terms = export.parse_term_list_with_modifiers(data) return export.insert_inflection(data) end return { numterms = 0 } end --[==[ Canonicalize a single term or term-like object or a list of either into a list of term-like objects. `abterms` is the term or list to canonicalize, and `field` is the name of the field holding the term (defaulting to {"term"}). This does the minimal work necessary, meaning that the return value may partly or completely share memory with the value passed in. As a special case, if `abterms` is {nil}, {nil} is returned. If `origin_val` is specified, add a field `origin` containing the value of `origin_val` to each resulting term-like object (in this case, the object will be copied a necessary to avoid side-effecting the passed-in objects). ]==] function export.canonicalize_termobj_list(abterms, field, origin_val) if abterms == nil then return nil end field = field or "term" if type(abterms) == "string" then return {{[field] = abterms, origin = origin_val}} elseif not abterms[1] then if origin_val ~= nil then abterms = shallow_copy(abterms) abterms.origin = origin_val end return {abterms} else -- Check if already in full list term and return directly if so (unless `origin_val` is given, in which case we -- need to shallow-copy both the list and each term in it). local must_convert = false for _, term in ipairs(abterms) do if type(term) == "string" then must_convert = true break end end if not must_convert then if origin_val ~= nil then abterms = shallow_copy(abterms) for i, abterm in ipairs(abterms) do abterms[i] = shallow_copy(abterm) abterms[i].origin = origin_val end end return abterms end end local retval = {} for _, term in ipairs(abterms) do if type(term) == "string" then insert(retval, {[field] = term, origin = origin_val}) else if origin_val ~= nil then term = shallow_copy(term) term.origin = origin_val end insert(retval, term) end end return retval end --[==[ Combine two sets of decorations. If either is {nil}, just return the other, and if both are {nil}, return {nil}. ]==] function export.combine_decorations(decs1, decs2) if not decs1 and not decs2 then return nil end if not decs1 then return decs2 end if not decs2 then return decs1 end local combined = shallow_copy(decs1) for _, dec in ipairs(decs2) do insert_if_not(combined, dec) end return combined end function export.combine_qualifiers_or_labels(...) -- FIXME: Added 2026-09-17. Remove after a month. error("Use combine_decorations instead") end --[==[ Combine the decorations (qualifiers, labels, references) and ID's of two term objects. `destobj` is the "destination term object" into which the combined properties are written, and `srcobj` is the "source object" into which the properties are merged. `destobj` is side-effected (but the lists inside of `destobj` are not); if this is undesirable, make sure to shallow-copy `destobj` first. If both objects have values for a given decoration, the values of `destobj` come first. If both objects have a value for `id`, the values must match or an error is thrown; otherwise, the resulting value of `id` comes from whichever one is defined. '''NOTE:''' This may not be the correct behavior when deduplicating a list of term objects. See `insert_termobj_combining_duplicates` for a different approach. ]==] function export.combine_termobj_decorations(destobj, srcobj) destobj.q = export.combine_decorations(destobj.q, srcobj.q) destobj.qq = export.combine_decorations(destobj.qq, srcobj.qq) destobj.l = export.combine_decorations(destobj.l, srcobj.l) destobj.ll = export.combine_decorations(destobj.ll, srcobj.ll) destobj.refs = export.combine_decorations(destobj.refs, srcobj.refs) if destobj.id and srcobj.id and destobj.id ~= srcobj.id then -- FIXME: We probably want to pass in an error function error(("Can't specify two different ID's %s and %s when combining objects"):format(srcobj.id, destobj.id)) end destobj.id = destobj.id or srcobj.id return destobj end function export.combine_termobj_qualifiers_labels(...) -- FIXME: Added 2026-09-17. Remove after a month. error("Use combine_termobj_decorations instead") end function export.termobj_has_decorations(obj) return obj.q and obj.q[1] or obj.qq and obj.qq[1] or obj.l and obj.l[1] or obj.ll and obj.ll[1] or obj.refs and obj.refs[1] end function export.termobj_has_qualifiers_or_labels(...) -- FIXME: Added 2026-09-17. Remove after a month. error("Use termobj_has_decorations instead") end local function one_decoration_equal(prop1, prop2) local prop1_is_nil = not prop1 or not prop1[1] local prop2_is_nil = not prop2 or not prop2[1] if prop1_is_nil and prop2_is_nil then return true end if prop1_is_nil or prop2_is_nil then return false end return deep_equals(prop1, prop2) end function export.termobj_decorations_equal(obj1, obj2) return one_decoration_equal(obj1.q, obj2.q) and one_decoration_equal(obj1.qq, obj2.qq) and one_decoration_equal(obj1.l, obj2.l) and one_decoration_equal(obj1.ll, obj2.ll) and one_decoration_equal(obj1.refs, obj2.refs) and obj1.id == obj2.id end function export.termobj_ancillary_properties_equal(...) -- FIXME: Added 2026-09-17. Remove after a month. error("Use termobj_decorations_equal instead") end function export.convert_termobj_to_formobj(termobj) local formobj = { form = termobj.term, translit = termobj.tr, } local footnotes local function mods_to_footnote(mod_prefix, mod_vals) if mod_vals and mod_vals[1] then footnotes = footnotes or {} for _, val in ipairs(mod_vals) do insert(footnotes, "[" .. mod_prefix .. ":" .. val .. "]") end end end mods_to_footnote("q", termobj.q) mods_to_footnote("qq", termobj.qq) mods_to_footnote("l", termobj.l) mods_to_footnote("ll", termobj.ll) mods_to_footnote("ref", termobj.refs) mods_to_footnote("id", termobj.id and {termobj.id} or nil) formobj.footnotes = footnotes return formobj end local recognized_multi_mods = { q = "q", qq = "qq", l = "l", ll = "ll", ref = "refs", } local recognized_single_mods = { id = "id", } function export.add_footnote_to_termobj(termobj, footnote) local stripped_footnote = footnote:match("^%[(.*)%]$") if not stripped_footnote then error("Internal error: Footnote should be surrounded by brackets at this stage: " .. footnote) end local prefix, rest = stripped_footnote:match("^([a-z]+):(.+)$") local field, is_multi if prefix then if recognized_multi_mods[prefix] then field = recognized_multi_mods[prefix] is_multi = true elseif recognized_single_mods[prefix] then field = recognized_single_mods[prefix] is_multi = false end end if not field then rest = stripped_footnote field = "l" is_multi = true end if is_multi then if not termobj[field] then termobj[field] = {} end insert(termobj[field], rest) else if termobj[field] and termobj[field] ~= rest then error(("Can't set two values for '%s': '%s' and '%s'"):format(field, termobj[field], rest)) end termobj[field] = rest end end function export.convert_formobj_to_termobj(formobj) local termobj = { term = formobj.form, tr = formobj.translit, } if formobj.footnotes then for _, footnote in ipairs(formobj.footnotes) do export.add_footnote_to_termobj(termobj, footnote) end end return termobj end local function extract_termobj_field_modifiers(fieldval) return fieldval:match("^([*+]?)(.*)$") end function export.remove_termobj_field_modifiers(termobj) local function remove_field_modifiers(field) if termobj[field] and termobj[field][1] then local any_field_modifiers = false for _, val in ipairs(termobj[field]) do local field_mods, _ = extract_termobj_field_modifiers(val) if field_mods ~= "" then any_field_modifiers = true break end end local new_field = {} if any_field_modifiers then for _, val in ipairs(termobj[field]) do local _, field_without_mods = extract_termobj_field_modifiers(val) insert_if_not(new_field, field_without_mods) end termobj[field] = new_field end end end remove_field_modifiers("q") remove_field_modifiers("qq") remove_field_modifiers("l") remove_field_modifiers("ll") remove_field_modifiers("refs") end function export.insert_termobj_combining_duplicates(destobjs, termobj) for _, destobj in ipairs(destobjs) do if destobj.term == termobj.term and destobj.tr == termobj.tr then -- Form already present; maybe combine footnotes. local function combine_field_values(field) if termobj[field] and termobj[field][1] then -- Check to see if there are existing values with *; if so, remove them. if destobj[field] and destobj[field][1] then local any_values_with_asterisk = false for _, val in ipairs(destobj[field]) do local field_mods, _ = extract_termobj_field_modifiers(val) if field_mods:find("%*") then any_values_with_asterisk = true break end end if any_values_with_asterisk then local filtered_values = {} for _, val in ipairs(destobj[field]) do local field_mods, _ = extract_termobj_field_modifiers(val) if not field_mods:find("%*") then insert(filtered_values, val) end end if filtered_values[1] then destobj[field] = filtered_values else destobj[field] = nil end end end local any_footnotes_with_plus = false for _, val in ipairs(termobj[field]) do local field_mods, _ = extract_termobj_field_modifiers(val) if field_mods:find("%+") then any_footnotes_with_plus = true break end end if any_footnotes_with_plus then if not destobj[field] then destobj[field] = {} else destobj[field] = shallow_copy(destobj[field]) end for _, val in ipairs(termobj[field]) do local already_seen = false local field_mods, field_without_mods = extract_termobj_field_modifiers(val) if field_mods:find("%+") then for _, existing_val in ipairs(destobj[field]) do local _, existing_field_without_mods = extract_termobj_field_modifiers(existing_val) if existing_field_without_mods == field_without_mods then already_seen = true break end end if not already_seen then insert(destobj[field], val) end end end end end end combine_field_values("q") combine_field_values("qq") combine_field_values("l") combine_field_values("ll") combine_field_values("refs") if destobj.id and termobj.id and destobj.id ~= termobj.id then -- FIXME: We probably want to pass in an error function error(("Can't specify two different ID's %s and %s when combining objects"):format(termobj.id, destobj.id)) end destobj.id = destobj.id or termobj.id return end end insert(destobjs, termobj) end export.allowed_special_indicators = { ["first"] = true, ["first-second"] = true, ["first-last"] = true, ["second"] = true, ["last"] = true, ["each"] = true, ["+"] = true, -- requests the default behavior with preposition handling } --[==[ Check for special indicators (values such as {"+first"} or {"+first-last"} that are used in a `pl`, `f`, etc. argument and indicate how to inflect a multiword term). If `form` is such an indicator, the return value is `form` minus the initial `+` sign; otherwise, if form begins with a `+` sign, an error is thrown; otherwise the return value is nil. ]==] function export.get_special_indicator(form, noerror) if form:find("^%+") then form = form:gsub("^%+", "") if not export.allowed_special_indicators[form] then if noerror then return nil end local indicators = {} for indic, _ in pairs(export.allowed_special_indicators) do insert(indicators, "+" .. indic) end sort(indicators) error("Special inflection indicator beginning with '+' can only be " .. mw.text.listToText(indicators) .. ": +" .. form) end return form end return nil end local function add_endings(bases, endings) local retval = {} if type(bases) ~= "table" then bases = {bases} end if type(endings) ~= "table" then endings = {endings} end for _, base in ipairs(bases) do for _, ending in ipairs(endings) do insert(retval, base .. ending) end end return retval end --[==[ Inflect a possibly multiword or hyphenated term `form` using the function `inflect`, which is a function of one argument that is called on a single word to inflect and should return either the inflected word or a list of inflected words. `special` indicates how to inflect the multiword term and should be e.g. {"first"} to inflect only the first word, {"first-last"} to inflect the first and last words, {"each"} to inflect each word, etc. See `allowed_special_indicators` above for the possibilities. If `special` is `+`, or is omitted and the term is multiword (i.e. containing a space character), and `prepositions` is supplied, the function checks for multiword or hyphenated terms containing the prepositions in `prepositions`, e.g. Italian [[senso di marcia]] or [[medaglia d'oro]] or Portuguese [[tartaruga-do-mar]]. If such a term is found, only the first word is inflected. Otherwise, the default is {"first-last"}. `prepositions` is a list of Lua patterns matching prepositions. The patterns will automatically have the separator character (space or hyphen) added to the left side but not the right side, so they should contain a space character (which will automatically be converted to the appropriate separator) on the right side unless the preposition is joined on the right side with an apostrophe. Examples of preposition patterns for Italian are {"di "}, {"sull'"} and {"d?all[oae] "} (which matches {"dallo "}, {"dalle "}, {"alla "}, etc.). The return value is always either a list of inflected multiword or hyphenated terms, or nil if `special` is omitted and `form` is not multiword. (If `special` is specified and `form` is not multiword or hyphenated, an error results.) ]==] function export.handle_multiword(form, special, inflect, prepositions, sep) sep = sep or form:find(" ") and " " or "%-" local raw_sep = sep == " " and " " or "-" -- Used to add regex version of separator in the replacement portion of ugsub() or :gsub() local sep_replacement = sep == " " and " " or "%%-" -- Given a Lua pattern, replace space with the appropriate separator. local function hack_re(re) if sep == " " then return re end return (re:gsub(" ", sep_replacement)) end if special == "first" then local first, rest = form:match(hack_re("^(.-)( .*)$")) if not first then error("Special indicator 'first' can only be used with a multiword term: " .. form) end return add_endings(inflect(first), rest) elseif special == "second" then local first, second, rest = form:match(hack_re("^([^ ]+ )([^ ]+)( .*)$")) if not first then error("Special indicator 'second' can only be used with a term with three or more words: " .. form) end return add_endings(add_endings({first}, inflect(second)), rest) elseif special == "first-second" then local first, space, second, rest = form:match(hack_re("^([^ ]+)( )([^ ]+)( .*)$")) if not first then error("Special indicator 'first-second' can only be used with a term with three or more words: " .. form) end return add_endings(add_endings(add_endings(inflect(first), space), inflect(second)), rest) elseif special == "each" then local terms = split(form, sep) if #terms < 2 then error("Special indicator 'each' can only be used with a multiword term: " .. form) end for i, term in ipairs(terms) do terms[i] = inflect(term) if i > 1 then terms[i] = add_endings(raw_sep, terms[i]) end end local result = "" for _, term in ipairs(terms) do result = add_endings(result, term) end return result elseif special == "first-last" then local first, middle, last = form:match(hack_re("^(.-)( .* )(.-)$")) if not first then first, middle, last = form:match(hack_re("^(.-)( )(.*)$")) end if not first then error("Special indicator 'first-last' can only be used with a multiword term: " .. form) end return add_endings(add_endings(inflect(first), middle), inflect(last)) elseif special == "last" then local rest, last = form:match(hack_re("^(.* )(.-)$")) if not rest then error("Special indicator 'last' can only be used with a multiword term: " .. form) end return add_endings(rest, inflect(last)) elseif special and special ~= "+" then error("Unrecognized special=" .. special) end -- Only do default behavior if special indicator '+' explicitly given or separator is space; otherwise we will -- break existing behavior with hyphenated words. if (special == "+" or sep == " ") and form:find(sep) then if prepositions then -- check for prepositions in the middle of the word; do it this way so we can handle -- more than one word before the preposition (and usually inflect each word) for _, prep in ipairs(prepositions) do local first, space_prep_rest = umatch(form, hack_re("^(.-)( " .. prep .. ".*)$")) if first then return add_endings(inflect(first), space_prep_rest) end end end -- multiword or hyphenated expressions default to first-last; we need to pass in the separator to avoid -- problems with multiword terms containing hyphens in the individual words return export.handle_multiword(form, "first-last", inflect, prepositions, sep) end return nil end local function link_hyphen_split_component(word, data) if data.link_hyphen_split_component then return data.link_hyphen_split_component(word) else return "[[" .. word .. "]]" end end -- Default function to split a word on apostrophes. Don't split apostrophes at the beginning or end of a word (e.g. -- [['ndrangheta]] or [[po']]). Handle multiple apostrophes correctly, e.g. [[l'altr'ieri]] -> [[l']][altr']][[ieri]]. function export.default_split_apostrophe(word, data) local apostrophe_parts = split(word, "'", true, true) local linked_apostrophe_parts = {} local apostrophes_at_beginning = "" local i = 1 -- Apostrophes at beginning get attached to the first word after (which will always exist but may -- be blank if the word consists only of apostrophes). while i < #apostrophe_parts do -- <, not <=, in case the word consists only of apostrophes local apostrophe_part = apostrophe_parts[i] i = i + 1 if apostrophe_part == "" then apostrophes_at_beginning = apostrophes_at_beginning .. "'" else break end end apostrophe_parts[i] = apostrophes_at_beginning .. apostrophe_parts[i] -- Now, do the remaining parts. A blank part indicates more than one apostrophe in a row; we join -- all of them to the preceding word. while i <= #apostrophe_parts do local apostrophe_part = apostrophe_parts[i] if apostrophe_part == "" then linked_apostrophe_parts[#linked_apostrophe_parts] = linked_apostrophe_parts[#linked_apostrophe_parts] .. "'" elseif i == #apostrophe_parts then insert(linked_apostrophe_parts, apostrophe_part) else insert(linked_apostrophe_parts, apostrophe_part .. "'") end i = i + 1 end for j, tolink in ipairs(linked_apostrophe_parts) do linked_apostrophe_parts[j] = link_hyphen_split_component(tolink, data) end return concat(linked_apostrophe_parts) end --[=[ Auto-add links to a word that should not have spaces but may have hyphens and/or apostrophes. We split off final punctuation, then split on hyphens if `data.split_hyphen` is given, and also split on apostrophes if `data.split_apostrophe` is given. We only split on hyphens if they are in the middle of the word, not at the beginning or end (hyphens at the beginning or end indicate suffixes or prefixes, respectively). `include_hyphen_prefixes`, if given, is a set of prefixes (not including the final hyphen) where we should include the final hyphen in the prefix. Hence, e.g. if "anti" is in the set, a Portuguese word like [[anti-herói]] "anti-hero" will be split [[anti-]][[herói]] (whereas a word like [[código-fonte]] "source code" will be split as [[código]]-[[fonte]]). If `data.split_apostrophe` is specified, we split on apostrophes unless `data.no_split_apostrophe_words` is given and the word is in the specified set, such as French [[c'est]] and [[quelqu'un]]. If `data.split_apostrophe` is true, the default algorithm applies, which splits on all apostrophes except those at the beginning and end of a word (as in Italian [['ndrangheta]] or [[po']]), and includes the apostrophe in the link to its left (so we auto-split French [[l'eau]] as [[l']][[eau]] and [[l'altr'ieri]] as [[l']][altr']][[ieri]]). If `data.split_apostrophe` is specified but not `true`, it should be a function of one argument that does custom apostrophe-splitting. The argument is the word to split, and the return value should be the split and linked word. ]=] local function add_single_word_links(space_word, data, term_has_spaces) local space_word_no_punct, punct local punct_pattern = data.punctuation if punct_pattern and is_callable(punct_pattern) then space_word_no_punct, punct = punct_pattern(space_word) else if punct_pattern == nil then punct_pattern = "[,;:?!]" end space_word_no_punct, punct = umatch(space_word, "^(.*)(" .. punct_pattern .. ")$") end space_word_no_punct = space_word_no_punct or space_word punct = punct or "" local words if space_word_no_punct:sub(1, 1) == "-" or space_word_no_punct:sub(-1) == "-" then -- don't split prefixes and suffixes words = {space_word_no_punct} else local splitter if term_has_spaces then splitter = data.split_hyphen_when_space else splitter = data.split_hyphen_when_no_space end if is_callable(splitter) then words = splitter(space_word_no_punct) if type(words) == "string" then return words .. punct end end end if not words then local split_hyphen if term_has_spaces then split_hyphen = data.split_hyphen_when_space else split_hyphen = data.split_hyphen_when_no_space if split_hyphen == nil then -- default to true; use `false` to avoid this split_hyphen = true end end if split_hyphen then words = split(space_word_no_punct, "-", true, true) else words = {space_word_no_punct} end end local linked_words = {} for j, word in ipairs(words) do if j < #words and data.include_hyphen_prefixes and data.include_hyphen_prefixes[word] then word = "[[" .. word .. "-]]" elseif j > 1 and data.include_hyphen_suffixes and data.include_hyphen_suffixes[word] then word = "[[-" .. word .. "]]" else -- Don't split on apostrophes if the word is in `no_split_apostrophe_words`. if (not data.no_split_apostrophe_words or not data.no_split_apostrophe_words[word]) and data.split_apostrophe and word:find("'", nil, true) then if data.split_apostrophe == true then word = export.default_split_apostrophe(word, data) else -- custom apostrophe splitter/linker word = data.split_apostrophe(word) end elseif word ~= "" then -- avoid -[[]]- (e.g. f--k) word = link_hyphen_split_component(word, data) end if j < #words then word = word .. "-" end end insert(linked_words, word) end return concat(linked_words) .. punct end --[=[ Auto-add links to a multiword term. `data` contains fields customizing how to do this. By default we proceed as follows: (1) If the term already has embedded links in it, they are left unchanged. (2) Otherwise, if there are spaces present, we split on spaces and link each word separately. (3) If a given space-separated component ends in punctuation (defaulting to [,;:?!]), it is separated off, the remainder of the algorithm run, and the punctuation pasted back on. (4) If there are hyphens in a given space-separated component, we may link each hyphenated term separately depending on the settings in `data`. Normally the hyphens are not included in the linked terms, but this can be overridden for specific prefixes and/or suffixes. By default, if there are spaces in the multiword term, we do not link hyphenated components (because of cases like "boire du petit-lait" where "petit-lait" should be linked as a whole), but do so otherwise (e.g. for "avant-avant-hier"); this can overridden for cases like "croyez-le ou non". Cases where only some of the hyphens should be split can always be handled by explicitly specifying the head (e.g. "Nord-Pas-de-Calais" given as head=[[Nord]]-[[Pas-de-Calais]]). (5) If there are apostrophes in a given component, we may link each apostrophe-separated term separately depending on the settings in `data`, including the apostrophe in the link to its left (so we split "de l'eau" as "[[de]] [[l']][[eau]]"). The settings in `data` are as follows: `split_hyphen_when_no_space`: Whether to split on hyphens when the term has no spaces. Defaults to true if set to `nil`. This can be a function of one argument, to implement a custom splitting algorithm for hyphen-separated terms. If this returns [FIXME: FINISH ME ...] If `data.split_apostrophe` is specified, we split on apostrophes unless `data.no_split_apostrophe_words` is given and the word is in the specified set, such as French [[c'est]] and [[quelqu'un]]. If `data.split_apostrophe` is true, the default algorithm applies, which splits on all apostrophes except those at the beginning and end of a word (as in Italian [['ndrangheta]] or [[po']]), and includes the apostrophe in the link to its left (so we auto-split French [[l'eau]] as [[l']][[eau]] and [[l'altr'ieri]] as [[l']][altr']][[ieri]]). If `data.split_apostrophe` is specified but not `true`, it should be a function of one argument that does custom apostrophe-splitting. The argument is the word to split, and the return value should be the split and linked word. We don't always split on hyphens because of cases like "boire du petit-lait" where "petit-lait" should be linked as a whole, but provide the option to do it for cases like "croyez-le ou non". If there's no space, however, then it makes sense to split on hyphens by `no_split_apostrophe_words` and `include_hyphen_prefixes` allow for special-case handling of particular words and are as described in the comment above add_single_word_links(). ]=] function export.add_links_to_multiword_term(term, data) if term:match("[%[%]]") then return term end local words = split(term, " ", true, true) local term_has_spaces = #words > 1 local linked_words = {} for _, word in ipairs(words) do insert(linked_words, add_single_word_links(word, data, term_has_spaces)) end local retval = concat(linked_words, " ") -- If we ended up with a single link consisting of the entire term, -- remove the link. return retval:match("^%[%[([^%[%]]*)%]%]$") or retval end local function canonicalize_begin_end_spec(spec) local from, to = spec:match("^(.-):(.*)$") if not from then from = spec to = "" end return from, to end --[==[ Given a `linked_term` that is the output of add_links_to_multiword_term(), apply modifications as given in `modifier_spec` to change the link destination of subterms (normally single-word non-lemma forms; sometimes collections of adjacent words). This is usually used to link non-lemma forms to their corresponding lemma, but can also be used to replace a span of adjacent separately-linked words to a single multiword lemma. The format of `modifier_spec` is one or more semicolon-separated subterm specs, where each such spec is of the form SUBTERM:DEST, where SUBTERM is one or more words in the `linked_term` but without brackets in them, and DEST is the corresponding link destination to link the subterm to. Any occurrence of ~ in DEST is replaced with SUBTERM. Alternatively, a single modifier spec can be of the form BEGIN[FROM:TO], which is equivalent to writing BEGINFROM:BEGINTO (see example below). For example, given the source phrase [[il bue che dice cornuto all'asino]] "the pot calling the kettle black" (literally "the ox that calls the donkey horned/cuckolded"), the result of calling add_links_to_multiword_term() is [[il]] [[bue]] [[che]] [[dice]] [[cornuto]] [[all']][[asino]]. With a modifier_spec of 'dice:dire', the result is [[il]] [[bue]] [[che]] [[dire|dice]] [[cornuto]] [[all']][[asino]]. Here, based on the modifier spec, the non-lemma form [[dice]] is replaced with the two-part link [[dire|dice]]. Another example: given the source phrase [[chi semina vento raccoglie tempesta]] "sow the wind, reap the whirlwind" (literally (he) who sows wind gathers [the] tempest"). The result of calling add_links_to_multiword_term() is [[chi]] [[semina]] [[vento]] [[raccoglie]] [[tempesta]], and with a modifier_spec of 'semina:~re; raccoglie:~re', the result is [[chi]] [[seminare|semina]] [[vento]] [[raccogliere|raccoglie]] [[tempesta]]. Here we use the ~ notation to stand for the non-lemma form in the destination link. A more complex example is [[se non hai altri moccoli puoi andare a letto al buio]], which becomes [[se]] [[non]] [[hai]] [[altri]] [[moccoli]] [[puoi]] [[andare]] [[a]] [[letto]] [[al]] [[buio]] after calling add_links_to_multiword_term(). With the following modifier_spec: 'hai:avere; altr[i:o]; moccol[i:o]; puoi: potere; andare a letto:~; al buio:~', the result of applying the spec is [[se]] [[non]] [[avere|hai]] [[altro|altri]] [[moccolo|moccoli]] [[potere|puoi]] [[andare a letto]] [[al buio]]. Here, we rely on the alternative notation mentioned above for e.g. 'altr[i:o]', which is equivalent to 'altri:altro', and link multiword subterms using e.g. 'andare a letto:~'. (The code knows how to handle multiword subexpressions properly, and if the link text and destination are the same, only a single-part link is formed.) ]==] function export.apply_link_modifiers(linked_term, modifier_spec, lang) local split_modspecs = split(modifier_spec, "%s*;%s*") for j, modspec in ipairs(split_modspecs) do local id if modspec:find("<") then local rest rest, id = modspec:match("^(.*)<id:(.-)>$") if rest then modspec = rest end end local subterm, dest, otherlang local begin_spec, rest, end_spec = modspec:match("^%[(.-)%]([^:]*)%[(.-)%]$") if begin_spec then local begin_from, begin_to = canonicalize_begin_end_spec(begin_spec) local end_from, end_to = canonicalize_begin_end_spec(end_spec) subterm = begin_from .. rest .. end_from dest = begin_to .. rest .. end_to end if not subterm then rest, end_spec = modspec:match("^([^:]*)%[(.-)%]$") if rest then local end_from, end_to = canonicalize_begin_end_spec(end_spec) subterm = rest .. end_from dest = rest .. end_to end end if not subterm then begin_spec, rest = modspec:match("^%[(.-)%]([^:]*)$") if begin_spec then local begin_from, begin_to = canonicalize_begin_end_spec(begin_spec) subterm = begin_from .. rest dest = begin_to .. rest end end if not subterm then subterm, dest = modspec:match("^(.-)%s*:%s*(.*)$") if subterm and subterm ~= "^" and subterm ~= "$" then local langdest -- Parse off an initial language code (e.g. 'en:Higgs', 'la:minūtia' or 'grc:σκατός'). Also handle -- Wikipedia prefixes ('w:Abatemarco' or 'w:it:Colle Val d'Elsa'). otherlang, langdest = dest:match("^([A-Za-z0-9._-]+):([^ ].*)$") if otherlang == "w" then local foreign_wikipedia, foreign_term = langdest:match("^([A-Za-z0-9._-]+):([^ ].*)$") if foreign_wikipedia then otherlang = otherlang .. ":" .. foreign_wikipedia langdest = foreign_term end dest = ("%s:%s"):format(otherlang, langdest) otherlang = nil elseif otherlang then otherlang = get_lang_by_code(otherlang, true, "allow etym") dest = langdest end end end if not subterm then if modspec == "?" or modspec == "!" then subterm = "$" dest = modspec elseif modspec == "..." or modspec == "...?" then subterm = "$" dest = " " .. modspec elseif modspec:find("^[A-Z]$") then -- X, Y, etc. by themselves are unlinked, to help with snowclones subterm = modspec dest = "_" else subterm = modspec dest = "~" end end if subterm == "^" then linked_term = dest:gsub("_", " ") .. linked_term elseif subterm == "$" then linked_term = linked_term .. dest:gsub("_", " ") else if subterm:find("[", nil, true) then error(("Subterm '%s' in modifier spec '%s' cannot have brackets in it"):format( escape_wikicode(subterm), escape_wikicode(modspec))) end local escaped_subterm = pattern_escape(subterm) local subterm_re = "%[%[" .. escaped_subterm:gsub("(%%?[ ',%-])", "%%]*%1%%[*") .. "%]%]" local expanded_dest if dest:find("~", nil, true) then expanded_dest = dest:gsub("~", replacement_escape(subterm)) else expanded_dest = dest end if otherlang then expanded_dest = expanded_dest .. "#" .. otherlang:getCanonicalName() end local subterm_replacement if expanded_dest == "_" then subterm_replacement = subterm if id then error("Can't supply <id:...> with an unlinked subterm") end if otherlang then error("Can't supply prefixed language with an unlinked subterm") end elseif id or otherlang then if id and expanded_dest:find("[", nil, true) then error("Can't supply <id:...> with destination with embedded brackets") end subterm_replacement = require(links_module).language_link { lang = otherlang or lang, term = expanded_dest, alt = subterm, id = id, } elseif expanded_dest:find("[", nil, true) then -- Use the destination directly if it has brackets in it (e.g. to put brackets around parts of a word). subterm_replacement = expanded_dest elseif expanded_dest == subterm then subterm_replacement = "[[" .. subterm .. "]]" else subterm_replacement = "[[" .. expanded_dest .. "|" .. subterm .. "]]" end local escaped_subterm_replacement = replacement_escape(subterm_replacement) local replaced_linked_term = ugsub(linked_term, subterm_re, escaped_subterm_replacement) if replaced_linked_term == linked_term then mw.log(("Attempted to replace %s with %s in %s"):format(subterm_re, escaped_subterm_replacement, linked_term)) error(("Subterm '%s' could not be located in %slinked expression %s, or replacement same as subterm"):format( subterm, j > 1 and "intermediate " or "", escape_wikicode(linked_term))) else linked_term = replaced_linked_term end end end return linked_term end local inflection_to_cats = { plural = { filter_plpos = function(plpos) -- plurals also occur with determiners, adjectives etc. and we don't want to generate categories like -- 'countable determiners', 'countable adjectives', etc. Note that the passed-in `plpos` has `proper nouns` -- converted to `nouns`. return plpos == "nouns" end, cats = {"countable {plpos}"}, no_cats = {"uncountable {plpos}"}, }, comparative = { cats = {"comparable {plpos}"}, no_cats = {"uncomparable {plpos}"}, }, ["female equivalent"] = { cats = {"{plpos} with other-gender equivalents"}, }, ["male equivalent"] = { cats = {"{plpos} with other-gender equivalents"}, }, } --[=[ Validate the items in `items` against the list or set of valid items in `valid_items`. If `field` is given, fetch the item to check from that-named field of each object in `items`; otherwise use the items in `items` directly. If an error occurs, `item_type` specifies the type of item to mention in the error message, which will also list the allowed items (either taken directly from `valid_items` if a list, or from the sorted keys if a set). ]=] local function validate_items(data) local items, field, valid_items, item_type = data.items, data.field, data.valid_items, data.item_type local valid_set if valid_items[1] then valid_set = list_to_set(valid_items) else valid_set = valid_items end for _, item in ipairs(items) do if field then item = item[field] end if not valid_set[item] then local valid_list if valid_items[1] then valid_list = valid_items else valid_list = {} for valid_item, _ in pairs(valid_items) do insert(valid_list, valid_item) end table.sort(valid_list) end error(("Invalid %s: %s; expected one of %s"):format(item_type, item, mw.text.listToText(valid_list))) end end end local Headdata = {} function Headdata:get_canonicalized_plpos() return (self.pos_category:gsub("proper noun", "noun")) end --[==[ Canonicalize a category. The category string will have the full language name (i.e. the name of the L2 language under which an entry is inserted, which may a parent language if the language in question is an etymology-only language) prepended to it, and any occurrences of `{plpos}` in the string replaced with the actual plural part of speech (with some canonicalization; specifically, `proper nouns` is converted to `nouns` when replacing `{plpos}`). To specify a full category and not have the language name prepended to it, precede it with {"Category:"}, which will be removed. ]==] function Headdata:canonicalize_category(category) if category:find("{plpos}") then local plpos = self:get_canonicalized_plpos() category = category:gsub("{plpos}", plpos) end if category:find("^Category:") then return (category:gsub("^Category:", "")) else return self.langfullname .. " " .. category end end --[==[ Canonicalize a list of categories according to the process described in `Headdata:canonicalize_category`. This simply loops over each category in `categories` and calls `Headdata:canonicalize_category` on each one. ]==] function Headdata:canonicalize_categories(categories) if not categories then return categories end local canon_cats = {} for _, cat in ipairs(categories) do insert(canon_cats, self:canonicalize_category(cat)) end return canon_cats end --[==[ Insert a category into the `categories` list in the headword `data` structure. `category` is normally a string naming the category, which will have the full language name prepended to it and any occurrences of `{plpos}` in the string replaced with the actual plural part of speech (with some canonicalization; specifically, `proper nouns` is converted to `nouns` when replacing `{plpos}`). To specify a full category and not have the language name prepended to it, precede it with {"Category:"}. ]==] function Headdata:insert_category(category) insert(self.categories, self:canonicalize_category(category)) end --[==[ Validate the genders in `genders` (a list of gender spec objects, as produced by {type = "genders"} in [[Module:parameters]] and accepted by [[Module:gender and number]]), checking that all specified genders are in the list given in `valid_genders`. Optional `props` controls how the validation happens. In particular, unless `props.no_augment` is given, then for any gender beginning with `m`, if a corresponding gender beginning with `f` occurs, analogous genders beginning with `mf`, `mfbysense` and `mfequiv` are also allowed. For example, if `m-d` (masculine dual) and `f-d` (feminine dual) both occur, genders `mf-d`, `mfbysense-d` and `mfequiv-d` are also allowed. If a disallowed gender is given, an error occurs, giving the disallowed gender along with the list of all allowed genders. ]==] function Headdata:validate_genders(genders, valid_genders, props) if not genders then return end props = props or {} local gender_type, no_augment = props.gender_type, props.no_augment gender_type = gender_type or "headword" local valid_gender_set = list_to_set(valid_genders) local augmented_gender_set if no_augment then augmented_gender_set = valid_gender_set else augmented_gender_set = {} for g, _ in pairs(valid_gender_set) do augmented_gender_set[g] = true if g:find("^m") and not g:find("^mf") and valid_gender_set[g:gsub("^m", "f")] then augmented_gender_set[g:gsub("^m", "mf")] = true augmented_gender_set[g:gsub("^m", "mfbysense")] = true augmented_gender_set[g:gsub("^m", "mfequiv")] = true end end end validate_items { items = genders, field = "spec", valid_items = augmented_gender_set, item_type = ("%s gender"):format(gender_type), } end --[==[ Parse an inflection specified in `field`, the name of a parameter holding an inflection. If the parameter is numeric, the field should be given as a number (as with the `params` structure passed to [[Module:parameters]]), not a string containing the representation of a number. The field can specify multiple comma-separated terms, and each term can have associated inline modifiers that will be parsed (unless there is top-level HTML in the parameter, i.e. HTML not contained inside an inline modifier, e.g. as may be generated by using {{tl|l}} or similar template inside a parameter). This is a wrapper around the top-level `parse_term_with_modifiers()` function. `props` is an optional structure containing additional properties, including all additional properties documented for the top-level `parse_term_with_modifiers()` function. If the parameter in `field` is unspecified, the return value of this function will be an empty list, not {nil}, so it is always safe to iterate over the return value. By default, the allowed modifiers are the same as for `parse_term_with_modifiers()`, except that (normally) the `<tr:...>` modifier will be allowed if `include_tr` was specified in the original call to `process_headword()`; likewise for the `<ts:...>` modifier if `include_ts` was specified and the `<sc:...>` modifier if `include_sc` was specified. If If you pass in your own `include_mods` list of additional allowed modifiers, it will (normally) automatically be augmented with {"tr"}, {"ts"} and/or {"sc"} if `include_tr`, `include_ts` and/or `include_sc` was specified when calling `process_headword()`. To disable automatic augmentation of these modifiers (whether or not you specify an `include_mods` property), specify {no_augment_include_mods = true} in `props`. ]==] function Headdata:parse_inflection(field, props) local val = self.process_props.args[field] if not val then return {} end props = props and shallow_copy(props) or {} local include_mods = props.include_mods local data = self.process_props.data if not props.no_augment_include_mods and (data.include_tr or data.include_ts or data.include_sc) then include_mods = include_mods and shallow_copy(include_mods) or {} if data.include_tr then insert_if_not(include_mods, "tr") end if data.include_ts then insert_if_not(include_mods, "ts") end if data.include_sc then insert_if_not(include_mods, "sc") end end props.val = val props.paramname = field props.splitchar = props.splitchar or "," props.include_mods = include_mods return export.parse_term_with_modifiers(props) or {} end --[==[ Insert previously-parsed terms into the `inflections` of the headword `data` structure. This is a wrapper around the top-level `insert_inflection()` function. `terms` is the list of parsed terms. (If {nil}, nothing happens unless `request` is set in `props`.) `label` is the the label that the inflections are given; any parts of the label surrounded in `<<...>>` are linked to the glossary. (If the contents of `<<...>>` contain a `|` in them, they are a two-part link.) `props` is an optional structure containing additional properties, including all additional properties documented for the top-level `insert_inflection()` function. Unless `no_auto_cats` is given in `props`, certain labels automatically trigger the insertion of additional categories in specific circumstances. This is controlled by the `inflection_to_cats` structure in [[Module:headword utilities]]. For example, if the part of speech is {"nouns"} or {"proper nouns"} and the label (after removing any links and `<<...>>` glossary specs) is {"plural"}, an additional category <code><var>lang</var> countable nouns</code> will be added if a plural value is given (i.e. the value is not {"-"}). If the value is {"-"} (which indicates that there is no plural and triggers the insertion of the fixed inflection label {"no plural"}), <code><var>lang</var> uncountable nouns</code> will be inserted instead, and if both {"-"} and a value are given (which triggers the insertion of the {"usually no plural"} fixed inflection label), both categories are added. Similar categories are inserted when a comparative is given (with a label {"comparative"}), and if the label is {"female equivalent"} or {"male equivalent"} and the value is not {"-"}, a category such as <code><var>lang</var> nouns with other-gender equivalents</code> is inserted. ]==] function Headdata:insert_inflection(terms, label, props) props = props and shallow_copy(props) or {} if not props.no_auto_cats then local bare_label = label if bare_label:find("[[", nil, true) then bare_label = require(links_module).remove_links(bare_label) end if bare_label:find("<<", nil, true) then bare_label = bare_label:gsub("<<.-|(.-)>>", "%1"):gsub("<<(.-)>>", "%1") end local cats = inflection_to_cats[bare_label] if cats then if not cats.filter_plpos or cats.filter_plpos(self:get_canonicalized_plpos()) then if props.cats == nil then props.cats = self:canonicalize_categories(cats.cats) end if props.usually_no_cats == nil then props.usually_no_cats = self:canonicalize_categories(cats.usually_no_cats) end if props.no_cats == nil then props.no_cats = self:canonicalize_categories(cats.no_cats) end end end end props.headdata = self props.terms = terms props.label = label return export.insert_inflection(props) end --[==[ Insert a "fixed" inflection (a label without associated values) into the `inflections` table of the headword `data` structure, labeled according to `label` (which can have glossary links in it specified using `<<...>>`, exactly as for `:insert_inflection()`). An example label (from {{tl|mn-noun}} in [[Module:mn-headword]]) is {"hidden-g declension"}, specifying that the noun belongs to the hidden-''g'' declension. This is a direct wrapper around the top-level function `insert_fixed_inflection()`; see that function for more details on optional `props`. ]==] function Headdata:insert_fixed_inflection(label, props) props = props and shallow_copy(props) or {} props.headdata = self props.label = label export.insert_fixed_inflection(props) end --[==[ Parse the inflection(s) specified in `field` and insert them into the `inflections` table of the headword `data` structure, labeled according to `label`. This is equivalent to calling {terms = data:parse_inflection(field, props)} followed by {return data:insert_inflection(terms, label, props)} and behaves the same as the combination of those two functions. See their documentation for more details. ]==] function Headdata:parse_and_insert_inflection(field, label, props) local terms = self:parse_inflection(field, props) return self:insert_inflection(terms, label, props) end --[==[ Generate an inflection that may be specified explicitly or defaulted (which involves looping over the specified or defaulted heads and determining the script of each one, since the formation of the default depends on the script). `data` is the data object passed into the POS handler. `terms` is the list of terms to process. Those where the term itself is not `+` will be returned unchanged, while those where the term is `+` will be handled by generating the appropriate inflections from the headwords using `make_inflection` (which is passed three arguments, `head`, `tr` and `sccode`, i.e. the script code of `head`) and should return two values, term and translit, either of which can be nil. A nil head will be ignored, and otherwise the decorations specified on the `+` term will be combined with the decorations specified on the head. The return value is a list of inflections where no requests for the default inflection remain. ]==] function Headdata:resolve_special(terms, handle_special, props) props = props or {} local infls = {} local is_special = props.is_special or function(_data, infl) return infl.term == "+" end for _, termobj in ipairs(terms) do if not is_special(self, termobj) then insert(infls, termobj) else for _, headobj in ipairs(self.heads) do local head = headobj.term or self.pagename local head_no_links if props.with_links then head = head:find("%[") and head or require(headword_module).add_multiword_links(head, not headobj.term) head_no_links = require(links_module).remove_links(head) else head = require(links_module).remove_links(head) head_no_links = head end local newterms = handle_special { head = head, tr = headobj.tr, infl = termobj, sc = self.lang:findBestScript(head_no_links), } if newterms then newterms = export.canonicalize_termobj_list(newterms, "term", "resolve_special") for _, newterm in ipairs(newterms) do if not props.no_combine_handle_special_retval_with_origin then export.combine_termobj_decorations(newterm, termobj) end if not props.no_combine_handle_special_retval_with_head then export.combine_termobj_decorations(newterm, headobj) end insert(infls, newterm) end end end end end return infls end --[==[ Add the current page to a tracking page named `Wiktionary:Tracking/``lang``-headword/``page```, where ``lang`` is the language code of the current language. For example, if the current language is `mak` and `page` is {"redundant-lon"}, the current page will get added to the tracking page `Wiktionary:Tracking/mak-headword/redundant-lon`. All pages added to that tracking page can be seen by going to [[Special:WhatLinksHere/Wiktionary:Tracking/mak-headword/redundant-lon]]. This is typically used to track issues occurring in user-specified parameters that do not rise to the level of errors (e.g. redundant parameters, deprecated usages or other dispreferred values). ]==] function Headdata:track(page) return require(debug_track_module)(self.langcode .. "-headword/" .. page) end local boolean_param = {type = "boolean"} --[==[ Process an arbitrary headword in an arbitrary language, handling generic and language-specific arguments and calling `full_headword()` in [[Module:headword]]. This is intended for use in implementing headword modules (e.g. [[Module:uz-headword]] for Uzbek, [[Module:mn-headword]] for Uzbek, [[Module:gsw-headword]] for Alemannic German, etc.) and provides a general implementation of such modules. On input, `data` is an object with the following fields: * `lang`: The language object of the language being handled. '''Required.''' Use the special value {false} to indicate that the language is specified by the user in {{para|1}}. * `frame`: The frame object passed into the `show()` function of your module, which implements headword-handling for all parts of speech in the module, including a generic POS-handling template (e.g. {{tl|uz-head}} or {{tl|mn-head}}), which allows arbitrary parts of speech to be handled. '''Required.''' * `pos_functions`: A table listing, for each part of speech requiring special handling, the extra parameters (if any) that the part of speech accepts, along with how to handle them. See the examples below. '''Required.''' * `validate_lang`: If {lang = true} is specified, this is a function of one argument (a language object, based on the language specified in {{para|1}}) that should throw an error if the language object is disallowed. If omitted, all languages are allowed. * `numbered_head`: If true, explicit headwords are specified in a numbered param instead of in {{para|head}}. The param used is usually {{para|1}}, but is {{para|2}} for generic POS templates such as {{tl|mn-head}} or for POS-specific templates when {lang = true} is specified (e.g. {{tl|arb-noun}}), and is {{para|3}} for generic POS templates when {lang = true} is spcified (e.g. {{tl|arb-head}}). * `include_tr`: If true, allow explicit transliterations to be specified. The transliteration(s) for the headword(s) themselves is/are specified in {{para|tr}} or through the {{cd|<tr:...>}} inline modifier on headwords, and transliterations of inflections are specified through the {{cd|<tr:...>}} inline modifier. This should generally be given when a headword for the language may be in a script other than Latin. * `include_ts`: If true, allow explicit transcriptions to be specified. The transcription(s) for the headword(s) themselves is/are specified in {{para|ts}} or through the {{cd|<ts:...>}} inline modifier on headwords, and transcriptions of inflections are specified through the {{cd|<ts:...>}} inline modifier. This should generally only be given for certain languages where the spelling is radically different from the pronunciation (e.g. in cuneiform languages such as Hittite and Akkadian, and potentially in Tibetan), and represents a pronunciation-based rendering (usually not direct IPA). * `include_sc`: If true, allow an explicit script code to be specified. The overall script code for the headword(s) themselves can be specified using {{para|sc}}, and per-headword or per-inflection script codes are specified using the {{cd|<sc:...>}} inline modifier. This should generally be given when a language supports multiple scripts. * `infls`: An inflections structure specifying extra generic parameters that apply to all parts of speech and how to handle them. The format is the same as for the `infls` structure in `pos_functions`. * `augment_params`: A callback function to add extra generic parameters, or modify existing generic parameters in the `params` structure; but in general, extra generic parameters should be added through the `infls` structure instead. This callback should not be used to add part-of-speech-specific parameters; those are handled through the appropriate setting in `pos_functions`. It is passed two single arguments, the `headdata` object and the `params` table to be augmented. See below for extra fields stored in the `process_props` structure of the `headdata` object. This function is called after initializing the `params` table and processing the overall `infls` structure, but just before adding part-of-speech-specific parameters (from `pos_functions`) to `params`. Thus, it can override any generic parameters but may itself be overridden by a part-of-speech-specific parameter. * `augment_headdata`: A callback function to modify the `headdata` object passed to `full_headword()` in [[Module:headword]]. This should not be used to for part-of-speech-specific parameter handling; this is handled through the appropriate setting in `pos_functions`. It is passed a single argument, the `headdata` object, as for `augment_params`; but the `process_props` structure and other fields will be more filled out, as this callback is called later. This can be used, for example, to override the value of a generic setting in `headdata` (e.g. [[Module:uz-headword]] uses this to mark non-Latin terms as variant forms by setting `headdata.var`, being careful not to override a value already set by the user). This function is called after initializing the `headdata` table with all information taken from generic parameters and processing generic parameters specified in the overall `infls` structure, and just before processing the appropriate part-of-speech-specific `infls` structure in `pos_functions` (which in turn is followed by any handler function in `pos_functions`). Thus, it can override any value set during generic parameter processing but may itself be overridden by a part-of-speech-specific parameter or handler. * `force_cat`: If true, add the headword to the appropriate categories even on non-mainspace pages. This can be used for testing category handling in sample template calls on userspace test pages or template documentation pages. It should not be set in production code. * `enable_auto_translit`: If true, turn on automatic transliteration of inflections at a global level (i.e. applying to all inflections). This has no effect on headwords, which are automatically transliterated by default if in a non-Latin script and automatic transliteration is available for the language. You can also set this value for particular inflections in the `insert_inflection()` function. The `headdata` headword data structure has an extra field in it called `process_props` that is specific to the `process_headword()` function, containing various extra properies. As the operation of `process_headword()` proceeds, this object gets filled out with more fields. For example, once parameter parsing happens, the resulting values are available in the `args` field of `process_props`. The following fields are found in `process_props` (note that `poscat`, the canonicalized plural part of speech of the headword being processed, is *not* present here; it's directly on `headdata`): * `namespace`: The name of the current namespace; an empty string for the mainspace. This references the namespace of the actual page and isn't affected by the {{para|pagename}} parameter. * `indexing_poscat`: The canonicalized part of speech of the headword used to index into `pos_functions`. This is the same as `poscat` for specific part-of-speech templates such as {{tl|uz-noun}}, but has the value {"head"} for generic part-of-speech templates such as {{tl|uz-head}}. (Note that `poscat` is directly available on `headdata`.) * `generic_pos_template`: True if a generic POS templates like {{tl|uz-head}} or {{tl|mn-head}} was used. (This is signaled by omitting the invocation parameter {{para|1}} to `process_headword`.) * `lang_in_1`: True if the language code is to be fetched from {{para|1}}. * `pos_param`: The parameter holding the part of speech, if a generic POS tempalte like {{tl|mn-head}} is being processed (i.e. `generic_pos_template` is set). In such a case, it will have the value of {1} or {2}, depending on whether the language code is being fetched from {{para|1}} (see `lang_in_1`). Otherwise it will be {nil}. * `head_param`: The parameter holding the explicit headword. If `numbered_head` was specified (as for Mongolian headword templates), this has the value {1}, {2} or {3} depending on whether the language code is being fetched from {{para|1}} (see `lang_in_1`) and whether a generic POS template like {{tl|mn-head}} is being processed (see `generic_pos_template`). Otherwise, it has the value {"head"}. Also see the `lang` and `numbered_head` properties in the `data` structure sent to `process_headword()`. * `is_suffix`: True if the current term is a suffix. This is set when processing the `suffix`, `nosuffix` and `clitic` parameters; it is always {false} beforehand (i.e. during `augment_params` and processing of the general `infls` structure). * `insert_specs`: This is a table mapping parameter names to the return value of `Headdata:insert_inflection()`, filled out as parameter values are processed. This lets a given parameter processing function in `infls` gain access to the result of calling `insert_inflection()` on previous parameters (which indicates the number of items inserted as well as whether `-` was specified). The `pos_functions` table contains an entry for each part of speech needing special handling, where the key is the canonical plural part of speech (e.g. {"adverbs"} or {"proper nouns"}). The value associated with each key is a table normally containing a field `infls`, listing the extra part-of-speech-specific inflection and other parameters along with how to handle them. The specs in `infls` are used in three ways: # to augment the `params` object passed to the `process()` function in [[Module:parameters]], specifying how to parse the appropriate inflectional parameters; # to specify how to process any inflectional parameters given and insert them into the `headdata` object passed to `full_headword()` in [[Module:headword]]; # to generate appropriate documentation for the parameters and other changes made by the headword template (e.g. inserting categories). Alternatively, you can separately control the augmentation of the `params` object and the procesing of the resulting arguments. This is done by specifying two fields in place of `infls`, named `params` and `func`. `params` is a table containing extra parameters to add to the overall `params` object passed to the `process()` function in [[Module:parameters]]. `func` is a function of two arguments, normally called `data` (the headword data structure `headdata`) and `args` (the processed arguments table). However, this alternative method is not normally recommended because it leads to duplication between the `params and `func` fields and the documentation, which must be manually specified. A simple example, as used to handle pronouns for Turoyo, is { local valid_genders = {"m", "f", "m-p", "f-p", "p", "?"} pos_functions["pronouns"] = { infls = { {2, type = "genders", validate = valid_genders}, {"f", label = "feminine"}, {"pl", label = "plural"}, }, } } The equivalent using `params` and `func` is { local valid_genders = {"m", "f", "m-p", "f-p", "p", "?"} pos_functions["pronouns"] = { params = { [2] = {type = "genders"}, f = true, pl = true, }, func = function(data, args) data:validate_genders(args[2], valid_genders) data.genders = args[2] data:parse_and_insert_inflection("f", "feminine") data:parse_and_insert_inflection("pl", "plural") end } } Note how the version with separate `params and `func` is longer and splits information on the parameters between the two fields. The `params` structure sets extra user-specifiable parameters {{para|2}} for genders (since the headword is in {{para|1}}) as well a {{para|f}} and {{para|pl}}, and the `func` handler processes those parameters. Note how this is done by calling methods on the headword `data` structure. Each such parameter can have multiple comma-separated values, and each value can have inline modifiers attached to it to specify further properties of the value. The `infls` version ends up making the same method calls, but does it for you instead of you having to do it yourself. These methods are implemented through a metatable set on the headword `data` structure, which is removed before calling `full_headword()` in [[Module:headword]]. The methods access extra information related to headword processing (such as the `args` table) that is stored in the `process_props` field of the headword `data` strucuture. This field is also removed prior to calling `full_headword()`. The methods available on the headword `data` structure are as follows. Each one also has its own documentation. * {parse_inflection(field, props)}: Parse value(s) specified in `field` (a user-specified parameter in the `args` table) and return a list of term objects. Optional `props` specifies additional properties controlling the parsing. * {insert_inflection(terms, label, props)}: Insert the terms in `terms` (a list of term objects as returned by `parse_inflection()`) into the `inflections` list in the headword `data` structure, giving the inflection the label as specified in `label`. Optional `props` specifies additional properties controlling the parsing. * {parse_and_insert_inflection(field, label, props)}: A combination of `parse_inflection()` and `insert_inflection()`, if no further processing of the parsed values needs to be done before insertion. * {insert_fixed_inflection(label, props)}: Insert a "fixed" inflection (a label without associated values) into the `inflections` table. An example (from {{tl|mn-noun}} in [[Module:mn-headword]]) is {"hidden-g declension"}, specifying that the noun belongs to the hidden-''g'' declension. * {resolve_special(terms, handle_special, props)}: Resolve "special" indicators as specified by the user in an inflection parameter. A typical example is {"+"}, requesting a default value. `terms` is the list of parsed term objects and `handle_special` is a handler function to process special indicators and convert them to their actual values. * {validate_genders(genders, valid_genders, props)}: Validate that the user-specified genders in `genders` all belong to the list given in `valid_genders`, throwing an error if not. * {insert_category(category)}: Insert a category into the `categories` list in the headword `data` structure. `category` is normally a string naming the category, which will have the language prepended to it and any occurrences of `{plpos}` in the string replaced with the actual plural part of speech. ]==] function export.process_headword(data) local lang, frame, pos_functions, validate_lang, numbered_head, include_tr, include_ts, include_sc, force_cat, enable_auto_translit, infls, augment_params, augment_headdata = data.lang, data.frame, data.pos_functions, data.validate_lang, data.numbered_head, data.include_tr, data.include_ts, data.include_sc, data.force_cat, data.enable_auto_translit, data.infls, data.augment_params, data.augment_headdata local iparams = { [1] = true, def = true, } local iargs = require(parameters_module).process(frame.args, iparams) local parargs = frame:getParent().args local langcode if not lang then error("Internal error: `data.lang` must be specified; either a language object or `true` for a user-specified language") end local lang_in_1 if lang == true then lang_in_1 = true langcode = ine(parargs[1]) if langcode then langcode = mw.text.trim(langcode) lang = require(languages_module).getByCode(langcode, 1, true) if validate_lang then validate_lang(lang) end else error("Language code (see [[WT:Language codes]]) must be specified in 1=") end else langcode = lang:getCode() if validate_lang then error("Internal error: `data.validate_lang` must not be specified if a language code is given in `data.lang`") end end local poscat = iargs[1] local generic_pos_template = not poscat local pos_param if generic_pos_template then pos_param = lang_in_1 and 2 or 1 poscat = ine(parargs[pos_param]) or mw.title.getCurrentTitle().fullText == ("Template:%s-head"):format(langcode) and "interjection" or error(("Part of speech must be specified in %s="):format(pos_param)) poscat = require(headword_module).canonicalize_pos(poscat) end local head_param = numbered_head and (generic_pos_template and lang_in_1 and 3 or (generic_pos_template or lang_in_1) and 2 or 1) or "head" local indexing_poscat = generic_pos_template and "head" or poscat local namespace = mw.loadData(headword_data_module).page.namespace -- Partly initialize headdata now for use in generic infls callbacks. Will be further initialized later after -- processing parameters. local headdata = { lang = lang, langcode = langcode, langfullcode = lang:getFullCode(), langname = lang:getCanonicalName(), langfullname = lang:getFullName(), process_props = { namespace = namespace, data = data, indexing_poscat = indexing_poscat, generic_pos_template = generic_pos_template, lang_in_1 = lang_in_1, pos_param = pos_param, head_param = head_param, is_suffix = false, insert_specs = {}, }, pos_category = poscat, orig_poscat = poscat, -- preserve user-specified poscat in case pos_category is changed to 'suffixes' categories = {}, inflections = {enable_auto_translit = enable_auto_translit}, force_cat_output = force_cat, no_redundant_head_cat = true, } setmetatable(headdata, {__index = Headdata}) local params = { [head_param] = {template_default = iargs.def}, head2 = {replaced_by = false, instead = ("use comma-separated |%s="):format(head_param)}, id = true, sort = true, cat = true, nolink = boolean_param, nolinkhead = {type = "boolean", alias_of = "nolink"}, suffix = boolean_param, nosuffix = boolean_param, clitic = true, addlpos = true, var = {type = "boolean", allow = {"both"}}, json = boolean_param, pagename = true, -- for testing } if include_sc then params.sc = {type = "script"} end if include_tr then params.tr = true params.tr2 = {replaced_by = false, instead = "use comma-separated |tr= or <tr:...> inline modifier on head"} end if include_ts then params.ts = true params.ts2 = {replaced_by = false, instead = "use comma-separated |ts= or <ts:...> inline modifier on head"} end if lang_in_1 then params[1] = {required = true} -- required but ignored as already processed above end if generic_pos_template then params[pos_param] = {required = true} -- required but ignored as already processed above end local function resolve_prop(prop, ...) if type(prop) == "function" then prop = prop(headdata, ...) end return prop end local function augment_params_from_infls(infls) infls = resolve_prop(infls) for _, infl in ipairs(infls) do local function interr(txt) error(("Internal error: %s (coming from infls spec %s)"):format(txt, dump(infl))) end local param = infl[1] if param then param = resolve_prop(param) if type(param) ~= "string" and type(param) ~= "number" then interr(("Parameter name %s must be a string or number"):format(dump(param))) end -- We handle defaults as well as validation ourselves. local typ = resolve_prop(infl.type) or "string" if typ ~= "genders" and typ ~= "boolean" and typ ~= "string" then -- FIXME: Handle more types. interr(('Unrecognized type %s; can only currently handle "genders", "boolean" and "string" (the default)'):format( dump(typ))) end params[param] = {type = typ, required = resolve_prop(infl.required), template_default = resolve_prop(infl.template_default)} if typ ~= "boolean" and type(param) == "string" then params[param .. "2"] = {replaced_by = false, instead = ("use comma-separated |%s="):format(param)} end end end end if infls then augment_params_from_infls(infls) end if augment_params then augment_params(headdata, params) end if pos_functions[indexing_poscat] then local pos_infls = pos_functions[indexing_poscat].infls if pos_infls then augment_params_from_infls(pos_infls) end local pos_params = pos_functions[indexing_poscat].params if pos_params then for key, val in pairs(pos_params) do params[key] = val end end end local args = require("Module:parameters").process(parargs, params) local pagename = args.pagename or mw.loadData(headword_data_module).pagename local sc = args.sc or lang:findBestScript(pagename) headdata.pagename = pagename headdata.process_props.args = args headdata.sc = sc headdata.id = args.id headdata.sort = args.sort -- No redundant script cat unless the user explicitly gave sc= headdata.no_script_code_cat = not args.sc headdata.var = args.var local extra_term_mods = {} if include_tr then insert(extra_term_mods, "tr") end if include_ts then insert(extra_term_mods, "ts") end if include_sc then insert(extra_term_mods, "sc") end if not extra_term_mods[1] then extra_term_mods = nil end local trs = args.tr and split_on_comma(args.tr) or {} local num_trs = #trs local tss = args.ts and split_on_comma(args.ts) or {} local num_tss = #tss local heads = args[head_param] and export.parse_term_with_modifiers { val = args[head_param], paramname = head_param, splitchar = ",", is_head = true, include_mods = extra_term_mods, } or {} local num_heads = #heads if num_heads > 0 and num_trs > 0 and num_heads ~= num_trs then error(("%s head%s specified explicitly but %s translit%s; they must match; use '+' to stand for the default head (the pagename) or default automatic translit and '-' to stand for no translit"):format( num_heads, num_heads > 1 and "s" or "", num_trs, num_trs > 1 and "s" or "")) end if num_heads > 0 and num_tss > 0 and num_heads ~= num_tss then error(("%s head%s specified explicitly but %s transcription%s; they must match; use '+' to stand for the default head (the pagename) and '-' to stand for no transcription"):format( num_heads, num_heads > 1 and "s" or "", num_tss, num_tss > 1 and "s" or "")) end if num_trs > 0 and num_tss > 0 and num_trs ~= num_tss then error(("%s translit%s specified explicitly but %s transcription%s; they must match; use '+' to stand for default automatic translit and '-' to stand for no translit or transcription"):format( num_trs, num_trs > 1 and "s" or "", num_tss, num_tss > 1 and "s" or "")) end -- Be careful here not to overwrite user_specified_heads if it's empty so we can later check user_specified_heads -- to see if the user provided any heads. local max_tr_ts = math.max(num_trs, num_tss) if num_heads == 0 and max_tr_ts > 0 then heads = {} for i = 1, max_tr_ts do heads[i] = {term = "+"} end end if not heads[1] then heads = {{term = "+"}} end for i, headobj in ipairs(heads) do if headobj.tr and trs[i] then if headobj.tr ~= trs[i] then error(("Saw two different translits '%s' and '%s' for head #%s"):format( headobj.tr, trs[i], i)) end else headobj.tr = headobj.tr or trs[i] end if headobj.tr == "+" then headobj.tr = nil end if headobj.ts and tss[i] then if headobj.ts ~= tss[i] then error(("Saw two different transcriptions '%s' and '%s' for head #%s"):format( headobj.ts, tss[i], i)) end else headobj.ts = headobj.ts or tss[i] end if headobj.ts == "-" then headobj.ts = nil end if headobj.term == "+" then headobj.term = args.nolink and pagename or nil if headobj.term and namespace == "Reconstruction" then headobj.term = "*" .. headobj.term end end end headdata.heads = heads local function pagename_is_suffix() if sc:getCode() == "Latn" then -- shortcut Latin terms to avoid unnecessarily loading [[Module:affix]] return pagename:find("^%-") and not pagename:find("%-$") else local affix_type, _, _, _ = require(affix_module).parse_term_for_affixes(pagename, lang, sc) return affix_type == "suffix" end end local clitic_label if args.clitic then clitic_label = require(yesno_module)(args.clitic, args.clitic) end if clitic_label == true then clitic_label = "clitic" end if clitic_label then headdata:insert_category("clitics") headdata:insert_fixed_inflection(clitic_label) elseif args.suffix or ( not args.nosuffix and pagename_is_suffix() and poscat ~= "suffixes" and poscat ~= "suffix forms" ) then headdata.process_props.is_suffix = true local function handle_suffix_pos(pos, is_first) local form_type = pos:match("^(.*) forms$") local actual_poscat if form_type then headdata:insert_category(("%s suffix forms"):format(form_type)) headdata:insert_fixed_inflection(form_type .. " suffix form") else local singular_pos = require(en_utilities_module).singularize(pos) headdata:insert_category(("%s-forming suffixes"):format(singular_pos)) headdata:insert_fixed_inflection(singular_pos .. "-forming suffix") end local postype = require(headword_module).pos_lemma_or_nonlemma(pos) if not postype then error(("Unrecognized canonicalized part of speech '%s' in addlpos=, cannot determine whether lemma or non-lemma form"):format( pos )) end actual_poscat = postype == "lemma" and "suffixes" or "suffix forms" if is_first then headdata.pos_category = actual_poscat elseif headdata.pos_category ~= actual_poscat then error(("Cannot mix suffixes and suffix forms using addlpos=; '%s' is a %s while overall POS '%s' is a %s; use separate POS headers for the two"): format(pos, actual_poscat, poscat, headdata.pos_category)) end end handle_suffix_pos(poscat, true) if args.addlpos then for _, addlpos in ipairs(split(args.addlpos, "%s*,%s*")) do addlpos = require(headword_module).canonicalize_pos(addlpos) handle_suffix_pos(addlpos, false) end end end if args.cat then for _, cat in ipairs(split_on_comma(args.cat)) do headdata:insert_category(cat) end end local function augment_headdata_from_infls(infls) infls = resolve_prop(infls) for _, infl in ipairs(infls) do local function interr(txt) error(("Internal error: %s (coming from infls spec %s)"):format(txt, dump(infl))) end local function process_labelobjs(labelobjs, originating_term, handle_labelobj) if labelobjs == nil then return end if type(labelobjs) ~= "string" and type(labelobjs) ~= "table" then interr(("Wrong type '%s' for label object(s) %s, expected string or table"):format( type(labelobjs), dump(labelobjs) )) end if type(labelobjs) == "string" or type(labelobjs) == "table" and not labelobjs[1] then labelobjs = {labelobjs} end for _, labelobj in ipairs(labelobjs) do local label, termobj if type(labelobj) == "string" then label = labelobj termobj = originating_term elseif type(labelobj) ~= "table" then interr(("Wrong type '%s' for label object %s, expected string or table"):format( type(labelobj), dump(labelobj) )) label = labelobj.term if type(label) ~= "string" then interr(("Wrong type '%s' for label %s from label object %s, expected string"):format( type(label), dump(label), dump(labelobj) )) end termobj = labelobj end handle_labelobj(label, termobj) end end local param = infl[1] if param then local vals -- Fetch the param and make sure it's a string or number. param = resolve_prop(param) if type(param) ~= "string" and type(param) ~= "number" then interr(("Parameter name %s must be a string or number"):format(dump(param))) end -- Fetch the type and validate. local typ = resolve_prop(infl.type) if typ == nil then typ = "string" end if typ ~= "genders" and typ ~= "boolean" and typ ~= "string" then -- FIXME: Handle more types. interr(('Unrecognized type %s; can only currently handle "genders", "boolean" and "string" (the default)'):format( dump(typ))) end -- Fetch the value(s). if typ == "genders" or typ == "boolean" then vals = args[param] elseif typ == "string" then local parse_inflection_props = resolve_prop(infl.parse_inflection_props) local include_mods = resolve_prop(infl.include_mods) local no_augment_include_mods = resolve_prop(infl.no_augment_include_mods) if include_mods ~= nil or no_augment_include_mods ~= nil then if parse_inflection_props == nil then parse_inflection_props = {} else parse_inflection_props = shallow_copy(parse_inflection_props) end if include_mods ~= nil then parse_inflection_props.include_mods = include_mods end if no_augment_include_mods ~= nil then parse_inflection_props.no_augment_include_mods = no_augment_include_mods end end vals = headdata:parse_inflection(param, parse_inflection_props) -- Convert an empty list to nil for consistent checking below. if not vals[1] then vals = nil end else interr(("Unrecognized type '%s"):format(typ)) end -- If value(s) nil, fetch the default. if vals == nil and infl.default ~= nil then local default = resolve_prop(infl.default) if typ == "genders" then vals = export.canonicalize_termobj_list(default, "spec", "default") elseif typ == "boolean" then vals = default elseif typ == "string" then vals = export.canonicalize_termobj_list(default, "term", "default") else interr(("Unrecognized type '%s"):format(typ)) end end -- Resolve "special" values (special signals a string values, such as requesting the default with "+"). if vals ~= nil and infl.resolve_special then if typ ~= "string" then interr(("Cannot specify resolve_special= for type %s"):format(dump(typ))) end local resolve_special_props = resolve_prop(infl.resolve_special_props, vals) if infl.is_special ~= nil then if resolve_special_props == nil then resolve_special_props = {} else resolve_special_props = shallow_copy(resolve_special_props) end resolve_special_props.is_special = infl.is_special end vals = headdata:resolve_special(vals, infl.resolve_special, resolve_special_props) end -- Validate the value(s). if vals ~= nil and infl.validate ~= nil then if typ == "boolean" then interr('Cannot specify validate= when type is "boolean"') elseif type(infl.validate) == "function" then infl.validate(headdata, vals) elseif typ == "genders" then headdata:validate_genders(vals, infl.validate) elseif typ == "string" then validate_items { items = vals, field = "term", valid_items = infl.validate, item_type = ("values in |%s="):format(param), } else interr(("Unrecognized type '%s"):format(typ)) end end -- Run the process_after_parse handler, if it exists. if vals ~= nil and infl.process_after_parse ~= nil then local intentionally_nil vals, intentionally_nil = infl.process_after_parse(headdata, vals) if vals == nil and not intentionally_nil then interr("If you return nil from process_after_parse, you must return a second non-nil return " .. "value to indicate that the nil return value was intentional") end end -- "Implement" the values, if non-falsy (i.e. we don't want to fire on boolean false or empty list). -- If a fixed label is specified, insert it. Then, depending on the type, attach the values to a label -- as an inflection, set the `genders` field, or do nothing if boolean (throwing an error if there was -- no fixed label). if vals == true or type(vals) == "table" and vals[1] then if infl.fixed_label and infl.all_fixed_label then interr("Cannot specify both fixed_label= and all_fixed_label=; specify one or the other") end local function check_fixed_label_references_val(label) if type(label) == "table" and label[1] then for _, lab in ipairs(label) do if check_fixed_label_references_val(lab) then return true end end return false end if type(label) == "table" then if not label.term then interr(("Fixed label structure %s does not have a value for `.term`"):format(dump(label))) end label = label.term end if type(label) ~= "string" then interr(("Wrong type for fixed label %s, should be string"):format(type(label))) end return not not label:find("{val}") end local fixed_label = infl.fixed_label local all_fixed_label = infl.all_fixed_label -- If the value being processed is boolean, there's only one value so treat a fixed_label as an -- all_fixed_label and output only once; likewise if the caller specified a fixed_label without -- {val} in it. if fixed_label and (typ == "boolean" or type(fixed_label) ~= "function" and not check_fixed_label_references_val(fixed_label)) then all_fixed_label = fixed_label fixed_label = nil end local inserted_fixed_label if fixed_label then if typ == "boolean" then interr("Boolean fixed_label values should have been converted to all_fixed_label") end for _, valobj in ipairs(vals) do local labelobjs = resolve_prop(fixed_label, valobj) process_labelobjs(labelobjs, valobj, function(label, termobj) if label:find("{val}") then if typ ~= "string" then interr(('Cannot specify {val} in fixed_label %s when type is "%s"'):format(dump(label), typ)) end label = label:gsub("{val}", replacement_escape(valobj.term)) end headdata:insert_fixed_inflection(label, { originating_term = termobj }) inserted_fixed_label = true end) end elseif all_fixed_label then local labelobjs = resolve_prop(all_fixed_label, vals) process_labelobjs(labelobjs, nil, function(label, termobj) if label:find("{vals}") then if typ ~= "string" then interr(('Cannot specify {vals} in all_fixed_label %s when type is "%s"'):format(dump(label), typ)) end local formatted_labels = {} for _, valobj in ipairs(vals) do insert(formatted_labels, add_decorations(valobj.term, valobj, lang)) end label = label:gsub("{vals}", replacement_escape(serial_comma_join(formatted_labels))) end headdata:insert_fixed_inflection(label, termobj) inserted_fixed_label = true end) end local inserted_vals if infl.label ~= nil then if typ ~= "string" then interr(("label=%s can only be specified for type 'string', not '%s'"):format( dump(infl.label), typ )) end local label = resolve_prop(infl.label, vals) if label ~= nil then local insert_inflection_props = resolve_prop(infl.insert_inflection_props, vals) local no_auto_cats = resolve_prop(infl.no_auto_cats, vals) if no_auto_cats ~= nil then if insert_inflection_props == nil then insert_inflection_props = {} else insert_inflection_props = shallow_copy(insert_inflection_props) end insert_inflection_props.no_auto_cats = infl.no_auto_cats end local insert_spec = headdata:insert_inflection(vals, label, insert_inflection_props) headdata.process_props.insert_specs[param] = insert_spec inserted_vals = true end end if typ == "genders" then headdata.genders = vals end local inserted_cat if infl.cat then local allcats = {} for _, valobj in ipairs(vals) do local cats = resolve_prop(infl.cat, valobj) if type(cats) == "string" then cats = {cats} end if cats ~= nil then for _, cat in ipairs(cats) do if cat:find("{val}") then cat = cat:gsub("{val}", replacement_escape(valobj.term)) end insert_if_not(allcats, cat) end end end for _, cat in ipairs(allcats) do headdata:insert_category(cat) inserted_cat = true end end if typ == "boolean" then if not inserted_fixed_label and not inserted_cat then interr(("User set boolean setting for %s= but no fixed label added and no category " .. "inserted; if you took action in process_after_parse(), make sure to return " .. "`nil, true`"):format(param)) end elseif typ == "string" then if not inserted_vals and not inserted_fixed_label then interr(("User set value(s) %s for %s= but no inflection inserted and no fixed label " .. "added; if you took action in process_after_parse(), make sure to return " .. "`nil, true`"):format(dump(vals), param)) end end end else -- no param specified if infl.label or infl.all_fixed_label then interr("Cannot have label= or all_fixed_label= without specifying a param") end if infl.fixed_label then local labelobjs = resolve_prop(infl.fixed_label) process_labelobjs(labelobjs, nil, function(label, termobj) if label:find("{val}") then interr("Cannot specify {val} in a fixed_label= value without specifying a param") end headdata:insert_fixed_inflection(label, { originating_term = termobj }) end) end if infl.cat then local cats = resolve_prop(infl.cat) if type(cats) == "string" then cats = {cats} end if cats ~= nil then for _, cat in ipairs(cats) do if cat:find("{val}") then interr("Cannot specify {val} in a cat= value without specifying a param") end headdata:insert_category(cat) end end end end end end if infls then augment_headdata_from_infls(infls) end if augment_headdata then augment_headdata(headdata, args) end if pos_functions[indexing_poscat] then local pos_infls = pos_functions[indexing_poscat].infls if pos_infls then augment_headdata_from_infls(pos_infls) end local func = pos_functions[indexing_poscat].func if func then func(headdata, args) end end setmetatable(headdata, nil) if args.json then return require("Module:JSON").toJSON(headdata) end headdata.process_props = nil return require(headword_module).full_headword(headdata) end return export ou0y7dxffzgvhrvsgvx5tbty4giij9y Padron:orthography 10 33948 178021 165462 2026-09-21T16:34:05Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Padron:ortograpiya]] sa [[Padron:orthography]] 165462 wikitext text/x-wiki <includeonly><span class="orth-brac">⟨</span><span class="orth-content">{{{1|{{error|Dapat magbigay ng parametro sa padron ng ortograpiya}}}}}</span><span class="orth-brac">⟩</span></includeonly><noinclude>{{dokumentasyon ng padron}}</noinclude> rsbfu4znoryrut6sb0fr6jkjgu8qglk Padron:orthography/documentation 10 33949 178023 165463 2026-09-21T16:34:28Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Padron:ortograpiya/doc]] sa [[Padron:orthography/documentation]] nang walang iniwang redirect 165463 wikitext text/x-wiki {{documentation subpage}} {{shortcut|Template:orth|Template:angbr}} Ginagamit upang markahan ang teksto sa mga angle panaklong, na ginagamit upang markahan ang mga grapema, i.e. mga letrang ginagamit sa ortograpiya, upang makilala ang mga ito mula sa malaponema o ponetika na notasyon sa International Phonetic Alphabet, o para simpleng gawing malinaw na ang teksto ay tumatalakay sa mga partikular na grapemang. Halimbawa, habang ang {{IPAchar|/a/}} (ponemiko) ay kumakatawan sa [[ponema]] ''a'' at {{IPAchar|[a]}} (ponetiko) ay kumakatawan sa [[phone]] ''a'', {{orth|a}} ay kumakatawan sa [[grapema]] ''a'', ibig sabihin, alinmang tunog ang, o ang mga tunog ay kinakatawan ng ''a' o'. Kailangan lang ng isang parametro, na kung saan ay ang teksto na ipapakita sa loob ng mga anggulong panaklong. ==TemplateData== {{TemplateData header}} <templatedata> { "params": { "1": { "label": "text", "description": "Tekstong ipapakita sa loob ng mga anggulong panaklong", "example": "a", "type": "string", "required": true } }, "description": "Gamitin ang padron na ito para markahan ang mga grapema, hal. mga titik o kumbinasyon nito sa isang ortograpiya, sa mga anggulong panaklong." } </templatedata> <includeonly> [[Category:Mga padron ng pormat ng teksto]] </includeonly> 4uyb9h6pj0tnjlw48s9mu0cqnsi9g4i Kategorya:Afrikāns na pangatnig 14 38853 178016 2026-09-21T16:28:27Z Yivan000 4078 Nilikha ang pahina na may '{{auto cat}}' 178016 wikitext text/x-wiki {{auto cat}} eomzlm5v4j7ond1phrju7cnue91g5qx Padron:RQ:Man'yōshū 10 38854 178018 2026-09-21T16:30:03Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Padron:RQ:Man'yōshū]] sa [[Padron:RQ:ojp:Man'yōshū]] 178018 wikitext text/x-wiki #REDIRECT [[Padron:RQ:ojp:Man'yōshū]] 571av7xbamy6flcc37jisogo0ebc3bh Padron:ortograpiya 10 38855 178022 2026-09-21T16:34:05Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Padron:ortograpiya]] sa [[Padron:orthography]] 178022 wikitext text/x-wiki #REDIRECT [[Padron:orthography]] i8xkr4zzus9m1dv7yjb45ehlk0diwg0 Padron:wgping 10 38856 178025 2026-09-21T16:38:19Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Padron:wgping]] sa [[Padron:workgroup ping]] 178025 wikitext text/x-wiki #REDIRECT [[Padron:workgroup ping]] 2qzdns82ss7zyl24iib65s75fffppsy Padron:Policy 10 38857 178029 2026-09-21T16:58:33Z Yivan000 4078 Nilipat ni Yivan000 ang pahinang [[Padron:Policy]] sa [[Padron:policy]] mula sa redirect 178029 wikitext text/x-wiki #REDIRECT [[Padron:policy]] 7h0nv17fix74mox2qo4s98ecg4lh4sg Pinagbuhatan 0 38858 178032 2026-09-22T04:45:08Z Yivan000 4078 Inilipat ni Yivan000 ang pahinang [[Pinagbuhatan]] sa [[pinagbuhatan]] 178032 wikitext text/x-wiki #REDIRECT [[pinagbuhatan]] 5rabgkdfqw8d0lc0d5h544ywvuf0doz 178033 178032 2026-09-22T04:46:25Z Yivan000 4078 Removed redirect to [[pinagbuhatan]] 178033 wikitext text/x-wiki =={{=tl=}}== ===Pagbigkas=== {{tl-pr}} ===Pangngalang pantangi=== {{tl-proper noun|b=+}} # {{place|tl|barangay|city/Pasig|r/Metro Manila|c/Philippines}} 8sg5dmsoc4yzec3u5fycahuva86q5qm