Procédures générales
  • appliquer Application d'un schème à une racine, résultat en alphabet latin :
{{ar-appliquer | ar-ma**û*ũ | ar-ktb}}
{{#invoke:arabe| appliquer | scheme = {{{1}}} | racine = {{{2}}} }}

Remplacement des "jokers" du schème par les lettres radicales. Voir {{ar-appliquer}}.

  • arabiser Réécriture dans l'alphabet arabe d'un texte translittéré (obtenu par ar-appliquer ou pas) :
{{ar-abiser | texte }}
{{#invoke:arabe| arabiser | texte = {{{1}}}}}
Utilitaires de vérification

À partir de {{ar-racine/liste}}

  • verifier : utilitaire utilisé dans la documentation des pages "modèle de racine" pour vérifier si les schèmes mentionnés sont connus du système : retourne la liste des schèmes inconnus. Appelé sous forme de #invoke par Modèle:ar-racine/doc (donc, sur tous les modèles de racine) pour vérifier que les modèles de type ar-ktb n'évoquent que des schèmes connus, et donne la liste des inconnus sinon.
Note : Les suffixes en -@ũ puis ceux en -iy²ũ sont réduits en -ũ. Il n'est donc pas nécessaire d'initialiser les formes correspondantes.
{{#invoke:arabe| verifier | racine={{pagename}}}}
  • scheme_connu : utilitaire utilisé dans la documentation des pages "modèle de schème" pour vérifier si le schème est connu du système, à partir de la liste de schèmes. Retourne "oui" si c'est le cas, rien sinon.
Note : Les suffixes en -@ũ puis ceux en -iy²ũ sont réduits en -ũ. Il n'est donc pas nécessaire d'initialiser les formes correspondantes.
{{#invoke:arabe| scheme_connu | scheme={{pagename}}}}
Utilitaires d'affichage
  • ligne : utilitaire d'affichage des mots relevant d'une racine, à partir de la liste de schèmes, appelé par la page de la racine (version simple).
  • ligne2 : utilitaire d'affichage des mots relevant d'une racine, à partir de la liste de schèmes, appelé par la page de documentation du modèle de racine (version tableau).
  • ligne3 : utilitaire d'affichage des formes potentielles d'une racine, à partir de la liste de schèmes, dans la page Modèle:ar-racine/tableau2.
  • ligne4 : utilitaire d'affichage des schèmes connus, à partir de la liste de schèmes, dans la page Annexe:Schèmes arabes.
  • liste_scheme : utilitaire d'affichage des schèmes associés à un shcème, à partir de la liste de schèmes, appelé par la page de documentation du modèle de schème.

local p = {}

local scheme , racine, contexte, modele_racine  = "", "", "", "" -- variables communes aux procédures

-- Translittérations de API / romain / ... vers arabe
local U = mw.ustring.char
local EnArabe = {
     [" "] = " ", -- blancs entre mots
     ["_"] = "", -- underscore ignoré pour décontextualisation éventuelle
[U(0x61B)] = U(0x61B), -- point virgule arabe
     [";"] = U(0x61B),
[U(0x60C)] = U(0x60C), -- virgule inversée
     [","] = U(0x60C),
[U(0x61E)] = U(0x61E), -- trois points
[U(0x61F)] = U(0x61F), -- point d'interrogation
     ["?"] = U(0x61F),
     ["!"] = "!", -- exclamation
[U(0x621)] = U(0x621), -- Hamza
     ["ò"] = U(0x654), --Hamza suscrite
     ["`"] = U(0x621),
     ["'"] = U(0x621),
     ["‘"] = U(0x621),
     ["ʾ"] = U(0x621),
     ["ʼ"] = U(0x621),
     ["ˈ"] = U(0x621),
     ["'"] = U(0x621),
[U(0x671)] = U(0x671), -- Alif wasla
     ["^"] = U(0x671),
[U(0x622)] = U(0x622), -- Alif madda
     ["~"] = U(0x622),
[U(0x623)] = U(0x623), -- Alif hamza
     ["à"] = U(0x623),
[U(0x624)] = U(0x624), -- Waw hamza
     ["ù"] = U(0x624),
[U(0x625)] = U(0x625), -- Alif hamza souscrite
     ["è"] = U(0x625),
[U(0x626)] = U(0x626), -- Ya hamza
     ["ì"] = U(0x626),
[U(0x627)] = U(0x627), -- Alif
     ["A"] = U(0x627),
     ["â"] = U(0x64E)..U(0x627), -- diacritique intégré
     ["ā"] = U(0x64E)..U(0x627), -- diacritique intégré
     ["e"] = U(0x627), -- permet d'écrire "el-"
[U(0x628)] = U(0x628), -- Ba
     ["b"] = U(0x628),
[U(0x629)] = U(0x629), -- Ta marbouta
     ["@"] = U(0x629),
[U(0x62A)] = U(0x62A), -- Té
     ["t"] = U(0x62A),
[U(0x62B)] = U(0x62B), -- Thé
     ["θ"] = U(0x62B),
     ["ṯ"] = U(0x62B),
     ["F"] = U(0x62B),
[U(0x62C)] = U(0x62C), -- Djim
     ["ʒ"] = U(0x62C),
     ["ǧ"] = U(0x62C),
     ["j"] = U(0x62C),
     ["g"] = U(0x62C),
[U(0x62D)] = U(0x62D), -- Ha
     ["ḥ"] = U(0x62D),
     ["ħ"] = U(0x62D),
     ["ḩ"] = U(0x62D),
     ["H"] = U(0x62D),
[U(0x62E)] = U(0x62E), -- Kha
     ["ḵ"] = U(0x62E),
     ["ẖ"] = U(0x62E),
     ["ḫ"] = U(0x62E),
     ["x"] = U(0x62E),
     ["X"] = U(0x62E),
     ["K"] = U(0x62E),
[U(0x62F)] = U(0x62F), -- Dal
     ["d"] = U(0x62F),
[U(0x630)] = U(0x630), -- Dhal
     ["ð"] = U(0x630),
     ["ḏ"] = U(0x630),
     ["V"] = U(0x630),
[U(0x631)] = U(0x631), -- Ra
     ["r"] = U(0x631),
[U(0x632)] = U(0x632), -- Zain
     ["z"] = U(0x632),
[U(0x633)] = U(0x633), -- Sîn
     ["s"] = U(0x633),
[U(0x634)] = U(0x634), -- Chîn
     ["ʃ"] = U(0x634),
     ["š"] = U(0x634),
     ["c"] = U(0x634),
     ["C"] = U(0x634),
[U(0x635)] = U(0x635), -- Çad
     ["ṣ"] = U(0x635),
     ["ş"] = U(0x635),
     ["S"] = U(0x635),
     ["ç"] = U(0x635),
     ["Ç"] = U(0x635),
[U(0x636)] = U(0x636), -- Dad
     ["ḍ"] = U(0x636),
     ["ḑ"] = U(0x636),
     ["D"] = U(0x636),
[U(0x637)] = U(0x637), -- Ta
     ["ṭ"] = U(0x637),
     ["ţ"] = U(0x637),
     ["T"] = U(0x637),
[U(0x638)] = U(0x638), -- Zza
     ["ẓ"] = U(0x638),
     ["Z"] = U(0x638),
[U(0x639)] = U(0x639), -- Rain
     ["ʕ"] = U(0x639),
     ["ʿ"] = U(0x639),
     ["ʻ"] = U(0x639),
     ["3"] = U(0x639),
[U(0x63A)] = U(0x63A), -- Ghain
     ["ɣ"] = U(0x63A),
     ["ḡ"] = U(0x63A),
     ["ğ"] = U(0x63A),
     ["ġ"] = U(0x63A),
     ["g"] = U(0x63A),
     ["R"] = U(0x63A),
[U(0x640)] = U(0x640), -- tiret
     ["-"] = U(0x640),
[U(0x641)] = U(0x641), -- Fa
     ["f"] = U(0x641),
[U(0x642)] = U(0x642), -- Qaf
     ["q"] = U(0x642),
[U(0x643)] = U(0x643), -- Kaf
     ["k"] = U(0x643),
[U(0x644)] = U(0x644), -- Lam
     ["l"] = U(0x644),
[U(0x645)] = U(0x645), -- Mîm
     ["m"] = U(0x645),
[U(0x646)] = U(0x646), -- Noun
     ["n"] = U(0x646),
[U(0x647)] = U(0x647), -- Hé
     ["h"] = U(0x647),
[U(0x648)] = U(0x648), -- Waw
     ["U"] = U(0x648),
     ["w"] = U(0x648),
     ["W"] = U(0x648),
     ["û"] = U(0x64F)..U(0x648), -- préfixage du diacritique
     ["ū"] = U(0x64F)..U(0x648), -- préfixage du diacritique
[U(0x649)] = U(0x649), -- Alif maksoura
     ["é"] = U(0x649),
     ["É"] = U(0x649),
[U(0x64A)] = U(0x64A), -- Waw
     ["I"] = U(0x64A),
     ["y"] = U(0x64A),
     ["Y"] = U(0x64A),
     ["î"] = U(0x650)..U(0x64A),
     ["ī"] = U(0x650)..U(0x64A),
[U(0x64B)] = U(0x64B), -- Fathatan
     ["ã"] = U(0x64B),
[U(0x64C)] = U(0x64C), -- Dammatan
     ["ũ"] = U(0x64C),
     ["õ"] = U(0x64C),
[U(0x64D)] = U(0x64D), -- Kasratan
     ["ĩ"] = U(0x64D),
     ["ñ"] = U(0x64D),
[U(0x64E)] = U(0x64E), -- Fatha
     ["a"] = U(0x64E),
[U(0x64F)] = U(0x64F), -- Damma
     ["u"] = U(0x64F),
[U(0x650)] = U(0x650), -- Damma
     ["i"] = U(0x650),
[U(0x651)] = U(0x651), -- Chadda
     ["²"] = U(0x651),
[U(0x652)] = U(0x652), -- Soukoun
     ["°"] = U(0x652),
[U(0x66D)] = U(0x66D), -- *
     ["*"] = U(0x66D),
[U(0x670)] = U(0x670), -- Alif suscrit
     ["E"] = U(0x670),
-- Lettres additionnelles diverses
     ["p"] = U(0x67E), -- pa
     ["v"] = U(0x06A4), -- ve
     ["B"] = U(0x06A5), -- ve algérien
     ["J"] = U(0x0686), -- tch perse
}

function p.arabiser (frame)
    -- translittération en arabe du paramètre, suivant l'assoc-liste EnArabe.
    local texte = frame.args.texte
    return arabiser_interne(texte)
    end
function arabiser_interne (p1)
    local texte = " " .. p1 .. " "
    -- on rajoute un blanc devant et derrière pour uniformiser les tests de début et fin de mot
    local transcription = ""
    local a_traiter
    -- à faire un jour : transformer tous les ² en redoublements explicites avant traitement
    -- à faire un jour : reporter sur la lettre attendue toutes les lettres équivalentes admissibles
    local diacritiques =( (mw.ustring.find(texte,"a")~=nil) or (mw.ustring.find(texte,"i")~=nil) or (mw.ustring.find(texte,"u")~=nil) or
                                   (mw.ustring.find(texte,"â")~=nil) or (mw.ustring.find(texte,"î")~=nil) or (mw.ustring.find(texte,"û")~=nil) or
                                   (mw.ustring.find(texte,"ã")~=nil) or (mw.ustring.find(texte,"ĩ")~=nil) or (mw.ustring.find(texte,"ũ")~=nil) or
                                   (mw.ustring.find(texte,"°")~=nil) )

    for curseur = 2, mw.ustring.len( texte )-1 do
        a_traiter = mw.ustring.sub( texte, curseur, curseur )

        -- orthographe différente suivant qu'on est en "début" ou en milieu de mot.

        -- début de mot
        if (mw.ustring.sub( texte, curseur-1, curseur-1 ) == " ") -- précédé d'un blanc = début de mot
         -- derrière el- il faut écrire comme en début de mot malgré la liaison :
         -- idem derrière particules inséparables
        or ( (curseur > 2) and (a_traiter ~= "'") and (
           -- Pb de la hamza dans des mots comme bi'r, ne pas traiter comme un préfixe
            (mw.ustring.sub( texte, curseur-3, curseur-1 ) == " el")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == " ^l") -- alif Wasla, marque de liaison
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == " bi")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == " fa")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == " ka")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == " la")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == " li")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == " wa")
           ))
        -- idem si plusieurs particules séparées par un blanc souligné
        or ( (curseur > 2) and (
           (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "_el") 
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "_^l")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "_bi")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "_fa")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "_ka")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "_la")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "_li")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "_wa")
           ))
        -- un blanc souligné permet de couper le mot s'il faut forcer un fa'tu en fa_'tu par exemple
        or ( (curseur > 2) and (
           (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "el_") 
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "^l_") -- alif Wasla, marque de liaison
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "bi_")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "fa_")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "ka_")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "la_")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "li_")
           or (mw.ustring.sub( texte, curseur-3, curseur-1 ) == "wa_")
           ))
        then -- on est en début de mot
            -- Si le début du mot est une voyelle il faut insérer en amont une hamza préfixe
            -- Mais si la structure est a'° ou â'° ou â il faut un alif madda
            local debut = mw.ustring.sub( texte, curseur, curseur+2 )
            if (debut=="a'i") or (debut=="a'î") or (debut=="a'u") or (debut=="a'û") or (debut=="a'a") or (debut=="a'â")
            then -- il y aura superposition d'une hamza instable et d'une hamza structurelle portant voyelle
                transcription = transcription .. U(0x623) .. U(0x64E) -- alif hamza + fatha
            elseif (mw.ustring.sub( texte, curseur, curseur+1 ) == "a'") or (mw.ustring.sub( texte, curseur, curseur+1 ) == "'â") or (a_traiter == "â")
            then
                transcription = transcription .. U(0x622) -- alif madda
            elseif a_traiter == "'" -- hamza explicite en début de mot
            then
                local suivant = mw.ustring.sub( texte, curseur+1, curseur+1 )
                if (suivant == "â")
                then transcription = transcription .. U(0x622) -- alif madda
                elseif (suivant == "a") or (suivant == "u") or (suivant == "û")
                then transcription = transcription .. U(0x623) -- support en haut
                elseif (suivant == "i") or (suivant == "î")
                then transcription = transcription .. U(0x625) -- support en bas
                else transcription = transcription .. U(0x627) -- par défaut, alif
                    end -- la hamza préfixe a été insérée, la voyelle suivante sera transcrite ensuite
            else -- Il faut rajouter la lettre à la transcription.

                -- Mais d'abord si c'est une voyelle, on met une hamza préfixe
                if (a_traiter == "a") or (a_traiter == "u") or (a_traiter == "û")
                then transcription = transcription .. U(0x623) -- support en haut
                elseif (a_traiter == "i") or (a_traiter == "î")
                then transcription = transcription .. U(0x625) -- support en bas
                end -- la hamza préfixe a été insérée

                -- reste à transcrire la lettre
                transcription = transcription .. EnArabe[a_traiter]
            end -- cas hamza préfixe
        -- post-traitement : si la consonne est derrière el- il faut rajouter un chadda aux lettres solaires
        if ((mw.ustring.sub( texte, curseur-1, curseur-1 ) == "l")
        and (mw.ustring.sub( texte, curseur-2, curseur-2 ) == "e" or mw.ustring.sub( texte, curseur-2, curseur-2 ) == "^"))
        then -- faire le test solaire
            if ((a_traiter=="t") or (a_traiter=="F") or (a_traiter=="d") or (a_traiter=="V")
            or (a_traiter=="r") or (a_traiter=="z") or (a_traiter=="s") or (a_traiter=="C")
            or (a_traiter=="S") or (a_traiter=="D") or (a_traiter=="T") or (a_traiter=="Z")
            or (a_traiter=="l") or (a_traiter=="n")) and diacritiques
            then transcription = transcription .. EnArabe["²"] end
        end -- faire le test solaire

        else -- on n'est pas en début de mot

            -- Ne présentent jamais de redoublement :
            
            if (a_traiter == "a") or (a_traiter == "i") or (a_traiter == "u") or (a_traiter == "e") or (a_traiter == "^")
            or (a_traiter == "î")
            or (a_traiter == "A") or (a_traiter == "I") or (a_traiter == "U") or (a_traiter == "E") or (a_traiter == "É") -- voyelles longues forcées sans diacritique
            or (a_traiter == "ĩ") or (a_traiter == "ũ") or (a_traiter == "õ") or (a_traiter == "_")
            then transcription =  transcription .. EnArabe[a_traiter]

            elseif (a_traiter == "é")-- 
            then 
                if (mw.ustring.sub( texte, curseur-1, curseur-1 ) ~= "ã")
                and (mw.ustring.sub( texte, curseur-1, curseur-1 ) ~= "_")
                and (mw.ustring.sub( texte, curseur-1, curseur-1 ) ~= "E")
                and diacritiques
                then transcription =  transcription .. EnArabe["a"]
                end
                transcription =  transcription .. EnArabe[a_traiter]

            elseif (a_traiter == "û")-- cas particulier d'un u final : alif muet
            then -- plus simple de ne pas le mettre.
                transcription =  transcription .. EnArabe[a_traiter]
                -- if (mw.ustring.sub( texte, curseur+1, curseur+1 ) == " ")
                -- then transcription = transcription .. EnArabe["e"] end

            elseif (a_traiter == "~") then
                if diacritiques then transcription =  transcription .. EnArabe["a"] end
                transcription =  transcription .. EnArabe["~"]
            
            -- Traitement des différents cas particuliers dépendants du contexte
            
            elseif (a_traiter == "ã")
            then -- le ã est suivi d'un alif muet, mais pas derrière ât et @ :
                transcription = transcription .. EnArabe[a_traiter]
                if  (mw.ustring.sub( texte, curseur-1, curseur-1 ) == "@")
                or  (mw.ustring.sub( texte, curseur-2, curseur-1 ) == "ât")
                -- ni devant un alif é
                or  (mw.ustring.sub( texte, curseur+1, curseur+1 ) == "é")
                then
                else transcription = transcription ..EnArabe["A"] 
                end
            
            elseif (a_traiter == "â")
            then -- pas de nouvel alif derrière une hammza portée par alif
                if mw.ustring.sub( texte, curseur-1, curseur-1) == "'"
                then
                    local avant = mw.ustring.sub( texte, curseur-2, curseur-2)
                    if avant == "'" then avant = mw.ustring.sub( texte, curseur-3, curseur-3) end
                    if (avant == "i") or (avant == "î") or (avant == "I") or (avant == "y")
                    or (avant == "u") or (avant == "û") or (avant == "w") or (avant == "â")
                    then transcription =  transcription .. EnArabe["â"]
                    end -- sinon : la hamza a déjà inséré un alif madda et on ne fait rien
                else transcription =  transcription .. EnArabe["â"]
                end
            
            elseif (a_traiter == "@")
            then -- ta arbouta : précédé de 'a' implicite, sauf quand derrière une voyelle longue
                if  (mw.ustring.sub( texte, curseur-1, curseur-1 ) ~= "â")
                and (mw.ustring.sub( texte, curseur-1, curseur-1 ) ~= "î")
                and (mw.ustring.sub( texte, curseur-1, curseur-1 ) ~= "û")
                and (mw.ustring.sub( texte, curseur-1, curseur-1 ) ~= "_")
                and diacritiques 
                then transcription = transcription .. EnArabe["a"]
                end
                transcription = transcription .. EnArabe["@"]

            elseif (a_traiter == "é")
            then -- alif maksoura : précédé de 'a' implicite, sauf quand devant un 'ã' ou quand on efface les voyelles
                if  (mw.ustring.sub( texte, curseur+1, curseur+1 ) ~= "ã")
                and (mw.ustring.sub( texte, curseur-1, curseur-1 ) ~= "_")
                then transcription = transcription .. EnArabe["a"]
                end
                transcription = transcription .. EnArabe["é"]
            
            -- Quelques cas où on ne veut pas examiner la présence d'un ²
            elseif (a_traiter == "°") -- Sukun explicite
            then transcription = transcription .. EnArabe["°"]
            elseif (a_traiter == "*") or (a_traiter == ".")
            then transcription = transcription .. EnArabe["*"]
            
            -- Lettre redoublée de la précédente :
            elseif (a_traiter == mw.ustring.sub( texte, curseur-1, curseur-1 )) and (a_traiter ~= "-") and diacritiques
            -- pas de gemmination sur les tirets
            -- Pas de gemmination si on est derrière un el- préfixe (el-lah)
            -- mais dans ce cas le second l est traité comme début de mot : pas cette branche.
            then transcription = transcription .. EnArabe["²"]
            
            elseif (a_traiter == "'") -- hamza
            then -- Hamza : problème du support
                local avant = mw.ustring.sub( texte, curseur-1, curseur-1 )
                local apres = mw.ustring.sub( texte, curseur+1, curseur+1 )

                -- insertion d'un sukun si nécessaire
                if (avant ~= "a") and (avant ~= "e") and (avant ~= "i") and (avant ~= "u")
                and (avant ~= "â") and (avant ~= "î") and (avant ~= "û") and (avant ~= "é")
                and (avant ~= "ã") and (avant ~= "ĩ") and (avant ~= "ñ") and (avant ~= "É")
                and (avant ~= "A") and (avant ~= "I") and (avant ~= "U") and (avant ~= "E")
                and (avant ~= "ñ") and (avant ~= "õ") and (avant ~= "-") and (avant ~= "~") and (avant ~= ",")
                and (avant ~= "é") and (avant ~= "_") and (avant ~= "°")  and (avant ~= "^")  and (avant ~= "?")
                and (mw.ustring.sub( texte, curseur-3, curseur-1 ) ~= " el") -- pas de sukun après el- en début de mot
                and (mw.ustring.sub( texte, curseur-3, curseur-1 ) ~= " ^l") -- cas du alif wasla
                and (mw.ustring.sub( texte, curseur-3, curseur-1 ) ~= "_el") -- pas de sukun après el- en début de mot
                and (mw.ustring.sub( texte, curseur-3, curseur-1 ) ~= "_^l") -- cas du alif wasla
                and diacritiques
                then transcription = transcription .. EnArabe["°"] end

                -- Traitement différent suivant qu'on est en fin de mot ou en milieu :
                if (curseur > mw.ustring.len( texte )-2) or (apres == " ")
                or (
                (mw.ustring.sub( texte, curseur+2, curseur+2 ) == " ")
                -- il ne faut pas de lettre de prolongation non plus
                and (apres~= "â") and (apres~= "î") and (apres~= "û") and (apres~= "é")
                and (apres~= "A") and (apres~= "I") and (apres~= "U") and (apres~= "E")
                )
                then -- hamza en fin de mot
                    if (avant== "i") then transcription = transcription .. EnArabe["ì"]
                    elseif (avant == "u") then transcription = transcription .. EnArabe["ù"]
                    elseif (avant == "a") then transcription = transcription .. EnArabe["à"]
                    else transcription = transcription .. EnArabe["'"]
                    end -- fin de mot
                else -- hamza en milieu de mot
                    if (apres == "'") or (apres == "²") then apres = mw.ustring.sub( texte, curseur+2, curseur+2 ) end

                    -- derrière un i, support ya sans point
                    if (avant== "i") or (avant == "î") or (avant == "I") or (avant == "y")
                    then transcription = transcription .. EnArabe["ì"]
                    -- derrière un waw, hamza en ligne
                    elseif (avant == "û") or (avant == "w")
                    then transcription = transcription .. EnArabe["'"]
                    -- derrière un u faut voir après
                    elseif (avant == "u")
                    then
                        if (apres == "i") or (apres == "î")
                        then transcription = transcription .. EnArabe["ì"]
                        else transcription = transcription .. EnArabe["ù"]
                        end
                    -- derrière un a faut voir après
                    elseif (avant == "a")
                    then
                        if (apres == "i") or (apres == "î")
                        then transcription = transcription .. EnArabe["ì"]
                        elseif (apres == "û") or (apres == "u")
                        then transcription = transcription .. EnArabe["ù"]
                        elseif (apres == "â")
                        then transcription = transcription .. EnArabe["~"] -- madda, et â sera omis
                        -- dans les autres cas, support alif, sauf le cas a' initial déjà traité avec le a initial
                        elseif ( mw.ustring.sub( texte, curseur-2, curseur-2 ) ~= " ")
                        then transcription = transcription .. EnArabe["à"]
                        end
                    -- derrière un â, on risque de trouver une hamza en ligne pour ā’a, ū’a & aw’a 
                    elseif (avant == "â")
                    then -- il y a nécessairement une consonne après
                        if (apres == "i") or (apres == "î")
                        then transcription = transcription .. EnArabe["ì"]
                        elseif (apres == "u")
                        then transcription = transcription .. EnArabe["ù"]
                        else transcription = transcription .. EnArabe["'"] -- en ligne
                        end
                    else -- pas de voyelle avant, donc sukun
                        if (apres == "i") or (apres == "î")
                        then transcription = transcription ..  EnArabe["ì"]
                        elseif (apres == "û") or (apres == "u")
                        then transcription = transcription .. EnArabe["ù"]
                        elseif (apres == "â")
                        then transcription = transcription .. EnArabe["~"]
                        else transcription = transcription ..  EnArabe["à"]
                        end
                    end -- traitement milieu de mot
                end -- fin ou pas
                -- fin du cas de la hamza

            -- Ici il faut isoler le traitement des caractères sur lesquels il n'y aura jamais de sukkun            
            elseif (a_traiter == ",")
            then transcription = transcription .. EnArabe[","]
            elseif (a_traiter == "-")
            then transcription = transcription .. EnArabe["-"]
            elseif (a_traiter == "²")
            then transcription = transcription .. EnArabe["²"]
            elseif (a_traiter == "^")
            then transcription = transcription .. EnArabe["^"]
            elseif (a_traiter == "?")
            then transcription = transcription .. EnArabe["?"]
            else -- dans les autres cas, translittération de la consonne, mais avec sukun éventuel

                local avant = mw.ustring.sub( texte, curseur-1, curseur-1 )
                -- on ne met pas de sukun après...
                if (avant ~= "a") and (avant ~= "e") and (avant ~= "i") and (avant ~= "u")
                and (avant ~= "â") and (avant ~= "î") and (avant ~= "û") and (avant ~= "é")
                and (avant ~= "ã") and (avant ~= "ĩ") and (avant ~= "ñ") and (avant ~= "É")
                and (avant ~= "A") and (avant ~= "I") and (avant ~= "U") and (avant ~= "E")
                and (avant ~= "ñ") and (avant ~= "õ") and (avant ~= "-") and (avant ~= "~")
                and (avant ~= "_") and (avant ~= "°") and (a_traiter~= " ") and (avant~= "^") and (avant~= "?")
                and (mw.ustring.sub( texte, curseur-3, curseur-1 ) ~= " el") -- pas de sukun après el- en début de mot
                and (mw.ustring.sub( texte, curseur-3, curseur-1 ) ~= " ^l") -- pas de sukun sur un alof wasla
                and (mw.ustring.sub( texte, curseur-3, curseur-1 ) ~= "_el") -- pas de sukun après el- en début de mot
                and (mw.ustring.sub( texte, curseur-3, curseur-1 ) ~= "_^l") -- pas de sukun sur un alof wasla
                and (mw.ustring.sub( texte, curseur-3, curseur-1 ) ~= " a'") -- pas de sukun sur un alif madda
                and diacritiques
                then transcription = transcription .. EnArabe["°"] end

                if EnArabe[a_traiter]~=nil then transcription = transcription .. EnArabe[a_traiter] end
                -- cas d'une consonne en fin de mot - rajouter un sukun final
                if (mw.ustring.sub( texte, curseur+1, curseur+1 ) == " ") and diacritiques
                then transcription = transcription .. EnArabe["°"] end
            end

        end
    end -- for - boucle de traitement
    return transcription
end

function est_voyelle (position)
    -- détecte la presence d'une voyelle à cette position.
    -- La voyelle peut être tout ce qui permet à une consonne d'être une initiale de syllabe : courte ou longue, tanwîn, ou ta marbuta
    return (mw.ustring.len(scheme) >= position) and (mw.ustring.find("aeiuâîûãĩũ@ñõ" , mw.ustring.sub( scheme, position, position) )~=nil)
    end
function est_voyelle_courte (position)
    -- détecte la presence d'une voyelle courte à cette position.
    -- comme ci-dessus mais sans les voyelles longues
    return (mw.ustring.len(scheme) >= position) and (mw.ustring.find("aeiuãĩũ@ñõ" , mw.ustring.sub( scheme, position, position) )~=nil)
    end

function nature (position)
    --[[    Renvoit la nature de la lettre  du schème=scheme située à la position=position.
            Ce peut être :
                    (voyelles)
            "vo" = voyelle courte dans une syllable ouverte ;
            "vf" = voyelle courte dans une syllable fermée ;
            "vl" = voyelle longue (dans une syllable longue) ;
                    (consonnes initiales)
            "io" = consonne initiale d'une syllable ouverte ;
            "if" = consonne initiale d'une syllable fermée ;
            "il" = consonne initiale d'une syllable longue ;
                    (consonnes doubles)
            "do" = consonne double, fermant une syllable et debutant une syllable ouverte ;
            "df" = consonne double debutant une syllable fermée ;
            "dl" = consonne double, debutant une syllable longue ;
                    (consonnes de fermeture)
            "fo" = fin de syllable fermée suivie d'une autre consonne ;
            "ff" = fin de syllable fermée et fin de mot (imperatif).
        ]]
        if est_voyelle (position)
        then -- cas voyelle
            if mw.ustring.find("âîû" , mw.ustring.sub( scheme, position, position) )~=nil
            then do return {"v", "l"} end ; -- voyelle longue
            elseif mw.ustring.find("ãĩũ@ñõ", mw.ustring.sub( scheme, position, position)) ~= nil
            then do return {"v", "o"} end ;-- par convention; une consonne précédente sera toujours "ouverte"
            elseif mw.ustring.sub( scheme, position+1, position+1) == ""
            then do return {"v", "o"} end ;                      -- voyelle courte finale donc ouverte
            elseif mw.ustring.sub( scheme, position+2, position+2) == ""
            then do return {"v", "f"} end ;                       -- voyelle courte + consonne finale donc fermée
            elseif est_voyelle (position+2)
            then do return {"v", "o"} end ;                      -- voyelle courte + consonne + voyelle donc ouverte
            else do return {"v", "f"} end ;
            end -- cas voyelle
        else -- cas consonne
            if mw.ustring.sub( scheme, position+1, position+1)=="" then return {"f", "f"} end                                       -- la consonne est la dernière lettre, donc finale fermée
            if (mw.ustring.sub( scheme, position+1, position+1)=="²") or (mw.ustring.sub( scheme, position+1, position+1)==mw.ustring.sub( scheme, position, position))
            then do return {"d" , nature(position+2)[2] } end ;                                 -- consonne double, voir la nature de la voyelle nécessairement présente à pos+2
            elseif  (mw.ustring.sub( scheme, position-1, position-1)==mw.ustring.sub( scheme, position, position))
            then do return {"d" , nature(position+1)[2] } end ;                                  -- 2ème de double, voir la nature de la voyelle nécessairement présente à pos+1
            elseif not(est_voyelle(position-1))
            then do return  {"i" , nature(position+1)[2] } end ;                                  -- 2ème de deux consonnes, idem
            elseif not(est_voyelle(position+1))
            then do return {"f", "o"} end ;                                                                 -- precede de voyelle et suivie de consonne
            else do return {"i", nature(position+1)[2] } end ; 
            end -- consonne
            do return {"?", "?"} end ;
         end
    end

function ProtectedExpandTemplate(frame, scheme, forme)
    -- ExpandTemplate déclenche une erreur si le schème appelé est vide.
    -- permet d'encapsuler cette erreur par le test de pcall.
    local bidon = frame:expandTemplate{ title = "ar-"..scheme, args = {"forme"} }
    end

function p.appliquer( frame ) -- à partir de la librairie standard
    -- les deux paramètres sont aussi des noms de modèles : scheme de la forme ar-ma**u* ; racine de la forme ar-Hmr
    -- le paramètre "var" indique une option, eg la forme du verbe
    scheme , racine, var = mw.ustring.sub(frame.args.scheme,4) , mw.ustring.sub(frame.args.racine, 4), frame.args.var
    return appliquer_interne(scheme, racine, var, frame)
    end
function appliquer_interne(p1, p2, p3, p4) -- Il faut passer par des variables pour que scheme &Cie restent des variables globales au module...
    scheme=p1 ; racine=p2 ; var=p3 ; frame=p4

    if (var == "") -- ne dit rien
    and pcall(ProtectedExpandTemplate, frame, scheme, forme) -- modèle existe?
    then -- essai de récupérer le n° de la forme par le modèle?
        var = frame:expandTemplate{ title = "ar-"..scheme, args = {"forme"} }
        end
    -- Dans les modèles de la forme ar-*a*a*a-i, les deux dernières lettres indiquent conventionnellement la voyelle de l'inaccompli
    -- et doivent être supprimées dans un affichage normal
    if mw.ustring.sub(scheme, -2, -2) == "-"  -- avant-dernière lettre = "-" ?
    then
        scheme = mw.ustring.sub(scheme, 1, -3) -- supprimer les deux dernières, donc limiter au rang -3.
        end
    -- voyelle préfixe mobile éventuelle
    local mobile
    if (mw.ustring.sub(scheme, 3, 3)=="u") or (mw.ustring.sub(scheme, 3, 3)=="û") then mobile= "u" else mobile= "i" end ;
    -- Variables auxilliaires
    local position, contexte ;

    -- Dans le schème, les lettres radicales sont symbolisées par des *, sauf si elles sont répétées, auquel cas elles sont symbolisées par leur numéro d'ordre.
    -- remplacement des étoiles successives par le rang d'ordre des lettres radicales (pour homogénéiser le traitement des verbes irréguliers) si le n° correspondant est absent :
    if mw.ustring.find ( scheme, "1") == nil then scheme = mw.ustring.gsub( scheme, "*", "1", 1) end ;
    if mw.ustring.find ( scheme, "2") == nil then scheme = mw.ustring.gsub( scheme, "*", "2", 1) end ;
    if mw.ustring.find ( scheme, "3") == nil then scheme = mw.ustring.gsub( scheme, "*", "3", 1) end ;
    if mw.ustring.find ( scheme, "4") == nil then scheme = mw.ustring.gsub( scheme, "*", "4", 1) end ;
    -- sauf pour 3, parce que sinon, on a des problèmes si "3" est present comme lettre radicale... donc on remet un caractère jocker.
    scheme = mw.ustring.gsub( scheme, "3", "µ") ;
    -- NB : on présume que les chiffres sont dans l'ordre ; avec ce système, un "schème" de type ar-3a2a1a réalise en fait une inversion des lettres - pas malin, mais bon.
    -- De même, on peut forcer une lettre faible à une autre valeur par exemple ar-mi**â*ũ peut être forcé sur ar-mi*yâ3ũ quand le W doit se transformer en Y.
    -- Les radicales faibles sont w et y. Pour "régulariser" sinon, mettre la radicale faible en majuscule.
    local shemeinit = scheme -- sauvegarde de la valeur primitive

    -- deuxième radicale = creuse?
    if ((var=="(2)") or (var=="(3)") or (var=="(5)") or (var=="(6)") or (var=="(9)")) and (mw.ustring.sub(racine, 2, 2) == "w")  -- ces formes sont régulières, cf Schier p.64. cf Ryding p. 580.
    then racine = mw.ustring.sub(racine,1,1).."W"..mw.ustring.sub(racine,3,3) end ;
    if ((var=="(2)") or (var=="(3)") or (var=="(5)") or (var=="(6)") or (var=="(9)")) and (mw.ustring.sub(racine, 2, 2) == "y")  -- ces formes sont régulières, cf Schier p.64. cf Ryding p. 580.
    then racine = mw.ustring.sub(racine,1,1).."Y"..mw.ustring.sub(racine,3,3) end ;

    -- Sinon, traitement des formes creuses après neutralisation des formes verbales invariables :
    if ((mw.ustring.sub(racine, 2, 2) == "w") or (mw.ustring.sub(racine, 2, 2) == "y"))
    and (scheme ~= "a12aµu") -- invariant, cf Ryding p. 246.
        then
            do -- verbe creux en W, cf Schier p. 71

                position = mw.ustring.find  ( scheme, "2")
                -- La 2ème radicale a pu être forcée à autre chose.
                if position  ~= nil then
                -- contexte de la radicale : quelles sont les voyelles (courtes ou longues) avant et après la consonne 2 :
                if est_voyelle(position-1) then contexte = mw.ustring.sub( scheme, position-1, position-1) .. "2" else contexte = "°2" end ;
                if  (mw.ustring.sub( scheme, position+1, position+1) == "²")
                or (mw.ustring.sub( scheme, position+1, position+1) == mw.ustring.sub( scheme, position, position))
                then
                    contexte = contexte .. "²" ;
                    if est_voyelle(position+2)
                    then contexte = contexte .. mw.ustring.sub( scheme, position+2, position+2)
                    else contexte = contexte .."°"
                    end ;
                else if est_voyelle(position+1)
                then contexte = contexte .. mw.ustring.sub( scheme, position+1, position+1)
                else contexte = contexte .."°" end ;
                end ;

                if contexte == "a2a" and position==3
                then -- la lettre en position +2 est-elle une finale de syllable ?
                        if (nature (position+2)[1] == "f") or (nature (position+2)[1] == "d")
                        then if (mw.ustring.sub(racine, 2, 2) == "w")
                                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "u" .. mw.ustring.sub( scheme, position+2)
                                else scheme=mw.ustring.sub( scheme, 1, position-2) .. "i" .. mw.ustring.sub( scheme, position+2)
                                end
                        else scheme=mw.ustring.sub( scheme, 1, position-2) .. "â" .. mw.ustring.sub( scheme, position+2)
                        end
                elseif contexte == "a2a" and position~=3
                then -- la lettre en position +2 est-elle une finale de syllable ?
                        if (nature (position+2)[1] == "f")
                        then scheme=mw.ustring.sub( scheme, 1, position-2) .. "a" .. mw.ustring.sub( scheme, position+2)
                        else scheme=mw.ustring.sub( scheme, 1, position-2) .. "â" .. mw.ustring.sub( scheme, position+2)
                        end

                -- a2i remplacé par â ou i
                elseif contexte == "a2i"
                then -- la lettre en position +2 est-elle une finale de syllable ?
                        if (nature (position+2)[1] == "f") or (nature (position+2)[1] == "d")
                        then scheme=mw.ustring.sub( scheme, 1, position-2) .. "i" .. mw.ustring.sub( scheme, position+2)
                        else scheme=mw.ustring.sub( scheme, 1, position-2) .. "â" .. mw.ustring.sub( scheme, position+2)
                        end

                -- a2u remplacé par â ou u
                elseif contexte == "a2u"
                then -- la lettre en position +2 est-elle une finale de syllable ?
                        if (nature (position+2)[1] == "f") or (nature (position+2)[1] == "d")
                        then scheme=mw.ustring.sub( scheme, 1, position-2) .. "u" .. mw.ustring.sub( scheme, position+2)
                        else scheme=mw.ustring.sub( scheme, 1, position-2) .. "â" .. mw.ustring.sub( scheme, position+2)
                        end

                -- a2î remplacé par âyi dans ar-*a*î*ũ
                elseif contexte == "a2î"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "âyi" .. mw.ustring.sub( scheme, position+2)

                -- a2²i remplacé par ay²i mais pas dans ar-mu*a2²i*ũ (forme 2 invariable)
                elseif  (contexte == "a2²i") and (scheme ~= "mu1a2²iµũ")
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ay²i" .. mw.ustring.sub( scheme, position+3)

                -- âwi : remplacé par â'i sauf formes verbales 2, 3, 5 et 6 
                elseif (contexte == "â2i")
                then  scheme=mw.ustring.sub( scheme, 1, position-2) .. "â'i" .. mw.ustring.sub( scheme, position+2)

                -- i2° remplacé par î
                elseif (contexte == "i2°")
                then  scheme=mw.ustring.sub( scheme, 1, position-2) .. "î" .. mw.ustring.sub( scheme, position+1)

                -- iwâ remplacé par iyâ
                elseif (contexte == "i2â")
                then  scheme=mw.ustring.sub( scheme, 1, position-2) .. "iyâ" .. mw.ustring.sub( scheme, position+2)

                -- uwi (passif) remplacé par î ou i
                elseif (contexte == "u2i") -- and (mw.ustring.sub(racine, 2, 2) == "w")
                then if (nature (position+2)[1] == "f") or (nature (position+2)[1] == "d")
                        then scheme=mw.ustring.sub( scheme, 1, position-2) .. "i" .. mw.ustring.sub( scheme, position+2)
                        else scheme=mw.ustring.sub( scheme, 1, position-2) .. "î" .. mw.ustring.sub( scheme, position+2)
                        end
                -- uyi (passif) remplacé par î ou u (?) sembler être une erreur
                -- elseif (contexte == "u2i") and (mw.ustring.sub(racine, 2, 2) == "y")
                -- then if (nature (position+2)[1] == "f") or (nature (position+2)[1] == "d")
                --         then scheme=mw.ustring.sub( scheme, 1, position-2) .. "u" .. mw.ustring.sub( scheme, position+2)
                --         else scheme=mw.ustring.sub( scheme, 1, position-2) .. "î" .. mw.ustring.sub( scheme, position+2)
                ---        end

                -- °2a : problème à l'impératif pour toutes ces formes : quand l'impératif se termine par la troisième radicale, celle-ci doit fermer la syllabe, et non ouvrir sur une terminaison.
                elseif (contexte == "°2a" )
                then -- °wa : â si la syllable longue est possible, a sinon
                        local suite = nature (position+2)
                        if (suite[1] == "f") and (suite[2] == "f" )
                        then scheme=mw.ustring.sub( scheme, 1, position-1) .. "a" .. mw.ustring.sub( scheme, position+2)
                        elseif suite[1] == "f"
                        then scheme=mw.ustring.sub( scheme, 1, position-1) .. "a" .. mw.ustring.sub( scheme, position+2)
                        elseif (suite[1] == "d")
                        then scheme=mw.ustring.sub( scheme, 1, position-1) .. "a" .. mw.ustring.sub( scheme, position+2)
                        else scheme=mw.ustring.sub( scheme, 1, position-1) .. "â" .. mw.ustring.sub( scheme, position+2)
                        end

                 -- °2â : â, et w supprimé
                elseif (contexte == "°2â") and (mw.ustring.sub(racine, 2, 2) == "w") -- pas de transformation pour "y"
                then -- distinction entre le nom verbal de la forme (iv) **â*ũ et le pluriel irrégulier a**â*ũ (régulier) & mi**â*ũ régulier
                    if (mw.ustring.sub( scheme, 1, 1) == "a") or (mw.ustring.sub( scheme, 1, 2) == "mi") 
                    then scheme=mw.ustring.sub( scheme, 1, position-1) .. "wâ" .. mw.ustring.sub( scheme, position+2)
                    else scheme=mw.ustring.sub( scheme, 1, position-1) .. "â" .. mw.ustring.sub( scheme, position+2)
                    end

                 -- °2i : î si la syllable longue est possible, i sinon
                elseif (contexte == "°2i")
                then
                        if (nature (position+2)[1] == "f")
                        then scheme=mw.ustring.sub( scheme, 1, position-1) .. "i" .. mw.ustring.sub( scheme, position+2)
                        else scheme=mw.ustring.sub( scheme, 1, position-1) .. "î" .. mw.ustring.sub( scheme, position+2)
                        end

                 -- °2u : û si la syllable longue est possible, u sinon
                elseif (contexte=="°2u") 
                then
                        if (nature (position+2)[1] == "f") or (nature (position+2)[1] == "d")
                        then scheme=mw.ustring.sub( scheme, 1, position-1) .. "u" .. mw.ustring.sub( scheme, position+2)
                        else scheme=mw.ustring.sub( scheme, 1, position-1) .. "û" .. mw.ustring.sub( scheme, position+2)
                        end

                -- °2û remplacé par û ou î (participe passif)
                elseif contexte == "°2û"
                then if (mw.ustring.sub(racine, 2, 2) == "w")
                        then scheme=mw.ustring.sub( scheme, 1, position-1) .. "û" .. mw.ustring.sub( scheme, position+2)
                        else scheme=mw.ustring.sub( scheme, 1, position-1) .. "î" .. mw.ustring.sub( scheme, position+2)
                        end

                elseif (contexte=="°û")
                then scheme=mw.ustring.sub( scheme, 1, position-1) .. "û" .. mw.ustring.sub( scheme, position+2)
                end -- if ... elseif ... else
                -- voiture balai : on remplace tous les "2" par la lettre radicale :
                scheme = mw.ustring.gsub( scheme, "2", mw.ustring.sub(racine, 2, 2))
            end end -- do verbe creux en W

        end ;

    -- première radicale en W
    if (mw.ustring.sub(racine, 1, 1) == "w")    then
        position = mw.ustring.find  ( scheme, "1")
        -- La 1ère radicale a pu être forcée à autre chose.
        if (position  ~= nil) then
            -- première forme, suppression du w dans les formes w2i3, sauf dans les verbes sourds (2=3)
            if (mw.ustring.sub(scheme, position+2, position+2) == "i")  and ( var == "(1)")
            and (mw.ustring.sub(racine, 2, 2) ~= mw.ustring.sub(racine, 3, 3))
            then scheme=mw.ustring.sub( scheme, 1, position-1) .. mw.ustring.sub( scheme, position+1)
            -- huitième forme : iwta2a3 => it²a2a3 : à faire à la main, la forme i*ta*a*a est une "exception régulière"
            end
        end end -- fin verbes assimilés en W

    -- verbe sourd, on supprime la voyelle intercalaire entre 2 et 3 si c'est possible (forme contractée préférentielle) =
    -- * Si la 3 porte un sukkun (la 2 est alors une initiale de syllabe fermée), pas de suppression (forme déployée).
    -- * Si la 3 porte une voyelle courte, la 2 peut porter un sukkun (forme contractée), dans ce cas :
    --    * Si la 1 porte une voyelle on peut supprimer la voyelle (courte et éventuelle) de la 2 ;
    --    * Si la 1 ne porte pas de voyelle on doit y transférer la voyelle courte de la 2.
    --  because of a phonological rule that prevents two identical consonants from being
    -- in sequence with a short vowel between them when they are directly followed by a vowel,
    -- However, if the second identical stem consonant is followed by another consonant,
    -- the identical consonants remain separated
    local position3 = mw.ustring.find  ( scheme, "µ")  ;
    if  (mw.ustring.sub(racine, 2, 2) == mw.ustring.sub(racine, 3, 3)) -- deux consonnes identiques
    and (mw.ustring.sub(racine, 2, 2)~="*") and (mw.ustring.sub(racine, 2, 2)~=".") and (mw.ustring.sub(racine, 2, 2)~="?") -- "lettres" bidon dans les modèles
    and ( position3 ~= nil) -- si un petit malin propose un schème sans position 3 en redoublant la 2...
    then -- on est dans un cas "sourd"
        local position2 = mw.ustring.find  ( scheme, "2")  ;
if position2~=nil then -- sécurité : exclusion du cas des modèles d'exception imposant la deuxième radicale
        local nature2= nature (position2) -- Quelle est la nature de la seconde radicale?

        if (nature2[1]..nature2[2] == "io") -- initiale d'une syllabe ouverte, donc 2 porte une voyelle courte et 3 une voyelle.
        -- contraction sur les verbes (var~=""), formes verbales, ou sur les noms (var=="") dont l'infixe n'est pas de la forme *v*v* (voyelle courte avant la deuxième radicale).
        -- le cas des noms n'est pas très clair, mais on constate que les **v* sont contractés, et certains *v*v* ne le sont pas, on suppose que ce qui apparaissent contractés sont des *v** d'origine (?)
        and (var~="" or (var=="" and mw.ustring.find("aiu" , mw.ustring.sub(scheme, position2-1, position2-1) )==nil ))
        then -- 
            if est_voyelle(position2-1) -- ie, la première radicale est vocalisée
            -- alors on peut supprimer la voyelle de la deuxième radicale
            -- La surdité n'est normalement réalisée que si la voyelle de la première radicale est courte.
            -- On ne peut normalement pas faire suivre une voyelle longue par une consonne avec tchechid (ce qui formerait une super-longue).
            -- Mais c'est une variante d'orthographe. Au besoin, créer un modèle de type ar-*â**a pour imposer la configuration.
            then if est_voyelle_courte (position2-1) then scheme = mw.ustring.sub( scheme, 1, position3-2) .. mw.ustring.sub( scheme, position3) end
            -- sinon on transfère la voyelle de la deuxième radicale sur la première
            else scheme = mw.ustring.sub( scheme, 1, position2-1) .. -- début jusqu'à la deuxième radicale
                mw.ustring.sub( scheme, position3-1, position3-1) .. -- insertion de la voyelle de la seconde radicale
                mw.ustring.sub( scheme, position2, position2) .. -- deuxième radicale
                mw.ustring.sub( scheme, position3) -- et directement la troisième (le signe de redoublement sera inséré lors de la translittération en arabe).
                end
            end
end -- fin exclusion de sécurité.
        end
    -- Cas des formes sourdes à quatre radicales = idem sur 3 et 4
    local position4 = mw.ustring.find  ( scheme, "4")  ;
    if  (mw.ustring.sub(racine, 4, 4) == mw.ustring.sub(racine, 3, 3)) -- deux consonnes identiques
    and (mw.ustring.sub(racine, 4, 4)~="*") and (mw.ustring.sub(racine, 4, 4)~=".") and (mw.ustring.sub(racine, 4, 4)~="?") -- "lettres" bidon dans les modèles
    and ( position4 ~= nil) -- si un petit malin propose un schème sans position 3 en redoublant la 2...
    then -- on est dans un cas "sourd"
        local position3 = mw.ustring.find  ( scheme, "µ")  ;
        local nature3= nature (position3) ;
        if (nature3[1]..nature3[2] == "io") -- initiale d'une syllabe ouverte, donc 3 porte une voyelle courte et 4 une voyelle.
        then -- 
            if est_voyelle(position3-1) -- ie, la deuxième radicale est vocalisée
            -- alors on peut supprimer la troisième radicale
            then if est_voyelle_courte (position2-1) then scheme = mw.ustring.sub( scheme, 1, position4-2) .. mw.ustring.sub( scheme, position4) end
            -- sinon on transfère la voyelle de la troisième radicale sur la deuxième
            else scheme = mw.ustring.sub( scheme, 1, position3-1) .. -- début jusqu'à la troisième radicale
                mw.ustring.sub( scheme, position4-1, position4-1) .. -- insertion de la voyelle de la troisième radicale
                mw.ustring.sub( scheme, position3, position3) .. -- troisième radicale
                mw.ustring.sub( scheme, position4) -- et directement la troisième (le signe de redoublement sera inséré lors de la translittération en arabe).
                end
            end
        end

    -- Inversement, les verbes où la troisième radicale est redoublée dans le schème doivent se conjuguer comme des sourds
    -- ie, si le schème contient un µµ ou un µ² devant une consonne il faut séparer les deux, et boucher le trou avec un "a" pour ne pas avoir trois consonnes d'affilée.
    if (mw.ustring.find ( scheme, "µµ") ~= nil) or  (mw.ustring.find ( scheme, "µ²") ~= nil)
    then
        scheme = mw.ustring.gsub( scheme, "µ²", "µµ", 1) -- homogénéisation des cas
        local position3 = mw.ustring.find  ( scheme, "µµ", 0, true)  ;
        if not (est_voyelle(position3+2)) or (mw.ustring.sub(scheme, position3+2)=="")
        then
            scheme =  mw.ustring.sub( scheme, 1, position3) .. "a" .. mw.ustring.sub( scheme, position3+1)
        end -- est_voyelle.
    end
    scheme = mw.ustring.gsub( scheme, "2", mw.ustring.sub(racine, 2, 2))

    -- Toisième radicale : cas des verbes défectifs
    if (mw.ustring.sub(racine, 3, 3) == "w")
    or (mw.ustring.sub(racine, 3, 3) == "y")
    then -- préparation du contexte
        position = mw.ustring.find  ( scheme, "µ")
        if position  ~= nil -- La 3ème radicale a pu être forcée à autre chose.
        then
            -- contexte de la radicale : quelles sont les voyelles (courtes ou longues) avant et après la consonne 3 :
            if est_voyelle(position-1) then contexte = mw.ustring.sub( scheme, position-1, position-1) .. "3" else contexte = "°3" end ;
            if  (mw.ustring.len(scheme) == position)
            then contexte = contexte -- fin de schème
            elseif  (mw.ustring.sub( scheme, position+1, position+1) == "²")
            or (mw.ustring.sub( scheme, position+1, position+1) == mw.ustring.sub( scheme, position, position))
            then
                contexte = contexte .. "²" ;
                if est_voyelle(position+2)
                then contexte = contexte .. mw.ustring.sub( scheme, position+2, position+2)
                else contexte = contexte .."°"
                end ;
            elseif est_voyelle(position+1)
            then contexte = contexte .. mw.ustring.sub( scheme, position+1, position+1)
            else contexte = contexte .."°"
            end ;

            -- troisième radicale défective en w
            if (mw.ustring.sub(racine, 3, 3) == "w") and ( var == "(1)" or var=="" )
            then -- verbe défectif en W, cf Schier p. 74

                if contexte == "a3a"
                then -- awa final devient â au prétérit de la première forme, é sinon
                    if (position == mw.ustring.len( scheme )-1)
                    then -- position finale
                        if (position ==5) and (mw.ustring.sub( scheme, 2, 2) == "a") -- première forme
                        then scheme=mw.ustring.sub( scheme, 1, position-2) .. "â" .. mw.ustring.sub( scheme, position+2)
                        else scheme=mw.ustring.sub( scheme, 1, position-2) .. "é" .. mw.ustring.sub( scheme, position+2)
                        end
                    else scheme=mw.ustring.sub( scheme, 1, position-2) .. "a" .. mw.ustring.sub( scheme, position+2)
                    end -- test sur première forme

                elseif contexte == "a3â"
                then -- awâ final devient ayâ au passif devant a3âni final
                    if (position == mw.ustring.len( scheme )-3) and (mw.ustring.sub( scheme, position+2, position+3)=="ni")
                    and (var~="") -- les duels ne sont pas concernés.
                    then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ayâ" .. mw.ustring.sub( scheme, position+2)
                    else scheme=mw.ustring.sub( scheme, 1, position-1) .. mw.ustring.sub(racine, 3, 3) .. mw.ustring.sub( scheme, position+1)
                    end

                elseif contexte == "a3@"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "â@" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "a3î"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ay" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "a3u"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "é" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "a3û"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "aw" .. mw.ustring.sub( scheme, position+2)

                elseif (contexte == "a3ũ")
                -- Pb ici, "ã" pour *a*a*ũ, *i*a*ũ et *u*a*ũ, "ãé" sinon. Cf. Palmer §50 p100
                then
                    if (shemeinit =="1a2aµũ") or (shemeinit =="1i2aµũ") or (shemeinit =="1u2aµũ")
                    then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ã"
                    else scheme=mw.ustring.sub( scheme, 1, position-2) .. "ãé"
                    end
                elseif (contexte == "a3ã")
                -- Pb ici, "ã" pour *a*a*ũ, *i*a*ũ et *u*a*ũ, "ãé" sinon. Cf. Palmer §50 p100
                then
                    if (shemeinit =="1a2aµã") or (shemeinit =="1i2aµã") or (shemeinit =="1u2aµã")
                    then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ã"
                    else scheme=mw.ustring.sub( scheme, 1, position-2) .. "ãé"
                    end
                elseif (contexte == "a3ĩ")
                -- Pb ici, "ã" pour *a*a*ũ, *i*a*ũ et *u*a*ũ, "ãé" sinon. Cf. Palmer §50 p100
                then
                    if (shemeinit =="1a2aµĩ") or (shemeinit =="1i2aµĩ") or (shemeinit =="1u2aµĩ")
                    then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ã"
                    else scheme=mw.ustring.sub( scheme, 1, position-2) .. "ãé"
                    end

                elseif contexte == "â3i"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "â'i".. mw.ustring.sub( scheme, position+2)
                -- typiquement -*i*â*iy²ũ doit conserver la hamza de -*i*â*ũ -- en fait, non, dico dixit. -- en fait on peut neutraliser via un W fort.

                elseif contexte == "â3ũ" -- seul cas pratique derrière un â long?
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "â'u" -- diptote dans ce cas

                elseif contexte == "a3°"
                then
                    -- inaccompli passif (2FP, 3FP) en ay
                    -- versus accompli actif en voyelle de l'inaccompli (?) :
                    if (mw.ustring.sub( scheme,  position-3, position-3) == "a") -- on est à l'inaccompli
                    then scheme=mw.ustring.sub( scheme, 1, position-2) .. "aw" .. mw.ustring.sub( scheme, position+1)
                    else scheme=mw.ustring.sub( scheme, 1, position-2) .. "ay" .. mw.ustring.sub( scheme, position+1)
                    end

                elseif contexte == "i3a"
                then  scheme=mw.ustring.sub( scheme, 1, position-2) .. "iya" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3@"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "iy@" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3i"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "i" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3â"
                then  scheme=mw.ustring.sub( scheme, 1, position-2) .. "iyâ" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3î"
                then  scheme=mw.ustring.sub( scheme, 1, position-2) .. "î" .. mw.ustring.sub( scheme, position+2)

                elseif (contexte == "i3ĩ")
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ĩ" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3u"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "iy" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3û"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "û" .. mw.ustring.sub( scheme, position+2)

                elseif (contexte == "i3ũ")
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ĩ" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3°"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "î" .. mw.ustring.sub( scheme, position+1)

                elseif contexte == "u3i"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "i" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "u3î"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "î" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "u3u" -- dépend si c'est en fin de mot
                then
                    if (position == mw.ustring.len( scheme )-1)
                    then scheme=mw.ustring.sub( scheme, 1, position-2) .. "û" .. mw.ustring.sub( scheme, position+2)
                    else scheme=mw.ustring.sub( scheme, 1, position-2) .. "u" .. mw.ustring.sub( scheme, position+2)
                    end

                elseif contexte == "u3û"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "û" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "u3ũ"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ĩ" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "u3" -- en fin de mot
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "u" .. mw.ustring.sub( scheme, position+1)
                elseif contexte == "u3°"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "û" .. mw.ustring.sub( scheme, position+1)

                elseif mw.ustring.sub( scheme, position-1, position-1) == "y" -- cas du diminutif en *u*ay*ũ ou *u*ay*@ũ
                then scheme=mw.ustring.sub( scheme, 1, position-1) .. "y" .. mw.ustring.sub( scheme, position+1)

                elseif contexte == "û3ũ" -- Pb d'écriture
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "uw²ũ" .. mw.ustring.sub( scheme, position+2)

                elseif (contexte == "°3ũ") and (mw.ustring.sub( scheme, position-2, position-2)=="a")
                -- traitement différent de *a*wũ et *u*wũ - bon, enfin, du moins ça marche :-/
                then scheme=mw.ustring.sub( scheme, 1, position-1) .. "wũ" .. mw.ustring.sub( scheme, position+2)
                elseif (contexte == "°3ũ") or (contexte == "°3ĩ")
                then scheme=mw.ustring.sub( scheme, 1, position-1) .. "ã" .. mw.ustring.sub( scheme, position+2)

                elseif (contexte == "°3ã") and (mw.ustring.sub( scheme, position+2)~="é")
                then scheme=mw.ustring.sub( scheme, 1, position-1) .. "ã" .. mw.ustring.sub( scheme, position+2)

                -- la radicale faible disparaît parfois devant @, mais il faut dans ce cas la supprimer à la main.
                end -- fin traitement des cas particuliers en w
          
            else -- verbe défectif en Y, cf Schier p. 74
            -- ou formes dérivées d'un verbe défectif, traité comme un "y"

                if contexte == "a3a"
                then
                    if (position == mw.ustring.len( scheme )-1) -- position finale
                    then scheme=mw.ustring.sub( scheme, 1, position-2) .. "é" .. mw.ustring.sub( scheme, position+2)
                    else scheme=mw.ustring.sub( scheme, 1, position-2) .. "a" .. mw.ustring.sub( scheme, position+2)
                    end

                elseif contexte == "a3â" -- 
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ayâ" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "a3@"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "â@" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "â3@"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ây@" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "a3î"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ay" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "a3u"
                then -- dépend si c'est en fin de mot
                    if (position == mw.ustring.len( scheme )-1)
                    then scheme=mw.ustring.sub( scheme, 1, position-2) .. "é".. mw.ustring.sub( scheme, position+2)
                    else scheme=mw.ustring.sub( scheme, 1, position-2) .. "ay".. mw.ustring.sub( scheme, position+2)
                    end

                elseif contexte == "a3û"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "aw" .. mw.ustring.sub( scheme, position+2)

                elseif (contexte == "a3ũ") or (contexte == "a3ã") or (contexte == "a3ĩ")
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ãé"

                elseif contexte == "â3i"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "â'i".. mw.ustring.sub( scheme, position+2)
                -- typiquement -*i*â*iy²ũ doit conserver la hamza de -*i*â*ũ

                elseif contexte == "â3ũ"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "â'u" -- diptote dans ce cas

                elseif contexte == "a3°" -- ay devant consonne, é en finale
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ay".. mw.ustring.sub( scheme, position+1)

                elseif contexte == "a3"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "i"

                elseif contexte == "i3a"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "iya" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3@"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "iy@" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "î3@"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "îy@" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3â"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "iyâ" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3i"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "i" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3î" -- î
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "î" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3ĩ"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ĩ" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3u" -- dépend si c'est en fin de mot
                then
                    if (position == mw.ustring.len( scheme )-1)
                    then scheme=mw.ustring.sub( scheme, 1, position-2) .. "î" .. mw.ustring.sub( scheme, position+2)
                    else scheme=mw.ustring.sub( scheme, 1, position-2) .. "u" .. mw.ustring.sub( scheme, position+2)
                    end

                elseif contexte == "i3û"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "û" .. mw.ustring.sub( scheme, position+2)

                elseif contexte == "i3ũ"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ĩ"

                elseif contexte == "i3°"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "î" .. mw.ustring.sub( scheme, position+1)

                elseif contexte == "i3" -- en fin de mot
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "i" .. mw.ustring.sub( scheme, position+1)

                elseif contexte == "u3ũ"
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "ĩ" .. mw.ustring.sub( scheme, position+2)

                elseif (contexte == "û3ũ") and (mw.ustring.sub( scheme, 1, 3)=="ma1")
                -- contamination du y sur le û dans la forme ma**û*ũ, cf Wright 1874 §170,
                -- mais la 2 est déjà remplacée dans le schème donc on ne peut pas tester le schème d'origine
                then scheme=mw.ustring.sub( scheme, 1, position-2) .. "iy²ũ" .. mw.ustring.sub( scheme, position+2)

                end -- fin traitement des cas particuliers en y
            end -- verbe défectifs

        end -- 3ème radicale présente
    end ; -- verbes défectifs
    --voiture balai :
    scheme = mw.ustring.gsub( scheme, "µ", mw.ustring.sub(racine, 3, 3)) ;

    -- quatrième radicale éventuelle
    if mw.ustring.sub(racine, 4, 4)== ""
    -- si on applique un schème quadrilittère à une racine à trois consonnes, on redouble simplement la dernière
    then scheme = mw.ustring.gsub ( scheme, "4", mw.ustring.sub(racine, 3, 3)) ;
    else scheme = mw.ustring.gsub ( scheme, "4", mw.ustring.sub(racine, 4, 4)) ;
    end ;

    -- première radicale
    scheme = mw.ustring.gsub( scheme, "1", mw.ustring.sub(racine, 1, 1)) ;

    -- pb : si le schème est en "1°" le "i" prosthétique est virtuel à ce stade :
    -- le cas général "de prolongation" ne marche pas, il faut forcer à la main :
    if (mw.ustring.sub( scheme, 1, 1)== "w") and not(est_voyelle(2))
    then scheme="î" .. mw.ustring.sub( scheme, 2)
    end

    -- Accord des w et y de prolongation en fonction du contexte vocalique (ne concerne pas les W et Y, invariables par principe) :
    while mw.ustring.find( scheme, "iw", 0, true)~= nil do
        position = mw.ustring.find( scheme, "iw", 0, true)
        if est_voyelle(position+2)
        then  scheme=mw.ustring.sub( scheme, 1, position-1) .. "iW" .. mw.ustring.sub( scheme, position+2) -- éviter une boucle infinie
        elseif (mw.ustring.sub( scheme, position+2, position+2)=="²") -- Pb sinon avec les -iw²- qu'il ne faut pas transformer en î², ce qui n'aurait aucun sens...
        then scheme=mw.ustring.sub( scheme, 1, position-1) .. "iY" .. mw.ustring.sub( scheme, position+2)
        else scheme=mw.ustring.sub( scheme, 1, position-1) .. "î" .. mw.ustring.sub( scheme, position+2)
        end
    end
    while mw.ustring.find( scheme, "uy", 0, true)~= nil do
        position = mw.ustring.find( scheme, "uy", 0, true)
        if est_voyelle(position+2)
        then scheme=mw.ustring.sub( scheme, 1, position-1) .. "uY" .. mw.ustring.sub( scheme, position+2)
        else  scheme=mw.ustring.sub( scheme, 1, position-1) .. "û" .. mw.ustring.sub( scheme, position+2)
        end
    end
    while mw.ustring.find( scheme, "wî", 0, true)~= nil do
        position = mw.ustring.find( scheme, "wî", 0, true)
        scheme=mw.ustring.sub( scheme, 1, position-1) .. "yi" .. mw.ustring.sub( scheme, position+2)
    end

    -- nettoyage éventuel : Y et W des verbes réguliers
    scheme = mw.ustring.gsub( scheme, "Y", "y") ;
    scheme = mw.ustring.gsub( scheme, "W", "w") ;

    -- écriture des lettres de prolongations
    while mw.ustring.find( scheme, "ûw", 0, true)~= nil do
        position = mw.ustring.find( scheme, "ûw", 0, true)
        scheme=mw.ustring.sub( scheme, 1, position-1) .. "uw²" .. mw.ustring.sub( scheme, position+2)
    end
    while mw.ustring.find( scheme, "uw", 0, true)~= nil do
        position = mw.ustring.find( scheme, "uw", 0, true)
        if est_voyelle(position+2)
        then scheme=mw.ustring.sub( scheme, 1, position-1) .. "uW" .. mw.ustring.sub( scheme, position+2)
        else  scheme=mw.ustring.sub( scheme, 1, position-1) .. "û" .. mw.ustring.sub( scheme, position+2)
        end
    end
    while mw.ustring.find( scheme, "iy", 0, true)~= nil do
        position = mw.ustring.find( scheme, "iy", 0, true)
        if est_voyelle(position+2) or (mw.ustring.sub( scheme, position+2, position+2)=="²") -- Pb sinon avec les -iy²-
        then scheme=mw.ustring.sub( scheme, 1, position-1) .. "iY" .. mw.ustring.sub( scheme, position+2)
        else  scheme=mw.ustring.sub( scheme, 1, position-1) .. "î" .. mw.ustring.sub( scheme, position+2)
        end
    end
    while mw.ustring.find( scheme, "îy", 0, true)~= nil do
        position = mw.ustring.find( scheme, "îy", 0, true)
        scheme=mw.ustring.sub( scheme, 1, position-1) .. "iy²" .. mw.ustring.sub( scheme, position+2)
    end
    while mw.ustring.find( scheme, "yî", 0, true)~= nil do
        position = mw.ustring.find( scheme, "yî", 0, true)
        if est_voyelle_courte(position-1) -- intercepter des cas comme taXyîTũ => taXYîTũ et pas taXy²iTũ ;
        -- d'autre part des séquences de type âyî restent invariables (pas de redoublement possible après une voyelle longue).
        then scheme=mw.ustring.sub( scheme, 1, position-1) .. "y²i" .. mw.ustring.sub( scheme, position+2)
        else scheme=mw.ustring.sub( scheme, 1, position-1) .. "Yî" .. mw.ustring.sub( scheme, position+2)
        end
    end
    while mw.ustring.find( scheme, "û²", 0, true)~= nil do
        position = mw.ustring.find( scheme, "û²", 0, true)
        scheme=mw.ustring.sub( scheme, 1, position-1) .. "uw²" .. mw.ustring.sub( scheme, position+2)
    end

    -- nettoyage éventuel : Y et W des verbes réguliers
    scheme = mw.ustring.gsub( scheme, "Y", "y") ;
    scheme = mw.ustring.gsub( scheme, "W", "w") ;

    -- ajout d'une voyelle mutable, si le mot commence par deux consonnes :
    if (not ( est_voyelle(1))) and (not ( est_voyelle(2))) 
    -- Consonne en première position et pas de voyelle en deuxième position = il faut rajouter une voyelle préfixe.
    then  scheme = mobile..scheme end ;

    -- ajustement de l'initiale pour les verbes hamzés en 1 : i' se transforme en î et u' en û (une même syllabe ne peut pas être à la fois ouverte et fermée par une hamza)
    if mw.ustring.sub( scheme, 1, 2) == "i'" then
    if est_voyelle(3) then scheme = "iy" .. mw.ustring.sub( scheme, 3) else scheme = "î" .. mw.ustring.sub( scheme, 3) end end
    if mw.ustring.sub( scheme, 1, 2) == "u'" then
    if est_voyelle(3) then scheme = "uw" .. mw.ustring.sub( scheme, 3) else scheme = "û" .. mw.ustring.sub( scheme, 3) end end
    if mw.ustring.sub( scheme, 1, 2) == "a'" then
    if est_voyelle(3) then scheme = "aw" .. mw.ustring.sub( scheme, 3) else scheme = "â" .. mw.ustring.sub( scheme, 3) end end

    -- ajustement pour les verbes assimilés en y
    if mw.ustring.find(scheme, "uy") then
       local position = mw.ustring.find  ( scheme, "uy")
       if not est_voyelle(position+2) then
            scheme = mw.ustring.sub( scheme, 1, position-1) .. "û" .. mw.ustring.sub( scheme, position+2)
            end
       end

    return scheme
    end

function p.squelette( frame )
    -- les deux paramètres sont aussi des noms de modèles : scheme de la forme ar-ma**u* ; racine de la forme ar-Hmr
    -- le paramètre "var" indique une option, eg la forme du verbe
    texte=frame.args.texte ;
    return squelette_interne(texte)
    end
function squelette_interne(texte)
    resultat = "" ;
    index=1 ;
    local alphabet = mw.ustring.char( 0x627, 0x628, 0x629, 0x62A, 0x62B, 0x62C, 0x62D, 0x62E, 0x62F ) ;
    alphabet = alphabet .. mw.ustring.char( 0x630, 0x631, 0x632, 0x633, 0x634, 0x635, 0x636, 0x637 ) ;
    alphabet = alphabet .. mw.ustring.char( 0x638, 0x639, 0x63A, 0x63B, 0x63C, 0x63D, 0x63E, 0x63F ) ;
    alphabet = alphabet .. mw.ustring.char( 0x640, 0x641, 0x642, 0x643, 0x644, 0x645, 0x646, 0x647 ) ;
    alphabet = alphabet .. mw.ustring.char( 0x648, 0x649, 0x64A, 0x20, 0x621 ) ;
    alphabet = alphabet .. mw.ustring.char( 0x67E, 0x06A4, 0x06A5) ; -- quelques lettres additionnelles.
    repeat
        lettre = mw.ustring.sub(texte, index, index) ;
        if (mw.ustring.find(alphabet, lettre)~=nil) then resultat = resultat .. lettre end ;
        -- supports de hamza
        if (lettre == U(0x622)) or (lettre == U(0x623)) or (lettre == U(0x625)) then resultat = resultat .. U(0x627) end ; -- alif
        if (lettre == U(0x624)) then resultat = resultat .. U(0x648) end ; -- waw
        if (lettre == U(0x626)) then resultat = resultat .. U(0x649) end ; -- ya
        index = index+1 ;
        until  index==mw.ustring.len(texte) +1
    return resultat;
    end

-- Ci-dessous  : Fonctions agissant sur la liste des schèmes :
-- Par mesure d'économie, les préfixes en el- et suffixes en -u, -@, -ĩ, -ât, -iy²@, -iy²ât, -âtiy² sont automatiquement déduits des suffixes en -ũ,
-- ils doivent donc être reconstitués (ou réduits) par les fonctions itérant sur les listes.

function p.verifier ( frame )
    -- Un modèle de racine est essentiellement un p-list, donnant (entre autre) une valeur à un index de schème.
    -- La fonction vérifie que la liste de schèmes attachée à une racine ne comporte pas de schème inconnu :
    -- paramètre = nom de page d'un modèle racine de la forme ar-ktb
    -- Utilisée sur la page de documentation des modèles de racines.
    -- La fonction suppose qu'il n'y a qu'une clef par valeur, merci de ne pas faire des valeurs multi-clefs - qui ne seraient pas reconnues... Ha Ha Ha. Seules sont reconnues les clefs individualisées.

    local racine = frame.args.racine                                                                 -- Récupération du nom de la racine.
    local moncode = mw.title.makeTitle( "template", racine):getContent()            -- récupération du texte brut du modèle
    local maliste = mw.title.makeTitle( "template", "ar-racine/liste"):getContent() -- récupération de la liste des schèmes connus

    -- décomposition du modèle racine
    -- positionnement au début du "#switch:"
    local index =  mw.ustring.find(moncode, "#switch:") ;
    -- on saute les premiers items (? utile ?)
    moncode=mw.ustring.sub(moncode, index+14) ;
    local resultat = "" ;

    repeat -- boucle sur chaque item de la p-list
        -- positionnement sur le prochain item : débute par un |
        index = mw.ustring.find(moncode, "|") ;
        if index == nil then break end ; -- fin du modèle, on termine le "repeat".
        -- suppression du fragment jusqu'à | inclusivement (déjà traité) :
        moncode=mw.ustring.sub(moncode, index+1) ;
        -- Le schème est entre le début et le "=" ; positionnement sur le prochain "="
        index = mw.ustring.find(moncode, "=") ;
        if index == nil then break end ;
        scheme=mw.ustring.sub(moncode, 1, index-1)
        scheme= string.gsub(scheme, " ", "")
        if mw.ustring.sub(scheme, 1, 3) == "ar-" -- Si c'est autre chose qu'un "ar-" on ne va pas plus loin dans la p-list :
        then
            index =  mw.ustring.find(maliste, scheme.."}}", 1, true) ;
            if index == nil -- pas trouvé sous sa forme originale, on cherche un dérivé :
                then
                -- Nettoyage du schème : -@ũ, -iy²ũ (et -iy²@ũ) sont réduits à -ũ :
                if mw.ustring.sub(scheme, 0, 5) == "ar-el" then scheme="ar-"..mw.ustring.sub(scheme, 6, mw.ustring.len(scheme)) end ; -- forme définie avec el- préfixé
                if mw.ustring.sub(scheme, -1) == "u" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-1).."ũ" end ; -- forme définie
                if mw.ustring.sub(scheme, -1) == "ĩ" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-1).."ũ" end ; -- forme adverbiale
                if mw.ustring.sub(scheme, -2) == "@ũ" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-2).."ũ" end ;
                if mw.ustring.sub(scheme, -3) == "âtũ" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-3).."ũ" end ;
                if mw.ustring.sub(scheme, -4) == "iy²ũ" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-4).."ũ" end ;
                if mw.ustring.sub(scheme, -3) == "âtũ" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-3).."ũ" end ; -- On peut avoir -âniy²ũ ou -iy²ânũ...
                -- on vérifie que le schème est bien dans la liste connue, encadré par "ar-" au début et "}}" à la fin :
                index =  mw.ustring.find(maliste, scheme.."}}", 1, true) ;
                -- Si pas trouvé, le schème inconnu est ajouté au "resultat" :
                if index == nil then resultat = resultat .. "{{" .. scheme.. "}}" end
                end -- recherche dérivé
            end -- schème en ar-
        until mw.ustring.find(moncode, "=") == nil ;
    return resultat
    end

function p.scheme_connu (frame)
    -- regarde si un schème (ou un de ses dérivés) figure dans la liste de référence. Utilisé sur la page de documentation associée aux modèles de schèmes.
    -- récupération du schème à tester :
    local scheme = frame.args.scheme
    scheme= string.gsub(scheme, " ", "")
    -- récupération de la liste des schèmes connus
    local maliste = mw.title.makeTitle( "template", "ar-racine/liste"):getContent()
    maliste= string.gsub(maliste, " ", "") -- suppression des espaces

    -- test si le schème est dans la liste sous sa propre forme :
    local index = mw.ustring.find(maliste, scheme.."}}", 0, true) ; -- NB : ", 0, true)" sont nécessaires ici pour que le schème ne soit pas interprété comme un "pattern".
    if index ~= nil then return "oui" end ;

    -- test s'il s'agit d'une forme dérivée dont la forme principale est dans la liste :
    if mw.ustring.sub(scheme, 0, 5) == "ar-el" then scheme="ar-"..mw.ustring.sub(scheme, 6, mw.ustring.len(scheme)) end ; -- forme définie avec el- préfixé
    if mw.ustring.sub(scheme, -1) == "u" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-1).."ũ" end ; -- forme définie
    if mw.ustring.sub(scheme, -1) == "ĩ" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-1).."ũ" end ; -- forme adverbiale
    if mw.ustring.sub(scheme, -2) == "@ũ" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-2).."ũ" end ; -- forme en -@
    if mw.ustring.sub(scheme, -3) == "âtũ" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-3).."ũ" end ; -- pluriel d'une forme en -@
    if mw.ustring.sub(scheme, -4) == "iy²ũ" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-4).."ũ" end ; -- adjectif relatif (les -iy²@ ont déjà été réduits en -iy²)
    if mw.ustring.sub(scheme, -3) == "âtũ" then scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-3).."ũ" end ; -- On peut avoir -âtiy²ũ ou -iy²âtũ...
    local index = mw.ustring.find(maliste, scheme.."}}", 0, true) ; -- NB : ", 0, true)" sont nécessaires ici pour que le schème ne soit pas interprété comme un "pattern".
    if index ~= nil then return "oui" end ;

    return ""
    end

function recup_racine (racine)
    -- Récupération et nettoyage des éléments associés à une racine
    modele_racine  = mw.title.makeTitle( "template", racine):getContent() -- récupération du modèle de racine pour avoir sa p-list
    -- Le modèle est une p-list bâtie sur un {{#switch: avec des lignes de la forme | ar-scheme = sens_à_mentionner
    -- Pb : éliminer les lignes vides qui ont quand même une clef
    -- suppression des commentaires :
    while mw.ustring.find(modele_racine, "<!--", 0, true)  do
        local index1 = mw.ustring.find(modele_racine, "<!--", 0, true)
        local index2 = mw.ustring.find(modele_racine, "-->", 0, true)
        modele_racine  = mw.ustring.sub(modele_racine, 0, index1-1) .. mw.ustring.sub(modele_racine, index2+3)
        end -- while
    -- suppression des retour à la ligne remplacés par des blancs (par prudence)
    modele_racine = string.gsub(modele_racine, string.char(10), " ")
    -- on veut pouvoir s'assurer que le schème se termine sur le "=" : suppression des blancs devant et derrière les délimiteurs :
    while mw.ustring.find(modele_racine, " =", 0, true)  do modele_racine = string.gsub(modele_racine, " =", "=") end
    while mw.ustring.find(modele_racine, "= ", 0, true)  do modele_racine = string.gsub(modele_racine, "= ", "=") end
    while mw.ustring.find(modele_racine, " |", 0, true)  do modele_racine = string.gsub(modele_racine, " |", "|") end
    while mw.ustring.find(modele_racine, "| ", 0, true)  do modele_racine = string.gsub(modele_racine, "| ", "|") end
    return modele_racine
    end

function p.ligne (frame)
    -- Appelée comme second paramètre sur l'itérateur ar-racine/liste, pour l'affichage des lignes d'une racine.
    -- La fonction reçoit de l'itérateur pour premier paramètre le modèle de la racine (ar-ktb) et pour second paramètre le nom du modèle de schème (de la forme ar-*a*a*a).
    --Si le schème est cité dans le modèle de racine, afficher la ligne, sinon ne rien afficher.
    -- récupération des arguments :
    local racine, scheme = frame.args[1], frame.args[2]
    scheme= string.gsub(scheme, " ", "") -- suppression des blancs éventuels par sécurité
    racine= string.gsub(racine, " ", "") -- suppression des blancs éventuels par sécurité
    modele_racine = recup_racine(racine)
    local reponse=ligne_affichage(racine, scheme, frame)
    if mw.ustring.sub(scheme, -1) == "ũ" then -- cas nominal = rechercher les suffixes possibles
        scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-1) -- supp du "ũ"
            reponse=reponse..ligne_affichage(racine, scheme.."u", frame)
            reponse=reponse..ligne_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."u", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."ĩ", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."@ũ", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."@u", frame)
            reponse=reponse..ligne_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."@u", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."@ĩ", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."âtũ", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."âtu", frame)
            reponse=reponse..ligne_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."âtu", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."âtĩ", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."iy²ũ", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."iy²u", frame)
            reponse=reponse..ligne_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²u", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."iy²ĩ", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."iy²@ũ", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."iy²@u", frame)
            reponse=reponse..ligne_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²@u", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."iy²@ĩ", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."iy²âtũ", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."iy²âtu", frame)
            reponse=reponse..ligne_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²âtu", frame)
            reponse=reponse..ligne_affichage(racine, scheme.."iy²âtĩ", frame)
        end -- cas nominal
        return reponse
    end
function ligne_affichage (racine, scheme, frame)
    -- Vérification que le schème est dans le modèle de racine :
    local reponse=""
    local index1 = mw.ustring.find(modele_racine, scheme.."=", 0, true) ; -- NB : ", 0, true)" sont nécessaires ici pour que le schème ne soit pas interprété comme un "pattern".
    if index1 ~= nil then -- on affiche
        sens =  mw.ustring.sub(modele_racine, index1) ; -- clipse du début
        index1 = mw.ustring.find(sens, "=", 0, true)
        sens =  mw.ustring.sub(sens, index1+1) ; -- clipse du schème
        index1 = mw.ustring.find(sens, "|", 0, true)
        if index1 ~= nil and index1 ~= 1 then sens =  mw.ustring.sub(sens, 0, index1-1) else sens="" end ; -- clipse de la fin (sans le pipe)
        translittere= appliquer_interne(mw.ustring.sub(scheme,4) , mw.ustring.sub(racine,4),"", frame)
        lexeme = arabiser_interne(translittere)
        if sens ~= "" then reponse =reponse
            -- nouvelle ligne de liste
            ..string.char(10).."* "
            -- lexème arabe mis en forme avec lien
            .."[["..lexeme .."|"..frame:expandTemplate{title='modèle:Lang', args={'ar', lexeme }}.."]]"
            -- translittération (= translittere) mise en forme :
            .." (<small>''[[Wiktionnaire:Conventions/arabe/Translittération|" .. translittere .."]]''</small>)"
            -- sens donné par la racine
            .. " : " .. frame:preprocess(sens) -- preprocess nécessaire pour exécuter les modèles internes.
            end -- sens non vide
        end -- on affiche
    return reponse --pour ne pas avoir une valeur "nil"
    end -- function

function p.ligne2 (frame)
    -- Appelée comme second paramètre sur l'itérateur ar-racine/liste, pour l'affichage des lignes d'un modèle de racine.
    -- La fonction reçoit de l'itérateur pour premier paramètre le modèle de la racine (ar-ktb) et pour second paramètre le nom du modèle de schème (de la forme ar-*a*a*a).
    -- Conventionnellement, si le schème est ar-*a*?*a (premier schème de l'itérateur) il faut générer l'en-tête du tableau ;
    -- Conventionnellement, si le schème est ar-***ũ (dernier schème de l'itérateur) il faut générer la clôture du tableau ;
    --Si le schème est cité dans le modèle de racine, afficher la ligne, sinon ne rien afficher.
    -- récupération des arguments :
    local racine, scheme = frame.args[1], frame.args[2]
    scheme= string.gsub(scheme, " ", "") -- suppression des blancs éventuels par sécurité
    racine= string.gsub(racine, " ", "") -- suppression des blancs éventuels par sécurité
    modele_racine = recup_racine(racine)
    if scheme=="ar-*a*?*a" then do return "{| class="..string.char(34).."wikitable sortable"..string.char(34)..string.char(10).."! Lexème !! Translitt. !! Squelette !! Sens !! Schème !! Nature" end
    elseif scheme=="ar-***ũ" then do return string.char(10).."|}" end
    else -- cas général
        local reponse=ligne2_affichage(racine, scheme, frame)
        if mw.ustring.sub(scheme, -1) == "ũ" then -- cas nominal = rechercher les suffixes possibles
            scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-1) -- supp du "ũ"
            reponse=reponse..ligne2_affichage(racine, scheme.."u", frame)
            reponse=reponse..ligne2_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."u", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."ĩ", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."@ũ", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."@u", frame)
            reponse=reponse..ligne2_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."@u", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."@ĩ", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."âtũ", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."âtu", frame)
            reponse=reponse..ligne2_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."âtu", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."âtĩ", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."iy²ũ", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."iy²u", frame)
            reponse=reponse..ligne2_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²u", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."iy²ĩ", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."iy²@ũ", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."iy²@u", frame)
            reponse=reponse..ligne2_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²@u", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."iy²@ĩ", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."iy²âtũ", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."iy²âtu", frame)
            reponse=reponse..ligne2_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²âtu", frame)
            reponse=reponse..ligne2_affichage(racine, scheme.."iy²âtĩ", frame)
            end -- cas nominal
        return reponse
        end -- cas général
    end
function get_nature(scheme, frame)
    local nature=frame:expandTemplate{title='modèle:'..scheme, args={'nature'}}
    return nature
    end
function ligne2_affichage (racine, scheme, frame)
    -- Vérification que le schème est dans le modèle de racine :
    local reponse=""
    local index1 = mw.ustring.find(modele_racine, scheme.."=", 0, true) ; -- NB : ", 0, true)" sont nécessaires ici pour que le schème ne soit pas interprété comme un "pattern".
    if index1 ~= nil then -- on affiche
        sens =  mw.ustring.sub(modele_racine, index1) ; -- clipse du début
        index1 = mw.ustring.find(sens, "=", 0, true)
        sens =  mw.ustring.sub(sens, index1+1) ; -- clipse du schème
        index1 = mw.ustring.find(sens, "|", 0, true)
        if index1 ~= nil and index1 ~= 1 then sens =  mw.ustring.sub(sens, 0, index1-1) else sens="" end ; -- clipse de la fin (sans le pipe)
        translittere= appliquer_interne(mw.ustring.sub(scheme,4) , mw.ustring.sub(racine,4),"", frame)
        lexeme = arabiser_interne(translittere)
        squelette = squelette_interne(lexeme)
        local existe, naturescheme = pcall(get_nature, scheme, frame)
        if not(existe) then naturescheme="[[modèle:"..scheme.."]]" end
        if (sens ~="") then reponse =reponse
            -- nouvelle ligne de tableau
            ..string.char(10).."|-"..string.char(10)
            -- lexème arabe mis en forme avec lien
            .."| align="..string.char(34).."right"..string.char(34).."| [["..lexeme .."|"..frame:expandTemplate{title='modèle:Lang', args={'ar', lexeme }}.."]] "
            -- translittération (= translittere) mise en forme :
            .." || .(<small>''[[Wiktionnaire:Conventions/arabe/Translittération|" .. translittere .."]]''</small>)."
            -- squelette mis en forme avec lien :
            .."|| align="..string.char(34).."right"..string.char(34).."| [[".. squelette .."|"..frame:expandTemplate{title='modèle:Lang', args={'ar', squelette }}.."]] "
            -- sens donné par la racine
            .. " || " ..  frame:preprocess(sens) -- preprocess nécessaire pour exécuter les modèles internes.
            -- Schème associé
            .."|| "..frame:expandTemplate{title='modèle:ar-sch', args={scheme}}
            -- Nature
            .."|| ".. naturescheme
            end -- sens non vide
        end -- on affiche
    return reponse --pour ne pas avoir une valeur "nil"
    end -- function

function p.ligne3 (frame)
    -- Appelée comme second paramètre sur l'itérateur ar-racine/liste, pour l'affichage des formes possibles à partir d'une racine (donne donc la liste des schèmes connus).
    -- La fonction reçoit de l'itérateur pour premier paramètre le modèle de la racine (ar-ktb) et pour second paramètre le nom du modèle de schème (de la forme ar-*a*a*a).
    -- Conventionnellement, si le schème est ar-*a*?*a (premier schème de l'itérateur) il faut générer l'en-tête du tableau ;
    -- Conventionnellement, si le schème est ar-***ũ (dernier schème de l'itérateur) il faut générer la clôture du tableau ;
    --Si la catégorie du schème n'est pas vide, afficher la ligne, sinon ne rien afficher.
    -- récupération des arguments :
    local racine, scheme = frame.args[1], frame.args[2]
    scheme= string.gsub(scheme, " ", "") -- suppression des blancs éventuels par sécurité
    racine= string.gsub(racine, " ", "") -- suppression des blancs éventuels par sécurité
    modele_racine = recup_racine(racine)
    if scheme=="ar-*a*?*a" then do return "{| class="..string.char(34).."wikitable sortable"..string.char(34)..string.char(10).."! Modèle !! # !! Forme !! Forme (trans) !! sens " end
    elseif scheme=="ar-***ũ" then do return string.char(10).."|}" end
    else -- cas général
        local reponse=ligne3_affichage(racine, scheme, frame)
        if mw.ustring.sub(scheme, -1) == "ũ" then -- cas nominal = rechercher les suffixes possibles
            scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-1) -- supp du "ũ"
            reponse=reponse..ligne3_affichage(racine, scheme.."u", frame)
            reponse=reponse..ligne3_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."u", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."ĩ", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."@ũ", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."@u", frame)
            reponse=reponse..ligne3_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."@u", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."@ĩ", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."âtũ", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."âtu", frame)
            reponse=reponse..ligne3_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."âtu", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."âtĩ", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."iy²ũ", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."iy²u", frame)
            reponse=reponse..ligne3_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²u", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."iy²ĩ", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."iy²@ũ", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."iy²@u", frame)
            reponse=reponse..ligne3_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²@u", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."iy²@ĩ", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."iy²âtũ", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."iy²âtu", frame)
            reponse=reponse..ligne3_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²âtu", frame)
            reponse=reponse..ligne3_affichage(racine, scheme.."iy²âtĩ", frame)
            end -- cas nominal
        return reponse
        end -- cas général
    end
function get_sens(scheme, frame)
    local sens =frame:expandTemplate{title=scheme, args={'sens'}}
    return sens
    end
function ligne3_affichage (racine, scheme, frame)
    -- Vérification que la catégorie du schème n'est pas vide :
    local reponse=""
    local existe, sens = pcall(get_sens, scheme, frame)
    if existe then -- on affiche (le "nombre" est une chaîne de caractères...)
        Nb = frame:callParserFunction{ name="PAGESINCATEGORY", args={scheme} }
        if Nb ~= "0" then
            terme = appliquer_interne(mw.ustring.sub(scheme,4) , mw.ustring.sub(racine,4),"", frame)
            lexeme = arabiser_interne(terme)
            reponse =reponse
            -- nouvelle ligne de tableau
            ..string.char(10).."|-" .. string.char(10)
            -- nom du modèle
            .. "| [[modèle:" .. scheme .. "|" .. mw.ustring.sub(scheme, 3, mw.ustring.len(scheme)) .. "]]"
            -- pages dans la catégorie
            .. "||style="..string.char(34).."text-align: center;"..string.char(34).."| ".. Nb
            -- application du schème à la racine
 	        .. "||style="..string.char(34).."text-align: right;"..string.char(34).."| ".. "[["..lexeme .."|"..frame:expandTemplate{title='modèle:Lang', args={'ar', lexeme }}.."]]"
            -- translittéré et délimité
            .. "|| ." .. terme
            -- sens du schème
            .. "|| " .. sens
            end -- cat non vide
        end -- on affiche
    return reponse --pour ne pas avoir une valeur "nil"
    end -- function

function p.ligne4 (frame)
    -- Appelée pour établir la liste des schèmes connus (pour lesquels il y a des exemples).
    -- paramètre 2 = schème à afficher.
    --Si la catégorie du schème n'est pas vide, afficher la ligne, sinon ne rien afficher.
    -- récupération des arguments :
    local racine, scheme = frame.args[1], frame.args[2]
    scheme= string.gsub(scheme, " ", "") -- suppression des blancs éventuels par sécurité
    racine= string.gsub(racine, " ", "") -- suppression des blancs éventuels par sécurité
    if scheme=="ar-*a*?*a" then do return "{| class="..string.char(34).."wikitable sortable"..string.char(34)..string.char(10).."! # !! Modèle !! P !! I !! S !! Type !! sens " end
    elseif scheme=="ar-***ũ" then do return string.char(10).."|}" end
    else -- cas général
        local reponse=ligne4_affichage(racine, scheme, frame)
        if mw.ustring.sub(scheme, -1) == "ũ" then -- cas nominal = rechercher les suffixes possibles
            scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-1) -- supp du "ũ"
            reponse=reponse..ligne4_affichage(racine, scheme.."u", frame)
            reponse=reponse..ligne4_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."u", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."ĩ", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."@ũ", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."@u", frame)
            reponse=reponse..ligne4_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."@u", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."@ĩ", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."âtũ", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."âtu", frame)
            reponse=reponse..ligne4_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."âtu", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."âtĩ", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."iy²ũ", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."iy²u", frame)
            reponse=reponse..ligne4_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²u", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."iy²ĩ", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."iy²@ũ", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."iy²@u", frame)
            reponse=reponse..ligne4_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²@u", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."iy²@ĩ", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."iy²âtũ", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."iy²âtu", frame)
            reponse=reponse..ligne4_affichage(racine, "ar-el"..mw.ustring.sub(scheme, 4, mw.ustring.len(scheme)).."iy²âtu", frame)
            reponse=reponse..ligne4_affichage(racine, scheme.."iy²âtĩ", frame)
            end -- cas nominal
        return reponse
        end -- cas général
    end
function ligne4_affichage (racine, scheme, frame)
    -- Vérification que la catégorie du schème n'est pas vide :
    local reponse=""
    local existe, sens = pcall(get_sens, scheme, frame)
    if existe then -- on affiche (le "nombre" est une chaîne de caractères...)
    local type = frame:expandTemplate{title=scheme, args={'type'}}
        Nb = frame:callParserFunction{ name="PAGESINCATEGORY", args={scheme} }
        if Nb ~= "0" then
            local prefixe, infixe, suffixe = "", "", ""
            -- Récupération d'une image du scheme avec que des "*" pour caler les découpages
            scheme1=scheme
            while mw.ustring.find(scheme1, "1", 1, true)~= nil do scheme1 =  mw.ustring.gsub(scheme1, "1", "*") end
            while mw.ustring.find(scheme1, "2", 1, true)~= nil do scheme1 =  mw.ustring.gsub(scheme1, "2", "*") end
            while mw.ustring.find(scheme1, "3", 1, true)~= nil do scheme1 =  mw.ustring.gsub(scheme1, "3", "*") end
            while mw.ustring.find(scheme1, "4", 1, true)~= nil do scheme1 =  mw.ustring.gsub(scheme1, "4", "*") end
            while mw.ustring.find(scheme1, "t²", 1, true)~= nil do scheme1 =  mw.ustring.gsub(scheme1, "t²", "*²") end
            if mw.ustring.find(scheme1, "*", 1, true)~=nil then
                prefixe = mw.ustring.sub(scheme, 4,  mw.ustring.find(scheme1, "*", 1, true)-1)
                infixe=mw.ustring.sub(scheme, mw.ustring.find(scheme1, "*", 1, true), mw.ustring.len(scheme))
                suffixe=mw.ustring.sub(scheme, mw.ustring.find(scheme1, "*", 1, true), mw.ustring.len(scheme))
                suffixe1=mw.ustring.sub(scheme1, mw.ustring.find(scheme1, "*", 1, true), mw.ustring.len(scheme))
                -- suppression de l'infixe = tant qu'il y a des "*"
                while mw.ustring.find(suffixe1, "*", 1, true)~=nil do
                    suffixe = mw.ustring.sub(suffixe, mw.ustring.find(suffixe1, "*", 1, true)+1, mw.ustring.len(suffixe1))
                    suffixe1 = mw.ustring.sub(suffixe1, mw.ustring.find(suffixe1, "*", 1, true)+1, mw.ustring.len(suffixe1))
                    end
                -- recalage de l'infixe à la bonne longueur :
                infixe=mw.ustring.sub(infixe, 1, mw.ustring.len(infixe)-mw.ustring.len(suffixe))
                end
            reponse =reponse
            -- nouvelle ligne de tableau
            ..string.char(10).."|-" .. string.char(10)
            -- pages dans la catégorie
            .. "|style="..string.char(34).."text-align: center;"..string.char(34).."| [[:catégorie:"..scheme.."|("..Nb..")]]"
            -- nom du modèle
            .. "|| [[modèle:" .. scheme .. "|" .. mw.ustring.sub(scheme, 3, mw.ustring.len(scheme)) .. "]]"
            -- décomposition
            .. string.char(10).."|style="..string.char(34).."text-align: right;"..string.char(34).." | " .. prefixe
            .. string.char(10).."|style="..string.char(34).."text-align: center;"..string.char(34).." | " .. infixe
            .. string.char(10).."|style="..string.char(34).."text-align: left;"..string.char(34).." | " .. suffixe
            -- typedu schème
            .. "|| " .. type
            -- sens du schème
            .. "|| " .. sens
            end -- cat non vide
        end -- on affiche
    return reponse --pour ne pas avoir une valeur "nil"
    end -- function

function p.liste_scheme (frame)
    -- Appelée comme second paramètre sur l'itérateur ar-racine/liste, pour l'affichage des schèmes associés à un modèle de schème.
    -- La fonction reçoit de l'itérateur pour premier paramètre le modèle du modèle (ar-*a*u*a) et pour second paramètre le nom du modèle de schème (de la forme ar-*a*a*a).
    -- Si le schème est cité dans le modèle de racine, afficher la ligne, sinon ne rien afficher.
    -- récupération des arguments :
    local modele, scheme = frame.args[1], frame.args[2]
    scheme= string.gsub(scheme, " ", "") -- suppression des blancs éventuels par sécurité
    modele_racine = recup_racine(modele) -- même problématique de nettoyage, en fait
    local reponse=liste_scheme_affichage (racine, scheme, frame)
    if mw.ustring.sub(scheme, -1) == "ũ" then -- cas nominal = rechercher les suffixes possibles
        scheme=mw.ustring.sub(scheme, 0, mw.ustring.len(scheme)-1) -- supp du "ũ"
            reponse=reponse..liste_scheme_affichage (racine, scheme.."u", frame)
            reponse=reponse..liste_scheme_affichage (racine, "el"..scheme.."u", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."ĩ", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."@ũ", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."@u", frame)
            reponse=reponse..liste_scheme_affichage (racine, "el"..scheme.."@u", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."@ĩ", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."âtũ", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."âtu", frame)
            reponse=reponse..liste_scheme_affichage (racine, "el"..scheme.."âtu", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."âtĩ", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."iy²ũ", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."iy²u", frame)
            reponse=reponse..liste_scheme_affichage (racine, "el"..scheme.."iy²u", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."iy²ĩ", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."iy²@ũ", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."iy²@u", frame)
            reponse=reponse..liste_scheme_affichage (racine, "el"..scheme.."iy²@u", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."iy²@ĩ", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."iy²âtũ", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."iy²âtu", frame)
            reponse=reponse..liste_scheme_affichage (racine, "el"..scheme.."iy²âtu", frame)
            reponse=reponse..liste_scheme_affichage (racine, scheme.."iy²âtĩ", frame)
        end -- cas nominal
    return reponse
    end

function liste_scheme_affichage (racine, scheme, frame)
    -- Vérification que le schème est dans le modèle de racine :
    local reponse=""
    local index1 = mw.ustring.find(modele_racine, scheme.."=", 0, true) ; -- NB : ", 0, true)" sont nécessaires ici pour que le schème ne soit pas interprété comme un "pattern".
    if index1 ~= nil then -- on affiche
        sens =  mw.ustring.sub(modele_racine, index1) ; -- clipse du début
        index1 = mw.ustring.find(sens, "=", 0, true)
        sens =  mw.ustring.sub(sens, index1+1) ; -- clipse du schème
        index1 = mw.ustring.find(sens, "|", 0, true)
        if index1 ~= nil and index1 ~= 1 then sens =  mw.ustring.sub(sens, 0, index1-1) else sens="" end ; -- clipse de la fin (sans le pipe)
        if sens ~= "" then
            if mw.ustring.sub(sens, 0, 3)=="ar-" then sens = "{{modl|"..sens.."}}" end
            reponse =reponse
            ..string.char(10).."* "
            -- sens donné par la racine
            .. frame:preprocess(sens) -- preprocess nécessaire pour exécuter les modèles internes.
            -- Schème associé
            .." : "..frame:expandTemplate{title='modèle:modl', args={scheme}}
            end -- sens non vide
        end -- on affiche
    return reponse --pour ne pas avoir une valeur "nil"
    end -- function

return p