Diferencia entre revisiones de «Módulo:NF»

De Wikipedia, la enciclopedia libre
Contenido eliminado Contenido añadido
Sin resumen de edición
Reformulo: separo en funciones más elementales que además son reutilizables, amplío géneros válidos en Wikidata
Línea 1: Línea 1:
local getArgs = require('Módulo:Argumentos').obtenerArgumentosConValor
local toRoman = require('Módulo:Números').Romano
local p = {}
local p = {}


function error ( msg )
local function error ( msg )
return '<strong class="error">Error: ' .. msg .. '</strong>'
return '<strong class="error">Error: ' .. msg .. '</strong>'
.. '[[Categoría:Wikipedia:Artículos con problema en la plantilla NF]]'
.. '[[Categoría:Wikipedia:Artículos con problema en la plantilla NF]]'
end
end


--[[
function p.main ( frame )
@name catSexGenderIdentity
local result = frame:preprocess('{{Control de autoridades}}\n')
@global none
local ns = mw.title.getCurrentTitle().namespace
@param none
if ns ~= 0 then
@return wikitext (categories)
return result
@descr Genera las categorías relacionadas con el sexo o género de una
end
persona en función de los datos obtenidos de Wikidata según su
local wd = mw.wikibase.getEntityObject()
propiedad P21.
local args = getArgs( frame )
--]]
local categories = ''
local errors = ''


function p.catSexGenderIdentity()
--[==[ Sex/Gender ]==]--
local wd = mw.wikibase.getEntityObject()
if wd and wd:formatPropertyValues( 'P31' ).value == 'ser humano' then
-- wd.claims.P31[1].mainsnak.datavalue.value.id == 'Q5'
if wd and wd:formatPropertyValues( 'P31' ).value == 'ser humano'
--[[ wd and wd.claims.P31[1].mainsnak.datavalue.value.id == 'Q5' --]]
then
--[==[ Main categories are:
[[Categoría:Hombres]]
[[Categoría:Mujeres]]
[[Categoría:Intersexuales]]
[[Categoría:Mujeres transgénero]]
[[Categoría:Hombres transgénero]]
[[Categoría:Personas no binarias]]
[[Categoría:Personas no categorizadas por sexo]]
--]==]
--[==[ valid sex/genders located in Wikidata: ]==]--
local validsexgenders = {
local validsexgenders = {
-- -- see https://www.wikidata.org/wiki/Property:P21#P2302
['femenino'] = 'Mujeres',
['mujer cisgénero'] = 'Mujeres',
-- ['IDENTIFIER'] --[[ ['TEXT LABEL'] --]] = 'CATEGORY',
['masculino'] = 'Hombres',
['Q6581097'] --[[ ['masculino'] --]] = 'Hombres',
['hombre cisgénero'] = 'Hombres',
['Q6581072'] --[[ ['femenino'] --]] = 'Mujeres',
['intersexual'] = 'Intersexuales',
['Q1097630'] --[[ ['intersexual'] --]] = 'Intersexuales',
['mujer transgénero'] = 'Mujeres transgénero',
['Q189125'] --[[ ['transgénero'] --]] = nil,
['hombre transgénero'] = 'Hombres transgénero',
['Q1052281'] --[[ ['mujer transgénero'] --]] = 'Mujeres transgénero',
['Q2449503'] --[[ ['hombre transgénero'] --]] = 'Hombres transgénero',
['género no-binario'] = 'Personas no binarias',
['género fluido'] = 'Personas no binarias',
['Q48270'] --[[ ['género no-binario'] --]] = 'Personas no binarias',
['genderqueer'] = 'Personas no binarias',
['Q1399232'] --[[ ['fa'afafine'] --]] = 'Personas no binarias', -- third gender in Samoan culture
['Q3277905'] --[[ ['māhū'] --]] = 'Personas no binarias', -- third gender in traditional Hawaiian, Kanaka and Maohi cultures
['Q746411'] --[[ ['kathoey'] --]] = 'Personas no binarias', -- third gender in Thai culture
['Q350374'] --[[ ['fakaleiti'] --]] = 'Personas no binarias', -- third gender in Tongan culture
['Q660882'] --[[ ['hijra'] --]] = 'Personas no binarias', -- third gender of South Asian cultures
['Q44148'] --[[ ['macho'] --]] = nil, -- non-human
['Q43445'] --[[ ['hembra'] --]] = nil, -- non-human
-- 'unknown value' or 'valor desconocido'
-- 'no value' or 'sin valor'
['Q207959'] --[[ ['androginia'] --]] = nil,
['Q301702'] --[[ ['dos espíritus'] --]] = 'Personas no binarias', -- third gender in the indigenous North American cultures
['Q27679766'] --[[ ['transmasculino'] --]] = 'Hombres transgénero',
['Q27679684'] --[[ ['transfemenino'] --]] = 'Mujeres transgénero',
['Q3177577'] --[[ ['muxe'] --]] = 'Mujeres transgénero', -- third gender in Zapotec culture
['Q28873047'] --[[ ['organismo intersexual'] --]] = nil, -- non-human
['Q505371'] --[[ ['agénero'] --]] = 'Personas no binarias',
['Q12964198'] --[[ ['genderqueer'] --]] = 'Personas no binarias',
['Q18116794'] --[[ ['género fluido'] --]] = 'Personas no binarias',
['Q1289754'] --[[ ['neutro'] --]] = 'Personas no binarias',
['Q179294'] --[[ ['eunuco'] --]] = 'Hombres',
['Q7130936'] --[[ ['pangénero'] --]] = 'Personas no binarias',
['Q64017034'] --[[ ['cogenitor'] --]] = nil, -- fictional, non-human
['Q52261234'] --[[ ['sexo neutro'] --]] = 'Personas no binarias',
['Q16674976'] --[[ ['hermafroditismo'] --]] = nil, -- non-human
['Q15145779'] --[[ ['mujer cisgénero'] --]] = 'Mujeres',
['Q15145778'] --[[ ['hombre cisgénero'] --]] = 'Hombres',
}
}
local sexgenderval = wd:formatPropertyValues( 'P21' ).value
local sexgenderval = wd.claims.P21[1].mainsnak.datavalue.value.id -- wd:formatPropertyValues( 'P21' ).value
local sexgendercat = validsexgenders[ sexgenderval ] or 'Personas no categorizadas por sexo'
local sexgendercat = validsexgenders[ sexgenderval ] or 'Personas no categorizadas por sexo'
categories = categories .. '[[Categoría:' .. sexgendercat .. ']]'
return '[[Categoría:' .. sexgendercat .. ']]'
end
end
return '' -- non-human
end


--[[
--[==[ Birth date ]==]--
@name catLivingStatus
local birthdate = ''
@global require('Módulo:Roman')
local living = false
@param birthdate, deathdate, no errors
if args and args[1] and args[1] ~= '' then
@return wikitext (categories and [optionally] errors)
birthdate = mw.text.trim( args[1] )
@descr Genera las categorías relacionadas con el nacimiento y fallecimiento
de una persona, así como identifica si está viva, en función de los
datos proporcionados como parámetro o los obtenidos automáticamente
de Wikidata según sus propiedades P569 y P570.
@aux filterBirthDate, filterLiveState, filterDeathDate, getDateStruct
--]]

local function filterBirthDate( value )
return mw.ustring.match( mw.ustring.upper( value ), "MISSING" )
or mw.ustring.match( mw.ustring.upper( value ), "UNKNOWN" )
or mw.ustring.match( value, "%?" )
or mw.ustring.match( value, "año desconocido" )
or mw.ustring.match( value, "valor desconocido" )
end

local function filterLiveState( value )
return mw.ustring.match( mw.ustring.upper( value ), "LIVING" )
or mw.ustring.match( mw.ustring.upper( value ), "VIVA" )
end

local function filterDeathDate( value )
return filterLiveState( value )
or filterBirthDate( value )
end

local function getDateStruct( wd, arg, prop, filter )
local result, number, margin -- string, integer, precision-like value
local value
local ModuloRoman = require('Módulo:Roman')
local convertArabicToRoman = ModuloRoman._Numeral -- convertArabicToRoman
local convertRomanToArabic = ModuloRoman.toArabic -- convertRomanToArabic
if arg and arg ~= '' then
value = mw.text.trim( arg )
elseif wd and wd:formatPropertyValues( 'P31' ).value == 'ser humano' then
elseif wd and wd:formatPropertyValues( 'P31' ).value == 'ser humano' then
-- wd.claims.P31[1].mainsnak.datavalue.value.id == 'Q5'
-- wd.claims.P31[1].mainsnak.datavalue.value.id == 'Q5'
birthdate = wd:formatPropertyValues( 'P569' ).value
value = wd:formatPropertyValues( prop ).value
end
end


if value and value ~= '' then
local property1 = birthdate
local err, val
if property1 and property1 ~= '' then
if filter and type(filter) == 'function' then
if mw.ustring.match( mw.ustring.upper( property1 ), "MISSING" )
err, val = pcall( filter, value )
or mw.ustring.match( mw.ustring.upper( property1 ), "UNKNOWN" )
end
or mw.ustring.match( property1, "%?" )
if err and val then
or mw.ustring.match( property1, "año desconocido" )
margin = value --
or mw.ustring.match( property1, "valor desconocido" ) then
birthdate = ''
number = 0
result = '' -- not nil, it is valid but filtered
elseif mw.ustring.match( property1, "milenio" ) then
local m = mw.ustring.match( property1, "(%a+) milenio" ) -- 'el mm milenio'
elseif mw.ustring.match( value, "milenio" ) then
local m = mw.ustring.match( value, "(%a+) milenio" ) -- 'el MM milenio', roman
if m then
if m then
margin = 1000
birthdate = 'el ' .. m .. ' milenio'
number = ( convertRomanToArabic( m ) - 1 ) * margin
-- TODO: optimize
if m == 'I' or m == 'II' or m == 'III' then
result = 'el ' .. m .. ' milenio'
living = true -- supposed (as it once was)
end
else
else
m = mw.ustring.match( property1, "(%d+). milenio" ) -- 'mm. milenio'
m = mw.ustring.match( value, "(%d+). milenio" ) -- WD:'mm. milenio AED'
if m then
if m then
margin = 1000
birthdate = 'el ' .. toRoman( tonumber(m) ) .. ' milenio'
number = ( tonumber( m ) - 1 ) * margin
-- TODO: optimize
if m == 1 or m == 2 or m == 3 then
result = 'el ' .. convertArabicToRoman( m ) .. ' milenio'
living = true -- supposed (as it once was)
end
else
else
result = nil -- error
errors = error('fecha de nacimiento no válida')
birthdate = ''
end
end
end
end
elseif mw.ustring.match( property1, "siglo" ) then
elseif mw.ustring.match( value, "siglo" ) then
local dcc = math.floor( (tonumber(os.date( "%Y" )) - 1) / 100 ) + 1 -- decimal current century
local c = mw.ustring.match( value, "(%d+)%. siglo" ) -- WD:'cc. siglo AED'
local rc0 = mw.getContentLanguage():formatDate( 'xry', tostring( dcc ) .. '-1-1' ) -- roman current century
local rc1 = mw.getContentLanguage():formatDate( 'xry', tostring( dcc - 1 ) .. '-1-1' ) -- roman previous century
local rc2 = mw.getContentLanguage():formatDate( 'xry', tostring( dcc - 2 ) .. '-1-1' ) -- roman before previous century
local c = mw.ustring.match( property1, "(%d+)%. siglo" ) -- 'cc. siglo'
if c then
if c then
margin = 100
birthdate = 'el siglo ' .. toRoman( tonumber(c) )
number = ( tonumber( c ) - 1 ) * margin
-- decimal number
if ( c == dcc or c == dcc - 1 )
result = 'el siglo ' .. convertArabicToRoman( c )
or ( c == dcc - 2 and tonumber(os.date( "%y" )) < 30 )
then
living = true -- maybe
else
living = false -- sure
end
else
else
c = mw.ustring.match( property1, "siglo (%a+)" ) -- 'el siglo cc'
c = mw.ustring.match( value, "siglo (%a+)" ) -- 'el siglo CC', roman
if c then
if c then
birthdate = 'el siglo ' .. c
margin = 100
number = ( convertRomanToArabic( c ) - 1 ) * margin
-- roman number
result = 'el siglo ' .. c
if ( mw.ustring.match(c, rc0) or mw.ustring.match(c, rc1) )
or ( mw.ustring.match(c, rc2) and tonumber(os.date( "%y" )) < 30 )
then
living = true -- maybe
else
living = false -- sure
end
else
else
result = nil -- error
errors = error('fecha de nacimiento no válida')
birthdate = ''
end
end
end
end
elseif mw.ustring.match( property1, "años" )
elseif mw.ustring.match( value, "años" )
or mw.ustring.match( property1, "%d+s" ) then
or mw.ustring.match( value, "%d+s" ) then
local dcc = math.floor( (tonumber(os.date( "%Y" )) - 1) / 100 ) + 1 -- decimal current century
local d = mw.ustring.match( value, "años (%d+)" ) -- 'años yyyy'
local d = mw.ustring.match( property1, "años (%d+)" ) -- 'años yyyy'
or mw.ustring.match( value, "(%d+)s" ) -- WD:'2020s AED'
or mw.ustring.match( property1, "%d+s" ) -- '2020s'
if d then
if d then
birthdate = 'los años ' .. d
margin = 10
local c = math.floor( (d - 1) / 100 ) + 1
number = tonumber( d )
if ( c == dcc or c == dcc - 1 )
result = 'los años ' .. number
or ( c == dcc - 2 and tonumber(os.date( "%y" )) < 30 )
then
living = true -- maybe
else
living = false -- sure
end
else
else
result = nil -- error
errors = error('fecha de nacimiento no válida')
birthdate = ''
end
end
else
else
local y = mw.ustring.match( property1, "^%d+ %a+ (%d+)" ) -- 'dd mmm aaaa'
local y = mw.ustring.match( value, "^%d+ %a+ (%d+)" ) -- 'dd mmm aaaa'
or mw.ustring.match( value, "^%a+ (%d+)" ) -- 'mmm aaaa'
or mw.ustring.match( value, "^(%d+)" ) -- 'aaaa'
if y then
if y then
birthdate = y
margin = 1
number = tonumber( y )
result = number
else
else
result = nil -- error
y = mw.ustring.match( property1, "^%a+ (%d+)" ) -- 'mmm aaaa'
if y then
birthdate = y
else
y = mw.ustring.match( property1, "^(%d+)" ) -- 'aaaa'
if y then
birthdate = y
else
errors = error('fecha de nacimiento no válida')
birthdate = ''
end
end
end
if y then
if tonumber(os.date( "%Y" )) - y < 130 then
living = true -- maybe
end
end
end
end
end


if birthdate
if result
and ( mw.ustring.match( property1, "a%. C%." )
and ( mw.ustring.match( value, "a%. C%." )
or mw.ustring.match( property1, "a%.%se%.%sc%." )
or mw.ustring.match( value, "a%.%se%.%sc%." )
or mw.ustring.match( property1, "^%-" )
or mw.ustring.match( value, "^%-" )
or mw.ustring.match( property1, "AEC" )
or mw.ustring.match( value, "AEC" )
or mw.ustring.match( property1, "BCE?$" ) ) then
or mw.ustring.match( value, "BCE?$" ) ) then
living = false -- sure
number = -number
birthdate = birthdate .. ' a. C.'
result = result .. ' a. C.'
end
end
else
result = false -- empty value
end
end
return result, number, margin
end


if birthdate and birthdate ~= '' then
function p.catLivingStatus( birthdate, deathdate, noerrors )
local wd = mw.wikibase.getEntityObject()
categories = categories .. '[[Categoría:Nacidos en ' .. birthdate .. ']]'
local categories, errors = '', ''
else
-- Birth date
categories = categories .. '[[Categoría:Nacidos en año desconocido]]'
local result1, number1, margin1 = getDateStruct(wd, birthdate, 'P569', filterBirthDate)
if property1 == '' then
-- Death date
categories = categories .. '[[Categoría:Wikipedia:Artículos con plantilla NF sin fechas]]'
local result2, number2, margin2 = getDateStruct(wd, deathdate, 'P570', filterDeathDate)
-- Living status
local living
if result2 then
living = false -- sure
elseif result1 then
if number1 < 0 then
living = false -- sure
elseif number1 then
living = true -- maybe
local curYear = tonumber(os.date( "%Y" ))
local maxLive = (number1 + margin1 + 130)
if curYear > maxLive then
living = false
end
end
end
end
end
-- Categories

if result1 == nil then
--[==[ Death date ]==]--
errors = error('fecha de nacimiento no válida')
local deathdate = ''
categories = categories .. '[[Categoría:Nacidos en año desconocido]]' -- unknow because not valid
if args and args[2] and args[2] ~= '' then
elseif result1 == false then
deathdate = mw.text.trim( args[2] )
errors = errors .. '[[Categoría:Wikipedia:Artículos con plantilla NF sin fechas]]'
elseif wd and wd:formatPropertyValues( 'P31' ).value == 'ser humano' then
categories = categories .. '[[Categoría:Nacidos en año desconocido]]' -- unknow because not set
-- wd.claims.P31[1].mainsnak.datavalue.value.id == 'Q5'
elseif result1 == '' then
deathdate = wd:formatPropertyValues( 'P570' ).value
categories = categories .. '[[Categoría:Nacidos en año desconocido]]' -- known to be unknown
if deathdate == 'sin valor' then deathdate = '' end
else -- valid value
categories = categories .. '[[Categoría:Nacidos en ' .. result1 .. ']]'
end
end
if result2 == nil then

errors = error('fecha de fallecimiento no válida')
local property2 = deathdate
-- categories = categories .. '[[Categoría:Fallecidos en año desconocido]]' -- unknow because not valid
if property2 and property2 ~= '' then
living = false
elseif result2 == false then
if living then
if mw.ustring.match( mw.ustring.upper( property2 ), "LIVING" )
categories = categories .. '[[Categoría:Personas vivas]]'
or mw.ustring.match( mw.ustring.upper( property2 ), "VIVA" ) then
living = true
deathdate = ''
elseif mw.ustring.match( mw.ustring.upper( property2 ), "MISSING" )
or mw.ustring.match( mw.ustring.upper( property2 ), "UNKNOWN" )
or mw.ustring.match( property2, "%?" )
or mw.ustring.match( property2, "año desconocido" )
or mw.ustring.match( property2, "valor desconocido" ) then
deathdate = ''
elseif mw.ustring.match( property2, "milenio" ) then
local m = mw.ustring.match( property2, "(%a+) milenio" ) -- 'el mm milenio'
if m then
deathdate = 'el ' .. m .. ' milenio'
else
m = mw.ustring.match( property1, "(%d+). milenio" ) -- 'mm. milenio'
if m then
deathdate = 'el ' .. toRoman( tonumber(m) ) .. ' milenio'
else
errors = error('fecha de fallecimiento no válida')
deathdate = ''
end
end
elseif mw.ustring.match( property2, "siglo" ) then
local c = mw.ustring.match( property2, "(%d+)%. siglo" ) -- 'cc. siglo'
if c then
deathdate = 'el siglo ' .. toRoman( tonumber(c) )
else
c = mw.ustring.match( property2, "siglo (%a+)" ) -- 'el siglo cc'
if c then
deathdate = 'el siglo ' .. c
else
errors = error('fecha de fallecimiento no válida')
deathdate = ''
end
end
elseif mw.ustring.match( property2, "años" )
or mw.ustring.match( property2, "^%d+s" ) then
local d = mw.ustring.match( property2, "años (%d+)" ) -- 'años yyyy'
or mw.ustring.match( property2, "^(%d+)s" ) -- '2020s'
if d then
deathdate = 'los años ' .. d
else
errors = error('fecha de fallecimiento no válida')
deathdate = ''
end
else
else
errors = errors .. '[[Categoría:Wikipedia:Artículos con plantilla NF sin fechas]]'
local y = mw.ustring.match( property2, "^%d+ %a+ (%d+)" ) -- 'dd mmm aaaa'
end
if y then
elseif result2 == '' then
deathdate = y
if filterLiveState( margin2 ) then
else
if living == false then
y = mw.ustring.match( property2, "^%a+ (%d+)" ) -- 'mmm aaaa'
categories = categories .. '[[Categoría:Fallecidos en año desconocido]]' -- unknow because not set
if y then
errors = errors .. '[[Categoría:Wikipedia:Artículos con plantilla NF sin fechas]]'
deathdate = y
errors = errors .. '[[Categoría:Wikipedia:Artículos con problema en la plantilla NF]]'
else
y = mw.ustring.match( property2, "^(%d+)" ) -- 'aaaa'
if y then
deathdate = y
else
errors = error('fecha de fallecimiento no válida')
deathdate = ''
end
end
end
end
end

if deathdate
and ( mw.ustring.match( property2, "a%. C%." )
or mw.ustring.match( property2, "a%.%se%.%sc%." )
or mw.ustring.match( property2, "^%-" )
or mw.ustring.match( property2, "AEC$" )
or mw.ustring.match( property2, "BCE?$" ) ) then
deathdate = deathdate .. ' a. C.'
end
end

if deathdate and deathdate ~= '' then
categories = categories .. '[[Categoría:Fallecidos en ' .. deathdate .. ']]'
elseif not living then
if property2 == '' then
categories = categories .. '[[Categoría:Wikipedia:Artículos con plantilla NF sin fechas]]'
else
else
categories = categories .. '[[Categoría:Fallecidos en año desconocido]]'
categories = categories .. '[[Categoría:Fallecidos en año desconocido]]' -- known to be unknown
end
end
else -- valid value
elseif birthdate and birthdate ~= '' then
categories = categories .. '[[Categoría:Personas vivas]]'
categories = categories .. '[[Categoría:Fallecidos en ' .. result2 .. ']]'
end
end
if noerrors then
return categories
end
return categories .. errors
end


--[[
--[==[ Sort key ]==]--
@name sortKey
@global none
@param value
@return string
@descr Genera la clave de ordenación del nombre de una persona, a través de
los datos obtenidos automáticamente de Wikidata según sus diferentes
propiedades.
@aux filterBirthDate, filterLiveState, filterDeathDate, getDateStruct
--]]

function p.sortKey( value )
local wd = mw.wikibase.getEntityObject()
local sortkey = ''
local sortkey = ''
if args and args[3] and args[3] ~= '' then
if value and value ~= '' then
sortkey = args[3]
sortkey = value
elseif wd and wd:formatPropertyValues( 'P31' ).value == 'ser humano' then
elseif wd and wd:formatPropertyValues( 'P31' ).value == 'ser humano' then
-- wd.claims.P31[1].mainsnak.datavalue.value.id == 'Q5'
-- wd.claims.P31[1].mainsnak.datavalue.value.id == 'Q5'
Línea 314: Línea 311:
end
end
end
end
return sortkey
end

--[[
@main
@global require('Módulo:Argumentos')
require('Módulo:Control de autoridades')
require('Módulo:Roman')
--]]

function p.main ( frame )
local getArgs = require('Módulo:Argumentos').obtenerArgumentosConValor
local args = getArgs( frame )

-- Authority control
local authorityControl = require('Módulo:Control de autoridades').authorityControl
local result = authorityControl(frame) .. '\n' -- frame:preprocess('{{Control de autoridades}}\n')
local ns = mw.title.getCurrentTitle().namespace
if ns ~= 0 then
return result
end

-- Sex/Gender
result = result .. p.catSexGenderIdentity()

-- Living status
result = result .. p.catLivingStatus( args and args[1], args and args[2] )

-- Sort key
local sortkey = p.sortKey( args and args[3] )
if sortkey and sortkey ~= '' then
if sortkey and sortkey ~= '' then
sortkey = frame:preprocess('{{ORDENAR:' .. sortkey .. '}}\n')
result = result .. frame:preprocess('{{ORDENAR:' .. sortkey .. '}}\n')
end
end


--[==[ NF ]==]--
-- NF
result = result .. sortkey .. categories .. errors
return result
return result
end
end

Revisión del 23:34 30 jul 2020

Este módulo no tiene página de documentación[crear]
local p = {}

local function error ( msg )
	return '<strong class="error">Error: ' .. msg .. '</strong>'
		.. '[[Categoría:Wikipedia:Artículos con problema en la plantilla NF]]'
end

--[[
	@name	catSexGenderIdentity
	@global	none
	@param	none
	@return	wikitext (categories)
	@descr	Genera las categorías relacionadas con el sexo o género de una
			persona en función de los datos obtenidos de Wikidata según su
			propiedad P21.
--]]

function p.catSexGenderIdentity()
	local wd = mw.wikibase.getEntityObject()
	if	wd and wd:formatPropertyValues( 'P31' ).value == 'ser humano'
		--[[ wd and wd.claims.P31[1].mainsnak.datavalue.value.id == 'Q5' --]]
	then
		--[==[ Main categories are:
				[[Categoría:Hombres]]
				[[Categoría:Mujeres]]
				[[Categoría:Intersexuales]]
				[[Categoría:Mujeres transgénero]]
				[[Categoría:Hombres transgénero]]
				[[Categoría:Personas no binarias]]
				[[Categoría:Personas no categorizadas por sexo]]
		--]==]
		--[==[ valid sex/genders located in Wikidata: ]==]--
		local validsexgenders = {
		--	-- see https://www.wikidata.org/wiki/Property:P21#P2302
		--	['IDENTIFIER']	--[[ ['TEXT LABEL'] --]]			= 'CATEGORY',
			['Q6581097']	--[[ ['masculino'] --]]				= 'Hombres',
			['Q6581072']	--[[ ['femenino'] --]]				= 'Mujeres',
			['Q1097630']	--[[ ['intersexual'] --]]			= 'Intersexuales',
			['Q189125']		--[[ ['transgénero'] --]]			= nil,
			['Q1052281']	--[[ ['mujer transgénero'] --]]		= 'Mujeres transgénero',
			['Q2449503']	--[[ ['hombre transgénero'] --]]	= 'Hombres transgénero',
			['Q48270']		--[[ ['género no-binario'] --]]		= 'Personas no binarias',
			['Q1399232']	--[[ ['fa'afafine'] --]]			= 'Personas no binarias', -- third gender in Samoan culture
			['Q3277905']	--[[ ['māhū'] --]]					= 'Personas no binarias', -- third gender in traditional Hawaiian, Kanaka and Maohi cultures
			['Q746411']		--[[ ['kathoey'] --]]				= 'Personas no binarias', -- third gender in Thai culture
			['Q350374']		--[[ ['fakaleiti'] --]]				= 'Personas no binarias', -- third gender in Tongan culture
			['Q660882']		--[[ ['hijra'] --]]					= 'Personas no binarias', -- third gender of South Asian cultures
			['Q44148']		--[[ ['macho'] --]]					= nil, -- non-human
			['Q43445']		--[[ ['hembra'] --]]				= nil, -- non-human
			-- 'unknown value' or 'valor desconocido'
			-- 'no value' or 'sin valor'
			['Q207959']		--[[ ['androginia'] --]]			= nil,
			['Q301702']		--[[ ['dos espíritus'] --]]			= 'Personas no binarias', -- third gender in the indigenous North American cultures
			['Q27679766']	--[[ ['transmasculino'] --]]		= 'Hombres transgénero',
			['Q27679684']	--[[ ['transfemenino'] --]]			= 'Mujeres transgénero',
			['Q3177577']	--[[ ['muxe'] --]]					= 'Mujeres transgénero', -- third gender in Zapotec culture
			['Q28873047']	--[[ ['organismo intersexual'] --]]	= nil, -- non-human
			['Q505371']		--[[ ['agénero'] --]]				= 'Personas no binarias',
			['Q12964198']	--[[ ['genderqueer'] --]]			= 'Personas no binarias',
			['Q18116794']	--[[ ['género fluido'] --]]			= 'Personas no binarias',
			['Q1289754']	--[[ ['neutro'] --]]				= 'Personas no binarias',
			['Q179294']		--[[ ['eunuco'] --]]				= 'Hombres',
			['Q7130936']	--[[ ['pangénero'] --]]				= 'Personas no binarias',
			['Q64017034']	--[[ ['cogenitor'] --]]				= nil, -- fictional, non-human
			['Q52261234']	--[[ ['sexo neutro'] --]]			= 'Personas no binarias',
			['Q16674976']	--[[ ['hermafroditismo'] --]]		= nil, -- non-human
			['Q15145779']	--[[ ['mujer cisgénero'] --]]		= 'Mujeres',
			['Q15145778']	--[[ ['hombre cisgénero'] --]]		= 'Hombres',
		}
		local sexgenderval = wd.claims.P21[1].mainsnak.datavalue.value.id -- wd:formatPropertyValues( 'P21' ).value
		local sexgendercat = validsexgenders[ sexgenderval ] or 'Personas no categorizadas por sexo'
		return '[[Categoría:' .. sexgendercat .. ']]'
	end
	return ''  -- non-human
end

--[[
	@name	catLivingStatus
	@global	require('Módulo:Roman')
	@param	birthdate, deathdate, no errors
	@return	wikitext (categories and [optionally] errors)
	@descr	Genera las categorías relacionadas con el nacimiento y fallecimiento
			de una persona, así como identifica si está viva, en función de los
			datos proporcionados como parámetro o los obtenidos automáticamente
			de Wikidata según sus propiedades P569 y P570.
	@aux	filterBirthDate, filterLiveState, filterDeathDate, getDateStruct
--]]

local function filterBirthDate( value )
	return mw.ustring.match( mw.ustring.upper( value ), "MISSING" )
		or mw.ustring.match( mw.ustring.upper( value ), "UNKNOWN" )
		or mw.ustring.match( value, "%?" )
		or mw.ustring.match( value, "año desconocido" )
		or mw.ustring.match( value, "valor desconocido" )
end

local function filterLiveState( value )
	return mw.ustring.match( mw.ustring.upper( value ), "LIVING" )
		or mw.ustring.match( mw.ustring.upper( value ), "VIVA" )
end

local function filterDeathDate( value )
	return filterLiveState( value )
		or filterBirthDate( value )
end

local function getDateStruct( wd, arg, prop, filter )
	local result, number, margin -- string, integer, precision-like value
	local value
	local ModuloRoman = require('Módulo:Roman')
	local convertArabicToRoman = ModuloRoman._Numeral -- convertArabicToRoman
	local convertRomanToArabic = ModuloRoman.toArabic -- convertRomanToArabic
	if arg and arg ~= '' then
		value = mw.text.trim( arg )
	elseif wd and wd:formatPropertyValues( 'P31' ).value == 'ser humano' then
		-- wd.claims.P31[1].mainsnak.datavalue.value.id == 'Q5'
		value = wd:formatPropertyValues( prop ).value
	end

	if value and value ~= '' then
		local err, val
		if filter and type(filter) == 'function' then
			err, val = pcall( filter, value )
		end
		if err and val then
			margin = value -- 
			number = 0
			result = '' -- not nil, it is valid but filtered
		elseif mw.ustring.match( value, "milenio" ) then
			local m = mw.ustring.match( value, "(%a+) milenio" ) -- 'el MM milenio', roman
			if m then
				margin = 1000
				number = ( convertRomanToArabic( m ) - 1 ) * margin
				result = 'el ' .. m .. ' milenio'
			else
				m = mw.ustring.match( value, "(%d+). milenio" ) -- WD:'mm. milenio AED'
				if m then
					margin = 1000
					number = ( tonumber( m ) - 1 ) * margin
					result = 'el ' .. convertArabicToRoman( m ) .. ' milenio'
				else
					result = nil -- error
				end
			end
		elseif mw.ustring.match( value, "siglo" ) then
			local c = mw.ustring.match( value, "(%d+)%. siglo" ) -- WD:'cc. siglo AED'
			if c then
				margin = 100
				number = ( tonumber( c ) - 1 ) * margin
				result = 'el siglo ' .. convertArabicToRoman( c )
			else
				c = mw.ustring.match( value, "siglo (%a+)" ) -- 'el siglo CC', roman
				if c then
					margin = 100
					number = ( convertRomanToArabic( c ) - 1 ) * margin
					result = 'el siglo ' .. c
				else
					result = nil -- error
				end
			end
		elseif mw.ustring.match( value, "años" )
			or mw.ustring.match( value, "%d+s" ) then
			local d = mw.ustring.match( value, "años (%d+)" ) -- 'años yyyy'
					or mw.ustring.match( value, "(%d+)s" ) -- WD:'2020s AED'
			if d then
				margin = 10
				number = tonumber( d )
				result = 'los años ' .. number
			else
				result = nil -- error
			end
		else
			local y = mw.ustring.match( value, "^%d+ %a+ (%d+)" ) -- 'dd mmm aaaa'
				   or mw.ustring.match( value, "^%a+ (%d+)" ) -- 'mmm aaaa'
				   or mw.ustring.match( value, "^(%d+)" ) -- 'aaaa'
			if y then
				margin = 1
				number = tonumber( y )
				result = number
			else
				result = nil -- error
			end
		end

		if result
		and (  mw.ustring.match( value, "a%. C%." )
			or mw.ustring.match( value, "a%.%se%.%sc%." )
			or mw.ustring.match( value, "^%-" )
			or mw.ustring.match( value, "AEC" )
			or mw.ustring.match( value, "BCE?$" ) ) then
			number = -number
			result = result .. ' a. C.'
		end
	else
		result = false -- empty value
	end
	return result, number, margin
end

function p.catLivingStatus( birthdate, deathdate, noerrors )
	local wd = mw.wikibase.getEntityObject()
	local categories, errors = '', ''
	-- Birth date
	local result1, number1, margin1 = getDateStruct(wd, birthdate, 'P569', filterBirthDate)
	-- Death date
	local result2, number2, margin2 = getDateStruct(wd, deathdate, 'P570', filterDeathDate)
	-- Living status
	local living
	if result2 then
		living = false -- sure
	elseif result1 then
		if number1 < 0 then
			living = false -- sure
		elseif number1 then
			living = true -- maybe
			local curYear = tonumber(os.date( "%Y" ))
			local maxLive = (number1 + margin1 + 130)
			if curYear > maxLive then
				living = false
			end
		end
	end
	-- Categories
	if result1 == nil then
		errors = error('fecha de nacimiento no válida')
		categories = categories .. '[[Categoría:Nacidos en año desconocido]]' -- unknow because not valid
	elseif result1 == false then
		errors = errors .. '[[Categoría:Wikipedia:Artículos con plantilla NF sin fechas]]'
		categories = categories .. '[[Categoría:Nacidos en año desconocido]]' -- unknow because not set
	elseif result1 == '' then
		categories = categories .. '[[Categoría:Nacidos en año desconocido]]' -- known to be unknown
	else -- valid value
		categories = categories .. '[[Categoría:Nacidos en ' .. result1 .. ']]'
	end
	if result2 == nil then
		errors = error('fecha de fallecimiento no válida')
		-- categories = categories .. '[[Categoría:Fallecidos en año desconocido]]' -- unknow because not valid
	elseif result2 == false then
		if living then
			categories = categories .. '[[Categoría:Personas vivas]]'
		else
			errors = errors .. '[[Categoría:Wikipedia:Artículos con plantilla NF sin fechas]]'
		end
	elseif result2 == '' then
		if filterLiveState( margin2 ) then
			if living == false then
				categories = categories .. '[[Categoría:Fallecidos en año desconocido]]' -- unknow because not set
				errors = errors .. '[[Categoría:Wikipedia:Artículos con plantilla NF sin fechas]]'
				errors = errors .. '[[Categoría:Wikipedia:Artículos con problema en la plantilla NF]]'
			end
		else
			categories = categories .. '[[Categoría:Fallecidos en año desconocido]]' -- known to be unknown
		end
	else -- valid value
		categories = categories .. '[[Categoría:Fallecidos en ' .. result2 .. ']]'
	end
	if noerrors then
		return categories
	end
	return categories .. errors
end

--[[
	@name	sortKey
	@global	none
	@param	value
	@return	string
	@descr	Genera la clave de ordenación del nombre de una persona, a través de
			los datos obtenidos automáticamente de Wikidata según sus diferentes
			propiedades.
	@aux	filterBirthDate, filterLiveState, filterDeathDate, getDateStruct
--]]

function p.sortKey( value )
	local wd = mw.wikibase.getEntityObject()
	local sortkey = ''
	if value and value ~= '' then
		sortkey = value
	elseif wd and wd:formatPropertyValues( 'P31' ).value == 'ser humano' then
		-- wd.claims.P31[1].mainsnak.datavalue.value.id == 'Q5'
		local givenname = wd:formatPropertyValues( 'P734' ).value
		local familyname = wd:formatPropertyValues( 'P735' ).value
		local secondfamilyname = wd:formatPropertyValues( 'P1950' ).value
		-- local birthname = wd:formatPropertyValues( 'P1477' ).value
		if familyname and familyname~= '' then
			sortkey = familyname
			if secondfamilyname and secondfamilyname ~= '' then
				sortkey = sortkey .. ' ' .. secondfamilyname
			end
			if givenname and givenname ~= '' then
				sortkey = sortkey .. ', ' .. givenname
			end
		else
			-- try roman format
			local nomen = wd:formatPropertyValues( 'P2359' ).value
			local cognomen = wd:formatPropertyValues( 'P2365' ).value
			local praenomen = wd:formatPropertyValues( 'P2358' ).value
			local unkval, notval = 'valor desconocido', 'sin valor'
			nomen = nomen:gsub(unkval, ''):gsub(notval, '')
			cognomen = cognomen:gsub(unkval, ''):gsub(notval, '')
			praenomen = praenomen:gsub(unkval, ''):gsub(notval, '')
			if nomen and nomen ~= '' then
				sortkey = nomen
				if cognomen and cognomen ~= '' then
					sortkey = sortkey .. ' ' .. cognomen
				end
				if praenomen and praenomen ~= '' then
					sortkey = sortkey .. ', ' .. praenomen
				end
			end
		end
	end
	return sortkey
end

--[[
	@main
	@global	require('Módulo:Argumentos')
			require('Módulo:Control de autoridades')
			require('Módulo:Roman')
--]]

function p.main ( frame )
	local getArgs = require('Módulo:Argumentos').obtenerArgumentosConValor
	local args = getArgs( frame )

	-- Authority control
	local authorityControl = require('Módulo:Control de autoridades').authorityControl
	local result = authorityControl(frame) .. '\n' -- frame:preprocess('{{Control de autoridades}}\n')
	local ns = mw.title.getCurrentTitle().namespace
	if ns ~= 0 then
		return result
	end

	-- Sex/Gender
	result = result .. p.catSexGenderIdentity()

	-- Living status
	result = result .. p.catLivingStatus( args and args[1], args and args[2] )

	-- Sort key
	local sortkey = p.sortKey( args and args[3] )
	if sortkey and sortkey ~= '' then
		result = result .. frame:preprocess('{{ORDENAR:' .. sortkey .. '}}\n')
	end

	-- NF
	return result
end

return p