From d8200e32e060400cf8a45d7305068e3a8e550798 Mon Sep 17 00:00:00 2001 From: Jonathan Harker Date: Tue, 6 Oct 2026 08:52:13 +1300 Subject: [PATCH 1/2] Use tracking category for missing first/last names in Wikidata --- module_citeq.lua | 7 ++++--- module_citeq_config.lua | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/module_citeq.lua b/module_citeq.lua index ceead63..6ea51a0 100644 --- a/module_citeq.lua +++ b/module_citeq.lua @@ -9,6 +9,8 @@ local cite_cfg = mw.loadData ('Module:Cite/config') local cfg = mw.loadData ('Module:Cite_Q/config') local cs1_module = 'Module:Citation/CS1' -- don't load the module yet, may not be needed local cs1_cfg = mw.loadData('Module:Citation/CS1/Configuration') +local opt_cat = '' + -------------------------------------------------------------------------------- -- makeOrdinal needs to be internationalised along with cfg.i18n_t @@ -363,6 +365,7 @@ local function get_name_list (nl_type, args, qid, wdl) args[nl_type .. '-first' .. i] = args[nl_type .. '-first' .. i] or out[k].first else args[nl_type .. i] = label + opt_cat = opt_cat .. cfg.i18n_t.trackingcats['missing-author-first-last-names']; end if link[k] then args[nl_type .. '-link' .. i] = args[nl_type .. '-link' .. i] or link[k] -- author-linkn or editor-linkn @@ -886,12 +889,10 @@ local function _cite_q (citeq_args) citeq_args.id = id end - local opt_cat = '' - -- Indicator if item has been retracted local retract = '' if citeq_args.retracted_by then - opt_cat = cfg.i18n_t.trackingcats.retracted + opt_cat = opt_cat .. cfg.i18n_t.trackingcats.retracted local retract_id = string.gsub(citeq_args.retracted_by, 'Q', '') local retr_params = { citeq = 'yes', diff --git a/module_citeq_config.lua b/module_citeq_config.lua index bd209f0..35dc8fa 100644 --- a/module_citeq_config.lua +++ b/module_citeq_config.lua @@ -32,6 +32,7 @@ local i18n_t = { ["replaced"] = "[[Category:Cite Q - cites a replaced work]]", ["unknown-author"] = "", -- [[Category:Cite Q - author unknown]] removed as misplaced; someone is welcome to restore it if it is placed outside of the template parameter value ["unknown-template"] = "[[Category:Cite Q - template unknown]]", + ["missing-author-first-last-names"] = "[[Category:Cite Q - authors with missing given and family names]]", }, } From 60a73e860803e9b0baf4bcae34dace4286ec28d9 Mon Sep 17 00:00:00 2001 From: Jonathan Harker Date: Wed, 14 Oct 2026 03:21:21 +1300 Subject: [PATCH 2/2] Fix author counting, display name errors when found --- module_citeq.lua | 77 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/module_citeq.lua b/module_citeq.lua index 6ea51a0..e527144 100644 --- a/module_citeq.lua +++ b/module_citeq.lua @@ -10,6 +10,7 @@ local cfg = mw.loadData ('Module:Cite_Q/config') local cs1_module = 'Module:Citation/CS1' -- don't load the module yet, may not be needed local cs1_cfg = mw.loadData('Module:Citation/CS1/Configuration') local opt_cat = '' +local max_authors_displayed = 10 -- Don't look up all 500+ author items (is this in CS1 config somewhere?) -------------------------------------------------------------------------------- @@ -83,13 +84,11 @@ local function accept_value( param_val, wd_val ) end -- Split string of comma-separated first names into a table of initials +-- 2026-10-10: corrected for UTF-8 by [[User:Pengo]]. local function getInitials(str) local initials = {} - for _, word in pairs(mw.text.split(str, ' ', true)) do - local initial = mw.text.trim(word) - if #initial > 0 then - table.insert(initials, initial:sub(1, 1):upper()) - end + for word in mw.ustring.gmatch(str, '[^%s%.]+') do + table.insert(initials, mw.ustring.upper(mw.ustring.sub(word, 1, 1))) end return initials end @@ -109,7 +108,6 @@ end -- function to fetch a value to display local function makelink(v, out, link, maxpos, wdl, namestyle) local label - local max_authors_displayed = 10 -- TODO: this is probably in CS1 config somewhere local item_lookup = false if v.mainsnak.snaktype == "value" then if v.mainsnak.datatype == "wikibase-item" then @@ -170,6 +168,7 @@ local function makelink(v, out, link, maxpos, wdl, namestyle) label = label, last = last_name or nil, first = first_names or nil, + qid = qnumber or nil, } else out[position] = label @@ -191,6 +190,7 @@ local function makelink(v, out, link, maxpos, wdl, namestyle) label = label, last = last_name or nil, first = first_names or nil, + qid = qnumber or nil, } else out[position] = label @@ -249,7 +249,10 @@ local function makelink(v, out, link, maxpos, wdl, namestyle) } end else - label = mw.wikibase.getLabel("Q4233718"):gsub("^%l", mw.ustring.upper) .. (cfg.i18n_t.trackingcats["unknown-author"] or "") + label = { + label = mw.wikibase.getLabel("Q4233718"):gsub("^%l", mw.ustring.upper) .. (cfg.i18n_t.trackingcats["unknown-author"] or ""), + qid = 'Q4233718', + } end maxpos = maxpos + 1 out[maxpos] = label @@ -264,12 +267,13 @@ arguments: args - pointer to the parameter arguments table from the template call qid - value from |qid= parameter; the Q-id of the source (book, etc.) in qid wdl - value from the |wdl= parameter; a Boolean passed to enable links to Wikidata when no article exists -returns nothing; modifies the args table +returns name data found in Wikidata (label, first, last, link, qid); modifies the args table ]=] local function get_name_list (nl_type, args, qid, wdl) local propertyID local fallbackID + local names = {} if nl_type =="author" then propertyID = 'P50' -- for authors @@ -345,6 +349,7 @@ local function get_name_list (nl_type, args, qid, wdl) end table.sort(keys) -- as they might be out of order for i, k in ipairs(keys) do + names[i] = {} local label if out[k].label then label = out[k].label @@ -352,26 +357,32 @@ local function get_name_list (nl_type, args, qid, wdl) label = out[k] end label = label:gsub(''', '\''); -- prevent cs1|2 multiple names categorization; replace html entity with the actual character + names[i].label = label + names[i].qid = out[k].qid or nil mw.log(i .. " " .. k .. " " .. label) if args[nl_type .. i] then -- name gets overwritten -- pull corresponding -link only if overwritten name is same as WD name if link[k] and (args[nl_type .. i] == label) then args[nl_type .. '-link' .. i] = args[nl_type .. '-link' .. i] or link[k] -- author-linkn or editor-linkn + names[i].link = link[k] end else -- name does not get overwritten, so pull name from WD if out[k].first and out[k].last then -- First/last names were found, so add them args[nl_type .. '-last' .. i] = args[nl_type .. '-last' .. i] or out[k].last args[nl_type .. '-first' .. i] = args[nl_type .. '-first' .. i] or out[k].first + names[i].last = out[k].last + names[i].first = out[k].first else args[nl_type .. i] = label - opt_cat = opt_cat .. cfg.i18n_t.trackingcats['missing-author-first-last-names']; end if link[k] then args[nl_type .. '-link' .. i] = args[nl_type .. '-link' .. i] or link[k] -- author-linkn or editor-linkn + names[i].link = link[k] end end end + return names end -- gets language codes used for a monolingual text property as a table @@ -767,6 +778,7 @@ local function _cite_q (citeq_args) end end + local names = {} if is_set (qid) then if not is_set (citeq_args.author) and not is_set (citeq_args.author1) and not is_set (citeq_args.subject) and not is_set (citeq_args.subject1) @@ -775,19 +787,19 @@ local function _cite_q (citeq_args) and not is_set (citeq_args.surname) and not is_set (citeq_args.surname1) and not is_set (citeq_args['author-last']) and not is_set (citeq_args['author-last1']) and not is_set (citeq_args['author1-last']) and not is_set (citeq_args['author-surname']) and not is_set (citeq_args['author-surname1']) and not is_set (citeq_args['author1-surname1']) then -- if neither are set, try to get authors from Wikidata - get_name_list ('author', citeq_args, qid, wdl) -- modify citeq_args table with authors from Wikidata + names.authors = get_name_list ('author', citeq_args, qid, wdl) -- modify citeq_args table with authors from Wikidata end if not is_set (citeq_args.editor) and not is_set (citeq_args.editor1) and not is_set (citeq_args['editor-last']) and not is_set (citeq_args['editor-last1']) and not is_set (citeq_args['editor1-last']) and not is_set (citeq_args['editor-surname']) and not is_set (citeq_args['editor-surname1']) and not is_set (citeq_args['editor1-surname']) then -- if neither are set, try to get editors from Wikidata - get_name_list ('editor', citeq_args, qid, wdl) -- modify citeq_args table with editors from Wikidata + names.editors = get_name_list ('editor', citeq_args, qid, wdl) -- modify citeq_args table with editors from Wikidata end if not is_set (citeq_args.translator) and not is_set (citeq_args.translator1) and not is_set (citeq_args['translator-last']) and not is_set (citeq_args['translator-last1']) and not is_set (citeq_args['translator1-last']) and not is_set (citeq_args['translator-surname']) and not is_set (citeq_args['translator-surname1']) and not is_set (citeq_args['translator1-surname']) then -- if neither are set, try to get translators from Wikidata - get_name_list ('translator', citeq_args, qid, wdl) -- modify citeq_args table with translators from Wikidata + names.translators = get_name_list ('translator', citeq_args, qid, wdl) -- modify citeq_args table with translators from Wikidata end end @@ -801,7 +813,7 @@ local function _cite_q (citeq_args) local author_count = 0 for k, v in pairs(citeq_args) do - if k:find("^author%d+$") then + if k:find("^author%d+$") or k:find("^author%-last%d+$") then author_count = author_count + 1 end end @@ -815,7 +827,7 @@ local function _cite_q (citeq_args) local editor_count = 0 for k, v in pairs(citeq_args) do - if k:find("^editor%d+$") then + if k:find("^editor%d+$") or k:find("editor%-last%d+$") then editor_count = editor_count + 1 end end @@ -827,6 +839,43 @@ local function _cite_q (citeq_args) end end + -- check only the names being displayed for missing first/last name errors + local missing_names = {} + for i, author in pairs(names.authors or {}) do + if not author.last and i <= (citeq_args['display-authors'] or author_count) then + if author.qid and author.qid == 'Q4233718' then + -- ignore anonymous + else + table.insert(missing_names, author.label) + end + end + end + for i, editor in pairs(names.editors or {}) do + if not editor.last and i <= (citeq_args['display-editors'] or editor_count) then + if editor.qid and editor.qid == 'Q4233718' then + -- ignore anonymous + else + table.insert(missing_names, editor.label) + end + end + end + for i, translator in pairs(names.translators or {}) do + if not translator.last then + if translator.qid and translator.qid == 'Q4233718' then + -- ignore anonymous + else + table.insert(missing_names, translator.label) + end + end + end + + -- add category and display error if name errors found + local name_cat = cfg.i18n_t.trackingcats['missing-author-first-last-names'] + if #missing_names > 0 and not string.find(opt_cat, name_cat, 1, true) then + opt_cat = opt_cat .. name_cat + opt_cat = opt_cat .. ' {{[[Template:Cite Q|Cite Q]]}}: Missing first/last names in Wikidata for ' .. table.concat(missing_names, ', ') .. ' ' + end + -- change edition to ordinal if it's set and numeric citeq_args.edition = citeq_args.edition and makeOrdinal(citeq_args.edition)