Naar inhoud springen

Module:European and national party data

Uit Wikipedia, de vrije encyclopedie
Moduledocumentatie​[bekijk] [bewerk] [ververs] [geschiedenis]
Informatie
Deze module is momenteel in beta-versie en is bedoeld om de European and national party data module aan te passen. De module wordt up-to-date gehouden op Wiki's via de Synchronizer tool. Stel bewerkingen voor op de geconsolideerde overlegpagina en relevante wijzigingen zullen worden doorgevoerd in de kernversie van de module.

Gebruik

{{#invoke:European and national party data|main|<partij_type>|<gegevens_type>|<partij>|<instelling>|extra parameters}}

Parameters

Parameter Beschrijving
1 Het type partij in kwestie; kan zijn:
  • europesean_entiteit (een Europese politieke partij, d.w.z. entiteiten die naar behoren zijn geregistreerd bij de Autoriteit voor Europese politieke partijen en Europese politieke stichtingen (APPF), of verschillende Europese politieke allianties); of
  • nationale_partij.

Deze parameter is verplicht.

2 Het type gegevens dat wordt opgevraagd en overgenomen van Wikidata, uit de volgende lijst:
  • zetels: het aantal zetels van een of meer entiteiten in een of meer instellingen (P1410);
  • zetel_quota: het zetelaandeel van een of meer entiteiten in een of meer instellingen (gebaseerd op P1410);
  • zetel_samenstelling_balk: een samenstellingsbalk die de zetels weergeeft van een of meer entiteiten in een of meer instellingen (gebaseerd op P1410);
  • acroniem: de korte naam van de entiteit (P1813);
  • kleur: de officiële kleur van de entiteit als hexadecimale code (P465);
  • land: het land waarin de entiteit is geregistreerd (P17);
  • oprichtingsdatum: de datum waarop de entiteit is opgericht (P571);
  • oprichtingsjaar: de jaar waarop de entiteit is opgericht (P571);
  • individuele_leden: het aantal individuele leden van de entiteit (P2124);
  • individuele_leden_datum: de referentiedatum voor het aantal individuele leden van de entiteit (gebaseerd op P2124);
  • individuele_leden_jaar: de referentiejaar voor het aantal individuele leden van de entiteit (gebaseerd op P2124);
  • label: de naam van de entiteit;
  • naam_officieel: de officiële lange naam van de entiteit (P1448);
  • parlementaire_groep: de parlementaire groep waartoe de entiteit behoort (P4100);
  • voorzitter: de leider of voorzitter van de entiteit (P488);
  • publieke_financiering: het bedrag aan publieke financiering dat de entiteit heeft ontvangen (P12919); of
  • website: de officiële website van de entiteit (P856), ontdaan van de voorvoegsels “https”, “http” en “www”.

Deze parameter is verplicht.

3 De naam van de entiteit, uit de volgende lijst:
  • in alle gevallen kan de naam worden weggelaten wanneer de module wordt aangeroepen vanaf de Wikipedia-pagina van de entiteit (als alternatief kan deze_partij worden gebruikt om te verwijzen naar de entiteit in kwestie);
  • voor Europese entiteiten: het acroniem van de entiteit (zie onderstaande lijst) of haar Wikidata qID; en
  • voor nationale partijen: de Wikidata qID van de partij.

Deze parameter is optioneel wanneer hij wordt aangeroepen vanaf de pagina van de entiteit in kwestie.

De volgende acroniemen worden gebruikt voor Europese partijen:

Daarnaast komen de volgende Europese politieke allianties aan bod:

Daarnaast kunnen vier speciale parameters worden gebruikt in plaats van Europese partijen (dus niet wanneer |partij_type=nationale_partij):

  • all: voor de zetels van alle Europese partijen samen;
  • none: voor de zetels die niet bezet zijn door leden van Europese partijen (niet voor lagere en hogere huizen); en
  • ind: voor onafhankelijke politici in de Europese Raad (alleen).

Opmerkingen:

  • het hoofdlettergebruik van parameters doet er niet toe;
  • gezien de kosten van het aanroepen van Wikidata bij gebruik van een specifieke qID (dus niet het aanroepen van Wikidata vanaf een gekoppelde Wikipedia-pagina), moet de speciale parameter deze_partij worden gebruikt wanneer deze module wordt aangeroepen vanaf de pagina van een Europese partij; en
  • aangezien de genoemde Europese politieke allianties geen Europese politieke partijen zijn, tellen ze niet mee voor het aantal zetels dat door Europese politieke partijen wordt bezet, noch voor het aantal zetels dat niet door Europese politieke partijen wordt bezet.
4 De naam van de instelling, uit de volgende lijst:

Opmerkingen:

  • Voor lager- en hogerhuizen voor nationale partijen bepaalt de module automatisch het relevante orgaan aan de hand van deze tabel;
  • Voor lager- en hogerhuizen voor Europese partijen telt de module het aantal zetels van de aangesloten partijen over de lidstaten bij elkaar op;
  • Voor het Europees Parlement voor nationale partijen gebruikt de module automatisch het aantal zetels van de lidstaat in het Parlement; en
  • Vanaf juni 2025 is de zetelverdeling van de PACE-fracties per Europese partij zelden beschikbaar.

Deze parameter is verplicht wanneer gegevens_type zetels, zetel_quota of zetel_samenstelling_balk is.

extra parameters De volgende extra parameters kunnen ook worden gebruikt, afhankelijk van het gevraagde gegevens_type:
  • alle gegevens_types:
    • referentie geeft de referentie weer wanneer |referentie=ja (deze parameter wordt genegeerd voor de zetels van de lagere of hogere huizen van Europese entiteiten, omdat veel nationale cijfers worden opgeteld);
  • zetel_quota:
    • kieskring zal het aantal zetels van de instelling overschrijven (bijvoorbeeld als de partij deel uitmaakt van een speciaal kiesdistrict);
  • zetel_samenstelling_balk:
    • kieskring zal het aantal zetels van de instelling overschrijven (bijvoorbeeld als de partij deel uitmaakt van een speciaal kiesdistrict);
    • breedte geeft de breedte van de balk aan en kan de volgende formaten hebben: “80” (standaardeenheid is pixel), ‘80px’, ‘80em’, of ‘80%’ (zonder spaties);
    • procent geeft het procentage weer wanneer |procent=ja;
    • balk-kleur, achtergrondkleur, en rand overschrijven de standaardkleuren wanneer een hexadecimale waarde is opgegeven (bijv.“#123ABC”, inclusief het pondeken) of een herkende kleur (bijv. “red”).
  • alle andere gegevens_types:
    • verbose: geeft een foutmelding als er geen waarde bestaat op Wikidata, evenals een relevante link, als |verbose=ja (anders is het veld leeg).

Deze parameters zijn optioneel.

Verwante sjablonen

De module wordt rechtstreeks geïmplementeerd door drie sjablonen::

Testgevallen

De module heeft twee testcase pagina's:

De module bijwerken

De module haalt zijn gegevens uit twee bronnen:

Om gegevens bij te werken die door de module worden geretourneerd, gaat u naar de Wikidata-pagina van de entiteit in kwestie (de link wordt vaak gegeven als commentaar in de infobox van het Wikipedia-artikel) en bewerkt u de relevante eigenschap, bij voorkeur door een nieuwe waarde toe te voegen en deze als voorkeur te markeren (in plaats van verouderde informatie te verwijderen).

Hier zijn enkele relevante eigenschappen voor de module:

  • aantal zetels in de assemblee: P1410, met de volgende kwalificaties:
    • wetgevend orgaan: P194
    • uitvoerend orgaan (voor de Europese Commissie en de Europese Raad): P208
    • parlementaire zittingsperiode (voor het Europees Parlement en de Europese Commissie): P2937
  • korte naam/acroniem: P1813
  • kleur/sRGB hex kleuren triplet: P465
  • land: P17
  • oprichtingsdatum: P571
  • individuele leden: P2124
  • officiële naam: P1448
  • parlementaire groep: P4100
  • voorzitter: P488
  • overheidsfinanciering: P12919
  • officiële website: P856

Probeer waar mogelijk:

  • een starttijd (P580) kwalificatie (en een bijpassende eindtijd (P582) in de verouderde vermelding) of een punt in de tijd (P585) kwalificatie, en
  • een referentie, inclusief de referentie URL (P854), titel (P1476), opgehaald (P813) en uitgever kwalificaties (P123).

Het bijwerken van Wikidata zorgt ervoor dat bijgewerkte informatie en informatie uit bronnen niet alleen beschikbaar is voor deze Wiki, maar voor alle versies van Wikipedia en voor andere diensten die informatie uit Wikidata halen.

De module vertalen

Volg deze stappen om de module aan een nieuwe Wiki aan te passen:

  1. Maak twee modules om de onderstaande modules te kopiëren (de inhoud moet hetzelfde blijven als in de Engelse versie):
    1. Module:European and national party data, en
    2. Module:European and national party data/Wd;
  2. Maak de volgende bestanden en vertaal ze indien nodig (vertaal alleen de niet-Engelse delen, zoals aangegeven):
    1. Module:European and national party data/config, en
    2. Module:European and national party data/Wd/i18n;
  3. Vertaal de moduledocumentaties en pas de voorbeelden waar nodig aan met de vertaalde termen;
  4. Maak testcases, zoals de onderstaande, en pas de voorbeelden waar nodig aan met de vertaalde termen:
    1. en:Module:European and national party data/testcases, en
    2. en:Module:European and national party data/testcases composition bar;
  5. Maak drie sjablonen om de onderstaande sjablonen te kopiëren:
    1. Sjabloon:Gegevens EUPP,
    2. Sjabloon:Gegevens politieke partij, en
    3. Sjabloon:Zetels EU-instellingen;
  6. Vertaal de sjabloondocumentaties op basis van de moduledocumentaties en pas de voorbeelden waar nodig aan met de vertaalde termen;
  7. Voeg de twee modules toe in de “Wikipedia” secties van de twee relevante Wikidata pagina's hieronder:
    1. Module:European and national party data
    2. Module:European and national party data/Wd
  8. Maak een onderwerp aan op de geconsolideerde module talk page om de inhoud van de gemeenschappelijke module (in het bijzonder de functie voor samenstellingsbalken) aan te passen aan de nieuwe Wiki. Na aanpassing zal de hoofdmodule worden gesynchroniseerd om de modules in alle Wiki-talen bij te werken; dit helpt ervoor te zorgen dat dezelfde module in alle Wiki's wordt gebruikt, wat essentieel is om de functies bijgewerkt te houden.

Voorbeelden

Gegevenstype zetels

Code Resultaat Uitgang
{{#invoke:European and national party data|main|europesean_entiteit|zetels|EVP|EP}} 182 zetels van de Europese Volkspartij in het Europees Parlement
{{#invoke:European and national party data|main|europesean_entiteit|zetels|PES|EC|referentie=ja}} 4[1] zetels van de Partij van Europese Sociaal-democraten in de Europese Commissie, met referentie
{{#invoke:European and national party data|main|europesean_entiteit|zetels|ind|EUCO}} 2 zetels van onafhankelijke politici in de Europese Raad
{{#invoke:European and national party data|main|europesean_entiteit|zetels|ALDE|lagerhuis}} 474 zetels van de Alliantie van Liberalen en Democraten voor Europa in de lagere huizen van de lidstaten
{{#invoke:European and national party data|main|europesean_entiteit|zetels|EGP|hogerhuis|referentie=ja}} 44 zetels van de Europese Groene Partij in de Hogerhuizen van de lidstaten, zonder referentie (zie bovenstaande tabel)
{{#invoke:European and national party data|main|europesean_entiteit|zetels|Q208242|EC}} 11 zetels van de Europese Volkspartij (genoemd naar haar Wikidata qID) in de Europese Commissie
{{#invoke:European and national party data|main|europesean_entiteit|zetels|Q208242|hogerhuis}} 461 zetels van de Europese Volkspartij (genoemd naar haar Wikidata qID) in de Hogerhuizen van de lidstaten
{{#invoke:European and national party data|main|nationale_partij|zetels|Q13564543|lagerhuis|referentie=ja}} 18[2] zetels van de Oostenrijkse NEOS (genoemd naar zijn Wikidata qID) in de Nationale Raad, met referentie
{{#invoke:European and national party data|main|nationale_partij|zetels|Q138198|hogerhuis}} 91 zetels van de Spaanse Socialistische Arbeiderspartij (genoemd naar haar Wikidata qID) in de Senaat
{{#invoke:European and national party data|main|nationale_partij|zetels|Q49768|EP}} 14 zetels van de Sociaal-Democratische Partij van Duitsland (genoemd naar haar Wikidata qID) in het Europees Parlement
{{#invoke:European and national party data|main|europesean_entiteit|zetels|alle|EP}} 670 zetels van alle Europese partijen samen in het Europees Parlement
{{#invoke:European and national party data|main|europesean_entiteit|zetels|geen|EP}} 50 zetels niet bezet door Europese partijen in het Europees Parlement

Gegevenstype zetel_quota

Code Resultaat Uitgang
{{#invoke:European and national party data|main|europesean_entiteit|zetel_quota|EVP|EP|referentie=ja}} 25.28 zetelaandeel van de Europese Volkspartij in het Europees Parlement, met referentie
{{#invoke:European and national party data|main|europesean_entiteit|zetel_quota|ind|EUCO}} 7.41 zetelaandeel van onafhankelijke politici in de Europese Raad
{{#invoke:European and national party data|main|europesean_entiteit|zetel_quota|ALDE|lagerhuis}} 7.62 zetelaandeel van de Alliantie van Liberalen en Democraten voor Europa in de lagere huizen van de lidstaten
{{#invoke:European and national party data|main|europesean_entiteit|zetel_quota|Q208242|EC}} 40.74 zetelaandeel van de Europese Volkspartij (genoemd naar haar Wikidata qID) in de Europese Commissie
{{#invoke:European and national party data|main|nationale_partij|zetel_quota|Q13564543|lagerhuis}} 9.84 zetelaandeel van de Oostenrijkse NEOS (genoemd naar zijn Wikidata qID) in de Nationale Raad
{{#invoke:European and national party data|main|nationale_partij|zetel_quota|Q655611|lagerhuis|kieskring=61}} 4.92 zetelaandeel van Écolo (genoemd naar zijn Wikidata qID) in de Franstalige zetels van de Kamer van Volksvertegenwoordigers
{{#invoke:European and national party data|main|nationale_partij|zetel_quota|Q49768|EP|referentie=ja}} 14.58 zetelaandeel van de Sociaal-Democratische Partij van Duitsland (genoemd naar haar Wikidata qID) in het Europees Parlement, met referentie
{{#invoke:European and national party data|main|europesean_entiteit|zetel_quota|alle|EP}} 93.06 zetelaandeel van alle Europese partijen samen in het Europees Parlement

Gegevenstype zetel_samenstelling_balk

Code Resultaat Uitgang
{{#invoke:European and national party data|main|europesean_entiteit|zetel_samenstelling_balk|EVP|EP|referentie=ja}}
182 / 720
[3]
zetelsamenstellingsbalk van de zetels van de Europese Volkspartij in het Europees Parlement, met referentie
{{#invoke:European and national party data|main|europesean_entiteit|zetel_samenstelling_balk|ind|EUCO|procent=ja}}
2 / 27
zetelsamenstellingsbalk van onafhankelijke politici in de Europese Raad, met referentie
{{#invoke:European and national party data|main|europesean_entiteit|zetel_samenstelling_balk|ALDE|lagerhuis}}
474 / 6.217
zetelsamenstellingsbalk van de Alliantie van Liberalen en Democraten voor Europa in de Tweede Kamer van de lidstaten
{{#invoke:European and national party data|main|europesean_entiteit|zetel_samenstelling_balk|Q208242|EC|procent=ja|referentie=ja}}
11 / 27(41%)
[4]
zetelsamenstellingsbalk van de Europese Volkspartij (genoemd naar haar Wikidata qID) in de Europese Commissie, met referentie
{{#invoke:European and national party data|main|nationale_partij|zetel_samenstelling_balk|Q655611|lagerhuis|kieskring=61}}
3 / 61
zetelsamenstellingsbalk van het Belgische Écolo (genoemd naar zijn Wikidata qID) in de Franstalige zetels van de Kamer van Volksvertegenwoordigers
{{#invoke:European and national party data|main|nationale_partij|zetel_samenstelling_balk|Q49768|EP|breedte=80%|achtergrondkleur=blue|rand=green|balk-kleur=red}}
14 / 96
zetelsamenstellingsbalk van de Sociaal-Democratische Partij van Duitsland (genoemd naar haar Wikidata qID) in het Europees Parlement, met speciale parameters
{{#invoke:European and national party data|main|europesean_entiteit|zetel_samenstelling_balk|alle|EP|breedte=80%|achtergrondkleur=#FFFF00|rand=#008080|balk-kleur=#A020F0}}
670 / 720
zetelsamenstellingsbalk van alle Europese partijen samen in het Europees Parlement, met speciale parameters

Andere gegevenstypen

Code Resultaat Uitgang
{{#invoke:European and national party data|main|europesean_entiteit|acroniem|EVP}} EVP acroniem van de Europese Volkspartij
{{#invoke:European and national party data|main|europesean_entiteit|color|PES}} #F0001C kleur van de Partij van Europese Socialisten
{{#invoke:European and national party data|main|europesean_entiteit|color|PES}} Tsjechië land van de partij Levice (genoemd naar haar Wikidata qID)
{{#invoke:European and national party data|main|europesean_entiteit|oprichtingsdatum|PES}} 10 november 1992 oprichtingsdatum van de Partij van Europese Socialisten
{{#invoke:European and national party data|main|europesean_entiteit|individuele_leden|EVP|referentie=ja}} 23[5] individuele leden van de Europese Volkspartij, met referentie
{{#invoke:European and national party data|main|europesean_entiteit|individuele_leden_datum|EVP}} 22 december 2025 individuele leden datum van de Europese Volkspartij
{{#invoke:European and national party data|main|europesean_entiteit|individuele_leden_datum|Volt}} 22 december 2025 individuele leden datum van de Volt
{{#invoke:European and national party data|main|europesean_entiteit|individuele_leden_jaar|EVP}} 2025 individuele leden jaar van de Europese Volkspartij
{{#invoke:European and national party data|main|europesean_entiteit|individuele_leden_jaar|Volt}} 2026 individuele leden jaar van de Volt
{{#invoke:European and national party data|main|europesean_entiteit|label|ALDE}} Partij van Europese Liberalen en Democraten label van de Alliantie van Liberalen en Democraten voor Europa
{{#invoke:European and national party data|main|europesean_entiteit|naam_officieel|EGP}} officiële naam van de Europese Groene Partij
{{#invoke:European and national party data|main|europesean_entiteit|parlementaire_groep|EVA}} De Groenen/Vrije Europese Alliantie parlementaire fractie van de Vrije Europese Alliantie
{{#invoke:European and national party data|main|europesean_entiteit|publieke_financiering|EGP}} 171.460,56 euros overheidsfinanciering van de Europese Groene Partij, met referentie
{{#invoke:European and national party data|main|nationale_partij|website|Q667680}} website van GroenLinks
{{#invoke:European and national party data|main|nationale_partij|naam_officieel|Q22748|verbose=ja}} Error: {{European and national party data}}: geen gegevens beschikbaar op Wikidata voor P1448, zie https://www.wikidata.org/wiki/Q22748 (help) officiële naam van Duitsland Die PARTEI, toont verbose foutmelding

  1. ↑ PES in the EU institutions. Geraadpleegd op 7 februari 2025.
  2. ↑ Sitzplan & Mandatsverteilung. Geraadpleegd op 9 april 2025.
  3. ↑ Error: Unable to display the reference from Wikidata properly. Technical details:
    • Reason for the failure of {{Cite web}}: The Wikidata reference contains the property Sjabloon:Property, which is not assigned to any parameter of this template.
    • Reason for the failure of {{Cite Q}}: The Wikidata reference contains the property Sjabloon:Property, which is not assigned to any parameter of this template.
    See the documentation for further details.
  4. ↑ Parties and partners. Geraadpleegd op 7 februari 2025.
  5. ↑ Number of individual members per European Political Party. Europees Parlement. Geraadpleegd op 26 februari 2026.
require ('strict');
local get_args = require ('Module:Arguments').getArgs;							-- function to fetch frame and parent frame arguments
local cfg = mw.loadData ('Module:European and national party data/config');		-- defines, configuration data, and i18n support
local namespace = mw.title.getCurrentTitle().namespace;							-- used for categorization


--[[==========================< S E C T I O N _ 1 : F U N C T I O N A L _ F U N C T I O N S >=======================

These are generic functions to accomplish specific, non-party-related tasks.

]]

--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------

substitutes $1, $2, etc in <message> with data from <data_t>. Returns plain-text substituted string when
<data_t> not nil; returns <message> else.

]]

local function substitute (message, data_t)
	return data_t and mw.message.newRawMessage (message, data_t):plain() or message;
end


--[[--------------------------< M A K E _ E R R O R _ M S G >--------------------------------------------------

assembles an error message from template name, message text, help link, and error category.

]]

local function make_error_msg (msg, template_name, nocat)
	local category;

	local category_link = ((0 == namespace) and not nocat) and substitute ('[[Category:$1]]', {cfg.settings_t.err_category}) or '';
	return substitute ('<span style="color:#d33">Error: &#x7B;{$1}}: $2 ([[:Template:$1|$3]])</span>$4',
		{
		template_name or cfg.settings_t.template_name or frame:getParent():getTitle(),	-- the template name without namespace
		msg,																	-- the error message
		cfg.settings_t.help,													-- help wikilink display text
		category_link															-- link to error category (main namespace only)
		})
end
	

--[[--------------------------< R O U N D >--------------------------------------------------------------------

return the rounded value of the arguments with two decimals

]]

local function round (n)
  return math.floor(100 * n + 0.5) / 100										-- round argument to two decimals
end


--[[--------------------------< S T R I P _ U R L >--------------------------------------------------------------------

return the stripped down URL with a hyperlink

]]

local function strip_URL (URL)
	local new_URL = URL;
	local patterns_t = {'^%[%[(.*)%]%]', '^https://www.', '^http://www.', '^https://', '^http://', '^www.', '/$'};	-- valid <width> patterns
	for i, pattern in ipairs (patterns_t) do									-- loop through the patterns in <patterns_t>
		new_URL = new_URL.gsub(new_URL, pattern, "");
	end

	return "[" .. URL .. " " .. new_URL .. "]";
end


--[[--------------------------< T R A N S L A T E >--------------------------------------------------------------------

translate a term based on the project language

]]

local function xlate (term)
	if term then
		--local new_term = string.gsub(term, " ", "_");
		if 'en' == cfg.this_project_language then
			return term;
		elseif not cfg.xlate_t[cfg.this_project_language] then
			return term;
		elseif cfg.xlate_t[cfg.this_project_language][term] then
			return cfg.xlate_t[cfg.this_project_language][term];
		else 
			return term;
		end
	end
end


--[[--------------------------< T R A N S L A T E _ P A R A M >--------------------------------------------------------------------

translate a parameter based on the project language

]]

local function xlate_param (parameter)
	if 'en' == cfg.this_project_language then
		return parameter;
	elseif not cfg.xlate_param_t[cfg.this_project_language] then
		return parameter;
	elseif cfg.xlate_param_t[cfg.this_project_language][parameter] then
		return cfg.xlate_param_t[cfg.this_project_language][parameter];
	else 
		return parameter;
	end
end


--[[--------------------------< L O C A L _ P A R A M E T E R _ T O _ V A L U E _ O R _ B O O L E A N  >--------------------------------------------------------------------

turns a given parameter into its local form and into a boolean

]]

local function local_parameter_to_value_or_boolean (frame, parameter, outcome)	-- to test calls and functions, for verification purposes
	local args_t = get_args (frame);											-- get arguments; empty string or whitespace positional parameters set to nil
	
	local localised_parameter = xlate_param (parameter);						-- translate given parameter from English into local language
	local argument = (args_t[tostring(localised_parameter)] and mw.ustring.lower(args_t[tostring(localised_parameter)])) or (args_t[parameter] and mw.ustring.lower(args_t[parameter]));	-- get argument (in local language) matching parameter in local language
	
	if outcome == 'boolean' then
		if nil == argument then													-- if no argument, return no
			argument = false;
		else
			argument = xlate (argument);										-- translate argument into English
			argument = 'yes' == argument;										-- turn argument into boolean
		end
	elseif nil ~= argument and argument:match ('^#') then
		argument = argument.gsub(argument, "#", "&#35;");
	end
	
	return argument;
end


--[[--------------------------< X L A T E _ W I K I D A T A >--------------------------------------------------------------------

call the {{wd}} or {{wikidata}} template based on language

arguments are as follows:
* data_requested: the type of data sought -- 'qualifier', 'property', 'references', 'label' -- compulsory
* qid: the Wikidata item on which data is sought -- e.g. Q208242 for the European People's Party -- not compulsory
* property_id: the property for which data is sought -- e.g. P1410 for number of seats in assembly -- compulsory
* qualifier_id: qualifier for property -- e.g. P194 for legislative body -- not compulsory
* value_of_qualifier: value of the qualifier -- e.g. P8889 for the European Parliament -- only compulsory if qualifier_id is provided
* reference: whether a reference should be displayed -- e.g. reference=yes to display the reference, anything else (preferably reference=no) otherwise; adding an "s" will display several references
* preferred: whether the preferred value should be displayed -- e.g. preferred=yes to display the preferred value, anything else (preferably preferred=no) otherwise
* raw: whether the qID should be displayed -- e.g. raw=yes to display the qID, anything else (preferably raw=no) otherwise
* linked: whether the value should be linked -- e.g. linked=yes to display the link, anything else (preferably linked=no) otherwise

]]

local function xlate_wikidata (data_requested, qid, property_id, qualifier_id, value_of_qualifier, reference, preferred, raw, linked, unit)
	mw.logObject( {data_requested, qid, property_id, qualifier_id, value_of_qualifier, reference, preferred, raw, linked}, "xlate_wikidata()" )
	local local_reference = (reference == 'reference=yes') and 'reference' or '';
	if local_reference == '' and reference == 'references=yes' then local_reference = 'references' end;
	local local_preferred = (preferred == 'preferred=yes') and 'preferred' or '';
	local local_raw = (raw == 'raw=yes') and 'raw' or '';
	local local_linked = (linked == 'linked=yes') and 'linked' or '';
	local local_unit = (unit == 'unit=yes') and 'unit' or '';
	local Wd = require('Module:European_and_national_party_data/Wd')
	
	local wdargs = {local_reference, local_preferred, local_raw, local_linked, local_unit, property_id}
	
	if qid then
		table.insert(wdargs, 6, qid)
	end
	if '' ~= qualifier_id then
		if '' ~= value_of_qualifier then
			wdargs[qualifier_id] = value_of_qualifier;
		else
			table.insert(wdargs, qualifier_id)
		end
	end
	mw.logObject( wdargs, "wdargs" )
	return Wd['_' .. data_requested](wdargs);
end


--[[--------------------------< X L A T E _ C O M P O S I T I O N _ B A R >--------------------------------------------------------------------

call the {{composition bar}} template based on language

arguments are as follows:
* seats: the number of seats to be displayed;
* total_seats: the total number of seats of the institution in question; 
* color: the color of the bar;
* width: the width of the bar;
* percentage: whether or not to display the percentage value;
* background_color: the background color of the bar;
* border: the color of the border;
* compactness: whether the template is the compact version

]]

local function xlate_composition_bar (frame, seats, total_seats, color, width, percentage, background_color, border, num1, bar, num2, compactness)
	if 'compact' == compactness then											-- if compactness is compact, then show compact template (which in most cases is the non-compact version)
		if 'fr' == cfg.this_project_language then
			return frame:expandTemplate ({title='Infobox Parti politique/Sièges', args = {seats, total_seats, ['hex'] = color, ['chiffres1'] = num1, ['barre'] = bar, ['chiffres2'] = num2}});
		elseif 'it' == cfg.this_project_language then
			return frame:expandTemplate ({title='Seggi', args = {seats, total_seats, ['c'] = color}});
		elseif 'es' == cfg.this_project_language then
			return frame:expandTemplate ({title='Composition bar', args = {seats, total_seats, ['hex'] = color}});
		elseif 'pt' == cfg.this_project_language then
			return frame:expandTemplate ({title='Info/Partido político/lugares', args = {seats, total_seats, color}});
		elseif 'nl' == cfg.this_project_language then
			local comp_bar_args_t = {
				seats,
				total_seats, 
				color,
				width=width,
				per=percentage,
				['background-color'] = background_color,
				border = border,
			};
			return frame:expandTemplate ({title='Percentagebalk', args = comp_bar_args_t});
		else																		-- for all other languages the assumption is that the template is called composition bar compact
			local comp_bar_args_t = {
				seats,
				total_seats, 
				color,
				width=width,
				per=percentage,
				['background-color'] = background_color,
				border = border,
			};
			return frame:expandTemplate ({title='Composition bar compact', args = comp_bar_args_t});
		end
	else																		-- if compactness is anything else than compact, then show regular version of template
		if 'fr' == cfg.this_project_language then
			return frame:expandTemplate ({title='Infobox Parti politique/Sièges', args = {seats, total_seats, ['hex'] = color, ['chiffres1'] = num1, ['barre'] = bar, ['chiffres2'] = num2}});
		elseif 'it' == cfg.this_project_language then
			return frame:expandTemplate ({title='Seggi', args = {seats, total_seats, ['c'] = color}});
		elseif 'es' == cfg.this_project_language then
			return frame:expandTemplate ({title='Composition bar', args = {seats, total_seats, ['hex'] = color}});
		elseif 'pt' == cfg.this_project_language then
			return frame:expandTemplate ({title='Info/Partido político/lugares', args = {seats, total_seats, color}});
		elseif 'nl' == cfg.this_project_language then
			local comp_bar_args_t = {
				seats,
				total_seats, 
				color,
				width=width,
				per=percentage,
				['background-color'] = background_color,
				border = border,
			};
			return frame:expandTemplate ({title='Percentagebalk', args = comp_bar_args_t});
		else																		-- for all other languages the assumption is that the template is called composition bar
			local comp_bar_args_t = {
				seats,
				total_seats, 
				color,
				width=width,
				per=percentage,
				['background-color'] = background_color,
				border = border,
			};
			return frame:expandTemplate ({title='Composition bar', args = comp_bar_args_t});
		end
	end
end



--[[==========================< S E C T I O N _ 2 : V A L I D A T I O N _ F U N C T I O N S >=======================

These are functions to ensure data validation and return error messages when relevant.

]]

--[[--------------------------< V A L I D A T E _ W I D T H >--------------------------------------------------

validates data format for the width parameter of composition bars; returns boolean true when valid; nil else

]]

local function validate_width (width)
	local patterns_t = {'^%d+$', '^%d+px$', '^%d+%%$', '^%d+em$'};				-- valid <width> patterns
	for i, pattern in ipairs (patterns_t) do									-- loop through the patterns in <patterns_t>
		if width:match (pattern) then											-- is there a match?
			return true;														-- yes, done
		end
	end
end


--[[--------------------------< H A R M O N I S E _ H O U S E _ T Y P E >----------------------------------------------

harmonises house type input (for calls relating to lower and upper houses)

]]

local function harmonise_lower_upper_house_name (house_type)
	if house_type == "LOWER-HOUSE" or house_type == "LOWER" or house_type == "MS-LOWER-HOUSE"then	-- the three accepted formats for input
		return "LOWER_HOUSE";													-- format actually used in the code
	elseif house_type == "UPPER-HOUSE" or house_type == "UPPER" or house_type == "MS-UPPER-HOUSE" then	-- the three accepted formats for input
		return "UPPER_HOUSE";													-- format actually used in the code
	else
		return house_type;
	end
end


--[[--------------------------< V A L I D A T E _ I N S T I T U T I O N >----------------------------

when institution parameter exists, checkes that it is correct; returns boolean true when valid; error message else

]]

local function validate_institution (institution, template_name)
	
	if institution and not cfg.institutions_t[institution] and not cfg.national_institutions_t[institution] then	-- if institution is present, it must be known
		return make_error_msg (substitute (cfg.error_messages_t.unknown_inst, {institution}), template_name);
	end

	return true;
end



--[[==========================< S E C T I O N _ 3 : G E T _ F U N C T I O N S >=======================

These are functions to grab data from Wikidata

]]

--[[--------------------------< G E T _ D A T A >----------------------------------------------------------

general function to return data for the requested property for a party; <frame> required to expand {{wikidata}} template

]]

local function allpp_get_data (frame, party, property_id, option)
	local template_name = frame:getParent():getTitle();
	local args_t = get_args (frame);

	local data = "";
	local data_unit = "";
	
	local reference = local_parameter_to_value_or_boolean (frame, 'reference', 'boolean');	-- check reference and make boolean
	reference = (reference and option ~= "raw-noref") and 'references=yes' or ''; -- if reference is true, then the call will return a reference
	local verbose = local_parameter_to_value_or_boolean (frame, 'verbose', 'boolean');	-- check verbose and make boolean
	local raw = (option == "raw" or option == "raw-noref") and "raw=yes" or "raw=no"; -- check raw and format correctly
	local linked = (option == "linked") and "linked=yes" or "linked=no";		-- check linked and format correctly
	local unit = (option == "unit") and "unit=yes" or "unit=no";				-- check linked and format correctly
	
	local party_qid = "";														-- init party_qid
	
	if not party then															-- party is required
		return make_error_msg (substitute (cfg.error_messages_t.unknown_party, {party}), template_name);
	elseif cfg.parties_t[party] then											-- if party is a European party
		party_qid = cfg.parties_t[party];
	elseif cfg.alliances_t[party] then											-- if party is a European alliance
		party_qid = cfg.alliances_t[party];
	elseif party:match ('^Q%d+$') then											-- if party is a qID
		party_qid = party;
	elseif property_id == 'P465' and (party == "ALL" or party == "IND" or party == "NONE") then -- default colour for special parameters
		return '&#35;BBB';
	elseif party ~= "THISPARTY" then											-- error message if no party is provided
		return make_error_msg (substitute (cfg.error_messages_t.unknown_party, {party}), template_name);
	end
	
	if not party then															-- direct call when no party is specified
		party_qid = ""															-- This should not be needed since the function
	end																			-- should error out above if no party specified.
	
	if property_id == "label" then												-- if the label of the Wikidata element is requested
		data = xlate_wikidata ('label', party_qid, '', '', '', 'reference=no', 'preferred=no', raw, linked, unit);
	elseif property_id == "individual members date" then						-- special case
		data = xlate_wikidata ('qualifier', party_qid, 'P2124', 'P585', '', 'reference=no', 'preferred=yes', raw, linked, unit);
	elseif property_id == cfg.data_prop_t.public_funding then						-- special case
		data = tonumber(xlate_wikidata ('property', party_qid, property_id, '', '', '', '', 'raw=yes', '', ''));
		data_unit = xlate_wikidata ('property', party_qid, property_id, '', '', '', '', '', '', 'unit=yes');
		if nil ~= data then
			if data > 1 then data_unit = data_unit .. 's' end;
		else
			data = '';
			data_unit = '';
		end
	else																		-- for all other cases
		data = xlate_wikidata ('property', party_qid, property_id, '', '', reference, 'preferred=no', raw, linked, unit);
	end
	
	if property_id == cfg.data_prop_t.colour then								-- if no colour, then default colour
		if '' == data then
			data = '&#35;BBB';
		else
			data = '&#35;' .. data;
		end
	elseif property_id == cfg.data_prop_t.website then							-- if no website, then empty string
		if '' == data then
			data = "";
		else
			data = strip_URL (data);
		end
	end

	if '' == data and verbose then												-- if verbose, then error message
		return make_error_msg (substitute (cfg.error_messages_t.no_data, {party_qid, property_id}));
	end
	
	if property_id == cfg.data_prop_t.public_funding and '' ~= data then	
		return mw.getContentLanguage():formatNum(data) .. " " .. data_unit;
	else
		return data;
	end
end


--[[--------------------------< H O U S E _ Q I D _ F R O M _ M E M B E R _ S T A T E >----------------------------------------------------------

return the qID of a house based on its name (lower house or upper house) and its member state; <frame> required to expand {{wikidata}} template

]]

local function house_qid_from_member_state_qid (house_type, member_state_qid)
	local house_qid = "";
	for row, _ in ipairs (cfg.ms_data_t) do										-- loop on table with lower/upper houses per member state
		if member_state_qid == cfg.ms_data_t[row].member_state_qid then
			if house_type == "LOWER_HOUSE" then
				house_qid = cfg.ms_data_t[row].lower_house_qid;					-- get the lower house qid
			elseif house_type == "UPPER_HOUSE" then
				house_qid = cfg.ms_data_t[row].upper_house_qid;					-- get the upper house qid
			end
		end
	end
	return house_qid;
end


--[[--------------------------< I N S T I T U T I O N _ S I Z E >----------------------------------------------------------

return the size of an institution; <frame> required to expand {{wikidata}} template

]]

local function institution_size (frame, institution)
	local institution_size = xlate_wikidata ('property', cfg.institutions_t[institution], 'P1342', '', '', 'reference=no', 'preferred=no', 'raw=no', 'linked=no');	-- get the institution size
	if '' == institution_size then												-- if no institution size
		return make_error_msg (substitute (cfg.error_messages_t.unknown_inst, {institution}));
	end
	return institution_size;
end


--[[--------------------------< M E M B E R _ S T A T E _ D E L E G A T I O N _ S I Z E >----------------------------------------------------------

return the size of a member state's delegation in the European Parliament; <frame> required to expand {{wikidata}} template

]]

local function member_state_delegation_size (frame, member_state_qid)
	local delegation_size = xlate_wikidata ('property', member_state_qid, 'P1410', 'P194', 'Q8889', 'reference=no', 'preferred=no', 'raw=no', 'linked=no');		-- get the delegation size
	if '' == delegation_size then												-- if no delegation size
		return make_error_msg (substitute (cfg.error_messages_t.not_member_state, {member_state_qid}));
	end
	return delegation_size;
end


--[[--------------------------< S I N G L E _ H O U S E _ S E A T S >------------------------------------------------

returns the number of seats in a given lower or upper house (identified by a row in the master table) from
wikidata.  When <house_type> not recognized or when <ms_data_t> does not have 'that' house, returns 0

]]

local function single_house_seats (frame, row, house_type)
	local house_qid;

	if house_type == "LOWER_HOUSE" then
		house_qid = cfg.ms_data_t[row].lower_house_qid;							-- get the lower house qid
	elseif house_type == "UPPER_HOUSE" then
		house_qid = cfg.ms_data_t[row].upper_house_qid;							-- get the upper house qid
	end

	return house_qid and xlate_wikidata ('property', house_qid, 'P1342', '', '', 'reference=no', 'preferred=no', 'raw=no', 'linked=no') or 0;	-- house_qid is nil when no upper or lower house 
end


--[[--------------------------< T O T A L _ H O U S E _ S E A T S >------------------------------------------------

returns the total number of seats of all lower or upper houses in all member states.

]]

local function total_house_seats (frame, house_type)
	local sum_seats = 0;														-- init sum of seats of European party's member parties in house_type

	for row, _ in ipairs (cfg.ms_data_t) do										-- for all member states
		sum_seats = sum_seats + single_house_seats (frame, row, house_type);		-- increase sum_seats
	end

	return sum_seats;
end


--[[--------------------------< A L L P P _ S E A T S _  R E F >---------------------------------------------------------------

return the reference for a seat claim; <frame> required to expand {{wikidata}} template

]]

local function allpp_seats_ref (frame, party, institution)
	local args_t = get_args (frame);
	local party_type = args_t[1] and mw.ustring.lower(args_t[1]);				-- force to lower case
	
	party_type = xlate (party_type);
	
	if institution == "LOWER_HOUSE" or institution == "UPPER_HOUSE" then
		if party_type == 'european_entity' then
			return '';
		elseif party_type == 'national_party' then
			if party == "THISPARTY" then
				local member_state_qid = allpp_get_data (frame, mw.wikibase.getEntityIdForCurrentPage(), cfg.data_prop_t.country, 'raw-noref');
				local house_qid = house_qid_from_member_state_qid (institution, member_state_qid)
				return xlate_wikidata ('references', '', 'P1410', 'P194', house_qid, 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
			elseif party:match ('^Q%d+$') then
				local member_state_qid = allpp_get_data (frame, party, cfg.data_prop_t.country, 'raw-noref');
				local house_qid = house_qid_from_member_state_qid (institution, member_state_qid)
				return xlate_wikidata ('references', party, 'P1410', 'P194', house_qid, 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
			end
		end
	elseif institution == 'EC' or institution == 'EUCO' then
		if party == "THISPARTY" then
			return xlate_wikidata ('references', '', 'P1410', 'P208', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
		elseif cfg.parties_t[party] then
			return xlate_wikidata ('references', cfg.parties_t[party], 'P1410', 'P208', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
		elseif cfg.alliances_t[party] then
			return xlate_wikidata ('references', cfg.alliances_t[party], 'P1410', 'P208', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
		elseif party:match ('^Q%d+$') then
			return xlate_wikidata ('references', party, 'P1410', 'P208', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
		end
	else
		if party == "THISPARTY" then
			return xlate_wikidata ('references', '', 'P1410', 'P194', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
		elseif cfg.parties_t[party] then
			return xlate_wikidata ('references', cfg.parties_t[party], 'P1410', 'P194', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
		elseif cfg.alliances_t[party] then
			return xlate_wikidata ('references', cfg.alliances_t[party], 'P1410', 'P194', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
		elseif party:match ('^Q%d+$') then
			return xlate_wikidata ('references', party, 'P1410', 'P194', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
		end
	end
end

local function allpp_get_seats_ref_qid (frame, institution_qid)
	return xlate_wikidata ('references', '', 'P1410', 'P194', institution_qid, 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
end



--[[==========================< S E C T I O N _ 4 : S U M _ F U N C T I O N S >=======================

These functions are the ones providing seat numbers for European or national parties, in European institutions or national lower/upper houses
* functions starting with eupp apply to European parties;
* functions starting with npp apply to national political parties; and
* functions starting with allpp apply to all political parties.

]]

--[[--------------------------< A L L P P _ M A K E _ S H A R E _ I N _ E U _ I N S T I T U T I O N S >--------------------------------------------------------------

return the share of a party's seats relative to the total size of a given institution listed in <cfg.parties_t> or <cfg.alliances_t> (so not including lower and upper houses)

<frame> required to expand {{wikidata}} template 

Note: P1342 is the property "number of seats", used to record an institution's number of seats

]]

local function allpp_make_share_in_eu_institutions (frame, party_seats, institution)
	local args_t = get_args (frame);
	local party_type = args_t[1] and mw.ustring.lower(args_t[1]);			-- force to lower case
	local party = args_t[3] and mw.ustring.upper(args_t[3]);				-- force to upper case
	
	local constituency = local_parameter_to_value_or_boolean (frame, 'constituency');	-- argument overriding the house's number of seats
	
	party_type = xlate (party_type);
	party = xlate (party);
	
	if constituency then
		return tonumber (party_seats) and round (100 * party_seats / constituency) or party_seats;
	elseif party_type == "national_party" and institution == "EP" then
		local member_state_qid = allpp_get_data (frame, party, cfg.data_prop_t.country, 'raw-noref');
		return tonumber (party_seats) and round (100 * party_seats / member_state_delegation_size (frame, member_state_qid)) or party_seats;
	else
		return tonumber (party_seats) and round (100 * party_seats / xlate_wikidata ('property', cfg.institutions_t[institution], 'P1342', '', '', 'reference=no', 'preferred=no', 'raw=no', 'linked=no')) or party_seats;
	end
end


--[[--------------------------< A L L P P _ S E A T S _ I N _ E U _ I N S T I T U T I O N S >------------------------------------------------------------------

return the number of seats occupied by a political party in an <institution> listed in <cfg.parties_t> or in <cfg.alliances_t> (so not including lower and upper houses). <body_prop> is the wikidata property:
	P194: legislative body
	P208: executive body

<frame> required to expand {{wikidata}} template 

Note: P1410 is the property "number of seats in assembly", used to record an entity's seats in legislative or executive bodies

]]

local function allpp_seats_in_eu_institutions (frame, party, institution, body_prop)
	local args_input_t = get_args (frame);
	local verbose = local_parameter_to_value_or_boolean (frame, 'verbose', 'boolean');	-- check verbose and make boolean
	
	local args_t = {};	
	local retval = "";
	if party == "THISPARTY" then												-- flag used when module is called from the page of a European party; less expensive
		retval = xlate_wikidata ('property', '', 'P1410', body_prop, cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');				-- init some of the {{wikidata}} parameters with THISPARTY (only when called from the page of a European party)
	elseif cfg.alliances_t[party] then
		retval = xlate_wikidata ('property', cfg.alliances_t[party], 'P1410', body_prop, cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');	-- init some of the {{wikidata}} parameters
	elseif cfg.parties_t[party] then
		retval = xlate_wikidata ('property', cfg.parties_t[party], 'P1410', body_prop, cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');	-- init some of the {{wikidata}} parameters
	elseif party:match ('^Q%d+$') then
		retval = xlate_wikidata ('property', party, 'P1410', body_prop, cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');			-- init some of the {{wikidata}} parameters
	end

	if '' == retval then														-- {{wikidata}} returns empty string when <party> not known to <institution>
		if party == "THISPARTY" then											-- specific error message if the module was called with THISPARTY from the wrong page
			return "";
		elseif not party then
			return	make_error_msg (substitute (cfg.error_messages_t.party_req_share)), true;
		else
			return  make_error_msg (substitute (cfg.error_messages_t.inst_unknown_party, {institution, party})), true;
		end
	end
	return retval;
end


--[[--------------------------< E U P P _ S U M _ S E A T S _ I N _ E U _ I N S T I T U T I O N S >------------------------------------------------------------------------

return the sum of seats for all European parties combined in an <institution> listed in <cfg.parties_t> (so not including lower and upper houses).  <body_prop> is the wikidata
property:
	P194: legislative body
	P208: executive body

<frame> required to expand {{wikidata}} template 

Note: P1410 is the property "number of seats in assembly", used to record an entity's seats in legislative or executive bodies

]]

local function eupp_sum_seats_in_eu_institutions (frame, institution, body_prop)
	local sum = 0;																-- init

	for _, qid in pairs (cfg.parties_t) do										-- loop through all parties in <cfg.parties_t>
		local local_qid = qid;														-- set the last {{wikidata}} parameter
		sum = sum + xlate_wikidata ('property', local_qid, 'P1410', body_prop, cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');	-- expand and tally
	end

	return sum;
end


--[[--------------------------< E U P P _ S E A T S _ I N _ E U _ I N S T I T U T I O N S >--------------------------------------------------------------------

return a number of seats of a European party (or special parameter) in an <institution> (so not including lower and upper houses).

<frame> required to expand {{wikidata}} template 

Note: 
* P1410 is the property "number of seats in assembly", used to record an entity's seats in legislative or executive bodies
* P1342 is the property "number of seats", used to record an institution's number of seats
* P208 is the property "executive body"
* P194 is the property "legislative body"

]]

local function eupp_seats_in_eu_institutions (frame, party, institution)
	if party == "IND" and institution == "EUCO" then						-- special case of independent politicians on European Council
		return xlate_wikidata ('property', cfg.misc_parties_t['IND'], 'P1410', 'P208', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');

	elseif party == "NONE" then													-- returns seats not occupied by European parties
		local retval = xlate_wikidata ('property', cfg.institutions_t[institution], 'P1342', '', '', 'reference=no', 'preferred=no', 'raw=no', 'linked=no');	-- get number of seats in the institution

		if institution == "EUCO" then											-- if EUCO, use P208 and separate case to account for independent politicians
			local ind = xlate_wikidata ('property', cfg.misc_parties_t['IND'], 'P1410', 'P208', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
			return retval - (eupp_sum_seats_in_eu_institutions (frame, institution, cfg.body_prop_t[institution]) + ind);

		else																	-- COR, EC, EP
			return retval - eupp_sum_seats_in_eu_institutions (frame, institution, cfg.body_prop_t[institution]);
		end

	elseif party == "ALL" then													-- returns seats occupied by all European parties combined
		return eupp_sum_seats_in_eu_institutions (frame, institution, cfg.body_prop_t[institution]);

	elseif party:match ('^Q%d+$') then
		local party_name = cfg.rev_parties_t[party] or cfg.rev_alliances_t[party];
		return allpp_seats_in_eu_institutions (frame, party_name, institution, cfg.body_prop_t[institution]);
	else																		-- returns the number of seats occupied by one party in one institution
		return allpp_seats_in_eu_institutions (frame, party, institution, cfg.body_prop_t[institution]);
	end
end


--[[--------------------------< E U P P _ S E A T _ S H A R E _ I N _ E U _ I N S T I T U T I O N S >--------------------------------------------------------

return a share of seats of a European party (or special parameter) in an <institution> (so not including lower and upper houses).

<frame> required to expand {{wikidata}} template 

Note: 
* P1410 is the property "number of seats in assembly", used to record an entity's seats in legislative or executive bodies
* P1342 is the property "number of seats", used to record an institution's number of seats
* P208 is the property "executive body"
* P194 is the property "legislative body"

]]

local function eupp_seat_share_in_eu_institutions (frame, party, institution)
	if party == "IND" and institution == "EUCO" then							-- special case of independent politicians on European Council
		return allpp_make_share_in_eu_institutions (frame, xlate_wikidata ('property', cfg.misc_parties_t['IND'], 'P1410', 'P208', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no'), institution);

	elseif party == "NONE" then													-- returns seats not occupied by European parties
		local retval = xlate_wikidata ('property', cfg.institutions_t[institution], 'P1342', '', '', 'reference=no', 'preferred=no', 'raw=no', 'linked=no');

		if institution == "EUCO" then											-- if EUCO, use P208 and separate case to account for independent politicians
			local ind = xlate_wikidata ('property', cfg.misc_parties_t['IND'], 'P1410', 'P208', cfg.institutions_t[institution], 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
			return allpp_make_share_in_eu_institutions (frame, retval - (eupp_sum_seats_in_eu_institutions (frame, institution, cfg.body_prop_t[institution]) + ind), institution);

		else																	-- for COR, EC, EP
			return allpp_make_share_in_eu_institutions (frame, retval - eupp_sum_seats_in_eu_institutions (frame, institution, cfg.body_prop_t[institution]), institution);
		end

	elseif party == "ALL" then													-- returns seats occupied by all European parties combined
		return allpp_make_share_in_eu_institutions (frame, eupp_sum_seats_in_eu_institutions (frame, institution, cfg.body_prop_t[institution]), institution);

	elseif party:match ('^Q%d+$') then
		party = cfg.rev_parties_t[party] or cfg.rev_alliances_t[party];
		return allpp_make_share_in_eu_institutions (frame, allpp_seats_in_eu_institutions (frame, party, institution, cfg.body_prop_t[institution]), institution);
	else																		-- returns the number of seats occupied by one party in one institution
		return allpp_make_share_in_eu_institutions (frame, allpp_seats_in_eu_institutions (frame, party, institution, cfg.body_prop_t[institution]), institution);
	end
end


--[[--------------------------< N P P _ S E A T S _ P E R _ R O W >------------------------------

returns the number of seats occupied by a given party (identified by a given row in the master table) in the
lower or upper house of its member state from wikidata.  When <house_type> not recognized or when <tab_data_t>
does not have 'that' house, returns 0

]]

local function npp_seats_per_row (frame, row, house_type)
	local house_qid = "";
	local national_party_qid = cfg.tab_data_t[row].national_party_qid;

	if house_type == "LOWER_HOUSE" then
		house_qid = cfg.tab_data_t[row].lower_house_qid;						-- get the qID of a lower house
	elseif house_type == "UPPER_HOUSE" then
		house_qid = cfg.tab_data_t[row].upper_house_qid;						-- get the qID of an upper house
	end
	
	return house_qid and xlate_wikidata ('property', national_party_qid, 'P1410', 'P194', house_qid, 'reference=no', 'preferred=no', 'raw=no', 'linked=no') or 0;
end


--[[--------------------------< E U P P _ S E A T S _ I N _ N A T I O N A L _ I N S T I T U T I O N S >------------------------------

returns the sum of seats occupied by all national parties members of a given European party in the lower or upper house of its member state.

]]

local function eupp_seats_in_national_institutions (frame, party, house_type)
	local sum_seats = 0;														-- init sum of seats of European party's member parties in house_type

	for row, _ in ipairs (cfg.tab_data_t) do
		if party == "THISPARTY" then											-- if called from the page of a European party
			local thisparty_qid = mw.wikibase.getEntityIdForCurrentPage();		-- get party qiD

			if thisparty_qid == cfg.tab_data_t[row]['european_party_qid'] then
				sum_seats = sum_seats + npp_seats_per_row (frame, row, house_type);	-- increase sum_seats
			end
		elseif party == "ALL" or party == "NONE" then							-- not accepted parameters
			return make_error_msg (substitute (cfg.error_messages_t.all_none_unavailable, {party}));
		elseif party == "IND" then												-- not accepted parameter
			return make_error_msg (substitute (cfg.error_messages_t.ind_only_euco));
		elseif party:match ('^Q%d+$') then										-- if party name is a qID
			if party == cfg.tab_data_t[row]['european_party_qid'] then
				sum_seats = sum_seats + npp_seats_per_row (frame, row, house_type);	-- increase sum_seats
			end
		else																	--for any other party name (already approved via party_type validation)
			if party == cfg.tab_data_t[row]['european_party'] then
				sum_seats = sum_seats + npp_seats_per_row (frame, row, house_type);	-- increase sum_seats
			end
		end
	end

	return sum_seats;
end


--[[--------------------------< E U P P _ S E A T _ S H A R E _ I N _ N A T I O N A L _ I N S T I T U T I O N S >--------------------------------------------------------

return a share of seats occupied by one or more entities listed in <cfg.parties_t> or <cfg.alliances_t>, or by none of them, in an <institution> (so not including lower and upper houses).

<frame> required to expand {{wikidata}} template 

]]

local function eupp_seat_share_in_national_institutions (frame, party, institution)
	return round (100 * eupp_seats_in_national_institutions (frame, party, institution) / total_house_seats (frame, institution));	-- return share of seats by calling seat_share()
end


--[[--------------------------< N P P _ S E A T S _ A N D _ S E A T _ S H A R E _ I N _ N A T I O N A L _ I N S T I T U T I O N S >------------------------------------------------

returns the sum or share of seats occupied by a national party in the lower or upper house of its member state.

]]

local function npp_seats_and_seat_share_in_national_institutions (frame, party, house_type, data)
	local args_t = get_args (frame);											-- get arguments; empty string or whitespace positional parameters set to nil
	local party_qid = "";
	local constituency = local_parameter_to_value_or_boolean (frame, 'constituency');	-- argument overriding the house's number of seats
	
	if party == "THISPARTY" then
		party_qid = mw.wikibase.getEntityIdForCurrentPage();
	elseif party:match ('^Q%d+$') then
		party_qid = party;
	end
	
--[=[ data validation for party_qid ]=]	

	if party_qid == '' then
		return make_error_msg (cfg.error_messages_t.no_qid, template_name);		-- yep, abandon with error message
	end

--[=[ get house_qid from party qid and house_seats ]=]	
	
	local member_state_qid = allpp_get_data (frame, party_qid, cfg.data_prop_t.country, 'raw-noref');
	local house_qid = house_qid_from_member_state_qid (house_type, member_state_qid);
	
	local npp_seats = house_qid and xlate_wikidata ('property', party_qid, 'P1410', 'P194', house_qid, 'reference=no', 'preferred=no', 'raw=no', 'linked=no') or 0;
	local house_seats = house_qid and xlate_wikidata ('property', house_qid, 'P1342', '', '', 'reference=no', 'preferred=no', 'raw=no', 'linked=no') or 0;
	
	if data == "seats" then
		return npp_seats;
	elseif data == "seat share" then
		if constituency then
			return round (100 * npp_seats / constituency);
		else
			return round (100 * npp_seats / house_seats);
		end
	elseif data == "house seats" then
		return house_seats;
	end
end


--[[--------------------------< A L L P P _ C O M P O S I T I O N _ B A R >------------------------------------------------

this function does whatever it is that {{composition bar}} does

implements {{EUPP composition bar}}

	{{EUPP composition bar|<institution>|<party>|width=<width>|percent=yes|reference=yes|bar-color=<color>|background-color=<color>|border=<color>}}
	
]]

local function allpp_composition_bar (frame, party, institution, party_type, compactness)
	local args_t = get_args (frame);											-- get arguments; empty string or whitespace positional parameters set to nil
	
	local verbose = local_parameter_to_value_or_boolean (frame, 'verbose', 'boolean');	-- check verbose and make boolean
	local percentage = local_parameter_to_value_or_boolean (frame, 'percent', 'boolean');	-- check percent and make boolean
	local reference = local_parameter_to_value_or_boolean (frame, 'reference', 'boolean');	-- check reference and make boolean
	local width = local_parameter_to_value_or_boolean (frame, 'width');			-- must be a number, or number with unit suffix: 'px', '%', 'em'; whitespace not allowed
	local constituency = local_parameter_to_value_or_boolean (frame, 'constituency');	-- argument overriding the house's number of seats
	
	local institution_seats = 0;
	local party_seats = 0;
	
	local background_color = local_parameter_to_value_or_boolean (frame, 'background-color');
	local border = local_parameter_to_value_or_boolean (frame, 'border');
	local num1 = local_parameter_to_value_or_boolean (frame, 'num1');
	local bar = local_parameter_to_value_or_boolean (frame, 'bar');
	local num2 = local_parameter_to_value_or_boolean (frame, 'num2');
	
	if width and not validate_width (width) then
		return make_error_msg (substitute (cfg.error_messages_t.parameter_invalid, {width}), template_name);	-- yep, abandon with error message
	end

--[=[ prepare arguments for composition bar ]=]	

	if party_type == "european_entity" then
		if institution == "LOWER_HOUSE" or institution == "UPPER_HOUSE" then
			party_seats = eupp_seats_in_national_institutions (frame, party, institution);	-- get sum of seats occupied by members of a European party
			institution_seats = total_house_seats(frame, institution);			-- get total seats of lower or upper houses
		else
			party_seats = eupp_seats_in_eu_institutions (frame, party, institution);	-- get total seats in <institution> occupied by <party>
			institution_seats = institution_size (frame, institution);			-- get total seats in <institution>
		end
	elseif party_type == "national_party" then
		if institution == "LOWER_HOUSE" or institution == "UPPER_HOUSE" then
			party_seats = npp_seats_and_seat_share_in_national_institutions (frame, party, institution, "seats");
			institution_seats = constituency or npp_seats_and_seat_share_in_national_institutions (frame, party, institution, "house seats")
		elseif institution == "EP" then
			local member_state_qid = allpp_get_data (frame, party, cfg.data_prop_t.country, 'raw-noref');
			local has_error;
			party_seats, has_error = allpp_seats_in_eu_institutions (frame, party, institution, cfg.body_prop_t[institution]);
			if has_error then
				return party_seats;												-- <party_seats> has an error message
			end
			institution_seats = constituency or member_state_delegation_size (frame, member_state_qid);	-- get total seats in <institution>
		else
			local has_error;
			party_seats, has_error = allpp_seats_in_eu_institutions (frame, party, institution, cfg.body_prop_t[institution]);
			if has_error then
				return party_seats;												-- <party_seats> has an error message
			end
			institution_seats = constituency or institution_size (frame, institution);	-- get total seats in <institution>
		end
	end
		
	local color = local_parameter_to_value_or_boolean (frame, 'bar-color') or allpp_get_data (frame, party, cfg.data_prop_t.colour);	-- get color associated with <party>; |bar-color= overrides wikidata
	
	if '' == party_seats or ''== institution_seats then
		if verbose then
			return make_error_msg (substitute (cfg.error_messages_t.no_data_short));
		else
			return "";
		end
	elseif party_type == "european_entity" and (institution == "LOWER_HOUSE" or institution == "UPPER_HOUSE") then
		return xlate_composition_bar (frame, party_seats, institution_seats, color, width, percentage, background_color, border, num1, bar, num2, compactness);
	else
		return xlate_composition_bar (frame, party_seats, institution_seats, color, width, percentage, background_color, border, num1, bar, num2, compactness) .. ((reference and allpp_seats_ref (frame, party, institution)) or '');
	end
end


--[[==========================< S E C T I O N _ 5 : M A I N _ & _ T E S T _ F U N C T I O N S >=======================]]

--[[--------------------------< M A I N >----------------------------------------------------------------------

implements {{EUPP data}} and {{political party data}} (the templates hard-code the <party_type> information)

carries out input error detection, reporting, and function dispatching

Module called by as follows:

{{EUPP data|<data_type>|<institution>|<party>|width=<width>|percent=yes|reference=yes|bar-color=<color>|background-color=<color>|border=<color>}}

{{Political party data|<data_type>|<institution>|<party>|width=<width>|percent=yes|reference=yes|bar-color=<color>|background-color=<color>|border=<color>}}

where <data_type> is:
* seats
* seat share
* seat composition bar
* colour
* individual members
* acronym
* country
* name
* public funding
* website
* foundation date
* chairperson

]]

local function main(frame)
	local template_name = frame:getParent():getTitle()
	local args_t = get_args (frame);											-- get arguments; empty string or whitespace positional parameters set to nil
	local party_type = args_t[1] and mw.ustring.lower(args_t[1]);				-- force to lower case
	local data_type = args_t[2] and mw.ustring.lower(args_t[2]);				-- force to lower case
	local party = args_t[3] and mw.ustring.upper(args_t[3]);					-- force to upper case
	local institution = args_t[4] and mw.ustring.upper(args_t[4]);				-- force to upper case
	local party_qid = "";
	local ref = "";
	
--[=[ translate arguments ]=]	
	
	party_type = xlate (party_type);
	data_type = xlate (data_type);
	party = xlate (party);
	institution = xlate (institution);
	
--[=[ prepare arguments ]=]	
	
	local reference = local_parameter_to_value_or_boolean (frame, 'reference', 'boolean');	-- make a boolean
	
	institution = harmonise_lower_upper_house_name (institution);				-- "ms-lower-house" and "lower" are turned to "lower_house" (same for upper house)
	party = harmonise_lower_upper_house_name (party);							-- in case institution is entered as party
	
	if cfg.institutions_t[party] or party == "LOWER_HOUSE" or party == "UPPER_HOUSE" then -- if the name of the party is actually the institution, then party is "thisparty"
		institution = party;
		party = "THISPARTY";
	end	
	
	if not party then															-- if party is missing, then it is "thisparty"
		party = "THISPARTY";
	end

--[=[ data validation party type ]=]	
	
	if party_type == "european_entity" and not (cfg.parties_t[party] or cfg.alliances_t[party] or cfg.rev_parties_t[party] or cfg.rev_alliances_t[party] or party == "ALL" or party == "NONE" or party == "IND" or party == "THISPARTY") then
		return make_error_msg (substitute (cfg.error_messages_t.not_valid_eupp_parameter, {party}), template_name);
	elseif party_type == "european_entity" and party == "THISPARTY" and not (cfg.rev_parties_t[mw.wikibase.getEntityIdForCurrentPage()] or cfg.rev_alliances_t[mw.wikibase.getEntityIdForCurrentPage()]) then
		return make_error_msg (substitute (cfg.error_messages_t.thisparty), template_name);
	elseif party_type == "national_party" and (cfg.parties_t[party] or cfg.alliances_t[party] or cfg.rev_parties_t[party] or cfg.rev_alliances_t[party] or party == "ALL" or party == "NONE" or party == "IND" or (party == "THISPARTY" and not mw.wikibase.getEntityIdForCurrentPage())) then
		return make_error_msg (substitute (cfg.error_messages_t.not_valid_npp, {party}), template_name);
	end
	
--[=[ data validation institution ]=]	

	local is_valid = false;
	
	is_valid = validate_institution (institution, template_name);
	
	if true ~= is_valid then													-- boolean true when valid; error message else
		return is_valid;														-- yep, abandon with error message
	end

--[=[ function dispatching ]=]

	--[=[ send to seat functions ]=]
	
	if data_type == "seats" then												-- we look for a seat number
		if not institution then													-- institution is required
			return make_error_msg (cfg.error_messages_t.missing_inst, template_name);
		end
		
		if true == reference then
			ref = allpp_seats_ref (frame, party, institution);
		end
		
		if party_type == "european_entity" then									-- the party is a European party or European alliance (specified by the calling template, not by the user)
			if institution == "LOWER_HOUSE" or institution == "UPPER_HOUSE" then	-- we look for seats aross lower or upper houses
				return eupp_seats_in_national_institutions (frame, party, institution) .. ref;	-- return the number of seats by calling eupp_seats_in_national_institutions
			else																-- we look for seats in a European institution
				return eupp_seats_in_eu_institutions (frame, party, institution) .. ref;	-- return the number of seats by calling eupp_seats_in_eu_institutions
			end
		elseif party_type == "national_party" then								-- the party is a national party
			if institution == "LOWER_HOUSE" or institution == "UPPER_HOUSE" then	-- we look for seats in a lower or upper house
				return npp_seats_and_seat_share_in_national_institutions (frame, party, institution, "seats") .. ref;	-- return the number of seats by calling ...
			else																-- we look for seats in a European institution
				return allpp_seats_in_eu_institutions (frame, party, institution, cfg.body_prop_t[institution]) .. ref;	-- return the number of seats by calling allpp_seats_in_eu_institutions
			end
		else
			return make_error_msg (substitute (cfg.error_messages_t.unknown_party_type, {party_type}), template_name);
		end
		
	--[=[ send to seat share functions ]=]
	
	elseif data_type == "seat share" then
		if not institution then													-- institution is required
			return make_error_msg (cfg.error_messages_t.missing_inst, template_name);
		end
		
		if party_type == "european_entity" then
			if institution == "LOWER_HOUSE" or institution == "UPPER_HOUSE" then
				return eupp_seat_share_in_national_institutions (frame, party, institution);
			else 
				return eupp_seat_share_in_eu_institutions (frame, party, institution);
			end
		
		elseif party_type == "national_party" then
			if institution == "LOWER_HOUSE" or institution == "UPPER_HOUSE" then
				return npp_seats_and_seat_share_in_national_institutions (frame, party, institution, "seat share");
			else 
				return allpp_make_share_in_eu_institutions (frame, allpp_seats_in_eu_institutions (frame, party, institution, cfg.body_prop_t[institution]), institution);	-- return share of seats by calling seat_share()
			end			
		
		else
			return make_error_msg (substitute (cfg.error_messages_t.unknown_party_type, {party_type}), template_name);
		end
		
	--[=[ send to composition bar functions ]=]
	
	elseif data_type == "seat composition bar" then
		if not institution then													-- institution is required
			return make_error_msg (cfg.error_messages_t.missing_inst, template_name);
		end
		
		return allpp_composition_bar (frame, party, institution, party_type, "not_compact"); -- composition bar is not compact
		
	--[=[ send to composition bar functions ]=]
	
	elseif data_type == "seat composition bar compact" then
		if not institution then													-- institution is required
			return make_error_msg (cfg.error_messages_t.missing_inst, template_name);
		end
		
		return allpp_composition_bar (frame, party, institution, party_type, "compact"); -- composition bar is compact
		
	--[=[ send to get_data functions ]=]
		
	elseif data_type == "acronym" then
		return allpp_get_data (frame, party, cfg.data_prop_t.acronym);
	elseif data_type == "color" then
		return allpp_get_data (frame, party, cfg.data_prop_t.colour);
	elseif data_type == "country" then
		return allpp_get_data (frame, party, cfg.data_prop_t.country, 'linked');
	elseif data_type == "foundation date" then
		return allpp_get_data (frame, party, cfg.data_prop_t.foundation_date);
	elseif data_type == "foundation year" then
		return mw.getContentLanguage():formatDate("Y",allpp_get_data (frame, party, cfg.data_prop_t.foundation_date, 'raw'));
	elseif data_type == "individual members" then
		return allpp_get_data (frame, party, cfg.data_prop_t.individual_members);
	elseif data_type == "individual members date" then
		return allpp_get_data (frame, party, 'individual members date');
	elseif data_type == "individual members year" then
		return mw.getContentLanguage():formatDate("Y",allpp_get_data (frame, party, 'individual members date', 'raw'));
	elseif data_type == "label" then
		return allpp_get_data (frame, party, 'label');	
	elseif data_type == "official name" then
		return allpp_get_data (frame, party, cfg.data_prop_t.official_name);
	elseif data_type == "parliamentary group" then
		return allpp_get_data (frame, party, cfg.data_prop_t.parliamentary_group, 'linked');
	elseif data_type == "chairperson" then
		return allpp_get_data (frame, party, cfg.data_prop_t.chairperson, 'linked');
	elseif data_type == "public funding" then
		return allpp_get_data (frame, party, cfg.data_prop_t.public_funding);
	elseif data_type == "website" then
		return allpp_get_data (frame, party, cfg.data_prop_t.website);

	else
		return make_error_msg (substitute (cfg.error_messages_t.unknown_data_type, {data_type}), template_name);
	end
end


--[[--------------------------< E U _ I N S T I T U T I O N _ S E A T S >----------------------------------------------------------------------
]]

local function eu_institution_seats (frame)
	local template_name = frame:getParent():getTitle()
	local args_t = get_args (frame);											-- get arguments; empty string or whitespace positional parameters set to nil
	local institution = args_t[1] and mw.ustring.upper(args_t[1]);				-- force to upper case
	
	institution = xlate (institution);
	
	institution = harmonise_lower_upper_house_name (institution);				-- "ms-lower-house" and "lower" are turned to "lower_house" (same for upper house)
	
--[=[ data validation institution ]=]	

	local is_valid = false;
	
	is_valid = validate_institution (institution, template_name);
	
	if true ~= is_valid then													-- boolean true when valid; error message else
		return is_valid;														-- yep, abandon with error message
	end
	
--[=[ return value ]=]

	if institution == 'LOWER_HOUSE' or institution == 'UPPER_HOUSE' then
		return total_house_seats (frame, institution);
	else
		return institution_size (frame, institution);
	end
	
end


--[[--------------------------< T E S T _ W I K I D A T A _ E N T R I E S >----------------------------------------------------------------------
]]

local function test_wikidata_entries (frame)														-- to test calls and functions, for verification purposes
	local wikidata_error = "Wikidata entries error(s):";
	
	for row, _ in ipairs (cfg.tab_data_t) do
		local national_party_qid = cfg.tab_data_t[row].national_party_qid;
		local national_party_name = "";
		
		if not cfg.tab_data_t[row].national_party then
			national_party_name = cfg.tab_data_t[row].national_party_english;
		else
			national_party_name = cfg.tab_data_t[row].national_party;
		end
		
		local lower_house_qid = cfg.tab_data_t[row].lower_house_qid;
		local lower_house_name = cfg.tab_data_t[row].lower_house;
		local upper_house_qid = cfg.tab_data_t[row].upper_house_qid;
		local upper_house_name = cfg.tab_data_t[row].upper_house;
		local retval_lower = xlate_wikidata ('property', national_party_qid, 'P1410', 'P194', lower_house_qid, 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
		local retval_upper = xlate_wikidata ('property', national_party_qid, 'P1410', 'P194', upper_house_qid, 'reference=no', 'preferred=no', 'raw=no', 'linked=no');
		
		if '' == retval_lower then
			wikidata_error = wikidata_error .. " [https://www.wikidata.org/wiki/" .. national_party_qid .. " " .. national_party_name .. "] (" .. lower_house_name .. ")";
		end
		
		if '' == retval_upper then
			wikidata_error = wikidata_error .. " [https://www.wikidata.org/wiki/" .. national_party_qid .. " " .. national_party_name .. "] (" .. upper_house_name .. ")";
		end
	end
	
	if wikidata_error == "Wikidata entries error(s):" then
		wikidata_error = "Wikidata entries: all good!";
	end
	
	return wikidata_error;
end


--[[--------------------------< T E S T >----------------------------------------------------------------------
]]

local function test (frame)																-- to test calls and functions, for verification purposes
	local args_t = get_args (frame);													-- get arguments; empty string or whitespace positional parameters set to nil
	local parameter = args_t['parameter'] and mw.ustring.lower(args_t['parameter']);	-- force to lower case
	local outcome = args_t['outcome'] and mw.ustring.lower(args_t['outcome']);			-- force to lower case
	
	local localised_parameter = xlate_param (parameter); -- translate given parameter from English into local language
	local argument = (args_t[tostring(localised_parameter)] and mw.ustring.lower(args_t[tostring(localised_parameter)])) or (args_t[parameter] and mw.ustring.lower(args_t[parameter]));	-- get argument (in local language) matching parameter in local language
	
	if outcome == 'boolean' then
		if nil == argument then													-- if no argument, return no
			argument = false;
		else
			argument = xlate (argument);										-- translate argument into English
			argument = 'yes' == argument;										-- turn argument into boolean
		end
	elseif argument:match ('^#') then
		argument = argument.gsub(argument, "#", "&#35;");
	end
	
	return argument;
	--return "parameter: " .. parameter .. " - outcome: " .. tostring(outcome) .. " - localised parameter: " .. localised_parameter .. " - argument: " .. tostring(argument);
end


local function test2 (frame)
	return cfg.this_project_language;
end

--[[--------------------------< E X P O R T S >----------------------------------------------------------------
]]

return {
	main = main,
	eu_institution_seats = eu_institution_seats,
	test = test,
	test2 = test2,
	test_wikidata_entries = test_wikidata_entries,
	-- xlate_wikidata = xlate_wikidata
	}