User:Rical/Central modules


 * This draft page and its talk must be in a better place, where you can copy it (in one or some pages).


 * This task T135845, seems enough advanced to share it.
 * That means enough defined, explicit and debug to permit at any developer to take a part of it and to work on it in coordination with others.
 * Then we can/must choose how to cooperate.
 * That means we can/must choose pages to discuss our works and changes.
 * This process also is a long term task for many central modules.
 * As a first step, on 2016-06-02, the initial developper creates this draft page to begin this process, and leave to others to take their parts of it.
 * At time, the initial developer Rical  works on   MW TestsCases.
 * Any developer can already.


 * Some related pages:
 * Draft documentation: Central modules.
 * Central libraries: Module:Central.
 * Simple examples of uses: Module:Central/Documentation
 * Full example: Victor_Hugo.

Task: Convert any module as central or centralisable

 * Scribunto permit to convert any module as central, or even centralisable before an efficient central repository exists.


 * That permits to use central modules in many languages, in many projects, even in many small wikis without enought helpers.


 * That provides an easier and more efficient peer review.
 * That enhanses the mean abilities of modules for a same global effort.
 * That reduces the duplication of effort for a same result.
 * That increases the mean availability of coders and helpers.


 * A central module can help users and helpers, in their own languages and the wiki languages, by errors, warnings, categories, reports and tests.


 * Example: display a category in the helper language and link to the category in wiki language.
 * Example: for each project and each language, choose detailed categories names or only categories "users modules errors" and "internal modules errors".


 * A central module must be very stable, understandable and strong against small usual misuses.
 * For that it permits managements of arguments, wikidata, errors, messages and modules versions.


 * The draft proposition for this task:task T135845 is in fr.wikisource Central modules.

What is a central module?
From actual live developments we can at least say:
 * It is able to use translations, in some or many languages, of its arguments names, catégories names, and errors messages that it produces.
 * Translations are in a /I18N submodule to not disturb it, except for minimal internal translations.
 * It is able to automaticly use any available translated languages.
 * It is able to use the local wiki language and the user language at the same time.
 * It can use a version management ability, at local and at central repository.
 * It can work at local like at central repository, for local tests without disturb central version, or for uses waiting central availability.
 * It is stable and contains necessary MW tests cases.
 * It is protected against too easy edit for a better stability.
 * If sought, it is able to help readers, helpers and developers in  mode, showing internal documentation, reports and tests of complex basic functions.
 * These abilities come from one or some scribunto libraries, depending of the complexity of the module an its submomules.
 * Its uses of central libraries must be very simple in any simple or complex modules.
 * Functions verify parameters types and replace missing parameters by default values.
 * Functions are strong enough to accept little calling faults when non ambiguous.

How to support central modules?

 * Like modules in talk pages? And like phab tasks? And sharing tasks?
 * Use a common sharing page: Talk:Central modules?
 * How to name a Lua developer? Developer? Coder? Lua coder?
 * Use the versions management, in tests places or in final places.


 * The rights of Global interface editors could give global ability.
 * To ask in Requests for other global permissions could give global ability.
 * The rights of Interface editors could give global ability only from local login.


 * Waiting an efficient central repository, some bots could repeat validated centralisable modules in some places where active coders experiment them.

Easier, faster and stable development

 * Keep in one module the example of central module, and its libraries until they will be stable:


 * to easy change groups of functions in libraries, or in object,
 * to easy coordinate changes in several parts of the code,
 * to easy install and update all central libraries in a new place where use the code or where change it.


 * In development phase, to show the abilities of central modules, keep some languages, errors, messages, categories...


 * Alias of functions insure the continuity of service across change in sub-module, then in calling module, then in sub-module to delete the alias.


 * In development phase, when many functions or even some libraries are not well defined, put them in the same module and re-distribute functions and parameters.


 * To try evolutions in a module or restructuration of some ones, use the versions management.

Short story of development

 * The previous templates was based on the oldest LISP programmation langage style.
 * On 2012-04-16, Mediawiki offered Lua in Scribunto  . This language is very simple to use, but very complete, all in objects, with the "meta" table to replace the words "inherited" or "class" (even sub-threads out of Mediawiki).
 * Of course then, many users began to convert each old templates in new Lua modules which was simple due to the already existing LISP-like templates.
 * But the previous French Template:Author was already a complex template, needing 6 sub-templates, see "liés".
 * On 2013-01-18, i18n tables was used to translate errors.
 * On 2013-01-25, in the Module:Author, the generic management of arguments, and the table to group their definitions, came from its large number of arguments, see "args_known".
 * On 2013-03-12, the Module:ControlArgs groups complex translations and management of arguments to support other modules to become centralisable.
 * On 2015-02-25, the Module:Author3 include the versions management for a better stability.
 * On 2016-01-30, the Module:Central convert modules in libraries.
 * On 2016-05-20, task T135845: a task propose to "Convert any module as centralizable".

State of development

 * In phase of development, some errors are needed to show them in some reports and to choose their better places.
 * Do not correct these errors, or even activate some ones.


 * Central translatable libraries are:  and.
 * Each translatable library contains internal translations in english, french and spanish.
 * The library  is a very small exemple of translatable library, only detects errors and has no mode nor options.


 * The  library binds modules in sought versions management and easy translates parametrable strings.
 * The  library support simple to complex modules.
 * Their supports are to translate, collect, manage and display views.


 * Translate is for arguments names from template, for images and texts on page and for categories and errors.
 * Waiting final true libraries, for local or central developments, the libraries and their translations can come from  and.
 * Where to place the i18n translations out of the final libraries to not disturb it when translations change?
 * Proposition: put the  library in.


 * The arguments management collects and keeps strings to translate and their parameters. Later also display lists of translated strings in right places (warning, errors, categories, categorize).
 * Manage arguments means also coming from wikidata, help for better argument name orthograph, auto correction of arguments names when non ambiguous, alias arguments names, verify if value is in the parametrable list of values, needed but absent, warning when twice defined, arguments descriptions.


 * The versions management  adequate versions of submodules to test, following known and sought versions, like.
 * This versions management reports versions used, errors, missing or replaced by normal ones... then helpers can better select and understand what happens.
 * Any helper of main module can select versions of its submodules from internal arguments or from template arguments.


 * Central libraries permit to easy generates categories, single or in group, translatable dropboxs, tables views, tests views...

Unavailable or sought abilities
on 2016-05-20


 * Central libraries are NOT stable and need to contain necessary MW tests cases.
 * For MW tests cases, we can also display the results in tableviews, like for many other tests.
 * Auto correction of arguments names when they are non ambiguous (see available levenstein).
 * Waiting the tasks debug, config arguments simulate informations depending of blocking tasks.
 * In the list of available languages, when it is large, we could display first a list of "near languages", like, defined in i18n translations for each language. Others are in alphabetic order of languages codes. See tools.maini18n_languages_list which returns "This module can translate 171 texts in 3 languages: English(en=English), español(es=Spanish), français(fr=French),".
 * For MW tests cases of the logic of centre.bindmodules, replace existing modules by a simulation of package.loaded.
 * Make a testviewer based on MW tests cases.
 * Main options for dropbox (title, content, image) also could be in the style options.
 * Tests of multiple values arguments must be explicit.

 States table of known tasks * =  ( detected state ) Used colors: , Resolved =  task already completed   , args =  task replaced by arguments or by the module   , other =  other tasks 
 * TestsCases mathroman: int2roman(2013) = MMXIII, roman2int(MMXVI) = 2016,
 * TestsCases, recursive level =  1  n/N = 13/13  , group =  mathroman_groups_1 
 * n/N = 1/13, countonly=13, sub_count=0,  name = mathroman_groups_1_int2roman_1(, i =  -11  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/13, countonly=14, sub_count=0,  name = mathroman_groups_1_int2roman_2(, i =  0  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/13, countonly=15, sub_count=0,  name = mathroman_groups_1_int2roman_3(, i =  12  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/13, countonly=16, sub_count=0,  name = mathroman_groups_1_int2roman_4(, i =  17  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 5/13, countonly=17, sub_count=0,  name = mathroman_groups_1_int2roman_5(, i =  18  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 6/13, countonly=18, sub_count=0,  name = mathroman_groups_1_int2roman_6(, i =  19  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 7/13, countonly=19, sub_count=0,  name = mathroman_groups_1_int2roman_7(, i =  111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 8/13, countonly=20, sub_count=0,  name = mathroman_groups_1_int2roman_8(, i =  444  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 9/13, countonly=21, sub_count=0,  name = mathroman_groups_1_int2roman_9(, i =  555  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 10/13, countonly=22, sub_count=0,  name = mathroman_groups_1_int2roman_10(, i =  777  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 11/13, countonly=23, sub_count=0,  name = mathroman_groups_1_int2roman_11(, i =  1111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 12/13, countonly=24, sub_count=0,  name = mathroman_groups_1_int2roman_12(, i =  4999  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 13/13, countonly=25, sub_count=0,  name = mathroman_groups_1_int2roman_13(, i =  5000  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * TestsCases, recursive level =  1  n/N = 8/32  , group =  mathroman_groups_14 
 * n/N = 1/32, countonly=32, sub_count=0,  name = mathroman_groups_14_roman2int_1(, rm =  -X  ),   , testcode =  nil   , argserrs =  
 * n/N = 2/32, countonly=33, sub_count=0,  name = mathroman_groups_14_roman2int_2(, rm =  0  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/32, countonly=34, sub_count=0,  name = mathroman_groups_14_roman2int_3(, rm =    ),   , testcode =  nil   , argserrs =  
 * n/N = 4/32, countonly=35, sub_count=0,  name = mathroman_groups_14_roman2int_4(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/32, countonly=36, sub_count=0,  name = mathroman_groups_14_roman2int_5(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/32, countonly=37, sub_count=0,  name = mathroman_groups_14_roman2int_6(, rm =  XJI  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/32, countonly=38, sub_count=0,  name = mathroman_groups_14_roman2int_7(, rm =  XIA  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/32, countonly=39, sub_count=0,  name = mathroman_groups_14_roman2int_8(, rm =  VLD  ),   , testcode =  nil   , argserrs =  
 * n/N = 9/32, countonly=40, sub_count=0,  name = mathroman_groups_14_roman2int_9(, rm =  IXC  ),   , testcode =  nil   , argserrs =  
 * n/N = 10/32, countonly=41, sub_count=0,  name = mathroman_groups_14_roman2int_10(, rm =  MMMMCMXCIX  ),   , testcode =  nil   , argserrs =  
 * n/N = 11/32, countonly=42, sub_count=0,  name = mathroman_groups_14_roman2int_11(, rm =  MMMMM  ),   , testcode =  nil   , argserrs =  
 * n/N = 12/32, countonly=43, sub_count=0,  name = mathroman_groups_14_roman2int_12(, rm =  MMMMMYJXC  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  2  n/N = 8/8  , group =  mathroman_groups_14_roman_group_13 
 * n/N = 1/8, countonly=8, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_1(, i =  1  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/8, countonly=9, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_2(, i =  3  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/8, countonly=10, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_3(, i =  6  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/8, countonly=11, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_4(, rm =  IV  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/8, countonly=12, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_5(, rm =  V  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/8, countonly=13, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_6(, rm =  III  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/8, countonly=14, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_7(, rm =  VI  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/8, countonly=15, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_8(, rm =  I  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  1  n/N = 4/4  , group =  mathroman_tests_recursive_9 
 * n/N = 1/4, countonly=4, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_1(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/4, countonly=6, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_3(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  


 * Tasks to open?
 * T00000: Add module and library types in scribunto ?
 * T00001: Sorted tableview do not sort date-time, in template and in module.
 * T00002: In a dropbox after \n* the content is after the box. Better define the case. Insert "\n--" before correct that. Try that out of fr.wikisource, in test2 or mediawiki...
 * T00003: bindI18N after bindmodules to protect sought translatios against un-sought ones.
 * T00011: Sorted tableview do not sort date-time
 * T00012: In a dropbox after \n* the content is not inside the box. Better define the case. Insert "\n--" before to correct that.
 * T00013: Insert and mask structured datas and errors in resulting wikitext for bots. In xml or json or template style.
 * T00014: Display changes in test_init arguments, in a dropbox.
 * T00015: Convert some groups of functions as new objects types: tableview with its headers and options, luatable and its luatablecount, dropbox and dropdownfunc and their options, get{} output from centre.get_module_and_time for modules and libraries.

Blocked tasks

 * task T41610: Scribunto should support global module invocations
 * task T127354: Consider helping some smaller Wikipedias' communities
 * task T122086: RFC: Sharing templates and modules between wikis - poor man's version (investigation)
 * task T89598: Convert Template:Authority_control to Lua and use Wikidata

Blocking tasks

 * Some blocking tasks are detected by the module itself.

 Mediawiki recursive TestsCases
 * TestsCases mathroman: int2roman(2013) = MMXIII, roman2int(MMXVI) = 2016,
 * TestsCases, recursive level =  1  n/N = 13/13  , group =  mathroman_groups_1 
 * n/N = 1/13, countonly=13, sub_count=0,  name = mathroman_groups_1_int2roman_1(, i =  -11  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/13, countonly=14, sub_count=0,  name = mathroman_groups_1_int2roman_2(, i =  0  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/13, countonly=15, sub_count=0,  name = mathroman_groups_1_int2roman_3(, i =  12  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/13, countonly=16, sub_count=0,  name = mathroman_groups_1_int2roman_4(, i =  17  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 5/13, countonly=17, sub_count=0,  name = mathroman_groups_1_int2roman_5(, i =  18  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 6/13, countonly=18, sub_count=0,  name = mathroman_groups_1_int2roman_6(, i =  19  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 7/13, countonly=19, sub_count=0,  name = mathroman_groups_1_int2roman_7(, i =  111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 8/13, countonly=20, sub_count=0,  name = mathroman_groups_1_int2roman_8(, i =  444  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 9/13, countonly=21, sub_count=0,  name = mathroman_groups_1_int2roman_9(, i =  555  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 10/13, countonly=22, sub_count=0,  name = mathroman_groups_1_int2roman_10(, i =  777  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 11/13, countonly=23, sub_count=0,  name = mathroman_groups_1_int2roman_11(, i =  1111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 12/13, countonly=24, sub_count=0,  name = mathroman_groups_1_int2roman_12(, i =  4999  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 13/13, countonly=25, sub_count=0,  name = mathroman_groups_1_int2roman_13(, i =  5000  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * TestsCases, recursive level =  1  n/N = 8/32  , group =  mathroman_groups_14 
 * n/N = 1/32, countonly=32, sub_count=0,  name = mathroman_groups_14_roman2int_1(, rm =  -X  ),   , testcode =  nil   , argserrs =  
 * n/N = 2/32, countonly=33, sub_count=0,  name = mathroman_groups_14_roman2int_2(, rm =  0  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/32, countonly=34, sub_count=0,  name = mathroman_groups_14_roman2int_3(, rm =    ),   , testcode =  nil   , argserrs =  
 * n/N = 4/32, countonly=35, sub_count=0,  name = mathroman_groups_14_roman2int_4(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/32, countonly=36, sub_count=0,  name = mathroman_groups_14_roman2int_5(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/32, countonly=37, sub_count=0,  name = mathroman_groups_14_roman2int_6(, rm =  XJI  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/32, countonly=38, sub_count=0,  name = mathroman_groups_14_roman2int_7(, rm =  XIA  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/32, countonly=39, sub_count=0,  name = mathroman_groups_14_roman2int_8(, rm =  VLD  ),   , testcode =  nil   , argserrs =  
 * n/N = 9/32, countonly=40, sub_count=0,  name = mathroman_groups_14_roman2int_9(, rm =  IXC  ),   , testcode =  nil   , argserrs =  
 * n/N = 10/32, countonly=41, sub_count=0,  name = mathroman_groups_14_roman2int_10(, rm =  MMMMCMXCIX  ),   , testcode =  nil   , argserrs =  
 * n/N = 11/32, countonly=42, sub_count=0,  name = mathroman_groups_14_roman2int_11(, rm =  MMMMM  ),   , testcode =  nil   , argserrs =  
 * n/N = 12/32, countonly=43, sub_count=0,  name = mathroman_groups_14_roman2int_12(, rm =  MMMMMYJXC  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  2  n/N = 8/8  , group =  mathroman_groups_14_roman_group_13 
 * n/N = 1/8, countonly=8, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_1(, i =  1  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/8, countonly=9, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_2(, i =  3  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/8, countonly=10, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_3(, i =  6  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/8, countonly=11, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_4(, rm =  IV  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/8, countonly=12, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_5(, rm =  V  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/8, countonly=13, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_6(, rm =  III  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/8, countonly=14, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_7(, rm =  VI  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/8, countonly=15, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_8(, rm =  I  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  1  n/N = 4/4  , group =  mathroman_tests_recursive_9 
 * n/N = 1/4, countonly=4, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_1(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/4, countonly=6, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_3(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  

Important support tasks

 * task T53660: Detect the edit state to adapt help messages to user errors.
 * To show edit or test mode only in edit state.


 * task T68051: Get the user language to help admins to maintain a module or a template
 * Permit to use the same module in many languages in many projects. This enlarge the use of modules in many more small wikis. This also enhanse the mean abilities of modules for a same global effort.
 * Help helpers, from large wikis in their own langages, to help small wikis in other languages. Example: display a category in the helper language and link to the category in wiki language.


 * task T119978: Get the own module name and last record date-time from each module
 * This task is necessary to reduce human errors:
 * to rightly collect /I18N translations,
 * and for a more confident versions management.
 * search this task id below for details.


 * task T122752: #invoke seems do not record the module
 * This task is a true bug which impacts the versions management.
 * But the centre library correct it for the main module. Other modules come by require and are not impacted.
 * In most other uses, this bug has no impact.
 * See
 * tools.task_T122752_get_state -- Detect T122752 : #invoke seems do not record the module
 * tools.task_T122752_correct_once -- Debug T122752 : #invoke seems do not record the module

Central repository tasks

 * These tasks impact the final stage of true central usage.
 * But the full development of central libraries is possible without central repository.
 * And the use of central libraries is possible in any local wiki with exactly the same modules, and only new i18n tranlations.
 * task T121470: Central Global Repository for Templates, Lua modules, and Gadgets
 * task T52329: We need a common repository for Scribunto modules and templates
 * task T41610: Scribunto should support global module invocations

Marginal tasks

 * These tasks are interesting to optimize somefunctions but have no link to any central aspects.
 * task T48160: Lua: Allow using labels in mw.wikibase.entity.formatPropertyValues
 * task T63958: Use existing $dateFormats to format dates on Wikidata
 * task T85412: The formatPropertyValues needs an option to format data from date-time, angle or geographic coordinates
 * task T75460: [Story] Make Luafunctions default to the user's language on multilingual wikis
 * task T85419: User groups should be exposed to Scribunto ( This permit to adapt errors and warning for administrators or modules coders )

Documentations examples
 Nelson Mandela Central v221030 , label =  Nelson Mandela  ,  , birthyear =  1918   , deathyear =  2013   , int2roman =  nil   , roman2int =  nil   , int2roman =  nil  This module can translate 208 sentences in 3 languages:  English(en=English),  español(es=Spanish),  français(fr=French),

?  States table of known tasks * =  ( detected state ) Used colors: , Resolved =  task already completed   , args =  task replaced by arguments or by the module   , other =  other tasks 
 * TestsCases mathroman: int2roman(2013) = MMXIII, roman2int(MMXVI) = 2016,
 * TestsCases, recursive level =  1  n/N = 13/13  , group =  mathroman_groups_1 
 * n/N = 1/13, countonly=13, sub_count=0,  name = mathroman_groups_1_int2roman_1(, i =  -11  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/13, countonly=14, sub_count=0,  name = mathroman_groups_1_int2roman_2(, i =  0  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/13, countonly=15, sub_count=0,  name = mathroman_groups_1_int2roman_3(, i =  12  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/13, countonly=16, sub_count=0,  name = mathroman_groups_1_int2roman_4(, i =  17  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 5/13, countonly=17, sub_count=0,  name = mathroman_groups_1_int2roman_5(, i =  18  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 6/13, countonly=18, sub_count=0,  name = mathroman_groups_1_int2roman_6(, i =  19  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 7/13, countonly=19, sub_count=0,  name = mathroman_groups_1_int2roman_7(, i =  111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 8/13, countonly=20, sub_count=0,  name = mathroman_groups_1_int2roman_8(, i =  444  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 9/13, countonly=21, sub_count=0,  name = mathroman_groups_1_int2roman_9(, i =  555  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 10/13, countonly=22, sub_count=0,  name = mathroman_groups_1_int2roman_10(, i =  777  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 11/13, countonly=23, sub_count=0,  name = mathroman_groups_1_int2roman_11(, i =  1111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 12/13, countonly=24, sub_count=0,  name = mathroman_groups_1_int2roman_12(, i =  4999  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 13/13, countonly=25, sub_count=0,  name = mathroman_groups_1_int2roman_13(, i =  5000  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * TestsCases, recursive level =  1  n/N = 8/32  , group =  mathroman_groups_14 
 * n/N = 1/32, countonly=32, sub_count=0,  name = mathroman_groups_14_roman2int_1(, rm =  -X  ),   , testcode =  nil   , argserrs =  
 * n/N = 2/32, countonly=33, sub_count=0,  name = mathroman_groups_14_roman2int_2(, rm =  0  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/32, countonly=34, sub_count=0,  name = mathroman_groups_14_roman2int_3(, rm =    ),   , testcode =  nil   , argserrs =  
 * n/N = 4/32, countonly=35, sub_count=0,  name = mathroman_groups_14_roman2int_4(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/32, countonly=36, sub_count=0,  name = mathroman_groups_14_roman2int_5(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/32, countonly=37, sub_count=0,  name = mathroman_groups_14_roman2int_6(, rm =  XJI  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/32, countonly=38, sub_count=0,  name = mathroman_groups_14_roman2int_7(, rm =  XIA  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/32, countonly=39, sub_count=0,  name = mathroman_groups_14_roman2int_8(, rm =  VLD  ),   , testcode =  nil   , argserrs =  
 * n/N = 9/32, countonly=40, sub_count=0,  name = mathroman_groups_14_roman2int_9(, rm =  IXC  ),   , testcode =  nil   , argserrs =  
 * n/N = 10/32, countonly=41, sub_count=0,  name = mathroman_groups_14_roman2int_10(, rm =  MMMMCMXCIX  ),   , testcode =  nil   , argserrs =  
 * n/N = 11/32, countonly=42, sub_count=0,  name = mathroman_groups_14_roman2int_11(, rm =  MMMMM  ),   , testcode =  nil   , argserrs =  
 * n/N = 12/32, countonly=43, sub_count=0,  name = mathroman_groups_14_roman2int_12(, rm =  MMMMMYJXC  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  2  n/N = 8/8  , group =  mathroman_groups_14_roman_group_13 
 * n/N = 1/8, countonly=8, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_1(, i =  1  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/8, countonly=9, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_2(, i =  3  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/8, countonly=10, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_3(, i =  6  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/8, countonly=11, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_4(, rm =  IV  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/8, countonly=12, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_5(, rm =  V  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/8, countonly=13, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_6(, rm =  III  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/8, countonly=14, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_7(, rm =  VI  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/8, countonly=15, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_8(, rm =  I  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  1  n/N = 4/4  , group =  mathroman_tests_recursive_9 
 * n/N = 1/4, countonly=4, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_1(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/4, countonly=6, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_3(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  

 Test of Wikidata arbitrary access
 * Wikidata for another Title: Q535, Victor Hugo ( 1802 - 1885 )  ⦁  Datas from Wikidata, 376 properties.
 * Sought properties:, sitelink =  nil   , label =  Victor Hugo   , deathyear =  1885   , country =  France   , description =  nil   , birthyear =  1802   , itemid2 =  Q535   , itemid =  Q535 
 * Wikidata for another Title: Q8023, Nelson Mandela ( 1918 - 2013 )  ⦁  Datas from Wikidata, 245 properties.
 * Sought properties:, sitelink =  nil   , label =  Nelson Mandela   , deathyear =  2013   , country =  South Africa   , description =  nil   , birthyear =  1918   , itemid2 =  Q8023   , itemid =  Q8023     Mediawiki recursive TestsCases
 * TestsCases mathroman: int2roman(2013) = MMXIII, roman2int(MMXVI) = 2016,
 * TestsCases, recursive level =  1  n/N = 13/13  , group =  mathroman_groups_1 
 * n/N = 1/13, countonly=13, sub_count=0,  name = mathroman_groups_1_int2roman_1(, i =  -11  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/13, countonly=14, sub_count=0,  name = mathroman_groups_1_int2roman_2(, i =  0  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/13, countonly=15, sub_count=0,  name = mathroman_groups_1_int2roman_3(, i =  12  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/13, countonly=16, sub_count=0,  name = mathroman_groups_1_int2roman_4(, i =  17  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 5/13, countonly=17, sub_count=0,  name = mathroman_groups_1_int2roman_5(, i =  18  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 6/13, countonly=18, sub_count=0,  name = mathroman_groups_1_int2roman_6(, i =  19  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 7/13, countonly=19, sub_count=0,  name = mathroman_groups_1_int2roman_7(, i =  111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 8/13, countonly=20, sub_count=0,  name = mathroman_groups_1_int2roman_8(, i =  444  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 9/13, countonly=21, sub_count=0,  name = mathroman_groups_1_int2roman_9(, i =  555  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 10/13, countonly=22, sub_count=0,  name = mathroman_groups_1_int2roman_10(, i =  777  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 11/13, countonly=23, sub_count=0,  name = mathroman_groups_1_int2roman_11(, i =  1111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 12/13, countonly=24, sub_count=0,  name = mathroman_groups_1_int2roman_12(, i =  4999  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 13/13, countonly=25, sub_count=0,  name = mathroman_groups_1_int2roman_13(, i =  5000  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * TestsCases, recursive level =  1  n/N = 8/32  , group =  mathroman_groups_14 
 * n/N = 1/32, countonly=32, sub_count=0,  name = mathroman_groups_14_roman2int_1(, rm =  -X  ),   , testcode =  nil   , argserrs =  
 * n/N = 2/32, countonly=33, sub_count=0,  name = mathroman_groups_14_roman2int_2(, rm =  0  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/32, countonly=34, sub_count=0,  name = mathroman_groups_14_roman2int_3(, rm =    ),   , testcode =  nil   , argserrs =  
 * n/N = 4/32, countonly=35, sub_count=0,  name = mathroman_groups_14_roman2int_4(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/32, countonly=36, sub_count=0,  name = mathroman_groups_14_roman2int_5(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/32, countonly=37, sub_count=0,  name = mathroman_groups_14_roman2int_6(, rm =  XJI  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/32, countonly=38, sub_count=0,  name = mathroman_groups_14_roman2int_7(, rm =  XIA  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/32, countonly=39, sub_count=0,  name = mathroman_groups_14_roman2int_8(, rm =  VLD  ),   , testcode =  nil   , argserrs =  
 * n/N = 9/32, countonly=40, sub_count=0,  name = mathroman_groups_14_roman2int_9(, rm =  IXC  ),   , testcode =  nil   , argserrs =  
 * n/N = 10/32, countonly=41, sub_count=0,  name = mathroman_groups_14_roman2int_10(, rm =  MMMMCMXCIX  ),   , testcode =  nil   , argserrs =  
 * n/N = 11/32, countonly=42, sub_count=0,  name = mathroman_groups_14_roman2int_11(, rm =  MMMMM  ),   , testcode =  nil   , argserrs =  
 * n/N = 12/32, countonly=43, sub_count=0,  name = mathroman_groups_14_roman2int_12(, rm =  MMMMMYJXC  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  2  n/N = 8/8  , group =  mathroman_groups_14_roman_group_13 
 * n/N = 1/8, countonly=8, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_1(, i =  1  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/8, countonly=9, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_2(, i =  3  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/8, countonly=10, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_3(, i =  6  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/8, countonly=11, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_4(, rm =  IV  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/8, countonly=12, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_5(, rm =  V  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/8, countonly=13, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_6(, rm =  III  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/8, countonly=14, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_7(, rm =  VI  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/8, countonly=15, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_8(, rm =  I  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  1  n/N = 4/4  , group =  mathroman_tests_recursive_9 
 * n/N = 1/4, countonly=4, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_1(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/4, countonly=6, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_3(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  

Translate arguments, errors, categories...

 * Translate arguments names (and their descriptions), errors, categories, title...

Define arguments

 * All arguments must be translated in all languages to operate.

Minimal centalisable module

 * A module without interface can form translated errors or categories in any function, without any p.interface(frame) functions.
 * It can also use translated arguments and/or form report to display later if sought.
 * The centre library and the mathroman library are in this case.


 * Any module using central library can contain, or none, internal translations in english and some other languages.
 * Minimal example:

Modes and options

 * Really used options come from p.options_for_modes and from options arguments.


 * Modes are composed of options to choose what and how to display. Default modes:

Versions management

 * Each centralisable main module can start with a definition of alternative versions of its sub-modules.
 * Then its versions management is available.


 * Template or invoke arguments can replace soughtversions and knownversions to try them without record, or in a test template.


 * In known versions, the first of each group of versions is the normal one and can replace any other if not available.


 * The versions management  adequate versions of submodules to test, following known and sought versions, like.
 * This versions management reports versions: used, errors, missing or replaced by normal ones... then helpers can better select and understand what happens.
 * Any helper of main module can select versions of its submodules from internal arguments or from template arguments.


 * When the developer copies or rename this file in a new version, he can forget to adapt that definition and then disturb the versions management.
 * To reduce this risk, each module need to know its own name.
 * To document the version date-time, we need that for each module or sub-module.
 * See the task task T119978: Get the own module name and last record date-time from each module

 Test for management of modules versions
 * tools.versions_management_test : The selector =  Box3, Group, Item1  means: check these modules versions among those available.
 * loaded_vers : Table of all loaded modules, or simulation.
 * Simulate existing versions:
 * The table below simulates loaded modules for behind tests cases.
 * , Number of versions simulated: =  12    Mediawiki recursive TestsCases
 * TestsCases mathroman: int2roman(2013) = MMXIII, roman2int(MMXVI) = 2016,
 * TestsCases, recursive level =  1  n/N = 13/13  , group =  mathroman_groups_1 
 * n/N = 1/13, countonly=13, sub_count=0,  name = mathroman_groups_1_int2roman_1(, i =  -11  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/13, countonly=14, sub_count=0,  name = mathroman_groups_1_int2roman_2(, i =  0  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/13, countonly=15, sub_count=0,  name = mathroman_groups_1_int2roman_3(, i =  12  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/13, countonly=16, sub_count=0,  name = mathroman_groups_1_int2roman_4(, i =  17  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 5/13, countonly=17, sub_count=0,  name = mathroman_groups_1_int2roman_5(, i =  18  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 6/13, countonly=18, sub_count=0,  name = mathroman_groups_1_int2roman_6(, i =  19  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 7/13, countonly=19, sub_count=0,  name = mathroman_groups_1_int2roman_7(, i =  111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 8/13, countonly=20, sub_count=0,  name = mathroman_groups_1_int2roman_8(, i =  444  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 9/13, countonly=21, sub_count=0,  name = mathroman_groups_1_int2roman_9(, i =  555  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 10/13, countonly=22, sub_count=0,  name = mathroman_groups_1_int2roman_10(, i =  777  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 11/13, countonly=23, sub_count=0,  name = mathroman_groups_1_int2roman_11(, i =  1111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 12/13, countonly=24, sub_count=0,  name = mathroman_groups_1_int2roman_12(, i =  4999  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 13/13, countonly=25, sub_count=0,  name = mathroman_groups_1_int2roman_13(, i =  5000  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * TestsCases, recursive level =  1  n/N = 8/32  , group =  mathroman_groups_14 
 * n/N = 1/32, countonly=32, sub_count=0,  name = mathroman_groups_14_roman2int_1(, rm =  -X  ),   , testcode =  nil   , argserrs =  
 * n/N = 2/32, countonly=33, sub_count=0,  name = mathroman_groups_14_roman2int_2(, rm =  0  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/32, countonly=34, sub_count=0,  name = mathroman_groups_14_roman2int_3(, rm =    ),   , testcode =  nil   , argserrs =  
 * n/N = 4/32, countonly=35, sub_count=0,  name = mathroman_groups_14_roman2int_4(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/32, countonly=36, sub_count=0,  name = mathroman_groups_14_roman2int_5(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/32, countonly=37, sub_count=0,  name = mathroman_groups_14_roman2int_6(, rm =  XJI  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/32, countonly=38, sub_count=0,  name = mathroman_groups_14_roman2int_7(, rm =  XIA  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/32, countonly=39, sub_count=0,  name = mathroman_groups_14_roman2int_8(, rm =  VLD  ),   , testcode =  nil   , argserrs =  
 * n/N = 9/32, countonly=40, sub_count=0,  name = mathroman_groups_14_roman2int_9(, rm =  IXC  ),   , testcode =  nil   , argserrs =  
 * n/N = 10/32, countonly=41, sub_count=0,  name = mathroman_groups_14_roman2int_10(, rm =  MMMMCMXCIX  ),   , testcode =  nil   , argserrs =  
 * n/N = 11/32, countonly=42, sub_count=0,  name = mathroman_groups_14_roman2int_11(, rm =  MMMMM  ),   , testcode =  nil   , argserrs =  
 * n/N = 12/32, countonly=43, sub_count=0,  name = mathroman_groups_14_roman2int_12(, rm =  MMMMMYJXC  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  2  n/N = 8/8  , group =  mathroman_groups_14_roman_group_13 
 * n/N = 1/8, countonly=8, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_1(, i =  1  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/8, countonly=9, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_2(, i =  3  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/8, countonly=10, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_3(, i =  6  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/8, countonly=11, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_4(, rm =  IV  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/8, countonly=12, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_5(, rm =  V  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/8, countonly=13, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_6(, rm =  III  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/8, countonly=14, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_7(, rm =  VI  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/8, countonly=15, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_8(, rm =  I  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  1  n/N = 4/4  , group =  mathroman_tests_recursive_9 
 * n/N = 1/4, countonly=4, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_1(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/4, countonly=6, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_3(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  

Translations management

 * Any translation must not involuntarily disturb an other and we must insure that this cannot happens, especially in new modules or libraries.
 * For this need we can/must start any translation key with the name of the module or library.
 * An alternative version can modify any translation of the normal version.
 * A main module can modify any translation from any submodule to adapt it to a new context.
 * A /I18N submodule can adjust or correct any translation from a normal or new version.

Then the function follows these rules:
 * starts with the libraries translations,
 * starts with the internal translations,
 * then add or mix translations from normal /I18N,
 * then add or mix translations from the /I18N alternative versions,


 * continue with the modules translations,
 * starts with the internal translations,
 * then add or mix translations from normal /I18N,
 * then add or mix translations from the /I18N alternative versions.
 * In doc or test mode, a report display missing or modified translations.


 * To reduce errors risks in the binding of translations, we need to base each /I18N sub-module name on the name of each module itself.
 * See the task task T119978: Get the own module name and last record date-time from each module

 Translations missings and changes in i18n tables:
 * Comparer les langues : es/fr,
 * Comparer les langues : fr/en, ⦁ Internal Error: Module missing i18n translation for the argument tools_auto_val_warning_2_msg   ⦁ Internal Error: There are 1 missings in 213 translations.
 * Translated languages: Langues traduites :, Langue : es , Langue : fr  , Langue : en
 * There are 3 tables of translations in these languages : es, fr, en,
 * Same example without translation for a test case : tools_languages_nbr_and_list-3-es, fr, en,


 * transdiff_report: Compare all differences of translations:
 * TestsCases mathroman: int2roman(2013) = MMXIII, roman2int(MMXVI) = 2016,
 * TestsCases, recursive level =  1  n/N = 13/13  , group =  mathroman_groups_1 
 * n/N = 1/13, countonly=13, sub_count=0,  name = mathroman_groups_1_int2roman_1(, i =  -11  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/13, countonly=14, sub_count=0,  name = mathroman_groups_1_int2roman_2(, i =  0  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/13, countonly=15, sub_count=0,  name = mathroman_groups_1_int2roman_3(, i =  12  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/13, countonly=16, sub_count=0,  name = mathroman_groups_1_int2roman_4(, i =  17  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 5/13, countonly=17, sub_count=0,  name = mathroman_groups_1_int2roman_5(, i =  18  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 6/13, countonly=18, sub_count=0,  name = mathroman_groups_1_int2roman_6(, i =  19  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 7/13, countonly=19, sub_count=0,  name = mathroman_groups_1_int2roman_7(, i =  111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 8/13, countonly=20, sub_count=0,  name = mathroman_groups_1_int2roman_8(, i =  444  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 9/13, countonly=21, sub_count=0,  name = mathroman_groups_1_int2roman_9(, i =  555  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 10/13, countonly=22, sub_count=0,  name = mathroman_groups_1_int2roman_10(, i =  777  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 11/13, countonly=23, sub_count=0,  name = mathroman_groups_1_int2roman_11(, i =  1111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 12/13, countonly=24, sub_count=0,  name = mathroman_groups_1_int2roman_12(, i =  4999  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 13/13, countonly=25, sub_count=0,  name = mathroman_groups_1_int2roman_13(, i =  5000  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * TestsCases, recursive level =  1  n/N = 8/32  , group =  mathroman_groups_14 
 * n/N = 1/32, countonly=32, sub_count=0,  name = mathroman_groups_14_roman2int_1(, rm =  -X  ),   , testcode =  nil   , argserrs =  
 * n/N = 2/32, countonly=33, sub_count=0,  name = mathroman_groups_14_roman2int_2(, rm =  0  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/32, countonly=34, sub_count=0,  name = mathroman_groups_14_roman2int_3(, rm =    ),   , testcode =  nil   , argserrs =  
 * n/N = 4/32, countonly=35, sub_count=0,  name = mathroman_groups_14_roman2int_4(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/32, countonly=36, sub_count=0,  name = mathroman_groups_14_roman2int_5(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/32, countonly=37, sub_count=0,  name = mathroman_groups_14_roman2int_6(, rm =  XJI  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/32, countonly=38, sub_count=0,  name = mathroman_groups_14_roman2int_7(, rm =  XIA  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/32, countonly=39, sub_count=0,  name = mathroman_groups_14_roman2int_8(, rm =  VLD  ),   , testcode =  nil   , argserrs =  
 * n/N = 9/32, countonly=40, sub_count=0,  name = mathroman_groups_14_roman2int_9(, rm =  IXC  ),   , testcode =  nil   , argserrs =  
 * n/N = 10/32, countonly=41, sub_count=0,  name = mathroman_groups_14_roman2int_10(, rm =  MMMMCMXCIX  ),   , testcode =  nil   , argserrs =  
 * n/N = 11/32, countonly=42, sub_count=0,  name = mathroman_groups_14_roman2int_11(, rm =  MMMMM  ),   , testcode =  nil   , argserrs =  
 * n/N = 12/32, countonly=43, sub_count=0,  name = mathroman_groups_14_roman2int_12(, rm =  MMMMMYJXC  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  2  n/N = 8/8  , group =  mathroman_groups_14_roman_group_13 
 * n/N = 1/8, countonly=8, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_1(, i =  1  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/8, countonly=9, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_2(, i =  3  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/8, countonly=10, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_3(, i =  6  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/8, countonly=11, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_4(, rm =  IV  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/8, countonly=12, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_5(, rm =  V  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/8, countonly=13, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_6(, rm =  III  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/8, countonly=14, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_7(, rm =  VI  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/8, countonly=15, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_8(, rm =  I  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  1  n/N = 4/4  , group =  mathroman_tests_recursive_9 
 * n/N = 1/4, countonly=4, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_1(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/4, countonly=6, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_3(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  

Structures and guidelines

 * In development phase keep some light errors to show how reports form errors.


 * The central code must be strong with or without central repository, libraries, known bugs and weak use.


 * Then central functions must specialy verify their arguments, run only once if needed, tested by tests cases, and tests shown for users.

Process of arguments and translations

 * Steps in arguments process:
 * : The main module defines all arguments, and they all must have translations in all availables languages.
 * : The source arguments come from template, else from #invoke, for each argument.
 * : Memorize direct configuration arguments.
 * : An argument can come from wikidata if its definition have a wikidata property like.
 * The priority in origin of an argument is always: first the template, else the, else the internal interaction between arguments in the module, else the internal default value in the module.
 * : The config arguments come without translations from source arguments. Translations are identical in all available languages.

 Mediawiki recursive TestsCases
 * TestsCases mathroman: int2roman(2013) = MMXIII, roman2int(MMXVI) = 2016,
 * TestsCases, recursive level =  1  n/N = 13/13  , group =  mathroman_groups_1 
 * n/N = 1/13, countonly=13, sub_count=0,  name = mathroman_groups_1_int2roman_1(, i =  -11  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/13, countonly=14, sub_count=0,  name = mathroman_groups_1_int2roman_2(, i =  0  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/13, countonly=15, sub_count=0,  name = mathroman_groups_1_int2roman_3(, i =  12  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/13, countonly=16, sub_count=0,  name = mathroman_groups_1_int2roman_4(, i =  17  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 5/13, countonly=17, sub_count=0,  name = mathroman_groups_1_int2roman_5(, i =  18  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 6/13, countonly=18, sub_count=0,  name = mathroman_groups_1_int2roman_6(, i =  19  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 7/13, countonly=19, sub_count=0,  name = mathroman_groups_1_int2roman_7(, i =  111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 8/13, countonly=20, sub_count=0,  name = mathroman_groups_1_int2roman_8(, i =  444  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 9/13, countonly=21, sub_count=0,  name = mathroman_groups_1_int2roman_9(, i =  555  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 10/13, countonly=22, sub_count=0,  name = mathroman_groups_1_int2roman_10(, i =  777  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 11/13, countonly=23, sub_count=0,  name = mathroman_groups_1_int2roman_11(, i =  1111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 12/13, countonly=24, sub_count=0,  name = mathroman_groups_1_int2roman_12(, i =  4999  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 13/13, countonly=25, sub_count=0,  name = mathroman_groups_1_int2roman_13(, i =  5000  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * TestsCases, recursive level =  1  n/N = 8/32  , group =  mathroman_groups_14 
 * n/N = 1/32, countonly=32, sub_count=0,  name = mathroman_groups_14_roman2int_1(, rm =  -X  ),   , testcode =  nil   , argserrs =  
 * n/N = 2/32, countonly=33, sub_count=0,  name = mathroman_groups_14_roman2int_2(, rm =  0  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/32, countonly=34, sub_count=0,  name = mathroman_groups_14_roman2int_3(, rm =    ),   , testcode =  nil   , argserrs =  
 * n/N = 4/32, countonly=35, sub_count=0,  name = mathroman_groups_14_roman2int_4(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/32, countonly=36, sub_count=0,  name = mathroman_groups_14_roman2int_5(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/32, countonly=37, sub_count=0,  name = mathroman_groups_14_roman2int_6(, rm =  XJI  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/32, countonly=38, sub_count=0,  name = mathroman_groups_14_roman2int_7(, rm =  XIA  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/32, countonly=39, sub_count=0,  name = mathroman_groups_14_roman2int_8(, rm =  VLD  ),   , testcode =  nil   , argserrs =  
 * n/N = 9/32, countonly=40, sub_count=0,  name = mathroman_groups_14_roman2int_9(, rm =  IXC  ),   , testcode =  nil   , argserrs =  
 * n/N = 10/32, countonly=41, sub_count=0,  name = mathroman_groups_14_roman2int_10(, rm =  MMMMCMXCIX  ),   , testcode =  nil   , argserrs =  
 * n/N = 11/32, countonly=42, sub_count=0,  name = mathroman_groups_14_roman2int_11(, rm =  MMMMM  ),   , testcode =  nil   , argserrs =  
 * n/N = 12/32, countonly=43, sub_count=0,  name = mathroman_groups_14_roman2int_12(, rm =  MMMMMYJXC  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  2  n/N = 8/8  , group =  mathroman_groups_14_roman_group_13 
 * n/N = 1/8, countonly=8, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_1(, i =  1  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/8, countonly=9, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_2(, i =  3  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/8, countonly=10, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_3(, i =  6  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/8, countonly=11, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_4(, rm =  IV  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/8, countonly=12, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_5(, rm =  V  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/8, countonly=13, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_6(, rm =  III  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/8, countonly=14, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_7(, rm =  VI  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/8, countonly=15, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_8(, rm =  I  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  1  n/N = 4/4  , group =  mathroman_tests_recursive_9 
 * n/N = 1/4, countonly=4, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_1(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/4, countonly=6, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_3(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  

Arguments properties
 Mediawiki recursive TestsCases
 * TestsCases mathroman: int2roman(2013) = MMXIII, roman2int(MMXVI) = 2016,
 * TestsCases, recursive level =  1  n/N = 13/13  , group =  mathroman_groups_1 
 * n/N = 1/13, countonly=13, sub_count=0,  name = mathroman_groups_1_int2roman_1(, i =  -11  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/13, countonly=14, sub_count=0,  name = mathroman_groups_1_int2roman_2(, i =  0  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/13, countonly=15, sub_count=0,  name = mathroman_groups_1_int2roman_3(, i =  12  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/13, countonly=16, sub_count=0,  name = mathroman_groups_1_int2roman_4(, i =  17  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 5/13, countonly=17, sub_count=0,  name = mathroman_groups_1_int2roman_5(, i =  18  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 6/13, countonly=18, sub_count=0,  name = mathroman_groups_1_int2roman_6(, i =  19  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 7/13, countonly=19, sub_count=0,  name = mathroman_groups_1_int2roman_7(, i =  111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 8/13, countonly=20, sub_count=0,  name = mathroman_groups_1_int2roman_8(, i =  444  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 9/13, countonly=21, sub_count=0,  name = mathroman_groups_1_int2roman_9(, i =  555  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 10/13, countonly=22, sub_count=0,  name = mathroman_groups_1_int2roman_10(, i =  777  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 11/13, countonly=23, sub_count=0,  name = mathroman_groups_1_int2roman_11(, i =  1111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 12/13, countonly=24, sub_count=0,  name = mathroman_groups_1_int2roman_12(, i =  4999  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 13/13, countonly=25, sub_count=0,  name = mathroman_groups_1_int2roman_13(, i =  5000  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * TestsCases, recursive level =  1  n/N = 8/32  , group =  mathroman_groups_14 
 * n/N = 1/32, countonly=32, sub_count=0,  name = mathroman_groups_14_roman2int_1(, rm =  -X  ),   , testcode =  nil   , argserrs =  
 * n/N = 2/32, countonly=33, sub_count=0,  name = mathroman_groups_14_roman2int_2(, rm =  0  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/32, countonly=34, sub_count=0,  name = mathroman_groups_14_roman2int_3(, rm =    ),   , testcode =  nil   , argserrs =  
 * n/N = 4/32, countonly=35, sub_count=0,  name = mathroman_groups_14_roman2int_4(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/32, countonly=36, sub_count=0,  name = mathroman_groups_14_roman2int_5(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/32, countonly=37, sub_count=0,  name = mathroman_groups_14_roman2int_6(, rm =  XJI  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/32, countonly=38, sub_count=0,  name = mathroman_groups_14_roman2int_7(, rm =  XIA  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/32, countonly=39, sub_count=0,  name = mathroman_groups_14_roman2int_8(, rm =  VLD  ),   , testcode =  nil   , argserrs =  
 * n/N = 9/32, countonly=40, sub_count=0,  name = mathroman_groups_14_roman2int_9(, rm =  IXC  ),   , testcode =  nil   , argserrs =  
 * n/N = 10/32, countonly=41, sub_count=0,  name = mathroman_groups_14_roman2int_10(, rm =  MMMMCMXCIX  ),   , testcode =  nil   , argserrs =  
 * n/N = 11/32, countonly=42, sub_count=0,  name = mathroman_groups_14_roman2int_11(, rm =  MMMMM  ),   , testcode =  nil   , argserrs =  
 * n/N = 12/32, countonly=43, sub_count=0,  name = mathroman_groups_14_roman2int_12(, rm =  MMMMMYJXC  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  2  n/N = 8/8  , group =  mathroman_groups_14_roman_group_13 
 * n/N = 1/8, countonly=8, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_1(, i =  1  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/8, countonly=9, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_2(, i =  3  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/8, countonly=10, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_3(, i =  6  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/8, countonly=11, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_4(, rm =  IV  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/8, countonly=12, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_5(, rm =  V  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/8, countonly=13, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_6(, rm =  III  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/8, countonly=14, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_7(, rm =  VI  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/8, countonly=15, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_8(, rm =  I  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  1  n/N = 4/4  , group =  mathroman_tests_recursive_9 
 * n/N = 1/4, countonly=4, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_1(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/4, countonly=6, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_3(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  

They can be needed, synonym, limited to some values ... typical examples:

Config support arguments
They drive directly support aspects, without translations:

Translations texts keys
They follow these guideline. That enable to group them in documentations for errors, categories and other:

How to name central libraries ?

 * How to distribute functions in one or some libraries ?


 * How to name also all the functions of these libraries ?


 * The  library mainly binds modules. Eventual names:
 * as international noun and to support to move in a central place.
 * as USA english noun and to support to move in a central place.
 * as the place in the middle.
 * as support to move in the middle.
 * as support to move in the middle.


 * The  library mainly extends the translation service and translatable usual viewers. Eventual names:
 * as tools for the centre library.
 * as available tools shared in the central space.
 * as available tools shared in the central space.


 * Whe could make a viewer or viewers library to group:
 * for table of raws and columns.
 * and  with title, content and style options.
 * for parametrable and bilingual categories, and to group their list.
 * for parametrable messages, and to group their list.
 * for counts and structures of luatable.

centre library

 * The  library binds modules in sought versions and their translations.

centre.new_library

 * Record a library in  from a table object.

centre.bindmodules

 * Bind all modules, versions and translations. Cumulate in  all translations from i18n tables from modules.

centre.get_module_and_time

 * This function can create a module and/or collect and complete data on a module or a library.
 * This code roughly describe it:

tools library

 * Internalfunctions to implement mainfunctions are not described.

tools.str_vars
Result in a parametrable string based on.
 * If  is a key of translatable string in i18n table, it is first translated.
 * If  is not a translatable key, thisfunction uses it like translated.
 * If the translated string contains  to   thisfunction replaces them by   to   respectively, after thisfunction converts them in strings.
 * If  is any other string, thefunction return it as is.

This is roughly equivalent to:

tools.str_test_case

 * This is a first step to work on tests_cases. See also mathroman.tests_cases


 * This function for test case do not translate but convert it like in:
 * This is better for tests cases:
 * Then tests cases depend of values but not of the languages.
 * Different translations have different keys but can have a same text.
 * This is roughly equivalent to:


 * For tests cases search : class ClassNameTest extends Scribunto_LuaEngineTestBase

tools.is_in

 * Returns  if the word is in the text, even inside another word. Else return.

This is roughly equivalent to:

tools.is_in_sp

 * Returns  if the word is in the text, beetwen spaces or separators, not inside another word. Else return.
 * This function is in centre which use it to find versions in list.

This is roughly equivalent to:

tools.cat_add

 * Record a category in, parametrable like tools.str_vars.

tools.catGroup

 * Generate categories from plural values in only one string argument divided by comas.


 * Record a  group of categories in.
 * Each part is translatable like in tools.str_vars(one of parts of groupList).


 * Example wich give Category:Country France, Category:Country Italy

This is roughly equivalent to:
 * For each part of  divided by a coma.

tools.err_add

 * Returns a error, parametrable like tools.str_vars.
 * Record also these errors in.

tools.msg_add

 * Returns a message, parametrable like tools.str_vars.
 * Record also these messages in.

tools.errors_lister

 * Returns the list of all recorded messages first, then all errors.
 * Does not return duplicates errors or messages.

tools.Th tableview

 * That could become the tableview object.

tools.dropbox
dropbox, documentation in a single dropbox, series of dropboxes.

options to select


 * Returns a dropbox with parametrable title and style.
 * The optional  parameter is a table containing options to define the style of the dropbox.

tools.dropdownfunc

 * Like tools.dropbox.


 * This function forms the dropbox if  is "allwaysview" or "enforcerun" or   or the   key before translation.


 * If the function fails the dropbox displays INTERNAL ERROR, to protect the displaying of the rest of the page.
 * Then a developer can replace  with   for this box. Then he/she can debug the code error. See examples below.


 * The content parameter can be a string or a function followed by any number of its parameters.
 * Options for the dropbox are in a table identified by one of its contents:


 * Options and their default values are:


 * Options are not but also could be title, content, image.


 * Example of dropbox style options:

 Test options from modes   options_from_mode_test: - , normal =   noerr   -  , read =   noerr   -  , edit =   : catview docview docdef docline docsrc docdata   -  , tests =   : catview docview docdef docline docsrc docdata tests   -  , doc1 =   nobox noerr nocat  
 * TestsCases mathroman: int2roman(2013) = MMXIII, roman2int(MMXVI) = 2016,
 * TestsCases, recursive level =  1  n/N = 13/13  , group =  mathroman_groups_1 
 * n/N = 1/13, countonly=13, sub_count=0,  name = mathroman_groups_1_int2roman_1(, i =  -11  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/13, countonly=14, sub_count=0,  name = mathroman_groups_1_int2roman_2(, i =  0  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/13, countonly=15, sub_count=0,  name = mathroman_groups_1_int2roman_3(, i =  12  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/13, countonly=16, sub_count=0,  name = mathroman_groups_1_int2roman_4(, i =  17  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 5/13, countonly=17, sub_count=0,  name = mathroman_groups_1_int2roman_5(, i =  18  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 6/13, countonly=18, sub_count=0,  name = mathroman_groups_1_int2roman_6(, i =  19  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 7/13, countonly=19, sub_count=0,  name = mathroman_groups_1_int2roman_7(, i =  111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 8/13, countonly=20, sub_count=0,  name = mathroman_groups_1_int2roman_8(, i =  444  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 9/13, countonly=21, sub_count=0,  name = mathroman_groups_1_int2roman_9(, i =  555  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 10/13, countonly=22, sub_count=0,  name = mathroman_groups_1_int2roman_10(, i =  777  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 11/13, countonly=23, sub_count=0,  name = mathroman_groups_1_int2roman_11(, i =  1111  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 12/13, countonly=24, sub_count=0,  name = mathroman_groups_1_int2roman_12(, i =  4999  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 13/13, countonly=25, sub_count=0,  name = mathroman_groups_1_int2roman_13(, i =  5000  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * TestsCases, recursive level =  1  n/N = 8/32  , group =  mathroman_groups_14 
 * n/N = 1/32, countonly=32, sub_count=0,  name = mathroman_groups_14_roman2int_1(, rm =  -X  ),   , testcode =  nil   , argserrs =  
 * n/N = 2/32, countonly=33, sub_count=0,  name = mathroman_groups_14_roman2int_2(, rm =  0  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/32, countonly=34, sub_count=0,  name = mathroman_groups_14_roman2int_3(, rm =    ),   , testcode =  nil   , argserrs =  
 * n/N = 4/32, countonly=35, sub_count=0,  name = mathroman_groups_14_roman2int_4(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/32, countonly=36, sub_count=0,  name = mathroman_groups_14_roman2int_5(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/32, countonly=37, sub_count=0,  name = mathroman_groups_14_roman2int_6(, rm =  XJI  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/32, countonly=38, sub_count=0,  name = mathroman_groups_14_roman2int_7(, rm =  XIA  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/32, countonly=39, sub_count=0,  name = mathroman_groups_14_roman2int_8(, rm =  VLD  ),   , testcode =  nil   , argserrs =  
 * n/N = 9/32, countonly=40, sub_count=0,  name = mathroman_groups_14_roman2int_9(, rm =  IXC  ),   , testcode =  nil   , argserrs =  
 * n/N = 10/32, countonly=41, sub_count=0,  name = mathroman_groups_14_roman2int_10(, rm =  MMMMCMXCIX  ),   , testcode =  nil   , argserrs =  
 * n/N = 11/32, countonly=42, sub_count=0,  name = mathroman_groups_14_roman2int_11(, rm =  MMMMM  ),   , testcode =  nil   , argserrs =  
 * n/N = 12/32, countonly=43, sub_count=0,  name = mathroman_groups_14_roman2int_12(, rm =  MMMMMYJXC  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  2  n/N = 8/8  , group =  mathroman_groups_14_roman_group_13 
 * n/N = 1/8, countonly=8, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_1(, i =  1  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 2/8, countonly=9, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_2(, i =  3  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 3/8, countonly=10, sub_count=0,  name = mathroman_groups_14_roman_group_13_int2roman_3(, i =  6  ),   , testcode =  nil   , argserrs =  mathroman_null_value_err-0 
 * n/N = 4/8, countonly=11, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_4(, rm =  IV  ),   , testcode =  nil   , argserrs =  
 * n/N = 5/8, countonly=12, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_5(, rm =  V  ),   , testcode =  nil   , argserrs =  
 * n/N = 6/8, countonly=13, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_6(, rm =  III  ),   , testcode =  nil   , argserrs =  
 * n/N = 7/8, countonly=14, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_7(, rm =  VI  ),   , testcode =  nil   , argserrs =  
 * n/N = 8/8, countonly=15, sub_count=0,  name = mathroman_groups_14_roman_group_13_roman2int_8(, rm =  I  ),   , testcode =  nil   , argserrs =  
 * TestsCases, recursive level =  1  n/N = 4/4  , group =  mathroman_tests_recursive_9 
 * n/N = 1/4, countonly=4, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_1(, rm =  XIJ  ),   , testcode =  nil   , argserrs =  
 * n/N = 3/4, countonly=6, sub_count=0,  name = mathroman_tests_recursive_9_roman2int_3(, rm =  MCXI  ),   , testcode =  nil   , argserrs =  

tools.maini18n_languages_list

 * Returns the list of available languages.
 * Example: "This module can translate 171 texts in 3 languages: English(en=English), español(es=Spanish), français(fr=French),".

tools.luatablecount

 * is a luatable or a name of table in tools library like
 * is a name of the  table.
 * is a string like "The table mathroman.i18n counts 30 texts, 0 functions, 3 sub-tables."
 * In whole the table, the number of string is, of functions is  , of sub-tables is  ,

tools.form_i18n_counts

 * Then  is a string like "maini18n = 157 sentences translated in 48 languages."

mathroman library

 * It converts decimal to roman numbers or reverse. It produces errors messages to explicite them. It have none interface(frame).

mathroman.int2roman

 * Returns the roman number first, then eventual text of errors.
 * Record also these errors in.

mathroman.roman2int

 * Returns the decimal integer first, then eventual text of errors.
 * Record also these errors in.

mathroman.tests_cases

 * This is a first step to work on tests_cases. See also tools.str_test_case


 * Returns the decimal integer first, then eventual text of errors.
 * Record also these errors in.


 * Where to find documents or examples?
 * Rical: I have search in phab, gerrit, mediawiki without success.
 * For tests cases search "ClassNameTest" or "LuaEngineTestBase" or "LuaEngineTestBase::testLua" in class Lua reference manual.
 * I found only my own code in 2013 in Module:Unitest_Scribunto
 * But I don't know if it is efficient. How to submit a library to mediawiki check in gerrit?
 * See also T48635 Scribunto_LuaLibraryBase registerInterface produces internal error on Windows platform