Module:Central

-- Module:Central

local p = {}

local try = p -- try part of Module:Central --	local CA = p -- try part of Module:Central (deprecated ControlArgs)

--[ [ Module:Central p.versions = { -- Modules dependencies. Dependencias del módulo. Dépendances du module. versionName = "Central", versionNumber = "1.03", versionDate = "2016-05-12 12:0", sought = "Central", -- Sought module and submodules versions known = "Central", -- Known module and submodules versions loaded_list = ",Central,",-- Module:Central } --] ]

-- Module:Central p.versions = { -- Modules dependencies. Dependencias del módulo. Dépendances du module.	versionName = "Central", versionNumber = "1.02", versionDate = "2016-02-21 23:53",	sought = "Central,Central01,cen tre,mathroman", -- Sought module and submodules versions	known = "Central,Central000	 ", -- Known module and submodules versions	loaded_list = ",Central,Central 01,centre,tools,mathroman,", } --

p.ModuleNS = mw.site.namespaces.Module.name .. ":"

-- Because the bug T122752 : #invoke seems do not record the module, for some weeks. -- https://phabricator.wikimedia.org/T122752 Rical created this task.Via Web ·Sat, Jan 2, 2016-01-02 23:08 -- Replace the missing of record of the module by : (Todo also in other modules) -- _G[p.ModuleNS .. p.versions.versionName] = p -- like _G["Module:Central1"] = p -- in _G to DEBUG T122752 : #invoke do not record the main module in package.loaded

-- -- Development guide line -- For an easier and faster work, group several modules and libraries and their tests simulations in the same true module. -- Whith several modules and libraries in 1 module, we can move and change variables and functions, several at once. -- Simulate libraries in _G space, waiting a true implementation. -- There is a bug report by Rical: T122752 : #invoke seems do not record the module, for some weeks. -- https://phabricator.wikimedia.org/T122752 Rical created this task.Via Web ·Sat, Jan 2, 2016-01-02 23:08 -- Simulate Modules in _G space, waiting the DEBUG of T122752#invoke. -- Simulate old and new versions of modules and libraries to satisfy the main module calls until need to change it. --

-- -- Development guide line for Library:tools, Library:centre and Library:mathroman. -- We simulate them here, to faster and easier install and coordinate them and their functions. --	if not centre		then start.new_library("centre", options)		end -- Install Library:centre as a true temporary library. --	if not tools		then start.new_library("tools", options)		end -- Install Library:tools as a true temporary library. --	if not mathroman	then start.new_library("mathroman", options)	end -- Install Library:mathroman as a true temporary library. --

-- --	Development guide line for i18n translations -- --	A central module could need a translation service and a versioning service to enhance its functions or its stability without disturbing the preview normal use. --	A main module can define its sought sub-modules versions names and its known sub-modules versions names. --	The Library:centre manages the versioning of modules, and the mix of translations from libraries, modules and their /I18N sub-modules. --	A central module and its translations can inpedendently change. For this goal a module contains only one or some tranlations, but its /I18N sub-module contains translations in some or all languages. --	The adaptation to any number of languages is automatic. --	The highest level is the main module. The lowest level is the libraries level. -- --	Any module or library can contain i18n tables. --	i18n tables are mixed from the lowest to the highest level, to permit at upper module to adapt the meaning of texts to a new use. --	Each library is independent of other ones and they can be mixed in any order. --	To avoid conflict of translations keys between libraries, all translations keys names start with the library name. -- --	A library contains internal autotests cases. --	But the view of tests cases for users, to verify or understand the functions or the uses, are in a tools library or in some modules. -- --	The Library:tools manages the translations used for received arguments names, errors, messages, categories, arguments lists... --	The Library:tools forms easy translatable dropboxes, tables views... --

-- --	Install Library:centre --	This library support modules to: --	* Collect and bind modules and sub-modules --	* Collect and bind translations from /I18N sub-modules --	* Form parametrable strings --	* Add a language needs only to add its own i18n subtable, like i18n.en = {} --	* Manage alternate versions of sub-modules sought from main, like Module:Sub, Module:Sub2, Module:SubPlus. -- --	This library do not support the bilingual categories, see Library:tools. --	Libraries dependencies: --	This Library:centre needs the Library:mw --	The Library:mathroman and the Library:tools and the Module:Author3 depend of this library. --

-- Translations for centre library centre = {} centre.i18n = {} -- Translations not used on 2016-05-17 centre.i18n.en = { centre_luatable_counts				= "%1 variables, %2 functions, %3 sub-tables", centre_table_dont_exists			= "The table %1 does not exist.", centre_table_listlimit_levelmaxi	= "Level limit levelmaxi = %1 ", centre_table_listlimit_max_n		= "Length limit max_n = %1 ", } -- centre.i18n.en

centre.i18n.es = { centre_luatable_counts				= "%1 variables, %2 funciones, %3 subtablas", centre_table_dont_exists			= "La tabla %1 no existe.", centre_table_listlimit_levelmaxi	= "Límite de nivel levelmaxi = %1", centre_table_listlimit_max_n		= "Límite de longitud max_n = %1", } -- centre.i18n.es

centre.i18n.fr = { centre_luatable_counts				= "%1 variables, %2 fonctions, %3 sous-tables", centre_table_dont_exists			= "La table %1 n'existe pas.", centre_table_listlimit_levelmaxi	= "Limite de niveau levelmaxi = %1 ", centre_table_listlimit_max_n		= "Limite de longueur max_n = %1 ", } -- centre.i18n.fr centre.wiki_translations = centre.i18n.en -- wiki's default translations centre.user_translations = centre.i18n.en -- user's default translations

centre.ModuleNS = mw.site.namespaces.Module.name .. ":"

function centre.trackallversions(where, txt) centre.report_trackallversions = (centre.report_trackallversions or "function report_trackallversions ") .. tools.ta(where, txt) return centre.report_trackallversions -- search .all_versions end

function centre.pcallrequire( version ) -- require must not fail and block the page. if type(version) == "string" then version = string.gsub( version, centre.ModuleNS, "" ) -- normalize for always one "Module:" version = centre.ModuleNS .. version -- example Module:Central/I18N end local success, module = pcall( require, version ) -- pcall or xpcall can run any function without blocking page. if success then return module else return nil end end

function centre.get_module_and_time(title, given_module) -- Get a descriptor of one loaded object --	local get = centre.get_module_and_time("Module:Central") local get = {} local module, required, loaded if type(title) ~= "string" then get.title = title get.isNil = true return get end -- If not loaded, return only an empty get if given_module then -- of any type module = given_module else -- to require a new module loaded = centre.pcallrequire(title) -- require must not fail and block the page if the module do not exists. if loaded then module = loaded -- The module is well loaded in package.loaded else return get end -- If not loaded, return only get.isTitled and get.title end get.title = title get.module = module get.isNil = not module get.isLoaded = true and package.loaded[title] get.isFunction = (type(module) == "function") get.isTable = (type(module) == "table") get.i18n = module.i18n get.versions = module.versions get.isLibrary = ( not tools.is_in(centre.ModuleNS, title) ) and ( (type(module) == "table") or (type(module) == "function") ) -- T000000 Rical task: Add module and library types in scribunto ? get.hasi18n = (type(module) == "table") and (type(get.i18n) == "table") get.versionName = string.gsub(get.title or "", centre.ModuleNS, "") -- full version name with perhaps /I18N get.versionTitle = centre.ModuleNS .. get.versionName -- normalize title like Module:module get.isModule = string.find(get.title, centre.ModuleNS) -- is module from title get.isI18N = true and string.find(get.title, "/I18N") -- is /I18N get.lessI18N = string.gsub(get.versionName, "/I18N", "") -- version without /I18N --	get.versionI18N = get.lessI18N .. "/I18N" -- eventual /I18N module to search get.nowstamp = os.date("%Y%m%d%H%M%S") -- YYYYMMDDhhmmss from module if get.isLibrary then get.revistamp = "20010101000000" -- default libraries timestamp at 2000-01-01T00:00:00Z, see ISO 8601 time format else get.revistamp = mw.getCurrentFrame:preprocess( "" ) end -- Special for isModule, isLibrary, isFunction get.versionName = string.gsub(get.title or "", centre.ModuleNS, "") -- full version name with perhaps /I18N get.simplename = string.gsub(get.title or "", centre.ModuleNS, "") -- delete "Module:" if any get.simplename = string.gsub(get.simplename, "/I18N", "") -- delete "/I18N" if any if type(module) == "function" then get.isFunction = true get.isModule = false get.isLibrary = false get.functionName = get.simplename get.alias = "function:" .. get.simplename elseif string.find(get.title, centre.ModuleNS) then -- If the module title begin with "Module:" get.isFunction = false get.isModule = true get.isLibrary = false get.moduleName = get.title -- complete the title with "Module:" get.subI18N = get.title .. "/I18N" -- eventual sub-module "/I18N" get.alias = centre.ModuleNS .. get.simplename if get.isI18N then get.alias = get.alias .. "/I18N" end else -- If the module is a library get.isFunction = false get.isModule = false get.isLibrary = true get.libraryName = get.title -- standard library name get.subI18N = centre.ModuleNS .. "Library/" .. get.title .. "/I18N" -- eventual sub-module "/I18N" get.alias = "Library:" .. get.title -- get.simplename if get.isI18N then get.alias = get.alias .. "/I18N" end end -- stamp, date and time function days(stamp) -- approximate the number of days from 0000-01-01 local day = 0 if (type(stamp) == "string") and (string.len(stamp) > 7) then day = tonumber(string.sub(stamp,1,4)) * 365 + tonumber(string.sub(stamp,5,6)) * 30 + tonumber(string.sub(stamp,7,8)) end return day end if get.revistamp then get.days_revis = days(get.revistamp) get.days_now = days(get.nowstamp) get.delay = get.days_now - get.days_revis get.revistime = tools.str_vars("%1-%2-%3 %4:%5",			string.sub(get.revistamp,1,4), string.sub(get.revistamp,5,6),			string.sub(get.revistamp,7,8), string.sub(get.revistamp,-6,-5), string.sub(get.revistamp,-4,-3) ) get.shortdays = string.sub(get.revistamp or "", 3, 8) get.shorttime = string.sub(get.revistime or "", -9, -1) if get.delay < 25 then get.shortVersion = "v" .. get.shorttime -- short version in "vDD hh:mm" until around 25 days else get.shortVersion = "v" .. get.shortdays -- later in date vYYMMDD end get.versionDate = get.revistime get.versionNumber = get.shortVersion end if get.versions then get.sought = get.versions.sought or get.versions.selector or "" get.known = get.versions.known or get.versions.all_versions or "" --		local str = string.gsub(get.sought, " ", ",") get.sought_tab = mw.text.split(str, ",", true) get.sought_count = #get.sought_tab --		local str = string.gsub(get.known, "*", ",") get.known_tab = mw.text.split(str, ",", true) get.known_count = #get.known_tab end --[ [	if get.hasi18n then --	version with internal .i18n ( module or its /I18N submodule ) local st, vr, fn, tb = tools.luatablecount(get.i18n, "i18n") -- count of internal .i18n get.i18n_text = st		get.i18n_vars = vr		get.i18n_func = fn		get.i18n_tabs = tb		-- get.i18n_varstabs = tools.str_vars("%1 texts in %2 languages", get.i18n_vars, get.i18n_tabs ) local st2, vr2, fn2, tb2 = tools.luatablecount(centre.maini18n, "maini18n") -- count of maini18n get.maini18n_text = st2 get.maini18n_vars = vr2 get.maini18n_func = fn2 get.maini18n_tabs = tb2 vr2 = vr2 or 0 tb2 = tb2 or 0 local vr_tb = 0 if tb2 == 0 then vr_tb = 0 else vr_tb = tonumber(vr2 / tb2) end vr2 = math.floor( vr_tb ) -- texts number in one language --	if type(txt) ~= "string" then txt = "tools_maini18n_languages_list" end get.i18n_varstabs = tools.str_vars("%1 texts in %2 languages, (all %3/%4)", get.i18n_vars, get.i18n_tabs, vr2, tb2) end --] ] centre.trackallversions("get_module_and_time " .. get.versionName, get.all_versions) return get, module --	get = { isTitled, title, module, isLoaded, isLibrary, hasi18n, versionName, versionTitle, versionDate, versionNumber, shortVersion, --			i18n, versions, sought, known, sought_tab, sought_count, known_tab, known_count, , --			isModule, isI18N, lessI18N, versionI18N, nowstamp, revistamp, revistime, shortdays, shorttime, nowstamp, delay } -- title = Module:Central, revistamp = 20151207214027, revistime = 2015-12-07 21:40, gettitle = Module:Author3, shortVersion = v07 21:40 or v150227 end -- get, module = function centre.get_module_and_time(title) -- Get a descriptor of one loaded object

function centre.get_loaded_modules(tab) -- List all package.loaded modules local loaded_txt = "" local loaded_pack = {} local elem = {} local tab_to_report = package.loaded centre.loaded_descriptors = {} local title, revistamp, revistime if type(tab) == "table" then tab_to_report = tab end local loaded_txt_memo = loaded_txt for title, module in pairs(tab_to_report) do -- List package.loaded modules local md = string.find(title, centre.ModuleNS) if (type(module) == "table") then -- md and local get = centre.get_module_and_time(title, module) loaded_txt = loaded_txt .. " '''" .. (get.title or "") .. "''', "		--	elem.title = title --	centre.trackallversions("loaded_modules", get.known) loaded_pack = centre.add_tab_elem_to_sort(loaded_pack, title, get) end end if loaded_txt == loaded_txt_memo then loaded_txt = loaded_txt .. "The input table contains no module." end -- centre.loaded_descriptors = loaded_pack return loaded_pack, loaded_txt end -- function centre.get_loaded_modules

function centre.transdiff(trans1, trans2) -- Collect all differences of translations centre.translations_differences = centre.translations_differences or {} if trans1.dtrans and trans2.dtrans and (trans1.dlang == trans2.dlang) and (trans1.dkey == trans2.dkey) and (trans1.dtrans ~= trans2.dtrans) then table.insert(centre.translations_differences, { ["trans1"] = trans1, ["trans2"] = trans2 }) -- build a table with only languages codes end -- Only fast collect to treat later if needed. end

--	Cumulate translations from modules or their /I18N sub-modules. --	Add or replace translations texts or new languages in the centre.maini18n table. function centre.addi18n(t, module_name, module_tab) t = t or "" centre.maini18n = centre.maini18n or {} local i18n, lang_N, text_N = {} ,0, 0 if type(module_tab) == "table" and type(module_tab.i18n) == "table"	 then -- and type(module_tab.i18n) == "table" then i18n = module_tab.i18n or {} -- i18n --	st, vr3, fn, tb = tools.luatablecount(i18n, "tab 3") lang_N, text_N = 0, 0 for lang, trans in pairs(i18n) do -- For all languages of the mixed module or library if centre.maini18n[lang] then -- the language already exists, add or replace imported fields lang_N = lang_N + 1 if type(trans) == "table" then -- if the language to add is really in a table for key, val in pairs(trans) do -- For all imported fields centre.transdiff( -- Collect all differences of translations							{ dlang = lang, dkey = key, dfile = "previous", dtrans = centre.maini18n[lang][key] },							{ dlang = lang, dkey = key, dfile = module_name, dtrans = val} ) centre.maini18n[lang][key] = val -- add or replace a field and its translation text_N = text_N + 1 end end t = t .. tools.str_vars(", lang:%1:%2:%3 ", lang, lang_N, text_N) else -- add the table and all is fields if it is not already in centre.maini18n if mw.language.isKnownLanguageTag(lang) then -- only for languages known in wikis lang_N = lang_N + 1 centre.maini18n[lang] = mw.clone(trans) text_N = text_N + #trans t = t .. tools.str_vars(", lang:%1:%2:%3 ", lang, lang_N, text_N) end end end end local st, vr, fn, tb = tools.luatablecount(centre.maini18n, "centre.maini18n") t = t .. tools.str_vars(", addi18n:%1:%2/%3 texts/langs, ", module_name, vr, tb) -- versionversion, lang:tot = ta:0 mix:Central1:441+3181=3181, return t, lang_N, text_N -- t, ln, an end -- function centre.addi18n(t, module_name, module_tab)

function centre.new_library(name, library, options) -- Record a library in package.loaded local err = "OK" -- RunOnce : Do not repeat this function to not disturb subsequent processes. if type(name) == "string" then if type(package.loaded[name]) ~= "nil" then return package.loaded[name], "" -- This library already exists, return it else end -- record the new_library below. else -- RunOnce return nil, "INTERNAL ERROR : new_library name is not a string." -- minimal answer in case of abnormal name. end -- RunOnce --	if type(name) ~= "string" then library = nil ; err = "name is not a string" end -- A library name must be a string. if library == nil then return centre "INTERNAL ERROR : new_library is not an object." end -- A new temporary library must be a table. if package.loaded[name] then library = nil ; err = "cannot replace a previous library" end -- A library cannot replace a previous library. -- below: A library name must be a string in %w ASCII alphanumeric characters only. With ":" for modules. local correctname = string.gsub(name, "[^:./%w]", "" ) if name ~= correctname then library = nil ; err = "name with forbiden characters -> " .. correctname end php = nil -- Remove setup function if library then library.setupInterface = nil end -- Copy the PHP callbacks to a local variable, and remove the global php = mw_interface mw_interface = nil -- Do any other setup here -- Install into the mw global mw = mw or {} mw.ext = mw.ext or {} mw.ext[name] = library -- Indicate that we're loaded package.loaded[name] = library --	package.loaded['mw.ext.' .. name] = library return library, err end -- function centre.new_library(name, library, options)

function centre.bindlibraries -- Bind translatable libraries before bind modules and versions. -- Record centralisable libraries if they are not included in standard mw.Extension:Scribunto -- RunOnce : Do not repeat this function to not disturb subsequent processes. tools.tracki18n("start.bind_libraries") centre.new_library("centre", centre) -- RunOnce tools.tracki18n("new_library:centre", centre) centre.new_library("tools", tools) -- RunOnce tools.tracki18n("new_library:tools", tools) centre.new_library("mathroman", mathroman) -- RunOnce tools.tracki18n("new_library:mathroman", mathroman) local name, name_I18N, tt, lang_N, text_N local nm = " Libraries after new_library in bind_libraries : " for name, library in pairs(package.loaded) do nm = nm .. name .. ", " end centre.tracki18n_new_libraries123 = nm or "no library in package.loaded" local t = "" t = t .. "\n* effective centre.bindlibraries : " centre.loaded_modules = centre.get_loaded_modules -- List all libraries with internal .i18n translations for title, get in pairs(centre.loaded_modules) do	--	if package.loaded[name] and package.loaded[name].i18n then if get.hasi18n and get.isLibrary then t = t .. "\n*" .. tools.ta("get.libraryName", get.libraryName) -- .. tools.ta("library", get.module) -- tools.ta("get.title", get.title) .. tools.ta("get.moduleName", get.moduleName) .. tt, lang_N, text_N = centre.addi18n(t, get.libraryName, get.module) t = t .. tools.form_i18n_counts(get.i18n, " + %1/%2, ") -- N translations/languages -- (get.libraryName or get.moduleName or "missing") .. t = t .. tools.form_i18n_counts(centre.maini18n, " all = %1/%2, ") -- N translations/languages t = t .. "\n*" .. tools.ta("get.subI18N", get.subI18N) -- .. tools.ta("name", get.libraryName) -- .. tools.ta("name_I18N", name_I18N) local getI18N = centre.get_module_and_time(get.subI18N) tt, lang_N, text_N = centre.addi18n(t, getI18N.subI18N, getI18N.module) if getI18N.libraryName then -- getI18N.i18n and	 -- addi18n eventual sub-module "/I18N" t = t .. "\n*" .. tools.ta("I18N", getI18N.libraryName) -- .. tools.ta("name_I18N", name_I18N) t = t .. tools.form_i18n_counts(getI18N.i18n, getI18N.libraryName .. " LB18+ %1/%2, ") -- Count available translations and languages t = t .. tools.form_i18n_counts(centre.maini18n, " all+ %1/%2, ") -- N translations/languages end end end tools.tracki18n("end.bind_libraries") centre.bind_i18n_report = (centre.bind_i18n_report or ".") .. (t or ".") return t end -- function centre.bindlibraries

-- local tt, vers_test = centre.bindmodules(p, vers_test) -- The main module can bind all its sub-modules versions, and their /I18N sub-modules. function centre.bindmodules(main_p, vers_test) local centre_maini18n_memo = centre.maini18n local tools_args_source_memo = tools.args_source local tools_args_config_memo = tools.args_config tools.args_source = new_source tools.args_config = args_config -- Bind all modules and versions, and their translations -- vers_test and loaded_versions are only for tests -- centre.bind_libraries -- Bind translatable libraries before bind modules and versions. centre.T122752_detect_correct(t) -- Correct the bug T122752 : #invoke do not record the main module in package.loaded local t = "\n*centre.bindmodules start, effective Search the main module: " -- Waiting the debug of T119978 Get the own module name and last record date-time from each module --	centre.main_versions = nil --	centre.main_module = nil local main_module = nil -- To get first local main_versions = nil local versions = nil local title = nil local gettitle = mw.getCurrentFrame:getTitle -- get the mainmodule title local package_loaded_gettitle = package.loaded[gettitle] centre.main_gettitle = gettitle t = t .. tools.ta("gettitle", gettitle) main_p = main_p or centre.T122752_main_module -- waiting debug of T122752 module found module.versions.sought -- Normal process if type(main_p) == "table" then -- A module can lauch itself or another as main module. main_module = main_p t = t .. tools.ta("main_p", main_p) if type(main_p) == "table" and type(main_p.versions) == "table" then -- For main modules using versions management title = centre.ModuleNS .. main_p.versions.versionName centre.main_p_versions_txt = "main_p.versions : " .. tools.ta("main_p.title", title) .. tools.ta("main_p.versionNumber", main_p.versions.versionNumber) .. tools.ta("main_p.sought", main_p.versions.sought) .. tools.ta("main_p.known", main_p.versions.known) end elseif type(package_loaded_gettitle) == "table" then -- If #invoke has already loaded the main module in package.loaded --		local maini18n_memo = mw.clone(centre.maini18n) main_p = package_loaded_gettitle main_module = main_p t = t .. "\n* main module from gettitle : correct T122752 '''" .. tostring(gettitle) .. "'''. "		if type(main_p) == "table" and type(main_p.versions) == "table" then -- For main modules using versions management centre.gettitle_versions_txt = "getTitle.versions : " .. tools.ta("getTitle.versionName", main_p.versions.versionName) .. tools.ta("getTitle.versionNumber", main_p.versions.versionNumber) .. tools.ta("getTitle.sought", main_p.versions.sought) .. tools.ta("getTitle.known", main_p.versions.known) end else -- If the main module was not recorded in package.loaded, try to require it. --		local module = centre.pcallrequire(gettitle) -- require must not fail and block the page. if module then-- Alert by a message in edit mode: the bug is already fixed. local maini18n_memo = centre.maini18n main_p = module main_module = main_p t = t .. "\n* main module from gettitle : repairs T122752 '''" .. tostring(gettitle) .. "'''. "		else -- The main module called this module, but something else is in error. --			local maini18n_memo = centre.maini18n main_p = p			main_module = main_p t = t .. "\n* main module from gettitle : not found '''" .. tostring(gettitle) .. "'''. "		end -- If not loaded, return only get.isTitled and get.title end -- After get the main module, get the versions for management. -- The main module can use or not the versions management. if type(main_p) == "table" and type(main_p.versions) == "table" then -- For main modules using versions management main_module = main_p t = t .. tools.ta("centre.main_module", centre.main_module) main_versions = main_p.versions t = t .. tools.ta("centre.main_versions", centre.main_versions) end if not main_module then -- The main module is not found. return tools.error_color( tools.str_vars("tools_main_module_missing_err") ) end centre.maini18n = centre_maini18n_memo -- Restore from centre.bindlibraries tools.args_source = tools_args_source_memo -- Restore from tools.args_config_init tools.args_config = tools_args_config_memo -- Restore from tools.args_config_init -- In normal cases if type(centre) == "table" and type(centre.main_gettitle) == "string" then main_versions.versionName = string.gsub(centre.main_gettitle, centre.ModuleNS, "") -- without Module: end --	if (type(vers_test) == "table") then -- In tests cases main_module.versions = vers_test -- In versions management test, vers_test replace the main versions main_versions = main_module.versions main_versions.used = "," end t = t .. " " .. tools.ta("main_module", main_module) .. tools.ta("main_versions", main_versions) t = t .. " BEFORE sought, known, versionName, versionNumber, version, main_module : " local versionName, versionNumber, sought, known if type(main_module) == "table" and type(main_versions) == "table" then -- Verify main module and versions management ability. sought = main_versions.sought known = main_versions.known versionName = main_versions.versionName versionNumber = main_versions.versionNumber t = t .. tools.ta("main_module", main_module) .. tools.ta("main_versions", main_versions) t = t .. tools.ta("sought", sought) .. tools.ta("known", known) t = t .. tools.ta("versionName", versionName) .. tools.ta("versionNumber", versionNumber) end t = t .. " AFTER sought, known, versionName, versionNumber, version, main_module : " centre.bindmodules_start = t	if type(main_versions.sought) == "string" and type(main_versions.known) == "string" then known = main_versions.known sought = main_versions.sought end t = t .. "\n*bindmodules starts: " local sought_t = string.gsub(main_versions.sought or sought or "", " ", ",") -- "," .. .. ","	local sought_tab = mw.text.split(sought_t, " ", true) local sought_maxn = table.maxn(sought_tab) --	local known_tab = mw.text.split(main_versions.known or known or "", "*", true) local known_maxn = table.maxn(known_tab) -- local known_maxn = #known_tab local used = "," local t = "" t = t .. "\n* effective centre.bindmodules : " .. tools.ta("main_versions.versionName", main_versions.versionName) .. tools.ta("main_versions.sought", main_versions.sought) .. tools.ta("sought_maxn", sought_maxn) .. " " .. tools.ta("main_versions.known", main_versions.known) .. tools.ta("known_max", known_max) for i = known_maxn, 1, -1 do -- alternatives = known_tab[i] alternatives = known_tab[i] alternatives = "," .. mw.text.trim(alternatives) .. "," -- normalize versions between "," alternatives = tools.compact_comma_list(alternatives) local altern_tab = mw.text.split(alternatives, ",", true) local elem, module, normal, alias, name_I18N for v, altern in ipairs(altern_tab) do			normal = "" ; version = "" altern = tostring(altern) altern = mw.text.trim(altern) if v == 1 and tools.is_in_sp(altern, sought, ",") then normal = altern kind = "normal" end if v > 1 and tools.is_in_sp(altern, sought, ",") then version = altern kind = "version" end local name_mod, name_I18N, tt, lang_N, text_N, get_i18n, getI18N if vers_test then -- In versions management test if tools.is_in_sp(altern, vers_test.loaded_list, ",") then used = (used or "- ") .. altern .. ", "				end name_I18N = altern .. "/I18N" else -- In normal run -- addi18n from te module itself get_i18n = centre.get_module_and_time(centre.ModuleNS .. altern) tt, lang_N, text_N = centre.addi18n(t, get_i18n.subI18N, get_i18n.module) if get_i18n.moduleName then -- get_i18n.i18n and	 -- addi18n eventual sub-module "/I18N" t = t .. "\n*" .. tools.ta("I18N", get_i18n.moduleName) -- .. tools.ta("name_I18N", name_I18N) t = t .. tools.form_i18n_counts(get_i18n.i18n, get_i18n.moduleName .. " MD+ %1/%2, ") -- Count available translations and languages t = t .. tools.form_i18n_counts(centre.maini18n, " all+ %1/%2, ") -- N translations/languages end end if vers_test then -- In versions management test if tools.is_in_sp(name_I18N, vers_test.loaded_list, ",") then used = (used or "- ") .. name_I18N .. ", "				end else -- In normal run -- addi18n from the sub-module /I18N getI18N = centre.get_module_and_time(get_i18n.subI18N) alias = getI18N.alias tt, lang_N, text_N = centre.addi18n(t, getI18N.subI18N, getI18N.module) if getI18N.moduleName then -- getI18N.i18n and	 -- addi18n eventual sub-module "/I18N" t = t .. "\n*" .. tools.ta("I18N", getI18N.moduleName) -- .. tools.ta("name_I18N", name_I18N) t = t .. tools.form_i18n_counts(getI18N.i18n, getI18N.moduleName .. " MDI18N+ %1/%2, ") -- Count available translations and languages t = t .. tools.form_i18n_counts(centre.maini18n, " all+ %1/%2, ") -- N translations/languages end end centre.track_i18n_vers = (centre.track_i18n_vers or "") .. tools.ta("Module:", (alias or "-") .. ", / " .. (normal or "-") .. " / " .. (version or "-") ) end -- for v, altern in ipairs(altern_tab) do	end -- for i = known_maxn, 1, -1 do -- alternatives = known_tab[i] local word, errs = "", "" if type(vers_test) == "table" then -- In tests run -- Versions management errors from overall look on modules local alloncesort = tools.compact_comma_list(vers_test.sought .. "," .. vers_test.known .. "," .. vers_test.used) -- .. "," .. loaded_report)	--	alloncetab = mw.text.split(alloncesort, ',') -- table of words		for i, name in ipairs(alloncetab) do -- list all used names, only one each, in alphabetic order			if tools.is_in_sp(name, vers_test.sought, ",") and not tools.is_in_sp(name, vers_test.known, ",") then				errs = errs .. tools.err_add("tools_missing_versions_err", name, vers_test.versionName ) -- new			--	tools_missing_versions_err		= "The module %1 misses in the main module %2.",			end			if tools.is_in_sp(name, vers_test.used, ",") and not tools.is_in_sp(name, vers_test.sought, ",") then				vers_test.replaced = vers_test.replaced .. name .. "," -- sought but not found				errs = errs .. tools.err_add("tools_replaced_versions_err", name, vers_test.versionName ) -- new			--	tools_replaced_versions_err		= "The module %1 replaces the missing module in the main module %2.",			--	tools_select_unknown_module_err = "Internal error: The missing Module:%1 is replaced by the normal Module:%2.", -- versionsmanagement end if tools.is_in_sp(name, vers_test.alloncesort, ",") and not tools.is_in_sp(name, vers_test.known, ",") then vers_test.unknown = vers_test.unknown .. name .. "," -- sought but not found errs = errs .. tools.err_add("tools_unknown_versions_err", name, vers_test.versionName ) -- new --	tools_unknown_versions_err		= "The module %1 is unknown in the main module %2.", end end -- for v, altern in ipairs(altern_tab) do	end main_versions.used = used if not (type(vers_test) == "table") then -- In normal run centre.main_module = main_module -- In normal cases and not in tests cases centre.main_versions = mw.clone(main_versions) -- In normal cases and not in tests cases end --	local loaded_pack = loaded_pack or centre.get_loaded_modules -- List all package.loaded modules			normal t = t .. "\n* centre.bindmodules END : " .. tools.ta("main_versions.used", main_versions.used) .. tools.ta("#loaded_pack", #loaded_pack) centre.bindmodules_start = t	centre.required_descriptors = loaded_pack centre.bind_i18n_report = (centre.bind_i18n_report or ".") .. (t or ".") return t, main_versions -- loaded_pack, centre.track_i18n_vers end -- function centre.bindmodules(main_p, vers_test) -- Bind all modules and versions and translations

function centre.add_tab_elem_to_sort(tab, name, elem) -- Add an element to a table, with an index to permit later to sort the table in the insert order if not (type(tab) == "table") then tab = {} end if (type(tab) == "table") and (type(name) == "string") and (type(elem) == "table") then tab[name] = elem elem.elem_index_order = #tab -- order of insert end return tab end -- function centre.add_tab_elem_to_sort(tab, name, elem)

-- for loaded_descriptors and other function centre.sort_table_in_insert_order(tab) -- Sort a table in the insert order of its elements, previously adapted if not (type(tab) == "table") then tab = {} end local tab_to_sort = mw.clone(tab) or {} table.sort(tab_to_sort, function (a, b) -- in recording order		return	( a.elem_index_order < b.elem_index_order )	end ) return tab_to_sort end -- function centre.sort_table_in_insert_order(tab)

function centre.tab_elem_report(tab, key) -- simple text report of versions elements mode = mode or 1 local t = "" if (type(tab) == "table") and (type(key) == "number") then for i, elem in ipairs(tab) do t = t .. "\n* " .. tools.ta("i", i) .. tools.ta("title", elem.title) t = t .. tools.ta("versionName", elem.versionName) .. tools.ta("versionNumber", elem.versionNumber) t = t .. tools.ta("versionDate", elem.versionDate) .. tools.ta("i18n_varstabs", elem.i18n_varstabs) end end if (type(tab) == "table") and (type(key) == "string") then for k, elem in pairs(tab) do			if not tonumber(key) then t = t .. "\n* " .. tools.ta(key, k) t = t .. tools.ta("versionName", elem.versionName) .. tools.ta("versionNumber", elem.versionNumber) t = t .. tools.ta("versionDate", elem.versionDate) .. tools.ta("i18n_varstabs", elem.i18n_varstabs) end end end return t end -- function centre.tab_elem_report(tab, key)

centre.track_i18n_vers = (centre.track_i18n_vers or "")

centre.trcPVG_txt = " trcPVG loaded_pack/loaded_vers/loaded_G " function centre.trcPVG(id, loaded_pack, loaded_vers, loaded_G) --	centre.i18n_trc = centre.i18n_trc .. " '''" .. (id or "") .. "''' t=" .. (t or "") local p, P, v, V, g, G = 0, 0, 0, 0, 0, 0 loaded_pack = loaded_pack or centre.loaded_pack loaded_vers = loaded_vers or centre.loaded_vers loaded_G = loaded_G or centre.loaded_G for i, elem in pairs(loaded_pack or centre.loaded_pack or {} ) do		p = p + 1 if elem.isI18N then P = P + 1 end end for i, elem in pairs(loaded_vers or centre.loaded_pack or {} ) do		v = v + 1 --	if elem.isI18N then V = V + 1 end end for i, elem in pairs(loaded_G or centre.loaded_pack or {} ) do	--	g = g + 1 --	if elem.isI18N then G = G + 1 end end centre.trcPVG_txt = (centre.trcPVG_txt or "") .. tools.str_vars("%1 = %2.%3/%4.%5/%6.%7 ", id, p, P, v, "", g, "") return end -- function centre.trcPVG(id, loaded_pack, loaded_vers, loaded_G)

function centre.version_warning_normal_list(d) -- From alternatives forms version, title, alias, warning, normal local d = d.versions or centre.versions or {} -- descriptor of submodule --	example of d.alternatives = "Central,CA,Central1,Central3" if type(d.alternates) == "string" then d.alternates = mw.text.trim(d.alternates) end if not d.alternates then d.alternates = "" ; return d	end local altern_tab = mw.text.split(d.alternates, ",", true) local version, alias, normal for v, altern in ipairs(altern_tab) do		altern = mw.text.trim(altern) if v == 1 and tools.is_in(altern, d.selector) then normal = altern ; version = altern end if v == 2 and tools.is_in(altern, d.selector) then normal = altern ; version = altern end if v > 2 and tools.is_in(altern, d.selector) then version = altern end end if version then d.version = string.gsub(version, centre.ModuleNS, "") -- version without Module: d.title = centre.ModuleNS .. d.version d.normal = normal d.normal_I18N = centre.ModuleNS .. normal .. "/I18N" d.normal_I18N = string.gsub(d.normal_I18N, "/I18N/I18N", "/I18N") d.version_I18N = centre.ModuleNS .. version .. "/I18N" d.version_I18N = string.gsub(d.version_I18N, "/I18N/I18N", "/I18N") d.alias = alias if d.normal and not tools.is_in(d.normal, d.norm or " ") then d.norm = (d.norm or " ") .. " " .. d.normal .. " " end if d.version and not tools.is_in(d.version, d.list or " ") then d.list = (d.list or " ") .. " " .. d.version .. " " end if d.normal_I18N and package.loaded[d.normal_I18N] and not tools.is_in(d.normal_I18N, d.list or " ") then d.list = (d.list or " ") .. " " .. d.normal_I18N .. " " end if d.version_I18N and package.loaded[d.version_I18N] and not tools.is_in(d.version_I18N, d.list or " ") then d.list = (d.list or " ") .. " " .. d.version_I18N .. " " end --	d.missing = d.missing .. " " .. d.version .. " " -- managed elsewhere --	d.excess = d.excess .. " " .. d.version .. " " -- managed elsewhere end return d end -- function centre.version_warning_normal_list(d)

function centre.modules_binder_raz(calling_module) -- raz excess _G local v, d = centre.versions, d or centre.d or {} -- descriptor of submodule local all_versions -- Along the init process : First step, the main_versions execute : require ("Module:XYZ") d.N_submodules = 0 if type(d.all_versions) == "string" then -- Cut and trim d.all_versions_split = mw.text.split(d.all_versions, "*", true) d.N_submodules = table.maxn(d.all_versions_split) end for i = 1, d.N_submodules do		d.alternates = d.all_versions[i] d.alternates = mw.text.trim(d.alternates) d = v.version_warning_normal_list(d) -- From alternatives forms version, title, alias, warning, normal if d.title then -- if submodule realy required _G[d.alias] = nil _G[d.title] = nil _G[d.version] = nil end end d.missings = "" ; d.unknowns = "" ; d.normals = "" ; d.listall = "" ; d.selectall = "" ; d.warnings = "" ; d.loaded_list = "" ; d.excess = "" ;	d.aliases = "" ; v.d = d	return d end -- function centre.modules_binder_raz(calling_module)

-- Detect the task T122752 : #invoke seems do not record the module local task_T122752_state = "triage" -- default value, at Require time local task_T122752_gettitle = mw.getCurrentFrame:getTitle -- get the mainmodule title if type(package.loaded[task_T122752_gettitle]) == "table" -- get task state at Require time then task_T122752_state = "OK" else task_T122752_state = "triage" end -- Detect T122752 : #invoke seems do not record the module

function centre.task_T122752_get_state -- Detect T122752 : #invoke seems do not record the module local gettitle = mw.getCurrentFrame:getTitle -- get the mainmodule title if task_T122752_state then return end if type(package.loaded[gettitle]) == "table" then task_T122752_state = "OK" else task_T122752_state = "triage" end end

-- To locate and to debug the bug T122752 in time, Rical lists here the versions of fr.wikisource.org/wiki/Module:ControlArgs1 -- Oldest research of "Replace the missing of record of the module by" : ModuleControlArgs 6 tools...lua 2016-01-16 -- (actu | diff) 2015-11-25T11:43:11‎ Rical (discussion | contributions | bloquer)‎. . (261 314 octets) (-3 519)‎. . (The versions management seems OK) (annuler) -- (actu | diff) 2015-11-28T09:55:37‎ Rical (discussion | contributions | bloquer)‎. . (267 472 octets) (+5 809)‎. . (find_main_module) -- (actu | diff) 2015-12-01T14:18:22‎ Rical (discussion | contributions | bloquer)‎. . (268 956 octets) (+1 614)‎. . (find_main_module OK ?) -- (actu | diff) 2016-01-18T02:09:45‎ Rical (discussion | contributions | bloquer)‎. . (319 599 octets) (+10 183)‎. . (translate library.i18n first)

function centre.T122752_detect_correct(t) -- Bypass the bug T122752 : #invoke do not record the main module in package.loaded -- When the parser build a wiki page, it do 	-- Because the bug T122752 : #invoke do not record the main module in package.loaded -- but the MainModule is active and require("Module:Central") -- Then	 centre.T122752_detect_correct verify centre.T122752_status -- before centre.bindmodules bind all modules and versions, and their translations local t = t or "" local gettitle = mw.getCurrentFrame:getTitle -- get the mainmodule title centre.main_gettitle = gettitle local module if type(package.loaded[gettitle]) == "table" then centre.T122752_status = "Resolved" else centre.T122752_status = "getmodule" -- "Open" module = centre.pcallrequire(gettitle) -- require must not fail and block the page if the module do not exists. if module then -- Alert? by a message in edit mode: the bug is already fixed. centre.T122752_main_module = module centre.T122752_status = "module found" -- "Open" --	t = t .. tools.str_vars("tools_try_waits_debug_T122752", tostring(gettitle) ) .. "#invoke T122752 replaced by pcallrequire." t = t .. "\n* T122752_detect_correct: repairs the main '''" .. tostring(gettitle) .. "'''. See: T122752 #invoke seems do not record the module " if type(package.loaded[gettitle]) == "table" then centre.T122752_status = "get corrected Resolved" end else centre.T122752_status = "module missing" -- "Open" -- Main error, there is no main module. end end centre.T122752_status = centre.T122752_status or "nil status" -- "Open" return t end -- function centre.T122752_detect_correct(t) -- Bypass the bug T122752 : #invoke do not record the main module in package.loaded

function centre.init(frame, args_known, mode_name, options_for_modes, itemid) -- Initializes translations, bindlibraries, bindmodules, get arguments, modes, options. -- Imports arguments from wikidata, module and template with increasing priorities. local res = "" tools.time1 = os.clock tools.module_init(frame) -- Get tools.args_source with tools.args_config tools.init_wiki_user_lang(tools.args_config.wikilang, tools.args_config.userlang) -- init user and the wiki languages from args tools.init_tools(frame, options_for_modes) -- Needed to init categories and errors res = res .. centre.bindlibraries -- Install central libraries, waiting true central libraries. --	centre.bindmodules(p) --	tools.tasks_table_report_full = tools.tasks_table_report --	tools.tasks_table_report_short = "\n*" .. tools.tasks_table_report("Tasks list and their states:", "short") centre.bindmodules tools.module_init(frame) -- Get tools.args_source with tools.args_config res = res .. "\n* p.init centre.bindlibraries centre.bindmodules : " res = res .. "\n* " .. (centre.bind_i18n_report or ".") res = res .. tools.tracki18n("after centre.bindmodules", tools) local mode_name, source_key, try_lang = tools.get_arg_mode(mode_name, source_key, try_lang, args_source) tools.mode_name = mode_name or tools.mode_name or "read" tools.init_wiki_user_lang(tools.args_config.wikilang, tools.args_config.userlang) -- init user and the wiki languages from args local args_known = args_known or tools.args_known if type(args_known) == "table" then tools.args_known = args_known end local dockey = tools.args_config.dockey -- or tools.args_config[1] local itemid = itemid or tools.args_config.itemid -- or tools.args_config.id or tools.args_config[2] tools.init_tools(frame, options_for_modes) -- Raz categories and errors before full translations local mode_name = tools.get_arg_mode(mode_name, source_key) tools.change_itemid -- "Q41568" tools.args_wikidata, t = tools.import_wikidata(tools.args_known, itemid) tools.tracki18n("after import_wikidata", tools.main_module) tools.time2 = os.clock tools.options_for_modes = options_for_modes if type(tools.args_config.c) == "string" then tools.invoke_options = tools.args_config.c	end if type(tools.args_config.mode) == "string" then mode_name = tools.args_source.mode end tools.invoke_options = tools.args_source.c or "" tools.mode_options = tools.options_from_mode(source_mode_name or mode_name) tools.args_import, t = tools.import_arguments local mode_name = tools.get_arg_mode -- (mode_name, source_key) --	tools.report_bind_verif_modules_details = tools.bindmodules_report -- Report all modules installation tools.bindmodules_report -- Report all modules installation tools.tasks_table_report_full = tools.tasks_table_report tools.tasks_table_report_short = "\n*" .. tools.tasks_table_report("Tasks list and their states:", "short") return res end -- function centre.init(frame, args_known, mode_name, options_for_modes, itemid)

-- End of Library:centre.

-- --	Install Library:tools --	This library support modules to: --	* Form parametrable strings --	* Translate parametrable texts, in wiki and user languages --	* Add a language needs only to add its own i18n subtable, like i18n.en = {} --	* Errors and messages: form one, collect them, display one or them --	* Categories: form one or a group of categories. Collect, display and activate categories --	* Support the bilingual categories, displaying in user language and linking in wiki language. -- --	Libraries dependencies: --	This Library:tools needs the Library:centre --	The Library:mathroman and the Module:Author3 depend of this library. --

--	local ctz = centre -- Share it under a local shortcut to distinct the definition and the use.

tools = {} tools.i18n = {}

tools.i18n.en = { -- Names and descriptions of configurations arguments [1]								= "1",	[2]								= "2",	[3]								= "3",	[4]								= "4",	label							= 'label', label_descr						= "Automatic Wikidata argument.", sitelink						= 'sitelink', sitelink_descr					= "Automatic Wikidata argument.", userlang						= "userlang", userlang_descr					= "Language of the user or the helper.", wikilang						= "wikilang", wikilang_descr					= "Language of the wiki.", itemid							= 'itemid', itemid_descr					= "Identifier of Wikidata data, such as  for Victor Hugo.", itemid2							= 'id', itemid2_descr					= "Identifier of Wikidata data, such as  for Victor Hugo.", debug							= 'debug', category						= 'Category', mode							= "mode", mode_descr						= "Type of use of the module or template: read, edit, document, test.", options							= "options", options_descr					= "Display options of a module or a model.", c								= "c", c_descr							= "Display options of a module or a model.", knownversions					= "knownversions", knownversions_descr				= "Known versions, to manage them.", soughtversions					= "soughtversions", soughtversions_descr			= "Sought versions, to manage them.", -- Groups of arguments tools_needed_to_verify			= "(required, to be checked)", tools_list_needed_args			= "List of needed arguments:", tools_list_all_config_arguments	= "List of all config arguments:", tools_list_all_system_arguments	= "List of all system arguments:", tools_list_all_other_args		= "List of all other arguments:",

-- Main texts, errors and categories of tools language							= 'language', tools_user_wiki_lang_msg			= "Languages: user: %1, wiki: %2.", tools_DropBox_label_Unwrap			= "Unwrap/Wrap", tools_language_cat					= 'Speaking %1', tools_date_months_names				= "January, February, March, April, May, June, July, August, September, October, November, December", tools_date_to_part_format			= "dd yyyy mmmm", tools_date_to_part_call_err			= "Internal Error: Abnormal calling arguments in date %1.", tools_date_to_part_call_cat			= "Module with internal error", tools_date_to_part_not_found_err	= "Internal Error: No part found in date %1.", tools_test_OK_cat					= "Test category generation OK", tools_module_usage_error_cat		= "Module with usage error", tools_module_internal_error_cat		= "Module with internal error", tools_module_with_error_cat			= "Module with error", tools_module_with_error_err			= "Module with error",

-- Arguments management tools_error_list_header_err			= "User support about parameters:", tools_need_arg_value_err			= "Error: This argument is required but absent : %1. Should define it.", tools_none_value_err				= "Error: No argument has been defined.", tools_unknown_argument_err			= "Error: parameter %1 is unknown in this template. Check the name or flag this gap.", tools_too_unnamed_arguments_err 	= "Error: This unnamed argument is too many: %1 = %2.", tools_internal_notice_wsid_err		= "Internal Error: Notify the developer that the internal argument %1 is unknown in the records.", tools_without_translation_err		= "Known argument, but not translated: %1.", tools_without_translation_N_err 	= "There are %1 arguments untranslated.", tools_is_defined_err				= "The argument %1:%2 is defined.", tools_is_undefined_err				= "The argument %1:%2 is not defined.", tools_args_values_err				= "Abnormal value of the argument %1 = %2 including (%3) ", -- Wikidata tools_wikidata_wikibase_err			= "Error: Wikibase is not available.", tools_wikidata_getEntity_err		= "Error: getEntity Wikidata is not available.", tools_wikidata_getEntityObject_err	= "Error: Element Wikidata %1 is not found.", tools_wikidata_property_err			= "Error: Wikidata property %1 is not found.", tools_wikidata_error_err			= "Error Wikidata: %1 ", --	tools_wikidata_cat_err				= "Error Wikidata", tools_wikidata_cat_err				= "Module with internal error",	 -- tools_module_internal_error_cat tools_structured_data_txt			= 'Datas from Wikidata', tools_wikidata_any_page_title		= "Wikidata for any page:", tools_wikidata_details_test_title	= "Tests and imported datas from wikidata", tools_wikidata_arbitrary_test_title = "Test of Wikidata arbitrary access", tools_wikidata_arbitrary_access_text= "Wikidata for another Title: ", tools_wikidata_time_details			= "Wikidata time properties for more details", -- Versions management tools_versions_no_select_altern_err = "Versions error: no selection in the alternative %1 of the module %2.", tools_versions_too_select_altern_err= "Versions error: %1 selections in the alternative %2 of the module %3.", tools_versions_select_not_used_err	= "Versions error: %1 selector is not in alternative %2 of the module %3.", tools_versions_missing_module_err	= "Versions error: missing module for the version %1 of the module %2.", tools_main_module_missing_err		= "The main module is not found.", tools_select_unknown_module_err 	= "Internal error: The missing Module:%1 is replaced by the normal Module:%2.", tools_I18N_module_no_base_err		= "The %1 translations module has no basic version.", tools_no_versions_module_err		= "The module %1 is not in the system of versions.", tools_all_versions_tests			= "Versions warning: %1, normal: %2, listall: %3.", tools_all_versions_check			= "Versions: missings: %1, unknowns: %2, normals: %3, excess: %4, all selected: %5.", tools_missing_versions_err			= "The module %1 misses in the main module %2.", tools_replaced_versions_err			= "The module %1 replaces the missing sub-module in the main module %2.", tools_unknown_versions_err			= "The module %1 is unknown in the main module %2.",

-- Miscellaneous messages and errors tools_maini18n_languages_list		= "This module can translate %1 sentences in %2 languages: ", tools_nearest_argument_err			= "Error: Do you need the known argument %1 ?", tools_max_nearest_argument_msg		= "A longer name argument accepts more letter errors.", tools_value_re_defined_err			= "Error: The value of the argument %1 is already defined. Choose only one value of a single synonymous.", tools_table_listlimit_levelmaxi 	= "Level limit levelmaxi = %1 ", tools_table_listlimit_max_n			= "Length limit max_n = %1 ", tools_i18n_list_all_texts			= "This list show all the texts, but cannot replace the original declarations.", tools_languages_nbr_and_list		= "\n* There are %1 tables of translations in these languages : %2 ", tools_module_miss_i18n_txt_err		= "Internal Error: The text %1 lack of translation in %2 language, and/or others.", tools_module_miss_i18n_count_err	= "Internal Error: There are %1 missings in %2 translations.", tools_module_miss_i18n_none_err 	= "OK, none missing translations.", tools_texts_translated_in_langs 	= "There are %1 texts translated in %2 languages.", tools_module_miss_i18n_trad_err 	= "Internal Error: Module missing i18n translation for the argument %1 ", --	tools_err_module_miss_i18n_cat		= "Module missing i18n translation", tools_err_module_miss_i18n_cat		= "Module with internal error",	 -- tools_module_internal_error_cat tools_module_miss_i18n_mini_err 	= "Error: I18n table has only 1% translations.", --	tools_no_args_known_err				= "Error: Module without known arguments table.", --	tools_no_args_source_err			= "Error: Module without source arguments table.", tools_no_wiki_translations_err		= "Error: Module without translated arguments table.", tools_no_args_wikidata_err			= "Error: Module without wikidata arguments table.", tools_lang_table_err				= "Error: The %1 language or its table is incorrect.", --	tools_lang_table_err_cat			= "Module with erroneous language arguments", tools_lang_table_err_cat			= "Module with internal error",	 -- tools_module_internal_error_cat tools_lang_not_exist_err			= "Error: The language %1 is not available.", tools_lang_not_translated_err		= "Error: The language %1 is not translated.", tools_generDoc1_paramName_err		= "Internal Error: in generDoc1, bad argument %1.", tools_sources_of_datas				= "Informations from: /Wikidata, /template or module, /other, /message, /error", tools_list_in_translated_lang		= "\n* %1 translations in language %2 : %3 : %4", tools_luatable_counts				= "The table %1 counts %2 texts, %3 functions and %4 sub-tables.", tools_table_dont_exists_err			= "The table %1 does not exist.", tools_auto_val_unknown_err			= "Internal Error: Unknown automatic argument: %1 = %2.", --	tools_delete_docbox_msg				= "You must remove this documentation before recording. Remove all modes to return to read mode.", tools_auto_val_warning_msg			= "Verify the automatic argument: %1 = %2.", --	tools_assist_user_param_err			= "User support for checking the settings:", tools_module_error_err				= "Module with error.", tools_no_known_arguments_err		= "Module without known arguments table.", tools_unknown_auto_arg_err			= "Internal Error: Unknown automatic argument: %1 = %2.", tools_args_values_err				= "Abnormal value of the argument %1 = %2 (%3)", --	tools_no_known_arguments_err		= "Internal Error: Module without known arguments table.", --	tools_tools_no_known_args_cat		= "Module without known arguments table.", tools_tools_no_known_args_cat		= "Module with internal error",	 -- tools_module_internal_error_cat tools_no_source_arguments_err		= "Internal Error: Module without source arguments table.", --	tools_no_source_arguments_cat		= "Module without source arguments table.", tools_no_source_arguments_cat		= "Module with internal error",	 -- tools_module_internal_error_cat

-- Titles of tests tools_page_tests_h3_title			= "Tests of this page", tools_page_tests_title				= "Testing and information related to this page:", tools_internal_tests_h3_title		= "Internal tests", tools_internal_tests_title			= "Internal regression tests:", tools_dropdown_missing_title		= "Missing title for this dropbox", tools_used_options_title			= "Options and their uses:", tools_options_from_mode_title		= "Test options from modes", tools_options_from_args_title		= "Test options from arguments", tools_spaces_page_names_title		= "Module, namespaces, and page names:", tools_luatables_counts_title		= "Counts of contents in tables", tools_list_all_args_title			= "List of all accepted arguments", tools_support_desk_title			= "Support desk", tools_bindmodules_report_title		= "Detailed effective versions", tools_versions_manage_tests_title	= "Versions management test", --	tools_unused_modules_tests_title	= "Tests of UNUSED selection of modules versions", tools_versions_management_title		= "Versions management test", tools_versionsmanagement_report		= "Versions management report", tools_bindmodules_test_title		= "Test for management of modules versions", tools_verif_bindmodules_report		= "Binding of modules and versions control", tools_bindmodules_test_headers		= "Sought versions, Used versions, Known versions, ACTUAL: Errors in the active module, SIMULATION: Errors in the active module", tools_transdiff_report_title		= "Compare all differences in translations", tools_transdiff_report_headers		= "Language, Key, Previous translation, New translation, Module", tools_documentations_changes_report = "Documentations, tasks and changes", tools_list_loaded_modules_headers	= "Title, Version, Date, i18n, Translations / Languages", tools_date_to_part_test_title		= "Tests of date to day, month, year or era", tools_cat_add_test_title			= "Test the creation of categories in some languages", tools_levenshtein_test_title		= "Test the distances between words Levenshtein:", tools_table_args_source_title		= "Table of received arguments, args_source:", tools_table_args_unknown_title		= "Table of unknown arguments, args_unknown:", tools_args_known_structure_title	= 'Table structure of arguments', tools_missing_translations_title	= "Translations missings and changes in i18n tables:", tools_similar_args_test_title		= "Test close words similar_args:", tools_test_luatable_lister_title	= "List a table, test without limits:", tools_luatable_tests_limits_title	= "List a table, test with limits:", tools_mixed_translations_title		= "Combined i18n translations tables:", tools_dummy_languages_title			= "Language Definitions:", tools_time_format_test_title		= "Tests of coding and conversion of dates", tools_normal_box_main_text_1		= "Simple infobox: page title: %1, description: %2", tools_normal_box_main_text_2		= " He was %1, named %2 %3 was dead in %4.", tools_try_waits_debug_T122752		= "#invoke has not loaded %1, but the debug of T122752 has loaded it.", tools_tasks_table_report_title		= "States table of known tasks", tools_tasks_table_report_short		= "Short states of known tasks", tools_tasks_table_report_headers	= "Number, Status, Title",

-- These texts are used to title some tests. tools_list_wiki_selectors_title		= "List of this wiki selectors:", tools_list_all_categories_title		= "List of all eventual categories of this wiki:", tools_list_all_errors_title			= "List of all detectable errors in this wiki:", tools_multiple_values_tests_title	= "Test of multiple values arguments", tools_multiple_selection_test_title	= "Multiple selection test", tools_multiple_selection_test_header= "Options,Selector,To select,Selected", tools_multiple_selection_test_select= "2,nobel,president,deputy,price",

} -- tools.i18n.en

tools.i18n.es = { -- Nombres y descripciones de argumentos de configuraciones [1]								= "1",	[2]								= "2",	[3]								= "3",	[4]								= "4",	label							= 'label', label_descr						= "Wikidata automática argumento.", sitelink						= 'sitelink', sitelink_descr					= "Wikidata automática argumento.", userlang						= "userlang", userlang_descr					= "Idioma del usuario o del encargado.", wikilang						= "wikilang", wikilang_descr					= "Idioma del wiki.", itemid							= 'itemid', itemid_descr					= "Nombre de los datos Wikidata, como  para Victor Hugo.", itemid2							= 'id', itemid2_descr					= "Nombre de los datos Wikidata, como  para Victor Hugo.", debug							= 'debug', category						= 'Categoría', mode							= "modo", mode_descr						= "Tipo de uso del módulo o modelo: leer, editar, documentar, probar.", options							= 'opciones', options_descr					= "Opciones de visualización de un módulo o un modelo.", c								= "c", c_descr							= "Opciones de visualización de un módulo o un modelo.", knownversions					= "knownversions", knownversions_descr				= "Conocidas versiones, para manejarlos.", soughtversions					= "soughtversions", soughtversions_descr			= "Versiones demanda, para manejarlos.", -- Grupos de argumentos tools_needed_to_verify			= "(obligatorio, se debe comprobar)", tools_list_needed_args			= "Lista de argumentos necesarios:", tools_list_all_config_arguments	= "Lista de argumentos de configuración:", tools_list_all_system_arguments	= "Lista de argumentos del sistema:", tools_list_all_other_args		= "Lista de los otros argumentos:", -- Textos principales, errores y categorías de instrumentos language						= 'lenguaje', tools_user_wiki_lang_msg		= "Idiomas: usuario: %1, wiki: %2.", tools_DropBox_label_Unwrap		= "Desenvolver/Envolver", tools_language_cat				= 'Hablando %1', tools_date_months_names			= "Enero, Febrero, Marzo, Abril, Mayo, Junio​​, Julio, Agosto, Septiembre, Octubre, Noviembre, Diciembre", tools_date_to_part_format			= "dd mmmm yyyy", tools_date_to_part_call_err			= "Error interno: argumentos de llamadas anómala en fecha %1.", tools_date_to_part_call_cat			= "Módulo con error interno", tools_date_to_part_not_found_err	= "Error interno: No se encuentra en fecha %1.", tools_test_OK_cat					= "Prueba generación categoría en OK", tools_module_usage_error_cat		= "Módulo con error del uso", tools_module_internal_error_cat		= "Módulo con error interno", tools_module_with_error_cat			= "Módulo con error", tools_module_with_error_err			= "Módulo con error",

-- Control de argumentos tools_error_list_header_err			= "Asistencia de los parámetros de este modelo:", tools_need_arg_value_err			= "Error: Usted tiene que fijar este argumento necesario, pero falta: %1.", tools_none_value_err				= "Error: No hay argumento se ha definido.", tools_unknown_argument_err			= "Error: El parámetro %1 es desconocido en este modelo. Compruebe el nombre o reportar esta falta.", tools_too_unnamed_arguments_err 	= "Error: Demasiado argumento sin nombre: %1 = %2.", tools_internal_notice_wsid_err		= "Error interno: Informar al el desarrollador que el argumento interno %1 es desconocido en los registros.", tools_without_translation_err		= "Argumento conocido, pero no traducido: %1.", tools_without_translation_N_err 	= "Hay 1% argumentos no traducidos.", tools_is_defined_err				= "El argumento %1:%2 está definido.", tools_is_undefined_err				= "El argumento %1:%2 no está definido.", tools_args_values_err				= "Valor anormal del argumento %1 = %2 entre: (%3) ", -- Wikidata tools_wikidata_wikibase_err			= "Erreur : Wikibase n'est pas disponible.", tools_wikidata_getEntity_err		= "Erreur : getEntity Wikidata n'est pas disponible.", tools_wikidata_getEntityObject_err	= "Error: Elemento %1 de Wikidata no se encuentra.", tools_wikidata_property_err			= "Erreur : La propriété %1 de Wikidata n'est pas trouvée.", tools_wikidata_error_err			= "Erreur Wikidata : %1 ", tools_wikidata_cat_err				= "Module with internal error",	 -- tools_module_internal_error_cat tools_structured_data_txt			= 'Datos de Wikidata', tools_wikidata_any_page_title		= "Wikidata para cualquier página:", tools_wikidata_details_test_title	= "Pruebas y datos importados de wikidata", tools_wikidata_arbitrary_test_title = "Prueba de Wikidata acceso arbitrario", tools_wikidata_arbitrary_access_text= "Wikidata por otro título: ", tools_wikidata_time_details			= "Wikidata propiedades de tiempo para más detalles",

-- Gestión de versiones tools_versions_no_select_altern_err = "Error de versiones: no hay selección en alternativa %1 del módulo %2.", tools_versions_too_select_altern_err= "Error de versiones: %1 selecciones en la alternativa %2 del módulo %3.", tools_versions_select_not_used_err	= "Error de versiones: selector %1 no es en alternativas %2 del módulo %3.", tools_versions_missing_module_err	= "Error de versiones: módulo ausente para la versión %1 del módulo %2.", tools_main_module_missing_err		= "El módulo principal no es encontrado.", tools_select_unknown_module_err 	= "Internal error: El Modulo:%1 faltante se reemplaza por lo normal Module:%2.", tools_I18N_module_no_base_err		= "El módulo de traducciones %1 no tiene ninguna versión básica.", tools_no_versions_module_err		= "El %1 módulo no está en el sistema de versiones.", tools_all_versions_tests			= "Versiones aviso: %1, normal: %2, lista: %3.", tools_all_versions_check			= "Versiones: falta: %1, incógnitas: %2, normales: %3, en exceso: %4, selecciona todo: %5.", tools_missing_versions_err			= "El módulo %1 no disponible en el módulo principal %2.", tools_replaced_versions_err			= "El módulo %1 reemplaza el sub-módulo ausente en el módulo principal %2.", tools_unknown_versions_err			= "El módulo %1 es desconocido en el módulo principal %2.", -- Titulos de pruebas tools_support_desk_title			= "Escritorio de ayuda", tools_bindmodules_report_title		= "Versiones efectivas detalladas", tools_versions_manage_tests_title	= "Prueba de la gestión de versiones", --	tools_unused_modules_tests_title	= "Pruebas de selección NO UTILIZADA de versiones de módulos", tools_versionsmanagement_report		= "Informe de gestión del versiones", tools_versions_management_title		= "Prueba de gestión de versiones", tools_bindmodules_test_title		= "Prueba de la gestión de versiones de módulos", tools_verif_bindmodules_report		= "Enlace de los módulos y de control de versións", tools_bindmodules_test_headers		= "Versiones solicitadas, Versiones utilizadas, Versiones conocidas, REALES: Errores en el módulo activo, SIMULACIÓN: Errores en el módulo activo",

-- Diversos mensajes y errores tools_maini18n_languages_list		= "Este módulo puede traducir %1 frases en %2 idiomas: ", tools_nearest_argument_err			= "Error : ¿Es usted conocido argumento %1 ?", tools_max_nearest_argument_msg		= "Un argumento nombre más largo acepta más letras errores.", tools_value_re_defined_err			= "Error: El valor del argumento %1 ya está definido. Elija sólo un valor de un solo sinónimo", tools_language_cat					= 'Habla %1', occupation_cat						= '%1', tools_sources_of_datas				= "Informacións de: /Wikidata, /modelo o módulo, /otros, /mensaje, /error", tools_languages_nbr_and_list		= "\n* Hay %1 mesas de traducciones en estas idiomas: %2 ", tools_list_in_translated_lang		= "\n* %1 traducciones en idioma %2 : %3 : %4", tools_module_miss_i18n_none_err 	= "OK, ninguno traducciones faltan.", tools_texts_translated_in_langs 	= "Hay %1 textos traducidos en 2% idiomas.", tools_module_miss_i18n_trad_err 	= "Error interno: falta de traducción para el argumento %1 ", --	tools_err_module_miss_i18n_cat		= "Módulo falta de traducción i18n", tools_err_module_miss_i18n_cat		= "Módulo con error interno", -- tools_module_internal_error_cat tools_i18n_list_all_texts			= "Esta lista muestra todos los textos, pero no puede sustituir a las declaraciones originales.", tools_luatable_counts				= "La tabla %1 cuenta %2 textos, %3 funciones y %4 sub-tablas.", tools_table_dont_exists_err			= "La tabla %1 no existe.", --	tools_delete_docbox_msg				= "Debe quitar esta documentación antes de grabar. Retire todos los modos para volver al modo read.", tools_auto_val_warning_msg			= "Verifique el argumento automático: %1 = %2.", --	tools_assist_user_param_err			= "Soporte al usuario para comprobar la configuración:", tools_module_error_err				= "Módulo con error.", tools_auto_val_unknown_err			= "Error interno: Argumento desconocido automático: %1 = %2.", tools_no_known_arguments_err		= "Módulo sin argumentos tabla conocida.", tools_unknown_auto_arg_err			= "Error interno: Argumento desconocido automático: %1 = %2.", tools_args_values_err				= "Valor anormal del argumento %1 = %2 (%3)", --	tools_no_known_arguments_err		= "Error interno: Módulo sin tabla de argumentos conocidos.", tools_tools_no_known_args_cat		= "Módulo con error interno", -- tools_module_internal_error_cat tools_no_source_arguments_err		= "Error interno: Módulo sin tabla de argumentos fuentes.", tools_no_source_arguments_cat		= "Módulo con error interno", -- tools_module_internal_error_cat

-- Titres des pruebas tools_page_tests_h3_title			= "Pruebas de esta página", tools_page_tests_title				= "Pruebas y información relacionada con esta página:", tools_internal_tests_h3_title		= "Pruebas internas", tools_internal_tests_title			= "Pruebas de no regresión internas:", tools_dropdown_missing_title		= "Falta el título para este dropbox", tools_used_options_title			= "Opciones y sus usos:", tools_options_from_mode_title		= "Prueba de opciones de modos", tools_options_from_args_title		= "Prueba de opciones de argumentos", tools_spaces_page_names_title		= "Módulo, namespaces, y nombres de páginas:", tools_luatables_counts_title		= "Condes des contenidos en tablas", tools_list_all_args_title			= "Lista de todos los argumentos aceptados", tools_transdiff_report_title		= "Comparar todas las diferencias en las traducciones", tools_transdiff_report_headers		= "Idioma, Clave, Traducción anterior, Nueva traducción, Módulo", tools_documentations_changes_report = "Documentación, parches y modificaciones", tools_list_loaded_modules_headers	= "Título, Versión, Fecha, i18n, Traducciones / Idiomas", tools_date_to_part_test_title		= "Pruebas de fecha a día, mes, año o época", tools_cat_add_test_title			= "Pruebe la creación de categorías en algunos idiomas", tools_levenshtein_test_title		= "Prueba de las distancias entre las palabras Levenshtein:", tools_table_args_source_title		= "Tabla de argumentos recibido, args_source:", tools_table_args_unknown_title		= "Tabla de argumentos desconocidos, args_unknown:", tools_args_known_structure_title	= 'Estructura de la tabla del argumentos', tools_missing_translations_title	= "Traducciones que faltan o cambiando en las tablas i18n:", tools_similar_args_test_title		= "Prueba de palabras cercanos similar_args:", tools_test_luatable_lister_title	= "Enumerar una tabla, prueba sin límites:", tools_luatable_tests_limits_title	= "Enumerar una tabla, prueba con límites:", tools_mixed_translations_title		= "Tablas traducciones i18n combinadas:", tools_dummy_languages_title			= "Definiciones de idiomas:", tools_time_format_test_title		= "Pruebas de codificación y conversión fechas", tools_normal_box_main_text_1		= "Simple caja de información: Título de la página: %1, descripción: %2", tools_normal_box_main_text_2		= " Él era un %1, es nombrado %2 %3 había muerto en %4.", tools_try_waits_debug_T122752		= "#invoke no ha cargado %1, pero la depuración de T122752 ha lo cargó.", tools_tasks_table_report_title		= "Tabla de estados de tareas conocidas", tools_tasks_table_report_short		= "Estados breves del tareas conocidas", tools_tasks_table_report_headers	= "Número, Estado, Título",

-- Estos textos se utilizan para titular algunas pruebas. tools_list_wiki_selectors_title		= "Lista de las selectores de este wiki:", tools_list_all_categories_title		= "Lista de todas las posibles categorías de esta wiki:", tools_list_all_errors_title			= "Lista de todos los errores detectables de este wiki:", tools_multiple_values_tests_title	= "Prueba de múltiples valores argumentos", tools_multiple_selection_test_title	= "Prueba de selección múltiple", tools_multiple_selection_test_header= "Opciones,Selector,Para seleccionar,Seleccionadas", tools_multiple_selection_test_select= "2,nobel,presidente,diputado,precio",

} -- tools.i18n.es

tools.i18n.fr = { -- Noms et descriptions des arguments de configurations [1]								= "1",	[2]								= "2",	[3]								= "3",	[4]								= "4",	label							= 'label', label_descr						= "Argument automatique de Wikidata.", sitelink						= 'sitelink', sitelink_descr					= "Argument automatique de Wikidata.", userlang						= "userlang", userlang_descr					= "Langue de l'utilisateur ou de l'aidant.", wikilang						= "wikilang", wikilang_descr					= "Langue du wiki.", itemid							= 'itemid', itemid_descr					= "Identifiant des données de wikidata, comme  pour Victor Hugo.", itemid2							= 'id', itemid2_descr					= "Identifiant 2 des données de wikidata, comme  pour Victor Hugo.", debug							= 'debug', category						= 'Catégorie', mode							= "mode", mode_descr						= "Type d'utilisation du module ou du modèle : lire, éditer, documenter, tester.", options							= "options", options_descr					= "Options d'affichage d'un module ou d'un modèle.", c								= "c", c_descr							= "Options d'affichage d'un module ou d'un modèle.", knownversions					= "knownversions", knownversions_descr				= "Versions connues, pour les gérer.", soughtversions					= "soughtversions", soughtversions_descr			= "Versions demandées, pour les gérer.", -- Groupes d'arguments tools_needed_to_verify			= "(obligatoire, à vérifier)", tools_list_needed_args			= "Liste des arguments nécessaires :", tools_list_all_config_arguments	= "Liste des arguments de configuration :", tools_list_all_system_arguments	= "Liste des arguments système :", tools_list_all_other_args		= "Liste des autres arguments :", -- Principaux textes, erreurs et catégories des outils language							= 'langue', tools_user_wiki_lang_msg			= "Langues : utilisateur : %1, wiki : %2.", tools_DropBox_label_Unwrap			= "Dérouler/Enrouler", tools_language_cat					= 'Parle %1', tools_date_months_names				= "Janvier, Février, Mars, Avril, Mai, Juin, Juillet, Août, Septembre, Octobre, Novembre, Décembre", tools_date_to_part_format			= "dd yyyy mmmm", tools_date_to_part_call_err			= "Erreur interne : Argument anormal de définition de date %1.", tools_date_to_part_call_cat			= "Module avec erreur interne", tools_date_to_part_not_found_err	= "Erreur interne : partie non définie de date %1.", tools_test_OK_cat					= "Test de génération de catégorie OK", tools_module_usage_error_cat		= "Module avec erreur d'utilisation", tools_module_internal_error_cat		= "Module avec erreur interne", tools_module_with_error_cat			= "Module avec erreur", tools_module_with_error_err			= "Module avec erreur",

-- Gestion des arguments tools_error_list_header_err			= "Assistance sur les paramètres de ce modèle :", tools_need_arg_value_err			= "Erreur : Vous devez définir cet argument nécessaire mais absent : %1.", tools_none_value_err				= "Erreur : Aucun argument n'a été défini.", tools_unknown_argument_err			= "Erreur : Le paramètre %1 est inconnu dans ce modèle. Vérifier ce nom ou signaler ce manque.", tools_too_unnamed_arguments_err 	= "Erreur : Ce paramètre non nommé est en trop : %1 = %2.", tools_internal_notice_wsid_err		= "Erreur interne : Signaler au développeur que l'argument interne %1 est inconnu dans les notices.", tools_without_translation_err		= "Argument connu, mais non traduit : %1.", tools_without_translation_N_err 	= "Il y a %1 arguments non traduits.", tools_is_defined_err				= "L'argument %1:%2 est défini.", tools_is_undefined_err				= "L'argument %1:%2 n'est pas défini.", tools_args_values_err				= "Valeur anormale de l'argument %1 = %2 parmi : (%3) ", -- Wikidata tools_wikidata_wikibase_err			= "Erreur : Wikibase n'est pas disponible.", tools_wikidata_getEntity_err		= "Erreur : getEntity Wikidata n'est pas disponible.", tools_wikidata_getEntityObject_err	= "Erreur : L'élément %1 de Wikidata n'est pas trouvé.", tools_wikidata_property_err			= "Erreur : La propriété %1 de Wikidata n'est pas trouvée.", tools_wikidata_error_err			= "Erreur Wikidata : %1 ", tools_wikidata_cat_err				= "tools_module_internal_error_cat", --	tools_wikidata_cat_err				= "Module with internal error",	 -- tools_module_internal_error_cat tools_structured_data_txt			= 'Données de Wikidata', tools_wikidata_any_page_title		= "Wikidata pour une autre page :", tools_wikidata_details_test_title	= "Tests et données importées de wikidata", tools_wikidata_arbitrary_test_title = "Test de Wikidata accès arbitraire", tools_wikidata_arbitrary_access_text= "Wikidata pour une autre page: ", tools_wikidata_time_details			= "Wikidata propriétés de temps pour plus de détails",

-- Gestion des versions tools_versions_no_select_altern_err = "Erreur de versions : pas de sélection dans l'alternative %1 du module %2.", tools_versions_too_select_altern_err= "Erreur de versions : %1 sélections dans l'alternative %2 du module %3.", tools_versions_select_not_used_err	= "Erreur de versions : le sélecteur %1 n'est pas dans les alternatives %2 du module %3.", tools_versions_missing_module_err	= "Erreur de versions : module absent pour la version %1 du module %2.", tools_main_module_missing_err		= "Le module principal est introuvable.", tools_select_unknown_module_err 	= "Internal error: Le Module:%1 manquant est remplacé par le module normal Module:%2.", tools_I18N_module_no_base_err		= "Le module de traductions %1 n'a pas de version de base.", tools_no_versions_module_err		= "Le module %1 n'est pas dans le système des versions.", tools_all_versions_tests			= "Versions avertissements : %1, normaux : %2, liste : %3.", tools_all_versions_check			= "Versions: manquantes: %1, inconnues: %2, normales: %3, en excès: %4, toutes selectionées : %5.", tools_missing_versions_err			= "Le module %1 manque dans le module principal %2.", tools_replaced_versions_err			= "Le module %1 remplace le sous-module absent dans le module principal %2.", tools_unknown_versions_err			= "Le module %1 est inconnu dans le module principal %2.",

-- Messages et erreurs divers tools_maini18n_languages_list		= "Ce module peut traduire %1 phrases en %2 langues: ", tools_nearest_argument_err			= "Erreur : Voulez vous l'argument connu %1 ?", tools_max_nearest_argument_msg		= "Un nom d'argument plus long accepte plus d'erreurs de lettres.", tools_value_re_defined_err			= "Erreur : La valeur de l'argument %1 est déjà définie. Choisir une seule valeur d'un seul synonyme.", tools_table_listlimit_levelmaxi 	= "Limite de niveau levelmaxi = %1 ", tools_table_listlimit_max_n			= "Limite de longueur max_n = %1 ", tools_i18n_list_all_texts			= "Cette liste montre tous les textes, mais ne peut remplacer les déclarations originales.", tools_languages_nbr_and_list		= "\n* Il y a %1 tables de traductions dans ces langues : %2 ", tools_module_miss_i18n_txt_err		= "Erreur interne : Le texte %1 manque de traduction en langue %2, et/ou d'autres.", tools_module_miss_i18n_count_err	= "Erreur interne : Il y a %1 manques parmi %2 traductions.", tools_module_miss_i18n_none_err 	= "OK, aucune traduction manquante.", tools_texts_translated_in_langs 	= "Il y a %1 textes traduits en %2 langues.", tools_module_miss_i18n_trad_err 	= "Erreur interne : manque de traduction pour l'argument %1 ", --	tools_err_module_miss_i18n_cat		= "Module manquant de traduction i18n", tools_err_module_miss_i18n_cat		= "Module avec erreur interne", -- tools_module_internal_error_cat tools_module_miss_i18n_mini_err 	= "Erreur interne : La table i18n n'a que %1 traductions.", --	tools_no_args_known_err				= "Erreur interne : Module sans table d'arguments connus.", --	tools_no_args_source_err			= "Erreur interne : Module sans table d'arguments sources.", tools_no_wiki_translations_err		= "Erreur interne : Module sans table d'arguments traduits.", tools_no_args_wikidata_err			= "Erreur interne : Module sans table d'arguments wikidata.", tools_lang_table_err				= "Erreur interne : La langue %1 ou sa table est erronée.", --	tools_lang_table_err_cat			= "Module avec langue d'arguments erronée", tools_lang_table_err_cat			= "Module avec erreur interne", -- tools_module_internal_error_cat tools_lang_not_exist_err			= "Erreur : La langue %1 n'est pas disponible.", tools_lang_not_translated_err		= "Erreur : La langue %1 n'est pas traduite.", tools_generDoc1_paramName_err		= "Erreur interne : en generDoc1, mauvais argument %1.", tools_sources_of_datas				= "Informations de : /Wikidata, /modèle ou module, /autres, /message, /erreur", tools_list_in_translated_lang		= "\n* %1 traductions en langage %2 : %3 : %4", tools_luatable_counts				= "La table %1 compte %2 textes, %3 fonctions, %4 sous-tables.", tools_table_dont_exists_err			= "La table %1 n'existe pas.", tools_auto_val_unknown_err			= "Erreur interne: Argument automatique inconnu : %1 = %2.", --	tools_delete_docbox_msg				= "Vous devez supprimer cette documentation avant d'enregistrer. Supprimez tous les modes pour revenir en mode read.", tools_auto_val_warning_2_msg		= "Vérifiez l'argument automatique BIS : %1 = %2.", tools_auto_val_warning_msg			= "tools_auto_val_warning_2_msg", --	tools_assist_user_param_err			= "Support aux utilisateurs pour vérifier les paramètres :", tools_module_error_err				= "Module avec erreur", tools_no_known_arguments_err		= "Module sans table d'arguments connus.", tools_unknown_auto_arg_err			= "Erreur interne : Argument automatique inconnu : %1 = %2.", tools_args_values_err				= "Valeur anormale de l'argument %1 = %2 (%3)", --	tools_no_known_arguments_err		= "Erreur interne : Module sans table d'arguments connus.", --	tools_tools_no_known_args_cat		= "Module sans table d'arguments connus.", tools_tools_no_known_args_cat		= "Module avec erreur interne", -- tools_module_internal_error_cat tools_no_source_arguments_err		= "Erreur interne : Module sans table d'arguments sources.", --	tools_no_source_arguments_cat		= "Module sans table d'arguments sources.", tools_no_source_arguments_cat		= "Module avec erreur interne", -- tools_module_internal_error_cat

-- Tests titles tools_page_tests_h3_title			= "Tests de cette page", tools_page_tests_title				= "Tests et informations liées à cette page :", tools_internal_tests_h3_title		= "Tests internes", tools_internal_tests_title			= "Tests internes de non régression :", tools_dropdown_missing_title		= "Titre manquant pour cette boite déroulante", tools_used_options_title			= "Options et leurs utilisations :", tools_options_from_mode_title		= "Test des options de modes", tools_options_from_args_title		= "Test des options des arguments", tools_spaces_page_names_title		= "Module, namespaces, et noms de pages :", tools_luatables_counts_title		= "Comptages des contenus de tables", tools_list_all_args_title			= "Liste de tous les arguments acceptés", tools_support_desk_title			= "Bureau d'aide", tools_bindmodules_report_title		= "Versions effectives détaillées", tools_versions_manage_tests_title	= "Test de la gestion des versions", tools_versionsmanagement_report		= "Rapport de gestion des versions", tools_versions_management_title		= "Test de gestion des versions", tools_bindmodules_test_title		= "Test de la gestion des versions des modules", tools_verif_bindmodules_report		= "Liaison des modules et contrôle des versions", tools_bindmodules_test_headers		= "Versions demandées, Versions utilisées, Versions connues, ACTUEL : Erreurs dans le module actif, SIMULATION : Erreurs dans le module actif", tools_transdiff_report_title		= "Comparez toutes les différences dans les traductions", tools_transdiff_report_headers		= "Langue, Clé, Traduction précédente, Nouvelle traduction, Module", tools_documentations_changes_report = "Documentations, tâches et modifications", tools_list_loaded_modules_headers	= "Titre, Version, Date, i18n, Traductions / Langues", tools_date_to_part_test_title		= "Tests de date vers jour, mois, année ou ère", tools_cat_add_test_title			= "Tester la création des catégories dans quelques langues", tools_levenshtein_test_title		= "Test des distances entre mots de Levenshtein:", tools_table_args_source_title		= "Table des arguments reçus, args_source :", tools_table_args_unknown_title		= "Table des arguments inconnus, args_unknown :", tools_args_known_structure_title	= 'Structure de la table des arguments', tools_missing_translations_title	= "Traductions manquantes ou changeantes dans les tables i18n:", tools_similar_args_test_title		= "Test des mots proches similar_args :", tools_test_luatable_lister_title	= "Lister une table, test sans limites :", tools_luatable_tests_limits_title	= "Lister une table, test avec limites :", tools_mixed_translations_title		= "Tables de traductions i18n combinées :", tools_dummy_languages_title			= "Définitions de langues :", tools_time_format_test_title		= "Tests de codage et conversions de dates", tools_normal_box_main_text_1		= "Boîte d'information simple : titre de cette page %1, description : %2", tools_normal_box_main_text_2		= " Il était %1, se nommait %2 %3, il est mort en %4.", tools_try_waits_debug_T122752		= "#invoke n'a pas chargé %1, mais le débogage de T122752 l'a chargé.", tools_tasks_table_report_title		= "Table des états de tâches connues", tools_tasks_table_report_short		= "États brefs de tâches connues", tools_tasks_table_report_headers	= "Numéro, État, Titre",

-- Ces textes sont utilisés pour titrer des tests. tools_list_wiki_selectors_title		= "Liste des sélecteurs de ce wiki :", tools_list_all_categories_title		= "Liste de toutes les catégories éventuelles de ce wiki :", tools_list_all_errors_title			= "Liste de toutes les erreurs détectables de ce wiki :", tools_multiple_values_tests_title	= "Test des arguments à valeurs multiples", tools_multiple_selection_test_title	= "Test de sélection multiple", tools_multiple_selection_test_header= "Options,Sélecteur,À sélectionner,Sélectionnés", tools_multiple_selection_test_select= "2,nobel,président,député,prix",

} -- tools.i18n.fr

--	Management of arguments and translations along their transformations : tools.args_known = {} -- Known arguments, at main module level tools.args_invoke = {} -- Invoke arguments, at level tools.args_template = {} -- Template arguments, at  level tools.args_source = {} -- Source arguments = args_template + args_invoke tools.args_unknown = {} -- Unknown arguments tools.args_wikidata = {} -- Wikidata arguments, from Wikidata tools.args_import = {} -- Import arguments tools.args_final = {} -- Final arguments, interactions in p.interact_args_final tools.args_selected = {} -- Selected arguments, in some modules tools.wiki_translations = {} -- Wiki translations tools.user_translations = {} -- User translations tools.errors_list = {} -- Errors list tools.categories_list = {} -- Categories lists tools.loaded_pack = {} -- loaded packages of modules and libraries tools.loaded_vers = {} -- loaded versions of modules and libraries --

--	For translations tools.wiki_lang = "en" -- wiki default language tools.wiki_translations = tostring(mw.language.getContentLanguage.code) -- wiki default language -- language of usual wiki for args and categories tools.user_lang = "en" -- user default language tools.user_translations = tostring(mw.language.getContentLanguage.code) -- wiki default language tools.msgs_list = tools.user_translations -- = tools.i18n[tools.user_lang] -- translations in the user language of identifiers, errors and messages --	https://www.mediawiki.org/wiki/Extension:UniversalLanguageSelector --	Flexible and easy way to select a language from a large set of languages. -- For reports

tools.report_main_short = "tools.report_main_short is missing." tools.report_main_discreet = "tools.report_main_discreet is missing." tools.report_REVISIONTIMESTAMP = "tools.report_REVISIONTIMESTAMP is missing." tools.report_actual_versions = "tools.report_actual_versions is missing." tools.recursivity = 11111 tools.tracks_level = 1 -- none=0, normal=1, details=2, full=3

function tools.args_config_init(args_source) -- Memorize direct configuration arguments, without translation, for helpers. if type(args_source) ~= "table" then args_source = tools.args_source end local new_source = mw.clone(args_source) local args_config = {} args_config.userlang = args_source.userlang -- user language argument new_source.userlang = nil args_config.wikilang = args_source.wikilang -- wiki language argument new_source.wikilang = nil args_config.mode = args_source.mode -- mode argument new_source.mode = nil args_config.c = args_source.c -- invoke options argument new_source.c = nil args_config.dockey = args_source.dockey or args_source[1] -- doc selector argument new_source.dockey = nil args_config.itemid = args_source.itemid or args_source.id or args_source[2] -- wikidata item id argument new_source.itemid = nil args_config.soughtversions = args_source.soughtversions -- sought_versions argument new_source.soughtversions = nil args_config.knownversions = args_source.knownversions -- known_versions argument new_source.knownversions = nil tools.args_source = new_source tools.args_config = args_config return args_config, new_source end -- function tools.args_config_init

function tools.change_itemid(id_in) if id_in then -- Local function parameter have priority. id = id_in else -- Else use the template arguments or inforce itemid here. id = tools.args_config.id --	id = "Q131671" -- (VIe siècle av. J.-C. – Ve siècle av. J.-C.) Xénophane --	id = "Q8739"	--	(vers 287 av. J.-C. – 212 av. J.-C.) Archimède --	id = "Q213330"			--		 (1330 – 1418) Nicolas Flamel --	id = "Q83428"			--	 (vers 1493 – 1541) Paracelse id = "Q41568"			--		 (1533 – 1592) Michel de Montaigne --	id = "Q535"				--		 (1802 – 1885) Victor Hugo --	id = "Q21157618"		--		 (		– 1932) Charles Maumené --	id = "Q9364"			--		 (1905 – 1980) Jean-Paul Sartre --	id = "Q213330"			--		 (1330 – 1418) Nicolas Flamel end local nst = 10 -- mw.site.namespaces.Template local nsm = 828 -- mw.site.namespaces.Module local mwtitle = mw.title.getCurrentTitle local nsX = mw.title.getCurrentTitle:inNamespaces("10", "11", "828", "829") local ns = tostring(mw.site.namespaces.id) if tools.is_in_sp(ns, "10,11,828,829", ",") then -- Change itemid only where title cannot be in wikidata. tools.args_config.id = id		tools.args_config.itemid = id	end --	tools.args_config.id = id -- always inforce --	tools.args_config.itemid = id -- always inforce return id end -- function tools.change_itemid(id_in)

function tools.maini18n_lang_v_t(i18n, txt) -- Count available translations and languages return tools.form_i18n_counts(i18n, txt) end

function tools.form_i18n_counts(i18n, txt) -- Count available translations and languages local st, vr, fn, tb = tools.luatablecount(i18n) -- or centre.maini18n local vr_tb = 0 if tb == 0 then vr_tb = 0 else vr_tb = tonumber(vr / tb) end --	if (vr_tb > 0) and (vr_tb < 1) then vr_tb = 1 end vr = math.floor( vr_tb ) -- texts number in one language if type(txt) ~= "string" then txt = "tools_maini18n_languages_list" end -- ", %1 sentences in %2 languages, " t = tools.str_vars(txt, vr, tb) return t end -- function tools.form_i18n_counts(i18n, txt)

function tools.maini18n_languages_list -- List available translations languages local t = tools.form_i18n_counts(centre.maini18n, "tools_maini18n_languages_list") -- tools_maini18n_languages_list local tab_to_sort = {} centre.maini18n = centre.maini18n or {} for lang, modname in pairs(centre.maini18n) do		table.insert(tab_to_sort, lang) -- build a table with only languages codes end table.sort(tab_to_sort, function (a, b) -- sort le languages codes in stable alphabetic order		return	( a < b )	end ) for i, lang in pairs(tab_to_sort) do -- describe each language local nativename = mw.language.fetchLanguageName(lang) local englishname = mw.language.fetchLanguageName(lang, "en") t = t .. tools.str_vars("%1(%2=%3), ", nativename, lang, englishname) end return t end -- function tools.maini18n_languages_list

function tools.group_translations(group_type, group_name_key, group_names_list, group_selected_languages) -- Todo later -- Enable to rename translations by cascading keys. Example: tools_err_XYZ = tools_user_error = "User error" -- Todo : That permit to group some detailed categories in only one to simplify lookup for helpers. -- Todo : That can be different in each projet and each language. Or automatic in all languages if the main module. -- group_translations is able without this function, only in i18n translations tables -- translations in the group_name_list are grouped in group_name_key, following the rules of group_type -- group_type could be "in_all_languages,in_selected_languages" return end -- function tools.group_translations

--	Tests : class ClassNameTest extends Scribunto_LuaEngineTestBase --	protected static $moduleName = 'ClassNameTest'; function tools.str_test_case(ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) -- db	-- add -v1 to -v9 to the ref local wt = nil if type(ref) == "string" then -- Use ref as reference of text. wt = ref if v1 then wt = wt .. "-" .. tostring(v1) end if v2 then wt = wt .. "-" .. tostring(v2) end if v3 then wt = wt .. "-" .. tostring(v3) end if v4 then wt = wt .. "-" .. tostring(v4) end if v5 then wt = wt .. "-" .. tostring(v5) end if v6 then wt = wt .. "-" .. tostring(v6) end if v7 then wt = wt .. "-" .. tostring(v7) end if v8 then wt = wt .. "-" .. tostring(v8) end if v9 then wt = wt .. "-" .. tostring(v9) end return wt	end return wt or "" end -- function tools.str_test_case(ref, v1, v2, v3, v4, v5, v6, v7, v8, v9)

function tools.string_vars(translations, ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) -- replace %1 to %9 by v1 to v9 in the user translation of ref, else in ref local wt = nil if translations and translations[ref] then -- Use ref as reference of text. ref = tostring(translations[ref]) -- See also tools.group_translations if translations and translations[ref] then -- Use ref as reference of text. -- Enable to rename translations by cascading keys. -- Example: tools_err_XYZ = "tools_user_error", -- Then :  tools_internal_error = "User error", -- Todo : That permit to group some detailed categories in only one to simplify lookup for helpers. -- Todo : That can be different in each projet and each language. Or automatic in all languages by the main module. --	tools_module_usage_error_cat		= "Module with usage error", --	tools_module_internal_error_cat		= "Module with internal error", --	tools_module_with_error_err			= "Module with error", --	tools_module_with_error_cat			= "Module with error", ref = tostring(translations[ref]) end wt = ref .. " "	elseif type(ref) == "string" then -- Else use ref as the text itself. wt = ref .. " "	end local percent = string.find(ref or "", "%", 1, true) if wt and percent then -- If reference has %1 to %9 v1 = v1 or " 1" v2 = v2 or " 2" v3 = v3 or " 3" v4 = v4 or " 4" v5 = v5 or " 5" v6 = v6 or " 6" v7 = v7 or " 7" v8 = v8 or " 8" v9 = v9 or " 9" if v1 then wt = string.gsub(wt, "%%1", tostring(v1) ) end if v2 then wt = string.gsub(wt, "%%2", tostring(v2) ) end if v3 then wt = string.gsub(wt, "%%3", tostring(v3) ) end if v4 then wt = string.gsub(wt, "%%4", tostring(v4) ) end if v5 then wt = string.gsub(wt, "%%5", tostring(v5) ) end if v6 then wt = string.gsub(wt, "%%6", tostring(v6) ) end if v7 then wt = string.gsub(wt, "%%7", tostring(v7) ) end if v8 then wt = string.gsub(wt, "%%8", tostring(v8) ) end if v9 then wt = string.gsub(wt, "%%9", tostring(v9) ) end return wt elseif type(ref) == "string" then -- Else use ref as the text itself. wt = tools.str_test_case(ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) --		wt = ref		if v1 then wt = wt .. "-" .. tostring(v1) end		if v2 then wt = wt .. "-" .. tostring(v2) end		if v3 then wt = wt .. "-" .. tostring(v3) end		if v4 then wt = wt .. "-" .. tostring(v4) end		if v5 then wt = wt .. "-" .. tostring(v5) end		if v6 then wt = wt .. "-" .. tostring(v6) end		if v7 then wt = wt .. "-" .. tostring(v7) end		if v8 then wt = wt .. "-" .. tostring(v8) end		if v9 then wt = wt .. "-" .. tostring(v9) end		-- wt = wt .. " "		return wt else -- Else internal error. wt = "string_vars.noref " return wt	end return wt or "" end -- function tools.string_vars(translations, ref, v1, v2, v3, v4, v5, v6, v7, v8, v9)

function tools.str_vars(ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) -- replace %1 to %7 by v1 to v7 in the user translation of ref, else in ref return tools.string_vars(tools.user_translations, ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) end -- function tools.str_vars(ref, v1, v2, v3, v4, v5, v6, v7)

function tools.str_test(ref, v1, v2, v3) local t = "" t = t .. "tools.i18n: " .. tools.string_vars(tools.i18n.fr, ref or "tools_auto_val_warning_msg", v1 or "str_test", v2 or 22) .. " "	t = t .. "centre.maini18n: " .. tools.string_vars(centre.maini18n.fr, ref or "tools_auto_val_warning_msg", v1 or "str_test", v2 or 22) .. " "	return t end

function tools.wiki_vars(ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) -- replace %1 to %7 by v1 to v7 in the wiki translation of ref, else in ref return tools.string_vars(tools.wiki_translations, ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) end -- function tools.wiki_vars(ref, v1, v2, v3, v4, v5, v6, v7)

function tools.is_in(word, text) -- The word is it in the text, even inside another word? local i = string.find(text or "", word or "", 1, true) return (i and true) end

function tools.is_in_sp(word, text, sep) -- The word is it in the text, beetwen spaces or separators, not inside another word? sep = sep or " " -- default separator is space. But could be * ;, or even any string. word = word or "" text = text or "" local i = string.find(sep .. text .. sep, sep .. (word or "") .. sep, 1, true) return (i and 1) end

function tools.is_version(module) -- A module is it in version management system? return (type(module) == "table") and module.versions end

-- Document the tables and their structures. List a table content, with formating. -- Documentar las tablas y sus estructuras. Lista de un contenido de la tabla, con el formateo. -- Documenter les tables et leurs structures. Lister un contenu de la table, avec le formatage.

-- Dump and format the content of a table and its sub-tables ; with limits in length, deep and exceptions. -- Listar y formatar le contento de una tabla y su sub-tablas. -- Lister et formater le contenu d'une table et ses sous-tables ; avec des limites en longueur, profondeur et exceptions. -- For each (sub)table, list : in first vars, then functions, then sub-tables list, then sub-tables contents

function tools.luatable_lister_recursive(tbl, uppername, name, recursive, countonly, levelmaxi, max_n, exclude1, exclude2, exclude3) if type(name) ~= "string" then name = "table" end local res, newname, part, shift = "", "", "", "" local sep, N = ", ", 0 local isempty = true local levelname = uppername .. "." .. name local tot_vars, tot_func, tot_tabs = 0, 0, 0 local nbr_vars, lst_vars = 0, "" local nbr_func, lst_func = 0, "" local nbr_tabs, lst_tabs = 0, "" local max, lst_subtabs = 0, "" local st, vr, fn, tb = "", 0, 0, 0 local list = not countonly local tobreak = nil -- limit the number of the level of sub-tables if type(tools.recursivity) ~= "number" then tools.recursivity = 11111 end if type(recursive) ~= "number" then recursive = 1 end levelmaxi = tonumber(levelmaxi) if type(levelmaxi) ~= "number" then levelmaxi = 99 end if recursive > levelmaxi then local t_levelmaxi = tools.str_vars("tools_table_listlimit_levelmaxi", levelmaxi) return tools.message_color( tostring(t_levelmaxi) ), tot_vars, tot_func, tot_tabs end max_n = tonumber(max_n) or 999 shift = string.rep("*", recursive) --	-- Do not list if exclude1, exclude2 or exclude3 are in the table name. if type(exclude1) == "string" and exclude1 ~= "" then if string.find(name, exclude1) ~= nil then return "", tot_vars, tot_func, tot_tabs end end if type(exclude2) == "string" and exclude2 ~= "" then if string.find(name, exclude2) ~= nil then return "", tot_vars, tot_func, tot_tabs end end if type(exclude3) == "string" and exclude3 ~= "" then if string.find(name, exclude3) ~= nil then return "", tot_vars, tot_func, tot_tabs end end -- display table error if type(tbl) ~= "table" then return ' The variable "' .. tostring(name) .. '" is not a table. ', tot_vars, tot_func, tot_tabs end --	-- List and count vars, functions and sub tables -- All named elements, including [1] and ["1"]. -- Tous les élements, y compris [1] et ["1"]. for k, v in pairs(tbl) do		k = tostring(k) if type(v) == "table" then lst_tabs = lst_tabs .. k .. sep nbr_tabs = nbr_tabs + 1 isempty = false newname = tostring(k) max = max + 1 -- List recursively (or no) each sub-table if recursive < tools.recursivity then st, vr, fn, tb = tools.luatable_lister_recursive(v, levelname, newname, recursive+1, countonly, levelmaxi, max_n, exclude1, exclude2, exclude3) tot_vars = tot_vars + vr				tot_func = tot_func + fn				tot_tabs = tot_tabs + tb + 1 if list then lst_subtabs = lst_subtabs .. st end end if recursive >= levelmaxi then local tools_table_listlimit_levelmaxi = tools.str_vars("tools_table_listlimit_levelmaxi", levelmaxi) if list then res = res .. " " .. tools.message_color( tools_table_listlimit_levelmaxi ) end break end local sep = "" if max == max_n then local tools_table_listlimit_max_n = tools.str_vars("tools_table_listlimit_max_n", max_n) if list then res = res .. "\n" .. shift .. " Table '''" .. levelname .. "''' " .. tools.message_color(tools_table_listlimit_max_n) end break end --			end elseif type(v) == "function" then nbr_func = nbr_func + 1 tot_func = tot_func + 1 isempty = false if list then lst_func = lst_func .. k .. sep end else -- type(v) == other nbr_vars = nbr_vars + 1 tot_vars = tot_vars + 1 isempty = false if list then lst_vars = lst_vars .. type(v) .. " - '''" .. tostring(k) .. "''' = " .. tostring(v) .. " " .. sep end end end if list then res = res .. "\n" .. shift .. " Table '''" .. levelname .. "''', " .. tostring(nbr_vars) .. " vars: " .. lst_vars end if list then res = res .. "\n" .. shift .. " Table '''" .. levelname .. "''', " .. tostring(nbr_func) .. " functions: " .. lst_func end if list then res = res .. "\n" .. shift .. " Table '''" .. levelname .. "''', " .. tostring(nbr_tabs) .. " tables: " .. lst_tabs .. lst_subtabs end return res, tot_vars, tot_func, tot_tabs end -- function tools.luatable_lister_recursive(tbl, uppername, name, recursive, countonly, levelmaxi, max_n, exclude1, exclude2, exclude3)

function tools.luatable_lister(table, tablename, opt) local res = "\n* Content of the '''" .. tostring(tablename) .. "''' table, begin:" -- test : check mw content if not opt then opt = { levelmaxi = 99 } end local levelmaxi = opt.levelmaxi or 99 local max_n = opt.max_n or 9999 local exclude1 = opt.exclude1 or "" local exclude2 = opt.exclude2 or "" local exclude3 = opt.exclude3 or "" local countonly = opt.countonly and true local tot_vars, tot_func, tot_tabs = 0, 0, 0 -- limit the number of the level of sub-tables if type(recursive) ~= "number" then recursive = 1 end if type(levelmaxi) ~= "number" then levelmaxi = 99 end if recursive > levelmaxi then return "", tot_vars, tot_func, tot_tabs end res = res .. " ( " .. tools.ta("levelmaxi", levelmaxi) .. tools.ta("max_n", max_n) .. tools.ta("exclude1", exclude1) .. tools.ta("exclude2", exclude2) .. tools.ta("exclude3", exclude3) .. " ) " local st, vr, fn, tb = tools.luatable_lister_recursive(table, "", tablename, 1, countonly, levelmaxi, max_n, exclude1, exclude2, exclude3) res = res .. st	tot_vars = tot_vars + vr	tot_func = tot_func + fn	tot_tabs = tot_tabs + tb res = res .. "\n* Content of the '''" .. tostring(tablename) .. "''' table, end: " res = res .. tools.str_vars(" %1 variables, %2 functions, %3 sub-tables.\n", vr, fn, tb) return res, tot_vars, tot_func, tot_tabs end -- function tools.luatable_lister(table, tablename, opt)

function tools.luatablecount(tab, tabname, recursive) if type(tools.recursivity) ~= "number" then tools.recursivity = 11111 end if type(recursive) ~= "number" then recursive = 1 end recursive = math.floor( recursive ) local t = "" local tot_vars, tot_func, tot_tabs = 0, 0, 0 local nbr_vars, nbr_func, nbr_tabs = 0, 0, 0 local txt, vr, fn, tb = "", 0, 0, 0 local level_max = 1000 if (type(tab) == "table") and (type(tabname) == "string") then -- for any tables -- normal case OK, do nothing elseif (type(tab) == "table") and (type(tabname) ~= "string") then -- for abnormal or missing tabname tabname = "tabname=" .. tostring(tab) .. "?"		tabname = tools.error_color(tabname) elseif (type(tab) ~= "table") and (type(tabname) == "string") then -- for abnormal table tabname = "tabname=" .. tostring(tabname) .. "?"		tabname = tools.error_color(tabname) elseif type(tab) == "string" then -- for tools.tables tabname = "tools." .. tab tab = tools[tab] else tabname = "tabname=" .. tostring(tab) .. "?"		tabname = tools.error_color(tabname) --	tabname = tostring(tabname) end if type(tab) == "table" then for key, var in pairs(tab) do -- List and count vars, functions and sub tables key = tostring(key) if type(var) == "table" then nbr_tabs = nbr_tabs + 1 if recursive < tools.recursivity then txt, vr, fn, tb, recursive = tools.luatablecount(var, tabname, recursive + 1) tot_vars = tot_vars + vr					tot_func = tot_func + fn					tot_tabs = tot_tabs + tb + 1 end elseif type(var) == "function" then nbr_func = nbr_func + 1 tot_func = tot_func + 1 isempty = false else -- type(var) == other nbr_vars = nbr_vars + 1 tot_vars = tot_vars + 1 isempty = false end end end t = t .. "'''" .. tabname .. "''': "	t = tools.str_vars("tools_luatable_counts", tabname, tot_vars, tot_func, tot_tabs) return t, tot_vars, tot_func, tot_tabs, recursive --	result example: The table args_known counts 161 texts, 0 functions and 24 sub-tables., 161, 0, 24, 3 end -- function tools.luatablecount(tab, tabname, recursive)

function tools.luatables_counts(t, ...) local t = t or "\n* Counts of contents of tables: " t = t .. " " .. tools.luatablecount(centre.i18n, "centre.i18n") t = t .. " " .. tools.luatablecount(tools.i18n, "tools.i18n") t = t .. " " .. tools.luatablecount(mathroman.i18n, "mathroman.i18n") --	t = t .. " " .. tools.luatablecount(p.i18n, "p.i18n") -- not available in any module t = t .. " " .. tools.luatablecount(centre.maini18n, "centre.maini18n") --	t = t .. " " .. tools.luatablecount("i18n") t = t .. " " .. tools.luatablecount("wiki_translations") t = t .. " " .. tools.luatablecount("user_translations") t = t .. " " .. tools.luatablecount("args_known") t = t .. " " .. tools.luatablecount("args_wikidata") --	t = t .. " " .. tools.luatablecount("args_invoke") --	t = t .. " " .. tools.luatablecount("args_template") t = t .. " " .. tools.luatablecount("args_source") t = t .. " " .. tools.luatablecount("args_config") t = t .. " " .. tools.luatablecount("args_import") t = t .. " " .. tools.luatablecount("args_final") t = t .. " " .. tools.luatablecount("args_unknown") --	t = t .. " " .. tools.luatablecount("args_selected") -- not available in any module t = t .. " " .. tools.luatablecount("errors_list") t = t .. " " .. tools.luatablecount("categories_list") t = t .. " " .. tools.luatablecount("loaded_pack") t = t .. " " .. tools.luatablecount("loaded_vers") --	t = t .. " " .. tools.luatablecount({}, "empty table") -- do not fail in errors cases --	t = t .. " " .. tools.luatablecount({}) -- do not fail in errors cases --	t = t .. " " .. tools.luatablecount(123.456) -- do not fail in errors cases --	t = t .. " " .. tools.luatablecount -- do not fail in errors cases return t end -- function tools.luatables_counts(t)

--	tools.i18n_trc = "-" function tools.i18n_trac(id, t, count) -- track for i18n DEBUG --	tools.i18n_trac("base_func", "end", 1) -- example of use t = t or "" t = t .. " '''" .. (id or "") .. "''' t=" .. t	if count then t = t .. " * " .. tools.luatablecount("i18n") t = t .. " * " .. tools.luatablecount("wiki_translations") t = t .. " * " .. tools.luatablecount("user_translations") end --	tools.i18n_trc = t	return t end

-- Manage errors and messages. Administrar errores y mensages. Gérer les erreurs et messages.

tools.errors_list = {} -- Table to collect errors and messages tools.erron = true -- Activated or not errors. Errores activado o no. Erreurs activées ou non.

-- Add a message, error or category to le lists. function tools.error_add(typ, ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) --	tools.err_add("tools_value_re_defined_err", k, key, xyz) if not tools.erron then return "" end local msg = { ["typ"] = typ, ["ref"] = ref, ["v1"] = v1, ["v2"] = v2, ["v3"] = v3, ["v4"] = v4, ["v5"] = v5, ["v6"] = v6, ["v7"] = v7, ["v8"] = v8, ["v9"] = v9 } local str = tools.str_vars(msg.ref, msg.v1, msg.v2, msg.v3, msg.v4, msg.v5, msg.v6, msg.v7, msg.v8, msg.v9) local do_it = true for k, reg in ipairs(tools.errors_list) do -- If the new error was previously registered, do not add it. local reg_txt = tools.str_vars(reg.ref, reg.v1, reg.v2, reg.v3, reg.v4, reg.v5, reg.v6, reg.v7, reg.v8, reg.v9) if str == reg_txt then do_it = false end end if do_it then table.insert(tools.errors_list, msg) end local res = "" if msg.typ == "msg" then res = ' ⦁ ' .. tools.message_color(str) end if msg.typ == "err" then res = ' ⦁ ' .. tools.error_color(str) end return res end -- function tools.error_add(typ, ref, v1, v2, v3, v4, v5, v6, v7, v8, v9)

function tools.err_add(ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) return tools.error_add("err", ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) end

function tools.msg_add(ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) return tools.error_add("msg", ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) end

function tools.errors_lister(title, v1, v2, v3, v4, v5, v6, v7, v8, v9) local res, msgref = "", "" --	res = res .. centre.luatable_lister(tools.errors_list, "tools.errors_list") local mwtitle = mw.title.getCurrentTitle local page = tostring(mwtitle.nsText) .. ":" .. tostring(mwtitle.text) if type(title) ~= "string" then title = "tools_error_list_header_err" end res = res .. '\n*' .. tools.str_vars(title, page, v1, v2, v3, v4, v5, v6, v7, v8, v9) -- .. ' - ' .. page local n = 0 for k, msg in ipairs(tools.errors_list) do		msgref = tools.str_vars(msg.ref, msg.v1, msg.v2, msg.v3, msg.v4, msg.v5, msg.v6, msg.v7, msg.v8, msg.v9) -- texte traduit ou direct if msg.typ == "msg" then res = res .. ' ⦁ ' .. tools.message_color(msgref) end end for k, msg in ipairs(tools.errors_list) do		msgref = tools.str_vars(msg.ref, msg.v1, msg.v2, msg.v3, msg.v4, msg.v5, msg.v6, msg.v7, msg.v8, msg.v9) -- texte traduit ou direct if msg.typ == "err" then res = res .. ' ⦁ ' .. tools.error_color(msgref) n = n + 1 end end if n > 0 then tools.cat_add("tools_module_with_error_err") end return res end -- function tools.errors_lister(title, v1, v2, v3, v4, v5, v6, v7, v8, v9)

--	Manage categories tools.categories_list = {} -- Table to collect all categories to generate in wikitext tools.catView = "" -- = ":" to document a category rather than truly categorize it

function tools.gener_categories(args_final) -- Only for this library, form categories without activate them if type(args_final) ~= "table" then args_final = tools.args_final end if args_final.birthyear then tools.cat_add("p_authors_birthyear_cat", args_final.birthyear) end if args_final.deathyear then tools.cat_add("p_authors_deathyear_cat", args_final.deathyear) end if args_final.description then --	tools.cat_add("p_authors_deathyear_cat", args_final.description) end return end -- function tools.gener_categories(args_final)

function tools.fenv_test(t) -- Test the stack to search names of modules. local t = t or "\n* fenv1 :" --	local env1 = getfenv(1) -- getfenv(1) fails when called t = t .. tools.luatable_lister(env1, "env1", { boxstyle = "boxstyle", levelmaxi = 1, max_n = 2 } ) t = "" return t --	It should be possible to get entity id from page title. See EntityIdLookup::getEntityIdForTitle. Project mediawiki/extensions/Wikibase --	res = res .. tools.dropdownfunc(select, "tools_luatable_tests_limits_title", tools.luatable_lister, tools.tablim, "tools.tablim", --		{ boxstyle = "boxstyle", levelmaxi = 2, max_n = 2, exclude1 = "hou" } ) --, {width = "88%", text_color = "blue"} --	if not sep then sep = "=" end end -- function tools.fenv_test(t)

function tools.ta(txt, val, sep) -- Formats an argument and its value in a documentation. The text is "nil" if the value is nil. if not val then val = "nil" end if not sep then sep = "=" end return ", " .. tostring(txt) .. " " .. tostring(sep) .. " ''' " .. tostring(val) .. " ''' " end

function tools.tam(txt, val, sep) -- Formats an argument and its value in a documentation. The text is "nil" if the value is nil. if not val then return "" end return tools.ta(txt, val, sep) end

function tools.all_versions_text(all_versions) -- DEBUG all_versions = all_versions or centre.all_versions if type(all_versions) == "string" then return all_versions end --	if type(all_versions) == "string" then all_versions = { all_versions } end if type(all_versions) == "table" then return table.concat(all_versions, " >> ") else return "" end end

function tools.track_i18n_t(t) tools.track_i18n_tt = (tools.track_i18n_tt or "track_i18n_tt ") .. (t or "track_i18n_tt") .. ":" .. tools.str_vars("err_J_before_end") .. " - "	return tools.track_i18n_tt -- .. " " .. tools.i18n_trc, see also track_i18n_vers end

function tools.warning_short --	t = t .. tools.track_i18n_vers return tools.report_main_short end

function tools.warning_small(d) -- samll display of the main module version local v, d, t = tools.versions, d or centre.d, "" --	t = t .. tools.warning_short(d) t = tools.str_vars(" " .. tools.report_main_short .. "  ") return t end

function tools.wiki_modules_users(t) -- Short counts of modules and users in this wiki. t = t or "Modules and users in this wiki: " t = t .. tools.ta("Modules", tostring(mw.site.stats.pagesInNamespace( 828 ) ) ) t = t .. tools.ta("activeUsers", tostring(mw.site.stats.activeUsers ) ) t = t .. tools.ta("Administrators(sysop)", tostring(mw.site.stats.usersInGroup( "sysop" ) ) ) t = t .. tools.ta("bots(bot)", tostring(mw.site.stats.usersInGroup( "bot" ) ) ) t = t .. tools.ta("patrollers(patroller)", tostring(mw.site.stats.usersInGroup( "patroller" ) ) ) t = t .. tools.ta("bureaucrats(bureaucrat)", tostring(mw.site.stats.usersInGroup( "bureaucrat" ) ) ) --	t = t .. tools.ta("checkuser(checkuser)", tostring(mw.site.stats.usersInGroup( "checkuser" ) ) ) --	t = t .. tools.ta("autoconfirmed(autoconfirmed)", tostring(mw.site.stats.usersInGroup( "autoconfirmed" ) ) ) --	t = t .. tools.ta("Autopatrol users(autoreview)", tostring(mw.site.stats.usersInGroup( "autoreview" ) ) ) --	t = t .. tools.ta("Account creators(accountcreator)", tostring(mw.site.stats.usersInGroup( "accountcreator" ) ) ) t = t .. " mw mw:Special:ListGroupRights " -- https://www.mediawiki.org/wiki/Special:ListGroupRights t = t .. " \n* Revision time and user language: " t = t .. tools.ta("REVISIONTIMESTAMP", tools.frame:preprocess( "" ) ) t = t .. tools.ta("CONTENTLANGUAGE", tools.frame:preprocess( "" ) ) t = t .. tools.ta("REVISIONUSER", tools.frame:preprocess( "" ) ) t = t .. tools.ta("USERLANG", tools.frame:preprocess( "" ) ) t = t .. tools.ta("UILANGCODE", tools.frame:preprocess( "" ) ) t = t .. tools.ta("USERIFCODE", tools.frame:preprocess( "" ) ) t = t .. tools.ta("USERLANGUAGE", tools.frame:preprocess( "" ) ) return t end -- function tools.wiki_modules_users(t)

function tools.warning_report(t) -- DEBUG: finish the migration by alias of "deprecated" fonctions. return tools.bindmodules_report(t) -- Test of binding of the modules and versions control tools_verif_bindmodules_report end -- function tools.warning_report(t)

function tools.args_known_structure(t, args_known) -- tools_args_known_structure_title = Table structure of arguments --	if true then return "" end -- to bypass in DEBUG local t = t or " * args_known_structure : " local tt	if type(args_known) ~= "table" then args_known = tools.args_known end for key, elem in pairs(args_known) do tt = tools.tam("typ", elem.typ) .. tools.tam("keyword", elem.keyword) .. tools.tam("syn", elem.syn) tt = tt .. tools.tam("need", elem.need) .. tools.tam("prop", elem.prop) .. tools.tam("format", elem.format) tt = string.sub(tt, 3, -1) t = t .. ' : ' .. tostring(key) .. ' = { ' .. tt .. ' } '	end return t end -- function tools.args_known_structure(t, args_known) old : -- tools_list_all_args_title table_args_known_title

-- relire Central/Auteur : module code in english

-- Miscelanous functions. Fonctions utilitaires.

function tools.table_iterator(t) -- iterator to use all elements of a table tree, one by one -- for noticeN in tools.table_iterator(notices_properties) do	-- modele : function list_iter (t) if type(t) ~= "table" then return {}, 0 ,0 end local i = 0 local n = table.getn(t) return function i = i + 1 n = table.getn(t) if t[i] ~= nil then return t[i], i ,n end end end -- function tools.table_iterator(t)

function tools.spaces_page_names_test(t) if type(t) ~= "string" then t = nil end local t = t or "\n* spaces_page_names_test :" local mwtitle = mw.title.getCurrentTitle t = t .. tools.ta("mwtitle", mwtitle) local nsText = mwtitle.nsText t = t .. tools.ta("nsText", nsText) local baseText = mwtitle.baseText -- namespace for the page t = t .. tools.ta("baseText", baseText) local url = tostring(mwtitle:canonicalUrl) t = t .. tools.ta("url", url) --	t = t .. "\n* Module namespace : " local ns = mw.site.namespaces if ns and ns[828] then t = t .. tools.ta("id828", ns[828].id) t = t .. tools.ta("canonicalName828", ns[828].canonicalName) t = t .. tools.ta("name828", ns[828].name) t = t .. tools.ta("displayName828", ns[828].displayName) end t = t .. "\n* All namespaces (from 0 to 2000) : " local ns = "" for ins = 0, 2000 do	--	if mw.site.contentNamespaces[ins] then if mw.site.namespaces[ins] then ns = mw.site.namespaces[ins].canonicalName t = t .. tools.ta(ns, ins) end end return t end -- function tools.spaces_page_names_test

-- Some usual fonctional styles for this module and those using it. -- Quelques styles fonctionnels banals dans ce module et ses modules appelants. function tools.error_color(t) -- Usual fonctional style for errors in red. return ' ' .. tostring(t) .. ' ' end

function tools.message_color(t) -- Usual fonctional style for messages in blue. return ' ' .. tostring(t) .. ' ' end

function tools.wikidata_color(t) -- Usual fonctional style for wikidata in green. return ' ' .. tostring(t) .. ' ' end

function tools.invoke_color(t) -- Usual fonctional style for invoke args in brown. return ' ' .. tostring(t) .. ' ' end

function tools.discreet_color(t) -- Usual fonctional style for discreet in light grey. return ' ' .. tostring(t) .. ' ' end

function tools.other_color(t) -- Usual fonctional style for other standard in black. return ' ' .. tostring(t) .. ' ' end

function tools.small_caps_style(t) -- Display a text in small-caps style. return ' ' .. t .. ' ' end

function tools.isDef(x) -- x is defined or no. x est défini ou non return (type(x) == "string") and (x ~= "") and (x ~= " ") and (x ~= "nil") end

function tools.tab_fields(tab) -- List the fields of a table if type(tab) ~= "table" then return tostring(tab) end local t = "" for key, val in pairs(tab) do t = t .. key .. ", "	end t = string.sub( t, 1, -3 ) return t end -- function tools.tab_fields(tab)

function tools.tab_pairs(tab) -- List a pairs table: Lister une table de pairs :"	local t = ""	for key, val in pairs(tab) do -- Pour tous les mots		t = t .. tostring(key) .. " = " .. tostring(val) .. ", "	end	t = string.sub( t, 1, -3 )	return t end -- function tools.tab_pairs(tab)

-- Build a table, with headers for columns. Example: -- ! style="text-align:left;"| Item -- {| class="wikitable" style="text-align: center; color: green;" -- {| border="1" style="border-collapse:collapse" -- {| class="wikitable sortable" border="1" mw-collapsible mw-collapsed" -- |} end of table function tools.Th(t) return '\n{| class="' .. tostring( t or 'wikitable alternative center' ) .. '" | ' end -- Table columns headers -- or " " -- A triable table start with : {| class="wikitable sortable" -- A column become fix and not triable with : ||class="unsortable"| -- A row become fix and not triable with : |- class="sortbottom" function tools.Tc(t) return '\n! scope="col" | ' .. tostring( t or " " ) end -- Table repeated or different columns headers function tools.Tr(t) return "\n|- " .. tostring( t or " " ) end -- Table -- row function tools.Td(t) return "\n| " .. tostring( t or " ") end -- Table data -- or " " function tools.Te(t) return "\n|}" end -- Table end

-- To do debug : Dropbox plus souple a traduire et parametrer par "style" une table de parametres nommés.

function tools.dropbox(title, content, boxstyle) -- alignT, image, alignB, margin_bottom, width, border_radius, border_color, background_color)	-- Form a drop box. Formar un cuadro desplegable. Former une boite déroulante.	local s = { -- options for style and other		title = tools.str_vars(title or "tools_dropdown_missing_title"),		content = content,		image = nil,		alignT = alignT or "left", -- align		alignB = alignB or "left", -- align		margin_all = margin_all or "0", -- margin		margin_bottom = margin_bottom or "1em", -- margin-bottom		width = width or "99%", -- width		border_radius = border_radius or "0", -- -border-radius		text_color = text_color or "black", -- color		background_color = background_color or "#fff", -- background-color		border_color = border_color or "#aaa", -- border-color		height = height or "1.6em", -- height		label = "&#x25bc;  /&#x25b6;   ", --	 = "Unwrap/Wrap",		-- ▼ = &#x25bc; -- ▶ = &#x25b6; https://fr.wikipedia.org/wiki/Table_des_caract%C3%A8res_Unicode/U25A0 --	label = label or tools.str_vars("tools_DropBox_label_Unwrap"), --	= "Unwrap/Wrap", = "Unwrap/Wrap", }	if type(boxstyle) == "table" then for key, val in pairs(boxstyle) do			if type(val) == "string" then s[key] = val end end end if type(title) ~= "string" then title = "tools_dropdown_missing_title" end s.title = tools.str_vars(title or "tools_dropdown_missing_title") if type(content) ~= "string" then content = "" end s.content = tools.str_vars(content) --	local txt = "" .. content .. "" --	image = image or "Nuvola_apps_bookcase_2.svg" -- image if type(s.image) == "string" then s.image = '' .. '' .. ''		.. ' ' -- 	else s.image = '' end local res = mw.html.create('div') :addClass('mw-collapsible') :css('padding', '4px') :css('font-size', '95%') :css('clear', 'both') :css('border', '1px solid ' .. s.border_color) :css('margin-bottom', s.margin_bottom) :css('width', s.width) :css('border-radius', s.border_radius) :css('background-color', s.background_color) :attr('title', s.label) :tag('div') :css('line-height', '1.6em') :css('font-weight', 'bold') :css('height', s.height) :css('color', s.text_color) :css('text-align', s.alignT) :wikitext(s.title) :done :tag('div') :addClass('mw-collapsible-content') :css('font-size', '100%') :css('margin', s.margin_all) :css('text-align', s.alignB) :wikitext(s.image .. s.content) :done :done -- -- alternative dropbox for template optimisation. Misses title.	local res = ''	.. ' ' -- \n--		.. ''			.. ' '				.. s.title			.. ' '			.. ''				.. s.image				.. s.content			.. ''		.. ' '	.. ' '	-- return tostring(res) end -- function tools.DropBox(title, content, boxstyle)

function tools.dropdown_func(select, title, content, ...) return tools.dropdownfunc (select, title, content, ...) end

function tools.dropdownfunc(select, title, content, ...) -- alignT, image, alignB, margin_bottom, width, border_radius, border_color, background_color)	-- select = "alltestsview" -- Deprecated, to view all boxes.	-- select = "allwaysview" -- To allways display one view. -- select = "enforcerun" -- To debug one box with INTERNAL ERROR.	if not ( (select == true) or (select == title) or (select == "allwaysview") or (select == "alltestsview") or (select == "enforcerun") ) then return "" end	local func = content	local t = ""	local args = { ... } -- optional arguments	local boxstyle = { }	local success, result	title = tools.str_vars(title or "tools_dropdown_missing_title")	if type(content) == "string" then		t = t .. content	elseif type(func) == "function" then		-- A function produces the wikitext.		-- Get the style options for the box, then mask this style for functions giving the content.		for i, tab in ipairs(args) do -- if type(tab) == "table" and tab.boxstyle == "boxstyle" then boxstyle = mw.clone( args[i] ) args[i] = nil end end -- select = "alltestsview" -- Deprecated, to view all boxes. -- select = "allwaysview" -- To allways display one view. -- select = "enforcerun" -- To debug one box with INTERNAL ERROR. if select == "enforcerun" then -- enforce run for one dropbox only. result = func( ... ) -- enforce run including in blocking cases, to debug it. success = true else success, result = pcall( func, ... ) -- replaces result = func( ... ) without blocking cases. --	title = title .. tools.error_color(" INTERNAL ERROR ") end if success then t = t .. result else -- In case of internal error, alert by a category and a clear not blocking display. tools.cat_add("tools_module_internal_error_cat") tools.categories_lister("") title = title .. tools.error_color(" function INTERNAL ERROR ") t = t .. tools.error_color(" See the internal error category. ") end --		In some cases the dropbox is not displayed for unknown reason, perhaps a bug in mediawiki.		After several tries to debug, Rical uses pcall to bypass the issue on 2015-12-15 14:38		res = res .. tools.dropdownfunc(1, "tools_luatables_counts_title", tools.luatables_counts)		res = res .. tools.dropdownfunc(1, "tools_spaces_page_names_title", tools.spaces_page_names_test)		Erreur Lua dans Module:Author3 à la ligne 2826 : attempt to concatenate field '?' (a nil value).		Pile des appels :		Module:Author3:2826 : dans la fonction « func »		Module:Central1:2638 : dans la fonction « dropdownfunc »		Module:Author3:4096 : dans la fonction « form_tests »		Module:Author3:4437 : dans la fonction « form_result »		Module:Author3:4804 : dans la fonction « chunk »		-- else t = "" tools.cat_add("tools_module_internal_error_cat") tools.categories_lister("") title = title .. tools.error_color(" INTERNAL ERROR ") t = t .. tools.error_color(" See the internal error category. ") end -- Search if the last arg is a table of args, then return it for DropBox style options. --	local maxn = table.maxn(args) --	if type(args[maxn]) == "table" then args = args[maxn] end --	return tools.dropbox( tostring(title), tostring(t), boxstyle) or "dropdownfunc" end -- function tools.dropdownfunc(select, title, content, ...)

-- Extract a part of date following a pre-defined format which starts with separator function tools.date_split(date, format) -- local dd, mmmm, yyyy, era = tools.date_split(a.birthdate, " dd mmmm yyyy") local dd, mmmm, yyyy, era local format_split = mw.text.split(format, "%s") local split = mw.text.split(date, "%s") for i, date_part in ipairs(split) do		if format_split[i] == "dd" then dd = tonumber(date_part) end if format_split[i] == "mmmm" then mmmm = date_part end if format_split[i] == "yyyy" then yyyy = tonumber(date_part) end if format_split[i] == "era" then era = date_part end end return dd, mmmm, yyyy, era end -- function tools.date_split(date, format)

-- Extract a part of date following a pre-defined format which starts with separator function tools.date_to_part(date, part) -- local t, err = tools.date_to_part(a.birthyear, " dd mmmm yyyy", "yyyy") part = part or "yyyy" local dd, mmmm, yyyy, era local found = false --	local err = "tools_date_to_part_not_found_err" if not found then dd, mmmm, yyyy, era = tools.date_split(date, "dd mmmm yyyy") if dd and mmmm and yyyy and not era then found = true end end if not found then dd, mmmm, yyyy, era = tools.date_split(date, "mmmm dd yyyy") if dd and mmmm and yyyy and not era then found = true end end if not found then dd, mmmm, yyyy, era = tools.date_split(date, "yyyy era") if not dd and not mmmm and yyyy then if era == "BCE" then yyyy = - yyyy end found = true end end if not found then dd, mmmm, yyyy, era = tools.date_split(date, "mmmm yyyy") if not dd and mmmm and yyyy and not era then --	tools_date_months_names				= "January, February, March, April, May, June, July, August, September, October, November, December", --	tools_date_months_names				= "Enero, Febrero, Marzo, Abril, Mayo, Junio​​, Julio, Agosto, Septiembre, Octubre, Noviembre, Diciembre", --	tools_date_months_names				= "Janvier, Février, Mars, Avril, Mai, Juin, Juillet, Août, Septembre, Octobre, Novembre, Décembre", found = true end end if not found then dd, mmmm, yyyy, era = tools.date_split(date, "yyyy") if not dd and not mmmm and yyyy and not era then found = true end end -- + cccc = roman number ? if found then if part == "yyyy" then return yyyy or "" end if part == "mmmm" then return mmmm or "" end if part == "dd" then return dd or "" end if part == "era" then return era or "" end end return "" -- tostring(dd)..tostring(mmmm)..tostring(yyyy)..tostring(era) --	A faire : Titus Livius (Q2039), format de dates : P569 = date of birth = 59 BCE, P570 = date of death = 17 --	Socrate (470-399 av. J.-C.). end -- function tools.date_to_part(date, part)

-- relire Central/Auteur : module code in english

-- Manage translations of arguments and messages -- Gestione traducciones de argumentos y mensajes -- Gérer les traductions des arguments et messages

function tools.trans(key) -- give the wiki translation of indentified texts, or arguments indentifier, or errors messages local t = tools.wiki_translations[key] if t == nil then t="" end return t end

function tools.get_IETF_fr -- Chargement de la base de donnée des langues avec gestion d'erreur. -- voir, see : https://fr.wikipedia.org/wiki/Module:Langue local dataLangue local success, resultat = pcall (mw.loadData, 'Module:Langue/Data' ) if success then dataLangue = resultat else -- Base de donnée à minima en cas de bug sur le Module:Langue/Data dataLangue = { en = { code = 'en', nom = 'anglais' }, fr = { code = 'fr', nom = 'français' }, de = { code = 'de', nom = 'allemand' }, es = { code = 'es', nom = 'espagnol' }, it = { code = 'it', nom = 'italien'	 }, la = { code = 'la', nom = 'latin'	 }, --			['rtl script'] = { Arab = true }, -- debug : risque d'anomalie, anomaly risc }		dataLangue.anglais = dataLangue.en		dataLangue['français'] = dataLangue.fr		dataLangue.francais = dataLangue.fr		dataLangue.allemand = dataLangue.de		dataLangue.espagnol = dataLangue.es		dataLangue.italien = dataLangue.it	end return dataLangue end -- function tools.get_IETF_fr

function tools.dummy_languages -- Test dummy languages -- https://fr.wikipedia.org/wiki/%C3%89tiquette_d%27identification_de_langues_IETF -- https://fr.wikipedia.org/wiki/Module:Langue/Data --	pour convertir en code de langue IETF les noms français de langues -- https://www.mediawiki.org/wiki/Manual:$wgDummyLanguageCodes --	List of language codes that have been renamed to new (correct) codes, or don't correspond to an actual interface language. --	array( 'als' => 'gsw', 'bat-smg' => 'sgs', 'be-x-old' => 'be-tarask', 'bh' => 'bho'...	local dummy_i18n = {		en = "Module:Central/I18N", -- english		es = "Modul:Central/I18N", -- spanish		fr = "Module:Central/I18N", -- french		Fr = "Module:Central/I18N", -- error test		als = "Modulen:Central/I18N", -- alemanish		gsw = "Mod-gsw:Central/I18N", -- unknown		["bat-smg"] = "Mod-bat-smg:Central/I18N", -- alemanish		sgs = "Mod-sgs:Central/I18N", -- unknown	}	local t = '\n* dummy_languages : ' .. tools.ta("isTag", "isKnownLanguageTag(xx)") .. tools.ta("isLang", "isSupportedLanguage(xx)") .. tools.ta("isBuilt", "isValidBuiltInCode(xx)")	t = t .. tools.Th .. tools.Tc("lang") .. tools.Tc("isTag") .. tools.Tc("isLang") .. tools.Tc("isBuilt")	t = t .. tools.Tc("langname") .. tools.Tc("native")	for lang, modname in pairs(dummy_i18n) do -- Pour tous les parametres connus		local isTag = mw.language.isKnownLanguageTag(lang) local isLang = mw.language.isSupportedLanguage(lang) local isBuilt = mw.language.isValidBuiltInCode(lang) local langname = mw.language.fetchLanguageName(lang, "en") local native = mw.language.fetchLanguageName(lang) local space_name = tostring(mw.site.namespaces.Module.name) t = t .. tools.Tr .. tools.Td(lang) .. tools.Td(isTag) .. tools.Td(isLang) .. tools.Td(isBuilt) t = t .. tools.Td(langname) .. tools.Td(native) end t = t .. tools.Te return t end -- function tools.dummy_languages

function tools.list_loaded_modules(t) t = t or "" t = t .. "\n* list_loaded_modules: " --	local loaded_libs = centre.get_loaded_modules -- List all libraries with internal .i18n translations for name, library in pairs(package.loaded) do t = t .. tools.ta(type(library), name ) end return t .. " " end -- function tools.list_loaded_modules(t)

tools.trac_lang_t = "" -- "track_lang: " function tools.trac_lang(where, args_tab) -- res = res .. tools.trac_lang("tools.init_args:", args_source) -- DEBUG tools.trac_lang_t = tools.trac_lang_t .. " '''" .. where .. "'''"	tools.trac_lang_t = tools.trac_lang_t .. tools.ta(".c", args_tab.c) tools.trac_lang_t = tools.trac_lang_t .. tools.ta(".userlang", args_tab.userlang) .. tools.ta(".wikilang", args_tab.wikilang) .. ":u." .. tools.user_lang .. "=" .. (tools.user_translations["title"] or "x") .. ":w." .. tools.wiki_lang .. "=" .. (tools.wiki_translations["title"] or "x") .. " " end

-- en : initialize or change the user and the wiki languages and their tables -- es : inicializar o cambiar el idiomas del usuario y del wiki y su tablas -- fr : initialiser ou modifier la langue de l'utilisateur et du wiki et leurs tables function tools.init_wiki_user_lang(wiki_lang, user_lang) -- initialize or change the user and the wiki languages and their tables local get_lang = mw.language.getContentLanguage.code -- default wiki_lang local wiki_lang = wiki_lang or tools.args_config.wikilang local user_lang = user_lang or tools.args_config.userlang -- WIKI if wiki_lang and centre.maini18n and centre.maini18n[wiki_lang] then -- Activate the wiki language for errors, messages and categories. tools.wiki_lang = wiki_lang else -- if asked is unavailable uses wiki_lang. tools.err_add("tools_lang_not_exist_err", wiki_lang) tools.wiki_lang = get_lang -- wiki_lang or tools.wiki_lang or get_lang end if tools.wiki_lang and centre.maini18n and centre.maini18n[tools.wiki_lang] then centre.wiki_translations = centre.maini18n[tools.wiki_lang] tools.wiki_translations = centre.wiki_translations end -- USER local get_lang = mw.language.getContentLanguage.code -- default user_lang if user_lang and centre.maini18n and centre.maini18n[user_lang] then -- Activate the wiki language for errors, messages and categories. tools.user_lang = user_lang else -- if asked is unavailable uses user_lang. tools.err_add("tools_lang_not_exist_err", user_lang) tools.user_lang = get_lang -- user_lang or tools.user_lang or get_lang end if tools.user_lang and centre.maini18n and centre.maini18n[tools.user_lang] then centre.user_translations = centre.maini18n[tools.user_lang] tools.user_translations = centre.user_translations end end -- function tools.init_wiki_user_lang(wiki_lang, user_lang)

function tools.init_user_lang(user_lang, wiki_lang) --	t = "\n* init_user_lang : sought user_lang = " .. tostring(user_lang) -- user_lang ok if i18n ok, else wiki language if type(user_lang) ~= "string" then user_lang = nil end if user_lang and centre.maini18n and centre.maini18n[user_lang] then -- Activate the user language for errors, messages and categories. tools.user_lang = user_lang or mw.language.getContentLanguage.code else -- degraded mode : = wiki_lang can replace missing user_lang. tools.err_add("tools_lang_not_exist_err", user_lang) -- Error if the language is not a wikipedia language tools.user_lang = user_lang or mw.language.getContentLanguage.code or "en" end centre.user_translations = centre.maini18n[tools.user_lang] tools.user_translations = centre.user_translations -- DEBUG wait for : T68051 Give at modules the user language to display errors and categories names for him local mwtitle = mw.title.getCurrentTitle local mwuri = mw.uri.canonicalUrl(mwtitle.prefixedText, { host, authority, user, password, } ) --	tools.trac_lang_t = tools.trac_lang_t .. tools.ta("host", tostring(mwuri.host)) .. tools.ta("authority", tostring(mwuri.authority)) return -- t .. " " end -- function tools.init_user_lang(user_lang)

-- Manage categories. Administrar categorías. Gérer les catégories.

function tools.catGen(ref, v1, v2, v3, v4, v5) -- add a category to the categories_list table.insert(tools.categories_list, { ["typ"] = "cat", ["ref"] = ref, ["v1"] = v1, ["v2"] = v2, ["v3"] = v3, ["v4"] = v4, ["v5"] = v5, ["v6"] = v6, ["v7"] = v7, ["v8"] = v8, ["v9"] = v9 }) end

-- Record in categories_list and genrate the wikitext of a category function tools.cat_add(ref, v1, v2, v3, v4, v5, v6, v7, v8, v9) -- add a category to the categories_list local cat = { ["typ"] = "cat", ["ref"] = ref, ["v1"] = v1, ["v2"] = v2, ["v3"] = v3, ["v4"] = v4, ["v5"] = v5, ["v6"] = v6, ["v7"] = v7, ["v8"] = v8, ["v9"] = v9 } local str = tools.str_vars(cat.ref, cat.v1, cat.v2, cat.v3, cat.v4, cat.v5, cat.v6, cat.v7, cat.v8, cat.v9) local do_it = true for k, reg in ipairs(tools.categories_list) do -- If the new category was previously registered, do not add it. local reg_txt = tools.str_vars(reg.ref, reg.v1, reg.v2, reg.v3, reg.v4, reg.v5, reg.v6, reg.v7, reg.v8, reg.v9) if str == reg_txt then do_it = false end end if do_it then table.insert(tools.categories_list, cat) end --	local c = tools.catView or tools.catView or "" --	if tools.catView == true or tools.catView == true then c = ":" else c = "" end local wiki_catspace = mw.site.namespaces.Category.name -- tools.wiki_translations.category or	local user_catspace = mw.site.namespaces.Category.name -- tools.user_translations.category or	local user_cat = tools.string_vars(tools.user_translations, cat.ref, cat.v1, cat.v2, cat.v3, cat.v4, cat.v5, cat.v6, cat.v7, cat.v8, cat.v9) local wiki_cat = tools.string_vars(tools.wiki_translations, cat.ref, cat.v1, cat.v2, cat.v3, cat.v4, cat.v5, cat.v6, cat.v7, cat.v8, cat.v9) --	user_cat = (user_cat or "") local user_verif = string.match( user_cat, "([%w_])") -- verif content with all alphanumeric characters. if not user_verif then user_verif = ":" .. user_cat .. ":" end --	user_cat = user_verif or ("<" .. user_cat .. ">") --	user_catspace = "" -- without "Category" word local wiki_catspace = mw.site.namespaces.Category.name -- name: Local namespace name. local res = " " .. user_catspace .. " " .. user_cat .. " " return res end -- function tools.cat_add(ref, v1, v2, v3, v4, v5)

-- Generate categories from plural values in only one argument function tools.catGroup(groupCat, groupList) -- generate some categories -- catGroup("Country %1", "France,Italie") -> if type(groupCat) ~= "string" then groupCat = "%1" end if type(groupList) ~= "string" then return "" end local cats = "" local t = "" t = t .. tools.ta("groupList", groupList) local splitxt = mw.text.split(groupList, ",", true) --	t = t .. " splitxt = " .. table.concat(splitxt, "+") for str in mw.text.gsplit(groupList, ",", true) do --	t = t .. ", s=" .. tools.cat_add(groupCat, str) cats = cats .. tools.cat_add(groupCat, str) end return cats, t end -- function tools.catGroup(groupCat, groupList)

function tools.options_to_catView -- Init or restaure tools.catView = tools.catView from options if tools.option(":") or tools.option("catview") then tools.catView = ":" ; tools.catView = ":" else tools.catView = "" ; tools.catView = "" end return tools.catView end -- function tools.options_to_catView

tools

-- generate the wikitext of the list of categories to only display them function tools.categories_lister(c) local res = "" -- "\n* Catégories : " local wiki_cat = "" local user_cat = "" tools.options_to_catView -- c can replace catView to enforce the documentation or the categorisation -- c peut remplacer catView pour forcer la documentation ou la catégorisation c = c or tools.catView or "" local user_catspace = mw.site.namespaces.Category.name -- Local namespace name. local wiki_catspace = mw.site.namespaces.Category.name -- Local namespace name. for k, cat in ipairs(tools.categories_list) do		user_cat = tools.string_vars(tools.user_translations, cat.ref, cat.v1, cat.v2, cat.v3, cat.v4, cat.v5, cat.v6, cat.v7, cat.v8, cat.v9) wiki_cat = tools.string_vars(tools.wiki_translations, cat.ref, cat.v1, cat.v2, cat.v3, cat.v4, cat.v5, cat.v6, cat.v7, cat.v8, cat.v9) user_catspace = "" -- without "Category" word user_cat = (user_cat or "") -- prize if user_cat == " " then user_cat = "" end if user_cat == " " then user_cat = "" end if user_cat == "	" then user_cat = "" end --	local user_verif = string.match( user_cat, "([%w_])") -- verif content with all alphanumeric characters. --	user_verif = mw.ustring.gsub( user_cat, "(%s)", "") -- verif content with all alphanumeric characters. local user_verif = mw.ustring.gsub( user_cat, "%s", "") -- verif content with all alphanumeric characters. if not user_verif then user_verif = "1" .. user_cat .. "2" end --	user_cat = user_verif or ("<" .. user_cat .. ">") res = res .. " " .. user_catspace .. user_cat .. " " end -- Category namespaces = 14 Category -- https://en.wikipedia.org/wiki/IETF_language_tag -- https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes --	res = res .. tools.track_i18n_vers return res end -- function tools.categories_lister(c)

-- Initialize the categories list. Initialise la liste des categories. function tools.categories_init(catName, catText) -- initialize the category list tools.categories_list = {} -- init the collect of categories return end

function tools.tasks_table_report(t, short) -- List the state of known bugs or tasks. t = t or "" t = t .. " * = ( detected state )" local head = mw.text.split( tools.str_vars("tools_tasks_table_report_headers"), ',') --	function one_task_short(task, detect, state, name, shortext) local task = task or "T0000" if not state then return " '''" .. task .. "''': " end if (state == "Resolved") or (state == "OK") then shortext = tools.message_color(shortext) elseif state == "args" then shortext = tools.other_color(shortext) else shortext = tools.error_color(shortext) end if detect == 1 then shortext = shortext .. " *" end local phabtask = "" .. task .. "" local t = phabtask .. ":'''" .. shortext .. "''', "		return t	end --	function one_task(short, task, detect, state, name, shortext) local task = tostring(task) or "T0000" -- task or		if short then return one_task_short(task, detect, state, name, shortext) end --	local head = mw.text.split( tools.str_vars("tools_tasks_table_report_headers"), ',') local phabtask = "" .. task .. "" if (state == "Resolved") or (state == "OK") then name = tools.message_color(name) elseif state == "args" then name = tools.other_color(name) elseif name then name = tools.error_color(name) end if detect == 1 then name = name .. " - ( detected state )" end local t = "" --	t = t .. one_task(short, "T122752", 1, centre.T122752_status, "#invoke do not record the main module in package.loaded", "invoke# main not loaded") if name and phabtask then t = t .. tools.Tr .. tools.Td(phabtask) .. tools.Td(state) .. tools.Td(name) elseif task and state and name then t = t .. tools.Tr .. tools.Td(task) .. tools.Td(state) .. tools.Td(name) elseif (type(task) == "string") and (not state) then t = t .. tools.Tr .. tools.Tc(task) .. tools.Tc("-") .. tools.Tc("-") elseif task and (not state) then t = t .. tools.Tr .. tools.Tc(task) .. tools.Tc("...") .. tools.Tc("...") end return t	end --	t = t .. " Used colors: " .. tools.ta("Resolved", tools.message_color("task already completed") ) .. tools.ta("args", tools.other_color("task replaced by arguments or by the module") ) .. tools.ta("other", tools.error_color("other tasks") ) if not short then t = t .. tools.Th .. tools.Tc(head[1]) .. tools.Tc(head[2]) .. tools.Tc(head[3]) end t = t .. one_task(short, "Important") t = t .. one_task(short, "T53660", 0, "Open", "Detect the edit state to adapt help messages to user errors", "edit state") centre.T68051_status = mw.uri.new.userLanguage if centre.T68051_status then centre.T68051_status = "Resolved" else centre.T68051_status = "args" end -- T68051 Any title with datas in wikibase give its item.id to any module. Probably across mw.uri.new.userLanguage t = t .. one_task(short, "T68051", 1, centre.T68051_status, "Give at modules the user language to display errors and categories names for him", "user language") t = t .. one_task(short, "T119978", 0, "Invalid", "Get the own module name and last record date-time from each module", "own module name") t = t .. one_task(short, "T85419", 0, "Open", "User groups should be exposed to Scribunto", "user groups") -- to adapt errors and warning for administrators or modules coders t = t .. one_task(short, "T122752", 1, centre.T122752_status, "#invoke do not record the main module in package.loaded", "invoke# main not loaded") t = t .. one_task(short, "T67507", 0, "Closed", "It should be possible to get entity id from page title. See EntityIdLookup::getEntityIdForTitle.", "entity id from title") -- T67507 = Wikibase\Store\EntityIdLookup::getEntityIdForTitle can do this. t = t .. one_task(short, "T123196", 0, "Resolved", "Access to item from talk page", "Access from talk page") -- T123196 description = There is a function in the mw.wikibase module (client/includes/DataAccess/Scribunto/mw.wikibase.lua, around line 65) which gets the item ID based on mw.title.getCurrentTitle.prefixedText, this means for me that we could change it to content page name (since talk pages won’t have own connected items, so it won’t cause conflict). local mwtitle = mw.title.getCurrentTitle local url = tostring(mwtitle:canonicalUrl) --	centre.T133498_status = mw.uri.canonicalUrl -- mw.uri.canonicalUrl local title_object = mw.title.new(url) -- .itemid -- mw.uri.canonicalUrl if title_object then centre.T133498_status = title_object.itemid end -- mw.uri.canonicalUrl if centre.T133498_status then centre.T133498_status = "Resolved" else centre.T133498_status = "Open" end -- Any title with datas in wikibase give its item.id to any module. Probably across mw.title.new.itemid t = t .. one_task(short, "T133498", 1, centre.T133498_status, "Any title in wikibase can give its item id to modules", "wikidata from title.itemid") t = t .. one_task(short, "Central") t = t .. one_task(short, "T121470", 0, "Open", "Central Global Repository for Templates, Lua modules, and Gadgets", "central repository") t = t .. one_task(short, "T135845", 0, "Open", "Convert any module as central or centralisable", "Convert as central") t = t .. one_task(short, "T52329", 0, "Stalled", "We need a common repository for Scribunto modules and templates", "common repository") t = t .. one_task(short, "T41610", 0, "Resolved", "Scribunto should support global module invocations", "global invocations") t = t .. one_task(short, "Marginal") t = t .. one_task(short, "T63958", 0, "Open", "Use existing $dateFormats to format dates on Wikidata", "existing $dateFormats") t = t .. one_task(short, "T85412", 0, "Open", "The formatPropertyValues needs an option to format data from date-time, angle or geographic coordinates", "format date-time") t = t .. one_task(short, "T75460", 0, "Resolved", "[Story] Make Lua functions default to the user's language on multilingual wikis", "multilingual wikis") if not short then t = t .. tools.Te end return t end -- function tools.tasks_table_report(t, short)

-- Manage options. Administrar opciones. Gérer les options.

--	Options de maitrise du fonctionnement de ce module

tools.invoke_options = "" -- Options normales venant du modèle. Aucune par defaut. Normal options from the template. --	In the template : options = "params docview docmin docmax docdef docnotice docafter docline docsrc"

- tools

tools.mode_options = "" -- Options de debug du module par edit. Aucune par defaut. -- tools.mode_options = "unitest debug noerr erron params docview nobox nocat docin docmax docnotice docdef docline docsrc notices " -- tools.mode_options change only by editing this module code or the calling module. Empty default value. -- tools.mode_options change n'est modifié que par ce module ou celui qui l'appele. Valeur par defaut vide.

tools.used_options = {} -- table to collect tested options then list them at end of tests

--	if tools.option(":") or tools.option("catview") then tools.catView = ":" ; tools.catView = ":" else tools.catView = "" ; tools.catView = "" end

function tools.option(key, opt) -- if option("nocat") then cat = "" end -- utilisation exemple simple -- Si le mot key est parmi les mots options, repondre true -- Chercher dans invoke_options, mode_options ou opt, voir ci-dessous -- tools.options = " : docdata docmin docdef docmax docline docview docsrc docafter docnotice " -- for documentation -- tools.options = " erron noerr nobox nocat " -- without normal result -- tools.options = " debug tests en es fr " -- for debug or enforce language -- Veiller à toujours séparer les mots par des espaces -- Les identifiants de langues permettent de forcer certaines langues. -- Les erreurs n'apparaissent que dans les espaces de noms Modèle ou Module, en attendant la réalisation du Bug 51660. if type(key) ~= "string" then key = false end if type(opt) ~= "string" then opt = false end local available_options = " " .. (tools.invoke_options or "") .. " "	if opt -- opt param can replace tools.mode_options then available_options = " " .. opt .. " " .. available_options .. " "		else available_options = " " .. tools.mode_options .. " " .. available_options .. " "	end -- options du modèle et de debug sinon -- Chercher le mot clef exact, non inclus dans un autre. -- Search the exact key, not included in another. local key2 = " " .. (key or "				 ") .. " "	-- Le mot cle est-il parmi les options definies ? -- The searched keyword is it among the options words? local n = string.find(available_options, key2) local ifyes = n and (n > 0) if not ifyes then ifyes = false else ifyes = true end -- collect options tested along the execution of the module if ifyes then tools.used_options[key] = "a" else tools.used_options[key] = "x" end return ifyes, available_options -- ( yes ~= nil ) end -- function tools.option(key, opt)

function tools.init_options(opt) -- tools.invoke_options = init_options(args.options) -- tools.invoke_options = init_options("fr params docview docmin docmax docdef docnotice docafter docline docsrc") --	if (type(opt) == "string") then tools.invoke_options = opt end --	 and (new ~= "") --	-- Early effects on options which modify other ones. -- Effets précosses pour des options qui agissent sur d'autres options. -- tools.options = " : docdata docmin docdef docmax docline docview docafter docnotice docsrc" -- for documentation -- tools.options = " erron noerr nobox nocat " -- without normal result -- tools.options = " debug tests en es fr " -- for debug or enforce language tools.options_to_catView if tools.option("noerr") then tools.erron = false end if tools.option("erron") then tools.erron = true end if tools.option("docolor") then tools.docolor = true end -- If an option is a language, enable this language for the user. -- Si una opción es un lenguaje, activar esta lengua para usuario. -- Si une option est une langue, activer cette langue pour l'utilisateur. local _lang for lang, tab in pairs(tools.i18n) do		if tools.option(lang) then --		tools.init_user_lang(lang, tools.wiki_lang) -- tools.user_lang, tools.wiki_lang --		_lang = lang end end --	if _lang then tools.option(_lang) end --	tools.init_user_lang(nil) --, tools.args_final.wikilang)	return opt end -- function tools.init_options(opt)

function tools.used_options_list(t, used_options) local t = "List of modes:" or t	for md, opt in pairs(tools.options_for_modes) do t = t .. " - " .. tools.ta(md, opt) end -- List of used options after collect them used_options = used_options or tools.used_options t = t or "" t = t .. "\n* " .. tools.str_vars("tools_user_wiki_lang_msg", tools.user_lang, tools.wiki_lang) -- ( or tools.str_vars("tools_user_wiki_lang_msg", tools.user_lang, tools.wiki_lang) or " missing user_wiki_lang_msg " ) t = t .. "\n* Actual mode used: '''" .. tools.mode_name .. "'''"	t = t .. "\n* Options read the last time in these tests, ones activated are in bold: " t = t .. "\n* Options lues pour la dernière fois pendant ces tests, celles activées sont en gras : " t = t .. " "	local opt = "" for key, x in pairs(tools.used_options) do if x == "a" then opt = opt .. ", '''" .. tostring(key) .. "''' "		else opt = opt .. ", " .. tostring(key) .. " " end end t = t .. opt --	t = t .. " * " .. tools.get_editstate --	t = t .. "\n* import_arguments_track : " .. tools.import_arguments_track return t, opt end -- function tools.used_options_list(t, used_options)

function tools.options_from_args_test(t) local mode_options_memo = tools.mode_options -- save local invoke_options_memo = tools.invoke_options -- save local used_options_memo = mw.clone(tools.used_options) -- save tools.used_options = {} local t = "options_from_args_test:" or t	t = t .. tools.Th .. tools.Tc("mode_options") .. tools.Tc("invoke_options") .. tools.Tc("opt can replace mode_options") .. tools.Tc("available options") .. tools.Tc("option result") local function options_from_args(mode_options, invoke_options, opt, key) tools.mode_options = mode_options tools.invoke_options = invoke_options local ifyes, available_options = tools.option(key, opt) return tools.Tr .. tools.Td(mode_options or "") .. tools.Td(invoke_options or "") .. tools.Td(opt or "") .. tools.Td( tostring(available_options) ) .. tools.Td(tools.ta(key, ifyes) ) end t = t .. options_from_args("nobox nocat", "en docview", nil,			"nobox") t = t .. options_from_args("nobox nocat", "en docview", nil,			"nocat") t = t .. options_from_args("nobox nocat", "en docview", nil,			"en") t = t .. options_from_args("nobox nocat", "en docview", nil,			"docview") t = t .. options_from_args("nobox nocat", ": docview",	nil,			":") t = t .. options_from_args("nobox nocat", "en docview", "docline fr",	"docline") t = t .. options_from_args("nobox nocat", "en docview", "docline fr",	"docline") t = t .. options_from_args("		  ", nil,			"docline fr",	"docline") t = t .. options_from_args("		  ", nil,			"docline fr",	"fr") t = t .. options_from_args("		  ", "en docview", "docline fr",	"en") t = t .. options_from_args("nobox nocat", nil,			"docline fr",	"docline") t = t .. options_from_args("nobox nocat", "en docview", "docline fr",	nil) t = t .. options_from_args("nobox nocat", "en docview", nil,			"docline") t = t .. tools.Te t = t .. tools.used_options_list(nil, tools.used_options) t = t .. "\n* After these tests, anterior options are restored. Après ces tests, les options antérieures sont restaurés." tools.mode_options = mode_options_memo -- restore tools.invoke_options = invoke_options_memo -- restore tools.used_options = used_options_memo -- restore return t end -- function tools.options_from_args_test(t)

function tools.wordstotable(txt, opt) -- convertit un texte en table de mots local t = "" local tab = {} local function inserer(ti) if ti ~= "" then table.insert(tab, ti.."") end end local xyz = string.gsub( txt, "(%S*%-*%S*)", inserer ) -- "(%w*%-*%'*%w*)", "(%S*%-*%S*)" for key, val in pairs(tab) do -- Pour tous les mots t = t .. " ( " .. tostring(key) .. " = " .. tostring(val) .. " ) " end t = "\n* wordstotable txt = " .. tostring(xyz) .. " " .. t	return tab, t, opt end -- function tools.wordstotable(txt, opt)

-- Argts : Manage arguments. Gestione argumentos. Gérer les arguments.

-- Compute the Levenshtein distance between 2 ASCII words. function tools.levenshtein(word1, word2) -- prevent exceptions local cout = 0 if (word1 == nil) or (word2 == nil) then return 999, " lev: " .. tools.ta("word1", word1) .. tools.ta("word2", word2) end local len1 = string.len(word1) local len2 = string.len(word2) local lev = 0 local t = " lev: " .. tools.ta("word1", word1) .. tools.ta("word2", word2) if (type(word1) ~= "string") or (type(word2) ~= "string") or (word1 == "") or (word2 == "") then lev = len1 + len2 return lev, t .. tools.ta("lev", lev) end -- simple case if (word1 == word2) then lev = 0 return lev, t .. tools.ta("lev", lev) end local d = {} for i = 1, len1+2 do -- for i = 1, len1-1+1 do		d[i] = {} --	d[i][1] = 0 -- d[i][1] = i		for j = 1, len2+2 do			--	d[i][j] = {} d[i][j] = 0 -- d[1][j] = j		end end -- simulate double dimensions tables for i = 2, len1+1 do -- for i = 1, len1-1+1 do		--	d[i] = {} d[i][1] = i-1 -- d[i][1] = i	end for j = 2, len2+1 do		d[1][j] = j-1 -- d[1][j] = j	end for i = 2, len1+1 do -- for i = 2, len1+1 do		for j = 2, len2+1 do -- for j = 2, len2+1 do			-- on récupère les deux caractères local c1 = string.byte(word1, i-1) local c2 = string.byte(word2, j-1) if (c1 == c2) then cout = 0 d[i][j] = d[i-1][j-1] else cout = 1 d[i][j] = math.min(d[i-1][j], d[i][j-1], d[i-1][j-1]) + 1 end --	d[i][j] = math.min(d[i-1][j]+1, d[i][j-1]+1, d[i-1][j-1]+cout) end end local lev = d[len1+1][len2+1] -- return d[len1-1][len2] - 1 return lev, t .. tools.ta("lev", lev) end -- function tools.levenshtein(word1, word2)

function tools.levenshtein_test_1(search, word, max) -- search = mot cherché dans la liste -- word = un des mot de la liste local diffmaxi = tools.similar_args_diffmaxi( string.len(search) ) local len1, len2, lev, tlev, t, diff --	t = t .. " - diff: " .. tools.ta("mot1", mot1) .. tools.ta("mot2", mot2) .. tools.ta("diff", diff) t = " levenshtein : " if (not search ) or (not word) then diff = 99 t = t .. tools.ta("diff", diff) .. " no word. " elseif search == word then diff = 0 t = t .. tools.ta("diff", diff) .. ", " .. search .. " = " .. word .. " "	else --	len1 = string.len(search) --	len2 = string.len(word) lev, tlev = tools.levenshtein(search, word) if (lev <= diffmaxi) then t = t .. tools.ta("diffmaxi", diffmaxi) .. " >= " .. tools.ta("lev", lev) .. " '''" .. search .. " ==> " .. word .. "''' "		else t = t .. tools.ta("diffmaxi", diffmaxi) .. " >= " .. tools.ta("lev", lev) .. " " .. search .. " / " .. word .. " "		end diff = lev end return diff, t, search, word end -- function tools.levenshtein_test_1(search, word, max)

function tools.levenshtein_test(res, c)	if type(res) ~= "string" then res = nil end local res = res or ("\n* " .. tools.str_vars("tools_max_nearest_argument_msg") ) local errors = "" local n, t = tools.levenshtein_test_1( "nom", "nom") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "nom", "Nom") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "top", "pot") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "ami", "amis") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "nom", "name") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "m", "mu") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "m", "mur") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "mur", "m") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "c", "C") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "c", "cf") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "c", "long") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "xxx", "") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "", "xyz") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "xxx", "xyz") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "prénom", "Prenom") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "catégorie", "Category") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "description", "Description") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "anneeDeces", "anneeNaissance") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "anoNacimiento", "anneeNaissance") res = res .. tostring(t) local n, t = tools.levenshtein_test_1( "avant-après", "après-avant") res = res .. tostring(t) if errors ~= "" then res = res .. "\n* levenshtein_test errors = " .. tools.error_color(errors) end return res end -- function tools.levenshtein_test( res, c)

tools.constants = tools.constants or {} -- Similar words search : diff on length -- Cerrar de palabras puscadas: diff en longitud -- Recherche de mots proches: diff sur longueur tools.constants.near_word_search_diff_coef = 0.30 -- Access to change these constants from anywhere. tools.constants.near_word_search_diff_const = 0.82

-- Maximum number of different letters between 2 argument names -- Número máximo de letras diferentes entre 2 nombres de argumento -- Nombre maximum de lettres différentes entre deux noms d'arguments function tools.similar_args_diffmaxi(length, t) -- diffmaxi from length of arg arglingual name local coef = tools.constants.near_word_search_diff_coef or 0.30 local constant = tools.constants.near_word_search_diff_const or 0.82 local diffmaxi = math.floor( coef * length + constant ) if t then t = t .. tostring(coef) .. " * length + " .. tostring(constant) end return diffmaxi, t end -- function tools.similar_args_diffmaxi(length, t)

-- Pour un argument inconnu, cherche le nom d'argument le plus proche, parmi les arguments connus traduits function tools.similar_args_list(args_known) local list, arglingual = {}, "xxx" if type(args_known) ~= "table" then args_known = tools.args_known end if type(args_known) ~= "table" then return "similar_args_list", 1 end -- faire la liste des arguments possibles, c'est a dire connus for key, argm in pairs(args_known) do		if not tonumber(key) then -- Pour les arguments nommés seulement key = tostring(key) arglingual = tostring(tools.wiki_translations[key]) list[key] = arglingual end end return list end -- function tools.similar_args_list(args_known)

-- For an unknown argument, seeking the name of the nearest argument among the known arguments -- Para un argumento desconocido, buscando el nombre del argumento más cercana entre los argumentos conocidos -- Pour un argument inconnu, cherche le nom d'argument le plus proche, parmi les arguments connus function tools.similar_args_search(search, list) local dist, lengths, tlev = 9, 0 local trouve1, trouve2, trouve3 = nil, nil, nil local min1, min2, min3 = 99, 99, 99 local diffmaxi = tools.similar_args_diffmaxi( string.len(search) ) local t = ", " .. tostring(diffmaxi) .. " / " .. tostring(length) .. " "	for key, arglingual in pairs(list) do -- Search the most similar and same length. Buscar las más similares y la misma longitud. Chercher le plus ressemblant et la même longueur. --	dist = tools.levenshtein_test_1(tostring(cherche), tostring(mot)) -- obsolete dist, tlev = tools.levenshtein(search, arglingual) --	if type(dist) ~= "number" then dist = 9 end if (dist <= min1) then trouve3 = trouve2 min3 = min2 trouve2 = trouve1 min2 = min1 min1 = dist trouve1 = tostring(arglingual) end end t = t .. " " .. tools.ta("cherche", cherche) .. tools.ta("trouve1", trouve1) .. tools.ta("min1", min1) .. tools.ta("trouve2", trouve2) .. tools.ta("min2", min2) .. " " .. t	if trouve1 and min1 == 0 then t = t .. tools.wikidata_color(tools.ta("connu", trouve1)) end if trouve1 and min1 <= diffmaxi then t = t .. tools.wikidata_color(tools.ta("min1 "..min1.."<="..diffmaxi, trouve1)) end if trouve2 and min2 <= diffmaxi then t = t .. tools.wikidata_color(tools.ta("min2 "..min2.."<="..diffmaxi, trouve2)) end if trouve3 and min3 <= diffmaxi then t = t .. tools.wikidata_color(tools.ta("min3 "..min3.."<="..diffmaxi, trouve3)) end return trouve1, min1, trouve2, min2, t end -- function tools.similar_args_search(search, list)

--	t = tools.similar_args_test1( t, "nomm", "digit") function tools.similar_args_test1( t, search, liste) local args_list = tools.similar_args_list(tools.args_known) local trouve1, min1, trouve2, min2 = tools.similar_args_search(search, args_list) --	local trouve1, min1, trouve2, min2 = "aaa", 1, "bbb", 22 t = t .. "\n* similar_args_test1 : " .. tools.ta("search", search) .. tools.ta("trouve1", trouve1) .. tools.ta("min1", min1) .. tools.tam("trouve2", trouve2) .. tools.tam("min2", min2) return t or " similar_args_test1 " end -- function tools.similar_args_test1( t, search, liste)

function tools.similar_args_test( t, args_known) if type(args_known) ~= "table" then args_known = tools.args_known end local err = tools.verify_args_tables(args_known, tools.args_source) if err then return err end --	local key, argsyn, arglingual, txt --	local coef = tools.constants.near_word_search_diff_coef --	local constant = tools.constants.near_word_search_diff_const t = "\n* " .. (t or "Formula to compute the near words limit: Formule de calcul de limite des mots proches : ") local diffmaxi diffmaxi, t = tools.similar_args_diffmaxi(10, t .. "diffmaxi = ") t = t .. "\n* List of diffmaxi / lengths : " for length = 1, 16 do -- For all lengths --	local diffmaxi = math.floor( coef * length + constant ) diffmaxi = tools.similar_args_diffmaxi(length) t = t .. ", " .. tostring(diffmaxi) .. " / " .. tostring(length) .. " "	end t = t .. "\n* List of known arguments and synonyms : " local txt, lingual = "", "" local ref_words = {} for key_known, argm in pairs(args_known) do -- Pour tous les paramètres connus if argm.syn == 1 then key = argm.keyword argsyn = key_known .. ">" -- synonym argument else key = key_known argsyn = "" -- synonym argument end --	tools.user_translations = tools.i18n[lang] or tools.user_translations --	tools.wiki_translations = mw.language.getContentLanguage.code lingual = tools.wiki_translations[key] or "-" -- importer un argument source txt = argsyn .. key .. "/" .. lingual if argm.syn == 1 then t = t .. ", '''" .. txt .. " " -- synonyms''' else t = t .. ", " .. txt .. " "		end ref_words[key] = {} ref_words[key].argmt = key ref_words[key].lingual = lingual end t = t .. "\n* Test similar arguments 1." t = tools.similar_args_test1( t, "anneedece", {["a"]="but", ["b"]="porter", ["c"]="anneedeces"}) t = t .. "\n* Test similar arguments 2." t = tools.similar_args_test1( t, "porte", {["a"]="but", ["b"]="porter", ["c"]="pot"}) return t end -- function tools.similar_args_test( t, args_known)

-- Check if the value of an argument is among the possible values. -- Vérifier si la valeur d'un argument est parmi les valeurs possibles. function tools.multiple_values(argmt, argvalue, args_final, args_known) local args_final = args_final or tools.args_final or {} --	local args_known = args_known or tools.args_known if type(args_known) ~= "table" then args_known = tools.args_known end local argvalue = argvalue or args_final[argmt] local arg_values, key_values, keyword, keyval, argval, rank local argm = args_known[argmt] if argm then arg_values = tools.wiki_translations[argm.arg_values]	or "" -- example "no,nada,cn,50,us,70,mpf" in local language key_values = argm.key_values						or "" -- example "no,none,cn,50,us,70,mpf" in referal english end if type(arg_values) == "string" and type(key_values) == "string" then local arg_tab = mw.text.split(arg_values, ',') -- table of arg local key_tab = mw.text.split(key_values, ',') -- table of key -- Default values keyword = nil rank = 0 -- rank of local value and key value keyval = nil -- key value argval = nil if argm and arg_values and argvalue then for i, key in ipairs(arg_tab) do				if key == argvalue then -- Search argvalue in arg_tab rank = i					keyval = key_tab[i] -- Return correponding keyval in key_tab argval = argvalue keyword = argm.keyword end end end end return keyword, keyval, argval, rank end -- function tools.multiple_values(argmt, argvalue, args_final, args_known)

function tools.multiple_values_tests(t) t = t or "\n* Test multiple_values :" t = t .. tools.Th .. tools.Tc("argm") .. tools.Tc("argvalue") .. tools.Tc("args_final") .. tools.Tc("keyword") .. tools.Tc("keyval") .. tools.Tc("argval") .. tools.Tc("rank") local function multiple_values_tests1(t, argm, argvalue, args_final) local keyword, keyval, argval, rank = tools.multiple_values(argm, argvalue, args_final) t = (t or "") .. tools.Tr .. tools.Td(argm) .. tools.Td(argvalue) .. tools.Td(args_final) .. tools.Td(keyword) .. tools.Td(keyval) .. tools.Td(argval) .. tools.Td(rank) return t	end -- function multiple_values_tests1(t, argm, argval) t = multiple_values_tests1(t, "region", "inde") t = multiple_values_tests1(t, "region", "inconnue") t = multiple_values_tests1(t, "rights", "mpf") t = multiple_values_tests1(t, "rights", "non") t = multiple_values_tests1(t, "rights", "aucun") t = multiple_values_tests1(t, "sex", "femme") t = multiple_values_tests1(t, "sex", "homme") t = multiple_values_tests1(t, "sex", "enfant") args_final = { region = "india", rights = "non", sex = "femme", } t = (t or "") .. tools.Tr .. tools.Tc .. tools.Tc .. tools.Tc('args_final = {') .. tools.Tc('region = "india"') .. tools.Tc('rights = "non"') .. tools.Tc('sex = "femme"') .. tools.Tc('}') t = t .. tools.Tr .. tools.Tc("argm") .. tools.Tc("argvalue") .. tools.Tc("args_final") .. tools.Tc("keyword") .. tools.Tc("keyval") .. tools.Tc("argval") .. tools.Tc("rank") t = multiple_values_tests1(t, "region", "inde", args_final) t = multiple_values_tests1(t, "region", nil, args_final) t = multiple_values_tests1(t, "rights", "mpf", args_final) t = multiple_values_tests1(t, "rights", "non", args_final) t = multiple_values_tests1(t, "rights", nil, args_final) t = multiple_values_tests1(t, "sex", nil, args_final) t = multiple_values_tests1(t, "sex", nil, args_final) t = multiple_values_tests1(t, "sex", "enfant", args_final) t = t .. tools.Te return t end -- function tools.multiple_values_tests(t)

function tools.multiple_selection(opt, selector, to_select) -- Select items to select containing selecting items local t, selected_txt, selector_txt, selector_tab, to_select_txt, to_select_tab, selected_tab = "", "" local cut = string.sub( opt, 1, 1 ) or "," if type(selector) == "table" then selector_tab = selector end if type(selector) == "string" then selector_tab = mw.text.split(selector, cut, true) end if type(to_select) == "table" then to_select_tab = clone(to_select) end if type(to_select) == "string" then to_select_tab = mw.text.split(to_select, cut, true) end selected_tab = {} --	local k, Nsel, N, maxi, pos = 0, 0, 1, 999, nil local reject_select = false local equal = true for i, select in ipairs(selector_tab) do -- select authorities only following selectors if Nsel >= maxi then break end select = mw.text.trim(select) N = tonumber(select) if select == "+" then -- select all items for key, val in pairs(to_select_tab) do				Nsel = Nsel + 1 selected_tab[key] = val end elseif select == "-" then -- minus sign rejects all reject_select = true elseif N and N < 1 then -- minus sign rejects all reject_select = true elseif N and (string.sub(select, 1, 1) == "+") then -- select +N more items maxi = Nsel + N		elseif N then -- select N maximum total items maxi = N		else -- select ONE item from to_select_tab if it matches select ( not - or + or +N or N ) for key, val in pairs(to_select_tab) do				local select_t, val_t = select, val if not tools.is_in("U", opt) then select_t = string.lower(select_t) end -- recognize lowercase and uppercase if not tools.is_in("t", opt) then select_t = mw.text.trim(select_t) end -- recognize after trim if not tools.is_in("U", opt) then val_t = string.lower(val_t) end -- recognize lowercase and uppercase if not tools.is_in("t", opt) then val_t = mw.text.trim(val_t) end -- recognize after trim equal = tools.is_in("=", opt) -- recognize only equal string if equal then equal = (select == val) else equal = tools.is_in(select_t, val_t) end --	if tools.is_in(select, val) then if equal then -- recognize if select is equal or is inside an item from to_select_tab t = t .. tools.ta(select, val) selected_tab[select] = val Nsel = Nsel + 1 to_select_tab[key] = " " -- Delete the selected item to use it only once selected_txt = selected_txt .. val .. ', '				end end end end --	selected_txt = table.concat(selected_tab) return selected_txt, selected_tab, t end -- function tools.multiple_selection(opt, selector, to_select)

function tools.multiple_selection_test(t) t = (t or "") .. "\n* multiple_selection options: " .. tools.ta("=", "equal only") .. tools.ta("t", "not trim before and after") .. tools.ta("U", "not lowercase and uppercase") local function multiple_selection_test1(t, opt, selector, to_select) local selected_txt, selected_tab, txt = tools.multiple_selection(opt, selector, to_select) t = t .. tools.Tr .. tools.Td(opt) .. tools.Td(selector) .. tools.Td(to_select) .. tools.Td( txt .. tools.ta("selected_txt", selected_txt) ) return t, opt, selector, to_select --, selected_txt, selected_tab end local opt = ", " t = t .. "\n: selector = nobel,+1,président,3,député,prix signifie : sélectionner le premier, puis 1 de plus parmi les suivants, puis 3 en tout au maximum." local head = mw.text.split( tools.str_vars("tools_multiple_selection_test_header"), ',') t = t .. tools.Th .. tools.Tc(head[1]) .. tools.Tc(head[2]) .. tools.Tc(head[3]) .. tools.Tc(head[4]) -- Todo ? P39 = fonction = "président de Pologne, député à l'Assemblée, Prix Nehru, Nobel de la paix" -- tools_multiple_selection_test_select	= "2, nobel, president, deputy, price", t = multiple_selection_test1( t, opt, "2, nobel, président, député, prix", "président de Pologne,député à l'Assemblée, Prix Nehru, Nobel de la paix" ) t = multiple_selection_test1( t, ",U", "2, nobel, président, député, prix", "président de Pologne,député à l'Assemblée, Prix Nehru, Nobel de la paix" ) t = multiple_selection_test1( t, opt, "3, député, prix, nobel, président", "président de Pologne,député à l'Assemblée, Prix Nehru, Nobel de la paix" ) t = multiple_selection_test1( t, ",=", "3,député, prix,nobel,président", "président de Pologne,député, Prix Nehru,Nobel" ) t = multiple_selection_test1( t, ",t", "3,député, prix,nobel,président", "président de Pologne,député, Prix Nehru,Nobel" ) t = multiple_selection_test1( t, ";", "3; prix; nobel;+1; président; député", "président de Pologne;député à l'Assemblée; Prix Nehru; Nobel de la paix" ) t = multiple_selection_test1( t, ";", "3; président; nobel; député; prix", "président de Pologne;député à l'Assemblée; Prix Nehru; Nobel de la paix" ) t = multiple_selection_test1( t, ";t", "3;député; prix;nobel;président", "président de Pologne;député; Prix Nehru;Nobel" ) t = multiple_selection_test1( t, ";U", "2; nobel; président; député; prix", "président de Pologne;député à l'Assemblée; Prix Nehru; Nobel de la paix" ) t = t .. tools.Te return t end -- function tools.multiple_selection_test(t)

function tools.bindmodules_test(t) return tools.versions_management_test(t) end -- Deprecated alias function function tools.versionsmanagement_test(t) return tools.versions_management_test(t) end -- Deprecated alias function function tools.versions_management_test(t) -- Test : List all loaded modules tools_bindmodules_test_title local t = (t or "") .. "\n* tools.versions_management_test : The selector =  Box3, Group, Item1  means: check these modules versions among those available." local loaded_tests = { -- loaded_tests -- Cases to look for the main module { key = "Box", versionName = "Box", versionDate = "2015-12-02 02:02", request = "normal modules", comment = 'normal module for Box, with alias like : ', i18n = { en = { a = "a" } }, sought = "Box", known = "Box", loaded_list = ",Box,", }, --		{ key = "Box/I18N", versionName = "Box", versionDate = "2016-05-07 18:36", request = "normal with /I18N", comment = "I18N translations for Box", i18n = { en = { a = "a" } }, sought = "Box", known = "Box", loaded_list = ",Box,Box/I18N,", }, --		{ key = "Box3", versionName = "Box2", versionDate = "2016-05-07 11:11", request = "normal replace known alternate", comment = "alternate version module for Box", i18n = { en = { a = "a" } }, sought = "Box2", known = "Box,Box2", loaded_list = ",Box,Box/I18N,Box2,Box2/I18N,", }, --		{ key = "Box2/I18N", versionName = "Box2", versionDate = "2016-05-07 19:19", request = "missing actual module", comment = "I18N translations without basic module. Form an alert.", i18n = { en = { a = "a" } }, sought = "Box", known = "Box2,Box3", loaded_list = ",Box3,Box3/I18N,Box2,Box2/I18N,", }, -- Cases to look for sub-modules --		{ key = "Group", versionName = "Box", I18N = "Group/I18N", request = "normal sub-module", comment = "normal module for Group", i18n = { en = { a = "a" } }, sought = "Group", known = "Group", loaded_list = ",Group,Group/I18N,", }, --		{ key = "Group4", versionName = "Box", versionDate = "2015-12-11 11:11", request = "unknown sought version", comment = "Mask this to test missing sought version", i18n = { en = { a = "a" } }, sought = "Box,Group", known = "Box", loaded_list = ",Box,", }, --		{ key = "Group/I18N", versionName = "Box", versionDate = "2016-05-07 22:2", request = "sub-module not exists", comment = "I18N translations for the normal module Group", i18n = { en = { a = "a" } }, sought = "Box,Group", known = "Box * Group", loaded_list = ",Box,", }, --		-- Cases to look for /I18N sub-modules { key = "Group2", versionName = "Box3", versionDate = "2015-12-22 22:2", versionDate = "2016-05-07 05:05", request = "normal sub-module with normal /18N", comment = "normal alternate sub-module Group for Group2", i18n = { en = { a = "a" } }, sought = "Box,Group2", known = "Box,Box2 * Group,Group2", loaded_list = ",Group,Group/I18N,Group2,Group2/I18N,Box,Box/I18N,Box2,Box2/I18N,", }, --		{ key = "Group2", versionName = "Box3", versionDate = "2015-12-22 22:2", versionDate = "2016-05-07 05:05", request = "unknown module for /18N sub-module", comment = "normal alternate sub-module Group for Group2", i18n = { en = { a = "a" } }, sought = "Box,Group2", known = "Box,Box2 * Group,Group2", loaded_list = ",Group,Group/I18N,Group2,Group2/I18N,Box,Box/I18N,Box2,Box2/I18N,", }, --		{ key = "Group2", versionName = "Box3", versionDate = "2015-12-22 22:2", versionDate = "2016-05-07 05:05", request = "missing module Box for /18N sub-module", comment = "normal alternate sub-module Group for Group2", i18n = { en = { a = "a" } }, sought = "Box,Group2", known = "Box,Box2 * Group,Group2", loaded_list = ",Group,Group/I18N,Group2,Group2/I18N,Box/I18N,Box2,Box2/I18N,", }, --		{ key = "Jocker", versionName = "Jocker", versionDate = "2015-12-21 11:33", request = "not central module, without i18n", comment = "Any module can have no i18n table.", sought = "Box", known = "Box", loaded_list = ",Box,", }, -- i18n = { en = { a = "a" } }, --		{ key = "Jocker", versionName = "Jocker", versionDate = "2015-12-21 11:33", request = "unknown and not sought actual module", comment = "Any module can be outside of the central system.", i18n = { en = { a = "a" } }, sought = "Jocker.2", known = "Jocker.2", loaded_list = ",Box,", }, }	local function bindmodules_test1(t, vers_test) local tt, vers = centre.bindmodules(main_p, vers_test) -- Bind all modules and versions local vers_err = tools.versions_management_report(vers) -- Detect versions management errors and warnings after bindmodules vers.sought = tools.compact_comma_list(vers.sought) --	local vers_sought = tools.compact_comma_list(vers.used) local vers_sought = "," .. string.gsub( (vers.sought or "-s-"), ",", ", " ) .. "," -- names in column local vers_used = tools.compact_comma_list(vers.used) vers_used = "," ..string.gsub( (vers_used or "-u-"), ",", ", " ) .. "," -- names in column local vers_known = "," .. string.gsub( (vers.known or ""), ",", ", " ) .. "," -- add spaces local vers_loaded_list = "," .. (vers.versionName or "versionName") .. ","		.. (vers.sought or "sought") .. "," .. (vers.known or "known") .. ","		vers_loaded_list = vers.loaded_list or vers_loaded_list or "empty loaded list" vers_loaded_list = tools.compact_comma_list(vers_loaded_list) vers_loaded_list = "," .. string.gsub(vers_loaded_list, ",", ", " ) .. "," -- add spaces local vers_results = "'''" .. (vers.request or "vers.request") .. "'''"		.. " sought: " .. (vers.sought or "") .. " in the main module: '''" .. vers.versionName .. "'''"		.. " " .. (vers_err or "") .. " known: " .. (vers_known or "") .. " loaded list: " .. vers_loaded_list .. " comment: " .. (vers.comment or "") t = (t or "") .. tools.Tr .. tools.Td(vers_sought) .. tools.Td(vers_used) .. tools.Td(vers_results) return t -- tools.Td(vers.used) .. end t = t .. "\n* loaded_vers : Table of all loaded modules, or simulation." t = t .. "\n* Simulate existing versions: " --	local loaded_versions = "Group,Group/I18N,Group2,Box,Box/I18N,Box2/I18N,Box3,Item,Item1/I18N,Jocker" -- example local loaded_versions = "," local loaded_vers = {} local head = mw.text.split( tools.str_vars("tools_bindmodules_test_headers"), ',') -- tools_bindmodules_test_title -- tools_versions_management_title t = t .. tools.Th .. tools.Tc(head[1]) .. tools.Tc(head[2]) .. tools.Tc(head[4]) t = bindmodules_test1( t, nil ) t = t .. tools.Tr .. tools.Tc(head[1]) .. tools.Tc(head[2]) .. tools.Tc(head[5]) local i = 0 for i, tst in ipairs(loaded_tests) do -- build a simili loaded_vers, from loaded_tests, for only versions management local vers_test = mw.clone(tst) -- vers_test is an empty module, only for version management. vers_test.comment = tst.comment -- .. " known : " .. tst.known --	vers_test.loaded_list = "Box,Box/I18N,Box2/I18N,Box3,Group,Group/I18N,Group2,Item,Item1/I18N,Jocker" local loaded_list = "," .. vers_test.key .. "," .. (vers_test.versionName or "versionName") .. ","		.. (vers_test.sought or "sought") .. "," .. (vers_test.known or "known") .. ","		vers_test.loaded_list = tst.loaded_list or tools.compact_comma_list(vers_test.loaded_list) --	vers_test.i18n = { en = { txt = "txt" } } -- if tools.is_in("/I18N", vers_test.key) then vers_test.isI18N = true end loaded_vers[i] = vers_test t = bindmodules_test1( t, vers_test) --	t = t .. "'''" .. vers_test.key .. "''', "	end t = t .. tools.Tr .. tools.Tc(head[1]) .. tools.Tc(head[2]) .. tools.Tc(head[5]) t = t .. tools.Te local t2 = "" local head = mw.text.split( tools.str_vars("tools_list_loaded_modules_headers"), ',') t2 = t2 .. "\n* The table below simulates loaded modules for behind tests cases." t2 = t2 .. tools.Th .. tools.Tc(head[1]) .. tools.Tc(head[2]) .. tools.Tc(head[3]) .. tools.Tc(head[4]) .. tools.Tc(head[5]) for key, elem in pairs(loaded_tests) do t2 = t2 .. tools.Tr .. tools.Td(elem.key) .. tools.Td(elem.versionName) .. tools.Td(elem.versionDate) .. tools.Td( type(elem.i18n) ) .. tools.Td(elem.comment) end t2 = t2 .. tools.Te t2 = t2 .. "\n* " .. tools.ta("Number of versions simulated:", #loaded_tests) t = t .. t2	return t end -- function tools.bindmodules_test(t)

function tools.compact_comma_list(list) -- Standardize list like "Central01,centre 2.4,tools,two words" local list = "," .. string.gsub(list or "", "*", "," ) .. "," -- mask "*" local list = "," .. string.gsub(list or "", " ", "," ) .. "," -- mask new line local listtab = mw.text.split(list or "", ',') -- names between commas local listtab2 = {} for i, name in ipairs(listtab) do -- for all names name = mw.text.trim(name) -- keep spaces in each name listtab2[i] = name end table.sort(listtab2, function (a, b) return (a < b) end ) -- sort in alphabetic order local list2 = "" for i, name in ipairs(listtab2) do -- list all names, only one each, in alphabetic order name = mw.text.trim(name) if (name ~= "") and not tools.is_in_sp(name, list2, ",") then list2 = list2 .. name .. "," end end local list = string.sub( list2, 1, -2 ) -- without last "," return list end -- function tools.compact_comma_list(list)

function tools.verif_i18n(i18n) return tools.verifyinit(i18n) end function tools.verifyinit(i18n) -- check coherence of translations, wiki_lang, user_lang, -- tools_missing_translations_title if type(i18n) ~= "table" then i18n = centre.i18n end if type(i18n) ~= "table" then return " verifyinit MISSING. " end local nerr, trad, t, err = 0, "", "", "" local nbr, list = 0, "" -- tools_missing_translations_title -- List any gaps of translations in i18n tables. -- Liste cualquier las lagunas traducciones en tablas i18n. -- Lister tous les manques de traductions dans les tables i18n. local prec_tab, suiv_tab, max, nk = nil, nil, 0, 0 local lang, prec_lang, suiv_lang, cats = "", "", "", "" local all_txts = {} for lang, texts in pairs(i18n) do -- Pour toutes les langues et tous les textes à traduire suiv_lang = lang -- table suivante de traduction d'une langue suiv_tab = texts -- table suivante de traduction d'une langue list = list .. lang .. ", "		nbr = nbr + 1 if type(texts) == "table" then -- pour chaque couple de langues à comparer for k, v in pairs(texts) do -- Lister tous les textes traduits au moins dans une langue all_txts[k] = "x" end if prec_tab ~= nil and suiv_tab ~= nil then -- pour chaque couple de langues à comparer t = t .. "\n* Comparer les langues : '''" .. prec_lang .. "/" .. suiv_lang .. "''', "				nk = 0 for k, x in pairs(all_txts) do -- Pour tous les textes à traduire trad = suiv_tab[k] nk = nk + 1 if trad == nil then -- and k ~= nil then -- args vers un argument nommé err = tools.err_add("tools_module_miss_i18n_trad_err", k, suiv_lang) -- tools_module_miss_i18n_txt_err t = t .. err .. " " -- .. " "						nerr = nerr + 1 end end if nk > max then max = nk end end end prec_lang = suiv_lang prec_tab = suiv_tab end if nerr > 0 then err = tools.err_add("tools_module_miss_i18n_count_err", nerr, max) t = t .. " " .. err .. " "		cats = cats .. tools.cat_add("tools_err_module_miss_i18n_cat") --		cats = cats .. tools.cat_add("tools_module_internal_error_cat") else err = tools.msg_add("tools_module_miss_i18n_none_err") t = t .. " " .. err .. " "	end -- tester vr le nombre total de variables de traductions local st, vr, fn, tb = tools.luatable_lister(i18n, "i18n") if vr < 33 then err = tools.err_add("tools_module_miss_i18n_mini_err", vr) t = t .. " " .. err .. " "		cats = cats .. tools.cat_add("tools_err_module_miss_i18n_cat") --		cats = cats .. tools.cat_add("tools_module_internal_error_cat") end --	-- List all translated languages t = t .. "\n* Translated languages: Langues traduites : " local an, ln, Nadd, Nchange, Ntotal = 0, 0, 0, 0, 0 for lng, argmts in pairs(i18n) do -- Pour toutes les langues à importer --	if tools.i18n[lng] then -- la langue existe déja, y ajouter ou y remplacer les champs importés if i18n[lng] then -- la langue existe déja, y ajouter ou y remplacer les champs importés t = t .. tools.str_vars(", Langue : %1 ", lng) ln = ln + 1 if type(texts) == "table" then -- pour chaque couple de langues à comparer for argn, val in pairs(argmts) do -- For all imported fields if tools.i18n[lng][argn] then Nchange = Nchange + 1 else Nadd = Nadd + 1 end -- Add or replace a field and its translation. Ajouter ou remplacer un champs et sa traduction tools.i18n[lng][argn] = val --	t = t .. tools.str_vars(", %1 ", argn) an = an + 1 end end else -- ajouter la table et tous ses champs si elle n'est pas encore dans tools.i18n if mw.language.isKnownLanguageTag(lng) then tools.i18n[lng] = i18n[lng] end end end local lst_lng = "" for lang, argmts in pairs(i18n) do -- Pour toutes les langues à importer Ntotal = 0 if type(texts) == "table" then -- pour chaque couple de langues à comparer for argn, val in pairs(tools.i18n[lang]) do -- For all existing fields Ntotal = Ntotal + 1 end local langname = mw.language.fetchLanguageName(lang, "en") local native = mw.language.fetchLanguageName(lang) lst_lng = lst_lng .. tools.str_vars("tools_list_in_translated_lang", Ntotal, lang, langname, native) -- tools_list_in_translated_lang	= "\n* %1 translations in language %2 : %3 : %4", end end tools.user_wiki_lang_msg = tools.str_vars("tools_user_wiki_lang_msg", tools.user_lang, tools.wiki_lang) tools.user_wiki_lang_err = tools.user_wiki_lang_msg -- deprecated for Module:Author3 tools.Lang_list = lst_lng t = t .. tools.str_vars("tools_languages_nbr_and_list", nbr, list) .. lst_lng t = t .. "\n* Same example without translation for a test case : " .. tools.str_test_case("tools_languages_nbr_and_list", nbr, list) t = t .. "\n\n" t = t .. tools.transdiff_report -- Compare all differences of translations return t, cats, lst_lng end -- function tools.verifyinit(i18n)

function tools.transdiff_report(t) -- Compare all differences of translations local t = t or ("\n* transdiff_report: Compare all differences of translations:") local head = mw.text.split( tools.str_vars("tools_transdiff_report_headers"), ',') t = t .. tools.Th("wikitable sortable") .. tools.Tc(head[1]) .. tools.Tc(head[2]) .. tools.Tc(head[3]) .. tools.Tc(head[4]) .. tools.Tc(head[5]) for key, trans in pairs(centre.translations_differences or {} ) do		local trans1 = trans.trans1 local trans2 = trans.trans2 t = t .. tools.Tr .. tools.Tc(trans1.dlang) .. tools.Tc(trans1.dkey) .. tools.Tc(trans1.dtrans) .. tools.Tc(trans2.dtrans) .. tools.Tc(trans2.dfile) end t = t .. tools.Te return t -- tools_transdiff_report_title end -- function tools.transdiff_report(t)

function tools.versionsmanagement_report(vers) return tools.versions_management_report(vers) end -- Deprecated alias function function tools.versions_management_report(vers) -- Detect versions management errors and warnings after bindmodules --[[	The versionning could have 2 meanings. One is successive states of a page or a module.	Another is a group of modules with similar names and functions. Example: job, job01, job02.	The versioning of group management that I experiment is managed by a user, which defines in a main_module a list of soughtversions included in a list of known_versions.	Example: soughtversions = "Author3 MathRoman2 Central1"	known_versions = " Author,Author3 * MathRoman,MathRoman2 * Central,Central1 "	The user changes sought and known at module level or at Args level.	And a versions_library supports the module and the user.	The main_module can display messages like "MathRoman44 is not in known versions, normal MathRoman replaces it." or "Central345 is missing".

tools_all_versions_tests		= "Versions warning: %1, normal: %2, listall: %3.", -- versionsmanagement tools_select_unknown_module_err = "Internal error: The missing Module:%1 is replaced by the normal Module:%2.", -- versionsmanagement tools_I18N_module_no_base_err	= "The %1 translations module has no basic version.", -- versionsmanagement tools_no_versions_module_err	= "The module %1 is not in the system centre.", -- versionsmanagement --]]	local errors_list_memo = tools.errors_list tools.errors_list = {} -- Table to collect errors and messages local categories_list_memo = tools.categories_list tools.categories_list = {} -- Table to collect all categories to generate in wikitext local t, errs, cats = "", "", "" if type(vers) ~= "table" then vers = tools.main_versions end if type(vers) ~= "table" then vers = centre.main_versions end --	if type(vers) ~= "table" then return t end --	p.versions_example = { -- Modules dependencies. Dependencias del módulo. Dépendances du module.		versionName = "Author3", versionNumber = "3.03", versionDate = "2016-04-25 10:31",		sought = " Author3, Central, Central01 ", -- sought submodules versions		known = " Author3 * Central,Central01 ", -- known submodules versions	} -- local sought_report, known_report, used_report, missing_report, unknown_report, replaced_report = "", "", "", "", "", "" local sought_report = tools.compact_comma_list(vers.sought) local known_report = tools.compact_comma_list(vers.known) local loaded_report = tools.compact_comma_list(vers.loaded_list) local used_report = tools.compact_comma_list(vers.used) local alloncesort = tools.compact_comma_list(sought_report .. "," .. known_report .. "," .. used_report) -- .. "," .. loaded_report) --	t = t .. "\n* Versions management report, second: " .. alloncesort	local argm = tools.args_known	alloncetab = mw.text.split(alloncesort, ',') -- table of words	for i, name in ipairs(alloncetab) do -- list all used names, only one each, in alphabetic order		local name_I18N = string.find(name, "/I18N")		if tools.is_in_sp(name, sought_report, ",") and not tools.is_in_sp(name, known_report, ",") and not name_I18N then			missing_report = missing_report .. name .. "," -- sought but not found			errs = errs .. tools.err_add("tools_missing_versions_err", name, vers.versionName )			cats = cats .. tools.cat_add("tools_module_usage_error_cat")		end		if tools.is_in_sp(name, used_report, ",") and not tools.is_in_sp(name, sought_report, ",") and not name_I18N then			replaced_report = replaced_report .. name .. "," -- missing version replaced by normal			errs = errs .. tools.err_add("tools_replaced_versions_err", name, vers.versionName ) cats = cats .. tools.cat_add("tools_module_usage_error_cat") end if tools.is_in_sp(name, alloncesort, ",") and not tools.is_in_sp(name, known_report, ",") and not name_I18N then unknown_report = unknown_report .. name .. "," -- found but not known errs = errs .. tools.err_add("tools_unknown_versions_err", name, vers.versionName ) cats = cats .. tools.cat_add("tools_module_usage_error_cat") end --		tools_no_versions_module_err	= "Le module %1 n'est pas dans le système des versions.",		tools_all_versions_tests		= "Versions avertissements : %1, normaux : %2, liste : %3.",		tools_all_versions_check		= "Versions: manquantes: %1, inconnues: %2, normales: %3, en excès: %4, toutes selectionées : %5.",		tools_missing_versions_err		= "Le module %1 manque dans le module %2.",		tools_replaced_versions_err		= "Le module %1 remplace le module absent %2.",		tools_unknown_versions_err		= "Le module %1 est inconnu dans le module %2.",		-- end missing_report = tools.compact_comma_list(missing_report) replaced_report = tools.compact_comma_list(replaced_report) unknown_report = tools.compact_comma_list(unknown_report) --	t = t .. "\n* Versions management report " --	t = t .. " Sought modules: '''" .. sought_report .. "'''" --	t = t .. " Known modules: '''" .. known_report .. "'''"	t = t .. errs -- " " .. -- --	t = t .. " Replaced modules, missing version replaced by normal: '''" .. replaced_report .. "'''" --	t = t .. " Selected modules, sought and found: '''" .. used_report .. "'''" --	t = t .. " Missing modules, sought but not found: '''" .. missing_report .. "'''" --	t = t .. " Unknown modules, found but not known: '''" .. unknown_report .. "'''" --	t = t .. " All used names, in alphabetic order: '''" .. alloncesort .. "'''" --	t = t .. " " .. cats tools.errors_list = errors_list_memo -- Table to collect errors and messages tools.categories_list = categories_list_memo -- Table to collect all categories to generate in wikitext return t end -- function tools.versions_management_report(vers)

-- Datas wikidata from mw.wikibase

function tools.import_wikidata(args_known, id) -- id = itemid --	wikidata structure args_known.father = mw.wikibase.label( "Q" .. entity.claims.p107[0].mainsnak.datavalue.value["numeric-id"]) if type(args_known) ~= "table" then args_known = tools.args_known end if type(id) ~= "string" then id = nil end local t, adr, val, proplabel = "", nil, nil, nil local wd = {} local wd_mng = {} -- wikidata manager wd_mng.wd_base = mw.wikibase if not wd_mng.wd_base then -- Wikibase available ? wd_mng.wd_error = "wd_base" t = t .. tools.ta("wd_error", wd_mng.wd_error) wd_mng.t = t		tools.args_wikidata = wd		return wd, t, wd_mng end function pcall_getEntityObject( wd_id ) -- wikidata arbitrary access must not fail and block the page. local success, entity = pcall( mw.wikibase.getEntity, wd_id ) -- pcall or xpcall can run any function without blocking page. if success then return entity else return nil end -- T49930 Allow accessing data from a Wikidata item not connected to the current page - arbitrary access (tracking) end if id then -- Wikidata item available ? wd_mng.wd_entity = pcall_getEntityObject( id ) else wd_mng.wd_entity = mw.wikibase.getEntityObject --	wd_mng.wd_entity = mw.wikibase.getEntity -- ex getEntityObject end if wd_mng.wd_entity then -- Page Wikidata disponible ? if wd_mng.wd_entity.claimRanks then wd_mng.wd_claimRanks = wd_mng.wd_entity.claimRanks wd_mng.wd_RANK_PREFERRED = wd_mng.wd_entity.claimRanks.RANK_PREFERRED wd_mng.wd_RANK_NORMAL = wd_mng.wd_entity.claimRanks.RANK_NORMAL wd_mng.wd_RANK_DEPRECATED = wd_mng.wd_entity.claimRanks.RANK_DEPRECATED -- https://www.mediawiki.org/wiki/Extension:WikibaseClient/Lua#mw.wikibase.entity.claimRanks -- Return the normal ranked claims with the property id P5			-- entity:formatPropertyValues( 'P5', { mw.wikibase.entity.claimRanks.RANK_NORMAL } ) -- Return all claims with id P123 (as the table passed contains all possible claim ranks) -- entity:formatPropertyValues( 'P123', mw.wikibase.entity.claimRanks ) -- mw.wikibase.entity.claimRanks = RANK_PREFERRED, RANK_NORMAL, RANK_DEPRECATED end wd_mng.sitelink = wd_mng.wd_entity:getSitelink wd_mng.label = wd_mng.wd_entity:getLabel -- Returns a string, like "Berlin" with 'de' wd_mng.props = wd_mng.wd_entity:getProperties -- or {} Returns a table like: { "P123", "P1337" } wd_mng.props_maxn = tostring(table.maxn( wd_mng.props ) ) wd_mng.props_txt = "T " .. mw.text.listToText( wd_mng.props ) --		wd_mng.props_list = " " for i, pp in ipairs(wd_mng.props) do -- Properties list wd_mng.formatPropertyValues = wd_mng.wd_entity:formatPropertyValues( pp ) if wd_mng.wd_claimRanks then wd_mng.formatPropertyValues_claimRanks = wd_mng.wd_entity:formatPropertyValues(	 pp, { wd_mng.wd_claimRanks } ) end if wd_mng.wd_RANK_PREFERRED then wd_mng.formatPropertyValues_RANK_PREFERRED = wd_mng.wd_entity:formatPropertyValues(	 pp, { wd_mng.wd_RANK_PREFERRED } ) end if wd_mng.wd_RANK_NORMAL then wd_mng.formatPropertyValues_wd_RANK_NORMAL = wd_mng.wd_entity:formatPropertyValues(	 pp, { wd_mng.wd_RANK_NORMAL } ) end if wd_mng.wd_RANK_DEPRECATED then wd_mng.formatPropertyValues_RANK_DEPRECATED = wd_mng.wd_entity:formatPropertyValues( pp, { wd_mng.wd_RANK_DEPRECATED } ) end val = wd_mng.formatPropertyValues.value proplabel = wd_mng.formatPropertyValues.label wd_mng.props_list = wd_mng.props_list .. ", " .. i .. "=" .. pp .. "=" .. tools.ta(proplabel, val) -- .. "/" .. tools.ta(proplabel, wd_mng.formatPropertyNORMAL) if pp == "P569" then -- birthyear P569 for test DEBUG tools.TimeName = pp .. ".1.mainsnak" ; tools.WikidataTimeDetails = wd_mng.wd_entity.claims[pp][1].mainsnak end if pp == "P570" then -- deathyear P570 for test DEBUG tools.TimeName = pp .. ".1.mainsnak" ; tools.WikidataTimeDetails = wd_mng.wd_entity.claims[pp][1].mainsnak end -- https://www.wikidata.org/wiki/Wikidata:Bistro#Date de décès inconnue -- Dans la propriete :Il y a trois petits rectangles à gauche qui permettent de dire si il n'y a pas de valeur (donc pas mort) où si la date est inconnue, le modèle ici ne tient pas compte de ces éléments. --Pino~eowiki 16:40, 27 January 2016 (UTC) end else -- if not wd_mng.wd_entity then entity unknown for the page. entity introuvable pour la page. wd_mng.wd_error = "wd_entity" t = t .. tools.ta("wd_error", wd_mng.wd_error) wd_mng.t = t		tools.args_wikidata = wd		return wd, t, wd_mng end if wd_mng.wd_error then -- Show an error, Signaler une erreur if wd_mng.wd_error == "wikidata_props" then err = tools.str_vars("tools_wikidata_error_err", "wikidata_props") end if wd_mng.wd_error == "wd_base" then err = tools.str_vars("tools_wikidata_wikibase_err") end if wd_mng.wd_error == "wd_entity" then err = tools.str_vars("tools_wikidata_getEntity_err", wd_mng.wd_entity) end if wd_mng.wd_error == "wd_property" then err = tools.str_vars("tools_wikidata_property_err", wd_mng.wd_property) end -- elem -> id		if wd_mng.wd_error == "wd_id" then err = tools.str_vars("tools_wikidata_getEntityObject_err", wd_mng.wd_id) end err = tools.err_add(err) t = t .. err local tools_wikidata_cat_err = tools.cat_add("tools_wikidata_cat_err") else if type(args_known) ~= "table" then args_known = {} end for key, pp in pairs(args_known) do -- Pour tous les paramètres connus if pp.prop then if pp.prop == "label" then val = wd_mng.label elseif pp.prop == "sitelink" then val = wd_mng.sitelink elseif pp.prop == "itemid" then val = wd_mng.wd_entity.id				elseif pp.prop == "description" then val = wd_mng.wd_base.description( wd_mng.wd_id ) -- wikibase.description( id ) elseif pp.prop == "claims" then val = wd_mng.wd_base.renderSnak( wd_mng.wd_entity['claims'] ) -- Returns the given Snaks formatted as wiki text. --	local entity = mw.wikibase.getEntityObject --	local snaks = entity['claims']['P342'][1]['qualifiers'] --	mw.wikibase.renderSnaks( snaks ) -- Returns the given Snaks formatted as wiki text. else wd_mng.formatPropertyValues = wd_mng.wd_entity:formatPropertyValues( pp.prop ) -- "P" .. pp.prop -- Returns a table like: { value = "Formatted claim value", label = "Label of the Property" } if wd_mng.wd_claimRanks then wd_mng.formatPropertyValues = wd_mng.wd_entity:formatPropertyValues( pp, { wd_mng.wd_claimRanks } ) end val = wd_mng.formatPropertyValues.value proplabel = wd_mng.formatPropertyValues.label end if pp.format == "year" then val = mw.ustring.sub( val, -4, -1 ) end wd[key] = val t = t .. tools.ta(key, val) -- .. tools.ta(key, wd_mng.formatPropertyNORMAL) end end end --	wd.lastname = wd.label wd_mng.t = t	tools.args_wikidata = wd	return wd, t, wd_mng end -- function tools.import_wikidata(args_known, id)

function tools.wikidata_details_test(t) local t = t or "\n* wikidata_details_test :" local wd, tw, wd_mng --	t = t .. tools.tools_wikidata_arbitrary_test wd, tw, wd_mng = tools.import_wikidata( tools.args_known ) -- for present page if wd_mng and wd_mng.wd_entity and wd_mng.wd_entity.id then t = t .. "\n* Entity.id: " .. (wd_mng.wd_entity.id or "") -- itemid local tools_structured_data_txt = tools.str_vars("tools_structured_data_txt") t = t .. ' ⦁ ' .. tools_structured_data_txt .. ' ' end t = t .. "\n* Sought properties: " .. tw t = t .. "\n* Properties number maxn: " .. (wd_mng.props_maxn or "") --	t = t .. "\n* Properties txt: " .. (wd_mng.props_txt or "") t = t .. "\n* Properties list: " .. (wd_mng.props_list or "") return t end -- function tools.wikidata_details_test(t)

function tools.tools_wikidata_arbitrary_test(t) -- T49930 Allow accessing data from a Wikidata item not connected to the current page - arbitrary access (tracking) t = "" -- tostring(t) -- t or "" local function one_arbitrary_access(id) local wd, tw, wd_mng = tools.import_wikidata(tools.args_known, id) -- tools.args_known, id) -- example Q535 = Victor Hugo = Victor Marie Hugo	--	local args_import, tx = tools.import_arguments -- tools.args_known, tools.args_source ) if wd_mng and wd_mng.wd_entity and wd_mng.wd_entity.id then t = "\n* " .. tools.str_vars("tools_wikidata_arbitrary_access_text") --	.. (wd.itemid or "") .. ", " .. (wd.sitelink or "") .. " ( " .. (wd.birthyear or "") .. " - " .. (wd.deathyear or "") .. " ) " .. (wd.itemid or "") .. ", " .. (wd.label or "") .. " ( " .. (wd.birthyear or "") .. " - " .. (wd.deathyear or "") .. " ) " --	.. (wd_mng.wd_id or "") .. ", " .. (wd_mng.title or "") .. " ( " .. (wd.birthyear or "") .. " - " .. (wd.deathyear or "") .. " ) " local tools_structured_data_txt = tools.str_vars("tools_structured_data_txt") t = t .. ' ⦁ ' .. tools_structured_data_txt .. '' t = t .. ", " .. (wd_mng.props_maxn or "") .. " properties. " -- "\n* Properties number maxn: " --	wd, tw, wd_mng = tools.import_wikidata( tools.args_known ) -- for present page if wd_mng and wd_mng.wd_entity and wd_mng.wd_entity.id then --		t = t .. "\n* Entity.id: " .. (wd_mng.wd_entity.id or "") -- itemid local tools_structured_data_txt = tools.str_vars("tools_structured_data_txt") --		t = t .. ' ⦁ ' .. tools_structured_data_txt .. ' ' end t = t .. "\n* Sought properties: " .. tw --	t = t .. "\n* Properties txt: " .. (wd_mng.props_txt or "") --	t = t .. "\n* Properties list: " .. (wd_mng.props_list or "") else t = " * No arbitrary access for: " .. tostring(id) end return t	end t = t .. one_arbitrary_access("Q535") -- Q535 = Victor Hugo = Victor Marie Hugo --	t = t .. one_arbitrary_access("Victor Hugo") -- Q535 = Victor Hugo = Victor Marie Hugo t = t .. one_arbitrary_access("Q8023") -- Q899264 = Nelson Mandela --	t = t .. one_arbitrary_access("Q899264") -- Q899264 = Martin Fleischmann return t end -- function tools.tools_wikidata_arbitrary_test(t)

function tools.verify_args_tables(_known, _source) -- initialize all the values to "" in arg table if type(_known) == "table" then tools.args_known = _known end if type(tools.args_known) ~= "table" then tools.err_add("tools_no_known_arguments_err") --		tools.cat_add("tools_tools_no_known_args_cat") return tools.error_color(" Internal error : no source or no known arguments ! ") end if type(_source) == "table" then tools.args_source = _source end if type(tools.args_source) ~= "table" then tools.err_add("tools_no_source_arguments_err") --		tools.cat_add("tools_no_source_arguments_cat") return tools.error_color(" Internal error : no source or no known arguments ! ") end return end -- function tools.verify_args_tables(_known, _source)

function tools.import_arguments(args_known, args_source, wiki_translations, args_wikidata) --	import all arguments from template, or invoke, or wikidata local args_import = {} -- table d'arguments internationale simple local err = nil local cats = "" -- default parameters if type(args_known) ~= "table" then args_known = tools.args_known end if type(args_known) ~= "table" then args_known = tools.args_known end if type(args_source) ~= "table" then args_source = tools.args_source end wiki_translations = wiki_translations or tools.wiki_translations --	if type(args_wikidata) ~= "table" then args_wikidata = tools.args_wikidata end tools.nowyear = tonumber(os.date("%Y") ) -- now_date = os.date("%Y-%m-%d %H:%M:%S") args_import.nowyear = tools.nowyear tools.import_arguments_err = "" tools.import_arguments_track = "" local err = tools.verify_args_tables(args_known, args_source) if err then return args_import, err end --	local err, er1, t2 = "", "", "" local key, argval, argid = "kkk", "xxx", "" local argknw, arglingual, argreceived = nil, "", "" local argm = {} -- used arguments --	tools.erron = true -- Errors actived or no. Errores activas o no. Erreurs activées ou non. --	tools.errors_list = {} -- collect all errors local key_N, key_NN = 0, 0 local arg_found, rec_found, already_found = false, false, false --	for key_known, argm in pairs(args_known) do		argm.found = 0 -- First, initialize all known arguments end --	tools.args_unknown = mw.clone(tools.args_source) -- unknown arguments to detect are source arguments without known arguments. local key_known_init = nil --	local argm_orig = nil local argm_syn = nil -- Try to read all known arguments. Intentar leer todos los argumentos conocidos. Essayer de lire tous les arguments connus. for key_known, argm in pairs(args_known) do		argm.src = nil argm.trk = " n"		key_known_init = key_known -- first initialise each known argument tools.import_arguments_track = tostring(tools.import_arguments_track) .. " - " .. tostring(key_known) argm_syn = args_known[argm.keyword] if argm.syn == 2 then -- Name an unnamed argument, positional, by its synonym. Nommer un argument non nommé, numéroté, par son synonyme. -- Rename a named argument, by its synonym. Renommer un argument nommé, par son synonyme. --			argm_orig = key_known -- DEBUG key_known = argm.keyword --	synonyms are defined with the stamp "syn = 2", then here stamp the basic argument with "syn = 1". args_known[key_known].syn = 1 argm = args_known[key_known] -- new variable argm argm.src = nil argm.trk = "s" tools.import_arguments_track = tostring(tools.import_arguments_track) .. ">" .. tostring(key_known) end -- initialiser un argument arg_found = false argval = nil argm.trk = argm.trk.."=" -- importer un argument wikidata if args_wikidata[key_known] then argval = args_wikidata[key_known] argm.src = "wd" argm.trk = argm.trk.."w" if argm_orig then --	args_known[argm_orig].src = "wd" --	args_known[argm_orig].trk = (args_known[argm_orig].trk or "").."w" end --			if argm_orig then argm_orig = key_known end -- DEBUG arg_found = true tools.import_arguments_track = tools.import_arguments_track .. "='''" .. tostring(argval) .. "''' "		end -- import a source argument. importer un argument source. arglingual = tools.wiki_translations[key_known] tools.import_arguments_track = tools.import_arguments_track .. "/" .. tostring(arglingual) if arglingual then -- The argument name has a translation in wiki language --	if tools.frame[arglingual] then --		argval = tools.frame[arglingual] --		argm.src = "inv" -- arg comes from invoke --	end if tools.frame.args[arglingual] then --			argval = tools.frame.args[arglingual] --			argm.src = "inv" -- arg comes from invoke --			arg_found = true end if tools.frame:getParent.args then --			argval = tools.frame:getParent.args[arglingual] --			argm.src = "tpl" -- arg comes from template --			arg_found = true end

if args_source[arglingual] and not tools.args_config[arglingual] then -- the argument come from template else from invoke else from wikidata --		if argval then -- the argument value exist and come from template else from invoke else from wikidata

argval = args_source[arglingual] argm.src = "args" argm.trk = argm.trk.." a"				arg_found = true local arg_values = wiki_translations[argm.arg_values] if argm.keys_values and arg_values then -- The argument is limited to multiple values with arg_values and keys_values, and the values are defined. local pos = string.find(arg_values, argval) if pos then -- The value of the argument is in the multiple values of the arguments. --		argm.src = "args" argm.trk = argm.trk.."m" --		arg_found = true if argm_orig then --	args_known[argm_orig].src = "args" --	args_known[argm_orig].trk = (args_known[argm_orig].trk or "").."d" end else tools.err_add("tools_args_values_err", argm.keyword, argval, arg_values) --		argval = nil end else --	argm.src = "args" argm.trk = argm.trk.."c" --	arg_found = true if argm_orig then --	args_known[argm_orig].src = "args" --	args_known[argm_orig].trk = (args_known[argm_orig].trk or "").."c" end end tools.import_arguments_track = tools.import_arguments_track .. "='''" .. tostring(argval) .. "''' "			end -- not args_source[arglingual] is normal else -- internal error and category --	tools.err_add("tools_module_miss_i18n_trad_err", key_known) -- Generate a category to list all modules with missing translation cats = cats .. tools.cat_add( "tools_err_module_miss_i18n_cat" ) end --		key_N = tonumber(key_known_init) if key_N and not args_known[key_N] then --			tools.err_add("tools_too_unnamed_arguments_err", key_N, argval) end -- Record the argument. Guarde el argumento. Enregistrer l'argument. if arg_found == true then argm.found = argm.found + 1 -- compter les arguments redéfinis argm.val = argval args_import[key_known] = argval -- table d'arguments internationale simple if tools.args_unknown[arglingual] then tools.args_unknown[arglingual] = nil -- unknown arguments are source arguments without known arguments. end end end -- tools.import_arguments: after import itself, some surrounding checks. for key_known, argm in pairs(args_known) do -- For all known arguments -- Redefined arguments. Argumentos redefinieron. Arguments redéfinis. --	if argm.found and (argm.found > 1) then --		tools.err_add("tools_value_re_defined_err", argm["keyword"]) --		cats = cats .. tools.cat_add("tools_module_usage_error_cat") --	end --	synonyms are defined with the stamp "syn = 2", then here stamp the basic argument with "syn = 1". --	if argm.keyword and args_known[argm.keyword] and args_known[argm.keyword].syn then -- if the argument is a synonym, increase the found level if argm.keyword and args_known[argm.keyword] and args_known[argm.keyword].syn then -- if the argument is a synonym, increase the found level if argm.found and (argm.found > 2) then tools.err_add("tools_value_re_defined_err", (argm["keyword"] or "**") ) --.. ">2")				cats = cats .. tools.cat_add("tools_module_usage_error_cat")			end		else			if argm.found and (argm.found > 1) then				tools.err_add("tools_value_re_defined_err", (argm["keyword"] or "**") ) --.. ">1") cats = cats .. tools.cat_add("tools_module_usage_error_cat") end end -- need = 0 not necessary argument -- need = 1 necessary from argument -- need = 2 necessary from argument or module interaction -- Missing Arguments. Argumentos que faltan. Arguments manquants. if argm.need and (argm.need == 1) and (not argm.val) then arglingual = wiki_translations[key_known] if arglingual then tools.err_add("tools_need_arg_value_err", arglingual) cats = cats .. tools.cat_add("tools_module_usage_error_cat") end end end -- All arguments sources have they been used? --	tools.args_unknown -- unknown arguments are source arguments without known arguments. local args_list = tools.similar_args_list(tools.args_known) for key_src, val_src in pairs(tools.args_unknown) do -- For all unknown source arguments. arglingual = tostring(key_src) -- chercher l'argument traduit key_N = tonumber(arglingual) -- No error for unmamed arguments -- Pas d'erreur pour les arguments non nommés if not key_N then tools.err_add("tools_unknown_argument_err", arglingual, val_src) cats = cats .. tools.cat_add("tools_module_usage_error_cat") -- "Erreur : Le paramètre %1 est inconnu dans ce modèle. Vérifier ce nom ou signaler ce manque.", -- Cherche un argument connu et de nom ressemblant local diffmaxi = tools.similar_args_diffmaxi( string.len(arglingual) ) local trouve1, min1, trouve2, min2 = tools.similar_args_search(arglingual, args_list) if min1 and (min1 <= diffmaxi) then tools.err_add("tools_nearest_argument_err", trouve1) end if min2 and (min2 <= diffmaxi) then tools.err_add("tools_nearest_argument_err", trouve2) end end key_N = tonumber(arglingual) if key_N and not args_known[key_N] then tools.err_add("tools_too_unnamed_arguments_err", key_N, val_src) tools.cat_add("tools_module_usage_error_cat") end end -- For all unknown source arguments. tools.nowyear = tonumber(os.date("%Y") ) -- now_date = os.date("%Y-%m-%d %H:%M:%S") args_import.nowyear = tools.nowyear tools.args_import = args_import --	tools.trac_lang("tools.import_arguments:", args_import) -- DEBUG return tools.args_import end -- function tools.import_arguments(args_known, args_source, wiki_translations, args_wikidata)

-- Argts : Generate documentation. Generar documentación. Générer la documentation.

function tools.generDoc1(paramName, n, paramData, opt) -- t = t .. generDoc1("nom", "ws-name", "docline docdef") -- Normaliser les parametres et signaler les erreurs -- Toujours afficher quelque chose dans la documentation du module ou du modèle. if type(paramName) ~= "string" or type(paramData) ~= "string" then -- signaler l'erreur tools.err_add("tools_generDoc1_paramName_err", tostring(paramName) ) return " " end opt = " "..tostring(opt).." " -- transparent, sinon peut donner nil, non génant --	-- former le texte à afficher local newline = " " -- Chaque parametre non nommé est traité par son synonyme. if n then return "" end if tools.option("docline", opt) then newline = "" end local argm = tools.args_known[paramName] if argm then --[ [		if tools.docolor then --	Document the data sources by colors if argm.src == "wd" then paramData = tools.wikidata_color(paramData) elseif argm.src == "args" then paramData = tools.invoke_color(paramData) --	elseif argm.src == "inter" then --		paramData = tools.inter_color(paramData) else paramData = tools.other_color(paramData) end end --] ]		paramData = paramData -- .. (argm.trk or "") end return " | " .. paramName .. " = '''" .. paramData .. "'''" .. newline end -- function tools.generDoc1(paramName, paramId, opt)

function tools.generDoc(opt, args_final, module_name) -- List of paramètres for the module documentation -- Lister des paramètres pour la documentation du module -- "docview" ajouter le panneau de documentation -- "docmin" quelques paramètres de base -- "docdef" seulement les paramètres définis, ayant une valeur non nulle -- "docmax" tous les paramètres connus -- "docnotice" generer les documentations des notices -- "docline" mettre tous les paramètres sur une seule ligne -- "docsrc" mettre les paramètres en couleurs selon les sources -- tools.options = " : docdata docmin docdef docmax docline docview docafter docnotice docsrc" -- for documentation -- tools.options = " erron noerr nobox nocat " -- without normal result -- tools.options = " debug tests en es fr " -- for debug or enforce language local args_known = tools.args_known local err = tools.verify_args_tables(args_known, tools.args_source) if err then return args_import, err end if type(module_name) ~= "string" then module_name = tools.module_name end if type(module_name) ~= "string" then module_name = tools.frame:getTitle end -- main module, example "Auteur" if type(module_name) ~= "string" then module_name = "Central" end local n, t, val = 0, "", "" if type(args_final) ~= "table" then t = t.."err_args_final="..type(args_final).." " end -- optional arguments if type(args_final) ~= "table" then args_final = tools.args_final end -- optional arguments local key, argknw, argval, arglingual = "", "", "" local lst = true local lst_doc, lst_1, lst_t = {}, {}, "" for key, parm in pairs(args_final) do -- for all known arguments val = "" n = tonumber(key) if n then key = tostring(parm["keyword"]) end -- key for unnamed arguments, in numeric sort argknw = args_known[key] arglingual = tostring(tools.user_translations[key]) -- multilingual name of the arg in the template if arglingual == "nil" then arglingual = key end -- if argument is translatable val = parm -- tostring(args_import[key]) if not tools.isDef(val) then val = "" end lst = false opt = opt .. " docdef " -- optional display if tools.option("docmin", opt) and (argknw["list"] == 1) then lst = true end if tools.option("docdef", opt) and (val ~= "") then lst = true end if tools.option("docmax", opt) then lst = true end if not args_known[key] then lst = false end if key and args_known[key] and args_known[key].typ == "sys" then lst = false end if lst then -- list if found and selected lst_t = tools.generDoc1(arglingual, n, val, opt) table.insert(lst_doc, {lst_t = lst_t, key = key, user_lang_key = tools.user_translations[key] or "trans"} ) end end table.sort(lst_doc, function (a, b) return (a.user_lang_key < b.user_lang_key) end ) -- alphabetic sort of translated arguments for i, parm in ipairs(lst_doc) do -- List all found arguments t = t .. parm.lst_t or "lst_t" end t = "\n" -- return t end -- function tools.generDoc(opt, args_final, module_name)

function tools.sources_of_datas_colors local res = "" if tools.docolor then --	Document the data sources by colors local tools_sources_of_datas = tools.str_vars("tools_sources_of_datas") --	tools_sources_of_datas = "Informations from: /Wikidata, /template or module, /other, /message, /error", local splitxt = mw.text.split(tools_sources_of_datas, "/", true) res = res .. splitxt[1]	 .. " ''' " .. tools.wikidata_color(splitxt[2]) .. tools.invoke_color(splitxt[3]) .. tools.other_color(splitxt[4]) .. tools.message_color(splitxt[5]) .. tools.error_color(splitxt[6]) .. ".''' "	else -- Document the data sources in black on white --		local tools_sources_of_datas = tools.str_vars("tools_sources_of_datas") --		res = res .. string.gsub(tools_sources_of_datas, "/", "") .. ".''' "	end return res end -- function tools.sources_of_datas_colors

function tools.docbox_namespace_error_and_cat -- T53660 Detect the edit state to adapt help messages to user errors -- We cannot replace this need by another test. -- If DocBox is displayed out of Module or Template namespace, generate an error and a category "Module with usage error" -- Si DocBox est affiché hors de l'espace de nom Module ou Modèle, générer une erreur et une catégorie "erreur d'utilisation" local namespace = mw.title.getCurrentTitle.namespace local nsText = mw.title.getCurrentTitle.nsText if namespace ~= 10 and namespace ~= 828 then -- ns:Template and ns:Module tools.err_add("docbox_namespace_error_err", nsText) tools.cat_add("docbox_namespace_error_cat") end return end -- function tools.docbox_namespace_error_and_cat

function tools.get_editstate local t = "" local mwtitle = mw.title.getCurrentTitle local url = tostring(mwtitle:canonicalUrl ) local n = string.find(url, "/w/") tools.EditState = false if tonumber( n ) then tools.EditState = true end return tools.ta("EditState", tools.EditState) .. " - " .. url end -- function tools.get_editstate

function tools.module_init(frame) -- Get tools.args_source with tools.args_config frame = frame or tools.frame or mw.getCurrentFrame tools.frame = frame tools.nowyear = tonumber(os.date("%Y") ) -- now_date = os.date("%Y-%m-%d %H:%M:%S") --	Mix arguments from, then arguments from the prioritary template which replace ones from. local v2, nn, ni = 0, 0, 0 local args_tab, mode = {} local templat = frame:getParent.args -- arguments from template local invoked = frame.args -- arguments from #invoke module -- Mix invoked modified arguments from prioritary template arguments. -- Argument 1 from template become the mode in #invoke. Other i arguments must be shifted. local args_tab = mw.clone(invoked) for key, val in pairs(templat) do -- template arguments can modify #invoke arguments. local key = mw.text.trim(key) local val = mw.text.trim(val) local i = tonumber(key) if i then if i == 1 then mode = val -- mode = template[1] args_tab.mode = val else args_tab[i-1] = val end -- transmit other unnamed arguments template[i], but shifted because the mode is in template[1] else args_tab[key] = val end -- transmit any named template arguments template. Even the mode, which replace template[1], behind. end tools.args_source = args_tab --	tools.args_config = tools.args_config_init -- Get tools.args_config -- Default values of main module version. if tools.main_versions then tools.main_versions.versionName = tools.main_versions.versionName or "Central0" tools.main_versions.versionNumber = tools.main_versions.versionNumber or "0.00" tools.main_versions.versionDate = tools.main_versions.versionDate or "2013-03-24" end --	tools.init_user_lang tools.args_config_init -- Extract and put apart args_config from args_source tools.verifyinit return -- tools.args_config end -- function tools.module_init(frame)

-- Main interface to templates -- Interfaz principales de modelos -- Interface principal avec les modèles

-- TEST part, with use of options, modes and resulting text -- TEST parte, con el uso de opciones, modos y texto resultante -- TEST partie, avec l'utilisation d'options, modes et texte résultant

-- Auto test of limits of the table list. -- Auto test des limites de liste de table. tools.tablim = { "one", "two", max1 = "MAX1", max2 = "MAX2", max3 = "MAX3"} tools.tablim.life = { animal = "dog", vegetal = "carot"} tools.tablim.life.animals = { "turtle"} tools.tablim.comfort = { "tv", mobile = "car"} tools.tablim.house = { "kitcheen", "bedroom"} tools.tablim.house.garden = { flower = "rose", nature = "river"}

function tools.cat_add_test_1(t, test, user_lang, wiki_lang, key,vals ) tools.catView = ":" --	tools.init_wiki_lang(wiki_lang) -- res = res .. --	tools.init_user_lang(user_lang) -- res = res .. tools.init_wiki_user_lang(wiki_lang, user_lang) if test == "cat_add" then catext = tools.cat_add(key, vals) elseif test == "catGroup" then catext = tools.catGroup(key, vals) end tools.options_to_catView return t .. tools.Tr .. tools.Td(test or "-") .. tools.Td(user_lang or "-") .. tools.Td(wiki_lang or "-") .. tools.Td(catext or "-") end

function tools.cat_add_test(t) -- tester les categories t = t or "\n* Test the function cat_add : " .. tools.ta("user_lang", tools.user_lang) .. tools.ta("wiki_lang", tools.wiki_lang) local cat_memo, catView, user_lang, wiki_lang = tools.categories_list, tools.catView, tools.user_lang_memo, tools.wiki_lang_memo local wiki_memo, user_memo = tools.wiki_lang, tools.user_lang --	tools.categories_init tools.categories_list = {} -- init the collect of categories tools.catView = ":" t = t .. tools.Th .. tools.Tc("Test type") .. tools.Tc("user language") .. tools.Tc("wiki language") .. tools.Tc("Categories") t = tools.cat_add_test_1(t, "cat_add", nil, nil, "tools_err_module_miss_i18n_cat") t = tools.cat_add_test_1(t, "cat_add", nil, nil, "tools_module_usage_error_cat") t = tools.cat_add_test_1(t, "cat_add", "en", nil, "tools_module_internal_error_cat") t = tools.cat_add_test_1(t, "cat_add", "en", "es", "tools_err_module_miss_i18n_cat") t = tools.cat_add_test_1(t, "catGroup", "en", "fr", "tools_language_cat", "french,italian,chinese") t = tools.cat_add_test_1(t, "catGroup", "en", "en", "occupation_cat", "Académiciens,Personnalités politiques") t = tools.cat_add_test_1(t, "cat_add", "fr", "en", "tools_module_internal_error_cat") t = tools.cat_add_test_1(t, "cat_add", "es", "en", "tools_module_internal_error_cat") t = tools.cat_add_test_1(t, "cat_add", "en", "x-y-z", "tools_module_internal_error_cat") t = tools.cat_add_test_1(t, "cat_add", "x-y-z", "en", "tools_module_internal_error_cat") t = t .. tools.Te tools.init_wiki_user_lang(wiki_memo, user_memo) t = t .. "\n* Test the function categories_lister : " .. tools.categories_lister(":") -- generate the categories wikitext t = t .. "\n* This test reset categories before the test." tools.options_to_catView return t end -- function tools.cat_add_test(tst)

function tools.i18n_lister(t, i18n_tables) if type(i18n_tables) ~= "table" then i18n_tables = tools.i18n end t = t or "\n* i18n_lister :" t = t .. tools.error_color("\n* This list show all the texts, but cannot replace the original declarations. ") t = t .. tools.error_color("\n* " .. tools.str_vars("tools_i18n_list_all_texts") .. "  " ) for lang, lang_table in pairs(i18n_tables) do t = t .. "\np.i18n." .. lang .. ' = { '		if type(lang_table) == "table" then for key, text in pairs(lang_table) do				if key and text then t = t .. "\n:" .. key .. ' = "' .. text .. '",' end end end t = t .. "\n}\n" end return t end -- function tools.i18n_lister(t, i18n_tables)

-- mw.language:formatDate lang:formatDate( format, timestamp, local ) -- Formats a date according to the given format string. timestamp else current time. The value for local must be a boolean or nil; if true, the time is formatted in the wiki's local time rather else in UTC. -- The format string and supported values for timestamp are identical to those for the #time parser function from Extension:ParserFunctions. Note that backslashes may need to be doubled in the Lua string where they wouldn't in wikitext: -- → 28 februari 1988 -- → 1424087375 --  → Mon, 16 Feb 2015 11:49:34 +0000

function tools.day_to_UTC(jj, mm, aaaa) local t = "@" .. tostring( jj*86400 + mm*30*86400 + (aaaa-1970)*31556926 ) return t end

function tools.day_to_stamp(jj, mm, aaaa) jj = tonumber(jj) if not jj then jj = "2" else jj = string.sub("0000" .. tostring(jj), -2, -1 ) end mm = tonumber(mm) if not mm then mm = "2" else mm = string.sub("0000" .. tostring(mm), -2, -1 ) end aaaa = tonumber(aaaa) if not aaaa then aaaa = "2000" else aaaa = string.sub("0000" .. tostring(aaaa), -4, -1 ) end return aaaa .. "-" .. mm .. "-" .. jj --	mm = tostring( mm or "1" ) --	aaaa = tostring( aaaa or "1" ) --	if jj == 1 and tools.language_obj:getCode == "fr" then t = string.gsub(t, "1 ", "1er " ) end --	if jj == 1 and tools.language_obj:getCode == "en" then t = string.gsub(t, "1 ", "1st " ) end end

function tools.format_date(format, timestamp, lang, loc) if not tools.language_obj then tools.language_obj = mw.language.new( "fr" ) end if lang then tools.language_obj = mw.language.new( lang ) end if tools.language_obj then tools.language_code = tools.language_obj:getCode end if type(loc) ~= "boolean" then loc = true end return tostring(tools.language_obj:formatDate(format, timestamp, loc)) end -- function tools.format_date(format, timestamp, loc)

function tools.time_format_test_1(t, test, format, timestamp, lang, loc) if lang then tools.language_obj = mw.language.new( lang ) end t = t .. tools.Tr .. tools.Td(test or "-") .. tools.Td(format or "-") .. tools.Td(timestamp or "-") .. tools.Td(tostring(lang)) .. tools.Td( tools.format_date(format, timestamp, loc) ) return t end

function tools.time_format_test(t) if not tools.language_obj then tools.language_obj = mw.language.new( "fr" ) end if tools.language_obj then tools.language_code = tools.language_obj:getCode end t = t or "\ntime_format_test :" t = t .. "\nCoding and conversion of dates by the parser function language_obj:formatDate(format, timestamp, loc)." t = t .. tools.ta("tools.language_code", tools.language_code) t = t .. " Verify some date formats: Vérifier quelques formats de dates :" t = t .. tools.Th .. tools.Tc("Test dates from seconds") .. tools.Tc("format") .. tools.Tc("timestamp") .. tools.Tc("lang") .. tools.Tc("Formated date") t = tools.time_format_test_1(t, " now", "U", "now") t = tools.time_format_test_1(t, " seconds to full UTC ", "r", "@1421117374") t = tools.time_format_test_1(t, " seconds to full UTC ", "r", "@1424087374") t = tools.time_format_test_1(t, " 2015-02-16T11:49:34+00:00 ", "c", "@1424107003") t = tools.time_format_test_1(t, " 14/7/1789 to english ", "F j Y", tools.day_to_UTC(14, 7, 1789), "en") t = tools.time_format_test_1(t, " seconds to french format ", "j F Y", "@1499997003") t = tools.time_format_test_1(t, " french 14/7/1789 ", "j F Y", tools.day_to_UTC(14, 7, 1789), "fr") t = tools.time_format_test_1(t, " french 14/7/234 ", "j F Y", tools.day_to_UTC(14, 7, 234), "fr") t = t .. tools.Tr .. tools.Tc("Test from UTC") .. tools.Tc("format") .. tools.Tc("timestamp") .. tools.Tc("lang") .. tools.Tc("Formated date") t = tools.time_format_test_1(t, " french date ", "j F Y", "1915-02-16T17:16:43+00:00", "fr") t = tools.time_format_test_1(t, " french date ", "j F Y", "1515-02-22T17:16:43+00:00", "fr") t = t .. tools.Tr .. tools.Tc("Test dates only") .. tools.Tc("format") .. tools.Tc("timestamp") .. tools.Tc("lang") .. tools.Tc("Formated date") t = tools.time_format_test_1(t, " french 2015-02-16 ", "j F Y", "2015-02-16", "fr") t = tools.time_format_test_1(t, " french 32-12-25 ", "j F Y", "32-12-25", "fr") t = tools.time_format_test_1(t, " french 0032-12-25 ", "j F Y", "0032-12-25", "fr") t = tools.time_format_test_1(t, " french 3/4/5 ", "j F Y", tools.day_to_stamp(3, 4, 5), "fr") t = tools.time_format_test_1(t, " french 24/11/31 ", "j F Y", tools.day_to_stamp(24, 11, 31), "fr") t = tools.time_format_test_1(t, " french 24/11/32 ", "j F Y", tools.day_to_stamp(24, 11, 32) ) t = tools.time_format_test_1(t, " french 24/12/32 ", "j F Y", tools.day_to_stamp(24, 12, 32) ) t = tools.time_format_test_1(t, " french 25/12/32 ", "j F Y", tools.day_to_stamp(25, 12, 32) ) t = tools.time_format_test_1(t, " french 25/12/32 roman year ", "j F xrY", tools.day_to_stamp(25, 12, 32) ) t = t .. tools.Tr .. tools.Tc("Test partial formats & missing datas") .. tools.Tc("format") .. tools.Tc("timestamp") .. tools.Tc("lang") .. tools.Tc("Formated date") t = tools.time_format_test_1(t, " partial format 3/4/5 ", "j F Y", tools.day_to_stamp(3, 4, 5) ) t = tools.time_format_test_1(t, " partial format 3/4/5 ", "Y", tools.day_to_stamp(3, 4, 5) ) t = tools.time_format_test_1(t, " missing day -/4/5 ", "F Y", tools.day_to_stamp(nil, 4, 5) ) t = tools.time_format_test_1(t, " missing month 3/-/5 ", "j Y", tools.day_to_stamp(3, nil, 5) ) t = tools.time_format_test_1(t, " missing year 3/4/- ", "j F", tools.day_to_stamp(3, 4, nil) ) t = tools.time_format_test_1(t, " missing day -/4/5 ", "F Y", tools.day_to_stamp(nil, 4, 5) ) t = tools.time_format_test_1(t, " missing month 3/-/5 ", "j Y", tools.day_to_stamp(3, nil, 5) ) t = tools.time_format_test_1(t, " missing year 3/4/- ", "j F", tools.day_to_stamp(3, 4, nil) ) t = t .. tools.Te return t end -- function tools.time_format_test(t)

function tools.date_to_part_test(t) function date_to_part_test_1(t, nom, date, part) t = t .. tools.Tr .. tools.Td(nom) .. tools.Td(date) .. tools.Td(part) .. tools.Td(tostring(tools.date_to_part(date, part))) return t	end t = t or "\n* date_to_part :" t = t .. "\n* Verify each value of part of date:" t = t .. tools.Th .. tools.Tc("Example") .. tools.Tc("date") .. tools.Tc("part") .. tools.Tc("value") t = date_to_part_test_1(t, "Socrate birth", "470 BCE", "era") t = date_to_part_test_1(t, "Tite-Live birth", "59 BCE", "yyyy") t = date_to_part_test_1(t, "Tite-Live death", "17", "yyyy") t = date_to_part_test_1(t, "empty", "", "yyyy") t = date_to_part_test_1(t, "Revolution", "14 July 1789", "mmmm") t = date_to_part_test_1(t, "Walk on Moon", "20 July 1969", " ") t = date_to_part_test_1(t, "English date", "July 20 1969", "yyyy") t = date_to_part_test_1(t, "English date", "July 20 1969", "mmmm") t = date_to_part_test_1(t, "Nelson Mandela birth", "July 1918", "yyyy") t = date_to_part_test_1(t, "Nelson Mandela death", "5 Decembre 2013", "dd") t = t .. tools.Te -- see https://fr.wikipedia.org/wiki/Discussion:ISO_8601#Av._J.C._:_contradiction_avec_l.27article_anglais -- see https://fr.wikipedia.org/w/index.php?title=ISO_8601&diff=next&oldid=12449725 -- see ISO 8601 time format like : 1977-04-22T01:00:00-05:00 (5 heures de décalage) = 1977-04-22T06:00:00Z local time -- os.date( format, time ) get datetime return t end -- function tools.date_to_part_test(t)

function tools.new_library_test(t) -- Show some use cases on centre.new_library(name, library, options) function new_library_test_1(t, name, library, options) libout, err = centre.new_library(name, library, options) if err ~= "OK" then err = tools.error_color(err) end t = t .. tools.Tr .. tools.Td(name) .. tools.Td(library) .. tools.Td( type(libout) ) .. tools.Td(err) return t	end t = t or "\n* new_library_test :" t = t .. "\n* Show some tests of use cases of centre.new_library(name, library, options) :" t = t .. tools.Th .. tools.Tc("library name") .. tools.Tc("library input") .. tools.Tc("library output") .. tools.Tc("error") t = new_library_test_1(t, "emptyTable", {}, "") t = new_library_test_1(t, "emptyFunction", functionend, "") t = new_library_test_1(t, "simpleNumber", 123, nil) t = new_library_test_1(t, "simpleString", "ABC", nil) t = new_library_test_1(t, "libraryExample", { a = "a", fctn = function(i)end }, "") t = new_library_test_1(t, "Module:Main/I18N", {}, "") t = new_library_test_1(t, "text/slash", {} ) t = new_library_test_1(t, "version.2.3", {} ) t = new_library_test_1(t, "available:non/alphanumeric.chars", {} ) t = new_library_test_1(t, "Module:Main/sub-version23", {}, "") t = new_library_test_1(t, "name with spaces", {} ) t = new_library_test_1(t, "semi;column", {} ) t = t .. tools.Te return t end -- function tools.new_library_test(t)

function tools.table_n_vars(tab, tab_name) local st, vr, fn, tb = tools.luatablecount(tab, tab_name) return vr, fn, tb end

function tools.debug_traceback(t) if type(t) ~= "string" then t = "\n* debug.traceback : " end t = t .. debug.traceback t = string.gsub(t, "Module", "\n* Module" ) return t end

function tools.bindmodules_report(t, tracks_level) -- Report all modules installation tools.main_module = centre.main_module tools.main_versions = centre.main_versions tools.main_gettitle = centre.main_gettitle tools.bindmodules_start = centre.bindmodules_start if tracks_level and type(tracks_level) == "number" then tracks_level = math.floor(tracks_level) else tracks_level = 1 end if tracks_level < 0 then tracks_level = 0 end local t = (t or "") .. "\n* tools.tools_verif_bindmodules_report : effective List and verify all modules tools." -- Get previous loaded modules and record tables for further uses and count --	local loaded_pack, loaded_txt = centre.get_loaded_modules -- get the modules state tools.loaded_txt = (loaded_txt or "") --	local loaded_to_sort = centre.loaded_descriptors -- or centre.loaded_vers or centre.loaded_pack or {x=x} tools.report_bind_modules_init_i18n = (tools.report_bind_modules_init_i18n or "") tools.required_sorted = centre.sort_table_in_insert_order(centre.required_descriptors) --[ [ simulate main_versions to try here local vers = { -- initial default version descriptor versionName = "Box3", versionNumber = "3.33", versionDate = "2015-09-09 09:09", sought = " Box3 Group2 Central1 ", -- Sought module and submodules versions known = " Box,Box3 * Group,Group2 * Central,Central1 ", }	--] ]	if tools.main_versions then vers = tools.main_versions end local main_versions = vers -- tools.main_versions local main_versionNumber = vers -- tools.main_versions -- Use main_versions rather than simulate it	-- -- Search the main module which has the most known and sought centre. local loaded_pack = centre.get_loaded_modules -- List all package.loaded modules -- in _G to DEBUG T122752 : #invoke do not record the main module in package.loaded local loaded_max, loaded_main = 0, {} local versionNumber = main_versions.versionNumber -- tools.main_versions.versionNumber for title, get in pairs(loaded_pack) do -- DEBUG reverse order t = t .. tools.ta("title", title) if get.sought_count and get.known_count and ( get.sought_count + get.known_count ) > loaded_max then loaded_max = get.sought_count + get.known_count loaded_main = package.loaded[get.title] pp = loaded_main t = t .. tools.ta("loaded_max", loaded_max) end if get.title == centre.main_gettitle then versionNumber = get.versionNumber end --	get.versionNumber = get.shortVersion end local main_module = loaded_main main_versions.versionNumber = versionNumber if main then t = t .. tools.str_vars(		" Versions report for %1 %2 %3 : "		.. " Main module selector: %4"		.. " Main module all versions: %5", main_versions.versionName, main_versions.versionNumber, main_versions.versionDate,			main_versions.sought, main_versions.known ) end t = t .. tools.ta("modules number", #loaded_pack) tools.bind_verif_modules_report_start = t	-- -- Form the report of centre.loaded_pack = package.loaded modules local loaded_sorted = {} for key, elem in pairs(loaded_pack) do --	if elem.isModule then elem.alias = "Module:" .. elem.versionName end -- Locate translations example in Module:Central/I18N --	if elem.isLibrary then elem.alias = "Library:" .. elem.versionName end -- Locate translations example in Module:Library/centre/I18N table.insert(loaded_sorted, elem) end table.sort(loaded_sorted, function (a, b) return ( a.alias < b.alias ) end ) t = "Report of effective mixed modules: " t2 = "" local head = mw.text.split( tools.str_vars("tools_list_loaded_modules_headers"), ',') t = t .. tools.Th("wikitable sortable") .. tools.Tc(head[1]) .. tools.Tc(head[2]) .. tools.Tc(head[3]) .. tools.Tc(head[4]) .. tools.Tc(head[5]) -- A triable table start with : {| class="wikitable sortable" -- A column become fix and not triable with : ||class="unsortable"| --	for key, elem in pairs(tools.loaded_sorted) do	for key, elem in ipairs(loaded_sorted) do	--	get = { isTitled, title, module, isLoaded, isLibrary, hasi18n, versionName, versionTitle, versionDate, versionNumber, shortVersion, --			i18n, versions, sought, known, sought_tab, sought_count, known_tab, known_count, , --			isModule, isI18N, lessI18N, versionI18N, nowstamp, revistamp, revistime, shortdays, shorttime, nowstamp, delay } -- title = Module:Central, revistamp = 20151207214027, revistime = 2015-12-07 21:40, gettitle = Module:Author3, shortVersion = v07 21:40 or v150227 if elem.i18n then -- elem.i18n local vers18 = elem.versionName --; if not elem.isI18N then vers18 = "" end if elem.isModule then elem.alias = "Module:" .. elem.versionName end -- Locate translations example in Module:Central/I18N if elem.isLibrary then elem.alias = "Library:" .. elem.versionName end -- Locate translations example in Module:Library/centre/I18N t = t .. tools.Tr .. tools.Td( (elem.alias or "") ) .. tools.Td(elem.versionName or "") .. tools.Td( (elem.versionDate or "date") .. ", " .. (elem.shortVersion or "vers") ) .. tools.Td(vers18 or "") .. tools.Td( tools.form_i18n_counts(elem.i18n, "+ %1 sentences in %2 languages") .. tools.form_i18n_counts(centre.maini18n, ", (all %1/%2)") ) if elem.versionName and elem.alias then t2 = t2 .. tools.str_vars(" * alias %1 = %2, version = %3, date = %4",				elem.alias, elem.versionName, elem.shortVersion, elem.versionDate) end end end t = t .. tools.Te tools.report_loaded_pack = t	tools.report_loaded_pack_alias_versions = t2 .. " effective " .. (tools.bindmodules_start or "") -- t = t .. "\n\n\n* effective tools.bindmodules_start: " .. (tools.bindmodules_start or " tools.bindmodules_start missing ") tools.report_loaded_txt = (loaded_txt or " loaded_txt ") --	-- Form the report of loaded_sorted --	local CentralModule, loaded_vers, err, select_txt, alias_txt = tools.bindmodules_verif(main, "list", centre.loaded_pack) tools.report_bind_verif_modules_list = select_txt local main_versions if type(centre.main_module) == "table" and type(centre.main_versions) == "table" then main_versions = centre.main_versions or { versionName = "versionName", versionNumber = "0.0", } tools.report_main_short = main_versions.versionName .. " " .. main_versions.versionNumber tools.report_main_discreet = tools.discreet_color( tools.report_main_short ) tools.report_REVISIONTIMESTAMP = tools.frame:preprocess( "" ) tools.report_actual_versions = (tools.report_main_discreet or "tools.report_main_discreet") -- .. tools.report_REVISIONTIMESTAMP .. " "	else tools.report_main_short = "tools.report_main_short is missing." tools.report_main_discreet = "tools.report_main_discreet is missing." tools.report_REVISIONTIMESTAMP = "tools.report_REVISIONTIMESTAMP is missing." tools.report_actual_versions = "tools.report_actual_versions is missing." end --	t = "" local head = mw.text.split( tools.str_vars("tools_bindmodules_test_headers"), ',') -- tools_bindmodules_test_title -- tools_versions_management_title t = t .. tools.Th .. tools.Tc(head[1]) .. tools.Tc(head[2]) .. tools.Tc(head[4]) if type(main_versions) == "table" then t = t .. tools.Tr .. tools.Td(main_versions.sought) .. tools.Td(main_versions.known) .. tools.Td(select_txt) .. tools.Td(alias_txt) .. tools.Td(err) end t = t .. tools.Te tools.report_bind_verif_modules = t	-- tools.report_loaded_descriptors = centre.tab_elem_report(centre.loaded_descriptors, "title") tools.report_required_descriptors = centre.tab_elem_report(centre.required_descriptors, "title") tools.report_loaded_descriptors_loaded_sorted = centre.tab_elem_report(tools.loaded_sorted, 1) --	centre.trcPVG("tools_verif_bindmodules_report") -- track for tools.bindmodules_verif -- Form the detailed Versions report t = "\n* Discreet main version: " .. (tools.report_main_discreet or " report_main_discreet missing ") t = t .. "\n* effective tools.bindmodules_start: " .. (tools.bindmodules_start or " tools.bindmodules_start missing ") t = t .. " \n\n* Start versions from main module: " .. (tools.bind_verif_modules_report_start or " bind_verif_modules_report_start missing ") t = t .. " \n\n* All versions from main module: " .. (tools.report_main_select_all or " report_main_select_all missing ") t = t .. " \n\n* Modules alias and versions: " .. (tools.report_loaded_pack_alias_versions or " report_loaded_pack_alias_versions missing ") t = t .. "\n\n\n* All selected modules versions: " .. (tools.report_bind_verif_modules or " report_bind_verif_modules missing ") t = t .. "\n\n\n* All loaded modules versions: " .. (tools.report_loaded_pack or " report_loaded_pack missing ") -- loaded_modules tools.support_desk_report = t -- tools.bindmodules_report -- Report all modules installation --	t = "" -- tools.report_bind_verif_modules_details t = t .. "\n* tools.bindmodules_start: " .. (tools.bindmodules_start or " tools.bindmodules_start missing ") t = t .. "\n\n\n* effective report_find_main_module: " .. (tools.report_find_main_module or " report_find_main_module missing ") t = t .. " \n* bind_verif_modules_recursive: " .. (tools.ta("bind_verif_modules_recursive", tools.bind_verif_modules_recursive) or " bind_verif_modules_recursive missing ") t = t .. " \n* effective list loaded descriptors: " .. (tools.report_loaded_descriptors or " report_loaded_descriptors missing ") t = t .. " \n* List required descriptors: " .. (tools.report_required_descriptors or " report_required_descriptors missing ") t = t .. " \n* List loaded descriptors sizes: " .. (tools.report_loaded_descriptors_loaded_sorted or " report_loaded_descriptors_loaded_sorted missing ") t = t .. " \n* Search the MainModule: " .. (tools.report_find_main_module or " report_find_main_module missing ") t = t .. " \n* List elem.alias : " .. (tools.alias_txt or " alias_txt missing ") t = t .. " \n\n* " .. (tools.report_bind_verif_modules_list or " report_bind_verif_modules_list missing ") --	t = t .. " \n\n* All used modules versions: " .. (tools.report_main_used or " report_main_used missing ") t = t .. "\n* Text report of package.loaded modules: " .. (tools.report_loaded_txt or " report_loaded_txt missing ") -- loaded_modules t = t .. "\n\n\n* Text report of _G global modules: " .. (tools.report_loaded_G or " report_loaded_G missing ") -- loaded_modules t = t .. " \n\n* All effective I18N modules used in this order. t/l = texts/languages : " .. (tools.report_bind_modules_init_i18n or " report_bind_modules_init_i18n missing ") --	t = t .. centre.get_edit_state -- Detect if the wiki page using the module is in edit state t = t .. " \n* " .. centre.trcPVG_txt --	t = t .. " \n* " .. tools.i18n_trc tools.report_bind_verif_modules_details = t	return t end -- function tools.bindmodules_report(t, tracks_level) -- Report all modules installation

function tools.versions_manage_report(t) -- Report some aspects of the versions management local t = t or " * tools.versions_manage_report:" t = t .. " \n* Discreet main version: " .. (tools.report_main_discreet or " report_main_discreet missing ") t = t .. " \n* All selected modules versions: " .. (tools.report_bind_verif_modules or " report_bind_verif_modules missing ") t = t .. " " .. tools.report_loaded_pack t = t .. " \n* " .. tools.list_loaded_modules t = t .. " \n* " .. (tools.report_bind_verif_modules_list or " report_bind_verif_modules_list missing ") t = t .. " \n* Modules alias and versions: " .. (tools.report_loaded_pack_alias_versions or " report_loaded_pack_alias_versions missing ") -- long t = t .. " \n* Start versions from main module: " .. (tools.bind_verif_modules_report_start or " bind_verif_modules_report_start missing ") t = t .. " \n* All versions from main module: " .. (tools.report_main_select_all or " report_main_select_all missing ") t = t .. " \n* " .. tools.wiki_modules_users -- Report some aspects of the versions management t = t .. " \n* tools.bindmodules_start: " .. (tools.bindmodules_start or " tools.bindmodules_start missing ") t = t .. " \n* List required descriptors: " .. (tools.report_required_descriptors or " report_required_descriptors missing ") --	t = t .. " \n* Search the MainModule: " ..ki18 (tools.report_find_main_module or " report_find_main_module missing ") --	t = t .. tools.tools_verif_bindmodules_report -- Test of binding of the modules and versions control tools_verif_bindmodules_report t = t .. " Track number of translations along bindmodules process" .. tools.tracki18n_all --	t = t .. (tools.report_bind_verif_modules_details or "") --	t = "\n--" .. t	return t end -- function tools.versions_manage_report(t) -- {-{Central|doc1|versions_manage_report_title}-}

function tools.documentations_changes_report(t) -- The tests function uses mode and options to include edit or tests. local res = t or "" res = res .. "\n: Documentation of Module:Central: wikisource:Central modules." res = res .. "\n: Development of Module:Central: wikisource:Module:Central." res = res .. "\n: Example of use: wikisource:Rical/Victor_Hugo." --	res = res .. tools.tasks_table_report_short res = res .. "\n* List of blocking tasks: " .. tools.tasks_table_report_full return res end -- function tools.documentations_changes_report(t)

function tools.running_times( if_view, res, time1, time2, time3, time4) -- Display example : -- Execution and test_time : 2014-02-22 18:09:15 UTC, url = http://fr.wikisource.org/wiki/Module:Central/Documentation , -- start = 84 mS, import + 8 mS , generate page + 0 mS , tests + 127 mS , total = 221 mS Central:tests:fr tools.time4 = os.clock if not if_view then return "" end time1 = time1 or tools.time1 or os.clock time2 = time2 or tools.time2 or time1 time3 = time3 or tools.time3 or time1 time4 = time4 or tools.time4 or time1 if time2 < time1 then time2 = time1 end if time3 < time2 then time3 = time2 end if time4 < time3 then time4 = time3 end local nowtime = os.date("%Y-%m-%d %H:%M:%S") local mwtitle = mw.title.getCurrentTitle local url = tostring(mwtitle:canonicalUrl) local time2d = time2 - time1 local time3d = time3 - time2 local time4d = time4 - time3 local duration = time2d + time3d + time4d time1 = tostring(math.floor( time1	 * 1000 )) .. " mS" time2d = tostring(math.floor( time2d * 1000 )) .. " mS" time3d = tostring(math.floor( time3d * 1000 )) .. " mS" time4d = tostring(math.floor( time4d * 1000 )) .. " mS" duration = tostring(math.floor( duration * 1000 )) .. " mS" res = res or "" res = res .."\n* Execution and test_time: " .. nowtime .. " UTC" .. tools.ta("url", url) -- prefixedText res = res .. tools.ta(" start in page", time1) .. tools.ta("import", time2d, "+") res = res .. tools.ta("form result", time3d, "+") .. tools.ta("tests", time4d, "+") .. tools.ta("duration", duration) --[ [	if tools.frame then res = res .. " \n* Revision time and user language: " res = res .. tools.ta("REVISIONTIMESTAMP:Module:Central", tools.frame:preprocess( "" ) ) res = res .. tools.ta("REVISIONTIMESTAMP", tools.frame:preprocess( "" ) ) res = res .. tools.ta("CONTENTLANGUAGE", tools.frame:preprocess( "" ) ) res = res .. tools.ta("REVISIONUSER", tools.frame:preprocess( "" ) ) res = res .. tools.ta("USERLANG", tools.frame:preprocess( "" ) ) res = res .. tools.ta("UILANGCODE", tools.frame:preprocess( "" ) ) res = res .. tools.ta("USERIFCODE", tools.frame:preprocess( "" ) ) res = res .. tools.ta("USERLANGUAGE", tools.frame:preprocess( "" ) ) end --] ]	-- see https://fr.wikipedia.org/wiki/Discussion:ISO_8601#Av._J.C._:_contradiction_avec_l.27article_anglais -- see https://fr.wikipedia.org/w/index.php?title=ISO_8601&diff=next&oldid=12449725 -- see ISO 8601 time format like : 1977-04-22T01:00:00-05:00 (5 heures de décalage) = 1977-04-22T06:00:00Z local time -- os.date( format, time ) get datetime -- =20151101023804 Timestamp as of time of edit. -- =2015, =07, =01	-- DEBUG wait for : T68051 Get the user language to help admins to maintain a module or a template (userInfo: String user and password) local mwuri = mw.uri.canonicalUrl(mwtitle.prefixedText, { host, authority, user, password, } ) --	res = res .. tools.ta("mwtitle.prefixedText", mwtitle.prefixedText) .. tools.ta("mwuri", mwuri) --	res = res .. "\n\n* Page title details: " .. tools.ta("host", tostring(mwuri.host)) .. tools.ta("authority", tostring(mwuri.authority))	res = res .. tools.ta("user", tostring(mwuri.user)) .. tools.ta("user_language", tostring(mwuri.language))	--	spaces_page_names_test :, mwtitle = Auteur:Nelson Mandela , nsText = Auteur , baseText = Nelson Mandela , url =	-- subpageText: If this is a subpage, just the subpage name. Otherwise, the same as title.text.	res = res .. tools.ta("text", tostring(mwtitle.text)) .. tools.ta("baseText", tostring(mwtitle.baseText))	res = res .. tools.ta("rootText", tostring(mwtitle.rootText)) .. tools.ta("subpageText", tostring(mwtitle.subpageText))	-- return res end -- function tools.running_times( if_view, res, time1, time2, time3, time4)

-- local object = {} local php function tools.setupInterface( options ) -- Remove setup function tools.setupInterface = nil -- Copy the PHP callbacks to a local variable, and remove the global php = mw_interface mw_interface = nil -- Do any other setup here -- Install into the mw global mw = mw or {} mw.ext = mw.ext or {} mw.ext.tools = tools -- Indicate that we're loaded package.loaded['mw.ext.tools'] = tools return tools end

function tools.invoke_central_doc1(title) --	res = res .. tools.invoke_central_doc1("tools_options_from_mode_title") -- calling example local res =					 " * '''funct = doc1, [1] = " .. title .. "'''"	res = res .. "  "	res = res .. tools.frame:preprocess("") --	res = res .. tools.frame:preprocess("") -- prototype return res end -- function tools.invoke_central_doc1(title)

function tools.tracki18n(where, module) -- List number of available translations and languages, and their central collection. tools.tracki18n_all = tools.tracki18n_all or "" local res = "\n* trk: '''" .. where .. "''', "	if type(module) == "table" and type(module.i18n) == "table" then res = res .. tools.form_i18n_counts(module.i18n, "module=%1/%2, ") end res = res .. tools.form_i18n_counts(centre.maini18n, "maini18n=%1/%2, ") res = res .. tools.form_i18n_counts(centre.maini18n, "mathroman_char_X_in_N_err") tools.tracki18n_all = tools.tracki18n_all .. res return res --	t = t .. " * " .. tools.form_i18n_counts(i18n, txt) --	function tools.tracki18n(where, module) --	local st, vr, fn, tb = tools.luatablecount(module.maini18n) end -- function tools.tracki18n(where, module)

function tools.init_tools(frame, options_for_modes) local res = "" frame = frame or mw.getCurrentFrame tools.frame = frame tools.errors_list = {} -- Table to collect errors and messages tools.categories_list = {} -- init the collect of categories --	tools.categories_init -- initialize the category list tools.options_for_modes = options_for_modes or tools.options_for_modes return res end -- function tools.init_tools(frame, options_for_modes)

--	Start of Simulation of Library:mathroman from Module:MathRoman --	_G["mathroman"] = {}

-- -- Install Library:mathroman													-- -- Libraries dependencies: -- For a right display of the errors messages, this Library:mathroman needs the Library:tools --

-- Tables des traductions des paramètres et messages dans les langues : en, es, fr. -- Tables of translations of settings and messages in the languages : en, es, fr. -- Mesas traducciones parámetros y mensajes en los idiomas : en, es, fr. -- -- i18n translations tables to extend and update in calling modules

mathroman = {} mathroman.i18n = {} -- translations tables known in the module

mathroman.i18n.en = { mathroman_errors_head_err				= "Error: ", mathroman_roman_err						= "Roman error: ", mathroman_value_error_err				= "Value error: ", mathroman_J_before_end_err				= "character J before the end", mathroman_char_X_in_N_err				= "character %1 in %2", mathroman_char_increase_err 			= "3 increasing characters", mathroman_greater_4999_err				= "value > 4999", mathroman_null_value_err				= "null value", mathroman_rom2dig_value_err				= "roman value error", mathroman_dig2rom_value_err				= "digital value error", mathroman_rom2dig_testtitle 			= "Test from roman to digital numbers", mathroman_dig2rom_testtitle 			= "Test from digital to roman numbers", mathroman_recursive_TestsCases_title	= "Mediawiki recursive TestsCases", } -- mathroman.i18n.en db

mathroman.i18n.es = { mathroman_errors_head_err				= "Error: ", mathroman_roman_err						= "Error de romano: ", mathroman_value_error_err				= "Error de valor: ", mathroman_J_before_end_err				= "carácter J antes del fin", mathroman_char_X_in_N_err				= "carácter 1% en %2", mathroman_char_increase_err 			= "3 crecientes caracteres", mathroman_greater_4999_err				= "valor > 4999", mathroman_null_value_err				= "valor null", mathroman_rom2dig_value_err				= "romano valor error", mathroman_dig2rom_value_err				= "decimale valor error", mathroman_rom2dig_testtitle 			= "Prueba de números romanos a números decimales", mathroman_dig2rom_testtitle 			= "Prueba de números decimales a números romanos", mathroman_recursive_TestsCases_title	= "Mediawiki TestsCases recursivos", } -- mathroman.i18n.es

mathroman.i18n.fr = { mathroman_errors_head_err				= "Erreur : ", mathroman_roman_err						= "Erreur de romain : ", mathroman_value_error_err				= "Erreur de valeur : ", mathroman_J_before_end_err				= "caractère J avant la fin", mathroman_char_X_in_N_err				= "caractère %1 en %2", mathroman_char_increase_err 			= "3 caractères croissants", mathroman_greater_4999_err				= "valeur > 4999", mathroman_null_value_err				= "valeur nulle", mathroman_rom2dig_value_err				= "erreur de valeur de romain", mathroman_dig2rom_value_err				= "erreur de valeur de décimal", mathroman_rom2dig_testtitle 			= "Test des nombres romains en nombres décimaux", mathroman_dig2rom_testtitle 			= "Test des nombres décimaux en nombres romains", mathroman_recursive_TestsCases_title	= "Mediawiki TestsCases recursifs", } -- mathroman.i18n.fr

--	vueRomains : XIJ=12 MCXI=1111 MCDXLIV=1444 MDCLXVI=1666 MCMXCIX=1999 MMCCXXII=2222 MMMMCMXCIX=4999 ERREURS=0 erreur caractere S en 7. XIA=11 erreur caractere A en 3. XJI=12 erreur caractere J avant la fin. IXC=89 erreur caracteres croissants. VLD=445 erreur caracteres croissants. MMMMM=5000 erreur > 4999. MMMMMYJXC=5089 erreur > 4999. erreur caractere Y en 6. erreur caractere J avant la fin.

mathroman.TestCaseOK = "OK" mathroman.TestCaseERR = "ERR" mathroman.TestCaseErrorsCode = ","

function mathroman.TestCaseErrors_add(ref, v1, v2, v3, v4, v5) -- DEBUG : mathroman.int2roman can fail without blocking page. mathroman.TestCaseErrorsCode = tostring(mathroman.TestCaseErrorsCode) .. "," .. tostring( tools.str_test_case(tostring(ref), v1, v2, v3, v4, v5) ) -- db	return mathroman.TestCaseErrorsCode end

function mathroman.pcall_int2roman(val, errs) -- DEBUG : mathroman.int2roman can fail without blocking page. --	EBUG: Without this patch the mathroman.int2roman get the parser error "attempt to call field 'int2roman' ". Patched by Rical 2015-04-20. --	local event_century_roman = "" --	word, errx = mathroman.int2roman(val, errs) -- See Maniphest T27845 Support loading wiki pages through mediaWiki.loader.load -- DEBUG code: local success, word, errs = pcall(mathroman.int2roman, val, errs) -- pcall or xpcall can run any function without blocking page. if success then return word, errs else return nil, errs end end

function mathroman.pcall_roman2int(word, errs) -- DEBUG : mathroman.roman2int can fail without blocking page. --	DEBUG: Without this patch the mathroman.int2roman get the parser error "attempt to call field 'roman2int' ". Patched by Rical 2015-04-20. --	val, errs = mathroman.roman2int(word, errs) local success, val, errs = pcall(mathroman.roman2int, word, errs) -- pcall or xpcall can run any function without blocking page. if success then return val, errs else return nil, errs end end

--	Romans view : XIJ=12 MCXI=1111 MCDXLIV=1444 MDCLXVI=1666 MCMXCIX=1999 MMCCXXII=2222 MMMMCMXCIX=4999 ERREURS=0 erreur caractere S en 7. XIA=11 erreur caractere A en 3. XJI=12 erreur caractere J avant la fin. IXC=89 erreur caracteres croissants. VLD=445 erreur caracteres croissants. MMMMM=5000 erreur > 4999. MMMMMYJXC=5089 erreur > 4999. erreur caractere Y en 6. erreur caractere J avant la fin.

function mathroman.roman2int(rm, testcase) --	tools.erron = true --	if type(rm) == "table" then rm = rm[1] end --	if type(rm) == "table" then rm = rm[rm] end -- NO --	if ( rm == nil ) then rm = '+' end --	if ( rm == '' ) then return '+' end if type(rm) == "table" then rm = rm[rm] end if type(testcase) ~= "table" then testcase = nil end if ( rm == nil ) then rm = '' end if ( rm ==  ) then return  end local v = 0 -- valeur totale local v1 = 0 -- valeur de derniere lettre local v2 = 0 -- valeur de lettre precedente local v3 = 0 -- valeur de lettre precedente local x = '-' -- caractere en cours d'evaluation local i = 1 -- numero du caractere en cours d'evaluation local j = 0 -- numero du caractere de reference courant (debut en Lua) local k = 0 -- numero du caractere de reference courant (fin en Lua) local testerrs = ",X," local errs = errs or "" errs = "" local lst = '-MDCLXVIJ' -- caracteres autorises x = string.sub(rm, i, i) or '' while (x ~= '') do		v3 = v2		v2 = v1		v1 = 0 --	x = string.sub(rm, i, i)		if ( x == 'M' ) then v1 = 1000 end if ( x == 'D' ) then v1 = 500 end if ( x == 'C' ) then v1 = 100 end if ( x == 'L' ) then v1 = 50 end if ( x == 'X' ) then v1 = 10 end if ( x == 'V' ) then v1 = 5 end if ( x == 'I' ) then v1 = 1 end if ( x == 'J' ) then v1 = 1 end if ( x == 'J' ) and ( i < string.len(rm) ) then errs = errs .. tools.err_add("mathroman_J_before_end_err") -- e4 = ' erreur caractere J avant la fin.' testerrs = testerrs .. mathroman.TestCaseErrors_add("mathroman_J_before_end_err", rm, i)		end if ( v1 == 0 ) then errs = errs .. tools.err_add("mathroman_char_X_in_N_err", x, i) -- e3 = ' erreur caractere '..x..' en '..i..'.' testerrs = testerrs .. mathroman.TestCaseErrors_add("mathroman_char_X_in_N_err", x, i)		end v = v + v1 if ( (v1 == 5*v2) or (v1 == 10*v2) ) then v = v - (2*v2) end -- ajuster 4, 9, 40, 90 ... j, k = string.find(lst, x)		if ( j == nil ) then j = -1 end if ( k == nil ) then k = -1 end if (v1 > v2) and (v2 > v3) and (v3 > 0) then errs = errs .. tools.err_add("mathroman_char_increase_err") -- e2 = ' caracteres croissants.' testerrs = testerrs .. mathroman.TestCaseErrors_add("mathroman_char_increase_err", rm, i) -- db		end i = i + 1 x = string.sub(rm, i, i) or '' end if ( v == 0 ) then --	e0 = ' valeur nulle.' errs = errs .. tools.err_add("mathroman_null_value_err") testerrs = testerrs .. mathroman.TestCaseErrors_add("mathroman_null_value_err", rm, v)	--	v = 1 end if ( v > 4999 ) then -- e1 = ' valeur > 4999.' errs = errs .. tools.err_add("mathroman_greater_4999_err") testerrs = testerrs .. mathroman.TestCaseErrors_add("mathroman_greater_4999_err", rm, v)	--	v = 4999 end --	if testcase then testcase.testerrs = testerrs end --	{ name = 'mathroman.roman2int (4)', func = mathroman.roman2int, args = { rm = "VI", }, expect = { 123 } }, if testcase then testcase.testcode = mathroman.TestCaseErrors_add(testcase.subkey .. "_testcode", rm, v)		testcase.testerrs = testerrs errs = testerrs end --	if testcase then --		testcase.testcode = mathroman.TestCaseErrors_add(testcase.subkey .. "_testcode", i, roman) --		errs = testerrs --	end return v, errs, cats end -- function mathroman.roman2int(rm)

function mathroman.romani2r(i, j)	if ( j == nil ) then j = '' end local rm='' if ( i == 1000 ) then rm = 'M' end if ( i == 500 ) then rm = 'D' end if ( i == 100 ) then rm = 'C' end if ( i == 50 ) then rm = 'L' end if ( i == 10 ) then rm = 'X' end if ( i == 5 ) then rm = 'V' end if ( i == 1 ) then rm = 'I'		if ( j == 'J' ) then rm = 'J' end end return rm end -- function mathroman.romani2r(i, j)

function mathroman.int2roman(i, testcase) local n = 0 if ( i == nil ) then n = 0 else n = i end -- anti nill if ( type(n) ~= 'number' ) then n = tonumber(n) end if ( type(n) ~= 'number' ) then n = 0 end n = math.floor(n) -- input:89: bad argument #1 to 'floor' (number expected, got nil) if type(errs) ~= 'string' then errs = "" end -- anti nill, to text errs = "" local v100 = 100 local v500 = v100*5 local v1000 = v100*10 -- roman cycle romain 1000, 100, 10, 1 local v, v1, v2, v3 = 0, 0, 0, 0 -- Total value, last, and previous. Valeur totale, derniere, et precedentes. local reste, reduction = 0, 0 -- Rest to convert, last reduction. Reste a convertir, derniere reduction. local rm = '' local roman = '' -- chiffre et nombre romain resultant local errs = "" -- errs or "" if type(testcase) ~= "table" then testcase = nil end local testerrs = ",*," reste = n	if ( n > 4999 ) then errs = errs .. tools.err_add("mathroman_greater_4999_err") -- e1 = ' valeur > 4999.' testerrs = testerrs .. mathroman.TestCaseErrors_add("mathroman_greater_4999_err", n) -- db		reste = 0 roman = "" -- 'ERROR' end if ( n < 1 ) then --	n = 0 errs = errs .. tools.err_add("mathroman_null_value_err") -- e2 = ' valeur < 1.' testerrs = testerrs .. mathroman.TestCaseErrors_add("mathroman_null_value_err", n) -- db		reste = 0 roman = "" -- 'ERROR' end while (reste > 0) do		v3 = v2		v2 = v1		v1 = reste reduction = 0 if ( reste >= v1000 ) then reduction = v1000 elseif ( reste >= v100*9 ) then reduction = v100 reste = reste + v100*2 elseif ( reste >= v500 ) then reduction = v500 elseif ( reste >= v100*4 ) then reduction = v100 reste = reste + v100*2 elseif ( reste >= v100 ) then reduction = v100 elseif ( reste >= 1000 ) then v100 = 100 v1000 = 1000 reduction = v1000 end rm = mathroman.romani2r(reduction) roman = roman .. rm		reste = reste - reduction if ( reste < v100 ) then if ( v100 >= 10 ) then v100 = v100/10 v500 = v100*5 v1000 = v100*10 end end end --	{ subkey = 'int2roman', func = mathroman.int2roman, args = { i = 444 }, expect = { "CDXLIV" } }, if testcase then testcase.testcode = mathroman.TestCaseErrors_add(testcase.subkey .. "_testcode", i, roman) errs = testerrs end return roman, errs -- avec ou sans erreurs end -- function mathroman.int2roman(i, testcase)

function mathroman.roman_to_digital_test(t, word) -- Unitary tests of mathroman.roman2int t = t or "roman_to_digital_test" t = "\n:*'''" .. t .. "''':" --	t = t .. tools.Th .. tools.Tc("Nombre romain") .. tools.Tc("Valeur décimale (et corrigée)") .. tools.Tc("Erreur") t = t .. tools.Th .. tools.Tc("Roman number") .. tools.Tc("Digital value (and corrected)") .. tools.Tc("Error") function roman_to_digital_test1(t, word) --	local val, errs = mathroman.pcall_roman2int(word) -- DEBUG : mathroman.roman2int can fail without blocking page. local val, errs = mathroman.roman2int(word) -- DEBUG : mathroman.roman2int can fail without blocking page. --	if not val then errs = errs .. " p " .. tools.err_add(errs) end local wordX, errsX = mathroman.int2roman(val) -- DEBUG : mathroman.roman2int can fail without blocking page. if wordX then val = tostring(val) .. " ( = " .. tostring(wordX) .. " ) " end t = (t or "") .. tools.Tr .. tools.Td(word) .. tools.Td(val or "") .. tools.Td(errs or "") return t	end t = roman_to_digital_test1( t, "-X") t = roman_to_digital_test1( t, "0") t = roman_to_digital_test1( t, "MCXI") t = roman_to_digital_test1( t, "XIJ") t = roman_to_digital_test1( t, "XJI") t = roman_to_digital_test1( t, "XIA") t = roman_to_digital_test1( t, "VLD") t = roman_to_digital_test1( t, "IXC") t = roman_to_digital_test1( t, "MMMMCMXCIX") t = roman_to_digital_test1( t, "MMMMM") t = roman_to_digital_test1( t, "MMMMMYJXC") t = t .. tools.Te return t end -- function mathroman.roman_to_digital_test( t, args_known)

function mathroman.digital_to_roman_test(t, val) -- Unitary tests of mathroman.int2roman t = t or "digital_to_roman_test" t = "\n:*'''" .. t .. "''':" --	t = t .. tools.Th .. tools.Tc("Nombre décimal") .. tools.Tc("Nombre romain") .. tools.Tc("Erreur") t = t .. tools.Th .. tools.Tc("Digital value") .. tools.Tc("Roman number") .. tools.Tc("Error") function digital_to_roman_test1( t, val) --	local word, errs = mathroman.pcall_int2roman(val, " ") -- DEBUG : mathroman.int2roman can fail without blocking page. local word, errs = mathroman.int2roman(val, " ") -- DEBUG : mathroman.int2roman can fail without blocking page. t = (t or "") .. tools.Tr .. tools.Td(val) .. tools.Td(word or "") .. tools.Td(errs or "") return t	end t = digital_to_roman_test1( t, -10) t = digital_to_roman_test1( t, 0) t = digital_to_roman_test1( t, 12) t = digital_to_roman_test1( t, 17) t = digital_to_roman_test1( t, "18") t = digital_to_roman_test1( t, "19") t = digital_to_roman_test1( t, 111) t = digital_to_roman_test1( t, 444) t = digital_to_roman_test1( t, 555) t = digital_to_roman_test1( t, "777") t = digital_to_roman_test1( t, "1111") t = digital_to_roman_test1( t, "4999") t = digital_to_roman_test1( t, "5000") t = t .. tools.Te return t end -- function mathroman.digital_to_roman_test(t, val)

--	vueRomains : XIJ=12 MCXI=1111 MCDXLIV=1444 MDCLXVI=1666 MCMXCIX=1999 MMCCXXII=2222 MMMMCMXCIX=4999 ERREURS=0 erreur caractere S en 7. XIA=11 erreur caractere A en 3. XJI=12 erreur caractere J avant la fin. IXC=89 erreur caracteres croissants. VLD=445 erreur caracteres croissants. MMMMM=5000 erreur > 4999. MMMMMYJXC=5089 erreur > 4999. erreur caractere Y en 6. erreur caractere J avant la fin.

--	End of Simulation of Library:mathroman from Module:MathRoman

--	Tests : class ClassNameTest extends Scribunto_LuaEngineTestBase --	protected static $moduleName = 'ClassNameTest'; mathroman.tests_cases = { -- Autotest cases to validate the mathroman library at mediawiki level. -- each test_case defines a name, a function, an input, an output. See also tools.str_test_case. db	{ subkey = 'int2roman', func = mathroman.int2roman, args = { i = 1, }, expect = { "I" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 2, }, expect = { "II" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 3, }, expect = { "III" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 4, }, expect = { "IX" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 5, }, expect = { "V" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 6, }, expect = { "VI" } }, --	{ subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "I" }, expect = { 1 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "II" }, expect = { 2 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "III", }, expect = { 6 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "VI", }, expect = { 123 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "V", }, expect = { 1 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "VI", }, expect = { 1 } }, }

--	Tests : class ClassNameTest extends Scribunto_LuaEngineTestBase --	protected static $moduleName = 'ClassNameTest'; mathroman.TestsCasesGroup = { -- Autotest cases to validate the mathroman library at mediawiki level. -- each test_case defines a name, a function, an input, an output. See also tools.str_test_case. { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 1 }, expect = { "I" }, }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 3 }, expect = { "III" }, }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 6 }, expect = { "VIII" }, }, --	{ subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "IV", }, expect = { 4 }, }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "V", }, expect = { 5 }, }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "III", }, expect = { 6 }, }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "VI", }, expect = { 6 }, }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "I" }, expect = { 22 }, }, }

--	Tests : class ClassNameTest extends Scribunto_LuaEngineTestBase db --	protected static $moduleName = 'ClassNameTest'; mathroman.Tests_int2roman = { -- Autotest cases to validate the mathroman library at mediawiki level. -- each test_case defines a name, a function, an input, an output. See also tools.str_test_case. --	{ subkey = 'int2roman', name = '_1', group = mathroman.TestsCasesGroup, args = { [1] =1 }, expect = { [1] = "I" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = -11 }, expect = { "" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 0 }, expect = { "" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 12 }, expect = { "XII" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 17 }, expect = { "XVII" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 18 }, expect = { "XVIII" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 19 }, expect = { "XIX" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 111 }, expect = { "CXI" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 444 }, expect = { "CDXLIV" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 555 }, expect = { "DLV" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 777 }, expect = { "DCCLXXVII" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 1111 }, expect = { "MCXI" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 4999 }, expect = { "MMMMCMXCIX" } }, { subkey = 'int2roman', func = mathroman.int2roman, args = { i = 5000 }, expect = { "0" } }, } mathroman.Tests_roman2int = { -- Autotest cases to validate the mathroman library at mediawiki level. -- each test_case defines a name, a function, an input, an output. See also tools.str_test_case. { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "-X" }, expect = { 10 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "0" }, expect = { 0 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "" }, expect = { 0 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "MCXI" }, expect = { 1111 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "XIJ" }, expect = { 12 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "XJI" }, expect = { 12 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "XIA" }, expect = { 11 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "VLD" }, expect = { 445 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "IXC" }, expect = { 89 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "MMMMCMXCIX" }, expect = { 4999 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "MMMMM" }, expect = { 5000 } }, { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "MMMMMYJXC" }, expect = { 5089 } }, { module = mathroman, subkey = 'roman_group', group = mathroman.TestsCasesGroup, }, -- name = 'mathroman_roman2int', } mathroman.TestsRecursive = { -- Autotest cases to validate the mathroman library at mediawiki level. { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "XIJ" }, expect = { 12 } }, { module = mathroman, subkey = 'TestsRecursive1', group = mathroman.TestsRecursive, }, -- name = 'mathroman_int2roman', { subkey = 'roman2int', func = mathroman.roman2int, args = { rm = "MCXI" }, expect = { 1111 } }, { module = mathroman, subkey = 'TestsRecursive2', group = mathroman.TestsRecursive, }, -- name = 'mathroman_int2roman', -- each test_case defines a name, a function, an input, an output. See also tools.str_test_case. } mathroman.TestsGroups = { -- Autotest cases to validate the mathroman library at mediawiki level. { module = mathroman, subkey = 'groups', group = mathroman.Tests_int2roman, }, -- name = 'mathroman_int2roman', { module = mathroman, subkey = 'groups', group = mathroman.Tests_roman2int, }, -- name = 'mathroman_roman2int', { module = mathroman, subkey = 'tests_recursive', group = mathroman.TestsRecursive, }, -- To test recursive limit -- each test_case defines a name, a function, an input, an output. See also tools.str_test_case. }

-- Define ClassCentralMathromanTests.lua

mathroman.count = 0 -- generic testcase for mathroman.TestsCases

function mathroman.provide(n, test_name, ok) -- generic testcase for mathroman.TestsCases return n, test_name, ok --	Extension:Scribunto/Lua reference manual : provide( n ): Function that returns three values: n, the name of test n, and a string that is the expected output for test n. end

function mathroman.run( n, testcase ) -- generic testcase for mathroman.TestsCases --	Extension:Scribunto/Lua reference manual : run( n ): Function that runs test n and returns one string. local ok = mathroman.TestCaseOK local t = "-", "" -- intern report to display for humans res = testcase.func( testcase.args ) if res ~= mathroman.TestCaseOK then res_all = res_all .. ", " .. res end return ok, t -- t is for trace end

function mathroman.TestsCases_recursive( test_name, group, recursive, count_only ) -- Run a group of tests and returns one string. local t = "" -- intern report to display for humans if type(tools.recursivity) ~= "number" then tools.recursivity = 111 end if type(recursive) ~= "number" then recursive = 1 end recursive = math.floor( recursive ) if recursive < 1 then recursive = 1 end if recursive > tools.recursivity then local t_levelmaxi = tools.str_vars("tools_table_listlimit_levelmaxi", recursive - 1) return tools.message_color( tostring(t_levelmaxi) ), tot_vars, tot_func, tot_tabs end local really_tests = not count_only local n, ok, outest, res, err, res2, name, args, tt, xxx, sub_ok, sub_t, sub_count local sub_ok, sub_t, sub_count ok = mathroman.TestCaseOK err = mathroman.TestCaseERR test_name = test_name or "_" res_all = 0 sub_count = 0 --	t = t .. "\n**; TestsCases " .. tools.ta("recursive", recursive) .. tools.ta("group.countonly", group.countonly) if group.countonly then group.count_all = group.count_all or 0 -- group.countonly or 	end group.count_one = 0 mathroman.count = sub_count -- group.count_one for k, testcase in ipairs(group) do -- For all sub-tests in the group testcase.subkey = testcase.subkey or "subkey" testcase.subkey_n = testcase.subkey .. "_" .. (group.count_one + 1) name = test_name .. "_" .. testcase.subkey_n if testcase.group then -- db			testcase.group.count_one = group.count_one if not count_only then testcase.group.countonly = 0 testcase.group.count_all = 0 sub_ok, sub_t, sub_count = mathroman.TestsCases_recursive( test_name, testcase.group, recursive, count_only ) -- Run a group of tests and returns one string. testcase.group.count_all = testcase.group.count_all + sub_count if not testcase.group.countonly then --		testcase.group.countonly = sub_count else --		testcase.group.countonly = testcase.group.countonly + sub_count --		testcase.group.count_all = testcase.group.count_all + sub_count end end testcase.group.count_all = testcase.group.count_all or group.count_all sub_ok, sub_t, sub_count = mathroman.TestsCases_recursive( name, testcase.group, recursive + 1 ) -- Run a group of tests and returns one string. group.countonly = testcase.group.countonly + sub_count group.count_one = testcase.group.count_one t = t .. "\n**; TestsCases " .. tools.ta("recursive level", recursive) .. tools.str_vars("n/N = %1/%2", group.count_one, testcase.group.count_all) .. tools.ta("group", name) t = t .. sub_t else group.count_one = group.count_one + 1 args = testcase.args local errs = "-*-" if args then mathroman.TestCaseErrorsCode = "," --	testcase.group.count_one = group.count_one if really_tests then mathroman.count = group.count_all n_, name_, ok_ = mathroman.provide(group.count_one, name, ok) -- generic testcase for mathroman.TestsCases res, tt = mathroman.run( group.count_one, testcase ) -- transmit any number of named args errs = errs .. tt				end local a = "" for k, val in pairs(args) do -- For all sub-tests in the group a = a .. tools.ta(k, val) end t = t .. "\n* " .. tools.str_vars("n/N = %1/%2, countonly=%3, sub_count=%4, ", group.count_one, group.count_all, group.countonly, sub_count) t = t .. tools.str_vars(" name = %1(%2), ", name, a)				if testcase.expect then if res == testcase.expect[1] then t = t .. tools.ta(" errs", errs) .. tools.ta("testcode", testcase.testcode) .. tools.ta("argserrs", mathroman.TestCaseErrorsCode) else mathroman.TestCaseErrorsCode = tools.compact_comma_list(mathroman.TestCaseErrorsCode) t = t .. tools.ta("testcode", testcase.testcode) .. tools.ta("argserrs", tools.error_color(mathroman.TestCaseErrorsCode) ) end end end group.countonly = group.countonly + 1 end end return ok, t, group.countonly or 1 --	Extension:Scribunto/Lua reference manual : run( n ): Function that runs test n and returns one string. end -- function mathroman.TestsCases_recursive( test_name, group, recursive )

function mathroman.example(t) -- db	local t = t or "TestsCases mathroman: " local i, r = 2013, "-" r = mathroman.int2roman(i) t = "\n*" .. t .. "int2roman(" .. i .. ") = " .. r .. ", "	local i, r = 0, "MMXVI" i = mathroman.roman2int(r) t = t .. "roman2int(" .. r .. ") = " .. i .. ", "	return t end -- function mathroman.example(t)

function mathroman.TestsCases_recursive_tests local t, tt, ok = "", "" t = t .. mathroman.example -- "mathroman:tests ")	ok, tt = mathroman.TestsCases_recursive( "mathroman", mathroman.TestsGroups ) -- Run a group of tests and returns one string.	t = t .. tt	return t end -- function mathroman.example(t)

-- Extension:Scribunto/Lua reference manual : Test cases in another extension There are (at least) two ways to run PHPUnit tests:   Run phpunit against core, allowing the tests/phpunit/suites/ExtensionsTestSuite.php to find the extension's tests using the UnitTestsList hook. If your extension's test class names all contain a unique component (e.g. the extension's name), the --filter option may be used to run only your extension's tests.    Run phpunit against the extension directory, where it will pick up any file ending in "Test.php". Either of these will work fine if Scribunto is loaded in LocalSettings.php. And it is easy for method

--	End of Simulation of Library:mathroman from Module:MathRoman

--	try part of Module:Central -- --	At code level, try part tests show how to use libraries: --	* To convert a module as centralisable using functions(frame). --	* To form categories, errors and messages, their collection and their activations. --	* To form dropboxes and tableform with translatable headers. --	* To display the structure of an internal luatable, to parameter this display and to get its counts of elements. -- --	At page level, try part tests show how to use libraries: --	* To get the wikitext resulting of a module in read or edit or tests or doc1 mode. --	* In edit mode, a docbox display received arguments, errors and categories. --	* In test mode, several dropboxes display many cases of tests that anybody can read and verify. --	* These tests verify libraries and tools. -- --	Libraries dependencies: --	This try part needs the Library:centre, the Library:tools and the Library:mathroman. --

-- Running internal tests and their documentations. -- Ejecución de las pruebas internas y su documentación. -- Exécution des tests internes et de leurs documentations. -- -- Errors are needed to test their detection. Do not correct them. -- Errores se necesitan para probar su detección. No corregirlos se. -- Les erreurs sont nécessaires pour tester leur détection. Ne pas les corriger.

-- Tables des traductions des paramètres et messages dans les langues : en, es, fr. -- Tables of translations of settings and messages in the languages : en, es, fr. -- Mesas traducciones parámetros y mensajes en los idiomas : en, es, fr. -- -- i18n translations tables to extend and update in calling modules

p.i18n = {} -- translations tables known in the module

p.i18n.en = { -- Arguments linked to the main module lastname						= 'name', lastname_descr					= "Family name. Please specify to correct the sort key.", firstname						= 'firstname', firstname_descr					= "First name. Please specify to correct the sort key.", firstname2						= 'firstname', firstname2_descr				= "First name. Please specify to correct the sort key.", initiale						= 'initial', initiale_descr					= "Initial to correct the category of authors.", title							= 'title', title_descr						= "Page title, automatic.", country							= 'country', flag_of_image					= 'Flag_of_England.svg', occupation_cat					= '%1', year_number_cat					= "Year %1", birthyear						= 'birthyear', -- birthyear P569 for test p_authors_birthyear_cat birthyear_descr					= "Year of birth.", p_authors_birthyear_cat 		= "%1 births", -- en.wikisource 1802 births - 1885 deaths deathyear						= 'deathyear', -- deathyear P570 for test p_authors_deathyear_cat deathyear_descr					= "Year of death.", p_authors_deathyear_cat 		= "%1 deaths", -- en.wikisource 1802 births - 1885 deaths description						= 'description', description_descr				= "Author's description, to clarify whether the automatic description does not fit.", -- Arguments limited to multiple values rights							= 'rights', rights_descr					= "Necessary copyrights type: 70,50,mpf,ONU,non.", rights_values					= '70,50,mpf,ONU,none', region							= 'region', region_values					= 'other,china,india,century', }

p.i18n.es = { -- Argumentos relacionados con el módulo principal occupation_cat					= '%1', p_authors_deathyear_cat 		= "Autores-%1", year_number_cat					= "Año %1", -- Nombres y descripciones de los argumentos lastname						= 'nombre', lastname_descr					= "Nombre. Por favor, especifique para corregir la clave de ordenación.", firstname						= 'apellido', firstname_descr					= "Primero. Proponer para corregir la autómata.", firstname2						= 'primero', firstname2_descr				= "Primero. Proponer para corregir la autómata.", initiale						= 'inicial', initiale_descr					= "Inicial para corregir la categoría de los autores.", title							= 'titulo', title_descr						= "Título de la página, automático.", country							= 'país', flag_of_image					= 'Flag_of_Spain.svg', birthyear						= 'nacimiento', birthyear_descr					= "Año de nacimiento.", p_authors_birthyear_cat 		= "N%1", -- es.wikisource N1802 - F1885 deathyear						= 'muerte', deathyear_descr					= "Año de la muerte.", p_authors_deathyear_cat 		= "F%1", -- es.wikisource N1802 - F1885 description						= 'descripcion', description_descr				= "Descripción del autor, para aclarar si la descripción automática no encaja.", -- Argumentos limitados a múltiples valores rights							= 'derechos', rights_descr					= "Tipo de derechos de autor necesario: 70,50,mpf,ONU,non.", rights_values					= '70,50,mpf,ONU,no', region							= 'región', region_values					= "otro,china,india,siglo", --	debug							= "debug", }

p.i18n.fr = { -- Arguments liés au module principal occupation_cat					= '%1', p_authors_deathyear_cat 		= "Auteurs-%1", year_number_cat					= "Année %1", -- Noms et descriptions des arguments lastname						= 'nom', lastname_descr					= "Nom. A préciser pour corriger la clé de tri.", firstname						= 'prénom', firstname_descr					= "Prénom. A préciser pour corriger la clé de tri.", firstname2						= 'prenom', firstname2_descr				= "Prénom. A préciser pour corriger la clé de tri.", initiale						= 'initiale', initiale_descr					= "Initiale pour corriger les catégories d'ateurs.", title							= 'titre', title_descr						= "Titre de la page, automatique.", country							= 'pays', flag_of_image					= 'Flag_of_France.svg', birthyear						= 'anneeNaissance', birthyear_descr					= "Année de naissance", p_authors_birthyear_cat 		= "Naissance en %1", -- fr.wikisource Naissance en 1802 Décès en 1885 deathyear						= 'anneeDeces', deathyear_descr					= "Année de décès", p_authors_deathyear_cat 		= "Décès en %1", -- fr.wikisource Naissance en 1802 Décès en 1885 description						= 'description', description_descr				= "Description de l'auteur, à préciser si la description automatique ne convient pas", -- Arguments limités à des valeurs multiples rights							= 'droits', rights_descr					= "Type de droits d'auteur nécessaire parmi : 70,50,mpf,ONU,non.", rights_values					= '70,50,mpf,ONU,non', region							= 'région', region_values					= "autre,chine,inde,siècle", }

-- p.i18n tables end

-- Arguments table, to change in calling modules

p.args_known = { -- Table of the definitions of all known arguments at module level.

-- Arguments in order without names, with their keyword for use as other arguments. -- Arguments dans l'ordre, non nommés, avec leur keyword pour traitement comme les autres arguments.

[1] =			{need = 0, syn = 2, keyword = "mode"},

-- Special arguments to modify the fonctions and outputs of this module. -- Arguments speciaux pour modifier le fonctionnement et les sorties de ce module.

mode =			{typ = "config", need = 0, keyword = "mode"},

c =				{typ = "config", need = 0, keyword = "c"},

options =		{typ = "config", need = 0, keyword = "options"},

-- The userlang argument permits at an administrator in his own langage (errors, messages, catégories, tests) to help a wiki in any language. -- El userlang argumento permisos en administrador en su propia langage (errores, mensajes, categorías, pruebas) para ayudar a un wiki en cualquier idioma. -- L'argument userlang permet à un administrateur dans son propre langage (erreurs, messages, catégories, tests) d'aider un wiki dans ne importe quelle langue. --	userlang =		{typ = "config", need = 0, --		keyword = "userlang"},

-- The wikilang argument permits to verify in one unique wiki that a module can well adapt itself to any wiki language. -- Los argumento wikilang permisos para verificar en una wiki único que un módulo puede así adaptarse a cualquier idioma de wiki. -- L'argument wikilang permet de vérifier dans un wiki unique qu'un module peut s'adapter à n'importe quelle langue de wiki. --	wikilang =		{typ = "config", need = 0, --		keyword = "wikilang"},

--	allversions =	{typ = "config", need = 0, --		keyword = "allversions"}, knownversions = {typ = "config", need = 0, keyword = "knownversions"},

--	selectversions = {typ = "config", need = 0, --		keyword = "selectversions"}, soughtversions = {typ = "config", need = 0, keyword = "soughtversions"},

debug =			{typ = "opt", need = 0, keyword = "debug"},

category =		{typ = "ctr", need = 0, keyword = "category"},

-- All arguments have a keyword identical to the registration name, except synonyms. -- Tous les arguments ont un keyword identique au nom d'enregistrement, sauf les synonymes.

label =			{typ = "dat", need = 0, keyword = "label", prop = "label"},

country =		{typ = "dat", need = 0, keyword = "country", prop = "P27", },

sitelink =		{typ = "dat", need = 0, keyword = "sitelink", prop = "sitelink"},

itemid =		{typ = "dat", need = 2, keyword = "itemid", prop = "itemid"},

itemid2 =		{typ = "dat", need = 2, syn = 2, keyword = "itemid", prop = "itemid"},

lastname =		{typ = "dat", need = 0, keyword = "lastname"},

lastname2 =		{typ = "dat", need = 0, syn = 2, keyword = "lastname"},

firstname =		{typ = "dat", need = 0, keyword = "firstname"},

firstname2 =	{typ = "dat", need = 0, syn = 2, keyword = "firstname"},

initiale =		{typ = "dat", need = 2, keyword = "initiale"},

title =			{typ = "dat", need = 2, keyword = "title"},

birthyear =		{typ = "dat", need = 0, keyword = "birthyear", prop = "P569", format = "year"},

deathyear =		{typ = "dat", need = 0, keyword = "deathyear", prop = "P570", format = "year"},

description =	{typ = "dat", need = 0, keyword = "description", prop = "description"},

} -- p.args_known

-- Main tables of arguments. Principales tablas de argumentos. Principales tables d'arguments.

p.args_source_example = { "Hugo", "Victor", "arg3", c = ' docdef docview docsrc erron ', nom = 'Voltaire', nomm = 'Voltaire', anneenaissance = '1987', BNF = '123456789' }

-- p.args_known = nil -- Table of the definitions of all known arguments at module level. p.args_wikidata = nil -- Table of present arguments values from wikidata p.args_source = nil -- Table of source arguments from calling template, based on argument names in wiki language p.args_unknown = nil -- unknown arguments are source arguments without known arguments. p.args_import = nil -- Table of values of all imported arguments, including wikidata, based on international english keys p.args_final = nil -- Table of values of arguments after interactions between them p.args_wikidata_import = nil -- Table of the first complete import from wikidata p.args_wikidata_selected = nil -- Table of imported arguments from wikidata after any selection

p.args_test_errors = { "aaa", "bbb", "ccc", "ddd", ["prénom"] = "Arthur", options = ' docdef docview docsrc ', lastXXname = 'Voltaire', birthyear = '1999', birthyear = '2000', } -- Arguments pour auto-test

-- Arguments sources examples -- -- Errors are needed to test their detection. Do not correct them. -- Errores se necesitan para probar su detección. No corregirlos se. -- Les erreurs sont nécessaires pour tester leur détection. Ne pas les corriger.

p.WikidataEN = { label = "John Smith", deathyear = "1789",	country = "France" }

p.ArgtestEN = { "mode One", "Rimbaud 2", name = "Rimbaud", firstname = "Arnaud", rights = "70", deathyear = "MDCCCJL",	langue = "allemand,français,espagnol" }

p.ArgtestES = { nombre = "Rimbaud", apellido = "Arthur", optionsES = " ", derechoss = "70", anoMuerte = "MDCCCJL"}

p.ArgtestFR = { "mode Un", "Rimbaud 2", "Jonh", nom = "Smith", ["prénom"] = "Arnaud", anneeDeces = "1234", }

function p.trc(fn_mode, t)	local res = "" -- to put in comment to desactivate --	res = res .. " * " .. t .. tools.ta("fn_mode", fn_mode) .. tools.ta("tools.mode_name", tools.mode_name) .. tools.ta("tools.mode_options", tools.mode_options) .. tools.ta("tools.invoke_options", tools.invoke_options) res = res .. tools.ta("trc try", tools.str_vars("tools_internal_tests_title")) .. tools.ta("MR", tools.str_vars("err_J_before_end")) .. tools.ta("AT", tools.str_vars("deathyear")) return res end

function tools.options_from_mode(mode_name) -- mode_name = mode_name or (tools.args_final and tools.args_final.mode) or (tools.args_import and tools.args_import.mode) or p.mode_name or tools.mode_name or "read" mode_name = mode_name or "read" local mode_options = "" if tools.options_for_modes and tools.options_for_modes[mode_name] then mode_options = tools.options_for_modes[mode_name] end --	tools.mode_options = mode_options return mode_options, mode_name end

function tools.options_from_mode_test(t) local t = "options_from_mode_test:" or t	for md, opt in pairs(tools.options_for_modes) do t = t .. " - " .. tools.ta(md, opt) end t = t .. tools.Th .. tools.Tc("Mode") .. tools.Tc("List of options") .. tools.Tc("noerr value") .. tools.Tc("docview value") .. tools.Tc("tests value") local function test_options_from_mode(md, op1, op2, op3) local opstest = tools.options_from_mode(md) or "" return tools.Tr .. tools.Td(md) .. tools.Td(opstest) .. tools.Td(tools.option(op1, opstest)) .. tools.Td(tools.option(op2, opstest)) .. tools.Td(tools.option(op3, opstest)) end t = t .. " options_from_mode_test:" t = t .. test_options_from_mode("read", "noerr", "docview", "tests") t = t .. test_options_from_mode("edit", "noerr", "docview", "tests") t = t .. test_options_from_mode("tests", "noerr", "docview", "tests") t = t .. tools.Te return t end -- function tools.options_from_mode_test(t)

function tools.get_arg_mode(mode_name, source_key, lang, args_source) local mode_key = "mode" local args_source = args_source or tools.args_source --	tools.wikilang = lang or args_source.wikilang or tostring(mw.language.getContentLanguage.code) or "en" --	try_lang = try_lang or mw.language.getContentLanguage:getCode or "en" --	if type(centre.maini18n) == "table" and type(centre.maini18n[tools.wikilang]) == "table" then tools.wiki_translations = centre.maini18n[tools.wikilang] end if type(args_source) == "table" -- and type(args_source[source_key]) == "string" then mode_name = mode_name or args_source[source_key] or "read" else tools.mode_name = mode_name or tools.mode_name or "read" end --	local mode_name = mode_name or args_source[source_key] or "read" --	tools.mode_name = mode_name or tools.mode_name or "read" return mode_name, source_key, try_lang end

function tools.list_all_categories(t) -- list_all_categories_title t = "\n* " .. (t or " List all eventual categories of this wiki:") for key, txt in pairs(tools.user_translations) do		if tools.is_in("cat_", key) or tools.is_in("_cat", key) then txt = tools.str_vars(txt, "**", "**", "**", "**", "**", "**") t = t .. " " .. tools.ta(key, txt) end end return t end -- function tools.list_all_categories(t)

function tools.list_all_errors(t) -- list_all_errors_title t = "\n* " .. (t or " List all detectable errors of this wiki:") for key, txt in pairs(tools.user_translations) do		if tools.is_in("err_", key) or tools.is_in("_err", key) then txt = tools.str_vars(txt, "**", "**", "**", "**", "**", "**") t = t .. " " .. tools.ta(key, txt) end end return t end -- function tools.list_all_errors(t)

function p.list_all_args_sub(t, args_known) -- tools_list_all_args_title = List of all arguments, for try local t = t or " * List_all_args : " t = t or " * List_all_args : " if type(args_known) ~= "table" then args_known = tools.args_known end local descr, description = "", "" local args = mw.clone(args_known) local arglst = {} for key, elem in pairs(args) do		elem.key = tostring(key) descr = key .. "_descr" -- key for description of an argument elem.description = tools.user_translations[descr] or "**missing translation**" elem.user_lang_key = tools.user_translations[elem.key] or "**missing translation**" elem.user_lang_keyword = tools.user_translations[elem.keyword] or "**missing translation**" elem.lev_arg_txt = "" local lst_lev = {} local lev_min = 99 for arg_lev, elem_lev in pairs(args_known) do			elem_lev.levenshtein = tools.levenshtein( tools.wiki_translations[arg_lev], tools.wiki_translations[key] ) or 99 if elem_lev.levenshtein < lev_min then lev_min = elem_lev.levenshtein elem.levenshtein = elem_lev.levenshtein elem.lev_min = lev_min elem.arg_lev = arg_lev elem.lev_lang = tools.wiki_translations[arg_lev] or arg_lev end elem.arg_lev = arg_lev elem.lev_arg_txt = tools.ta("lev", tostring(elem.lev_lang) .. ":" .. tostring(elem.lev_min) .. ":" .. elem.arg_lev ) --	tools.err_add("tools_too_unnamed_arguments_err", key_N, val_src .. " LLL lev=" .. tostring(arglst[1].levenshtein) ) --	tools.cat_add("tools_module_usage_error_cat") end table.insert(arglst, elem) end -- insert in the arguments their own key table.sort(arglst, function (a, b) return (a.user_lang_key < b.user_lang_key) end ) local gr_syn, gr_need, gr_other = {}, {}, {} for i, elem in ipairs(arglst) do -- group arguments in some groups if elem.need == 1 or elem.need == 2 then table.insert(gr_need, elem) else table.insert(gr_other, elem) end end local needed = tools.small_caps_style(tools.str_vars("tools_needed_to_verify")) local function list_group( group, needed ) needed = needed or "" local t = "" for key, elem in pairs(group) do			if elem.syn then t = t .. " * '''" .. tostring(elem.user_lang_key) .. " => " .. elem.user_lang_keyword .. "''' : " .. needed .. " " .. tostring(elem.description) .. elem.lev_arg_txt else t = t .. " * '''" .. tostring(elem.user_lang_key) .. "''' : " .. needed .. " " .. tostring(elem.description) .. elem.lev_arg_txt end end return t	end t = t .. " * '''" .. tools.str_vars("tools_list_needed_args") .. "''' " .. list_group( gr_need, needed ) t = t .. " * '''" .. tools.str_vars("tools_list_all_other_args") .. "''' " .. list_group( gr_other ) return t end -- function p.list_all_args_sub(t, args_known) -- tools_list_all_args_title for try

function p.list_all_args_main(t, args_known) -- tools_list_all_args_title = List of all arguments for main local t = t or "\n* List_all_args : " if type(args_known) ~= "table" then args_known = tools.args_known end t = t .. tools.ta("args N", #args_known ) local descr, description = "", "" local args = mw.clone(args_known) local arglst = {} for key, elem in pairs(args) do		elem.key = tostring(key) descr = key .. "_descr" -- key for description of an argument elem.description = tools.user_translations[descr] or "**missing translation**" elem.user_lang_key = tools.user_translations[elem.key] or "**missing translation**" elem.user_lang_keyword = tools.user_translations[elem.keyword] or "**missing translation**" --	elem.base_id = elem.base_id --	elem.base_base = elem.base_base --	elem.not_type = elem.not_type table.insert(arglst, elem) end -- insert in the arguments their own key table.sort(arglst, function (a, b) return (a.user_lang_key < b.user_lang_key) end ) -- alphabetic sort of translated arguments local gr_sys, gr_config, gr_need, gr_other, gr_authority = {}, {}, {}, {}, {} for i, elem in ipairs(arglst) do -- group arguments in some groups if elem.need == 1 or elem.need == 2 then table.insert(gr_need, elem) elseif elem.typ == "sys" then table.insert(gr_sys, elem) elseif elem.typ == "config" then table.insert(gr_config, elem) elseif elem.base_base then table.insert(gr_authority, elem) else table.insert(gr_other, elem) end end local needed = tools.small_caps_style(tools.str_vars("tools_needed_to_verify")) local function list_group( group, needed ) needed = needed or "" local t = "" for key, elem in pairs(group or {}) do			if elem.syn then t = t .. " * '''" .. tostring(elem.user_lang_key) .. " => " .. elem.user_lang_keyword .. "''' : " .. needed .. " " .. tostring(elem.description) -- .. elem.lev_arg_txt else t = t .. " * '''" .. tostring(elem.user_lang_key) .. "''' : " .. needed .. " " .. tostring(elem.description) end end return t	end t = t .. " * '''" .. tools.str_vars("tools_list_needed_args") .. "''' " .. list_group( gr_need, needed ) t = t .. " * '''" .. tools.str_vars("tools_list_all_other_args") .. "''' " .. list_group( gr_other ) t = t .. " * '''" .. tools.str_vars("list_all_authorities") .. "''' " .. list_group( gr_authority ) t = t .. " * '''" .. tools.str_vars("tools_list_all_config_arguments") .. "''' " .. list_group( gr_config ) t = t .. " * '''" .. tools.str_vars("tools_list_all_system_arguments") .. "''' " .. list_group( gr_sys ) return t end -- function p.list_all_args_main(t, args_known) -- tools_list_all_args_title for main

-- Display the documentation in an infobox, similar to edit-boxs -- Affichage de documentation dans un cadre (box), semblable aux boites d'edition function p.formDocBox(args_final) -- tools.options = " : docdata docmin docdef docmax docline docsrc docview docafter docnotice docsrc" -- for documentation -- tools.options = " erron noerr nobox " -- without normal result -- tools.options = " debug tests en es fr " -- for debug or enforce language if type(args_final) ~= "table" then args_final = tools.args_final end -- optional arguments local err = tools.verify_args_tables(tools.args_known, tools.args_source) if err then return err end res = "" --	res = res .. "\n--" res = res .. tools.error_color("" .. tools.str_vars("tools_delete_docbox_msg") .. "") local gettitle = mw.getCurrentFrame:getTitle -- get the mainmodule title if type(package.loaded[gettitle]) == "table" then -- If #invoke has already loaded the main module in package.loaded else end tools.formDocBox_dropdown_title = tools.str_vars("tools_support_desk_title") .. " - " .. tools.report_main_discreet .. " - " .. tools.form_i18n_counts(centre.maini18n, "tools_maini18n_languages_list") -- select = "alltestsview" -- Deprecated, to view all boxes. -- select = "allwaysview" -- To allways display one view. -- select = "enforcerun" -- To debug one box with INTERNAL ERROR. res = res .. tools.dropdownfunc("allwaysview", tools.formDocBox_dropdown_title, tools.support_desk_report ) if tools.docolor then res = res .. "\n:.\n: " .. tools.sources_of_datas_colors end if tools.option("debug")		then res = res .. "\n*" .. tools.ta("tools.catView", tools.catView) .. tools.ta("tools.invoke_options", tools.invoke_options) .. tools.ta("tools.mode_options", tools.mode_options) end if tools.option("docdata")		then res = res .. "\n*" .. tools.generDoc(" docdef docline ", tools.args_wikidata, "Wikidata") end if tools.option("docview")		then res = res .. "\n*" .. tools.generDoc("", args_final, "Arguments") end if not tools.option("noerr")	then res = res .. "\n*" .. tools.errors_lister end res = res .. "\n* " .. tools.categories_lister(":") res = ' ' .. res .. ' '	return res end -- function p.formDocBox(args_final)

function p.normal_box(args_final, title) local res = "" local warning_versions = tools.report_main_short -- tools.warning_short if type(args_final) ~= "table" then args_final = tools.args_final end if not title then title = args_final.title end if not title then title = "TITLE" end res = res .. " " .. title .. " " .. tools.report_main_discreet .. ""	local flag_of_image = tools.str_vars("flag_of_image") if type(flag_of_image) == "string" then -- and image ~= "" flag_of_image = ' ' else flag_of_image = " " end res = res .. flag_of_image function arglingual(key) local t = "" if key and tools and tools.user_translations and tools.user_translations[key] then t = t .. tools.tam(tools.user_translations[key], args_final[key] ) else t = ", " end return t	end res = res .. arglingual("label") res = res .. arglingual("description") res = res .. arglingual("occupation") res = res .. arglingual("firstname") res = res .. arglingual("lastname") res = res .. arglingual("birthyear") res = res .. arglingual("deathyear") tools.nowyear = tonumber(os.date("%Y") ) -- now_date = os.date("%Y-%m-%d %H:%M:%S") --	local i2r = mathroman.int2roman(tools.nowyear) --	local r2i = mathroman.roman2int(i2r) --	local r2r = mathroman.int2roman(r2i) res = res .. tools.ta("int2roman", i2r) .. tools.ta("roman2int", r2i) .. tools.ta("int2roman", r2r) res = res .. " " .. tools.maini18n_languages_list -- List available translations languages res = '' .. res .. ' '	return res end -- function p.normal_box(args_final, title)

-- Normal result of the module -- Resultado normal del módulo -- Résultat normal du module function p.form_result(args_final) if type(args_final) ~= "table" then args_final = tools.args_final end -- optional arguments local res = "" --	res = res .. tools.dropdownfunc(1, "tools_cat_add_test_title", tools.cat_add_test) tools.gener_categories(args_final) -- Produire les catégories sans les activer if tools.option("docview") then res = res .. "\n--" res = res .. p.formDocBox(args_final) end if not tools.option("nobox") then res = res .. p.normal_box(args_final) end -- Display categories. Afficher les catégories. if ( not tools.option("nobox") ) and ( tools.option("catview") or tools.option(":") ) then res = res .. tools.categories_lister(":") end tools.time3 = os.clock if tools.option("tests") or (tools.args_final.mode == "tests") then res = res .. p.testsview("allwaysview") end tools.time4 = os.clock if tools.option("tests") or (tools.args_final.mode == "tests") then res = res .. tools.running_times(true, "") end return res end -- function p.form_result(args_final)

function p.form_tests_init(res, args_source) -- Special init for the test mode if type(res) ~= "string" then res = "\n* Mode test : " end if type(args_source) ~= "table" then args_source = {} end if p.i18n and p.i18n.en then p.i18n.en.error_i18n_wanted_to_test_missing_translation = 'English error i18n wanted for tests missing translation' end if p.i18n and p.i18n.es then p.i18n.es.error_i18n_deseada_para_probar_traduccion_faltan = 'Espagnol error i18n deseada para probar traducción faltan' end if p.i18n and p.i18n.fr then p.i18n.fr.error_i18n_voulue_pour_test_de_traduction_manquante = 'Français erreur i18n voulue pour tests de traduction manquante' end --	if not args_source.userlang then args_source.userlang = "en" end --	if not args_source.wikilang then args_source.wikilang = "es" end if not args_source.name then args_source.name = "Jack Smith" end if not args_source.nom then args_source.nom = "Victor Hugo" end if not args_source.region then args_source.region = "india" end if not args_source["région"] then args_source["région"] = "chine" end if not args_source.description then args_source.description = "Victor Hugo est très connu." end if not args_source.langue then args_source.langue = "français,japonais" end if not args_source.occupation then args_source.occupation = "Académiciens,Personnalités politiques" end tools.args_source = args_source return res end -- function p.form_tests_init(res, args_source)

-- Interact parameters in international args_final function tools.interact_args_final(args_import) return p.interact_args_final(args_import) end function p.interact_args_final(args_import) -- args_final = p.interact_args_final(args_import) if type(args_import) ~= "table" then args_import = tools.args_import end local args_final = mw.clone(args_import)

local a = args_import local i = {} -- interact --	t = "\n* begin :" .. tools.ta("initiale", a.initiale) .. tools.ta("firstname", a.firstname) .. tools.ta("lastname", a.lastname) .. tools.ta("title", a.title) --	local tit = nil if not a.title then -- If title is undefined, enforce it. if a.lastname and a.firstname then tit = a.firstname .. " " .. a.lastname end i.title = a.label or tit or a.sitelink or a.lastname or tools.module_name end --	if not a.initiale then -- If initiale is undefined, enforce it. -- if absent, default initiale come from the last word of title local title = a.title or i.title if title then local tab = mw.text.split(title, '%s') -- table of words local max = table.maxn( tab ) i.initiale = tab[max] -- select the last word i.initiale = string.sub( i.initiale, 1, 1 ) -- select the first letter i.initiale = string.upper( i.initiale or "" ) end end --	-- if absent, synonym of basic arguments, syn = 2 if not a.firstname then i.firstname = (i.firstname2 or a.firstname2) end if not a.lastname then i.lastname = (i.lastname2 or a.lastname2) end if not a.firstname2 then i.firstname2 = (i.firstname or a.firstname) end if not a.lastname2 then i.lastname2 = (i.lastname or a.lastname) end --	if a.birth and not a.birthyear then local tt, err = tools.date_to_part(a.birth, tools.str_vars("tools_date_to_part_format"), "yyyy") if tt then i.birthyear = tt else tools.err_add(err, tools.str_vars("birthyear"), "yyyy") tools.cat_add("tools_date_to_part_call_cat") end end --	if a.userlang then --		i.userlang = a.userlang --		tools.init_user_lang(a.userlang, tools.wiki_lang) end if a.wikilang then --		i.wikilang = a.wikilang --		tools.init_user_lang(tools.user_lang, a.wikilang) end --	-- memorize interactions in tools.args_final and show errors or messages local n = 0 for key, val in pairs(i) do		local args_kwn = tools.args_known[key] if args_kwn then args_final[key] = val -- = i[key] args_kwn.src = "inter" args_kwn.trk = args_kwn.trk.." i"			n = n + 1 if (args_kwn.need == 2) and not a[key] then -- -- need=2 necessary from argument or module interaction tools.msg_add("tools_auto_val_warning_msg", tools.user_translations[key], val) end else tools.err_add("tools_auto_val_unknown_err", tools.wiki_translations[key], val) --	tools.err_add("tools_unknown_auto_arg_err", tools.wiki_translations[key], val) end end if tools.args_known and tools.args_known.title then tools.args_known.title.trk = (tools.args_known.title.trk or "").."i="..n end tools.args_final = args_final return args_final, t end -- function p.interact_args_final(args_import)

-- Interfaces, alias and functions to templates -- Interfaces, alias y funciones para modelos -- Interfaces, allias et fonctions pour les modèles

p.options_for_modes = { -- default init normal	= " noerr ", read	= " noerr ", edit	= " : catview docview docdef docline docsrc docdata ", doc1	= " nobox noerr nocat ", tests	= " : catview docview docdef docline docsrc docdata tests ", -- Option nocat means "Do not categorize and do not show categories." }

function p.init(frame, mode_name, args_known, options_for_modes, itemid) return centre.init(frame, args_known, mode_name, options_for_modes, itemid) end

function p.normal(frame) return p.read(frame) end -- Deprecated alias function function p.read(frame) -- The read function imports, translates and verifies arguments. -- It generates read text and uses options to include edit or tests local res, t = "", "" --	res = res .. ' ' -- t = t .. tools.form_i18n_counts centre.init(frame, p.args_known, "read", p.options_for_modes, itemid) --	res = res .. tools.tracki18n("read mode") tools.init_wiki_user_lang tools.args_final = p.interact_args_final(tools.args_import) -- Interactions between arguments tools.tracki18n("read:interact_args_final", tools) tools.time3 = os.clock centre.trcPVG(" * read : ") -- track for tools.bindmodules_verif --	res = res .. tools.dropdownfunc("versions_manage_report_title", "versions_manage_report_title", tools.versions_manage_report) -- Report some aspects of the versions management tools.tracki18n("read before form_result", try) res = res .. p.form_result --	tools.trac_lang("read args_final", tools.args_final) -- --	res = res .. " read end : " .. tools.luatablecount("args_source") tools.tracki18n("read end", try) --	res = res .. tools.tracki18n_all return res end -- function p.read(frame)

-- function p.doc(frame) return p.edit(frame) end -- Deprecated alias function function p.edit(frame) -- The edit function imports, translates and verifies arguments. -- It generates edit panel and edit text. local res = "", "" centre.init(frame, p.args_known, "edit", p.options_for_modes) --, "Q535" --	res = res .. mathroman.example -- "mathroman:read ") --	local ok, t = mathroman.TestsCases_recursive( "mathroman", mathroman.TestsCasesGroup ) -- Run a group of tests and returns one string. --	res = res .. t --	res = res .. mathroman.example -- "mathroman:read ") --	local ok, t = mathroman.TestsCases_recursive( "mathroman", mathroman.TestsGroups, 1 ) -- Run N groups of tests and returns one string. --	res = res .. t --	res = res .. tools.tracki18n("edit mode") tools.init_wiki_user_lang tools.init_tools -- frame, p.options_for_modes)	tools.args_final = p.interact_args_final(tools.args_import) -- Interactions between argumensts	tools.init_wiki_user_lang	tools.tracki18n("edit:interact_args_final")	tools.time3 = os.clock	centre.trcPVG(" * doc : ") -- track for tools.bindmodules_verif	tools.tracki18n("edit:before form_result") --	res = res .. tools.tracki18n("before edit form_result")	res = res .. p.form_result(tools.args_final)	tools.tracki18n("edit end") --	res = res .. tools.tracki18n_all	return res end -- function p.edit(frame)

function p.doc1(frame) return p.doc(frame) end -- Deprecated alias function function p.doc(frame) -- Form as documentation, a test in a dropbox. local res, t = "", "" centre.init(frame, p.args_known, "doc", p.options_for_modes) --, "Q535" local dockey = tools.args_config.dockey or tools.args_source[1] local itemid = tools.args_config.itemid or tools.args_config.id or tools.args_source[2] --	res = res .. --	tools.args_config_init -- Get tools.args_config tools.change_itemid -- "Q41568" tools.args_final = p.interact_args_final(tools.args_import) -- Interactions between argumensts tools.time3 = os.clock if dockey then res = res .. p.testsview(dockey, itemid) return res else return "" end end -- function p.doc(frame)

function tools.test_section(select, section) -- select = "alltestsview" -- Deprecated, to view all boxes. -- select = "allwaysview" -- To allways display one view. -- select = "enforcerun" -- To debug one box with INTERNAL ERROR. local res = "" if select == "allwaysview" then res = res .. " " .. tools.str_vars(section) .. " "		res = res .. tools.report_main_short -- "tools.report_main_short is missing." end return res end -- function tools.test_section(select, section)

function p.testsview(select, itemid) -- Form a documentation of one dropbox or all. -- select = "alltestsview" -- Deprecated, to view all boxes. -- select = "allwaysview" -- To allways display one view. -- select = "enforcerun" -- To debug one box with INTERNAL ERROR. local res, t = "", "" --	res = res .. tools.test_section(select, "tools_page_tests_h3_title") --	tools.support_desk_title = tools.report_main_discreet .. " - " .. tools.str_vars("tools_support_desk_title") -- tools.warning_short res = res .. tools.dropdownfunc(select, "tools_support_desk_title", tools.support_desk_report ) res = res .. tools.dropdownfunc(select, "tools_used_options_title", tools.used_options_list ) res = res .. tools.dropdownfunc(select, "tools_list_all_args_title", p.list_all_args_main) --	res = res .. tools.dropdownfunc(select, "tools_luatables_counts_title", tools.luatables_counts) res = res .. tools.dropdownfunc(select, "tools_spaces_page_names_title", tools.spaces_page_names_test) res = res .. tools.dropdownfunc(select, "tools_table_args_source_title", tools.luatable_lister, tools.args_source, "tools.args_source") res = res .. tools.dropdownfunc(select, "tools_table_args_unknown_title", tools.luatable_lister, tools.args_unknown, "tools.args_unknown",		{ boxstyle = "boxstyle", image = "Gtk-dialog-info.svg"} ) -- "" res = res .. tools.dropdownfunc(select, "tools_args_known_structure_title", tools.args_known_structure) --	res = res .. tools.test_section(select, "tools_internal_tests_h3_title") --	res = res .. tools.dropdownfunc(select, "tools_list_all_categories_title", tools.list_all_categories) res = res .. tools.dropdownfunc(select, "tools_list_all_errors_title", tools.list_all_errors) res = res .. tools.dropdownfunc(select, "tools_transdiff_report_title", tools.transdiff_report) res = res .. tools.dropdownfunc(select, "tools_options_from_mode_title", tools.options_from_mode_test,		{ boxstyle = "boxstyle", width = "80%", text_color="green", alignT="left", alignB="center", margin_all="3em",		background_color="yellow", border_color="red", height="2em", image="Gtk-dialog-info.svg"} ) -- "" res = res .. tools.dropdownfunc(select, "tools_options_from_args_title", tools.options_from_args_test) --	-- versions management --	res = res .. tools.dropdownfunc(select, "tools_unused_modules_tests_title", centre.select_modules_test ) --	res = res .. tools.dropdownfunc(select, "tools_verif_bindmodules_report", tools.bindmodules_report ) -- binding of the modules --	tools.report_bind_verif_modules_details = tools.bindmodules_report -- Report all modules installation res = res .. tools.dropdownfunc(select, "tools_bindmodules_report_title", tools.report_bind_verif_modules_details ) res = res .. tools.dropdownfunc(select, "tools_missing_translations_title", tools.verifyinit, centre.maini18n) -- tools.i18n --	res = res .. tools.dropdownfunc(select, "tools_versionsmanagement_report", tools.versions_management_report ) --	res = res .. tools.dropdownfunc(select, "tools_similar_args_test_title", tools.similar_args_test) res = res .. tools.dropdownfunc(select, "tools_levenshtein_test_title", tools.levenshtein_test) res = res .. tools.dropdownfunc(select, "tools_cat_add_test_title", tools.cat_add_test) res = res .. tools.dropdownfunc(select, "tools_multiple_values_tests_title", tools.multiple_values_tests) res = res .. tools.dropdownfunc(select, "tools_multiple_selection_test_title", tools.multiple_selection_test) --	res = res .. tools.dropdownfunc(select, "tools_mixed_translations_title", tools.i18n_lister) res = res .. tools.dropdownfunc(select, "tools_wikidata_arbitrary_test_title", tools.tools_wikidata_arbitrary_test,		{ boxstyle = "boxstyle", image = "Gtk-dialog-info.svg"} ) -- "" res = res .. tools.dropdownfunc(select, "mathroman_rom2dig_testtitle", mathroman.roman_to_digital_test) res = res .. tools.dropdownfunc(select, "mathroman_dig2rom_testtitle", mathroman.digital_to_roman_test) res = res .. tools.dropdownfunc(select, "tools_date_to_part_test_title", tools.date_to_part_test) res = res .. tools.dropdownfunc(select, "tools_time_format_test_title", tools.time_format_test) res = res .. tools.dropdownfunc(select, "tools_wikidata_time_details", tools.luatable_lister, tools.WikidataTimeDetails, "tools.WikidataTimeDetails.claims." .. (tools.TimeName or "Pxxx") ) res = res .. tools.dropdownfunc(select, "tools_tasks_table_report_short", ( tools.tasks_table_report_short or "tasks_table_report_short missing") ) -- "enforcerun" res = res .. tools.dropdownfunc(select, "tools_tasks_table_report_title", ( tools.tasks_table_report_full or "tasks_table_report_full missing") ) -- "enforcerun" -- --	res = res .. tools.dropdownfunc(select, "tools_versions_management_title", centre.bindmodules_start ) -- "enforcerun" res = res .. tools.dropdownfunc(select, "tools_bindmodules_test_title", tools.bindmodules_test ) -- "enforcerun" --	res = res .. tools.dropdownfunc(select, "tools_dummy_languages_title", tools.dummy_languages) res = res .. tools.dropdownfunc(select, "tools_test_luatable_lister_title", tools.luatable_lister, tools.tablim, "tools.tablim", {} ) res = res .. tools.dropdownfunc(select, "tools_luatable_tests_limits_title", tools.luatable_lister, tools.tablim, "tools.tablim",		{ boxstyle = "boxstyle", levelmaxi = 2, max_n = 2, exclude1 = "hou" } ) --, {width = "88%", text_color = "blue"} res = res .. tools.dropdownfunc(select, "tools_documentations_changes_report", tools.documentations_changes_report ) res = res .. tools.dropdownfunc("enforcerun", "mathroman_recursive_TestsCases_title", mathroman.TestsCases_recursive_tests ) return res end -- function p.testsview(select)

function p.tests(frame) local res = "" centre.init(frame, p.args_known, "tests", p.options_for_modes) --, "Q535" --	local res = mathroman.example -- "mathroman:tests ") --	local ok, t = mathroman.TestsCases_recursive( "mathroman", mathroman.TestsGroups ) -- Run a group of tests and returns one string. --	res = res .. ok .. t	tools.tracki18n("tests mode")	tools.init_wiki_user_lang	tools.args_final = p.interact_args_final(tools.args_import) -- Interactions between arguments	p.form_tests_init	tools.errors_list = {} -- Table to collect errors and messages	tools.categories_list = {} -- init the collect of categories --	tools.categories_init -- initialize the category list	tools.init_tools -- frame, p.options_for_modes) tools.args_final = p.interact_args_final(tools.args_import) -- Interactions between argumensts tools.mode_name = tools.args_final.mode or tools.args_import.mode or tools.args_config.mode or "tests" tools.mode_options = tools.options_from_mode(tools.mode_name) tools.tracki18n("tests:options_from_mode") tools.init_wiki_user_lang tools.tracki18n("tests:init_wiki_user_lang") tools.time3 = os.clock tools.main_versions = tools.main_versions or { versionName = "versionName", versionNumber = "0.0", } local res_function = " * " .. tools.main_versions.versionName .. ":" .. tools.mode_name .. ":" .. tools.wiki_lang .. " "	-- If there is no MainModule, THIS version of Central is used alone if not tools.main_versions then tools.main_versions = tools.versions or p.versions end local res_function = " \n" .. (tools.main_versions.versionName or "MainModule_t") .. " " .. (tools.main_versions.versionNumber or "0.0_t") .. ":" .. tools.mode_name .. ":" .. tools.wiki_lang .. " "	res = res .. res_function .. " Begin:" .. " "	local loaded_pack, loaded_txt, modu = centre.get_loaded_modules tools.loaded_modules_track = "p.tests : " .. loaded_txt centre.trcPVG(" * tests form_result : ") -- track for tools.bindmodules_verif res = res .. p.form_result -- Generate wikitext, categories, and others res = res .. res_function .. " End." .. " "	tools.tracki18n("tests:end") return res end -- function p.tests(frame)

return p