Différences entre les pages « Module:Coordinates » et « Module:Wikidata »

De Les Mots de l'agronomie
(Différence entre les pages)
imported>Jacques Ducloy
m (1 révision importée)
 
imported>Jacques Ducloy
m (1 révision importée)
 
Ligne 1 : Ligne 1 :
local math_mod = require( "Module:Math" )
+
--script that retrieves basic data stored in Wikidata, for the datamodel, see https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua
  
local p = {}
+
local wd = {}
  
--Chargement de la liste En/Au/Aux/A
+
local modules = { }
local gdata
+
local modulesNames = {
local success, resultat = pcall (mw.loadData, "Module:Drapeau/Data" )
+
reference = 'Module:Wikidata/Références',
if success then
+
linguistic = 'Module:Linguistique',
gdata = resultat
+
formatDate = 'Module:Date complexe',
else
+
formatNum = 'Module:Conversion',
-- Banque de données à minima en cas de bogue dans le Module:Langue/Data
+
langmodule = 'Module:Langue',
gdata={}
+
cite = 'Module:Biblio',
gdata.data={};
+
getData = 'Module:Wikidata/Récup',
gdata.data[142]={qid="Q142", label="France", genre="fs"}
+
entities = 'Module:Wikidata/Formatage entité',
 +
tools = 'Module:Wikidata/Outils',
 +
globes = 'Module:Wikidata/Globes',
 +
langcodes = 'Module:Dictionnaire Wikidata/Codes langue', -- gros et rarement utilisé
 +
weblink = 'Module:Weblink'
 +
}
 +
 
 +
local function loadModule( t, key )
 +
if modulesNames[key] then
 +
local m = require( modulesNames[key] )
 +
t[key] = m
 +
return m
 +
end
 
end
 
end
 +
setmetatable( modules, { __index = loadModule } )
  
local i18n = {
+
local tools = require 'Module:Wikidata/Outils'
N = 'N',
+
local translate = tools.translate
Nlong = 'nord',
+
local defaultlang = mw.getContentLanguage():getCode()
W = 'O',
 
Wlong = 'ouest',
 
E = 'E',
 
Elong = 'est',
 
S = 'S',
 
Slong = 'sud',
 
degrees = '° ',
 
minutes = '′ ',
 
seconds = '″ ',
 
geohackurl = 'http://tools.wmflabs.org/geohack/geohack.php?language=fr',
 
tooltip = 'Cartes, vues aériennes, etc.',
 
errorcat = 'Page avec des balises de coordonnées mal formées',
 
sameaswikidata = 'Page avec coordonnées similaires sur Wikidata',
 
notaswikidata = 'Page avec coordonnées différentes sur Wikidata',
 
nowikidata = 'Page sans coordonnées Wikidata',
 
throughwikidata = 'Page géolocalisée par Wikidata',
 
invalidFormat = 'format invalide',                                          -- 'invalid coordinate format',
 
invalidNSEW = 'orientation invalide, devrait être "N", "S", "E" or "W"',    -- 'invalid direction should be "N", "S", "E" or "W"',
 
invalidNS = 'orientation de latitude invalide, devrait être "N" ou "S"',    -- 'could not find latitude direction (should be N or S)',
 
invalidEW = 'orientation de longitude invalide, devrait être "E" ou "W"',  -- 'could not find longitude direction (should be W or E) ',
 
noCardinalDirection = 'orientation cardinale non trouvée',                  -- 'no cardinal direction found in coordinates',
 
invalidDirection = 'direction invalide',                                    -- 'invalid direction',
 
latitude90 = 'latitude > 90',
 
longitude360 = 'longitude > 360',
 
minSec60 = 'minutes ou secondes > 60',
 
negativeCoode = 'en format dms les degrés doivent être positifs',          -- 'dms coordinates should be positive',
 
dmIntergers = 'degrés et minutes doivent être des nombres entiers',        -- 'degrees and minutes should be integers',
 
tooManyParam = 'trop de paramètres pour la latitude ou la longitude',      -- 'too many parameters for coordinates',
 
coordMissing = 'latitude ou longitude absente',                            -- 'latitude or longitude missing',
 
invalidGlobe = 'globe invalide : ',                                        -- 'invalid globe:',
 
}
 
local coordParse = {
 
NORTH = 'N',
 
NORD = 'N',
 
EAST = 'E',
 
EST = 'E',
 
WEST = 'W',
 
O = 'W',
 
OUEST = 'W',
 
SOUTH = 'S',
 
SUD = 'S',
 
}
 
  
--Aide:Fonction_genre
+
function wd.getLabel(entity, args)
local genre = {
+
modules.entities.getLabel(entity)
ms =    {le="le ",  du="du ",    de="du ",  au="au ",  en="au "},
+
end
msa =  {le="l'",  du="de l'",  de="d'",  au="à l'", en="en "},
 
msi =  {le="",    du="de ",    de="de ",  au="à ",  en="à "},
 
msia =  {le="",    du="d'",    de="d'",  au="à ",  en="à "},
 
msiae = {le="",    du="d'",    de="d'",  au="à ",  en="en "},
 
fs =    {le="la ",  du="de la ", de="de ",  au="à la ",en="en "},
 
fsa =  {le="l'",  du="de l'",  de="d'",  au="à l'", en="en "},
 
fsi =  {le="",    du="de ",    de="de ",  au="à ",  en="à "},
 
fsia =  {le="",    du="d'",    de="d'",  au="à ",  en="à "},
 
mp =    {le="les ", du="des ",  de="des ", au="aux ", en="aux "},
 
fp =    {le="les ", du="des ",  de="des ", au="aux ", en="aux "}
 
}
 
  
local globedata = {
+
function wd.formatEntity(entity, args)
--[[ notes:
+
return modules.entities.formatEntity(entity, args)
radius in kilometers (especially imprecise for non spheric bodies)
+
end
defaultdisplay is currently disabled, activate it ?
 
]]--
 
ariel = {radius = 580, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
callisto =  {radius = 2410, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
ceres =  {radius = 470, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
charon =  {radius = 1214, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
deimos =  {radius = 7, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
dione =  {radius = 560, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
enceladus =  {radius = 255, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
ganymede =  {radius = 2634, defaultdisplay = 'dec west', trackingcat = 'sur Ganymède'},
 
earth = {radius = 6371, defaultdisplay = 'dms', trackingcat = 'sur Terre'},
 
europa =  {radius = 1561, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
hyperion =  {radius = 140, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
iapetus =  {radius = 725, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
['io'] =  {radius = 1322, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
jupiter =  {radius = 68911, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
mars =  {radius = 3389.5, defaultdisplay = 'dec east', trackingcat =  'sur Mars' },
 
mercury =  {radius = 2439.7, defaultdisplay = 'dec west', trackingcat = 'sur Mercure'},
 
mimas =  {radius = 197, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
miranda =  {radius = 335, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
moon =  {radius = 1736, defaultdisplay = 'dec', trackingcat = 'sur la Lune'},
 
neptune =  {radius = 24553, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
oberon =  {radius = 761, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
phoebe =  {radius = 110, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
phobos =  {radius = 11, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
pluto =  {radius = 1185, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
rhea =  {radius = 765, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
saturn =  {radius = 58232, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
titan =  {radius = 2575.5, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
tethys =  {radius = 530, defaultdisplay = 'dec west', trackingcat = 'extraterrestre'},
 
titania =  {radius = 394, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
triton = {radius = 1353, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
umbriel =  {radius = 584, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
uranus =  {radius = 25266, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'},
 
venus =  {radius = 6051.8, defaultdisplay = 'dec east', trackingcat = 'sur Vénus'},
 
vesta =  {radius = 260, defaultdisplay = 'dec east', trackingcat = 'extraterrestre'}
 
}
 
globedata[''] = globedata.earth
 
  
local wikidatathreshold = 10 -- si la distance entre coordonnées Wikipédia et Wikidata dépasse se seuil (en kilomètes), une catégorie de maintenance est ajoutée
+
function wd.addtrackingcat(prop, cat) -- doit parfois être appelé par d'autres modules
local lang = mw.language.getContentLanguage()
+
if type(prop) == 'table' then
local default_zoom = 13
+
prop = prop[1] -- devrait logiquement toutes les ajouter
 +
end
 +
if not prop and not cat then
 +
return error("no property provided")
 +
end
 +
if not cat then
 +
cat = translate('trackingcat', prop or 'P??')
 +
end
 +
return tools.addcat(cat )
 +
end
  
local function makecat(cat, sortkey)
+
local function removeblanks(args)
if type( sortkey ) == 'string' then
+
for i, j in pairs(args) do
return '[[Category:' .. cat .. '|' .. sortkey .. ']]'
+
if j == '' then args[i] = nil end
else
 
return '[[Category:' .. cat .. ']]'
 
 
end
 
end
 +
return args
 
end
 
end
  
----------------------------------------
+
local function unknownvalue(snak, label)
--Error handling
+
local str = label
--[[ Notes:
 
when errors occure a new error message is concatenated to errorstring
 
an error message contains an error category with a sortkey
 
For major errors, it can also display an error message (the error message will the usually be returned and the function terminated)
 
More minor errors do only add a category, so that readers are not bothered with error texts
 
sortkeys:
 
* A: invalid latitude, longitude or direction
 
* B: invalid globe
 
* C: something wrong with other parameters
 
* D: more than one primary coord
 
]]--
 
  
local errorstring = ''
+
if type(str) == "function" then
 +
str = str(snak)
 +
end
  
local function makeerror(args)
+
if (not str) then
local errormessage = ''
+
if snak.datatype == 'time' then
if args.message then  
+
str = translate('sometime')
errormessage = '<strong class="error"> Coordonnées : ' .. args.message .. '</strong>'  
+
else
 +
str = translate('somevalue')
 +
end
 
end
 
end
local errorcat = ''
+
 
if mw.title.getCurrentTitle().namespace == 0 then  
+
if type(str) ~= "string" then
errorcat = makecat(i18n.errorcat, args.sortkey)
+
return tools.formatError(snak.datatype)
 
end
 
end
errorstring = errormessage .. errorcat -- reinitializes the string to avoid absurdly long messages
+
return str
return nil
 
 
end
 
end
  
local function showerrors()
+
local function novalue(displayformat)
return errorstring
+
if not displayformat then
 +
return translate('novalue')
 +
end
 +
if type(displayformat) == 'string' then
 +
return displayformat
 +
end
 +
return tools.formatError()
 
end
 
end
  
 +
local function getlangcode(entityid)
 +
return modules.langcodes[tonumber(entityid:sub(2))]
 +
end
  
 
+
local  function showlang(statement) -- retourne le code langue entre paranthèse avant la valeur (par exemple pour les biblios et liens externes)
-- Distance computation
+
local mainsnak = statement.mainsnak
function p._distance(a, b, globe) -- calcule la [[distance orthodromique]] en kilomètres entre deux points du globe
+
if mainsnak.snaktype ~= 'value' then
 
+
return nil
globe = string.lower(globe or 'earth')
 
 
-- check arguments and converts degreees to radians
 
local latA, latB, longA, longB = a.latitude, b.latitude, a.longitude, b.longitude
 
if (not latA) or (not latB) or (not longA) or (not longB) then return
 
error('coordinates missing, can\'t compute distance')
 
 
end
 
end
if type(latA) ~= 'number' or type(latB) ~= 'number' or type(longA) ~= 'number' or type(longB) ~= 'number' then
+
local langlist = {}
error('coordinates are not numeric, can\'t compute distance')
+
if mainsnak.datavalue.type == 'monolingualtext' then
 +
langlist = {mainsnak.datavalue.value.language}
 +
elseif (not statement.qualifiers) or (not statement.qualifiers.P407) then
 +
return
 +
else
 +
for i, j in pairs( statement.qualifiers.P407 ) do
 +
if  j.snaktype == 'value' then
 +
local langentity = tools.getId(j)
 +
local langcode = getlangcode(langentity)
 +
table.insert(langlist, langcode)
 +
end
 +
end
 
end
 
end
if not globe or not globedata[globe] then
+
if (#langlist > 1) or (#langlist == 1 and langlist[1] ~= defaultlang) then -- si c'est en français, pas besoin de le dire
return error('globe: ' .. globe .. 'is not supported')
+
return modules.langmodule.indicationMultilingue(langlist)
 
end
 
end
+
end
-- calcul de la distance angulaire en radians
+
 
local convratio = math.pi / 180 -- convertit en radians
+
local function formattable(statements, params) -- transform a table of claims into a table of formatted values
latA, latB, longA, longB = convratio * latA, convratio * latB, convratio * longA, convratio * longB
+
for i, j in pairs(statements) do
local cosangle = math.sin(latA) * math.sin(latB) + math.cos(latA) * math.cos(latB) * math.cos(longB - longA)
+
j = wd.formatStatement(j, params)
if cosangle >= 1 then -- may be above one because of rounding errors
 
return 0
 
 
end
 
end
local angle = math.acos(cosangle)
+
return statements
-- calcul de la distance en km
 
local radius = globedata[globe].radius
 
return radius * angle
 
 
end
 
end
  
function p.distance(frame)
+
function wd.tableToText(values, params) -- takes a list of already formatted values and make them a text
local args = frame.args
+
if not values then
return p._distance(
+
return nil
{latitude = tonumber(args.latitude1), longitude = tonumber(args.longitude1)},
+
end
{latitude = tonumber(args.latitude2), longitude = tonumber(args.longitude2)},
+
 
args.globe)
+
-- filters out nil values to avoid error in subsequent table.concat
 +
local filteredValues = {}
 +
for i, v in ipairs(values) do
 +
if v ~= nil then
 +
table.insert(filteredValues, v)
 +
end
 +
end
 +
 
 +
return modules.linguistic.quickconj( filteredValues, params.conjtype)--modules.linguistic.conj( values, params.lang, params.conjtype )
 
end
 
end
  
local function geoHackUrl(decLat, decLong, globe, displayformat, objectname, extraparams)
+
 
extraparams = extraparams or ''
+
function wd.addStandardQualifs(str, statement)
local geohacklatitude, geohacklongitude
+
if (not statement) or (not statement.qualifiers) then
-- format latitude and longitude for the URL
+
return str
if tonumber(decLat) < 0 then
+
end
geohacklatitude = tostring(-tonumber(decLat)) .. '_S'
+
if not str then
else
+
return tools.formatError("adding qualifs to a nil str !")-- il y a un problème
geohacklatitude = decLat .. '_N'
 
 
end
 
end
if tonumber(decLong) < 0  then
+
if statement.qualifiers.P1480 then
geohacklongitude = tostring(-tonumber(decLong)) .. '_W'
+
for i, j in pairs(statement.qualifiers.P1480) do
elseif globedata[globe].defaultdisplay == 'dec west' then
+
local v = tools.getId(j)
geohacklongitude = decLong .. '_W'
+
if (v == "Q21818619") then
else
+
str = str .. " (ou environs)"
geohacklongitude = decLong .. '_E'
+
elseif (v == "Q18122778") or (v == "Q18912752") then
 +
str = str.. " (?)"
 +
elseif (v == "Q5727902") then -- traité séparément, car plus complexe séparément
 +
end
 +
end
 
end
 
end
-- prepares the 'paramss=' parameter
+
return str
local geohackparams = geohacklatitude .. '_' .. geohacklongitude .. '_' ..extraparams
 
-- concatenate parameteres for geohack
 
return i18n.geohackurl ..
 
"&pagename=" .. mw.uri.encode(mw.title.getCurrentTitle().prefixedText, "WIKI") ..
 
"&params=" .. geohackparams ..
 
(objectname and ("&title=" .. mw.uri.encode(objectname)) or "")
 
 
end
 
end
  
--HTML builder for a geohack link
+
function wd.rangeobject(begin, ending, params)
local function buildHTML(decLat, decLong, dmsLat, dmsLong, globe, displayformat, displayinline, displaytitle, objectname, extraparams)
+
--[[
-- geohack url
+
objet comportant un timestamp pour le classement chronologique et deux dateobject (begin et ending)
local url = geoHackUrl(decLat, decLong, globe, displayformat, objectname, extraparams)
+
]]--  
+
local timestamp
-- displayed coordinates
+
if begin then
local displaycoords
+
timestamp = begin.timestamp
if string.sub(displayformat,1,3) == 'dec' then
 
displaycoords = p.displaydec(decLat, decLong, displayformat)
 
 
else
 
else
displaycoords = {
+
timestamp = ending.timestamp
p.displaydmsdimension(dmsLat, displayformat),
 
p.displaydmsdimension(dmsLong, displayformat),
 
}
 
 
end
 
end
+
return {begin = begin, ending = ending, timestamp = timestamp, type = 'rangeobject'}
-- build coordinate in h-geo / h-card microformat
+
end
local globeNode
+
 
if globe and globe ~= 'earth' then
+
function wd.dateobject(orig, params)
globeNode = mw.html.create('data')
+
--[[ transforme un snak en un nouvel objet utilisable par Module:Date complexe
:addClass('p-globe')
+
{type = 'dateobject', timestamp = str, era = '+' ou '-', year = number, month = number, day = number, calendar = calendar}
:attr{ value = globe }
+
]]--
:done()
+
if not params then
 +
params = {}
 
end
 
end
 
 
local coordNode = mw.html.create('')
+
local newobj = modules.formatDate.splitDate(orig.time, orig.calendar)
if objectname then
 
coordNode = mw.html.create('span')
 
:addClass('h-card')
 
:tag('data')
 
:addClass('p-name')
 
:attr{ value = objectname }
 
:done()
 
end
 
coordNode
 
:tag('span')
 
:addClass('h-geo')
 
:addClass('geo-' .. string.sub(displayformat,1,3))
 
:tag('data')
 
:addClass('p-latitude')
 
:attr{ value = decLat }
 
:wikitext( displaycoords[1] )
 
:done()
 
:wikitext(", ")
 
:tag('data')
 
:addClass('p-longitude')
 
:attr{ value = decLong }
 
:wikitext( displaycoords[2] )
 
:done()
 
:node( globeNode )
 
:done()
 
 
 
-- buid GeoHack link
+
newobj.precision = params.precision or orig.precision
local root = mw.html.create('span')
+
newobj.type = 'dateobject'
:addClass('plainlinks nourlexpansion')
+
return newobj
:attr('title', i18n.tooltip)
+
end
:wikitext('[' .. url )
+
 
:node(coordNode)
+
function wd.objecttotext(obj, params)
:wikitext("]")
+
if obj.type == 'dateobject' then
:done()
+
return modules.formatDate.simplestring(obj, params)
+
elseif obj.type == 'rangeobject' then
-- format result depending on args["display"] (nil, "inline", "title", "inline,title")
+
return modules.formatDate.daterange(obj.begin, obj.ending, params)
local inlineText = displayinline and tostring(root) or ''
 
local titleText = ''
 
if displaytitle then
 
local htmlTitle = mw.html.create('span')
 
:attr{ id = 'coordinates' }
 
:addClass( displayinline and 'noprint' or nil )
 
:node( root )
 
local frame = mw.getCurrentFrame()
 
titleText = frame:extensionTag( 'indicator', tostring(htmlTitle), { name = 'coordinates' } )
 
 
end
 
end
 
return inlineText .. titleText
 
 
end
 
end
  
local function zoom( extraparams )
+
local function getDatefromQualif(statement, qualif)
local zoomParam = extraparams:match( '%f[%w]zoom: ?(%d+)' )
+
if (not statement) or (not statement.qualifiers) or not (statement.qualifiers[qualif]) then
if zoomParam then
+
return nil
return zoomParam
 
 
end
 
end
+
local v = statement.qualifiers[qualif][1]
local scale = extraparams:match( '%f[%w]scale: ?(%d+)' )
+
if v.snaktype ~= 'value' then -- que faire dans ce cas ?
if scale then
+
return nil
return math.floor(math.log10( 1 / tonumber( scale ) ) * 3 + 25)
 
end
 
 
local extraType = extraparams:match( '%f[%w]type: ?(%w+)' )
 
if extraType then
 
local zoomType = {
 
country = 5,
 
state = 6,
 
adm1st = 7,
 
adm2nd = 8,
 
city = 9,
 
isle = 10,
 
mountain = 10,
 
waterbody = 10,
 
airport = 12,
 
landmark = 13,
 
}
 
return zoomType[ extraType ]
 
 
end
 
end
 +
return wd.dateobject(v.datavalue.value)
 
end
 
end
  
--HTML builder for a geohack link
+
function wd.getDate(statement)
local function buildMaplinkHTML( decLat, decLong, dmsLat, dmsLong, globe, displayformat, displayinline, displaytitle, objectname, extraparams )
+
local period = getDatefromQualif(statement, 'P585') -- retourne un dateobject
-- displayed coordinates
+
if period then
local displaycoords
+
return period
if string.sub(displayformat,1,3) == 'dec' then
 
displaycoords = p.displaydec(decLat, decLong, displayformat)
 
else
 
displaycoords = {
 
p.displaydmsdimension(dmsLat, displayformat),
 
p.displaydmsdimension(dmsLong, displayformat),
 
}
 
 
end
 
end
+
local begin, ending = getDatefromQualif(statement, 'P580'), getDatefromQualif(statement, 'P582')
-- JSON for maplink
+
if begin or ending then
local jsonParams = {
+
return wd.rangeobject(begin, ending) -- retourne un rangeobject fait de deux dateobject
type = 'Feature',
 
geometry = {
 
type ='Point',
 
coordinates = {
 
math_mod._round( decLong, 6 ), -- max precision in GeoJSON format
 
math_mod._round( decLat, 6 )
 
}
 
},
 
properties = {
 
['marker-color'] = "228b22",
 
}
 
}
 
if objectname then
 
jsonParams.properties.title = objectname
 
 
end
 
end
-- ajout de geoshape via externaldata
+
end
local geoshape = extraparams:match( '%f[%w]geoshape: ?(Q%d+)' )
+
function wd.getFormattedDate(statement, params, useallqualifiers)
if not geoshape and displaytitle and mw.wikibase.getEntity() then
+
if not statement then
geoshape = mw.wikibase.getEntity().id
+
return nil
 
end
 
end
if geoshape then
+
local str
jsonParams = {
+
 
jsonParams,
+
local fuzzy = modules.getData.hasqualifier(statement, {"P1480"}, {"Q5727902"})
{
+
if fuzzy then
type = 'ExternalData',
+
fuzzy = true
service = 'geoshape',
 
ids = geoshape,
 
properties = {
 
['fill-opacity'] = 0.2
 
}
 
}
 
}
 
 
end
 
end
  
local maplink = mw.getCurrentFrame():extensionTag{
+
--cherche la date avec les qualifs P580/P582
name = 'maplink',
+
local datetable = wd.getDate(statement)
content = mw.text.jsonEncode( jsonParams ),
+
if datetable then
args = {
+
str = wd.objecttotext(datetable, params)
text = displaycoords[1] .. ", " .. displaycoords[2],
+
end
zoom = zoom( extraparams ) or default_zoom,
 
latitude = decLat,
 
longitude = decLong,
 
}
 
}
 
 
 
-- format result depending on args["display"] (nil, "inline", "title", "inline,title")
+
-- puis limite intérieur / supérieur
local inlineText = displayinline and maplink or ''
+
if not str then
local titleText = ''
+
local start, ending = getDatefromQualif(statement, 'P1319'), getDatefromQualif(statement, 'P1326')
if displaytitle then
+
str = modules.formatDate.between(start, ending, params)
local htmlTitle = mw.html.create('span')
 
:attr{ id = 'coordinates' }
 
:addClass( displayinline and 'noprint' or nil )
 
:wikitext( maplink )
 
local frame = mw.getCurrentFrame()
 
titleText = frame:extensionTag( 'indicator', tostring(htmlTitle), { name = 'coordinates' } )
 
 
end
 
end
 
return inlineText .. titleText
 
end
 
  
-- dms specific funcions
+
-- sinon, le mainsnak, pour les données de type time
 +
if (not str) and (statement.mainsnak.datatype == 'time') then
 +
local mainsnak = statement.mainsnak
 +
if
 +
(mainsnak.snaktype == 'value' and mainsnak.datavalue.value.precision > 7)
 +
or
 +
(mainsnak.snaktype == 'somevalue')
 +
then
 +
str = wd.formatSnak(mainsnak, params)
 +
end
 +
end
  
local function twoDigit( value )
+
-- ajouter le qualificatif "environ"
if ( value < 10 ) then
+
if fuzzy then
value = '0' .. lang:formatNum( value )
+
str = modules.formatDate.fuzzydate(str)
else
+
end
value = lang:formatNum( value )
+
-- autres valeurs de qualité de l'information
 +
if str and (useallqualifiers ~= "-") then
 +
str = wd.addStandardQualifs(str, statement)
 +
if params.showqualifiers then
 +
str = wd.showQualifiers(str, statement, params)
 +
end
 
end
 
end
return value
+
return str
 
end
 
end
  
function p.displaydmsdimension(valuetable, format) -- formate en latitude ou une longitude dms
+
-- Fonction qui trie des Claims de type time selon l'ordre chronologique
local str = ''
+
-- Une clé de tri nomée « dateSortKey » est ajouté à chaque claim.
local direction = valuetable.direction
+
-- Si des clés de tri de ce nom existent déjà, elles sont utilisées sans modification.
local degrees, minutes, seconds = '', '', ''
+
function wd.sortDateClaims( claims )
local dimension
+
for _, claim in ipairs( claims ) do
 +
if not claim.dateSortKey then
 +
local iso = wd.formatSnak( claim.mainsnak, { displayformat = 'raw' } )
 +
-- transformation en nombre (indication de la base car gsub retourne deux valeurs)
 +
iso = tonumber( iso:gsub( '(%d)%D', '%1' ), 10 ) or 0
 +
claim.dateSortKey = iso
 +
end
 +
end
 +
table.sort(
 +
claims,
 +
function ( c1, c2 )
 +
return c1.dateSortKey < c2.dateSortKey
 +
end
 +
)
 +
end
  
if format == 'dms long' then
+
function wd.wikidataDate(prop, item, params)
direction = i18n[direction .. 'long']
+
local claims = wd.getClaims{entity = item, property = prop}
else
+
if not claims then
direction = i18n[direction]
+
return nil
 +
end
 +
wd.sortDateClaims( claims )
 +
params = params or {}
 +
local vals = {}
 +
for i, j in ipairs(claims) do
 +
local v = wd.getFormattedDate(j, params)
 +
if v then
 +
table.insert(vals, v)
 +
end
 
end
 
end
degrees = lang:formatNum( valuetable.degrees ) .. i18n.degrees
 
 
 
if valuetable.minutes then
+
local str = modules.linguistic.conj(vals, params.conjtype or 'or')
minutes = twoDigit( valuetable.minutes ) .. i18n.minutes
+
 
 +
if not str then
 +
return
 +
end
 +
 
 +
if params.addcat ~= '-' then
 +
str = str .. wd.addtrackingcat(prop)
 
end
 
end
if valuetable.seconds then
+
 
seconds = twoDigit( valuetable.seconds ) .. i18n.seconds
+
if params.linkback ~= '-' then
 +
str = wd.addLinkback(str, item, prop)
 
end
 
end
return degrees .. minutes .. seconds .. direction
+
return str
 
end
 
end
  
local function validdms(coordtable)
+
function wd.getReferences(statement)
local direction = coordtable.direction
+
local refdata = statement.references
local degrees = coordtable.degrees or 0
+
if not refdata then
local minutes = coordtable.minutes or 0
+
return nil
local seconds = coordtable.seconds or 0
 
local dimension = coordtable.dimension
 
if not dimension then
 
if direction == 'N' or direction == 'S' then
 
dimension = 'latitude'
 
elseif direction == 'E' or direction == 'W' then
 
dimension = 'longitude'
 
else
 
makeerror({message = i18n.invalidNSEW, sortkey = 'A'})
 
return false
 
end
 
 
end
 
end
  
if type(degrees) ~= 'number' or type(minutes) ~= 'number' or type(seconds) ~= 'number' then
+
local function firstsnak(prop)
makeerror({message = i18n.invalidFormat, sortkey = 'A'})
+
return wd.formatSnak(prop[1])
return false
 
 
end
 
end
 +
 +
local refs = {}
 +
for i, ref in pairs(refdata) do
 +
local s
 +
local function hasValue(prop) -- checks that the prop is here with valid value
 +
if ref.snaks[prop] and ref.snaks[prop][1].snaktype == 'value' then
 +
return true
 +
end
 +
return false
 +
end
 +
 +
if ref.snaks.P248 then
 +
for j, source in pairs(ref.snaks.P248) do
 +
if source.snaktype == 'value' then
 +
local page, accessdate
 +
if hasValue('P304') then
 +
page = wd.formatSnak(ref.snaks.P304[1])
 +
end
 +
if hasValue('P813') then
 +
accessdate = wd.formatSnak(ref.snaks.P813[1])
 +
end
 +
s = modules.reference.citeitem(tools.getId(source), {['page'] = page, ['accessdate'] = accessdate})
 +
table.insert(refs, s)
 +
end
 +
end
 
 
if dimension == 'latitude' and direction ~= 'N' and direction ~= 'S' then
+
elseif hasValue('P854') and hasValue('P1476') then
makeerror({message = i18n.invalidNS, sortkey = 'A'})
+
local url, title, accessdate, publishdate, publishlang
return false
+
url, title = wd.formatSnak(ref.snaks.P854[1], {text = "-"}), wd.formatSnak(ref.snaks.P1476[1])
 +
if hasValue('P813') then
 +
accessdate = wd.formatSnak(ref.snaks.P813[1])
 +
end
 +
-- publishdate avec P577 ? (ne semble pas vraiment correspondre)
 +
if hasValue('P407') then
 +
local id = tools.getId(ref.snaks.P407[1])
 +
publishlang = getlangcode(id)
 +
end
 +
s = modules.cite.lienWeb{titre = title, url = url, langue = publishlang, ['en ligne le'] = publishdate, ['consulté le'] = accessdate}
 +
table.insert(refs, s)
 +
elseif ref.snaks.P854 and ref.snaks.P854[1].snaktype == 'value' then
 +
s = wd.formatSnak(ref.snaks.P854[1], {text = "-"})
 +
table.insert(refs, s)
 +
end
 
end
 
end
if dimension == 'longitude' and direction ~= 'W' and direction ~= 'E' then
+
if #refs > 0 then
makeerror({message = i18n.invalidEW, sortkey = 'A'})
+
return refs
return false
 
 
end
 
end
+
end
if dimension == 'latitude' and degrees > 90 then
+
 
makeerror({message = i18n.latitude90, sortkey = 'A'})
+
function wd.getDatavalue(snak, params)
return false
+
if not params then
 +
params = {}
 
end
 
end
+
local speciallabels = params.speciallabels -- parfois on a besoin de faire une liste d'éléments pour lequel le libellé doit être changé, pas très pratique d'utiliser une fonction pour ça
if dimension == 'longitude' and degrees > 360 then
+
 
makeerror({message = i18n.longitude360, sortkey = 'A'})
+
if snak.snaktype ~= 'value' then
return false
+
return nil
 
end
 
end
 +
 +
local datatype = snak.datatype
 +
local value = snak.datavalue.value
 
 
if degrees < 0 or minutes < 0 or seconds < 0 then
+
local displayformat = params.displayformat
makeerror({message = i18n.negativeCoode, sortkey = 'A'})
+
if type(displayformat) == 'function' then
return false
+
return displayformat(snak, params)
 
end
 
end
+
 
if minutes > 60 or seconds > 60 then
+
if datatype == 'wikibase-item' then
makeerror({message = i18n.minSec60, sortkey = 'A'})
+
return modules.entities.formatEntity(tools.getId(snak), params)
return false
 
end
 
if (math.floor(degrees) ~= degrees and minutes ~= 0) or (math.floor(minutes) ~= minutes and seconds ~= 0) then
 
makeerror({message = i18n.dmIntergers, sortkey = 'A'})
 
return false
 
 
end
 
end
return true
 
end
 
  
local function builddmsdimension(degrees, minutes, seconds, direction, dimension)
+
if datatype == 'url' then
-- no error checking, done in function validdms
+
return modules.weblink.makelink(value, params.text)
local dimensionobject = {}
 
 
-- direction and dimension (= latitude or longitude)
 
dimensionobject.direction = direction
 
if dimension then
 
dimensionobject.dimension = dimension
 
elseif direction == 'N' or direction == 'S' then
 
dimensionobject.dimension = 'latitude'
 
elseif direction == 'E' or direction == 'W' then
 
dimensionobject.dimension = 'longitude'
 
 
end
 
end
 
-- degrees, minutes, seconds
 
dimensionobject.degrees = tonumber(degrees)
 
dimensionobject.minutes = tonumber(minutes)
 
dimensionobject.seconds = tonumber(seconds)
 
if degrees and not dimensionobject.degrees then dimensionobject.degrees = 'error' end
 
if minutes and not dimensionobject.minutes then dimensionobject.minutes = 'error' end
 
if seconds and not dimensionobject.seconds then dimensionobject.seconds = 'error' end
 
return dimensionobject
 
end
 
  
function p._parsedmsstring(str, dimension) -- prend une séquence et donne des noms aux paramètres
+
if datatype == 'math' then
-- output table: {latitude=, longitude = , direction =  }
+
return mw.getCurrentFrame():extensionTag( "math", value)
if type( str ) ~= 'string' then
 
return nil
 
 
end
 
end
str = mw.ustring.gsub( mw.ustring.upper( str ), '%a+', coordParse )
+
 
if not tonumber( str ) and not str:find( '/' ) and str:find( '°' ) then
+
if (datatype == 'string') or (datatype == 'external-id') or (datatype == 'commonsMedia') then -- toutes les données de type string sauf "math"
local str2 = mw.ustring.gsub( str, '[°″′\"\'\194\160 ]+', '/' )
+
if params.urlpattern then
-- avoid cases were there is degree ans seconds but no minutes
+
local urlpattern = params.urlpattern
if not mw.ustring.find( str, '[″"]' ) or mw.ustring.find( str, '%d[′\'][ \194\160%d]' ) then
+
if type(urlpattern) == 'function' then
str = str2
+
urlpattern = urlpattern(value)
 +
end
 +
local url = mw.ustring.gsub(urlpattern, '$1', (value:gsub('%%', '%%%%'))):gsub(' ', '%%20')
 +
value = '[' .. url .. ' ' .. (params.text or value) .. ']'
 
end
 
end
 +
return value
 
end
 
end
if not tonumber(str) and not string.find(str, '/') then
+
makeerror({message = i18n.invalidFormat, sortkey= 'A'})
+
if datatype == 'time' then -- format example: +00000001809-02-12T00:00:00Z
return nil
+
local precision = params.precision -- degré de précision à afficher ('day', 'month', 'year'), inférieur ou égal à value.precision
 +
if displayformat == 'raw' then
 +
return value.time
 +
else
 +
return wd.objecttotext(wd.dateobject(value, {precision = precision}), {linktopic = params.linktopic})
 +
end
 
end
 
end
args = mw.text.split(str, '/', true)
+
 
if #args > 4 then
+
if datatype == 'globe-coordinate' then
makeerror({message = i18n.tooManyParam, sortkey= 'A' })
+
-- retourne une table avec clés latitude, longitude, précision et globe à formater par un autre module (à changer ?)
end
+
if displayformat == 'latitude' then
local direction = mw.text.trim(args[#args])
+
return value.latitude
table.remove(args)
+
elseif displayformat == 'longitude' then
local degrees, minutes, seconds = args[1], args[2], args[3]
+
return value.longitude
local dimensionobject = builddmsdimension(degrees, minutes, seconds, direction, dimension)
+
else
if validdms(dimensionobject) then
+
local coordvalue = mw.clone( value )
return dimensionobject
+
coordvalue.globe = modules.globes[value.globe] -- transforme l'ID du globe en nom anglais utilisable par geohack
else
+
return coordvalue -- note : les coordonnées Wikidata peuvent être utilisée depuis Module:Coordinates. Faut-il aussi autoriser à appeler Module:Coordiantes ici ?
return nil
+
end
 
end
 
end
end
 
  
--- decimal specific functions
+
if datatype == 'quantity' then -- todo : gérer les paramètre précision
function p.displaydec(latitude, longitude, format)
+
local amount, unit = value.amount, value.unit
lat = lang:formatNum( latitude )
+
 
long = lang:formatNum( longitude )
+
if unit then
+
unit = unit:match('Q%d+')
if format == 'dec west' or  format == 'dec east' then
 
local symbolNS, symbolEW = i18n.N, i18n.E
 
if latitude < 0 then  
 
symbolNS = i18n.S
 
lat = lat:sub( 2 )
 
 
end
 
end
if format == 'dec west' then
+
 
symbolEW = i18n.W
+
local showunit = params.showunit or true
 +
if showunit == '-' then
 +
showunit = false
 
end
 
end
if longitude < 0 then  
+
local raw
long = lang:formatNum( 360 + longitude )
+
if displayformat == "raw" then
 +
raw = true
 
end
 
end
+
return modules.formatNum.displayvalue(amount, unit,
return { lat .. i18n.degrees .. symbolNS, long ..  i18n.degrees .. symbolEW }
+
{targetunit = params.targetunit, raw = raw, rounding = params.rounding, showunit = showunit}
+
)
else
 
return { lat, long }
 
 
end
 
end
 +
if datatype == 'monolingualtext' then
 +
if value.language == defaultlang then
 +
return value.text
 +
else
 +
return modules.langmodule.langue({value.language, value.text})
 +
end
 +
end
 +
return tools.formatError('unknown-datavalue-type' )
 +
 
end
 
end
  
 +
function wd.getClaims( args ) -- returns a table of the claims matching some conditions given in args
 +
return modules.getData.getClaims(args)
 +
end
  
local function parsedec(dec, coordtype, globe) -- coordtype = latitude or longitude
+
 
dec = mw.text.trim(dec)
+
function wd.stringTable(args) -- like getClaims, but get a list of string rather than a list of snaks, for easier manipulation
if not dec then
+
 +
local claims = args.claims
 +
if not claims then
 +
claims = wd.getClaims(args)
 +
end
 +
if not claims or claims == {} then
 
return nil
 
return nil
 
end
 
end
if coordtype ~= 'latitude' and coordtype ~= 'longitude' then
+
local props = {} -- liste des propriétés associété à chaque string pour catégorisation et linkback
makeerror({'invalid coord type', sortkey = "A"})
+
for i, j in pairs(claims) do
 +
claims[i] = wd.formatStatement(j, args)
 +
table.insert(props, j.mainsnak.property)
 +
end
 +
if args.removedupes and (args.removedupes ~= '-') then
 +
claims = tools.addnewvalues({}, claims) -- devrait aussi supprimer de props celles qui ne sont pas utilisées
 +
end
 +
return claims, props
 +
end
 +
 
 +
function wd.getQualifiers(statement, qualifs, params)
 +
if not statement.qualifiers then
 
return nil
 
return nil
 
end
 
end
local numdec = tonumber(dec) -- numeric value, kept separated as it looses significant zeros
+
local vals = {}
if not numdec then -- tries the decimal + direction format
+
if type(qualifs) == 'string' then
dec = mw.ustring.gsub( mw.ustring.upper( dec ), '%a+', coordParse )
+
qualifs = tools.splitStr(qualifs)
local direction = mw.ustring.sub(dec, mw.ustring.len(dec), mw.ustring.len(dec))
+
end
dec = mw.ustring.sub(dec, 1, mw.ustring.len(dec)-2) -- removes the /N at the end
+
for i, j in pairs(qualifs) do
if not dec or not tonumber(dec) then
+
if statement.qualifiers[j] then
return nil
+
for k, l in pairs(statement.qualifiers[j]) do
end
+
table.insert(vals, l)
if direction == 'N' or direction == 'E' or direction == 'W' and globedata[globe].defaultdisplay == 'dec west' then
 
return dec
 
elseif direction == 'W' or direction == 'S' then
 
return '-' .. dec
 
else
 
if coordtype == 'latitude' then
 
makeerror({message = i18n.invalidNS, sortkey = 'A'})
 
else
 
makeerror({message = i18n.invalidEW, sortkey = 'A'})
 
 
end
 
end
return nil
 
 
end
 
end
 
end
 
end
 +
if #vals == 0 then
 +
return nil
 +
end
 +
return vals
 +
end
  
if coordtype == 'latitude' and math.abs(numdec) > 90 then
+
function wd.getFormattedQualifiers(statement, qualifs, params)
makeerror({message = i18n.latitude90 , sortkey = 'A'})
+
if not params then params = {} end
 +
local qualiftable = wd.getQualifiers(statement, qualifs)
 +
if not qualiftable then
 
return nil
 
return nil
 
end
 
end
if coordtype == 'longitude' and math.abs(numdec) > 360 then
+
for i, j in pairs(qualiftable) do
makeerror({message = i18n.longitude360 , sortkey = 'A'})
+
qualiftable[i] = wd.formatSnak(j, params)
return nil
 
 
end
 
end
return dec
+
return modules.linguistic.conj(qualiftable, params.conjtype)
 
end
 
end
  
-- dms/dec conversion functions
+
function wd.showQualifiers(str, statement, args) -- utilisée par formatStatement et par wikidatadate
local function convertprecision(precision) -- converts a decimal precision like "2" into "dm"
+
local qualifs =  args.showqualifiers
if precision >= 3 then
+
if not qualifs then
return 'dms'
+
return str -- or error ?
elseif precision >=1 then
+
end
return 'dm'
+
if type(qualifs) == 'string' then
else
+
qualifs = tools.splitStr(qualifs)
return 'd'
+
end
 +
local qualifargs = args.qualifargs or {}
 +
-- formatage des qualificatifs = args commençant par "qualif", ou à défaut, les mêmes que pour la valeur principale
 +
qualifargs.displayformat = args.qualifdisplayformat or args.displayformat
 +
qualifargs.labelformat = args.qualiflabelformat or args.labelformat
 +
qualifargs.link = args.qualiflink or args.link
 +
qualifargs.conjtype = args.qualifconjtype
 +
 +
local formattedqualifs = wd.getFormattedQualifiers(statement, qualifs, qualifargs)
 +
if formattedqualifs and str then
 +
str = str .. modules.linguistic.inparentheses(formattedqualifs, defaultlang)
 
end
 
end
 +
return str
 
end
 
end
  
local function determinedmsprec(decs) -- returns the most precision for a dec2dms conversion, depending on the most precise value in the decs table
+
 
local precision = 0
+
function wd.sourceStr(sources)
for d, val in ipairs(decs) do
+
if not sources or (#sources == 0) then
precision = math.max(precision, math_mod._precision(val))
+
return nil
 
end
 
end
return convertprecision(precision)
+
for i, j in pairs(sources) do
 +
sources[i] = mw.getCurrentFrame():extensionTag( "ref", j)
 +
end
 +
return table.concat(sources, '<sup class="reference cite_virgule">,</sup>')
 
end
 
end
  
local function dec2dms_d(dec)
+
function wd.formatStatement( statement, args )
local degrees = math_mod._round( dec, 0 )
+
if not args then
return degrees
+
args = {}
end
+
end
 +
if not statement.type or statement.type ~= 'statement' then
 +
return tools.formatError( 'unknown-claim-type' )
 +
end
 +
local prop = statement.mainsnak.property
  
local function dec2dms_dm(dec)
+
local str
dec = math_mod._round( dec * 60, 0 )
 
local minutes = dec % 60
 
dec = math.floor( (dec - minutes) / 60 )
 
local degrees = dec % 360
 
return degrees, minutes
 
end
 
  
local function dec2dms_dms(dec)
+
-- partie principale
dec = math_mod._round( dec * 60 * 60, 0 )
+
if args.showonlyqualifier and (args.showonlyqualifier ~= '') then
local seconds = dec % 60
+
str = wd.getFormattedQualifiers(statement, args.showonlyqualifier, args)
dec = math.floor( (dec - seconds) / 60 )
+
if not str then
local minutes = dec % 60
+
return nil
dec = math.floor( (dec - minutes) / 60 )
+
end
local degrees = dec % 360
+
elseif args.statementformat and (type(args.statementformat) == 'function') then
return degrees, minutes, seconds
+
str = args.statementformat(statement, args)
end
+
else
 +
str = wd.formatSnak( statement.mainsnak, args )
 +
end
  
function p._dec2dms(dec, coordtype, precision, globe) -- coordtype: latitude or longitude
+
-- ajouts divers
local degrees, minutes, seconds
+
if args.showlang == true then
+
str = (showlang(statement) or '') .. '&#32;' .. str
-- vérification du globe
+
end
if not ( globe and globedata[ globe ] ) then
+
if args.showqualifiers then
globe = 'earth'
+
str = wd.showQualifiers(str, statement, args)
 
end
 
end
+
 
-- precision
+
if args.showdate then -- when "showdate and chronosort are both set, date retrieval is performed twice
if not precision or precision == '' then
+
local period = wd.getFormattedDate(statement, args, "-") -- 3 arguments indicate the we should not use additional qualifiers, alrady added by wd.formatStatement
precision = determinedmsprec({dec})
+
if period then
 +
str = str .. " <small>(" .. period ..")</small>"
 
end
 
end
if precision ~= 'd' and precision ~= 'dm' and precision ~= 'dms' then
 
return makeerror({sortkey = 'C'})
 
 
end
 
end
local dec = tonumber(dec)
+
 
+
if args.showsource then
-- direction
+
local sources = wd.getReferences(statement)
local direction
+
if sources then
if coordtype == 'latitude' then  
+
local source = wd.sourceStr(sources)
if dec < 0 then
+
str = str .. (source or "")
direction = 'S'
 
else
 
direction = 'N'
 
end
 
elseif coordtype == 'longitude' then
 
if dec < 0 or globedata[globe].defaultdisplay == 'dec west' then
 
direction = 'W'
 
else
 
direction = 'E'
 
 
end
 
end
 
end
 
end
+
if statement.qualifiers then
-- conversion
+
str = wd.addStandardQualifs(str, statement)
dec = math.abs(dec) -- les coordonnées en dms sont toujours positives
+
end
if precision == 'dms' then  
+
return str
degrees, minutes, seconds = dec2dms_dms(dec)
+
end
elseif precision == 'dm' then
+
 
degrees, minutes = dec2dms_dm(dec)
+
function wd.formatSnak( snak, params )
 +
if not params then params = {} end -- pour faciliter l'appel depuis d'autres modules
 +
if snak.snaktype == 'somevalue' then
 +
return unknownvalue(snak, params.unknownlabel)
 +
elseif snak.snaktype == 'novalue' then
 +
return novalue(params.novaluelabel)
 +
elseif snak.snaktype == 'value' then
 +
return wd.getDatavalue( snak, params)
 
else
 
else
degrees = dec2dms_d(dec)
+
return tools.formatError( 'unknown-snak-type' )
 
end
 
end
return builddmsdimension(degrees, minutes, seconds, direction)
 
 
end
 
end
  
function p.dec2dms(frame) -- legacy function somewhat cumbersome syntax
+
function wd.getDescription(entity, lang)
args = frame.args
+
lang = lang or defaultlang
local dec = args[1]
+
 
if not tonumber(dec) then
+
local description
makeerror({message = i18n.invalidFormat, sortkey = 'A'})
+
if lang == defaultlang then
return showerrors()
+
return mw.wikibase.descriptionl(qid)
 
end
 
end
local dirpositive = string.lower(args[2] or '')
+
if not entity.descriptions then
local dirnegative = string.lower(args[3] or '')
+
return translate('no description')
local precision = string.lower(args[4] or '')
 
local displayformat, coordtype
 
 
if dirpositive == 'n' or dirpositive == 'nord' then
 
coordtype = 'latitude'
 
else
 
coordtype = 'longitude'
 
 
end
 
end
if dirpositive == 'nord' or dirpositive == 'est' or dirnegative == 'ouest' or dirnegative == 'sud' then
+
local descriptions = entity.descriptions
displayformat = 'dms long'
+
if not descriptions then
 +
return nil
 
end
 
end
local coordobject = p._dec2dms(dec, coordtype, precision)
+
if descriptions[lang] then
if coordobject then
+
return descriptions[delang].value
return p.displaydmsdimension(coordobject, displayformat) .. showerrors()
 
else
 
return showerrors()
 
 
end
 
end
 +
return entity.id
 
end
 
end
  
 
+
function wd.addLinkback(str, id, property)
function p._dms2dec(dmsobject) -- transforme une table degré minute secondes en nombre décimal
+
if not id then
local direction, degrees, minutes, seconds = dmsobject.direction, dmsobject.degrees, dmsobject.minutes, dmsobject.seconds
+
id = tools.getEntity()
local factor = 0
+
end
local precision = 0
+
if not id then
if not minutes then minutes = 0 end
+
return str
if not seconds then seconds = 0 end
+
end
+
if type(property) == 'table' then
if direction == "N" or direction == "E" then
+
property = property[1]
factor = 1
 
elseif direction == "W" or direction == "S" then
 
factor = -1
 
elseif not direction then
 
makeerror({message = i18n.noCardinalDirection, sortkey = 'A'})
 
return nil
 
else
 
makeerror({message = i18n.invalidDirection, sortkey = 'A'})
 
return nil
 
 
end
 
end
+
if type(id) == 'table' then
if dmsobject.seconds then -- vérifie la précision des données initiales
+
id = id.id
precision = 5 + math.max( math_mod._precision(tostring(seconds), 0 ) ) -- passage par des strings assez tarabiscoté ?
 
elseif dmsobject.minutes then
 
precision = 3 + math.max( math_mod._precision(tostring(minutes), 0 ) )
 
else
 
precision = math.max( math_mod._precision(tostring(degrees), 0 ) )
 
 
end
 
end
 
 
local decimal = factor * (degrees+(minutes+seconds/60)/60)
+
local class = ''
return math_mod._round(decimal, precision)
+
if property then
end
+
class = 'wd_' .. string.lower(property)
 
 
function p.dms2dec(frame) -- legacy function, somewhat bizarre syntax
 
local args = frame.args
 
if tonumber(args[1]) then  
 
return args[1] -- coordonnées déjà en décimal
 
elseif not args[2] then
 
local dmsobject = p._parsedmsstring(args[1])
 
if dmsobject then
 
return p._dms2dec(dmsobject) -- coordonnées sous la fore 23/22/N
 
else
 
return showerrors()
 
end
 
else
 
return p._dms2dec({direction = args[1], degrees = tonumber(args[2]), minutes = tonumber(args[3]), seconds = tonumber(args[4])})
 
 
end
 
end
 +
local icon = '[[File:Blue pencil.svg|%s|10px|baseline|class=noviewer|link=%s]]'
 +
local title = translate('see-wikidata-value')
 +
local url = mw.uri.fullUrl('d:' .. id, 'uselang=fr')
 +
url.fragment = property -- ajoute une #ancre si paramètre "property" défini
 +
url = tostring(url)
 +
local v = mw.html.create('span')
 +
:addClass(class)
 +
:wikitext(str)
 +
:tag('span')
 +
:addClass('noprint wikidata-linkback')
 +
:css('padding-left', '0.5em')
 +
:wikitext(icon:format(title, url))
 +
:allDone()
 +
return tostring(v)
 
end
 
end
  
-- Wikidata
+
function wd.addRefAnchor(str, id)
local function convertwikidataprecision(precision) -- converts a decima like "0.1" into "dm"
+
--[[
if precision < 0.016 then
+
Insère une ancre pour une référence générée à partir d'un élément wd.
return 'dms'
+
L'id Wikidata sert d'identifiant à l'ancre, à utiliser dans les modèles type "harvsp"
elseif precision < 1 then
+
--]]
return 'dm'
+
return tostring(
else
+
mw.html.create('span')
return 'd'
+
:attr('id', id)
end
+
:attr('class', "ouvrage")
 +
:wikitext(str)
 +
)
 
end
 
end
  
local function wikidatacoords(query)
+
function wd.formatStatements( args )--Format statement and concat them cleanly
query = query or {property = 'p625'}
+
if args.value == '-' then
query.formatting = 'raw'
+
return nil
local wd = require('Module:Wikidata')
 
local claim = wd.getClaims(query)
 
if claim and claim[1] then -- redundant but more robust in case of a change in the code of Module:Wikidata
 
local coords = wd.formatSnak(claim[1].mainsnak) -- todo: check for special values
 
-- Wikidata does not handle correctly +West longitudes
 
if globedata[ coords.globe ] and globedata[ coords.globe ].defaultdisplay == 'dec west' then
 
coords.longitude = math.abs( coords.longitude )
 
end
 
return coords.latitude, coords.longitude, coords.globe or 'earth', convertwikidataprecision(coords.precision or .001)
 
 
end
 
end
return nil
+
local valueexpl = translate("activate-query")
end
+
--If a value is already set, use it
 
+
if args.value and (args.value ~= '') and (args.value ~= valueexpl) then
 
+
return args.value
local function wikidatacat(globe)
 
--catbase= Article géolocalisé sur Terre
 
local entitycat = mw.wikibase.getEntity()
 
 
local basecat = 'Article géolocalisé'
 
local finalcat = {}
 
--BADGES
 
if entitycat then
 
--BADGES
 
  for i, badgeId in ipairs( entitycat.sitelinks['frwiki'].badges ) do
 
if badgeId == 'Q17437796'  then
 
basecat=string.gsub(basecat, "Article géolocalisé", "Article de qualité géolocalisé")
 
end
 
if badgeId == 'Q17437798'  then
 
basecat=string.gsub(basecat, "Article géolocalisé", "Bon article géolocalisé")
 
end
 
end
 
 
end
 
end
 
+
-- if args.expl: return something only one if explicitly required in Wikitext
if globe == 'earth'  then
+
if args.expl and (args.value ~= valueexpl) then
if entitycat and entitycat.claims  then
+
return nil
local country=entitycat.claims['P17']
 
if not country then
 
--pas pays à récupérer
 
basecat=basecat .. ' sur Terre'
 
table.insert(finalcat,basecat)
 
else
 
--parfois plusieurs pays
 
for i, paysId in ipairs( country ) do
 
--on fait confiance au label wikidata
 
local gdataone,qid
 
 
if paysId.mainsnak.snaktype == 'value' then
 
qid=paysId.mainsnak.datavalue.value['numeric-id']
 
gdataone=gdata.data[qid]
 
else
 
--Bir Tawil n'a pas de pays connu
 
qid='?'
 
end
 
if gdataone ~= nil then
 
local prep=genre[gdataone['genre']]['en'] or 'en '
 
local thecat=basecat .. ' '..prep ..mw.wikibase.label( 'Q'.. qid)
 
if mw.title.new('category:'..thecat).exists then
 
table.insert(finalcat,thecat)
 
else
 
--Dommage!
 
mw.log(thecat .. ' à créer')
 
end
 
else
 
--pas d'id?
 
mw.log(qid .. ' à paramétrer')
 
end
 
end
 
if #finalcat == 0 then
 
--pas pays à récupérer
 
basecat=basecat .. ' sur Terre'
 
table.insert(finalcat,basecat)
 
end
 
end
 
else
 
--pas wikidata
 
basecat=basecat .. ' sur Terre'
 
table.insert(finalcat,basecat)
 
end
 
elseif globedata[globe] then
 
basecat=basecat .. ' ' .. globedata[globe].trackingcat
 
table.insert(finalcat,basecat)
 
else
 
basecat=basecat .. ' extraterrestre'
 
table.insert(finalcat,basecat)
 
 
end
 
end
return finalcat
+
args.entity = tools.getEntity(args.entity)
end
 
 
 
-- main function for displaying coordinates
 
function p._coord(args)
 
 
 
-- I declare variable
 
local displayformat = args.format -- string: one of: 'dms', 'dms long', 'dec', 'dec east' and 'dec west'
 
local displayplace = string.lower(args.display or 'inline') --string: one of 'inline', 'title' or 'inline,title'
 
local objectname = (args.name ~= '') and args.name -- string: name of the title displayed in geohack
 
local notes = (' ' and args.notes) or '' -- string: notes to de displayed after coordinates
 
local wikidata = args.wikidata -- string: set to "true" if needed
 
local wikidataquery = args.wikidataquery -- table: see [[Module:Wikidata]] see function wikidatacoords
 
local dmslatitude, dmslongitude -- table (when created)
 
local extraparams = args.extraparams or '' -- string (legacy, corresponds to geohackparams)
 
local trackingstring = '' -- tracking cats except error cats (already in errorstring)
 
local rawlat, rawlong = args.latitude, args.longitude
 
if rawlat == '' then rawlat = nil end
 
if rawlong == '' then rawlong = nil end
 
local globe = string.lower( args.globe or extraparams:match('globe:(%a+)') or '' ) -- string: see the globedata table for accepted values
 
local latitude, longitude, precision, dmslatitude, dmslongitude -- latitude and longitude in decimal / dmslatitude and dmslongitude: tables withdms coords
 
local maplink = true -- use maplink whenever it is possible
 
 
-- II extract coordinates from Wikitext
 
if (rawlat or rawlong) then
 
if (not rawlat) or (not rawlong) then -- if latitude is provided so should be longitude
 
makeerror({message = i18n.coordMissing, sortkey = 'A'})
 
return showerrors()
 
end
 
latitude = parsedec(rawlat, 'latitude', globe)
 
  
if latitude then -- if latitude is decimal
+
if args.grouped and args.grouped ~= '' then
longitude = parsedec(rawlong, 'longitude', globe) -- so should be longitude
+
args.grouped = false
precision = determinedmsprec({latitude, longitude}) -- before conversion from string to number for trailing zeros
+
return wd.groupedStatements(args)
if not latitude or not longitude then
 
if errorstring == '' then
 
makeerror({message = i18n.invalidFormat, sortkey = 'A'})
 
end
 
return showerrors()
 
end
 
dmslatitude, dmslongitude = p._dec2dms(latitude, 'latitude', precision), p._dec2dms(longitude, 'longitude', precision, globe)
 
latitude, longitude = tonumber(latitude), tonumber(longitude)
 
else -- if latitude is not decimal try to parse it as a dms string
 
dmslatitude, dmslongitude = p._parsedmsstring(args.latitude, 'latitude'), p._parsedmsstring(args.longitude, 'longitude')
 
if not dmslatitude or not dmslongitude then
 
return showerrors()
 
end
 
latitude, longitude = p._dms2dec(dmslatitude), p._dms2dec(dmslongitude)
 
end
 
 
end
 
end
 
+
local valuetable = args.valuetable -- dans le cas où les valeurs sont déjà formtées
-- III extract coordinate data from Wikidata and compare them to local data
+
local props -- les prorpriétés réellement utilisées (dans certainse cas, ce ne sont pas toutes celles de ags.property
local wikidatalatitude, wikidatalongitude, wikidataglobe, wikidataprecision
+
if not valuetable then -- cas le plus courant
if wikidata == 'true' then
+
valuetable, props = wd.stringTable(args)
wikidatalatitude, wikidatalongitude, wikidataglobe, wikidataprecision = wikidatacoords(wikidataquery)
 
 
if wikidatalatitude and latitude and longitude then
 
local maxdistance = tonumber(args.maxdistance) or wikidatathreshold
 
if p._distance({latitude = latitude, longitude= longitude}, {latitude = wikidatalatitude, longitude= wikidatalongitude}, wikidataglobe) <  maxdistance then
 
trackingstring = trackingstring .. makecat(i18n.sameaswikidata)
 
else
 
trackingstring = trackingstring .. makecat(i18n.notaswikidata)
 
end
 
end
 
if wikidatalatitude and not latitude then
 
latitude, longitude, globe, precision = wikidatalatitude, wikidatalongitude, wikidataglobe, wikidataprecision
 
dmslatitude, dmslongitude = p._dec2dms(latitude, 'latitude', precision), p._dec2dms(longitude, 'longitude', precision, globe)
 
trackingstring = trackingstring .. makecat(i18n.throughwikidata)
 
end
 
 
if latitude and not wikidatalatitude then
 
if mw.title.getCurrentTitle().namespace == 0 then
 
trackingstring = trackingstring .. makecat(i18n.nowikidata)
 
end
 
end
 
 
end
 
end
  
 
+
local str = wd.tableToText(valuetable, args)
-- exit if stil no latitude or no longitude
+
if not str then
if not latitude and not longitude then
+
return nil
return nil -- ne rien ajouter ici pour que l'appel à cette fonction retourne bien nil en l'absence de données
 
 
end
 
end
 
+
if not props then
-- IV best guesses for missing parameters
+
props = tools.splitStr(args.property)[1]
 
--- globe
 
if globe == '' then
 
globe = 'earth'
 
 
end
 
end
if not globedata[globe] then
+
if args.ucfirst ~= '-' then
makeerror({message = i18n.invalidGlobe .. globe})
+
str = modules.linguistic.ucfirst(str)
globe = 'earth'
 
 
end
 
end
if globe ~= 'earth' then
+
 
extraparams = extraparams .. '_globe:' .. globe -- pas de problème si le globe est en double
+
if args.addcat and (args.addcat ~= '-') then
maplink = false
+
str = str .. wd.addtrackingcat(props)
 
end
 
end
+
if args.linkback and (args.linkback ~= '-') then
--- diplayformat
+
str = wd.addLinkback(str, args.entity, props)
if not displayformat or displayformat == '' then
 
displayformat = globedata[globe].defaultdisplay
 
 
end
 
end
 +
return str
 +
end
 +
 +
function wd.showQualifier( args )
 +
local qualifs = args.qualifiers or args.qualifier
 
 
-- displayinline/displaytitle
+
if not qualifs then
local displayinline =  string.find(displayplace, 'inline')
+
return tools.formatError( 'property-param-not-provided' )
local displaytitle = string.find(displayplace, 'title')
 
if not displayinline and not displaytitle then
 
displayinline = true
 
if displayplace ~= '' then
 
makeerror({sortkey = 'C'}) --error if display not empty, but not not a major error, continue
 
end
 
 
end
 
end
if displaytitle and mw.title.getCurrentTitle().namespace == 0 then
+
if type(qualifs) == 'string' then
--local cattoappend=globedata[globe].trackingcat
+
qualifs = tools.splitStr(qualifs)
--Récupération des badges
 
local cats=wikidatacat(globe)
 
for i, cat in ipairs( cats ) do
 
trackingstring = trackingstring .. makecat(cat)
 
end
 
 
 
end
 
end
 
-- V geodata
 
local geodata = ''
 
if latitude and longitude then
 
local latstring, longstring = tostring(latitude), tostring(longitude)
 
local primary = ''
 
  
local frame = mw.getCurrentFrame()
+
local claims = wd.getClaims(args)
local geodataparams = {[1] = latstring, [2] = longstring, [3] = extraparams }
+
if not claims then
if displaytitle then
+
return nil
geodataparams[4] = 'primary'
 
end
 
if objectname then
 
geodataparams.name = objectname
 
end
 
geodata = frame:callParserFunction('#coordinates', geodataparams )
 
if string.find(geodata, 'error') then -- the only error that has not been caught yet is primary key
 
geodata = ''
 
makeerror({sortkey='D'})
 
end
 
 
end
 
end
-- VI final output
+
local str = ''
local mainstring = ''
+
for i, j in pairs(claims) do
if maplink then
+
local new = wd.getFormattedQualifiers(j, qualifs, args) or ''
mainstring = buildMaplinkHTML(latitude, longitude, dmslatitude, dmslongitude, globe, displayformat, displayinline, displaytitle, objectname,extraparams )
+
str = str .. new
else
 
mainstring = buildHTML(latitude, longitude, dmslatitude, dmslongitude, globe, displayformat, displayinline, displaytitle, objectname,extraparams )
 
 
end
 
end
+
return str
return mainstring .. notes .. trackingstring .. geodata .. showerrors()
 
 
end
 
end
  
function p.coord(frame) -- parrses the strange parameters of Template:Coord before sending them to p.coord
+
function wd.formatAndCat(args)
local args = frame.args
+
if not args then
local numericargs = {}
+
return nil
for i, j in ipairs(args) do
 
args[i] = mw.text.trim(j)
 
if type(i) == 'number' and args[i] ~= '' then
 
table.insert(numericargs, args[i])
 
end
 
 
end
 
end
 +
args.linkback = true
 +
args.addcat = true
 +
if args.value then -- do not ignore linkback and addcat, as formatStatements do
 +
local val = args.value .. wd.addtrackingcat(args.property)
 +
val = wd.addLinkback(val, args.entity, args.property)
 +
return val
 +
end
 +
return wd.formatStatements( args )
 +
end
  
if #numericargs %2 == 1 then -- if the number of args is odd, the last one provides formatting parameters
+
function wd.getTheDate(args)
args.extraparams = numericargs[#numericargs]
+
local claims = wd.getClaims(args)
if #numericargs == 1 and tonumber(numericargs[1]) then
+
if not claims then
makeerror({message = i18n.coordMissing, sortkey = 'A'})
+
return nil
return showerrors()
+
end
 +
local formattedvalues = {}
 +
for i, j in pairs(claims) do
 +
local v = wd.getFormattedDate(j, args)
 +
if v then
 +
table.insert(formattedvalues, v )
 
end
 
end
table.remove(numericargs)
 
 
end
 
end
for i, j in ipairs(numericargs) do
+
local val = modules.linguistic.conj(formattedvalues)
if i <= (#numericargs / 2) then
+
if not val then
if not args.latitude then
+
return nil
args.latitude = j
 
else
 
args.latitude = args.latitude .. '/' .. j
 
end
 
else
 
if not args.longitude then
 
args.longitude = j
 
else
 
args.longitude = args.longitude .. '/' .. j
 
end
 
end
 
 
end
 
end
 
+
if args.addcat == true then
if string.find(args.latitude or '', 'E') or string.find(args.latitude or '', 'W') then
+
val = val .. wd.addtrackingcat(args.property)
args.latitude, args.longitude = args.longitude, args.latitude
 
 
end
 
end
return p._coord(args)
+
val = wd.addLinkback(val, args.entity, args.property)
 +
return val
 
end
 
end
  
function p.Coord(frame)
+
 
return p.coord(frame)
+
-- Complex functions using several items
 +
local function getids(query)
 +
query.excludespecial = true
 +
query.displayformat = 'raw'
 +
return wd.stringTable(query)
 
end
 
end
  
function p.latitude(frame) -- helper function pour infobox, à déprécier
+
 
local args = frame.args
+
function wd.Dump(entity)
local latitude  = frame.args[1]
+
entity = tools.getEntity(entity)
if latitude and mw.text.trim(latitude) ~= '' then
+
if not entity then
return latitude
+
return tools.formatError("entity-param-not-provided")
elseif frame.args['wikidata'] == 'true' then
 
local lat, long = wikidatacoords()
 
return lat
 
 
end
 
end
 +
return "<pre>"..mw.dumpObject(entity).."</pre>"
 
end
 
end
function p.longitude(frame) -- helper function pour infobox, à déprécier
+
 
local args = frame.args
+
function wd.groupedStatements(args, type)
local longitude = frame.args[1]
+
-- regroupe les affirmations ayant la même valeur en mainsnak, mais des qualificatifs différents
if longitude and mw.text.trim(longitude) ~= '' then
+
-- (seulement pour les propriétés de type élément)
return longitude
+
 
elseif frame.args['wikidata'] == 'true' then
+
local claims = wd.getClaims(args)
local lat, long = wikidatacoords()
+
if not claims then
return long
+
return nil
 +
end
 +
local groupedClaims = {}
 +
 
 +
-- regroupe les affirmations par valeur de mainsnak
 +
local function addClaim(claim)
 +
local id = tools.getMainId(claim)
 +
for i, j in pairs(groupedClaims) do
 +
if (j.id == id) then
 +
table.insert(groupedClaims[i].claims, claim)
 +
return
 +
end
 +
end
 +
table.insert(groupedClaims, {id = id, claims = {claim}})
 
end
 
end
 +
for i, claim in pairs(claims) do
 +
addClaim(claim)
 +
end
 +
 +
local stringTable = {}
 +
 +
-- instructions ad hoc pour les paramètres concernant la mise en forme d'une déclaration individuelle
 +
local funs = {
 +
{param = "showqualifiers", fun = function(str, claims)
 +
local qualifs = {}
 +
for i, claim in pairs(claims) do
 +
local news = wd.getFormattedQualifiers(claim, args.showqualifiers, args)
 +
if news then
 +
table.insert(qualifs, news)
 +
end
 +
end
 +
local qualifstr = modules.linguistic.conj(qualifs, " ; ") -- point virgule pour séparer les années
 +
if not qualifstr then
 +
return str
 +
end
 +
return str .. " " .. modules.linguistic.inparentheses(qualifstr)
 +
end
 +
},
 +
{param = "showdate", fun = function(str, claims)
 +
-- toutes les dates sont regroupées à l'intérieur des mêmes parenthèses ex "médaille d'or (1922, 1924)"
 +
local dates = {}
 +
for i, statement in pairs(claims) do
 +
local s = wd.getFormattedDate(statement, args, true) -- l'option useallqualifiers ne doit pas être désactivée dans ce cas
 +
if statement then table.insert(dates, s) end
 +
end
 +
local datestr = modules.linguistic.conj(dates)
 +
if not datestr then
 +
return str
 +
end
 +
return str .. "<small>" .. modules.linguistic.inparentheses(datestr) .. "</small>"
 +
end
 +
},
 +
{param = "showsource", fun = function(str, claims)
 +
-- les sources sont toutes affichées au même endroit, à la fin
 +
-- si deux affirmations ont la même source, on ne l'affiche qu'une fois
 +
local sources = {}
 +
 +
local function dupeRef(old, new)
 +
for i, j in pairs(old) do
 +
if j == new then
 +
return true
 +
end
 +
end
 +
end
 +
for i, claim in pairs(claims) do
 +
local refs = wd.getReferences(claim)
 +
if refs then
 +
for i, j in pairs(refs) do
 +
if not dupeRef(sources, j) then
 +
table.insert(sources, j)
 +
end
 +
end
 +
end
 +
end
 +
return str .. (wd.sourceStr(sources) or "")
 +
end
 +
}
 +
}
 +
 +
for i, group in pairs(groupedClaims) do -- bricolage pour utiliser les arguments de formatStatements
 +
local str = wd.formatEntity(group.id, args)
 +
for i, fun in pairs(funs) do
 +
if args[fun.param] then
 +
str = fun.fun(str, group.claims, args)
 +
end
 +
end
 +
table.insert(stringTable, str)
 +
end
 +
 +
args.valuetable = stringTable
 +
return wd.formatStatements(args)
 
end
 
end
  
 
+
return wd
return p
 

Version actuelle datée du 28 décembre 2020 à 11:45

La documentation pour ce module peut être créée à Module:Wikidata/doc

--script that retrieves basic data stored in Wikidata, for the datamodel, see https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua

local wd = {}

local modules = { }
local modulesNames = {
	reference = 'Module:Wikidata/Références',
	linguistic = 'Module:Linguistique',
	formatDate = 'Module:Date complexe',
	formatNum = 'Module:Conversion',
	langmodule = 'Module:Langue',
	cite = 'Module:Biblio',
	getData = 'Module:Wikidata/Récup',
	entities = 'Module:Wikidata/Formatage entité',
	tools = 'Module:Wikidata/Outils',
	globes = 'Module:Wikidata/Globes',
	langcodes = 'Module:Dictionnaire Wikidata/Codes langue', -- gros et rarement utilisé
	weblink = 'Module:Weblink'
}

local function loadModule( t, key )
	if modulesNames[key] then
		local m = require( modulesNames[key] )
		t[key] = m
		return m
	end
end
setmetatable( modules, { __index = loadModule } )

local tools = require 'Module:Wikidata/Outils'
local translate = tools.translate
local defaultlang = mw.getContentLanguage():getCode()

function wd.getLabel(entity, args)
	modules.entities.getLabel(entity)
end

function wd.formatEntity(entity, args)
	return modules.entities.formatEntity(entity, args)
end

function wd.addtrackingcat(prop, cat) -- doit parfois être appelé par d'autres modules
	if type(prop) == 'table' then
		prop = prop[1] -- devrait logiquement toutes les ajouter
	end
	if not prop and not cat then
		return error("no property provided")
	end
	if not cat then
		cat = translate('trackingcat', prop or 'P??')
	end
	return tools.addcat(cat )
end

local function removeblanks(args)
	for i, j in pairs(args) do
		if j == '' then args[i] = nil end
	end
	return args
end

local function unknownvalue(snak, label)
	local str = label

	if type(str) == "function" then
		str = str(snak)
	end

	if (not str) then
		if snak.datatype == 'time' then
			str = translate('sometime')
		else
			str = translate('somevalue')
		end
	end

	if type(str) ~= "string" then
		return tools.formatError(snak.datatype)
	end
	return str
end

local function novalue(displayformat)
	if not displayformat then
		return translate('novalue')
	end
	if type(displayformat) == 'string' then
		return displayformat
	end
	return tools.formatError()
end

local function getlangcode(entityid)
	return modules.langcodes[tonumber(entityid:sub(2))]
end

local  function showlang(statement) -- retourne le code langue entre paranthèse avant la valeur (par exemple pour les biblios et liens externes)
	local mainsnak = statement.mainsnak
	if mainsnak.snaktype ~= 'value' then
		return nil
	end
	local langlist = {}
	if mainsnak.datavalue.type == 'monolingualtext' then
		langlist = {mainsnak.datavalue.value.language}
	elseif (not statement.qualifiers) or (not statement.qualifiers.P407) then
		return
	else
		for i, j in pairs( statement.qualifiers.P407 ) do
			if  j.snaktype == 'value' then
				local langentity = tools.getId(j)
				local langcode =  getlangcode(langentity)
				table.insert(langlist, langcode)
			end
		end
	end
	if (#langlist > 1) or (#langlist == 1 and langlist[1] ~= defaultlang) then -- si c'est en français, pas besoin de le dire
		return modules.langmodule.indicationMultilingue(langlist)
	end
end

local function formattable(statements, params) -- transform a table of claims into a table of formatted values
	for i, j in pairs(statements) do
		j = wd.formatStatement(j, params)
	end
	return statements
end

function wd.tableToText(values, params) -- takes a list of already formatted values and make them a text
	if not values then
		return nil
	end

	-- filters out nil values to avoid error in subsequent table.concat
	local filteredValues = {}
	for i, v in ipairs(values) do
		if v ~= nil then
			table.insert(filteredValues, v)
		end
	end

	return modules.linguistic.quickconj( filteredValues, params.conjtype)--modules.linguistic.conj( values, params.lang, params.conjtype )
end


function wd.addStandardQualifs(str, statement)
	if (not statement) or (not statement.qualifiers) then
		return str
	end
	if not str then
		return tools.formatError("adding qualifs to a nil str !")-- il y a un problème
	end
	if statement.qualifiers.P1480 then
		for i, j in pairs(statement.qualifiers.P1480) do
			local v = tools.getId(j)
			if (v == "Q21818619") then
				str = str .. " (ou environs)"
			elseif (v == "Q18122778") or (v == "Q18912752") then
				str = str.. " (?)"
			elseif (v == "Q5727902") then -- traité séparément, car plus complexe séparément
			end			
		end
	end
	return str
end

function wd.rangeobject(begin, ending, params)
	--[[
		objet comportant un timestamp pour le classement chronologique et deux dateobject (begin et ending)
	]]-- 
	local timestamp
	if begin then
		timestamp = begin.timestamp
	else
		timestamp = ending.timestamp
	end
	return {begin = begin, ending = ending, timestamp = timestamp, type = 'rangeobject'}
end

function wd.dateobject(orig, params)
	--[[ transforme un snak en un nouvel objet utilisable par Module:Date complexe
		{type = 'dateobject', timestamp = str, era = '+' ou '-', year = number, month = number, day = number, calendar = calendar}
	]]-- 
	if not params then
		params = {}
	end
	
	local newobj = modules.formatDate.splitDate(orig.time, orig.calendar)
	
	newobj.precision = params.precision or orig.precision
	newobj.type = 'dateobject'
	return newobj
end

function wd.objecttotext(obj, params)
	if obj.type == 'dateobject' then
		return modules.formatDate.simplestring(obj, params)
	elseif obj.type == 'rangeobject' then
		return modules.formatDate.daterange(obj.begin, obj.ending, params)
	end
end

local function getDatefromQualif(statement, qualif)
	if (not statement) or (not statement.qualifiers) or not (statement.qualifiers[qualif]) then
		return nil
	end
	local v = statement.qualifiers[qualif][1]
	if v.snaktype ~= 'value' then -- que faire dans ce cas ?
		return nil
	end
	return wd.dateobject(v.datavalue.value)
end

function wd.getDate(statement)
	local period = getDatefromQualif(statement, 'P585') -- retourne un dateobject
	if period then
		return period
	end
	local begin, ending = getDatefromQualif(statement, 'P580'),  getDatefromQualif(statement, 'P582')
	if begin or ending then
		return wd.rangeobject(begin, ending) -- retourne un rangeobject fait de deux dateobject
	end
end
function wd.getFormattedDate(statement, params, useallqualifiers)
	if not statement then
		return nil
	end
	local str

	local fuzzy = modules.getData.hasqualifier(statement, {"P1480"}, {"Q5727902"})
	if fuzzy then
		fuzzy = true
	end

	--cherche la date avec les qualifs P580/P582
	local datetable = wd.getDate(statement)
	if datetable then
		str = wd.objecttotext(datetable, params)
	end
	
	-- puis limite intérieur / supérieur
	if not str then
		local start, ending = getDatefromQualif(statement, 'P1319'), getDatefromQualif(statement, 'P1326')
		str = modules.formatDate.between(start, ending, params)
	end

	 -- sinon, le mainsnak, pour les données de type time
	if (not str) and (statement.mainsnak.datatype == 'time') then
		local mainsnak = statement.mainsnak
		if
			(mainsnak.snaktype == 'value' and mainsnak.datavalue.value.precision > 7)
			or
			(mainsnak.snaktype == 'somevalue')
		then
		str = wd.formatSnak(mainsnak, params)
		end
	end

	-- ajouter le qualificatif "environ"
	if fuzzy then
		str = modules.formatDate.fuzzydate(str)
	end
	-- autres valeurs de qualité de l'information
	if str and (useallqualifiers ~= "-") then
		str = wd.addStandardQualifs(str, statement)
		if params.showqualifiers then
			str = wd.showQualifiers(str, statement, params)
		end
	end
	return str
end

-- Fonction qui trie des Claims de type time selon l'ordre chronologique
-- Une clé de tri nomée « dateSortKey » est ajouté à chaque claim.
-- Si des clés de tri de ce nom existent déjà, elles sont utilisées sans modification.
function wd.sortDateClaims( claims )
	for _, claim in ipairs( claims ) do
		if not claim.dateSortKey then
			local iso = wd.formatSnak( claim.mainsnak, { displayformat = 'raw' } ) 
			-- transformation en nombre (indication de la base car gsub retourne deux valeurs)
			iso = tonumber( iso:gsub( '(%d)%D', '%1' ), 10 ) or 0
			claim.dateSortKey = iso
		end
	end
	table.sort( 
		claims,
		function ( c1, c2 )
			return c1.dateSortKey < c2.dateSortKey
		end
	)
end

function wd.wikidataDate(prop, item, params)
	local claims = wd.getClaims{entity = item, property = prop}
	if not claims then
		return nil
	end
	wd.sortDateClaims( claims )
	params = params or {}
	local vals = {}
	for i, j in ipairs(claims) do
		local v = wd.getFormattedDate(j, params)
		if v then
			table.insert(vals, v)
		end
	end
	
	local str = modules.linguistic.conj(vals, params.conjtype or 'or')

	if not str then
		return
	end

	if params.addcat ~= '-' then
		str = str .. wd.addtrackingcat(prop)
	end

	if params.linkback ~= '-' then
		str = wd.addLinkback(str, item, prop)
	end
	return str
end

function wd.getReferences(statement)
	local refdata = statement.references
	if not refdata then
		return nil
	end

	local function firstsnak(prop)
		return wd.formatSnak(prop[1])
	end

	local refs = {}
	for i, ref in pairs(refdata) do
		local s
		local function hasValue(prop) -- checks that the prop is here with valid value
			if ref.snaks[prop] and ref.snaks[prop][1].snaktype == 'value' then
				return true
			end
			return false
		end		

		if ref.snaks.P248 then
			for j, source in pairs(ref.snaks.P248) do
				if source.snaktype == 'value' then
					local page, accessdate
					if hasValue('P304') then
						page = wd.formatSnak(ref.snaks.P304[1])
					end
					if hasValue('P813') then
						accessdate = wd.formatSnak(ref.snaks.P813[1])
					end
					s = modules.reference.citeitem(tools.getId(source), {['page'] = page, ['accessdate'] = accessdate})
					table.insert(refs, s)
				end
			end
	
		elseif hasValue('P854') and hasValue('P1476') then
			local url, title, accessdate, publishdate, publishlang
			url, title = wd.formatSnak(ref.snaks.P854[1], {text = "-"}), wd.formatSnak(ref.snaks.P1476[1])
			if hasValue('P813') then
				accessdate = wd.formatSnak(ref.snaks.P813[1])
			end
			-- publishdate avec P577 ? (ne semble pas vraiment correspondre) 
			if hasValue('P407') then
				local id = tools.getId(ref.snaks.P407[1])
				publishlang = getlangcode(id)
			end
			s = modules.cite.lienWeb{titre = title, url = url, langue = publishlang, ['en ligne le'] = publishdate, ['consulté le'] = accessdate}
			table.insert(refs, s)			
		elseif ref.snaks.P854 and ref.snaks.P854[1].snaktype == 'value' then
			s = wd.formatSnak(ref.snaks.P854[1], {text = "-"})
			table.insert(refs, s)
		end
	end
	if #refs > 0 then
		return refs
	end
end

function wd.getDatavalue(snak, params)
	if not params then
		params = {}
	end
	local speciallabels = params.speciallabels -- parfois on a besoin de faire une liste d'éléments pour lequel le libellé doit être changé, pas très pratique d'utiliser une fonction pour ça

	if snak.snaktype ~= 'value' then
		return nil
	end

	local datatype = snak.datatype
	local value = snak.datavalue.value
	
	local displayformat = params.displayformat
	if type(displayformat) == 'function' then
		return displayformat(snak, params)
	end

	if datatype == 'wikibase-item' then
		return modules.entities.formatEntity(tools.getId(snak), params)
	end

	if datatype == 'url' then
		return modules.weblink.makelink(value, params.text)
	end

	if datatype == 'math' then
		return mw.getCurrentFrame():extensionTag( "math", value)
	end

	if (datatype == 'string') or (datatype == 'external-id') or (datatype == 'commonsMedia') then -- toutes les données de type string sauf "math"
		if params.urlpattern then
			local urlpattern = params.urlpattern
			if type(urlpattern) == 'function' then
				urlpattern = urlpattern(value)
			end
			local url = mw.ustring.gsub(urlpattern, '$1', (value:gsub('%%', '%%%%'))):gsub(' ', '%%20')
			value = '[' .. url .. ' ' .. (params.text or value) .. ']'
		end
		return value
	end
	
	if datatype == 'time' then -- format example: +00000001809-02-12T00:00:00Z
		local precision = params.precision -- degré de précision à afficher ('day', 'month', 'year'), inférieur ou égal à value.precision
		if displayformat == 'raw' then
			return value.time
		else
			return wd.objecttotext(wd.dateobject(value, {precision = precision}), {linktopic = params.linktopic})
		end
	end

	if datatype == 'globe-coordinate' then
		-- retourne une table avec clés latitude, longitude, précision et globe à formater par un autre module (à changer ?)
		if displayformat == 'latitude' then
			return value.latitude
		elseif displayformat == 'longitude' then
			return value.longitude
		else
			local coordvalue = mw.clone( value )
			coordvalue.globe = modules.globes[value.globe] -- transforme l'ID du globe en nom anglais utilisable par geohack
			return coordvalue -- note : les coordonnées Wikidata peuvent être utilisée depuis Module:Coordinates. Faut-il aussi autoriser à appeler Module:Coordiantes ici ?
		end
	end

	if datatype == 'quantity' then -- todo : gérer les paramètre précision
		local amount, unit = value.amount, value.unit

		if unit then
			unit = unit:match('Q%d+')
		end

		local showunit = params.showunit or true		
		if showunit == '-' then
			showunit = false
		end
		local raw	
		if displayformat == "raw" then
			raw = true
		end
		return modules.formatNum.displayvalue(amount, unit,
			{targetunit = params.targetunit, raw = raw, rounding = params.rounding, showunit = showunit}
		)
	end
	if datatype == 'monolingualtext' then
		if value.language == defaultlang then
			return value.text
		else
			return modules.langmodule.langue({value.language, value.text})
		end
	end	
	return tools.formatError('unknown-datavalue-type' )

end

function wd.getClaims( args ) -- returns a table of the claims matching some conditions given in args
	return modules.getData.getClaims(args)
end


function wd.stringTable(args) -- like getClaims, but get a list of string rather than a list of snaks, for easier manipulation
	
	local claims = args.claims
	if not claims then
		claims = wd.getClaims(args)
	end
	if not claims or claims == {} then
		return nil
	end
	local props = {} -- liste des propriétés associété à chaque string pour catégorisation et linkback
	for i, j in pairs(claims) do
		claims[i] = wd.formatStatement(j, args)
		table.insert(props, j.mainsnak.property)
	end
	if args.removedupes and (args.removedupes ~= '-') then
		claims = tools.addnewvalues({}, claims) -- devrait aussi supprimer de props celles qui ne sont pas utilisées
	end
	return claims, props
end

function wd.getQualifiers(statement, qualifs, params)
	if not statement.qualifiers then
		return nil
	end
	local vals = {}
	if type(qualifs) == 'string' then
		qualifs = tools.splitStr(qualifs)
	end
	for i, j in pairs(qualifs) do
		if statement.qualifiers[j] then
			for k, l in pairs(statement.qualifiers[j]) do
				table.insert(vals, l)
			end
		end
	end
	if #vals == 0 then
		return nil
	end
	return vals
end

function wd.getFormattedQualifiers(statement, qualifs, params)
	if not params then params = {} end
	local qualiftable = wd.getQualifiers(statement, qualifs)
	if not qualiftable then
		return nil
	end
	for i, j in pairs(qualiftable) do
		qualiftable[i] = wd.formatSnak(j, params)
	end
	return modules.linguistic.conj(qualiftable, params.conjtype)
end

function wd.showQualifiers(str, statement, args) -- utilisée par formatStatement et par wikidatadate
	local qualifs =  args.showqualifiers
	if not qualifs then
		return str -- or error ?
	end
	if type(qualifs) == 'string' then
			qualifs = tools.splitStr(qualifs)
	end
	local qualifargs = args.qualifargs or {}
	-- formatage des qualificatifs = args commençant par "qualif", ou à défaut, les mêmes que pour la valeur principale
	qualifargs.displayformat = args.qualifdisplayformat or args.displayformat
	qualifargs.labelformat = args.qualiflabelformat or args.labelformat
	qualifargs.link = args.qualiflink or args.link
	qualifargs.conjtype = args.qualifconjtype
			
	local formattedqualifs = wd.getFormattedQualifiers(statement, qualifs, qualifargs)
	if formattedqualifs and str then
		str = str .. modules.linguistic.inparentheses(formattedqualifs, defaultlang)
	end
	return str
end


function wd.sourceStr(sources)
	if not sources or (#sources == 0) then
		return nil
	end
	for i, j in pairs(sources) do
		sources[i] = mw.getCurrentFrame():extensionTag( "ref", j)
	end
	return table.concat(sources, '<sup class="reference cite_virgule">,</sup>')
end

function wd.formatStatement( statement, args )
	if not args then
		args = {}
	end
	if not statement.type or statement.type ~= 'statement' then
		return tools.formatError( 'unknown-claim-type' )
	end
	local prop = statement.mainsnak.property

	local str

	-- partie principale
	if args.showonlyqualifier and (args.showonlyqualifier ~= '') then
		str = wd.getFormattedQualifiers(statement, args.showonlyqualifier, args)
		if not str then
			return nil
		end
	elseif args.statementformat and (type(args.statementformat) == 'function') then
		str = args.statementformat(statement, args)
	else 
		str = wd.formatSnak( statement.mainsnak, args )
	end

	-- ajouts divers	
	if args.showlang == true then
		str = (showlang(statement) or '') .. '&#32;' .. str
	end
	if args.showqualifiers then
		str = wd.showQualifiers(str, statement, args)
	end

	if args.showdate then -- when "showdate and chronosort are both set, date retrieval is performed twice
	local period = wd.getFormattedDate(statement, args, "-") -- 3 arguments indicate the we should not use additional qualifiers, alrady added by wd.formatStatement
	if period then
		str = str .. " <small>(" .. period ..")</small>"
	end
	end

	if args.showsource then
		local sources = wd.getReferences(statement)
		if sources then
			local source = wd.sourceStr(sources)
			str = str .. (source or "")
		end
	end
	if statement.qualifiers then
		str = wd.addStandardQualifs(str, statement)
	end
	return str
end

function wd.formatSnak( snak, params )
	if not params then params = {} end -- pour faciliter l'appel depuis d'autres modules
	if snak.snaktype == 'somevalue' then
		return unknownvalue(snak, params.unknownlabel)
	elseif snak.snaktype == 'novalue' then
		return novalue(params.novaluelabel)
	elseif snak.snaktype == 'value' then
		return wd.getDatavalue( snak, params)
	else
		return tools.formatError( 'unknown-snak-type' )
	end
end

function wd.getDescription(entity, lang)
	lang = lang or defaultlang

	local description
	if lang == defaultlang then
		return  mw.wikibase.descriptionl(qid)
	end
	if not entity.descriptions then
		return translate('no description')
	end
	local descriptions = entity.descriptions
	if not descriptions then
		return nil
	end
	if descriptions[lang] then
		return descriptions[delang].value
	end
	return entity.id
end

function wd.addLinkback(str, id, property)
	if not id then
		id = tools.getEntity()
	end
	if not id then
		return str
	end
	if type(property) == 'table' then
		property = property[1]
	end
	if type(id) == 'table' then
		id = id.id
	end
	
	local class = ''
	if property then
		class = 'wd_' .. string.lower(property)
	end
	local icon = '[[File:Blue pencil.svg|%s|10px|baseline|class=noviewer|link=%s]]'
	local title = translate('see-wikidata-value')
	local url = mw.uri.fullUrl('d:' .. id, 'uselang=fr')
	url.fragment = property -- ajoute une #ancre si paramètre "property" défini
	url = tostring(url)
	local v = mw.html.create('span')
		:addClass(class)
		:wikitext(str)
		:tag('span')
			:addClass('noprint wikidata-linkback')
			:css('padding-left', '0.5em')
			:wikitext(icon:format(title, url))
		:allDone()
	return tostring(v)
end

function wd.addRefAnchor(str, id)
--[[
	Insère une ancre pour une référence générée à partir d'un élément wd.
	L'id Wikidata sert d'identifiant à l'ancre, à utiliser dans les modèles type "harvsp"
--]]
	return tostring(
		mw.html.create('span')
			:attr('id', id)
			:attr('class', "ouvrage")
			:wikitext(str)
	)
end

function wd.formatStatements( args )--Format statement and concat them cleanly
	if args.value == '-' then
		return nil
	end
	local valueexpl = translate("activate-query")
	--If a value is already set, use it
	if args.value and (args.value ~= '') and (args.value ~= valueexpl) then
		return args.value
	end
	-- if args.expl: return something only one if explicitly required in Wikitext
	if args.expl and (args.value ~= valueexpl) then
		return nil
	end
	args.entity = tools.getEntity(args.entity)

	if args.grouped and args.grouped ~= '' then
		args.grouped = false
		return wd.groupedStatements(args)
	end
	local valuetable = args.valuetable -- dans le cas où les valeurs sont déjà formtées
	local props -- les prorpriétés réellement utilisées (dans certainse cas, ce ne sont pas toutes celles de ags.property
	if not valuetable then -- cas le plus courant
		valuetable, props = wd.stringTable(args)
	end

	local str = wd.tableToText(valuetable, args)
	if not str then
		return nil
	end
	if not props then
		props = tools.splitStr(args.property)[1]
	end
	if args.ucfirst ~= '-' then
		str = modules.linguistic.ucfirst(str)
	end

	if args.addcat and (args.addcat ~= '-') then
		str = str .. wd.addtrackingcat(props)
	end
	if args.linkback and (args.linkback ~= '-') then
		str = wd.addLinkback(str, args.entity, props)
	end
	return str
end

function wd.showQualifier( args )
	local qualifs = args.qualifiers or args.qualifier
	
	if not qualifs then
		return tools.formatError( 'property-param-not-provided' )
	end
	if type(qualifs) == 'string' then
		qualifs = tools.splitStr(qualifs)
	end

	local claims = wd.getClaims(args)
	if not claims then
		return nil
	end
	local str = ''
	for i, j in pairs(claims) do
		local new = wd.getFormattedQualifiers(j, qualifs, args) or ''
		str = str .. new
	end
	return str
end

function wd.formatAndCat(args)
	if not args then
		return nil
	end
	args.linkback = true
	args.addcat = true
	if args.value then -- do not ignore linkback and addcat, as formatStatements do
		local val = args.value .. wd.addtrackingcat(args.property)
		val = wd.addLinkback(val, args.entity, args.property)
		return val
	end 
	return wd.formatStatements( args )
end

function wd.getTheDate(args)
	local claims = wd.getClaims(args)
	if not claims then
		return nil
	end
	local formattedvalues = {}
	for i, j in pairs(claims) do
		local v = wd.getFormattedDate(j, args)
		if v then
			table.insert(formattedvalues, v )
		end
	end
	local val = modules.linguistic.conj(formattedvalues)
	if not val then
		return nil
	end
	if args.addcat == true then
		val = val .. wd.addtrackingcat(args.property)
	end
	val = wd.addLinkback(val, args.entity, args.property)
	return val
end


-- Complex functions using several items
local function getids(query)
	query.excludespecial = true
	query.displayformat = 'raw'
	return wd.stringTable(query)
end


function wd.Dump(entity)
	entity = tools.getEntity(entity)
	if not entity then
		return tools.formatError("entity-param-not-provided")
	end
	return "<pre>"..mw.dumpObject(entity).."</pre>"
end

function wd.groupedStatements(args, type)
	-- regroupe les affirmations ayant la même valeur en mainsnak, mais des qualificatifs différents
	-- (seulement pour les propriétés de type élément)

	local claims = wd.getClaims(args)
	if not claims then
		return nil
	end
	local groupedClaims = {}

	-- regroupe les affirmations par valeur de mainsnak
	local function addClaim(claim)
		local id = tools.getMainId(claim)
		for i, j in pairs(groupedClaims) do 
			if (j.id == id) then
				table.insert(groupedClaims[i].claims, claim)
				return
			end
		end
		table.insert(groupedClaims, {id = id, claims = {claim}})
	end
	for i, claim in pairs(claims) do	
		addClaim(claim)
	end

	local stringTable = {}

	-- instructions ad hoc pour les paramètres concernant la mise en forme d'une déclaration individuelle
	local funs = {
		{param = "showqualifiers", fun = function(str, claims)
			local qualifs = {}
			for i, claim in pairs(claims) do
				local news = wd.getFormattedQualifiers(claim, args.showqualifiers, args)
				if news then
					table.insert(qualifs, news)
				end
			end
			local qualifstr = modules.linguistic.conj(qualifs, " ; ") -- point virgule pour séparer les années
			if not qualifstr then
				return str
			end
			return str .. " " .. modules.linguistic.inparentheses(qualifstr)
			end
		},
		{param = "showdate", fun = function(str, claims)
			-- toutes les dates sont regroupées à l'intérieur des mêmes parenthèses ex "médaille d'or (1922, 1924)"
			local dates = {}
			for i, statement in pairs(claims) do
				local s = wd.getFormattedDate(statement, args, true) -- l'option useallqualifiers ne doit pas être désactivée dans ce cas
				if statement then table.insert(dates, s) end
			end
			local datestr = modules.linguistic.conj(dates)
			if not datestr then
				return str
			end
			return str .. "<small>" .. modules.linguistic.inparentheses(datestr) .. "</small>"
			end
		},
		{param = "showsource", fun = function(str, claims)
			-- les sources sont toutes affichées au même endroit, à la fin
			-- si deux affirmations ont la même source, on ne l'affiche qu'une fois
			local sources = {}
		
			local function dupeRef(old, new)
				for i, j in pairs(old) do
					if j == new then
						return true
					end
				end
			end
			for i, claim in pairs(claims) do
				local refs = wd.getReferences(claim)
				if refs then
					for i, j in pairs(refs) do
						if not dupeRef(sources, j) then
							table.insert(sources, j)
						end
					end
				end
			end
			return str .. (wd.sourceStr(sources) or "")
			end
		}
	}

	for i, group in pairs(groupedClaims) do -- bricolage pour utiliser les arguments de formatStatements
		local str = wd.formatEntity(group.id, args)
		for i, fun in pairs(funs) do
			if args[fun.param] then
				str = fun.fun(str, group.claims, args)
			end
		end
		table.insert(stringTable, str)
	end
				
	args.valuetable = stringTable
	return wd.formatStatements(args)
end

return wd