MediaWiki:Gadget-CreerTrad-dev.js

Définition, traduction, prononciation, anagramme et synonyme sur le dictionnaire libre Wiktionnaire.

Remarque: après avoir sauvegardé, vous devez vider le cache de votre navigateur pour que les changements prennent effet. Mozilla, cliquez sur Actualiser (ou ctrl-r). Internet Explorer / Opera: ctrl-f5. Safari: cmd-r. Konqueror ctrl-r.

/*******************************************************************************************
 * (en)
 * Lets the users create the page for a translation just by clicking its (red) link in the
 * French entry.
 *******************************************************************************************
 * (fr)
 * Permet aux utilisateurs de créer la page d’une traduction en cliquant juste sur son lien
 * (rouge) dans l’entrée en français.
 *******************************************************************************************
 * v1.0 2013-06-13
 * v2.0 2020-11-01 Full rewrite.
 * v2.1 2021-05-08 Smarter wikicode analysis;
 *                 page reloads instead of having its content replaced
 *******************************************************************************************
 * [[Catégorie:JavaScript du Wiktionnaire|CreerTrad-dev]]
 *******************************************************************************************/

$(function () {
  if (wikt.page.hasNamespaceIn(["", "Reconstruction"])
      && ["view", "edit", "submit"].includes(mw.config.get("wgAction"))) {
    console.log("Chargement de Gadget-CreerTrad-dev.js…");

    window.wikt.gadgets.createTranslation = {
      NAME: "Créer traduction",

      VERSION: "2.1",

      /** @type {boolean} */
      _editMode: false,
      /** @type {string} */
      _word: "",
      /** @type {string} */
      _translation: "",
      /** @type {string} */
      _langCode: "",
      /**
       * Map that associates a language code to a
       * function that generates the code for it.
       * @type {Object<string, Function>}
       */
      _generators: {},

      /**
       * Initializes this gadget by hooking a callback to
       * every red links in the infoboxes with the "translations" class.
       * @param editMode {boolean} Whether the gadget should be loaded in edit or view mode.
       */
      init: function (editMode) {
        this._editMode = !!editMode;
        console.log("Gadget CreerTrad-dev loaded in {0} mode.".format(this._editMode ? "editing" : "viewing"));
        var self = this;

        if (!this._editMode) {
          $(".translations .new").each(function () {
            var $link = $(this);
            var translation = $link.text();

            if (translation) {
              var langCode = $link.parent().attr("lang");
              $link.css("background-color", "#77b5fe");
              $link.attr("title", "Cliquez pour créer «\u00a0{0}\u00a0» avec le gadget".format(translation));
              $link.click(function (event) {
                event.preventDefault();
                self.createTrans(translation, langCode);
              });
            }
          });
        } else {
          this._edit();
        }
      },

      /**
       * Register a generator for the given language.
       * @param langCode {string} Language’s code.
       * @param generator {Function} The generator function.
       */
      registerGeneratorForLanguage: function (langCode, generator) {
        this._generators[langCode] = generator;
      },

      /**
       * Makes a GET request to get the wikicode for the current page.
       * Stores the word, translation and language code for use further down the line.
       * @param translation {string} The word to create.
       * @param lang {string} The word’s language code.
       */
      createTrans: function (translation, lang) {
        this._word = mw.config.get("wgTitle");
        this._translation = translation;
        switch (lang) {
          case "zh-Hant":
            this._langCode = "zh";
            break;
          case "ko-Hani":
            this._langCode = "ko";
            break;
          default:
            this._langCode = lang;
        }

        // Get current article’s wikicode
        $.get(
            mw.config.get("wgServer") + mw.config.get("wgScript"),
            {
              "title": this._word,
              "action": "raw",
            },
            this._generateWikicode.bind(this)
        );
      },

      /**
       * Extracts relevent data to generate translation’s wikicode from the given wikicode.
       * @param wikicode {string} Current article’s wikicode.
       * @private
       */
      _generateWikicode: function (wikicode) {
        var wikicodeLines = wikicode.split("\n");

        var translationLineIndex = 0;
        var translationLine = "";

        // Fetch line where the translation is.
        for (var i = 0; i < wikicodeLines.length && !translationLine; i++) {
          var line = wikicodeLines[i];
          var translationMatch = new RegExp(
              "{{trad(?:\\+|-|--)\\|" + this._langCode + "\\|(?:[^}]*?tradi=)?" + this._translation
          ).exec(line);
          if (translationMatch) {
            translationLineIndex = i;
            translationLine = line;
          }
        }

        if (!translationLine) {
          console.log("{0} could not find trad template for {1}".format(this.NAME, this._translation));
          return;
        }

        var self = this;
        var tradTemplateArgs = $.grep(translationLine.match(/{{trad(?:\+|-|--)\|[^}]+?}}/g), function (m) {
          return m.includes(self._translation);
        })[0];
        var templateArgsArray = $.map(
            tradTemplateArgs.substr(2, tradTemplateArgs.length - 4).split("|"),
            function (s) {
              return s.trim();
            }
        );

        var transcription = "";
        var dif = "";
        var gender = "";

        for (var i2 = 0; i2 < templateArgsArray.length; i2++) {
          var arg = templateArgsArray[i2];
          var m;

          // Get transcription if there is one.
          if (m = /^(?:tr|R)\s*=\s*(.+)$/.exec(arg)) {
            transcription = m[1];
            // Get dif parameter if it is defined.
            // Example : <nowiki>* {{T|he}} : {{trad+|he|מכלב|R=makhlev|dif=מַכְלֵב}}</nowiki>
          } else if (m = /^dif\s*=\s*(.+)$/.exec(arg)) {
            dif = m[1];
            // Get gender if there is one.
          } else if (/^(m|f|n|c|s|p|d|mf|mp|fp|mfp|np|ma|mi|fa|fi|na|ni)$/.test(arg)) {
            gender = arg;
          }
        }

        var sectionLineIndex = 0;
        var nature = "";
        var definitionNumber = [1];
        var definitionNumberFound = false;
        var definitionsLines = [];

        /*
         * We go through each line upwards from the translation until we encounter a level-2 (===) section.
         * This section is the nature of the word.
         * We also gather all encountered definitions and the definition number the translation refers to.
         */
        for (var i3 = translationLineIndex; i3 >= 0 && !nature; i3--) {
          var line2 = wikicodeLines[i3];

          // Fetch enclosing trad-début template to get definition number
          var tradStartTemplateMatch;
          if (!definitionNumberFound && (tradStartTemplateMatch = /{{trad-début\|[^|]*\|([^|}]+)/.exec(line2))) {
            definitionNumber = $.map(
                tradStartTemplateMatch[1].toLowerCase().split("."),
                function (s, i) {
                  s = s.trim();
                  var n = parseInt(s);
                  if (isNaN(n)) {
                    switch (i) {
                      case 0:
                        return NaN;
                      case 1:
                        return /^[a-z]$/.test(s) ? s.charCodeAt(0) - "a".charCodeAt(0) + 1 : NaN;
                      default:
                        return wikt.text.romanNumeralToInt(s);
                    }
                  } else {
                    return n;
                  }
                }
            );
            definitionNumberFound = true;
          }

          // Fetch word type
          var natureMatch;
          if (natureMatch = /^===\s*{{S\|([^|}]+)/.exec(line2)) {
            nature = natureMatch[1];
            sectionLineIndex = i3;
          }
        }

        // Fetch all definitions starting from the line after
        // the word type section line until the next encountered section
        for (var i4 = sectionLineIndex + 1; i4 < translationLineIndex && !/^(=+).+\1$/.test(wikicodeLines[i4]); i4++) {
          var line3 = wikicodeLines[i4];
          var defMatch;
          if ((defMatch = /^(#+)/.exec(line3)) && !/^#+\*/.test(line3)) {
            definitionsLines.push([defMatch[1].length, i4])
          }
        }

        // Recursively fetches the line for definitionNumber
        var getDefinitionLine = function (level, i) {
          var levelCounter = 0;

          for (var i5 = i; i5 < definitionsLines.length; i5++) {
            var item = definitionsLines[i5];
            if (item[0] === level + 1) {
              levelCounter++;
              if (levelCounter === definitionNumber[level]) {
                if (level === definitionNumber.length - 1) {
                  // We reached the end of definitionNumber array, return line number
                  return item[1];
                } else {
                  // Recursively handle the rest of the definitionNumber array
                  return getDefinitionLine(level + 1, i5 + 1);
                }
              }
            }
          }
          return NaN;
        };

        var definitionLineIndex = getDefinitionLine(0, 0) || definitionsLines[0][1];
        var domains = "";

        // We look for a template of the form <nowiki>{{lexique|boulangerie|fr}}</nowiki>.
        var domainMatch;
        if (domainMatch = /{{lexique\|([^}]+?)\|[^|}]+?}}/.exec(wikicodeLines[definitionLineIndex])) {
          domains = domainMatch[1];
        }

        // Wikicode generation.

        var newWikicode = "== {" + "{langue|{0}}} ==\n".format(this._langCode);
        newWikicode += "{" + "{ébauche|{0}}}\n".format(this._langCode);
        newWikicode += "=== {" + "{S|étymologie}} ===\n";
        newWikicode += ": {" + "{ébauche-étym|{0}}}\n\n".format(this._langCode);
        newWikicode += "=== {" + "{S|{0}|{1}}} ===\n".format(nature, this._langCode);

        var generator;
        if (generator = this._generators[this._langCode]) {
          newWikicode += generator(this._translation, nature, gender, transcription, dif).trim();
        } else {
          newWikicode += this._genericGenerator(nature, gender, transcription, dif).trim();
        }

        newWikicode += "\n# ";
        if (domains) {
          newWikicode += "{" + "{lexique|{0}|{1}}} ".format(domains, this._langCode);
        }
        newWikicode += "[[{0}#fr|{1}]].\n".format(this._word, this._word.charAt(0).toUpperCase() + this._word.substring(1));
        newWikicode += "#* {" + "{exemple|lang={0}}}\n\n".format(this._langCode);

        // Get HTML code of translation’s page.
        location.href = mw.config.get("wgServer") + mw.config.get("wgScript")
            + "?title={0}&action=edit&gadget-CreerTrad-content={1}".format(
                encodeURIComponent(this._translation),
                encodeURIComponent(newWikicode)
            );
      },

      /**
       * Replaces the content of the current page by that of the translation’s page in edit mode then loads the
       * generated wikicode in the edit field.
       * @private
       */
      _edit: function () {
        var content = new URL(location.href).searchParams.get("gadget-CreerTrad-content");
        if (content) {
          $("#wpTextbox1").val(content);
          $("#wpSummary").val("Création avec [[Aide:Gadget-CreerTrad|{0} v{1}]].".format(this.NAME, this.VERSION));
        }
      },

      /**
       * Fallback wikicode generator for languages not explicitly supported by the gadget.
       * @param nature {string} Word’s grammatical nature.
       * @param gender {string?} Word’s gender if any.
       * @param transcription {string?} Word’s latin transcription if any.
       * @param dif {string?} Text to show on the in place of the translation.
       * @return {string} The content of the main section.
       * @private
       */
      _genericGenerator: function (nature, gender, transcription, dif) {
        var wikicode = "";

        if (dif) {
          wikicode += "'''{0}'''".format(dif);
        } else {
          wikicode += "'''{0}'''".format(this._translation);
        }

        if (transcription) {
          wikicode += ", ''{0}''".format(transcription);
        }

        wikicode += (" {" + "{pron||{0}}}").format(this._langCode);

        if (nature === "nom" && gender) {
          wikicode += " {{{0}}}".format(gender);
        }

        return wikicode;
      }
    };

    /*
     * Generators registration
     */

    // Catalan/Catalan
    wikt.gadgets.createTranslation.registerGeneratorForLanguage(
        "ca",
        function (translation, nature, gender) {
          var wikicode = "";

          if (nature === "nom") {
            wikicode += "{" + "{ca-rég|<!-- Compléter -->}}\n";
          }

          wikicode += ("'''{0}''' {" + "{pron||ca}}").format(translation);
          if (nature === "nom" && gender) {
            wikicode += " {{{0}}}".format(gender);
          }

          return wikicode;
        }
    );
    // Esperanto/Espéranto
    wikt.gadgets.createTranslation.registerGeneratorForLanguage(
        "eo",
        function (translation, nature) {
          var wikicode = "";

          if (nature === "adjectif" || nature === "nom") {
            wikicode += "{" + "{eo-flexions|<!-- Compléter -->}}\n";
          } else if (nature === "verbe") {
            wikicode += "{" + "{eo-verbe}}\n";
          }

          wikicode += ("'''{0}''' {" + "{pron||eo}}").format(translation);
          if (nature === "verbe") {
            wikicode += " {" + "{valence ?|eo}} {" + "{conjugaison|eo}}";
          }

          return wikicode;
        }
    );
    // Spanish/Espagnol
    wikt.gadgets.createTranslation.registerGeneratorForLanguage(
        "es",
        function (translation, nature, gender) {
          var wikicode = "";

          if (nature === "nom") {
            wikicode += "{" + "{es-rég|<!-- Compléter -->}}\n";
          }

          wikicode += ("'''{0}''' {" + "{pron||es}}").format(translation);
          if (nature === "nom" && gender) {
            wikicode += " {{{0}}}".format(gender);
          }

          return wikicode;
        }
    );
    // Italian/Italien
    wikt.gadgets.createTranslation.registerGeneratorForLanguage(
        "it",
        function (translation, nature, gender) {
          var wikicode = "";

          if (nature === "nom") {
            wikicode += "{" + "{it-flexion|<!-- Compléter -->}}\n";
          }

          wikicode += ("'''{0}''' {" + "{pron||it}}").format(translation);
          if (nature === "nom" && gender) {
            wikicode += " {{{0}}}".format(gender);
          } else {
            wikicode += " {" + "{genre ?|it}}";
          }

          return wikicode;
        }
    );
    // Occitan/Occitan
    wikt.gadgets.createTranslation.registerGeneratorForLanguage(
        "oc",
        function (translation, nature, gender) {
          var wikicode = "";

          if (nature === "adjectif") {
            wikicode += "{" + "{oc-accord-mixte|<!-- Compléter -->}}\n";
          } else if (nature === "nom") {
            wikicode += "{" + "{oc-rég|<!-- Compléter -->}}\n";
          }

          wikicode += ("'''{0}''' {" + "{pron||oc}}").format(translation);
          if (nature === "nom" && gender) {
            wikicode += " {{{0}}}".format(gender);
          }

          return wikicode;
        }
    );
    // Russian/Russe
    wikt.gadgets.createTranslation.registerGeneratorForLanguage(
        "ru",
        function (translation, nature, gender) {
          var wikicode = "";

          if (nature === "nom" && gender) {
            wikicode += "{" + "{ru-décl{0}|<!-- Compléter -->}}\n".format(gender);
          }

          wikicode += ("'''{0}''', ''{" + "{transliterator|ru|{0}}}'' {" + "{pron||ru}}").format(translation);
          if (nature === "nom" && gender) {
            wikicode += " {{{0}}}".format(gender);
          }

          return wikicode;
        }
    );
    // Swedish/Suédois
    wikt.gadgets.createTranslation.registerGeneratorForLanguage(
        "sv",
        function (translation, nature, gender) {
          var wikicode = "";

          if (nature === "adjectif") {
            wikicode += "{" + "{sv-adj}}\n";
          } else if (nature === "nom") {
            if (translation.endsWith("a")) {
              wikicode += "{" + "{sv-nom-c-or}}\n";
            } else if (translation.endsWith("ing")) {
              wikicode += "{" + "{sv-nom-c-ar}}\n";
            } else if (translation.endsWith("are")) {
              wikicode += "{" + "{sv-nom-c-ar|are=}}\n";
            } else if (translation.endsWith("ande")) {
              wikicode += "{" + "{sv-nom-n-n}}\n";
            } else if (translation.endsWith("ende")) {
              wikicode += "{" + "{sv-nom-n-n}}\n";
            } else if (translation.endsWith("um")) {
              wikicode += "{" + "{sv-nom-n-er|um=}}\n";
            } else if (translation.endsWith("tion")) {
              wikicode += "{" + "{sv-nom-c-er}}\n";
            } else if (translation.endsWith("tör")) {
              wikicode += "{" + "{sv-nom-c-er}}\n";
            } else if (translation.endsWith("ier")) {
              wikicode += "{" + "{sv-nom-c-er|r=}}\n";
            } else if (translation.endsWith("iker")) {
              wikicode += "{" + "{sv-nom-c-er|r=}}\n";
            } else if (translation.endsWith("else")) {
              wikicode += "{" + "{sv-nom-c-er|e=}}\n";
            } else if (gender === "neutre") {
              wikicode += "{" + "{sv-nom-n-0}}\n";
            } else {
              wikicode += "{" + "{sv-nom-c-er}}\n";
            }
          } else if (nature === "verbe") {
            wikicode += "{" + "{sv-conj-ar}}\n";
          }

          wikicode += ("'''{0}''' {" + "{pron||sv}}").format(translation);
          if (nature === "nom") {
            if (gender) {
              wikicode += " {{{0}}}".format(gender);
            } else if (translation.endsWith("ande") || translation.endsWith("ende") || translation.endsWith("um")) {
              wikicode += " {" + "{n|sv}}";
            } else {
              wikicode += " {" + "{c|sv}}";
            }
          }

          return wikicode;
        }
    );

    var editMode = ["edit", "submit"].includes(mw.config.get("wgAction"));
    wikt.gadgets.createTranslation.init(editMode);
  }
});