Module:Country data/Bac à sable
[voir] [modifier] [historique] [purger]
Ce module contient des informations utilisées par le système country.
La documentation de ce module est générée par le modèle {{Documentation module}}.
Elle est incluse depuis la page Modèle:Documentation module Country data. Veuillez placer les catégories sur cette page-là.
Les éditeurs peuvent travailler dans le bac à sable (modifier).
Voir les statistiques d'appel depuis le wikicode sur l'outil wstat et les appels depuis d'autres modules.
--[[
This module is intended to replace the functionality of {{drapeau2}} and related
templates. It provides several methods, including
]]
local titleSelf = mw.title.new(... or mw.getCurrentFrame():getTitle())
local sandbox = false
if titleSelf.isSubpage then
sandbox = titleSelf.subpageText:match[[^Bac à sable]] and true
end
local p = {};
local gdata = mw.loadData ("Module:Country data/liste" .. (sandbox and "/Bac à sable" or ""))
local dates = require "Module:date complexe"
local linguistic = require "Module:Linguistique"
local Outils = require "Module:Outils"
local Drapeau = require("Module:Drapeau" .. (sandbox and "/Bac à sable" or ""))
local function _getCompetition(c,aaaa)
local gdomain = mw.loadData ( "Module:Drapeau/Domaine" ) -- chargé seulement sur les articles où ça sert, ça prend un peu de place
local symbs = {
['cm'] = "à la Coupe du monde",
['coupedumonde'] = "à la Coupe du monde",
['ce'] = "au championnat d'Europe",
['euro'] = "au championnat d'Europe",
['chm'] = "au championnat du monde",
['can'] = "à la Coupe des Confédérations",
['coupedesconfederations'] = "à la Coupe des Confédérations",
['en'] = "en",
['jo'] = "aux Jeux olympiques",
['jp'] = "aux Jeux paralympiques",
}
local str = symbs[string.lower(c or '')] or ""
--edition
if(aaaa ~= nil and aaaa ~= "") then
if(c=="jo" or c=="jp" ) then
local o=gdomain.jo["_"..aaaa];
if(o ~= nil) then
str = str .." "..o
end
else
str = str .." "..aaaa
end
end
return str
end
local function printFlag(flagfile, alt, displayformat)
displayformat = displayformat or {}
local size = displayformat.size or '20x15'
local border = 'border|'
if displayformat.border == '-' then
border = ''
end
if not alt then
alt = ''
end
return '<span class="flagicon">' ..
'[[Fichier:' .. flagfile .. '|' .. size ..'px|' .. border .. alt ..'|class=noviewer]]' ..
'</span>';
end
local function bestfordate(data, period) -- data contient une table dont les clés sont des dates au format ['2010'] = ou ['2010-05-04'] =
if type(data) ~= 'table' then
return data
end
-- très artisanal, à améliorer
if (not period) or (period == 'default') then
return data.default
end
local val = data.default
local bestdate = '-1000-01-01'
for i, j in pairs(data) do
if i ~= 'default' and (i:match('^-?%d+$') or i:match('^-?%d--%d--%d+$')) and dates.before(period, i) and dates.before(i, bestdate) then
val = j
bestdate = i
end -- bestdate est la date la plus récente antérieure ou égale à period, val est la donnée à cette date
end
return val
end
local function valueAtDate(data, period, topic, forceTopic) -- topic: type de drapeau, genre de l'adjectif, etc.
topic = topic or "default"
if type(data) ~= 'table' and (topic == "default" or forceTopic ~= true) then
return data
end
if topic ~= "default" and data[topic] then
return bestfordate(data[topic], period)
elseif topic == "default" or forceTopic ~= true then
if type(data.default) == 'table' and data.default.default then
return bestfordate(data.default, period)
else
return bestfordate(data, period)
end
end
return error()
end
local function getData(datatable, typedata, topic, period, forceTopic) -- récupère la chaîne de caractère la plus appropriée dans la datatable
-- datatable: la table de sous module par exemple [[Module:Country data/grenade]]
-- typedata: "flag" / "name" / "adjective"
-- period: data in ISO format
-- topic: for instance "navy" for naval ensign
local val = datatable[typedata]
if val == nil then -- error handling ?
return nil
end
local val = valueAtDate(val, period, topic, forceTopic)
if val == nil then -- error handling ?
return error(val)
end
return val
end
local function getAdjective(data, gender, number)
if not gender then
gender = 'm'
end
if not number then
number = 's'
end
if (gender ~= 'm' and gender ~= 'f') then
return error('gender devrait être m ou f mais est ' .. gender)
end
if (number ~= 's' and number ~= 'p') then
return error('number devrait être s ou p mais est ' .. number)
end
return getData(data, 'adjective', (gender .. number))
end
local function getDemonym (data, gender, number)
if data.demonym == nil then
return linguistic.ucfirst( getAdjective(data, gender, number) )
end
gender = gender or 'm'
number = number or 's'
if (gender ~= 'm' and gender ~= 'f') then
return error('gender devrait être m ou f mais est ' .. gender)
end
if (number ~= 's' and number ~= 'p') then
return error('number devrait être s ou p mais est ' .. number)
end
return getData(data, 'demonym', (gender .. number))
end
local function getLabel(data, topic, period, form)
local label
if (not form) or form == 'short' then
label = getData(data, 'shortname', topic, period)
end
if not label then
label = getData(data, 'name')
end
if (not label) and data.item then
label = mw.wikibase.label(getData(data, 'item'))
end
return label
end
local function getLink(data, topic, period)
local link = getData(data, 'link', topic, period)
if (not link) and data.item then
link = mw.wikibase.label(getData(data, 'item'))
end
return link
end
local function applyregex(str, areadata)
local cio = 'code CIO (en attente)' --require('Module:Wikidata')._formatStatements({entity= areadata.item, property= 'P984'}) or '??'
local label = getData(areadata, 'name')
local of = linguistic.of(label, areadata.genre)
str = mw.ustring.gsub(str, '$de$label', of)
str = mw.ustring.gsub(str, '$label', label)
str = mw.ustring.gsub(str, '$cio', 'cio')
if string.find(str, '$gentile') then
local function get(genre) return getData(areadata, 'adjective', genre) end
local gentileMS, gentileFS, gentileMP, gentileFP = get('ms'), get('fs'), get('mp'), get('fp')
str = mw.ustring.gsub(str, '$gentileMS', gentileMS)
str = mw.ustring.gsub(str, '$gentileFS', gentileFS)
str = mw.ustring.gsub(str, '$gentileMP', gentileMP)
str = mw.ustring.gsub(str, '$gentileFP', gentileFP)
end
return str
end
local function getDatatable(zone)
zoneLower = mw.ustring.lower(zone)
zoneUpper = mw.ustring.upper(zone)
zone = gdata.wikidata[zoneLower] or gdata.alpha3[zoneUpper] or gdata.redirects[zoneLower] or zoneLower
return require('Module:Country data/' .. zone)
end
local function flagIcon(data, flagtype, period, displayformat)
local flagimage = getData(data, 'flag', flagtype, period)
if flagimage then
return printFlag(flagimage, '', displayformat)
end
end
local function getcontents(frame,country,params)
return frame:expandTemplate({title="Country data "..country;args=params})
end
function p.gettable(frame,country,params)
--Returns the parameters of a country data template as a Lua table
--If not a valid data template, return empty table
local bool, s = pcall(getcontents,frame,country,params or {})
if bool and (string.find(s,"^%{%{ *%{%{%{1") or string.find(s,"^%{%{safesubst: *%{%{%{1"))
then
--Replace parameter delimiters with arbitrary control characters
--to avoid clashes if param values contain equals/pipe signs
s = string.gsub(s,"|([^|=]-)=","\1\1%1\2")
s = string.gsub(s,"}}%s*$","\1")
--Loop over string and add params to table
local part = {}
for par in string.gmatch(s,"\1[^\1\2]-\2[^\1\2]-\1") do
local k = string.match(par,"\1%s*(.-)%s*\2")
local v = string.match(par,"\2%s*(.-)%s*\1")
if v and not (v=="" and string.find(k,"^flag alias")) then
part[k] = v
end
end
return part
else
return {}
end
end
function p.gettemplate(frame)
--For testing, recreates the country data from the created Lua table
--Get data table
local data = p.gettable(frame,frame.args[1])
--Concatenate fields into a template-like string
local out = "{{ {{{1}}}"
for k,v in pairs(data) do
out = out.."\n| "..k.." = "..v
end
return out.."\n}}"
end
local function convertTemplateToModuleFormat(data)
if not data.alias or not data['flag alias'] then
return false, nil
end
local newData = {
name = data['shortname alias'] or data.alias,
--gender = {},
link = {default = {default = data.alias}},
flag = {default = {default = data['flag alias']}},
--flagsize = {},
--flagborder = {},
--flagalt = {},
--sortkey = {},
}
if data.size and data.size ~= '' then
newData.size = {default = {default = data.size}}
end
local keys = {
gender = 'gender',
link = 'link',
flag = 'flag',
['size flag'] = 'flagsize',
border = 'flagborder',
['alt attribute'] = 'flagalt',
sortkey = 'sortkey',
}
local topics = {
naval = 'naval',
['air force'] = 'airforce',
army = 'army',
marines = 'marines',
['coast guard'] = 'coastguard',
military = 'military',
}
for k, v in pairs(data) do
local foundKey, foundTopic, foundPeriod
for key, newKey in pairs(keys) do
for topic, newTopic in pairs(topics) do
if k == key .. ' alias-' .. topic then
foundPeriod = 'default'
else
foundPeriod = k:match('^' .. key .. ' alias%-' .. topic .. '%-(%d+)$')
end
if foundPeriod then
foundTopic = newTopic
break
end
end
if not foundTopic then
if k == key then
foundPeriod = 'default'
else
foundPeriod = k:match('^' .. key .. ' alias%-(%d+)$')
end
if foundPeriod then
foundTopic = 'default'
end
end
if not foundTopic then
foundPeriod = 'default'
foundTopic = k:match('^' .. key .. ' alias%-(.+)')
end
if foundTopic then
foundKey = newKey
break
end
end
if foundKey and foundTopic and foundPeriod then
newData[foundKey] = newData[foundKey] or {}
newData[foundKey][foundTopic] = newData[foundKey][foundTopic] or {}
if key == 'link' and v:find('|') then
newData['name'] = newData['name'] or {}
newData['name'][foundTopic] = newData['name'][foundTopic] or {}
local vlink, vname = v:match('^(.-)|(.-)$')
newData[foundKey][foundTopic][foundPeriod] = vlink
newData['name'][foundTopic][foundPeriod] = vname
else
newData[foundKey][foundTopic][foundPeriod] = v
end
end
end
return true, newData
end
-- Retrouver topic et period utilisés par le format modules de données à partir de la variant utilisée par les modèles
local function getTopicAndPeriodFromVariant(variant)
if variant == nil then
return nil, nil
end
-- TODO déplacer un niveau au-dessus pour éviter la répétition ?
local topics = {
naval = 'naval',
['air force'] = 'airforce',
army = 'army',
marines = 'marines',
['coast guard'] = 'coastguard',
military = 'military',
}
for topic, newTopic in pairs(topics) do
if variant == topic then
return newTopic, nil
end
local period = variant:match('^' .. topic .. '%-(%d+)$')
if period then
return newTopic, period
end
end
if variant:match('^(%d+)$') then
return nil, variant
end
return variant, nil
end
local function getDatatableFromTemplate(country)
local data = p.gettable(mw.getCurrentFrame(), country)
if next(data) == nil then
return false, nil
end
return convertTemplateToModuleFormat(data)
end
local function getDatatableFallback(zone)
local success, data = pcall(getDatatable, zone)
if not success then
success, data = getDatatableFromTemplate(zone)
end
return success, data
end
local function getAnyDatatable(zone, usedata)
if usedata == 'template' then
return getDatatableFromTemplate(zone)
elseif usedata == 'module' then
return pcall(getDatatable, zone)
else
return getDatatableFallback(zone)
end
end
function p.standarddisplay(zone, args)
if not zone then
return nil
end
-- nettoyage des paramètres
if not args then
args = {}
end
for i, j in pairs(args) do
args[i] = mw.text.trim(j) -- remove whitespaces
if args[i] == '' then args[i] = nil end
end
-- ajout des valeurs par défaut
local size = args.flagsize or '20x15'
local flagtype = args.type
local align = args.align or 'left'
local link = args.link
local period = args.date
local competition = args.competition
local edition = args.edition
local extra = ''
local success, data = pcall(getDatatable, zone)
if not success then
success, data = getDatatableFromTemplate(zone)
end
if not success then
if args.strict then
return error('lieu non reconnu')
end
return nil
end
-- image
local flag = flagIcon(data, flagtype, period)
if (args.label == '-') then
return flag, true
end
-- text
local text
local label = getLabel(data, flagtype)
local link = getLink(data, flagtype)
if competition then
competition = _getCompetition(linguistic.toascii(competition),args["édition"])
end
if link and competition then
link = link .. ' ' .. competition
end
if link then
text = '[[' .. link .. '|' .. label .. ']]'
end
-- si les données sont extraites d'un formulaire standard comme module:Drapeau/domain, appliquer des regex
if string.match(text, '%$') then
text = applyregex(text, data)
end
local val
if align == 'right' then
val = text .. ' ' .. flag
else
val = flag .. ' ' .. text
end
return val, true -- true indique le succès
end
-- fonction appelable avec #invoke
function p.standarddisplay2(frame)
result, success = p.standarddisplay(frame.args['pays'],frame.args)
return result
end
-- fonction utilitaire pour récupérer les données du drapeau
function p.getFlagData(country, topic, period, usedata)
local success, datatable = getAnyDatatable(country, usedata)
if not success then
return error('Lieu non reconnu') -- FIXME comment faudrait-il gérer l'erreur ?
end
local name = getData(datatable, 'name', topic, period)
local sortkey = getData(datatable, 'sortkey', topic, period)
if not sortkey then
sortkey = name
end
local flag = getData(datatable, 'flag', topic, period)
local border = getData(datatable, 'flagborder', topic, period)
border = border ~= '' and border ~= false
local alt = getData(datatable, 'flagalt', topic, period)
if not alt then
alt = name
end
local size = getData(datatable, 'flagsize', topic, period)
local link = getData(datatable, 'link', topic, period)
if not link then
link = name
end
local gender = getData(datatable, 'gender', topic, period)
return {
flag = flag,
name = name,
sortkey = sortkey,
border = border,
alt = alt,
size = size,
link = link,
gender = gender,
}
end
-- modèle {{pays}}
function p.pays(frame)
local args = Outils.extractArgs(frame)
local templatename = Outils.validTextArg(args, 1)
local name = Outils.validTextArg(args, 'name', 'nom', 1)
local variant = Outils.validTextArg(args, 'variant', 2)
local size = Outils.validTextArg(args, 'size', 'taille')
if not size then
size = '20x18'
end
size = size .. 'px'
-- FIXME La rétrocompatibilité parfaite avec {{pays}} implique de mettre à jour les sous-modules de données
-- par exemple ajouter border="" dans le sous-module Module:Country data/népal
local topic, period = getTopicAndPeriodFromVariant(variant)
-- TODO args.usedata ne devrait pas avoir lieu d'être à terme, mais il est utile pour tester
local flagData = p.getFlagData(templatename, topic, period, args.usedata)
local alt = flagData.alt
if alt == nil then
alt = flagData.name
end
return Drapeau.displayFlag(flagData.flag, {
border = flagData.border,
size = size,
alt = alt,
sortkey = flagData.sortkey,
text = '[[' .. flagData.link .. '|' .. name .. ']]'
})
end
-- modèle {{pays/lien seul}}
function p.pays_lien_seul(frame)
local args = Outils.extractArgs(frame)
local templatename = Outils.validTextArg(args, 1)
local variant = Outils.validTextArg(args, 2)
-- TODO args.usedata ne devrait pas avoir lieu d'être à terme, mais il est utile pour tester
local success, datatable = getAnyDatatable(templatename, args.usedata)
if not success then
return error('Lieu non reconnu') -- FIXME comment faudrait-il gérer l'erreur ?
end
local topic, period = getTopicAndPeriodFromVariant(variant)
local name = getData(datatable, 'name', topic, period)
local link = getData(datatable, 'link', topic, period)
if not link then
link = name
end
return '[[' .. link .. '|' .. name .. ']]'
end
-- Selon la valeur de topic, implémente les modèles
-- naval : {{marine de guerre}}
-- army : {{armée de terre}}
-- airforce : {{armée de l'air}}
local function topicTemplate(frame, topic, prefix)
local args = Outils.extractArgs(frame)
local templatename = Outils.validTextArg(args, 1)
local period = Outils.validTextArg(args, 'variant', 2)
local size = Outils.validTextArg(args, 'size')
if not size then
size = '22x20px'
end
local name = Outils.validTextArg(args, 'name')
-- TODO args.usedata ne devrait pas avoir lieu d'être à terme, mais il est utile pour tester
local success, datatable = getAnyDatatable(templatename, args.usedata)
if not success then
return error('Lieu non reconnu') -- FIXME comment faudrait-il gérer l'erreur ?
end
local flag = getData(datatable, 'flag', topic, period)
local border = getData(datatable, 'flagborder', topic, period)
border = border ~= '' and border ~= false
local linkSuccess, link = pcall(getData, datatable, 'link', topic, period, true)
if not linkSuccess or not link then
link = prefix .. getData(datatable, 'name', topic, period)
end
local linkNameSuccess, linkName = pcall(getData, datatable, 'name', topic, period, true)
if not linkNameSuccess or not linkName then
linkName = name
end
return Drapeau.displayFlag(flag, {
border = border,
size = size,
text = '[[' .. link .. (linkName and ('|' .. linkName) or '') .. ']]'
})
end
-- modèle {{marine de guerre}}
function p.marine_de_guerre(frame)
return topicTemplate(frame, 'naval', 'Marine de ')
end
-- modèle {{armée de terre}}
function p.armee_de_terre(frame)
return topicTemplate(frame, 'army', 'Armée de ')
end
-- modèle {{armée de l'air}}
function p.armee_de_l_air(frame)
return topicTemplate(frame, 'airforce', 'Force aérienne de ')
end
-- modèle {{drapeau}}
function p.drapeau(frame)
local args = Outils.extractArgs(frame)
local templatename = Outils.validTextArg(args, 1)
local variant = Outils.validTextArg(args, 'variant', 2)
local size = Outils.validTextArg(args, 'size', 'taille')
if not size then
size = '20x18'
end
size = size .. 'px'
local topic, period = getTopicAndPeriodFromVariant(variant)
-- TODO args.usedata ne devrait pas avoir lieu d'être à terme, mais il est utile pour tester
local success, flagData = pcall(p.getFlagData, templatename, topic, period, args.usedata)
if not success then
flagData = {}
end
local alt = flagData.alt
if alt == nil and flagData.name then
alt = 'Drapeau : ' .. flagData.name
end
return Drapeau.displayFlag(flagData.flag, {
border = flagData.border,
size = size,
alt = alt
})
end
-- modèle {{getalias}}
function p.getalias(frame)
local args = Outils.extractArgs(frame)
local templatename = Outils.validTextArg(args, 1)
local name = Outils.validTextArg(args, 2)
local variant = Outils.validTextArg(args, 'variant', 3)
-- TODO args.usedata ne devrait pas avoir lieu d'être à terme, mais il est utile pour tester
local success, datatable = getAnyDatatable(templatename, args.usedata)
if not success then
return error('Lieu non reconnu') -- FIXME comment faudrait-il gérer l'erreur ?
end
local topic, period = getTopicAndPeriodFromVariant(variant)
-- Seuls "link" (par défaut), "shortname" et "flag" sont documentés.
if name == 'flag' then
return getData(datatable, 'flag', topic, period)
end
if name == 'shortname' then
return getData(datatable, 'name', topic, period)
end
return getData(datatable, 'link', topic, period)
end
function p.nationality(zone, gender, number, topic, period)
local success, data = pcall(getDatatable, zone)
if not success then return
zone
end
local str = getAdjective(data, gender, number)
if not str then
return zone
end
local link = getLink(data, topic, period)
if link then
str = '[[' .. link .. '|' .. str .. ']]'
end
return str, true-- true indique le succès
end
function p.getNationality(args) -- pour obtenir la nationalité d'une personne sur Wikidata sous forme d'adjectifs
if not args then
return nil
end
local wikidata = require "Module:Wikidata"
local complexdate = require "Module:Date complexe"
if type(args) == 'string' then -- si un seul argument, c'est l'entité à utiliser
args = {item = args}
end
if args.args then -- si vient de frame
args = args.args
end
local item = args.item or args[1]
-- établit la variable gender pour l'élément
local vals = {
['Q6581072'] = 'f',
['Q6581097'] = 'm',
default = '?'
}
local gender = args.gender
if not gender then
gender = wikidata.formatStatements{entity = item, property = 'P21', displayformat = 'raw'}
gender = vals[gender] or vals.default
end
-- désactivation si date de naissance avant l'Ère contemporaine : trop d'imprécisions et d'anachronismes
local mindate = args.mindate or '1789'
if mindate ~= "-" then
local birthdate = wikidata.formatStatements{entity = item, property = 'P569', displayformat = 'raw', numval = 1}
local deathdate = wikidata.formatStatements{entity = item, property = 'P570', displayformat = 'raw', numval = 1}
if ((not birthdate) or complexdate.before(mindate, birthdate)) and ((not deathdate) or complexdate.before(mindate, deathdate)) then
return nil
end
end
return wikidata.formatStatements{
property = 'P27',
showdate = true,
entity = item,
conjtype = args.conjtype or 'and',
removedupes = true,
linktopic = '-',
displayformat =
function(snak)
local g = gender -- genre de la personne, pour affichage du gentilé
if g == '?' then -- si inconnu, au masculin
g = 'm'
end
local val, success = p.nationality(wikidata.getId(snak), g)
if not success then
val = wikidata.formatSnak(snak)
end
return val
end
}
end
return p