Module:Wd
![]() | This module is rated as ready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing. |
![]() | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
![]() | This Lua module is used on approximately 1,760,000 pages, or roughly 3% of all pages. To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them. |
![]() | You might want to use one of the user-friendly wrapper templates {{Wikidata}} and {{WikidataOI}} instead of invoking this module directly. |
This module is intended to fetch data from Wikidata with or without a link to the connected Wikipedia article and with many other features.
Usage
The general structure of a call to this module is as follows. Note that the basic structure consists of positional commands, flags and arguments, which all have a fixed position.
{{#invoke:wd|command1|flag1a|flag1b|flag1c|command2|flag2a|flag2b|flag2c|flag0a|flag0b|flag0c|arg1|arg2|arg3}}
Use different commands to get different kinds of values from Wikidata. At least one command must be given and multiple commands can be combined into one call as shown above (in any order, more than two is also possible), but this only applies to commands from the claim class; calls containing a command from the general class cannot contain any other command. Each command can be followed by any number of command flags, which are optional and can be used to tweak the output generated by that command.
The commands and their flags may be followed by any number of configuration flags, which are also optional and affect the selection of data and the module's behaviour in general. The call is closed with the positional arguments, which may be required depending on the given command(s). Some named arguments (i.e. name-value pairs) also exist, as well as a set of named flags for advanced usage that can be used to change the way the fetched values are merged together into the output.
This module was designed to provide the basic needs for fetching data from Wikidata, but a lot can be achieved through different combinations of calls. For convenience, such combinations could be wrapped into new templates that serve a specific need. See also the section on common use cases below for some examples of useful "building blocks". Likewise, the functionality of this module can be extended by creating wrapper templates that use the main
command provided by this module (just like {{WikidataOI}} does).
Common use cases
Below follows a list of common use cases. In the future, shortcut commands may be implemented that are equivalent to these calls for convenience.
Call | Use case |
---|---|
{{#invoke:wd|label|raw}} | Returns the Q-identifier of the Wikidata item connected to the current page (e.g. "Q55"). |
{{#if: | Performs a check to determine if the current page has a Wikidata item. Note that this statement relies on a returned value that is either empty or non-empty and that the |
Commands
The commands (command1
, command2
, ...) determine what kind of values are returned. One call can only contain commands from a single class.
Claim class
The claim class commands can be combined, meaning that multiple commands of different types from this class can be given at one time (see above for usage).
Combine multiple commands into one call to this module, instead of making multiple calls to this module with one command each, to be sure that all the returned pieces of information belong to each other (see also the examples below).
Type | Command | Returns | Basic usage | Description |
---|---|---|---|---|
I | property | first match[a] | {{#invoke:wd|property|P1}} | Returns the requested property – or list of properties – from the current item-entity or from a given entity. This command can be given only once in one call. |
properties | all matches | {{#invoke:wd|properties|P1}} | ||
II | qualifier | first match[b] | {{#invoke:wd|qualifier|P1|P2}} | Returns the requested qualifier – or list of qualifiers – from the given property of the current item-entity or of a given entity. Unlike the other claim class commands, this command can be given multiple times to retrieve different qualifiers in one call. |
qualifiers | all matches | {{#invoke:wd|qualifiers|P1|P2}} | ||
III | reference | first match[b] | {{#invoke:wd|reference|P1}} | Returns a reference – or list of references – from the given property of the current item-entity or of a given entity.[c] This command can be given only once in one call. |
references | all matches | {{#invoke:wd|references|P1}} | ||
|
General class
The general class commands cannot be combined.
Type | Command | Returns | Basic usage | Description |
---|---|---|---|---|
I | label | {{#invoke:wd|label}} | Returns the label of the current item-entity or of a given entity if present. | |
II | title | {{#invoke:wd|title}} | Returns the title of the page connected to the current item-entity or to a given item-entity if such page exists. | |
III | description | {{#invoke:wd|description}} | Returns the description of the current item-entity or of a given entity if present. | |
IV | alias | first match[a] | {{#invoke:wd|alias}} | Returns an alias – or list of aliases – of the current item-entity or of a given entity if present. |
aliases | all matches | {{#invoke:wd|aliases}} | ||
V | badge | first match[a] | {{#invoke:wd|badge}} | Returns a badge – or list of badges – for the page connected to the current item-entity or to a given item-entity if such page exists. |
badges | all matches | {{#invoke:wd|badges}} | ||
Flags
The following (optional) flags are available which can be used to alter this module's behaviour. They must be given after the (first) command and before the positional arguments. For convenience, empty flags (i.e. ||
) are allowed and will simply be ignored.
Command flags
These flags (flag1*
, flag2*
, ...) apply to the command that precedes them directly.
Flag | Description |
---|---|
raw | Returns the raw value if applicable. If this flag is used with item or property datatypes, then this will return the Q-identifier or P-identifier instead of the regular label. For quantity datatypes, this flag will strip off any units of measurement, unless the If this flag is used with time datatypes, then the returned date will be in the format of If it is used with globe coordinate datatypes, then it replaces the various symbols with forward slashes in the returned value (e.g. |
linked | Creates a link to the Wikipedia article that is connected to the property or qualifier if it exists. Also links units of measurement that may be appended to values. If this parameter is omitted, then the plain property or qualifier value will be returned. |
short | [EXPENSIVE] Returns the short name (P1813) of any entity returned if they have one attached. If that is not the case, then the default behaviour of returning the entity's label will occur. |
multilanguage | Returns monolingual text values in any available language, not just the current wiki's language. |
unit | Returns only the unit of measurement for quantity datatypes. |
Configuration flags
These flags (flag0*
) are general configuration flags and can be given anywhere after the first command (but before the positional arguments).
Flag | Description | Command class | |
---|---|---|---|
Combination of: | preferred | Sets a rank constraint for the selected claim(s). The first three set the ranks for which claim(s) will be selected. They can optionally be followed by a If the The default is Output is always sorted from highest rank to lowest (regardless of any of these flags being set). | claim |
normal | |||
deprecated | |||
best | |||
Combination of: | future | Sets a time constraint for the selected claim(s). Uses the claims' qualifiers of start time (P580) and end time (P582) to determine if the claim is valid for the selected time period(s). The default is | claim |
current | |||
former | |||
mdy | Returns date values in month-day-year order instead of day-month-year order. | claim | |
single | Returns only a single claim instead of multiple (if multiple claims match). Has no effect if the property /properties command is given, in which case this flag would be redundant. | claim | |
sourced | Only returns claims that have at least one non-empty reference. (References having only ignored parameters are considered empty.) | claim | |
One of: | edit | Adds a clickable icon after the output that may be used by readers to edit the returned claim on Wikidata. If | claim, general |
edit@end |
Arguments
The arguments determine the sources from which all the returned values are fetched.
Positional arguments
The following table shows the available positional arguments (arg*
) in their fixed order. For each command, the applicable set of arguments is marked. If multiple commands are given, then the applicable set is the union of the individual sets. For instance, if the commands properties
and qualifiers
have been given, then at least both the arguments property_id
and qualifier_id
should be given as well.
More than one qualifier
/qualifiers
command can be given. The order in which these commands with their flags are given matches the order in which the respective qualifier_id
arguments are given.
(required) | (optional) | (optional) | (required) | (optional) | (required) | (required) | |||
{{#invoke:wd | commands | flags | entity_id | property_id | raw_value | qualifier_id | qualifier_id | }} | |
---|---|---|---|---|---|---|---|---|---|
label , title ,description ,alias /aliases ,badge /badges | |||||||||
property /properties | |||||||||
reference /references | |||||||||
qualifier /qualifiers | |||||||||
qualifier /qualifiers (optional 2nd, 3rd, etc.) | |||||||||
Below follows a description of all positional arguments.
Argument | Description |
---|---|
entity_id (optional) | [EXPENSIVE] Q-identifier of the item-entity to be accessed (e.g. Q55 ), P-identifier (or an available alias) of the property-entity to be accessed preceded by the Property: prefix (e.g. Property:P38 ), or page title of the Wikipedia article whose connected item-entity is to be accessed preceded by : , a prefixed colon (e.g. :Netherlands ). In case of the general class commands, the If this parameter is omitted, then the item-entity connected to the current page will be used (except when |
property_id | P-identifier (or an available alias) of the property within the entity to be accessed, without the Property: prefix (e.g. P35 ). |
raw_value (optional) | Either the Q-identifier equal to the property value (e.g. Q29574 ) or a literal value (i.e. string or quantity etc., no entity label) equal to the raw property value of the particular claim to be accessed. Dates as literal values must be formatted Globe coordinates as literal values must be formatted with forward slashes (i.e. The special type 'no value' can be given by entering the empty string (i.e. To get a literal vertical bar If this parameter is omitted, then all claims (matching any other constraints) within the property will be accessed. |
qualifier_id | P-identifier (or an available alias) of the qualifier within the entity to be accessed, without the Property: prefix (e.g. P580 ). |
Named arguments
Below follows a description of all named arguments, which are name-value pairs (i.e. |name=value
). These are all optional and can be given anywhere after the first command.
Argument | Description | Command class |
---|---|---|
eid= | [EXPENSIVE] This argument can be used to give the Q-identifier (e.g. |eid=Q55 ) or P-identifier (or an available alias) of the entity to be accessed. It offers the same functionality as the positional argument entity_id , with one difference: if the argument is given but its value is left empty (i.e. |eid= ), then no entity is accessed at all instead of the item-entity connected to the current page. This is useful in some cases where a variable entity-ID is expected, but where the item-entity connected to the current page should not be accessed as the default. Also, the This argument only has effect if the positional argument | claim, general |
page= | [EXPENSIVE] This argument can be used to give the page title (e.g. |page=Netherlands ) of the Wikipedia article whose connected item-entity is to be accessed. It behaves similar to the named argument eid= and can be used instead of the positional argument entity_id (note that no prefixed colon, : , is required). If the argument is given but its value is left empty (i.e. |page= ), then no entity is accessed at all instead of the item-entity connected to the current page. This argument only has effect if the positional argument | claim, general |
date= | This argument can be used to set a particular date (e.g. |date=1731-02-11 ) relative to which claim matching using the future , current and former flags is done, instead of relative to today. It overrides the default of these flags to current so that by default only claims that were valid at the given date are returned (based on the claims' qualifiers of start time (P580) and end time (P582)). The date value must be formatted | claim |
<qualifier>= | The <qualifier> is a placeholder for a set of arguments that determine which claims should be accessed based on qualifier value, analogous to the pair of positional arguments property_id and raw_value (that determine access based on property value). As such, Example: Multiple arguments of this type can be given to match multiple qualifier values simultaneously for each claim. | claim |
Property aliases
Property aliases are other names for P-identifiers that can be used instead. The following property aliases (which are case-sensitive) are currently available:
Alias | translates to | P-identifier |
---|---|---|
coord | → | P625 |
image | → | P18 |
author | → | P50 |
authorNameString | → | P2093 |
publisher | → | P123 |
importedFrom | → | P143 |
wikimediaImportURL | → | P4656 |
statedIn | → | P248 |
pages | → | P304 |
language | → | P407 |
hasPart | → | P527 |
publicationDate | → | P577 |
startTime | → | P580 |
endTime | → | P582 |
chapter | → | P792 |
retrieved | → | P813 |
referenceURL | → | P854 |
sectionVerseOrParagraph | → | P958 |
archiveURL | → | P1065 |
title | → | P1476 |
formatterURL | → | P1630 |
quote | → | P1683 |
shortName | → | P1813 |
definingFormula | → | P2534 |
archiveDate | → | P2960 |
inferredFrom | → | P3452 |
typeOfReference | → | P3865 |
column | → | P3903 |
subjectNamedAs | → | P1810 |
wikidataProperty | → | P1687 |
References
When either the reference
or the references
command is used and a reference is encountered (in Wikidata), the module checks if the reference contains an imported from Wikimedia project (P143), inferred from (P3452) or Wikimedia import URL (P4656) property. In the case one of these properties is present, the whole reference is ignored (i.e. it is treated as if it wasn't present).
Else, the module attempts to display the reference using the {{Cite web}} template. The reference has to have a reference URL (P854) property. The below table shows the mapping of Wikidata properties to parameters of Cite web.
Wikidata property | Parameter of Cite web | Notes |
---|---|---|
archive date (P2960) | archive-date | |
archive URL (P1065) | archive-url | |
author (P50) | author/authorN | N can be 1, 2, 3... |
author name string (P2093) | ||
language of work or name (P407) | language | Ignored when the same as the local language. |
page(s) (P304) | pages | |
publication date (P577) | date | |
publisher (P123) | publisher | |
quotation (P1683) | quote | |
reference URL (P854) | url | |
retrieved (P813) | access-date | |
section, verse, paragraph, or clause (P958) | at | |
stated in (P248) | website | |
subject named as (P1810) | title | Used only when title (P1476) is not present, but a URL (either from reference URL (P854) or from an external identifier, as described below) is, otherwise ignored. |
title (P1476) | title |
The following properties are ignored: image (P18), type of reference (P3865).
If there is no reference URL (P854) property present in the reference, but a property of the "External identifier" data type is present both in the reference and in the Wikidata property (P1687) of the item in stated in (P248), a URL is generated from its content and is used in the same manner as a URL given in reference URL (P854).
If there is no reference URL (P854) property, or the reference has unknown properties, the module attempts to display it using the {{Cite Q}} template. The stated in (P248) property is mandatory. The below table shows the mapping of properties to Cite Q parameters.
Wikidata property | Parameter of Cite Q | Notes |
---|---|---|
stated in (P248) | 1 | Value supplied to the parameter is raw, i.e. it is just the plain QID. |
chapter (P792) | chapter | |
column (P3903) | at | |
page(s) (P304) | pages | |
publication date (P577) | date | |
retrieved (P813) | access-date | |
section, verse, paragraph, or clause (P958) | section | |
title (P1476) | title | |
any property of the "External identifier" data type | id | The label ("name") of the property is prepended before its content. |
The properties listed under the first table (in this section) are also ignored when using Cite Q.
A reference could be displayed using Cite Q only if the reference has a stated in (P248) property and has only properties listed in the table above. If neither Cite web nor Cite Q could be used to display a reference, the following an error message with an explanation is returned.
To fix this error, check if the reference has the required properties and doesn't have any unknown properties, as described above. The Wikidata help page on references can also be helpful when sourcing statements.
Advanced usage
The layout of the output from (a combination of) commands that have both a singular and a plural form (e.g. property
/properties
) can be customized by using a number of named flags, which are name-value pairs (i.e. |flag=value
), that can be given anywhere after the first command. The table below shows the available named flags.
To insert a space at the beginning or end of a value
, use an underscore _
. To get a literal underscore, escape it by placing a backslash \
directly in front of it (i.e. \_
); the same holds for a literal backslash (i.e. \\
). To get a literal vertical bar |
, use {{!}}
or |
.
Named flag | Default value | Default condition | Description | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
format= | %p[%s][%r] | if the property /properties command was given and the qualifier /qualifiers command was not given | The format of a single claim. The available parameters are as follows.
Optional parameters can be given by encapsulating them between square brackets: To use two opening square brackets that directly follow each other (i.e. At least one parameter must be given that is not optional, while the To get a literal | ||||||||||||||||
%q[%s][%r] | if the property /properties command was not given and the qualifier /qualifiers command was given | ||||||||||||||||||
%r | if only the reference /references command was given | ||||||||||||||||||
%p[ <spanstyle="font-size:85\%">(%q)</span>][%s][%r] | if the property /properties command was given and the qualifier /qualifiers command was given | ||||||||||||||||||
%a[%s] | if the alias /aliases command was given | ||||||||||||||||||
%b[%s] | if the badge /badges command was given | ||||||||||||||||||
sep= | _ | default | The fixed separator between each pair of claims, aliases or badges. | ||||||||||||||||
| if only the reference /references command was given without the raw flag | ||||||||||||||||||
sep%s= | , | default | The movable separator between each pair of claims, aliases or badges. This will be the value of the %s parameter applied to all claims, aliases or badges, except for the last in the list (which can be set with the punc flag). | ||||||||||||||||
; | if the property /properties command was not given and the qualifier /qualifiers command was given | ||||||||||||||||||
sep%q1= , sep%q2= , sep%q3= , ... | ,_ | default | The separator between each pair of qualifiers of a single claim. These are the value separators for the %q1 , %q2 , %q3 , ... parameters. If only one | ||||||||||||||||
sep%q= | ,_ | if exactly onequalifier /qualifiers command was given | The separator between each set of qualifiers of a single claim. This is the value separator for the %q parameter. If only one | ||||||||||||||||
;_ | if more than onequalifier /qualifiers command was given | ||||||||||||||||||
sep%r= |
| default | The separator between each pair of references of a single claim. This is the value separator for the %r parameter. | ||||||||||||||||
_ | if the raw flag was given for the reference /references command | ||||||||||||||||||
punc= |
| default | A punctuation mark placed at the end of the output. This will be placed on the %s parameter applied to the last claim (or alias or badge) in the list. This allows the last claim's references to be placed after the punctuation mark when the output is used as part of a sentence. |
Examples
Parameters and output types | Example | Description |
---|---|---|
Q55 = "Netherlands", P395 = "licence plate code"
[string] | {{#invoke:wd|property|Q55|P395}}
| Gets a literal string value. |
P395 = "licence plate code"
[string] | {{#invoke:wd|property|P395}}
| If the module is transcluded on the Netherlands page (which is linked to Q55), then the Q55 can be omitted. |
Q55 = "Netherlands", P395 = "NL"
[string] | {{#invoke:wd|property|eid=Q55|P395}}
| An entity-ID can also be given using the eid= argument. |
P395 = "NL"
[string] | {{#invoke:wd|property|page=Netherlands|P395}}
| A page title can be given instead of an entity-ID using the page= argument. |
Q55 = "Netherlands", P395 = "licence plate code"
[string] | {{#invoke:wd|property|edit|Q55|P395}} | Adds a clickable icon that may be used to edit the returned value on Wikidata. |
Q55 = "Netherlands", P395 = "licence plate code"
[string] | {{#invoke:wd|property|edit@end|Q55|P395}} | Places the edit icon at the end of the line. |
Q55 = "Netherlands", P1082 = "population"
[quantity] | {{#invoke:wd|property|normal+|Q55|P1082}}
| Gets a single property value from claims with a 'normal' rank or higher. |
Q55 = "Netherlands", P1082 = "population"
[quantity] | {{#invoke:wd|properties|normal+|Q55|P1082}}
| Gets multiple property values from claims with a 'normal' rank or higher. |
Q55 = "Netherlands", P1082 = "population", P585 = "point in time"
[quantity], [time] | {{#invoke:wd|properties|qualifier|normal+|Q55|P1082|P585}}
| Gets a single qualifier value for each claim, additional to the property value. |
Q55 = "Netherlands", P1082 = "population", P585 = "point in time"
[quantity], [time], [reference] | {{#invoke:wd|properties|qualifier|references|normal+|Q55|P1082|P585}} | Gets references for each claim. |
Q55 = "Netherlands", P1082 = "population"
[quantity], [reference] | A total of
| Gets a property with its references. |
Q55 = "Netherlands", P1082 = "population"
[quantity], [reference] | The Netherlands has a population of
| Adds a punctuation mark at the end of the output, in front of the references. |
Q55 = "Netherlands", P1082 = "population", P585 = "point in time"
[quantity], [time], [reference] | <ul>
| Returns the output in a custom format. |
Q55 = "Netherlands", P1082 = "population", P585 = "point in time"
[time] | {{#invoke:wd|qualifier|normal+|Q55|P1082|P585}}
| Gets a single qualifier per claim, by default for multiple matching claims. |
Q55 = "Netherlands", P1082 = "population", P585 = "point in time"
[time] | {{#invoke:wd|qualifier|normal+|single|Q55|P1082|P585}}
| To get a single qualifier for only a single claim, give the single flag too so that only a single claim will be accessed. |
Q55 = "Netherlands", P1082 = "population", P585 = "point in time"
[time] | {{#invoke:wd|qualifier|Q55|P1082|10026773|P585}}
| Gets a qualifier from claims for which the (raw) property value matches a given literal value. |
Q55 = "Netherlands", P1082 = "population", P585 = "point in time"
[time] | {{#invoke:wd|qualifier|mdy|Q55|P1082|10026773|P585}}
| Gets dates in month-day-year order. |
Q55 = "Netherlands", P1082 = "population", P585 = "point in time"
[time] | {{#invoke:wd|qualifier|raw|Q55|P1082|10026773|P585}}
| Gets a raw date value. |
Q55 = "Netherlands", P1082 = "population"
[reference] | {{#invoke:wd|references|Q55|P1082|10026773}}
| Gets the references from a particular claim. |
Q55 = "Netherlands", P1082 = "population"
[reference] | {{#invoke:wd|references|raw|Q55|P1082|10026773}}
| Gets references from a particular claim in their raw form. |
Q55 = "Netherlands", P1081 = "Human Development Index"
[quantity], [reference] | {{#invoke:wd|properties|references|normal+|Q55|P1081}}
| Gets properties from each claim with any references they have. |
Q55 = "Netherlands", P1081 = "Human Development Index"
[quantity], [reference] | {{#invoke:wd|properties|references|normal+|sourced|Q55|P1081}}
| Only gets properties from claims that have at least one reference. |
Q55 = "Netherlands", P2855 = "VAT rate", P518 = "applies to part"
[entity label] | {{#invoke:wd|qualifier|Q55|P2855|P518}}
| Gets a single qualifier value (for each matching claim). |
Q55 = "Netherlands", P2855 = "VAT rate", P518 = "applies to part"
[entity label] | {{#invoke:wd|qualifiers|Q55|P2855|P518}}
| Gets multiple qualifier values (for each matching claim). |
Q55 = "Netherlands", P2855 = "VAT rate", P518 = "applies to part"
[quantity], [entity label] | {{#invoke:wd|properties|qualifiers|Q55|P2855|P518}}
| Gets multiple property values along with multiple qualifier values. |
Q55 = "Netherlands", P2855 = "VAT rate", P518 = "applies to part"
[quantity], [entity label] | {{#invoke:wd|properties|qualifiers|Q55|P2855|P518|sep=_+_|sep%s=|sep%q=_/_}}
| Returns the output with custom separators. |
Q55 = "Netherlands", P35 = "head of state", P580 = "start time", P582 = "end time"
[entity label], [time] | {{#invoke:wd|properties|qualifier|qualifier|normal+|Q55|P35|P580|P582}}
| Gets two different qualifier values for each claim. |
Q55 = "Netherlands", P35 = "head of state", P580 = "start time", P582 = "end time"
[entity label], [time] | {{#invoke:wd|properties|qualifier|qualifier|normal+|Q55|P35|P580|P582|sep%q=_–_}}
| Returns the output with a custom separator. |
Q55 = "Netherlands", P35 = "head of state", P580 = "start time", P582 = "end time"
[entity label], [time] | {{#invoke:wd|properties|qualifier|qualifier|normal+|Q55|P35|P580|P582|format=%p[ <span style="font-size:85\%">(%q1[ – %q2])</span>][%s][%r]}}
| Returns the output in a custom format instead of with a custom separator. |
Q55 = "Netherlands", P35 = "head of state", P580 = "start time", P582 = "end time"
[entity label], [time] | {{#invoke:wd|properties|qualifier|qualifier|normal+|Q55|P35|P580|P582|format=%p[ <span style="font-size:85\%">([<![]--%q2]since [%q2--[]>]%q1[ – %q2])</span>][%s][%r]}}
| To add text only when a certain value is not present, like adding the word since if there is no end time, wrap it in between two optional blocks containing HTML comment tags and the relevant parameter (this also prevents the text from being added to the page source). |
Q55 = "Netherlands", P35 = "head of state", Q29574 = "Beatrix of the Netherlands", P580 = "start time", P582 = "end time"
[entity label], [time] | {{#invoke:wd|properties|qualifier|raw|qualifier|normal+|Q55|P35|Q29574|P580|P582|format=%p[ <span style="font-size:85\%">(%q1[ – %q2])</span>][%s][%r]}}
| Gets a property with qualifiers from claims for which the property matches a given Q-identifier, with one of the qualifier values in its raw form. |
Q55 = "Netherlands", P38 = "currency", P518 = "applies to part"
[entity label] | {{#invoke:wd|properties|qualifiers|normal+|current|Q55|P38|P518}}
| Gets claims that are currently valid. |
Q55 = "Netherlands", P38 = currency", P518 = "applies to part"
[entity label] | {{#invoke:wd|properties|linked|qualifiers|normal+|current|Q55|P38|P518}}
| Gets claims with linked property values. |
Q55 = "Netherlands", P38 = currency", P518 = "applies to part"
[entity label] | {{#invoke:wd|properties|qualifiers|linked|normal+|current|Q55|P38|P518}}
| Gets claims with linked qualifier values. |
Q55 = "Netherlands", P38 = currency", P518 = "applies to part"
[entity label] | {{#invoke:wd|properties|linked|short|qualifiers|linked|normal+|current|Q55|P38|P518}}
| Gets claims with linked property and qualifier values, with short property values wherever available. |
Q55 = "Netherlands", P38 = currency", Q4917 = "United States dollar", P518 = "applies to part"
[entity label] | {{#invoke:wd|qualifiers|normal+|current|Q55|P38|Q4917|P518}}
| Gets qualifiers from claims for which the (raw) property value matches a given Q-identifier. |
Q55 = "Netherlands", P38 = currency", P518 = "applies to part", Q27561 = "Caribbean Netherlands"
[entity label] | {{#invoke:wd|properties|normal+|current|Q55|P38|P518=Q27561}}
| Gets properties from claims for which a (raw) qualifier value matches a given Q-identifier. |
Q55 = "Netherlands", P38 = currency"
[entity label] | {{#invoke:wd|properties|normal+|former|Q55|P38}}
| Gets claims that were valid in the past. |
Q55 = "Netherlands", P38 = currency"
[entity label] | {{#invoke:wd|properties|raw|normal+|former|Q55|P38}}
| Gets raw property values. |
Q55 = "Netherlands", P38 = currency"
[entity label] | {{#invoke:wd|properties|raw|linked|normal+|former|Q55|P38}} | Gets raw property values that are linked to Wikidata. |
Q55 = "Netherlands", P1549 = "demonym"
[monolingual text] | {{#invoke:wd|property|Q55|P1549}}
| Gets a monolingual text value in the current wiki's language. |
Q55 = "Netherlands", P1549 = "demonym", P407 = "language of work or name", Q36846 = "Toki Pona"
[monolingual text] | {{#invoke:wd|property|multilanguage|Q55|P1549|P407=Q36846}}
| Gets a monolingual text value in any available language. |
Q55 = "Netherlands", P2884 = "mains voltage"
[quantity] | {{#invoke:wd|property|Q55|P2884}}
| Gets a quantity value with its associated unit of measurement. |
Q55 = "Netherlands", P2884 = "mains voltage"
[quantity] | {{#invoke:wd|property|linked|Q55|P2884}}
| Gets a quantity value with a linked unit of measurement. |
Q55 = "Netherlands", P2884 = "mains voltage"
[quantity] | {{#invoke:wd|property|raw|Q55|P2884}}
| Gets a raw quantity value. |
Q55 = "Netherlands", P2884 = "mains voltage"
[quantity] | {{#invoke:wd|property|unit|Q55|P2884}}
| Gets only the unit of measurement. |
Q55 = "Netherlands", P2884 = "mains voltage"
[quantity] | {{#invoke:wd|property|unit|raw|Q55|P2884}}
| Gets the raw unit of measurement. |
Q55 = "Netherlands", P625 = "coordinate location"
[globe coordinate] | {{#invoke:wd|property|Q55|P625}}
| Gets a globe coordinate value. |
Q55 = "Netherlands", P625 = "coordinate location"
[globe coordinate] | {{#invoke:wd|property|linked|Q55|P625}} | Gets a linked globe coordinate value. |
Q55 = "Netherlands", P625 = "coordinate location"
[globe coordinate] | {{#invoke:wd|property|raw|Q55|P625}}
| Gets a raw globe coordinate value. |
Q55 = "Netherlands", P625 = "coordinate location"
[globe coordinate] | {{#invoke:wd|property|Q55|coord}}
| A property alias can be used instead of the P-identifier. |
Q55 = "Netherlands", P41 = "flag image"
[commons media] | {{#invoke:wd|property|linked|Q55|P41}} | Gets a media file name and links to it on Commons. |
Q55 = "Netherlands", P41 = "flag image"
[commons media] | {{#invoke:wd|property|raw|Q55|P41|format=\[\[File:%p {{!}} thumb {{!}} left\]\]}} | A Commons media file can be included on the page as-is by omitting the linked and raw flags, but by using the raw flag it can be freely formatted. |
Q55 = "Netherlands", P41 = "flag image"
[commons media] | {{#invoke:wd|property|raw|date=1700-05-06|Q55|P41|format=\[\[File:%p {{!}} thumb {{!}} left\]\]}} | To get the value of a property that was valid at a given time, the date= argument can be used. |
Q55 = "Netherlands", P41 = "flag image"
[commons media] | {{#invoke:wd|property|raw|date=1700-05-06|former|Q55|P41|format=\[\[File:%p {{!}} thumb {{!}} left\]\]}} | The time constraint flags work relatively to the date value given for the date= argument. |
Q915684 = "Lorentz–Lorenz equation", P2534 = "defining formula"
[math] | {{#invoke:wd|property|Q915684|P2534}} | Gets a mathematical expression. |
Q915684 = "Lorentz–Lorenz equation", P7235 = "in defining formula", P9758 = "symbol represents"
[entity label], [math] | <ul> | Mathematical expressions can be combined with regular text as usual. |
Q6256 = "country", P3896 = "geoshape"
[geographic shape] | {{#invoke:wd|property|linked|Q6256|P3896}} | Gets a geographic shape data file name and links to it on Commons. |
Q4917 = "United States dollar"
[entity label] | {{#invoke:wd|label|Q4917}}
| Gets an item's label. |
Q4917 = "United States dollar"
[entity label] | {{#invoke:wd|label|short|linked|Q4917}} | Gets an item's short and linked label. |
P38 = currency"
[entity label] | {{#invoke:wd|label|P38}}
| Gets a property's label. |
P38 = currency"
[entity label] | {{#invoke:wd|label|linked|P38}} | Gets a property's label that is linked to Wikidata. |
Q776 = "Utrecht"
[entity label] | {{#invoke:wd|label|Q776}}
| Gets an item's label. |
Q776 = "Utrecht"
[entity label] | {{#invoke:wd|label|linked|Q776}} | Gets an item's linked label. |
[entity label] | {{#invoke:wd|label}}
| If the module is transcluded on the Utrecht (province) page (which is linked to Q776), then the Q776 can be omitted. |
[entity label] | {{#invoke:wd|label|raw}}
| If just the label command with the raw flag is given, then the Q-identifier of the item connected to the current page is returned. |
[entity label] | {{#invoke:wd|label|raw|linked}}
| If additionally the linked flag is given, then the Q-identifier of the item connected to the current page is linked to Wikidata. |
Q776 = "Utrecht"
[page title] | {{#invoke:wd|title|Q776}}
| Gets the title of the page on the current wiki that is linked to the given item. |
Q776 = "Utrecht"
[page title] | {{#invoke:wd|title|linked|Q776}} | Gets the linked title of the page on the current wiki that is linked to the given item. |
[page title] | {{#invoke:wd|title}}
| If the module is transcluded on the Utrecht (province) page (which is linked to Q776), then the Q776 can be omitted. |
Q55 = "Netherlands"
[entity description] | {{#invoke:wd|description|Q55}}
| Gets an item's description. |
[entity description] | {{#invoke:wd|description}}
| If the module is transcluded on the Netherlands page (which is linked to Q55), then the Q55 can be omitted. |
Q55 = "Netherlands"
[entity alias] | {{#invoke:wd|alias|Q55}}
| Gets one of an item's aliases. |
Q55 = "Netherlands"
[entity alias] | {{#invoke:wd|aliases|Q55}}
| Gets all of an item's aliases. |
Q55 = "Netherlands"
[entity alias] | {{#invoke:wd|alias|linked|Q55}} | Gets a linked alias from an item. |
[entity alias] | {{#invoke:wd|alias}}
| If the module is transcluded on the Netherlands page (which is linked to Q55), then the Q55 can be omitted. |
Q2 = "Earth"
[page badge] | {{#invoke:wd|badges|Q2}}
| Gets the badges for the page on the current wiki that is linked to the given item. |
Q2 = "Earth"
[page badge] | {{#invoke:wd|badges|raw|Q2}}
| Gets the raw badges for the page on the current wiki that is linked to the given item. |
[page badge] | {{#invoke:wd|badges}}
| If the module is transcluded on the Earth page (which is linked to Q2), then the Q2 can be omitted. |
Q28865 = "Python", P548 = "version type", P348 = "software version identifier",
[version], [reference] | {{#invoke:wd|property|reference|edit|Q28865|P548=Q2804309|P348}}
| Get Python's latest stable release version with its references. You may want to use P548=Q2122918 to get the latest preview release version. |
Example references
- ^ abcdefghij"Bevolking; kerncijfers, 1950-2022".
- ^ abcde"CBS StatLine - Bevolking; kerncijfers". Statistics Netherlands. Archived from the original on 27 August 2015. Retrieved 22 August 2015.
- ^ ab"CBS StatLine - Bevolking; kerncijfers". Archived from the original on 3 September 2014. Retrieved 26 August 2014.
- ^ ab"Nederland telt 17 miljoen inwoners". 21 March 2016.
- ^ ab"Bevolking; kerncijfers, 1950-2022". Retrieved 18 March 2023.
- ^ abcdefghijklmnopqrstuvwxyzaaabacadaeafagahaiajakalamanaoapaqarasatauavawaxayazbabbbcbd"Human Development Data (1990-2017)". Human Development Report. Archived from the original on 30 December 2018.
- ^ abcdefghijklmn"Netherlands". Archived from the original on 2 February 2017.
- ^"It's time for another set of Python releases! Python 3.11.3, 3.10.11 and 3.12 alpha 7 are now available". 5 April 2023. Retrieved 6 April 2023.
TemplateData
This template fetches data from the centralized knowledge base Wikidata. To edit the data, click on "Wikidata item" in the left sidebar.
Parameter | Description | Type | Status | |||
---|---|---|---|---|---|---|
No parameters specified |
See also
- {{Wikidata}}, a user-friendly wrapper template for this module.
- {{WikidataOI}}, a wrapper template for this module that adds an opt-in toggle.
- {{Pageid to title}}, to get a page title using its local page id, rather than Wikidata
-- Original module located at [[:en:Module:Wd]] and [[:en:Module:Wd/i18n]].require("strict")localp={}localmodule_arg=...locali18nlocali18nPathlocalfunctionloadI18n(aliasesP,frame)localtitleifframethen-- current module invoked by page/template, get its title from frametitle=frame:getTitle()else-- current module included by other module, get its title from ...title=module_argendifnoti18ntheni18nPath=title.."/i18n"i18n=require(i18nPath).init(aliasesP)endendp.claimCommands={property="property",properties="properties",qualifier="qualifier",qualifiers="qualifiers",reference="reference",references="references"}p.generalCommands={label="label",title="title",description="description",alias="alias",aliases="aliases",badge="badge",badges="badges"}p.flags={linked="linked",short="short",raw="raw",multilanguage="multilanguage",unit="unit",-------------preferred="preferred",normal="normal",deprecated="deprecated",best="best",future="future",current="current",former="former",edit="edit",editAtEnd="edit@end",mdy="mdy",single="single",sourced="sourced"}p.args={eid="eid",page="page",date="date",globalSiteId="globalSiteId"}localaliasesP={coord="P625",-----------------------image="P18",author="P50",authorNameString="P2093",publisher="P123",importedFrom="P143",wikimediaImportURL="P4656",statedIn="P248",pages="P304",language="P407",hasPart="P527",publicationDate="P577",startTime="P580",endTime="P582",chapter="P792",retrieved="P813",referenceURL="P854",sectionVerseOrParagraph="P958",archiveURL="P1065",title="P1476",formatterURL="P1630",quote="P1683",shortName="P1813",definingFormula="P2534",archiveDate="P2960",inferredFrom="P3452",typeOfReference="P3865",column="P3903",subjectNamedAs="P1810",wikidataProperty="P1687",publishedIn="P1433"}localaliasesQ={percentage="Q11229",prolepticJulianCalendar="Q1985786",citeWeb="Q5637226",citeQ="Q22321052"}localparameters={property="%p",qualifier="%q",reference="%r",alias="%a",badge="%b",separator="%s",general="%x"}localformats={property="%p[%s][%r]",qualifier="%q[%s][%r]",reference="%r",propertyWithQualifier="%p[ <span style=\"font-size:85\\%\">(%q)</span>][%s][%r]",alias="%a[%s]",badge="%b[%s]"}localhookNames={-- {level_1, level_2}[parameters.property]={"getProperty"},[parameters.reference]={"getReferences","getReference"},[parameters.qualifier]={"getAllQualifiers"},[parameters.qualifier.."\\d"]={"getQualifiers","getQualifier"},[parameters.alias]={"getAlias"},[parameters.badge]={"getBadge"}}-- default value objects, should NOT be mutated but instead copiedlocaldefaultSeparators={["sep"]={" "},["sep%s"]={","},["sep%q"]={"; "},["sep%q\\d"]={", "},["sep%r"]=nil,-- none["punc"]=nil-- none}localrankTable={["preferred"]=1,["normal"]=2,["deprecated"]=3}localfunctionreplaceAlias(id)ifaliasesP[id]thenid=aliasesP[id]endreturnidendlocalfunctionerrorText(code,...)localtext=i18n["errors"][code]ifargthentext=mw.ustring.format(text,unpack(arg))endreturntextendlocalfunctionthrowError(errorMessage,...)error(errorText(errorMessage,unpack(arg)))endlocalfunctionreplaceDecimalMark(num)returnmw.ustring.gsub(num,"[.]",i18n['numeric']['decimal-mark'],1)endlocalfunctionpadZeros(num,numDigits)localnumZeroslocalnegative=falseifnum<0thennegative=truenum=num*-1endnum=tostring(num)numZeros=numDigits-num:len()for_=1,numZerosdonum="0"..numendifnegativethennum="-"..numendreturnnumendlocalfunctionreplaceSpecialChar(chr)ifchr=='_'then-- replace underscores with spacesreturn' 'elsereturnchrendendlocalfunctionreplaceSpecialChars(str)localchrlocalesc=falselocalstrOut=""fori=1,#strdochr=str:sub(i,i)ifnotescthenifchr=='\\'thenesc=trueelsestrOut=strOut..replaceSpecialChar(chr)endelsestrOut=strOut..chresc=falseendendreturnstrOutendlocalfunctionbuildWikilink(target,label)ifnotlabelortarget==labelthenreturn"[["..target.."]]"elsereturn"[["..target.."|"..label.."]]"endend-- used to make frame.args mutable, to replace #frame.args (which is always 0)-- with the actual amount and to simply copy tableslocalfunctioncopyTable(tIn)ifnottInthenreturnnilendlocaltOut={}fori,vinpairs(tIn)dotOut[i]=vendreturntOutend-- used to merge output arrays together;-- note that it currently mutates the first input arraylocalfunctionmergeArrays(a1,a2)fori=1,#a2doa1[#a1+1]=a2[i]endreturna1endlocalfunctionsplit(str,del)localout={}locali,j=str:find(del)ifiandjthenout[1]=str:sub(1,i-1)out[2]=str:sub(j+1)elseout[1]=strendreturnoutendlocalfunctionparseWikidataURL(url)localidifurl:match('^http[s]?://')thenid=split(url,"Q")ifid[2]thenreturn"Q"..id[2]endendreturnnilendlocalfunctionparseDate(dateStr,precision)precision=precisionor"d"locali,j,index,ptrlocalparts={nil,nil,nil}ifdateStr==nilthenreturnparts[1],parts[2],parts[3]-- year, month, dayend-- 'T' for snak values, '/' for outputs with '/Julian' attachedi,j=dateStr:find("[T/]")ifithendateStr=dateStr:sub(1,i-1)endlocalfrom=1ifdateStr:sub(1,1)=="-"then-- this is a negative number, look further aheadfrom=2endindex=1ptr=1i,j=dateStr:find("-",from)ifithen-- yearparts[index]=tonumber(dateStr:sub(ptr,i-1),10)-- explicitly give base 10 to prevent errorifparts[index]==-0thenparts[index]=tonumber("0")-- for some reason, 'parts[index] = 0' may actually store '-0', so parse from string insteadendifprecision=="y"then-- we're donereturnparts[1],parts[2],parts[3]-- year, month, dayendindex=index+1ptr=i+1i,j=dateStr:find("-",ptr)ifithen-- monthparts[index]=tonumber(dateStr:sub(ptr,i-1),10)ifprecision=="m"then-- we're donereturnparts[1],parts[2],parts[3]-- year, month, dayendindex=index+1ptr=i+1endendifdateStr:sub(ptr)~=""then-- day if we have month, month if we have year, or yearparts[index]=tonumber(dateStr:sub(ptr),10)endreturnparts[1],parts[2],parts[3]-- year, month, dayendlocalfunctiondatePrecedesDate(aY,aM,aD,bY,bM,bD)ifaY==nilorbY==nilthenreturnnilendaM=aMor1aD=aDor1bM=bMor1bD=bDor1ifaY<bYthenreturntrueendifaY>bYthenreturnfalseendifaM<bMthenreturntrueendifaM>bMthenreturnfalseendifaD<bDthenreturntrueendreturnfalseendlocalfunctiongetHookName(param,index)ifhookNames[param]thenreturnhookNames[param][index]elseifparam:len()>2thenreturnhookNames[param:sub(1,2).."\\d"][index]elsereturnnilendendlocalfunctionalwaysTrue()returntrueend-- The following function parses a format string.---- The example below shows how a parsed string is structured in memory.-- Variables other than 'str' and 'child' are left out for clarity's sake.---- Example:-- "A %p B [%s[%q1]] C [%r] D"---- Structure:-- [-- {-- str = "A "-- },-- {-- str = "%p"-- },-- {-- str = " B ",-- child =-- [-- {-- str = "%s",-- child =-- [-- {-- str = "%q1"-- }-- ]-- }-- ]-- },-- {-- str = " C ",-- child =-- [-- {-- str = "%r"-- }-- ]-- },-- {-- str = " D"-- }-- ]--localfunctionparseFormat(str)localchr,esc,param,root,cur,prev,newlocalparams={}localfunctionnewObject(array)localobj={}-- new objectobj.str=""array[#array+1]=obj-- array{object}obj.parent=arrayreturnobjendlocalfunctionendParam()ifparam>0thenifcur.str~=""thencur.str="%"..cur.strcur.param=trueparams[cur.str]=truecur.parent.req[cur.str]=trueprev=curcur=newObject(cur.parent)endparam=0endendroot={}-- arrayroot.req={}cur=newObject(root)prev=nilesc=falseparam=0fori=1,#strdochr=str:sub(i,i)ifnotescthenifchr=='\\'thenendParam()esc=trueelseifchr=='%'thenendParam()ifcur.str~=""thencur=newObject(cur.parent)endparam=2elseifchr=='['thenendParam()ifprevandcur.str==""thentable.remove(cur.parent)cur=prevendcur.child={}-- new arraycur.child.req={}cur.child.parent=curcur=newObject(cur.child)elseifchr==']'thenendParam()ifcur.parent.parentthennew=newObject(cur.parent.parent.parent)ifcur.str==""thentable.remove(cur.parent)endcur=newendelseifparam>1thenparam=param-1elseifparam==1thenifnotchr:match('%d')thenendParam()endendcur.str=cur.str..replaceSpecialChar(chr)endelsecur.str=cur.str..chresc=falseendprev=nilendendParam()-- make sure that at least one required parameter has been definedifnotnext(root.req)thenthrowError("missing-required-parameter")end-- make sure that the separator parameter "%s" is not amongst the required parametersifroot.req[parameters.separator]thenthrowError("extra-required-parameter",parameters.separator)endreturnroot,paramsendlocalfunctionsortOnRank(claims)localrankPoslocalranks={{},{},{},{}}-- preferred, normal, deprecated, (default)localsorted={}for_,vinipairs(claims)dorankPos=rankTable[v.rank]or4ranks[rankPos][#ranks[rankPos]+1]=vendsorted=ranks[1]sorted=mergeArrays(sorted,ranks[2])sorted=mergeArrays(sorted,ranks[3])returnsortedendlocalfunctionisValueInTable(searchedItem,inputTable)for_,iteminpairs(inputTable)doifitem==searchedItemthenreturntrueendendreturnfalseendlocalConfig={}-- allows for recursive callsfunctionConfig:new()localcfg={}setmetatable(cfg,self)self.__index=selfcfg.separators={-- single value objects wrapped in arrays so that we can pass by reference["sep"]={copyTable(defaultSeparators["sep"])},["sep%s"]={copyTable(defaultSeparators["sep%s"])},["sep%q"]={copyTable(defaultSeparators["sep%q"])},["sep%r"]={copyTable(defaultSeparators["sep%r"])},["punc"]={copyTable(defaultSeparators["punc"])}}cfg.entity=nilcfg.entityID=nilcfg.propertyID=nilcfg.propertyValue=nilcfg.qualifierIDs={}cfg.qualifierIDsAndValues={}cfg.bestRank=truecfg.ranks={true,true,false}-- preferred = true, normal = true, deprecated = falsecfg.foundRank=#cfg.rankscfg.flagBest=falsecfg.flagRank=falsecfg.periods={true,true,true}-- future = true, current = true, former = truecfg.flagPeriod=falsecfg.atDate={parseDate(os.date('!%Y-%m-%d'))}-- today as {year, month, day}cfg.mdyDate=falsecfg.singleClaim=falsecfg.sourcedOnly=falsecfg.editable=falsecfg.editAtEnd=falsecfg.inSitelinks=falsecfg.langCode=mw.language.getContentLanguage().codecfg.langName=mw.language.fetchLanguageName(cfg.langCode,cfg.langCode)cfg.langObj=mw.language.new(cfg.langCode)cfg.siteID=mw.wikibase.getGlobalSiteId()cfg.states={}cfg.states.qualifiersCount=0cfg.curState=nilcfg.prefetchedRefs=nilreturncfgendlocalState={}functionState:new(cfg,type)localstt={}setmetatable(stt,self)self.__index=selfstt.conf=cfgstt.type=typestt.results={}stt.parsedFormat={}stt.separator={}stt.movSeparator={}stt.puncMark={}stt.linked=falsestt.rawValue=falsestt.shortName=falsestt.anyLanguage=falsestt.unitOnly=falsestt.singleValue=falsereturnsttend-- if id == nil then item connected to current page is usedfunctionConfig:getLabel(id,raw,link,short)locallabel=nillocalprefix,title="",nilifnotidthenid=mw.wikibase.getEntityIdForCurrentPage()ifnotidthenreturn""endendid=id:upper()-- just to be sureifrawthen-- check if given id actually existsifmw.wikibase.isValidEntityId(id)andmw.wikibase.entityExists(id)thenlabel=idendprefix,title="d:Special:EntityPage/",label-- may be nilelse-- try short name first if requestedifshortthenlabel=p._property{aliasesP.shortName,[p.args.eid]=id}-- get short nameiflabel==""thenlabel=nilendend-- get labelifnotlabelthenlabel=mw.wikibase.getLabel(id)endendifnotlabelthenlabel=""elseiflinkthen-- build a link if requestedifnottitlethenifid:sub(1,1)=="Q"thentitle=mw.wikibase.getSitelink(id)elseifid:sub(1,1)=="P"then-- properties have no sitelink, link to Wikidata insteadprefix,title="d:Special:EntityPage/",idendendlabel=mw.text.nowiki(label)-- escape raw label text so it cannot be wikitext markupiftitlethenlabel=buildWikilink(prefix..title,label)endendreturnlabelendfunctionConfig:getEditIcon()localvalue=""localprefix=""localfront=" "localback=""ifself.entityID:sub(1,1)=="P"thenprefix="Property:"endifself.editAtEndthenfront='<span style="float:'ifself.langObj:isRTL()thenfront=front..'left'elsefront=front..'right'endfront=front..'">'back='</span>'endvalue="[[File:OOjs UI icon edit-ltr-progressive.svg|frameless|text-top|10px|alt="..i18n['info']['edit-on-wikidata'].."|link=https://www.wikidata.org/wiki/"..prefix..self.entityID.."?uselang="..self.langCodeifself.propertyIDthenvalue=value.."#"..self.propertyIDelseifself.inSitelinksthenvalue=value.."#sitelinks-wikipedia"endvalue=value.."|"..i18n['info']['edit-on-wikidata'].."]]"returnfront..value..backend-- used to create the final output string when it's all done, so that for references the-- function extensionTag("ref", ...) is only called when they really ended up in the final outputfunctionConfig:concatValues(valuesArray)localoutString=""localj,skipfori=1,#valuesArraydo-- check if this is a referenceifvaluesArray[i].refHashthenj=i-1skip=false-- skip this reference if it is part of a continuous row of references that already contains the exact same referencewhilevaluesArray[j]andvaluesArray[j].refHashdoifvaluesArray[i].refHash==valuesArray[j].refHashthenskip=truebreakendj=j-1endifnotskipthen-- add <ref> tag with the reference's hash as its name (to deduplicate references)outString=outString..mw.getCurrentFrame():extensionTag("ref",valuesArray[i][1],{name=valuesArray[i].refHash})endelseoutString=outString..valuesArray[i][1]endendreturnoutStringendfunctionConfig:convertUnit(unit,raw,link,short,unitOnly)localspace=" "locallabel=""localitemIDifunit==""orunit=="1"thenreturnnilendifunitOnlythenspace=""enditemID=parseWikidataURL(unit)ifitemIDthenifitemID==aliasesQ.percentagethenreturn"%"elselabel=self:getLabel(itemID,raw,link,short)iflabel~=""thenreturnspace..labelendendendreturn""endfunctionState:getValue(snak)returnself.conf:getValue(snak,self.rawValue,self.linked,self.shortName,self.anyLanguage,self.unitOnly,false,self.type:sub(1,2))endfunctionConfig:getValue(snak,raw,link,short,anyLang,unitOnly,noSpecial,type)ifsnak.snaktype=='value'thenlocaldatatype=snak.datavalue.typelocalsubtype=snak.datatypelocaldatavalue=snak.datavalue.valueifdatatype=='string'thenifsubtype=='url'andlinkthen-- create link explicitlyifrawthen-- will render as a linked number like [1]return"["..datavalue.."]"elsereturn"["..datavalue.." "..datavalue.."]"endelseifsubtype=='commonsMedia'theniflinkthenreturnbuildWikilink("c:File:"..datavalue,datavalue)elseifnotrawthenreturn"[[File:"..datavalue.."]]"elsereturndatavalueendelseifsubtype=='geo-shape'andlinkthenreturnbuildWikilink("c:"..datavalue,datavalue)elseifsubtype=='math'andnotrawthenlocalattribute=nilif(type==parameters.propertyor(type==parameters.qualifierandself.propertyID==aliasesP.hasPart))andsnak.property==aliasesP.definingFormulathenattribute={qid=self.entityID}endreturnmw.getCurrentFrame():extensionTag("math",datavalue,attribute)elseifsubtype=='external-id'andlinkthenlocalurl=p._property{aliasesP.formatterURL,[p.args.eid]=snak.property}-- get formatter URLifurl~=""thenurl=mw.ustring.gsub(url,"$1",datavalue)return"["..url.." "..datavalue.."]"elsereturndatavalueendelsereturndatavalueendelseifdatatype=='monolingualtext'thenifanyLangordatavalue['language']==self.langCodethenreturndatavalue['text']elsereturnnilendelseifdatatype=='quantity'thenlocalvalue=""localunitifnotunitOnlythen-- get value and strip + signs from frontvalue=mw.ustring.gsub(datavalue['amount'],"^%+(.+)$","%1")ifrawthenreturnvalueend-- replace decimal mark based on localevalue=replaceDecimalMark(value)-- add delimiters for readabilityvalue=i18n.addDelimiters(value)endunit=self:convertUnit(datavalue['unit'],raw,link,short,unitOnly)ifunitthenvalue=value..unitendreturnvalueelseifdatatype=='time'thenlocaly,m,d,p,yDiv,yRound,yFull,value,calendarID,dateStrlocalyFactor=1localsign=1localprefix=""localsuffix=""localmayAddCalendar=falselocalcalendar=""localprecision=datavalue['precision']ifprecision==11thenp="d"elseifprecision==10thenp="m"elsep="y"yFactor=10^(9-precision)endy,m,d=parseDate(datavalue['time'],p)ify<0thensign=-1y=y*signend-- if precision is tens/hundreds/thousands/millions/billions of yearsifprecision<=8thenyDiv=y/yFactor-- if precision is tens/hundreds/thousands of yearsifprecision>=6thenmayAddCalendar=trueifprecision<=7then-- round centuries/millenniums up (e.g. 20th century or 3rd millennium)yRound=math.ceil(yDiv)ifnotrawthenifprecision==6thensuffix=i18n['datetime']['suffixes']['millennium']elsesuffix=i18n['datetime']['suffixes']['century']endsuffix=i18n.getOrdinalSuffix(yRound)..suffixelse-- if not verbose, take the first year of the century/millennium-- (e.g. 1901 for 20th century or 2001 for 3rd millennium)yRound=(yRound-1)*yFactor+1endelse-- precision == 8-- round decades down (e.g. 2010s)yRound=math.floor(yDiv)*yFactorifnotrawthenprefix=i18n['datetime']['prefixes']['decade-period']suffix=i18n['datetime']['suffixes']['decade-period']endendifrawandsign<0then-- if BCE then compensate for "counting backwards"-- (e.g. -2019 for 2010s BCE, -2000 for 20th century BCE or -3000 for 3rd millennium BCE)yRound=yRound+yFactor-1endelselocalyReFactor,yReDiv,yReRound-- round to nearest for tens of thousands of years or moreyRound=math.floor(yDiv+0.5)ifyRound==0thenifprecision<=2andy~=0thenyReFactor=1e6yReDiv=y/yReFactoryReRound=math.floor(yReDiv+0.5)ifyReDiv==yReRoundthen-- change precision to millions of years only if we have a whole number of themprecision=3yFactor=yReFactoryRound=yReRoundendendifyRound==0then-- otherwise, take the unrounded (original) number of yearsprecision=5yFactor=1yRound=ymayAddCalendar=trueendendifprecision>=1andy~=0thenyFull=yRound*yFactoryReFactor=1e9yReDiv=yFull/yReFactoryReRound=math.floor(yReDiv+0.5)ifyReDiv==yReRoundthen-- change precision to billions of years if we're in that rangeprecision=0yFactor=yReFactoryRound=yReRoundelseyReFactor=1e6yReDiv=yFull/yReFactoryReRound=math.floor(yReDiv+0.5)ifyReDiv==yReRoundthen-- change precision to millions of years if we're in that rangeprecision=3yFactor=yReFactoryRound=yReRoundendendendifnotrawthenifprecision==3thensuffix=i18n['datetime']['suffixes']['million-years']elseifprecision==0thensuffix=i18n['datetime']['suffixes']['billion-years']elseyRound=yRound*yFactorifyRound==1thensuffix=i18n['datetime']['suffixes']['year']elsesuffix=i18n['datetime']['suffixes']['years']endendelseyRound=yRound*yFactorendendelseyRound=ymayAddCalendar=trueendifmayAddCalendarthencalendarID=parseWikidataURL(datavalue['calendarmodel'])ifcalendarIDandcalendarID==aliasesQ.prolepticJulianCalendarthenifnotrawtheniflinkthencalendar=" ("..buildWikilink(i18n['datetime']['julian-calendar'],i18n['datetime']['julian'])..")"elsecalendar=" ("..i18n['datetime']['julian']..")"endelsecalendar="/"..i18n['datetime']['julian']endendendifnotrawthenlocalce=nilifsign<0thence=i18n['datetime']['BCE']elseifprecision<=5thence=i18n['datetime']['CE']endifcetheniflinkthence=buildWikilink(i18n['datetime']['common-era'],ce)endsuffix=suffix.." "..ceendvalue=tostring(yRound)ifmthendateStr=self.langObj:formatDate("F","1-"..m.."-1")ifdthenifself.mdyDatethendateStr=dateStr.." "..d..","elsedateStr=d.." "..dateStrendendvalue=dateStr.." "..valueendvalue=prefix..value..suffix..calendarelsevalue=padZeros(yRound*sign,4)ifmthenvalue=value.."-"..padZeros(m,2)ifdthenvalue=value.."-"..padZeros(d,2)endendvalue=value..calendarendreturnvalueelseifdatatype=='globecoordinate'then-- logic from https://github.com/DataValues/Geo (v4.0.1)localprecision,unitsPerDegree,numDigits,strFormat,value,globelocallatitude,latConv,latValue,latLinklocallongitude,lonConv,lonValue,lonLinklocallatDirection,latDirectionN,latDirectionS,latDirectionENlocallonDirection,lonDirectionE,lonDirectionW,lonDirectionENlocaldegSymbol,minSymbol,secSymbol,separatorlocallatDegrees=nillocallatMinutes=nillocallatSeconds=nillocallonDegrees=nillocallonMinutes=nillocallonSeconds=nillocallatDegSym=""locallatMinSym=""locallatSecSym=""locallonDegSym=""locallonMinSym=""locallonSecSym=""locallatDirectionEN_N="N"locallatDirectionEN_S="S"locallonDirectionEN_E="E"locallonDirectionEN_W="W"ifnotrawthenlatDirectionN=i18n['coord']['latitude-north']latDirectionS=i18n['coord']['latitude-south']lonDirectionE=i18n['coord']['longitude-east']lonDirectionW=i18n['coord']['longitude-west']degSymbol=i18n['coord']['degrees']minSymbol=i18n['coord']['minutes']secSymbol=i18n['coord']['seconds']separator=i18n['coord']['separator']elselatDirectionN=latDirectionEN_NlatDirectionS=latDirectionEN_SlonDirectionE=lonDirectionEN_ElonDirectionW=lonDirectionEN_WdegSymbol="/"minSymbol="/"secSymbol="/"separator="/"endlatitude=datavalue['latitude']longitude=datavalue['longitude']iflatitude<0thenlatDirection=latDirectionSlatDirectionEN=latDirectionEN_Slatitude=math.abs(latitude)elselatDirection=latDirectionNlatDirectionEN=latDirectionEN_Nendiflongitude<0thenlonDirection=lonDirectionWlonDirectionEN=lonDirectionEN_Wlongitude=math.abs(longitude)elselonDirection=lonDirectionElonDirectionEN=lonDirectionEN_Eendprecision=datavalue['precision']ifnotprecisionorprecision<=0thenprecision=1/3600-- precision not set (correctly), set to arcsecondend-- remove insignificant detaillatitude=math.floor(latitude/precision+0.5)*precisionlongitude=math.floor(longitude/precision+0.5)*precisionifprecision>=1-(1/60)andprecision<1thenprecision=1elseifprecision>=(1/60)-(1/3600)andprecision<(1/60)thenprecision=1/60endifprecision>=1thenunitsPerDegree=1elseifprecision>=(1/60)thenunitsPerDegree=60elseunitsPerDegree=3600endnumDigits=math.ceil(-math.log10(unitsPerDegree*precision))ifnumDigits<=0thennumDigits=tonumber("0")-- for some reason, 'numDigits = 0' may actually store '-0', so parse from string insteadendstrFormat="%."..numDigits.."f"ifprecision>=1thenlatDegrees=strFormat:format(latitude)lonDegrees=strFormat:format(longitude)ifnotrawthenlatDegSym=replaceDecimalMark(latDegrees)..degSymbollonDegSym=replaceDecimalMark(lonDegrees)..degSymbolelselatDegSym=latDegrees..degSymbollonDegSym=lonDegrees..degSymbolendelselatConv=math.floor(latitude*unitsPerDegree*10^numDigits+0.5)/10^numDigitslonConv=math.floor(longitude*unitsPerDegree*10^numDigits+0.5)/10^numDigitsifprecision>=(1/60)thenlatMinutes=latConvlonMinutes=lonConvelselatSeconds=latConvlonSeconds=lonConvlatMinutes=math.floor(latSeconds/60)lonMinutes=math.floor(lonSeconds/60)latSeconds=strFormat:format(latSeconds-(latMinutes*60))lonSeconds=strFormat:format(lonSeconds-(lonMinutes*60))ifnotrawthenlatSecSym=replaceDecimalMark(latSeconds)..secSymbollonSecSym=replaceDecimalMark(lonSeconds)..secSymbolelselatSecSym=latSeconds..secSymbollonSecSym=lonSeconds..secSymbolendendlatDegrees=math.floor(latMinutes/60)lonDegrees=math.floor(lonMinutes/60)latDegSym=latDegrees..degSymbollonDegSym=lonDegrees..degSymbollatMinutes=latMinutes-(latDegrees*60)lonMinutes=lonMinutes-(lonDegrees*60)ifprecision>=(1/60)thenlatMinutes=strFormat:format(latMinutes)lonMinutes=strFormat:format(lonMinutes)ifnotrawthenlatMinSym=replaceDecimalMark(latMinutes)..minSymbollonMinSym=replaceDecimalMark(lonMinutes)..minSymbolelselatMinSym=latMinutes..minSymbollonMinSym=lonMinutes..minSymbolendelselatMinSym=latMinutes..minSymbollonMinSym=lonMinutes..minSymbolendendlatValue=latDegSym..latMinSym..latSecSym..latDirectionlonValue=lonDegSym..lonMinSym..lonSecSym..lonDirectionvalue=latValue..separator..lonValueiflinkthenglobe=parseWikidataURL(datavalue['globe'])ifglobethenglobe=mw.wikibase.getLabelByLang(globe,"en"):lower()elseglobe="earth"endlatLink=table.concat({latDegrees,latMinutes,latSeconds},"_")lonLink=table.concat({lonDegrees,lonMinutes,lonSeconds},"_")value="[https://geohack.toolforge.org/geohack.php?language="..self.langCode.."¶ms="..latLink.."_"..latDirectionEN.."_"..lonLink.."_"..lonDirectionEN.."_globe:"..globe.." "..value.."]"endreturnvalueelseifdatatype=='wikibase-entityid'thenlocallabellocalitemID=datavalue['numeric-id']ifsubtype=='wikibase-item'thenitemID="Q"..itemIDelseifsubtype=='wikibase-property'thenitemID="P"..itemIDelsereturn'<strong class="error">'..errorText('unknown-data-type',subtype)..'</strong>'endlabel=self:getLabel(itemID,raw,link,short)iflabel==""thenlabel=nilendreturnlabelelsereturn'<strong class="error">'..errorText('unknown-data-type',datatype)..'</strong>'endelseifsnak.snaktype=='somevalue'andnotnoSpecialthenifrawthenreturn" "-- single space represents 'somevalue'elsereturni18n['values']['unknown']endelseifsnak.snaktype=='novalue'andnotnoSpecialthenifrawthenreturn""-- empty string represents 'novalue'elsereturni18n['values']['none']endelsereturnnilendendfunctionConfig:getSingleRawQualifier(claim,qualifierID)localqualifiersifclaim.qualifiersthenqualifiers=claim.qualifiers[qualifierID]endifqualifiersandqualifiers[1]thenreturnself:getValue(qualifiers[1],true)-- raw = trueelsereturnnilendendfunctionConfig:snakEqualsValue(snak,value)localsnakValue=self:getValue(snak,true)-- raw = trueifsnakValueandsnak.snaktype=='value'andsnak.datavalue.type=='wikibase-entityid'thenvalue=value:upper()endreturnsnakValue==valueendfunctionConfig:setRank(rank)localrankPosifrank==p.flags.bestthenself.bestRank=trueself.flagBest=true-- mark that 'best' flag was givenreturnendifrank:sub(1,9)==p.flags.preferredthenrankPos=1elseifrank:sub(1,6)==p.flags.normalthenrankPos=2elseifrank:sub(1,10)==p.flags.deprecatedthenrankPos=3elsereturnend-- one of the rank flags was given, check if another one was given beforeifnotself.flagRankthenself.ranks={false,false,false}-- no other rank flag given before, so unset ranksself.bestRank=self.flagBest-- unsets bestRank only if 'best' flag was not given beforeself.flagRank=true-- mark that a rank flag was givenendifrank:sub(-1)=="+"thenfori=rankPos,1,-1doself.ranks[i]=trueendelseifrank:sub(-1)=="-"thenfori=rankPos,#self.ranksdoself.ranks[i]=trueendelseself.ranks[rankPos]=trueendendfunctionConfig:setPeriod(period)localperiodPosifperiod==p.flags.futurethenperiodPos=1elseifperiod==p.flags.currentthenperiodPos=2elseifperiod==p.flags.formerthenperiodPos=3elsereturnend-- one of the period flags was given, check if another one was given beforeifnotself.flagPeriodthenself.periods={false,false,false}-- no other period flag given before, so unset periodsself.flagPeriod=true-- mark that a period flag was givenendself.periods[periodPos]=trueendfunctionConfig:qualifierMatches(claim,id,value)localqualifiersifclaim.qualifiersthenqualifiers=claim.qualifiers[id]endifqualifiersthenfor_,vinpairs(qualifiers)doifself:snakEqualsValue(v,value)thenreturntrueendendelseifvalue==""then-- if the qualifier is not present then treat it the same as the special value 'novalue'returntrueendreturnfalseendfunctionConfig:rankMatches(rankPos)ifself.bestRankthenreturn(self.ranks[rankPos]andself.foundRank>=rankPos)elsereturnself.ranks[rankPos]endendfunctionConfig:timeMatches(claim)localstartTime=nillocalstartTimeY=nillocalstartTimeM=nillocalstartTimeD=nillocalendTime=nillocalendTimeY=nillocalendTimeM=nillocalendTimeD=nilifself.periods[1]andself.periods[2]andself.periods[3]then-- any timereturntrueendstartTime=self:getSingleRawQualifier(claim,aliasesP.startTime)ifstartTimeandstartTime~=""andstartTime~=" "thenstartTimeY,startTimeM,startTimeD=parseDate(startTime)endendTime=self:getSingleRawQualifier(claim,aliasesP.endTime)ifendTimeandendTime~=""andendTime~=" "thenendTimeY,endTimeM,endTimeD=parseDate(endTime)endifstartTimeY~=nilandendTimeY~=nilanddatePrecedesDate(endTimeY,endTimeM,endTimeD,startTimeY,startTimeM,startTimeD)then-- invalidate end time if it precedes start timeendTimeY=nilendTimeM=nilendTimeD=nilendifself.periods[1]then-- futureifstartTimeYanddatePrecedesDate(self.atDate[1],self.atDate[2],self.atDate[3],startTimeY,startTimeM,startTimeD)thenreturntrueendendifself.periods[2]then-- currentif(startTimeY==nilornotdatePrecedesDate(self.atDate[1],self.atDate[2],self.atDate[3],startTimeY,startTimeM,startTimeD))and(endTimeY==nilordatePrecedesDate(self.atDate[1],self.atDate[2],self.atDate[3],endTimeY,endTimeM,endTimeD))thenreturntrueendendifself.periods[3]then-- formerifendTimeYandnotdatePrecedesDate(self.atDate[1],self.atDate[2],self.atDate[3],endTimeY,endTimeM,endTimeD)thenreturntrueendendreturnfalseendfunctionConfig:processFlag(flag)ifnotflagthenreturnfalseendifflag==p.flags.linkedthenself.curState.linked=truereturntrueelseifflag==p.flags.rawthenself.curState.rawValue=trueifself.curState==self.states[parameters.reference]then-- raw reference values end with periods and require a separator (other than none)self.separators["sep%r"][1]={" "}endreturntrueelseifflag==p.flags.shortthenself.curState.shortName=truereturntrueelseifflag==p.flags.multilanguagethenself.curState.anyLanguage=truereturntrueelseifflag==p.flags.unitthenself.curState.unitOnly=truereturntrueelseifflag==p.flags.mdythenself.mdyDate=truereturntrueelseifflag==p.flags.singlethenself.singleClaim=truereturntrueelseifflag==p.flags.sourcedthenself.sourcedOnly=truereturntrueelseifflag==p.flags.editthenself.editable=truereturntrueelseifflag==p.flags.editAtEndthenself.editable=trueself.editAtEnd=truereturntrueelseifflag==p.flags.bestorflag:match('^'..p.flags.preferred..'[+-]?$')orflag:match('^'..p.flags.normal..'[+-]?$')orflag:match('^'..p.flags.deprecated..'[+-]?$')thenself:setRank(flag)returntrueelseifflag==p.flags.futureorflag==p.flags.currentorflag==p.flags.formerthenself:setPeriod(flag)returntrueelseifflag==""then-- ignore empty flags and carry onreturntrueelsereturnfalseendendfunctionConfig:processFlagOrCommand(flag)localparam=""ifnotflagthenreturnfalseendifflag==p.claimCommands.propertyorflag==p.claimCommands.propertiesthenparam=parameters.propertyelseifflag==p.claimCommands.qualifierorflag==p.claimCommands.qualifiersthenself.states.qualifiersCount=self.states.qualifiersCount+1param=parameters.qualifier..self.states.qualifiersCountself.separators["sep"..param]={copyTable(defaultSeparators["sep%q\\d"])}elseifflag==p.claimCommands.referenceorflag==p.claimCommands.referencesthenparam=parameters.referenceelsereturnself:processFlag(flag)endifself.states[param]thenreturnfalseend-- create a new state for each commandself.states[param]=State:new(self,param)-- use "%x" as the general parameter nameself.states[param].parsedFormat=parseFormat(parameters.general)-- will be overwritten for param=="%p"-- set the separatorself.states[param].separator=self.separators["sep"..param]-- will be nil for param=="%p", which will be set separatelyifflag==p.claimCommands.propertyorflag==p.claimCommands.qualifierorflag==p.claimCommands.referencethenself.states[param].singleValue=trueendself.curState=self.states[param]returntrueendfunctionConfig:processSeparators(args)localsepfori,vinpairs(self.separators)doifargs[i]thensep=replaceSpecialChars(args[i])ifsep~=""thenself.separators[i][1]={sep}elseself.separators[i][1]=nilendendendendfunctionConfig:setFormatAndSeparators(state,parsedFormat)state.parsedFormat=parsedFormatstate.separator=self.separators["sep"]state.movSeparator=self.separators["sep"..parameters.separator]state.puncMark=self.separators["punc"]end-- determines if a claim has references by prefetching them from the claim using getReferences,-- which applies some filtering that determines if a reference is actually returned,-- and caches the references for later usefunctionState:isSourced(claim)self.conf.prefetchedRefs=self:getReferences(claim)return(#self.conf.prefetchedRefs>0)endfunctionState:resetCaches()-- any prefetched references of the previous claim must not be usedself.conf.prefetchedRefs=nilendfunctionState:claimMatches(claim)localmatches,rankPos-- first of all, reset any cached values used for the previous claimself:resetCaches()-- if a property value was given, check if it matches the claim's property valueifself.conf.propertyValuethenmatches=self.conf:snakEqualsValue(claim.mainsnak,self.conf.propertyValue)elsematches=trueend-- if any qualifier values were given, check if each matches one of the claim's qualifier valuesfori,vinpairs(self.conf.qualifierIDsAndValues)domatches=(matchesandself.conf:qualifierMatches(claim,i,v))end-- check if the claim's rank and time period matchrankPos=rankTable[claim.rank]or4matches=(matchesandself.conf:rankMatches(rankPos)andself.conf:timeMatches(claim))-- if only claims with references must be returned, check if this one has anyifself.conf.sourcedOnlythenmatches=(matchesandself:isSourced(claim))-- prefetches and caches referencesendreturnmatches,rankPosendfunctionState:out()localresult-- collection of arrays with value objectslocalvaluesArray-- array with value objectslocalsep=nil-- value objectlocalout={}-- array with value objectslocalfunctionwalk(formatTable,result)localvaluesArray={}-- array with value objectsfori,vinpairs(formatTable.req)doifnotresult[i]ornotresult[i][1]then-- we've got no result for a parameter that is required on this level,-- so skip this level (and its children) by returning an empty resultreturn{}endendfor_,vinipairs(formatTable)doifv.paramthenvaluesArray=mergeArrays(valuesArray,result[v.str])elseifv.str~=""thenvaluesArray[#valuesArray+1]={v.str}endifv.childthenvaluesArray=mergeArrays(valuesArray,walk(v.child,result))endendreturnvaluesArrayend-- iterate through the results from back to front, so that we know when to add separatorsfori=#self.results,1,-1doresult=self.results[i]-- if there is already some output, then add the separatorsif#out>0thensep=self.separator[1]-- fixed separatorresult[parameters.separator]={self.movSeparator[1]}-- movable separatorelsesep=nilresult[parameters.separator]={self.puncMark[1]}-- optional punctuation markendvaluesArray=walk(self.parsedFormat,result)if#valuesArray>0thenifsepthenvaluesArray[#valuesArray+1]=sependout=mergeArrays(valuesArray,out)endend-- reset state before next iterationself.results={}returnoutend-- level 1 hookfunctionState:getProperty(claim)localvalue={self:getValue(claim.mainsnak)}-- create one value objectif#value>0thenreturn{value}-- wrap the value object in an array and return itelsereturn{}-- return empty array if there was no valueendend-- level 1 hookfunctionState:getQualifiers(claim,param)localqualifiersifclaim.qualifiersthenqualifiers=claim.qualifiers[self.conf.qualifierIDs[param]]endifqualifiersthen-- iterate through claim's qualifier statements to collect their values;-- return array with multiple value objectsreturnself.conf.states[param]:iterate(qualifiers,{[parameters.general]=hookNames[parameters.qualifier.."\\d"][2],count=1})-- pass qualifier state with level 2 hookelsereturn{}-- return empty arrayendend-- level 2 hookfunctionState:getQualifier(snak)localvalue={self:getValue(snak)}-- create one value objectif#value>0thenreturn{value}-- wrap the value object in an array and return itelsereturn{}-- return empty array if there was no valueendend-- level 1 hookfunctionState:getAllQualifiers(claim,param,result,hooks)localout={}-- array with value objectslocalsep=self.conf.separators["sep"..parameters.qualifier][1]-- value object-- iterate through the output of the separate "qualifier(s)" commandsfori=1,self.conf.states.qualifiersCountdo-- if a hook has not been called yet, call it nowifnotresult[parameters.qualifier..i]thenself:callHook(parameters.qualifier..i,hooks,claim,result)end-- if there is output for this particular "qualifier(s)" command, then add itifresult[parameters.qualifier..i]andresult[parameters.qualifier..i][1]then-- if there is already some output, then add the separatorif#out>0andsepthenout[#out+1]=sependout=mergeArrays(out,result[parameters.qualifier..i])endendreturnoutend-- level 1 hookfunctionState:getReferences(claim)ifself.conf.prefetchedRefsthen-- return references that have been prefetched by isSourcedreturnself.conf.prefetchedRefsendifclaim.referencesthen-- iterate through claim's reference statements to collect their values;-- return array with multiple value objectsreturnself.conf.states[parameters.reference]:iterate(claim.references,{[parameters.general]=hookNames[parameters.reference][2],count=1})-- pass reference state with level 2 hookelsereturn{}-- return empty arrayendend-- level 2 hookfunctionState:getReference(statement)localciteParamMapping=i18n['cite']['param-mapping']localciteConfig=i18n['cite']['config']localciteTypes=i18n['cite']['output-types']-- will hold rendered properties of the reference which are not directly from statement.snaks, -- Namely, these are a backup title from "subject named as" and a URL generated from an external ID.localadditionalProcessedProperties={}-- for each citation type, there will be an associative array that associates lists of rendered properties-- to citation-template parameterslocalgroupedProcessedProperties={}-- like above, but only associates one rendered property to each parameter; if the above variable-- contains more strings for a parameter, the strings will be assigned to numbered params (e.g. "author1")localciteParams={}localciteErrors={}localreferenceEmpty=true-- will be set to false if at least one parameter is left unremovedlocalversion=11-- increment this each time the below logic is changed to avoid conflict errorsifnotstatement.snaksthenreturn{}end-- don't use bot-added references referencing Wikimedia projects or containing "inferred from" (such references are not usable on Wikipedia)ifstatement.snaks[aliasesP.importedFrom]orstatement.snaks[aliasesP.wikimediaImportURL]orstatement.snaks[aliasesP.inferredFrom]thenreturn{}end-- don't include "type of reference"ifstatement.snaks[aliasesP.typeOfReference]thenstatement.snaks[aliasesP.typeOfReference]=nilend-- don't include "image" to prevent litteringifstatement.snaks[aliasesP.image]thenstatement.snaks[aliasesP.image]=nilend-- don't include "language" if it is equal to the local oneifself:getReferenceDetail(statement.snaks,aliasesP.language)==self.conf.langNamethenstatement.snaks[aliasesP.language]=nilendifstatement.snaks[aliasesP.statedIn]andnotstatement.snaks[aliasesP.referenceURL]then-- "stated in" was given but "reference URL" was not.-- get "Wikidata property" properties from the item in "stated in"-- if any of the returned properties of the external-id datatype is in statement.snaks, generate a link from it and use the link in the reference-- find the "Wikidata property" properties in the item from "stated in"localwikidataPropertiesOfSource=mw.text.split(p._properties{p.flags.raw,aliasesP.wikidataProperty,[p.args.eid]=self.conf:getValue(statement.snaks[aliasesP.statedIn][1],true,false)},", ",true)fori,wikidataPropertyOfSourceinpairs(wikidataPropertiesOfSource)doifstatement.snaks[wikidataPropertyOfSource]andstatement.snaks[wikidataPropertyOfSource][1].datatype=="external-id"thenlocaltempLink=self:getReferenceDetail(statement.snaks,wikidataPropertyOfSource,false,true)-- not raw, linkedifmw.ustring.match(tempLink,"^%[%Z- %Z+%]$")then-- getValue returned a URL in square brackets.-- the link is in wiki markup, so strip the square brackets and the display text-- gsub also returns another, discarted value, therefore the result is assigned to tempLink firsttempLink=mw.ustring.gsub(tempLink,"^%[(%Z-) %Z+%]$","%1")additionalProcessedProperties[aliasesP.referenceURL]={tempLink}statement.snaks[wikidataPropertyOfSource]=nilbreakendendendend-- don't include "subject named as", but use it as the title when "title" is not present but a URL isifstatement.snaks[aliasesP.subjectNamedAs]thenifnotstatement.snaks[aliasesP.title]and(statement.snaks[aliasesP.referenceURL]oradditionalProcessedProperties[aliasesP.referenceURL])thenadditionalProcessedProperties[aliasesP.title]={self:getReferenceDetail(statement.snaks,aliasesP.subjectNamedAs,false,false,true)}-- not raw, not linked, anyLangendstatement.snaks[aliasesP.subjectNamedAs]=nilend-- initialize groupedProcessedProperties and citeParamsfor_,citeTypeinipairs(citeTypes)dogroupedProcessedProperties[citeType]={}citeParams[citeType]={}end-- fill groupedProcessedPropertiesforrefPropertyinpairs(statement.snaks)do-- add the parameter to each matching type of citationfor_,citeTypeinipairs(citeTypes)dorepeat-- just a simple wrapper to emulate "continue"-- skip if there already have been errorsifciteErrors[citeType]thenbreakend-- set mappingKey and prefixlocalmappingKeylocalprefix=""ifstatement.snaks[refProperty][1].datatype=='external-id'thenmappingKey="external-id"prefix=self.conf:getLabel(refProperty)ifprefix~=""thenprefix=prefix.." "endelsemappingKey=refPropertyendlocalparamName=citeParamMapping[citeType][mappingKey]-- skip properties with empty parameter nameifparamName==""thenbreakendreferenceEmpty=false-- handle unknown properties in the referenceifnotparamNamethenlocalerror_message=errorText("unknown-property-in-ref",refProperty)assert(error_message)-- Should not be nilciteErrors[citeType]=error_messagebreakend-- set processedPropertylocalprocessedPropertylocalraw=false-- if the value is wanted rawifisValueInTable(paramName,citeConfig[citeType]["raw-value-params"]or{})thenraw=trueendifisValueInTable(paramName,citeConfig[citeType]["numbered-params"]or{})then-- Multiple values may be given.processedProperty=self:getReferenceDetails(statement.snaks,refProperty,raw,self.linked,true)-- anyLang = trueelse-- If multiple values are given, all but the first suitable one are discarted.processedProperty={self:getReferenceDetail(statement.snaks,refProperty,raw,self.linkedand(statement.snaks[refProperty][1].datatype~='url'),true)}-- link = true/false, anyLang = trueendif#processedProperty==0thenbreakend-- add an entry to groupedProcessedPropertiesifnotgroupedProcessedProperties[citeType][paramName]thengroupedProcessedProperties[citeType][paramName]={}endfor_,propertyValueinpairs(processedProperty)dotable.insert(groupedProcessedProperties[citeType][paramName],prefix..propertyValue)enduntiltrueendend-- handle additional propertiesforrefPropertyinpairs(additionalProcessedProperties)dofor_,citeTypeinipairs(citeTypes)dorepeat-- skip if there already have been errorsifciteErrors[citeType]thenbreakendlocalparamName=citeParamMapping[citeType][refProperty]-- handle unknown properties in the referenceifnotparamNamethen-- Skip this additional property, but do not cause an error.breakendifparamName==""thenbreakendreferenceEmpty=falseifnotgroupedProcessedProperties[citeType][paramName]thengroupedProcessedProperties[citeType][paramName]={}endfor_,propertyValueinpairs(additionalProcessedProperties[refProperty])dotable.insert(groupedProcessedProperties[citeType][paramName],propertyValue)enduntiltrueendend-- fill citeParamsfor_,citeTypeinipairs(citeTypes)doforparamName,paramValuesinpairs(groupedProcessedProperties[citeType])doif#paramValues==1ornotisValueInTable(paramName,citeConfig[citeType]["numbered-params"]or{})thenciteParams[citeType][paramName]=paramValues[1]else-- There is more than one value for this parameter - the values will-- go into separate numbered parameters (e.g. "author1", "author2")forparamNum,paramValueinpairs(paramValues)dociteParams[citeType][paramName..paramNum]=paramValueendendendend-- handle missing mandatory parameters for the templatesfor_,citeTypeinipairs(citeTypes)dofor_,requiredCiteParaminpairs(citeConfig[citeType]["mandatory-params"]or{})doifnotciteParams[citeType][requiredCiteParam]then-- The required param is not present.ifciteErrors[citeType]then-- Do not override the previous error, if it exists.breakendlocalerror_message=errorText("missing-mandatory-param",requiredCiteParam)assert(error_message)-- Should not be nilciteErrors[citeType]=error_messageendendendlocalciteTypeToUse=nil-- choose the output templatefor_,citeTypeinipairs(citeTypes)doifnotciteErrors[citeType]thenciteTypeToUse=citeTypebreakendend-- set refContentlocalrefContent=""ifciteTypeToUsethenlocaltemplateToUse=citeConfig[citeTypeToUse]["template"]localparamsToUse=citeParams[citeTypeToUse]ifnottemplateToUseortemplateToUse==""thenthrowError("no-such-reference-template",tostring(templateToUse),i18nPath,citeTypeToUse)end-- if this module is being substituted then build a regular template call, otherwise expand the templateifmw.isSubsting()thenfori,vinpairs(paramsToUse)dorefContent=refContent.."|"..i.."="..vendrefContent="{{"..templateToUse..refContent.."}}"elsexpcall(function()refContent=mw.getCurrentFrame():expandTemplate{title=templateToUse,args=paramsToUse}end,function()throwError("no-such-reference-template",templateToUse,i18nPath,citeTypeToUse)end)end-- If the citation couldn't be displayed using any template, but is not empty (barring ignored propeties), throw an error.elseifnotreferenceEmptythenrefContent=errorText("malformed-reference-header")for_,citeTypeinipairs(citeTypes)dorefContent=refContent..errorText("template-failure-reason",citeConfig[citeType]["template"],citeErrors[citeType])endrefContent=refContent..errorText("malformed-reference-footer")end-- wrap refContentlocalref={}ifrefContent~=""thenref={refContent}ifnotself.rawValuethen-- this should become a <ref> tag, so save the reference's hash for laterref.refHash="wikidata-"..statement.hash.."-v"..(tonumber(i18n['version'])+version)endreturn{ref}elsereturn{}endend-- gets a detail of one particular type for a referencefunctionState:getReferenceDetail(snaks,dType,raw,link,anyLang)localswitchLang=anyLanglocalvalue=nilifnotsnaks[dType]thenreturnnilend-- if anyLang, first try the local language and otherwise any languagerepeatfor_,vinipairs(snaks[dType])dovalue=self.conf:getValue(v,raw,link,false,anyLangandnotswitchLang,false,true)-- noSpecial = trueifvaluethenbreakendendifvalueornotanyLangthenbreakendswitchLang=notswitchLanguntilanyLangandswitchLangreturnvalueend-- gets the details of one particular type for a referencefunctionState:getReferenceDetails(snaks,dType,raw,link,anyLang)localvalues={}ifnotsnaks[dType]thenreturn{}endfor_,vinipairs(snaks[dType])do-- if nil is returned then it will not be added to the tablevalues[#values+1]=self.conf:getValue(v,raw,link,false,anyLang,false,true)-- noSpecial = trueendreturnvaluesend-- level 1 hookfunctionState:getAlias(object)localvalue=object.valuelocaltitle=nilifvalueandself.linkedthenifself.conf.entityID:sub(1,1)=="Q"thentitle=mw.wikibase.getSitelink(self.conf.entityID)elseifself.conf.entityID:sub(1,1)=="P"thentitle="d:Property:"..self.conf.entityIDendiftitlethenvalue=buildWikilink(title,value)endendvalue={value}-- create one value objectif#value>0thenreturn{value}-- wrap the value object in an array and return itelsereturn{}-- return empty array if there was no valueendend-- level 1 hookfunctionState:getBadge(value)value=self.conf:getLabel(value,self.rawValue,self.linked,self.shortName)ifvalue==""thenvalue=nilendvalue={value}-- create one value objectif#value>0thenreturn{value}-- wrap the value object in an array and return itelsereturn{}-- return empty array if there was no valueendendfunctionState:callHook(param,hooks,statement,result)-- call a parameter's hook if it has been defined and if it has not been called beforeifnotresult[param]andhooks[param]thenlocalvaluesArray=self[hooks[param]](self,statement,param,result,hooks)-- array with value objects-- add to the resultif#valuesArray>0thenresult[param]=valuesArrayresult.count=result.count+1elseresult[param]={}-- an empty array to indicate that we've tried this hook alreadyreturntrue-- miss == trueendendreturnfalseend-- iterate through claims, claim's qualifiers or claim's references to collect valuesfunctionState:iterate(statements,hooks,matchHook)matchHook=matchHookoralwaysTruelocalmatches=falselocalrankPos=nillocalresult,gotRequiredfor_,vinipairs(statements)do-- rankPos will be nil for non-claim statements (e.g. qualifiers, references, etc.)matches,rankPos=matchHook(self,v)ifmatchesthenresult={count=0}-- collection of arrays with value objectslocalfunctionwalk(formatTable)localmissfori2,v2inpairs(formatTable.req)do-- call a hook, adding its return value to the resultmiss=self:callHook(i2,hooks,v,result)ifmissthen-- we miss a required value for this level, so return falsereturnfalseendifresult.count==hooks.countthen-- we're done if all hooks have been called;-- returning at this point breaks the loopreturntrueendendfor_,v2inipairs(formatTable)doifresult.count==hooks.countthen-- we're done if all hooks have been called;-- returning at this point prevents further childs from being processedreturntrueendifv2.childthenwalk(v2.child)endendreturntrueendgotRequired=walk(self.parsedFormat)-- only append the result if we got values for all required parameters on the root levelifgotRequiredthen-- if we have a rankPos (only with matchHook() for complete claims), then update the foundRankifrankPosandself.conf.foundRank>rankPosthenself.conf.foundRank=rankPosend-- append the resultself.results[#self.results+1]=result-- break if we only need a single valueifself.singleValuethenbreakendendendendreturnself:out()endlocalfunctiongetEntityId(arg,eid,page,allowOmitPropPrefix,globalSiteId)localid=nillocalprop=nilifargthenifarg:sub(1,1)==":"thenpage=argeid=nilelseifarg:sub(1,1):upper()=="Q"orarg:sub(1,9):lower()=="property:"orallowOmitPropPrefixtheneid=argpage=nilelseprop=argendendifeidthenifeid:sub(1,9):lower()=="property:"thenid=replaceAlias(mw.text.trim(eid:sub(10)))ifid:sub(1,1):upper()~="P"thenid=""endelseid=replaceAlias(eid)endelseifpagethenifpage:sub(1,1)==":"thenpage=mw.text.trim(page:sub(2))endid=mw.wikibase.getEntityIdForTitle(page,globalSiteId)or""endifnotidthenid=mw.wikibase.getEntityIdForCurrentPage()or""endid=id:upper()ifnotmw.wikibase.isValidEntityId(id)thenid=""endreturnid,propendlocalfunctionnextArg(args)localarg=args[args.pointer]ifargthenargs.pointer=args.pointer+1returnmw.text.trim(arg)elsereturnnilendendlocalfunctionclaimCommand(args,funcName)localcfg=Config:new()cfg:processFlagOrCommand(funcName)-- process first command (== function name)locallastArg,parsedFormat,formatParams,claims,valuelocalhooks={count=0}-- set the date if given;-- must come BEFORE processing the flagsifargs[p.args.date]thencfg.atDate={parseDate(args[p.args.date])}cfg.periods={false,true,false}-- change default time constraint to 'current'end-- process flags and commandsrepeatlastArg=nextArg(args)untilnotcfg:processFlagOrCommand(lastArg)-- get the entity ID from either the positional argument, the eid argument or the page argumentcfg.entityID,cfg.propertyID=getEntityId(lastArg,args[p.args.eid],args[p.args.page],false,args[p.args.globalSiteId])ifcfg.entityID==""thenreturn""-- we cannot continue without a valid entity IDendcfg.entity=mw.wikibase.getEntity(cfg.entityID)ifnotcfg.propertyIDthencfg.propertyID=nextArg(args)endcfg.propertyID=replaceAlias(cfg.propertyID)ifnotcfg.entityornotcfg.propertyIDthenreturn""-- we cannot continue without an entity or a property IDendcfg.propertyID=cfg.propertyID:upper()ifnotcfg.entity.claimsornotcfg.entity.claims[cfg.propertyID]thenreturn""-- there is no use to continue without any claimsendclaims=cfg.entity.claims[cfg.propertyID]ifcfg.states.qualifiersCount>0then-- do further processing if "qualifier(s)" command was givenif#args-args.pointer+1>cfg.states.qualifiersCountthen-- claim ID or literal value has been givencfg.propertyValue=nextArg(args)endfori=1,cfg.states.qualifiersCountdo-- check if given qualifier ID is an alias and add itcfg.qualifierIDs[parameters.qualifier..i]=replaceAlias(nextArg(args)or""):upper()endelseifcfg.states[parameters.reference]then-- do further processing if "reference(s)" command was givencfg.propertyValue=nextArg(args)end-- check for special property value 'somevalue' or 'novalue'ifcfg.propertyValuethencfg.propertyValue=replaceSpecialChars(cfg.propertyValue)ifcfg.propertyValue~=""andmw.text.trim(cfg.propertyValue)==""thencfg.propertyValue=" "-- single space represents 'somevalue', whereas empty string represents 'novalue'elsecfg.propertyValue=mw.text.trim(cfg.propertyValue)endend-- parse the desired format, or choose an appropriate formatifargs["format"]thenparsedFormat,formatParams=parseFormat(args["format"])elseifcfg.states.qualifiersCount>0then-- "qualifier(s)" command givenifcfg.states[parameters.property]then-- "propert(y|ies)" command givenparsedFormat,formatParams=parseFormat(formats.propertyWithQualifier)elseparsedFormat,formatParams=parseFormat(formats.qualifier)endelseifcfg.states[parameters.property]then-- "propert(y|ies)" command givenparsedFormat,formatParams=parseFormat(formats.property)else-- "reference(s)" command givenparsedFormat,formatParams=parseFormat(formats.reference)end-- if a "qualifier(s)" command and no "propert(y|ies)" command has been given, make the movable separator a semicolonifcfg.states.qualifiersCount>0andnotcfg.states[parameters.property]thencfg.separators["sep"..parameters.separator][1]={";"}end-- if only "reference(s)" has been given, set the default separator to none (except when raw)ifcfg.states[parameters.reference]andnotcfg.states[parameters.property]andcfg.states.qualifiersCount==0andnotcfg.states[parameters.reference].rawValuethencfg.separators["sep"][1]=nilend-- if exactly one "qualifier(s)" command has been given, make "sep%q" point to "sep%q1" to make them equivalentifcfg.states.qualifiersCount==1thencfg.separators["sep"..parameters.qualifier]=cfg.separators["sep"..parameters.qualifier.."1"]end-- process overridden separator values;-- must come AFTER tweaking the default separatorscfg:processSeparators(args)-- define the hooks that should be called (getProperty, getQualifiers, getReferences);-- only define a hook if both its command ("propert(y|ies)", "reference(s)", "qualifier(s)") and its parameter ("%p", "%r", "%q1", "%q2", "%q3") have been givenfori,vinpairs(cfg.states)do-- e.g. 'formatParams["%q1"] or formatParams["%q"]' to define hook even if "%q1" was not defined to be able to build a complete value for "%q"ifformatParams[i]orformatParams[i:sub(1,2)]thenhooks[i]=getHookName(i,1)hooks.count=hooks.count+1endend-- the "%q" parameter is not attached to a state, but is a collection of the results of multiple states (attached to "%q1", "%q2", "%q3", ...);-- so if this parameter is given then this hook must be defined separately, but only if at least one "qualifier(s)" command has been givenifformatParams[parameters.qualifier]andcfg.states.qualifiersCount>0thenhooks[parameters.qualifier]=getHookName(parameters.qualifier,1)hooks.count=hooks.count+1end-- create a state for "properties" if it doesn't exist yet, which will be used as a base configuration for each claim iteration;-- must come AFTER defining the hooksifnotcfg.states[parameters.property]thencfg.states[parameters.property]=State:new(cfg,parameters.property)-- if the "single" flag has been given then this state should be equivalent to "property" (singular)ifcfg.singleClaimthencfg.states[parameters.property].singleValue=trueendend-- if the "sourced" flag has been given then create a state for "reference" if it doesn't exist yet, using default values,-- which must exist in order to be able to determine if a claim has any references;-- must come AFTER defining the hooksifcfg.sourcedOnlyandnotcfg.states[parameters.reference]thencfg:processFlagOrCommand(p.claimCommands.reference)-- use singular "reference" to minimize overheadend-- set the parsed format and the separators (and optional punctuation mark);-- must come AFTER creating the additonal statescfg:setFormatAndSeparators(cfg.states[parameters.property],parsedFormat)-- process qualifier matching values, analogous to cfg.propertyValuefori,vinpairs(args)doi=tostring(i)ifi:match('^[Pp]%d+$')oraliasesP[i]thenv=replaceSpecialChars(v)-- check for special qualifier value 'somevalue'ifv~=""andmw.text.trim(v)==""thenv=" "-- single space represents 'somevalue'endcfg.qualifierIDsAndValues[replaceAlias(i):upper()]=vendend-- first sort the claims on rank to pre-define the order of output (preferred first, then normal, then deprecated)claims=sortOnRank(claims)-- then iterate through the claims to collect valuesvalue=cfg:concatValues(cfg.states[parameters.property]:iterate(claims,hooks,State.claimMatches))-- pass property state with level 1 hooks and matchHook-- if desired, add a clickable icon that may be used to edit the returned values on Wikidataifcfg.editableandvalue~=""thenvalue=value..cfg:getEditIcon()endreturnvalueendlocalfunctiongeneralCommand(args,funcName)localcfg=Config:new()cfg.curState=State:new(cfg)locallastArglocalvalue=nilrepeatlastArg=nextArg(args)untilnotcfg:processFlag(lastArg)-- get the entity ID from either the positional argument, the eid argument or the page argumentcfg.entityID=getEntityId(lastArg,args[p.args.eid],args[p.args.page],true,args[p.args.globalSiteId])ifcfg.entityID==""ornotmw.wikibase.entityExists(cfg.entityID)thenreturn""-- we cannot continue without an entityend-- serve according to the given commandiffuncName==p.generalCommands.labelthenvalue=cfg:getLabel(cfg.entityID,cfg.curState.rawValue,cfg.curState.linked,cfg.curState.shortName)elseiffuncName==p.generalCommands.titlethencfg.inSitelinks=trueifcfg.entityID:sub(1,1)=="Q"thenvalue=mw.wikibase.getSitelink(cfg.entityID)endifcfg.curState.linkedandvaluethenvalue=buildWikilink(value)endelseiffuncName==p.generalCommands.descriptionthenvalue=mw.wikibase.getDescription(cfg.entityID)elselocalparsedFormat,formatParamslocalhooks={count=0}cfg.entity=mw.wikibase.getEntity(cfg.entityID)iffuncName==p.generalCommands.aliasorfuncName==p.generalCommands.badgethencfg.curState.singleValue=trueendiffuncName==p.generalCommands.aliasorfuncName==p.generalCommands.aliasesthenifnotcfg.entity.aliasesornotcfg.entity.aliases[cfg.langCode]thenreturn""-- there is no use to continue without any aliassesendlocalaliases=cfg.entity.aliases[cfg.langCode]-- parse the desired format, or parse the default aliases formatifargs["format"]thenparsedFormat,formatParams=parseFormat(args["format"])elseparsedFormat,formatParams=parseFormat(formats.alias)end-- process overridden separator values;-- must come AFTER tweaking the default separatorscfg:processSeparators(args)-- define the hook that should be called (getAlias);-- only define the hook if the parameter ("%a") has been givenifformatParams[parameters.alias]thenhooks[parameters.alias]=getHookName(parameters.alias,1)hooks.count=hooks.count+1end-- set the parsed format and the separators (and optional punctuation mark)cfg:setFormatAndSeparators(cfg.curState,parsedFormat)-- iterate to collect valuesvalue=cfg:concatValues(cfg.curState:iterate(aliases,hooks))elseiffuncName==p.generalCommands.badgeorfuncName==p.generalCommands.badgesthenifnotcfg.entity.sitelinksornotcfg.entity.sitelinks[cfg.siteID]ornotcfg.entity.sitelinks[cfg.siteID].badgesthenreturn""-- there is no use to continue without any badgesendlocalbadges=cfg.entity.sitelinks[cfg.siteID].badgescfg.inSitelinks=true-- parse the desired format, or parse the default aliases formatifargs["format"]thenparsedFormat,formatParams=parseFormat(args["format"])elseparsedFormat,formatParams=parseFormat(formats.badge)end-- process overridden separator values;-- must come AFTER tweaking the default separatorscfg:processSeparators(args)-- define the hook that should be called (getBadge);-- only define the hook if the parameter ("%b") has been givenifformatParams[parameters.badge]thenhooks[parameters.badge]=getHookName(parameters.badge,1)hooks.count=hooks.count+1end-- set the parsed format and the separators (and optional punctuation mark)cfg:setFormatAndSeparators(cfg.curState,parsedFormat)-- iterate to collect valuesvalue=cfg:concatValues(cfg.curState:iterate(badges,hooks))endendvalue=valueor""ifcfg.editableandvalue~=""then-- if desired, add a clickable icon that may be used to edit the returned value on Wikidatavalue=value..cfg:getEditIcon()endreturnvalueend-- modules that include this module should call the functions with an underscore prepended, e.g.: p._property(args)localfunctionestablishCommands(commandList,commandFunc)for_,commandNameinpairs(commandList)dolocalfunctionwikitextWrapper(frame)localargs=copyTable(frame.args)args.pointer=1loadI18n(aliasesP,frame)returncommandFunc(args,commandName)endp[commandName]=wikitextWrapperlocalfunctionluaWrapper(args)args=copyTable(args)args.pointer=1loadI18n(aliasesP)returncommandFunc(args,commandName)endp["_"..commandName]=luaWrapperendendestablishCommands(p.claimCommands,claimCommand)establishCommands(p.generalCommands,generalCommand)-- main function that is supposed to be used by wrapper templatesfunctionp.main(frame)ifnotmw.wikibasethenreturnnilendlocalf,argsloadI18n(aliasesP,frame)-- get the parent frame to take the arguments that were passed to the wrapper templateframe=frame:getParent()orframeifnotframe.args[1]thenthrowError("no-function-specified")endf=mw.text.trim(frame.args[1])iff=="main"thenthrowError("main-called-twice")endassert(p["_"..f],errorText('no-such-function',f))-- copy arguments from immutable to mutable tableargs=copyTable(frame.args)-- remove the function name from the listtable.remove(args,1)returnp["_"..f](args)endreturnp