Módulo:auto cat
Módulo que genera estructura automática para las páginas de las Categorías.
Uso
{{auto cat}}
Subpáginas
Esta documentación está transcluida desde Módulo:auto cat/doc.
Los editores pueden experimentar en la zona de pruebas de este módulo.
Por favor, añade las categorías e interwikis a la subpágina de documentación. Subpáginas de este módulo.
Los editores pueden experimentar en la zona de pruebas de este módulo.
Por favor, añade las categorías e interwikis a la subpágina de documentación. Subpáginas de este módulo.
local export = {}
local insert = table.insert
local concat = table.concat
local m_str = require("Módulo:String")
local strexplode = m_str.explode_utf8
local strfind = m_str.find
local strmatch = m_str.match
local strsub = m_str.gsub
local strsplit = m_str.split
local strlower = m_str.lower
local strupper = m_str.upper
local strucfirst = m_str.ucfirst
local strlcfirst = m_str.lcfirst
local substr = m_str.sub
local strlen = m_str.len
local m_leng = require("Módulo:lenguas")
local m_nombres = mw.loadData("Módulo:lenguas/nombre_a_cod")
local WIKCIONARIO = 1
local COD = 2
local SWADESH = 3
local TRADUCCIONES = 4
local RIMAS = 5
local PRON_GRAF = 6
local ETIMOLOGIA = 7
local GRAMATICA = 8
local CONTEXTO = 9
local LENGUAS = 10
local PLANTILLAS = 11
local MANTENIMIENTO = 12
local POR_IDIOMA = 13
local USUARIOS = 14
local ESCRITURAS = 15
local function obtener_alfabeto(args)
-- por el momento, si no está standardChars, entonces no genero el alfabeto.
-- En un futuro, podría hacer que genere el alfabeto que provee directamente el script,
-- pero hay que implementar la función que devuelva eso porque la que está ahora mismo devuelve un rango de caracteres en regex
if not args["idioma"] or not args["idioma"].standardChars then
return ""
end
local ignorar_script = {["Brai"] = true, ["Sgnw"] = true}
local abc = {}
if type(args["idioma"].standardChars) == "string" then
abc[1] = args["idioma"].standardChars
else
local m_sc = require("Módulo:scripts")
for script in args["idioma"][4]:gmatch("([^,]+)%s*,?%s*") do -- tomo todos los scripts que haya, y para cada uno busco el alfabeto
if script == "All" then
return ""
end
if not ignorar_script[script] then
local chars = m_sc.getByCode(script):getCharacters()
script_ = args["idioma"].standardChars[script]
if script_ then
insert(abc, strexplode(strupper(script_)))
end
end
end
end
local t = {}
for _,alfabeto in ipairs(abc) do
if alfabeto then
local mem = {["-"] = true} --ignoro el guion porque eso es parte de los regex en el caso de los alfabetos obtenidos directo del script
insert(t, "<div style=\"font-size:90%; text-align:center\">\n")
insert(t, "{|class=\"plainlinks\" align=\"center\" style=\"padding:3px 15px 3px 15px;\"\n")
insert(t, "|style=\"text-align: center; font-weight:bold; font-size:100%; padding-left:15px; padding-right:15px\"|\n")
local pg = args["pagename"]
for i,c in ipairs(alfabeto) do
if not mem[c] then
mem[c] = true
insert(t, "["..tostring(mw.uri.canonicalUrl("Categoría:"..pg, "from="..c)).." "..c.."] \n")
end
end
insert(t, "|}\n</div>\n")
end
end
return concat(t)
end
local function generar_titulo(texto, args)
local t = {}
insert(t, "<div style=\"background-color:#f6f6f6; border:1px dotted #ABCDEF; padding:8px; width:95%; margin:0 auto;\">\n")
if texto then
if args["Idioma"] then
insert(t, "<div style=\"font-size:110%; text-align:center\">"..args["Idioma"]..": "..texto)
else
insert(t, "<div style=\"font-size:110%; text-align:center\">"..texto)
end
if args["oculta"] then
insert(t, "__HIDDENCAT__<br>Esta es una categoría de mantenimiento que no se muestra directamente en los artículos. Si deseas habilitar la visualización de estas categorías, puedes hacerlo en [[Especial:Preferencias|tus preferencias]].")
end
insert(t, "</div>\n")
end
return concat(t)..obtener_alfabeto(args).."</div>\n"
end
local function generar_aviso(tipo, texto)
local header = {
["info"] = "<table style=\"aviso\" class=\"plainlinks ambox ambox-notice\">"
}
local imagen = {
["info"] = "[[Imagen:Emblem-notice.svg]]"
}
return header[tipo].."<tr><td class=\"ambox-image\"><div style=\"width:52px;\">"..imagen[tipo].."</div></td><td class=\"ambox-text\">"..texto.."</td></tr></table>"
end
local function generar_categorias(padres, args)
if not args["COD"] then
return padres
end
local padres_ = {}
for _,padre in ipairs(padres) do
if padre and padre ~= "" then
insert(padres_, args["COD"]..":"..padre)
else
insert(padres_, args["Idioma"]..'| ')
end
end
-- if args["wik"] then
-- insert(padres_,"Wikcionario")
-- end
return padres_
end
local handlers = {}
-- Detección de "Wikcionario"
handlers[WIKCIONARIO] =
function(clave, args)
if clave == "Wikcionario" then
args["wik"] = true
end
end
-- Detección de código de idioma en mayúscula
handlers[COD] =
function(clave, args)
local x,y,z
if strfind(clave, "^%u%u+$") or strfind(clave, "^%u%u+%-%u%u+$") or strfind(clave, "^%u%u+%-%u%u+%-%u%u+$") then
x = strlower(clave)
y = clave
z = m_leng.cod_a_idioma(x)
end
if x and y and z then
args["cod"] = x
args["COD"] = y
args["idioma"] = z
args["Idioma"] = strucfirst(z[1])
return false
end
return nil
end
--Lista Swadesh
handlers[SWADESH] =
function(clave, args)
if clave ~= "Lista Swadesh" then
return nil
end
return true, generar_titulo("Lista de [[w:Lista Swadesh|vocabulario básico altamente resistente a préstamos]], concepto del lingüista [[w:Morris Swadesh|Mauricio Swadesh]].", args), generar_categorias({""}, args)
end
--Traducciones: debería estar en mantenimiento??
handlers[TRADUCCIONES] =
function (clave, args)
local m = {strmatch(clave, "^([a-zA-ZÀ-ž ]+)%-([a-zA-ZÀ-ž ]+)$")}
if not m[1] or not m[2] then
m = strfind(clave, "^Traducciones desde el español$")
if not m then
return nil
end
args["oculta"] = true
return true, generar_titulo("En esta categoría se encuentran todas las entradas de traducción desde el español.", args), {}
end
local a = strlcfirst(m[1])
local b = strlcfirst(m[2])
local idioma1, idioma2 = m_nombres[a], m_nombres[b]
if not idioma1 or not idioma2 then
return nil
end
args["oculta"] = true
return true, generar_titulo("En esta categoría se encuentran todas las entradas de traducción del idioma "..a.." al "..b..".", args), {"Traducciones desde el "..a}
end
--Rimas
handlers[RIMAS] =
function (clave, args)
if clave == "Rimas" then
if args["i_"] == args["L_"] then
args["no sufijo"] = true
return true, generar_titulo("Lista de rimas.", args), generar_categorias({""}, args)
else
args["Rimas"] = true
return nil
end
elseif args["Rimas"] then
return true, generar_titulo("Lista de rimas con -"..clave..".", args), generar_categorias({"Rimas|"..clave}, args)
end
return nil
end
-- Pron-graf
handlers[PRON_GRAF] =
function(clave, args)
local padres = mw.loadData("Módulo:auto cat/pron-graf")[clave]
if not padres then
return nil
end
if clave == "Palabras sin transcripción fonética" then
args["oculta"] = true
args["no sufijo"] = true
end
return true, generar_titulo("Lista de "..strlcfirst(clave)..".", args), generar_categorias(padres, args)
end
-- Etimología
handlers[ETIMOLOGIA] =
function (clave, args)
-- Etimología de otro idioma
local m = {strmatch(clave, "^Palabras provenientes del ([a-zA-ZÀ-ž ]+)$")}
if m[1] then
args["no sufijo"] = true
return true, generar_titulo("Lista de "..strlcfirst(clave)..".", args), generar_categorias({"Palabras por idioma de origen|"..m[1]}, args)
end
m = {strmatch(clave, "^Palabras documentadas desde el siglo [IVX]+$")}
if m[1] then
args["no sufijo"] = true
return true, generar_titulo("Lista de "..strlcfirst(clave)..".", args), generar_categorias({"Palabras por época de origen"}, args)
end
-- Prefijos, infijos, sufijos
m = {strmatch(clave, "^Palabras con el prefijo (.*)$")}
if m[1] then
args["no meta"] = true
return true, generar_titulo("Lista de "..strlcfirst(clave)..".", args), generar_categorias({"Palabras formadas por prefijación|"..m[1]}, args)
end
m = {strmatch(clave, "^Palabras con el infijo (.+)$")}
if m[1] then
args["no meta"] = true
return true, generar_titulo("Lista de "..strlcfirst(clave)..".", args), generar_categorias({"Palabras formadas por infijación|"..m[1]}, args)
end
m = {strmatch(clave, "^Palabras con el sufijo -(.+)$")}
if m[1] then
args["no meta"] = true
return true, generar_titulo("Lista de "..strlcfirst(clave)..".", args), generar_categorias({"Palabras formadas por sufijación|"..m[1]}, args)
end
if clave == "Palabras de etimología sin precisar" then
args["no sufijo"] = true
args["oculta"] = true
end
-- Otros tipos de etimologías
local padres = mw.loadData("Módulo:auto cat/etimología")[clave]
if not padres then
return nil
end
return true, generar_titulo("Lista de "..strlcfirst(clave)..".", args), generar_categorias(padres, args)
end
--Gramática
handlers[GRAMATICA] =
function (clave, args)
local padres = mw.loadData("Módulo:auto cat/gramática")[clave]
if not padres then
return nil
end
args["no sufijo"] = true
return true, generar_titulo("Lista de "..strlcfirst(clave)..".", args), generar_categorias(padres, args)
end
--Csem, ambito, uso
handlers[CONTEXTO] =
function (clave, args)
if strfind(clave, "^Idiomas de [^a-z]") then
return true, generar_titulo(clave..".", args), generar_categorias({"Idiomas"}, args)
end
local padres = mw.loadData("Módulo:auto cat/uso")[clave]
if padres then
return true, generar_titulo("Lista de "..clave..".", args), generar_categorias(padres, args)
end
local padres = mw.loadData("Módulo:auto cat/campos semánticos")[clave]
if padres then
return true, generar_titulo("Lista de términos relacionados con "..strlcfirst(clave)..".", args), generar_categorias(padres, args)
end
local padres = mw.loadData("Módulo:auto cat/ámbito")[clave]
if padres then
args["no sufijo"] = true
return true, generar_titulo("Lista de términos propios de "..clave..".", args), generar_categorias(padres, args)
end
-- casos especiales (serán muchos)
--- Topónimos
m = {strmatch(clave, "^Topónimos de (.+)$")}
if m[1] then
return true, generar_titulo("Lista de "..strlcfirst(clave), args), generar_categorias({'Topónimos|'..m[1]}, args)
end
return nil
end
--Nombre de idioma o familia
handlers[LENGUAS] =
function (clave, args)
clave = strlcfirst(clave)
local cod = m_nombres[clave]
if not cod then
return nil
end
local es_familia = strmatch(clave, "^lenguas")
local idioma
if not es_familia then
idioma = m_leng.cod_a_idioma(cod)
else
idioma = m_leng.cod_a_familia(cod)
end
local dag, familia = m_leng.obtener_dag(idioma, es_familia)
local arbol = require("Módulo:DAG").dagAHtml(dag, "Árbol genealógico")
local t = {}
local i = 1
local function insert(s)
t[i] = s
i = i + 1
end
local cat = {}
local i_ = 1
local function insert_cat(s)
cat[i_] = s
i_ = i_ + 1
end
-- En realidad final va al comienzo de todo, me confundí xd
local final = {}
local i__ = 1
local function insert_final(s)
final[i__] = s
i__ = i__ + 1
end
insert("=== Información ===\n")
insert(":* '''Código''': <code>"..cod.."</code>\n")
insert(":* '''Nombre canónico''': "..clave.."\n")
insert(":* '''ID de Wikidata''': [https://www.wikidata.org/wiki/Q"..tostring(idioma[2]).." "..tostring(idioma[2]).."]\n")
if familia then
insert(":* '''Familia''': [[:Categoría:"..familia.."|"..familia.."]]\n")
insert_cat(familia)
else
insert_cat("Lenguas")
end
if not es_familia then
insert(":* '''Script(s)''': ")
for script in idioma[4]:gmatch("([^,]+)%s*,?%s*") do
insert("[[Wikcionario:Lista de scripts#" .. script .. "|<code>" .. script .. "</code>]] ")
--insert_cat("Script "..script)
end
insert_cat("Idiomas")
insert("\n")
end
if idioma.otherNames then
insert(":* '''Otros nombres''': ")
for l,n in ipairs(idioma.otherNames) do
if l == 1 then
insert(n)
else
insert(", "..n)
end
end
insert(".\n")
end
insert("=== Véase también ===\n")
if not es_familia then
insert(":* [[File:Wiktionary-logo.svg|25px]] [["..clave.."|Entrada]] en el Wikcionario.\n")
end
local titulo_wikipedia = mw.wikibase.sitelink("Q"..tostring(idioma[2]), 'eswiki')
if titulo_wikipedia then
insert(":* [[File:Wikipedia-logo.svg|25px]] [[w:"..titulo_wikipedia.."|Entrada]] en Wikipedia.\n")
end
insert(":* [[File:Wikidata-logo.svg|25px]] [[wikidata:Q"..tostring(idioma[2]).."|Entrada]] en Wikidata.\n")
insert(":* [[File:Commons-logo.svg|25px]] [[commons:"..clave.."|Búsqueda]] en Wikimedia Commons.\n")
--insert(":* [[Wikcionario:Convenciones para nombrar entradas/"..cod.."|Convenciones]] para nombrar entradas.\n")
if not es_familia then
insert(":* [[Wikcionario:Códigos de idioma|Lista]] completa de idiomas.\n")
else
insert(":* [[Wikcionario:Familias de idiomas|Lista]] completa de familias.\n")
end
local im = mw.title.new("Lang-"..cod..".gif", 6)
if im and im.fileExists then
insert_final("[[File:Lang-"..cod..".gif|200px]]\n\n")
end
insert_final("Esta es la categoría principal ")
if not es_familia then
insert_final("del idioma "..clave..".\n")
else
insert_final("de las "..clave..".\n")
end
local hay_arg = false
for j, arg in ipairs(args) do
if j == 1 then
insert_final("Se habla en: [["..args[1].."]]")
insert_cat("Idiomas de "..args[1])
else
insert_final(", [["..args[j].."]]")
insert_cat("Idiomas de "..args[j])
end
hay_arg = true
end
if hay_arg then
insert_final(".\n")
end
-- https://stackoverflow.com/questions/31455768/html-table-cell-spacing-only-between-cells-no-outer-one
return true, "<table border=0 cellspacing=0 cellpadding=0 style=\"margin:-10px;width:99.9%;border-spacing:10px;\">\n<tr>\n<td style=\"text-align:left;vertical-align:top;\">\n"..concat(final)..concat(t).."</td>\n<td style=\"text-align:center;\">\n"..arbol.."</td>\n</tr>\n</table>\n", cat
end
-- Plantillas (muy ampliable)
handlers[PLANTILLAS] =
function (clave, args)
m = {}
if strmatch(clave, "Plantillas de flexión de")
or strmatch(clave, "Plantillas auxiliares de flexión")
or strmatch(clave, "Plantillas de mutación") then
args["no sufijo"] = true
m[clave] = {"Plantillas de flexión"}
elseif strmatch(clave, "Plantillas$") then
args["no sufijo"] = true
m[clave] = {}
elseif strmatch(clave, "Plantillas") then
args["no sufijo"] = true
m[clave] = {"Plantillas"}
end
local padres = m[clave]
if not padres then
return nil
end
return true, generar_titulo("Lista de "..strlcfirst(clave)..".", args), generar_categorias(padres, args)
end
-- Detección de Mantenimiento
handlers[MANTENIMIENTO] =
function(clave, args)
-- if not args["wik"] then
-- return nil
-- end
local m = mw.loadData("Módulo:auto cat/mantenimiento")
if m[clave] then
return true, generar_aviso("info", "__HIDDENCAT__"..
"Esta categoría es de mantenimiento"..
" y por lo tanto no se mostrará directamente. Si desea que se "..
"muestre en cada página, puede cambiar "..
"[[Especial:Preferencias|sus preferencias]]."),
generar_categorias(m[clave], args)
-- TODO: Nombres de categorías. ¿Eliminar Wikicionario:? Creo q es razonable
-- dejar esas categorías sólo para páginas del espacio Wikcionario
end
end
-- Contrucción de metacategorías por idioma
handlers[POR_IDIOMA] =
function(clave, args)
if args["metacat"] then
return nil -- por las dudas
end
local m = {strmatch(clave, "^(.+) por idioma$")}
local clave_ = m[1]
if clave_ then
args["metacat"] = true -- útil?
for i,handler in ipairs(handlers) do -- cómo evito que vuelva a pasar recursivamente de forma ilimitada
local padres_ = {}
local terminar, msj, padres = handler(clave_, args)
if terminar == true then
for i, padre_ in ipairs(padres) do
if padre_ ~= "" then
insert(padres_, padre_..' por idioma| ')
insert(padres_, clave_..'| ')
else
-- puede tener un mejor nombre? creo que sí
insert(padres_, 'Metacategorías espejo| ')
insert(padres_, clave_..'| ')
end
end
return true,
-- quizá mejorar este título
generar_titulo("Metacategoría de ''"..strlcfirst(clave_).."'' por idioma", args),
generar_categorias(padres_, args)
elseif terminar == false then -- si no es nil
break
end
end
end
return nil
end
-- Usuarios por idioma, debería fusionarlo con el handler de arriba?
handlers[USUARIOS] =
function(clave, args)
local m = {strmatch(clave, "^Usuarios por idioma %- ?(.+)$")}
if not m[1] then
return nil
end
local c = {"0", "básico", "intermedio", "avanzado", "experto", "nativo"}
local r = nil
local s = nil
for _,q in ipairs(c) do
local m2 = {strmatch(m[1], "^(.+) ?"..q.."$")}
if m2[1] then
r = m2[1]
s = q
break
end
end
local padres_ = {}
if not r then
insert(padres_, "Usuarios por idioma")
return true, generar_titulo("Lista de usuarios que hablan "..m[1], args), generar_categorias(padres_, args)
else
insert(padres_, "Usuarios por idioma - "..r)
if s == "0" then
return true, generar_titulo("Lista de usuarios que NO entienden "..r, args), generar_categorias(padres_, args)
else
return true, generar_titulo("Lista de usuarios que hablan "..r..", nivel "..s, args), generar_categorias(padres_, args)
end
end
end
-- Escrituras
handlers[ESCRITURAS] =
function(clave, args)
local m_escrituras = mw.loadData("Módulo:auto cat/escrituras")
local codigos = m_escrituras[clave]
if codigos then
for _,cod in ipairs(codigos) do
if cod == args["COD"] then
return true, generar_titulo("Lista de palabras pertenecientes a la escritura "..clave..".", args), generar_categorias({"Escrituras"}, args)
end
end
end
local m = strfind(clave, "^Escrituras$")
if m then
return true, generar_titulo("Lista de escrituras.", args), generar_categorias({}, args)
end
return nil
end
function export.categorizar(frame)
local title = mw.title.getCurrentTitle().fullText
if title == "Plantilla:auto cat" then
return "Use esta plantilla en el espacio de Categorías."
end
local pagename = mw.title.getCurrentTitle().text
if pagename == "Módulo:auto cat" then
return nil
end
local ns = mw.title.getCurrentTitle().namespace
assert(ns == 14, "La plantilla sólo puede utilizarse en el espacio de Categorías")
local args = frame:getParent().args
args["pagename"] = pagename
local claves = strsplit(pagename, ":")
local L = #claves
args["i_"] = 1
args["L_"] = L
local t = {}
while args["i_"] <= L do
local clave = claves[args["i_"]]
for i,handler in ipairs(handlers) do
local terminar, msj, padres = handler(clave, args)
if terminar == true then
insert(t, msj)
-- Paso 1: metacategorías
-- Caso a: "no meta" = no metacategoría x idioma
if args["no meta"] then
-- nada
-- Caso b: sin sufijo
elseif args["COD"] and L == 2 and args["no sufijo"] then
insert(t, "[[Categoría:"..clave.."|"..args["COD"].."]]")
-- Caso c: caso general
elseif args["COD"] and L == 2 then
insert(t, "[[Categoría:"..clave.." por idioma|"..args["COD"].."]]")
-- Caso d: eventualmente eliminar Categorías:Wikicionario:
-- salvo para páginas realmente internas. Por ahora mantener
elseif args["COD"] and args["wik"] and L == 3 then -- caso para Categoría:Wikcionario:XXXX
insert(t, "[[Categoría:Wikcionario:"..claves[3].."|"..args["COD"].."]]")
end
-- Paso 2: árbol de categorías
for i,padre in ipairs(padres) do
-- Caso a: Categorías fundamentales. Padre "", sin código
if not args["wik"] and not args["COD"] and padre == "" then
insert(t, "[[Categoría:Fundamental| ]]\n")
elseif padre ~= "" then
insert(t, "[[Categoría:"..padre.."| ]]\n")
end
end
return concat(t)
elseif terminar == false then -- si no es nil
break
end
end
args["i_"] = args["i_"] + 1
end
if args["wik"] then
return nil
end
error("La categoría no puede ser reconocida.")
end
return export