Revue processus inscription (avec parrainage)

This commit is contained in:
Fabrice PENHOËT 2020-08-12 17:08:26 +02:00
parent e417dbb7a5
commit 1c056db3bd
6 changed files with 32 additions and 40 deletions

View File

@ -206,13 +206,13 @@ exports.signup = async (req, res, next) =>
req.body.password=await bcrypt.hash(req.body.password, config.bcryptSaltRounds); req.body.password=await bcrypt.hash(req.body.password, config.bcryptSaltRounds);
const user=await db["User"].create({ ...req.body }, { fields: ["name", "email", "password", "newsletterOk", "GodfatherId", "timeDifference"] }); const user=await db["User"].create({ ...req.body }, { fields: ["name", "email", "password", "newsletterOk", "GodfatherId", "timeDifference"] });
req.body.UserId=user.id; req.body.UserId=user.id;
// l'utilisateur a répondu à un quiz avant de créer son compte. On enregistre ses résultats. // si l'utilisateur a répondu à un quiz avant de créer son compte, on enregistre son résultats.
if(req.body.QuestionnaireId) if(req.body.QuestionnaireId)
{ {
await Promise.all([ await Promise.all([
db["QuestionnaireAccess"].create({ ...req.body }, { fields: ["QuestionnaireId", "UserId"] }), db["QuestionnaireAccess"].create({ ...req.body }, { fields: ["QuestionnaireId", "UserId"] }),
db["Answer"].create({ ...req.body }, { fields: ["nbQuestions", "nbCorrectAnswers", "duration", "QuestionnaireId", "UserId"] }) db["Answer"].create({ ...req.body }, { fields: ["nbQuestions", "nbCorrectAnswers", "duration", "QuestionnaireId", "UserId"] })
]); // pas nécessaire ici de créer le cache, car normalement il sera créé lors du premier appel ]); // pas nécessaire ici de créer le cache JSON, car il sera créé lors de la première connexion au compte.
} }
await sendValidationLink(user); await sendValidationLink(user);
res.status(201).json({ message: txt.mailValidationMessage }); res.status(201).json({ message: txt.mailValidationMessage });
@ -257,7 +257,7 @@ exports.signupValidation = async (req, res, next) =>
EMAIL : config.senderEmail, EMAIL : config.senderEmail,
LINK_URL : config.siteUrl+"/"+configTpl.connectionPage LINK_URL : config.siteUrl+"/"+configTpl.connectionPage
}; };
const mailDatas= const mailDatas =
{ {
mailSubject: txt.mailWelcomeSubject, mailSubject: txt.mailWelcomeSubject,
mailPreheader: txt.mailWelcomeSubject, mailPreheader: txt.mailWelcomeSubject,
@ -463,7 +463,6 @@ exports.checkLoginLink = async (req, res, next) =>
try try
{ {
const db = require("../models/index"); const db = require("../models/index");
console.log(req);
const userDatas= await checkTokenUser(req.body.t); const userDatas= await checkTokenUser(req.body.t);
if(userDatas.User.status!=="user") if(userDatas.User.status!=="user")
res.status(403).json({ errors: [txtGeneral.notAllowed] }); res.status(403).json({ errors: [txtGeneral.notAllowed] });
@ -540,7 +539,6 @@ exports.modify = async (req, res, next) =>
messageRetour.push(txt.updatedNeedUniqueEmail.replace("NEW_EMAIL", req.body.email)); messageRetour.push(txt.updatedNeedUniqueEmail.replace("NEW_EMAIL", req.body.email));
else else
newLogin.email=req.body.email; newLogin.email=req.body.email;
console.log(messageRetour);
} }
} }
if(req.body.newPassword) if(req.body.newPassword)

View File

@ -30,7 +30,7 @@
<div id="prompt" class="cardboard"> <div id="prompt" class="cardboard">
<a href="/" title="Page d'accueil WikLerni"><img src="/themes/wikilerni/img/wikilerni-purple-2-512.png" alt="Logo WikiLerni" title="W I K I L E R N I" /></a> <a href="/" title="Page d'accueil WikLerni"><img src="/themes/wikilerni/img/wikilerni-purple-2-512.png" alt="Logo WikiLerni" title="W I K I L E R N I" /></a>
<p class="cardboard">Cultivons notre jardin !</p> <p class="cardboard">Cultivons notre jardin !</p>
<div id="response" class="error">Si vous voyez ce message, c'est que votre lien de validation n'est pas valide ou a expiré. Vous pouvez <a href="/connexion.html">en recevoir un nouveau en cliquant ici</a>.</div> <div id="response">Si vous voyez ce message, c'est que votre lien de validation n'est pas valide ou a expiré. Vous pouvez <a href="/connexion.html">en recevoir un nouveau en cliquant ici</a>.</div>
</div> </div>
<footer class="cardboard"> <footer class="cardboard">

View File

@ -10,7 +10,7 @@ const lang=availableLangs[0];
const configTemplate = require("../../views/"+theme+"/config/"+lang+".js"); const configTemplate = require("../../views/"+theme+"/config/"+lang+".js");
const configUsers = require("../../config/users"); const configUsers = require("../../config/users");
// Importation des fonctions utile au script : // Importation des fonctions utiles au script :
import { getLocaly, removeLocaly, saveLocaly } from "./tools/clientstorage.js"; import { getLocaly, removeLocaly, saveLocaly } from "./tools/clientstorage.js";
import { addElement } from "./tools/dom.js"; import { addElement } from "./tools/dom.js";
import { helloDev } from "./tools/everywhere.js"; import { helloDev } from "./tools/everywhere.js";
@ -18,7 +18,8 @@ import { getDatasFromInputs, setAttributesToInputs } from "./tools/forms.js";
import { checkAnswerDatas, checkSession, getConfig, getPassword, getTimeDifference } from "./tools/users.js"; import { checkAnswerDatas, checkSession, getConfig, getPassword, getTimeDifference } from "./tools/users.js";
// Dictionnaires : // Dictionnaires :
const txt = require("../../lang/"+lang+"/general"); const txtServerError = require("../../lang/"+lang+"/general").serverError;
const txtNotRequired = require("../../lang/"+lang+"/general").notRequired;
const txtUsers = require("../../lang/"+lang+"/user"); const txtUsers = require("../../lang/"+lang+"/user");
// Principaux éléments du DOM manipulés : // Principaux éléments du DOM manipulés :
@ -41,7 +42,7 @@ const initialise = async () =>
const isConnected=await checkSession(); const isConnected=await checkSession();
if(isConnected) if(isConnected)
{ {
saveLocaly("message", { message: txtUsers.alreadyConnected, color:"information" });// pour l'afficher sur la page suivante saveLocaly("message", { message: txtUsers.alreadyConnected, color:"info" });// pour l'afficher sur la page suivante
const user=getLocaly("user", true); const user=getLocaly("user", true);
const homePage=user.status+"HomePage"; const homePage=user.status+"HomePage";
window.location.assign("/"+configTemplate[homePage]); window.location.assign("/"+configTemplate[homePage]);
@ -54,7 +55,7 @@ const initialise = async () =>
} }
catch(e) catch(e)
{ {
addElement(divResponse, "p", txt.serverError, "", ["error"]); addElement(divResponse, "p", txtServerError, "", ["error"]);
console.error(e); console.error(e);
} }
} }
@ -66,13 +67,13 @@ passwordLink.addEventListener("click", function(e)
e.preventDefault(); e.preventDefault();
passwordInput.type="text"; passwordInput.type="text";
passwordInput.value=getPassword(8, 12); passwordInput.value=getPassword(8, 12);
// copie du mot de passe généré dans le presse-papier // Copie du mot de passe généré dans le "presse-papier" de l'ordinateur :
passwordInput.select(); passwordInput.select();
document.execCommand("copy"); document.execCommand("copy");
addElement(passwordHelp, "div", txtUsers.passwordCopied, "", ["success"]); addElement(passwordHelp, "div", txtUsers.passwordCopied, "", ["success"]);
}); });
// Test si l'e-mail saisi est déjà utilisé pour un compte déjà existant. // Test si l'e-mail saisi est déjà utilisé par un autre compte.
// Si c'est le cas, la validation du formulaire est bloquée. // Si c'est le cas, la validation du formulaire est bloquée.
emailInput.addEventListener("focus", function(e) emailInput.addEventListener("focus", function(e)
{ {
@ -105,11 +106,10 @@ emailInput.addEventListener("blur", function(e)
} }
}); });
// Vérification que le code de parrainage saisi est valide. // Vérification que le code/e-mail de parrainage saisi est valide.
// Si ce n'est pas le cas, cela n'est pas bloquant.
codeGodfatherInput.addEventListener("focus", function(e) codeGodfatherInput.addEventListener("focus", function(e)
{ // on efface l'éventuel message d'erreur si on revient sur le champ pour rectifier le tir { // on efface l'éventuel message d'erreur si on revient sur le champ pour tester un autre code.
addElement(document.getElementById("codeGodfatherMessage"), "i", txt.notRequired); addElement(document.getElementById("codeGodfatherMessage"), "i", txtNotRequired);
}); });
codeGodfatherInput.addEventListener("blur", function(e) codeGodfatherInput.addEventListener("blur", function(e)
{ {
@ -124,7 +124,7 @@ codeGodfatherInput.addEventListener("blur", function(e)
{ {
if (this.status === 204) if (this.status === 204)
addElement(document.getElementById("codeGodfatherMessage"), "div", txtUsers.godfatherNotFound, "", ["error"]); addElement(document.getElementById("codeGodfatherMessage"), "div", txtUsers.godfatherNotFound, "", ["error"]);
else // !! à revoir car cela peut permettre de savoir qu'une adresse e-mail est présente dans le bd else
addElement(document.getElementById("codeGodfatherMessage"), "div", txtUsers.godfatherFound, "", ["success"]); addElement(document.getElementById("codeGodfatherMessage"), "div", txtUsers.godfatherFound, "", ["success"]);
} }
} }
@ -151,18 +151,15 @@ myForm.addEventListener("submit", function(e)
{ {
myForm.style.display="none"; myForm.style.display="none";
addElement(divResponse, "p", response.message, "", ["success"]); addElement(divResponse, "p", response.message, "", ["success"]);
removeLocaly("lastAnswer");// ! important pour ne pas enregister plusieurs fois le résultat removeLocaly("lastAnswer");// ! important pour ne pas enregister plusieurs fois le résultat.
} }
else if (response.errors) else if (response.errors)
{ {
if(Array.isArray(response.errors)) response.errors = response.errors.join("<br>");
response.errors = response.errors.join("<br>");
else
response.errors = txt.serverError;
addElement(divResponse, "p", response.errors, "", ["error"]); addElement(divResponse, "p", response.errors, "", ["error"]);
} }
else else
addElement(divResponse, "p", txt.serverError, "", ["error"]); addElement(divResponse, "p", txtServerError, "", ["error"]);
} }
} }
xhr.setRequestHeader("Content-Type", "application/json"); xhr.setRequestHeader("Content-Type", "application/json");
@ -177,7 +174,7 @@ myForm.addEventListener("submit", function(e)
} }
catch(e) catch(e)
{ {
addElement(divResponse, "p", txt.serverError, "", ["error"]); addElement(divResponse, "p", txtServerError, "", ["error"]);
console.error(e); console.error(e);
} }
}); });

View File

@ -20,7 +20,7 @@ import { getUrlParams } from "./tools/url.js";
import { checkSession } from "./tools/users.js"; import { checkSession } from "./tools/users.js";
// Dictionnaires : // Dictionnaires :
const txt = require("../../lang/"+lang+"/general"); const txtServerError = require("../../lang/"+lang+"/general").serverError;
const txtUsers = require("../../lang/"+lang+"/user"); const txtUsers = require("../../lang/"+lang+"/user");
const divResponse = document.getElementById("response"); const divResponse = document.getElementById("response");
@ -33,9 +33,9 @@ const initialise = async () =>
const isConnected=await checkSession(); const isConnected=await checkSession();
if(isConnected) if(isConnected)
{ {
saveLocaly("message", { message: txtUsers.alreadyConnected, color:"information" }); saveLocaly("message", { message: txtUsers.alreadyConnected, color:"info" });
const user=getLocaly("user", true); const user=getLocaly("user", true);
const homePage=user.status+"HomePage";// lors de la création, seul le statut 'user" est possible const homePage=user.status+"HomePage";// lors de la création d'un compte, seul le statut "user" est possible.
window.location.assign("/"+configTemplate[homePage]); window.location.assign("/"+configTemplate[homePage]);
} }
else else
@ -57,10 +57,7 @@ const initialise = async () =>
} }
else if ((this.status === 200 || this.status === 404) && response.errors != undefined) else if ((this.status === 200 || this.status === 404) && response.errors != undefined)
{ {
if(Array.isArray(response.errors)) response.errors = response.errors.join("<br>");
response.errors = response.errors.join("<br>");
else
response.errors = txt.serverError;
addElement(divResponse, "p", response.errors, "", ["error"]); addElement(divResponse, "p", response.errors, "", ["error"]);
} }
else else
@ -74,7 +71,7 @@ const initialise = async () =>
catch(e) catch(e)
{ {
console.error(e); console.error(e);
addElement(divResponse, "p", txt.serverError, "", ["error"]); addElement(divResponse, "p", txtServerError, "", ["error"]);
} }
} }
initialise(); initialise();

View File

@ -8,7 +8,7 @@ module.exports =
needNotTooLongEmail: "Merci de saisir une adresse e-mail ne comptant pas plus de 255 caractères.", needNotTooLongEmail: "Merci de saisir une adresse e-mail ne comptant pas plus de 255 caractères.",
needPassWord : "Merci de fournir un mot de passe.", needPassWord : "Merci de fournir un mot de passe.",
needLongPassWord : "Merci de fournir un mot de passe d'au moins MIN_LENGTH caractères.", needLongPassWord : "Merci de fournir un mot de passe d'au moins MIN_LENGTH caractères.",
passwordCopied: "Le mot de passe généré a été copié dans votre presse-papier. Vous pouvez le recopier (Ctrl+V) où vous le souhaitez.", passwordCopied: "Le mot de passe généré a été copié dans le presse-papier de votre ordinateur (ou mobile). Vous pouvez le \"coller\" où vous le souhaitez.",
needStatus : "Il manque le statut.", needStatus : "Il manque le statut.",
needLanguage : "Il manque le code langue.", needLanguage : "Il manque le code langue.",
needValidLastConnectionDate : "La date de dernière connexion n'est pas valide.", needValidLastConnectionDate : "La date de dernière connexion n'est pas valide.",
@ -21,23 +21,23 @@ module.exports =
needUGCOk : "Merci d'accepter les CGU pour créer votre compte.", needUGCOk : "Merci d'accepter les CGU pour créer votre compte.",
godfatherNotFound: "Désolé mais aucun utilisateur n'a été trouvé pour ce code/e-mail parrain :(", godfatherNotFound: "Désolé mais aucun utilisateur n'a été trouvé pour ce code/e-mail parrain :(",
godfatherFound: "Votre \"parrain\" a bien été trouvé :)", godfatherFound: "Votre \"parrain\" a bien été trouvé :)",
mailValidationMessage: "Votre inscription est bien enregistrée.\nPour la finaliser, merci de cliquer dans les 24H sur le lien de confirmation qui vient de vous être envoyé par e-mail.", mailValidationMessage: "Votre inscription est bien enregistrée.\nPour la finaliser, merci de cliquer dans les 24 H sur le lien de confirmation qui vient de vous être envoyé par e-mail.",
mailValidationLinkSubject : "Merci de valider votre inscription", mailValidationLinkSubject : "Merci de valider votre inscription",
mailValidationLinkTxt : "Valider mon compte.", mailValidationLinkTxt : "Valider mon compte.",
mailValidationLinkSBodyTxt : "Bonjour USER_NAME,\n\nPour valider votre inscription, merci de cliquer sur le lien suivant dans les 24h :\nLINK_URL", mailValidationLinkSBodyTxt : "Bonjour USER_NAME,\n\nPour valider votre inscription, merci de cliquer sur le lien suivant dans les 24h :\nLINK_URL",
mailValidationLinkSBodyHTML : "<h3>Bonjour USER_NAME,</h3><p>Pour valider votre inscription, merci de cliquer sur le lien ci-dessous dans les 24h.</p>", mailValidationLinkSBodyHTML : "<h3>Bonjour USER_NAME,</h3><p>Pour valider votre inscription, merci de cliquer sur le lien ci-dessous dans les 24h.</p>",
validationMessage: "Votre compte vient bien d'être validé. Merci et bienvenue !<br>Vous pouvez sans tarder vous connecter ci-dessous pour accéder à votre compte.", validationMessage: "Votre compte vient bien d'être validé. Merci et bienvenue !<br>Vous pouvez sans tarder vous connecter ci-dessous pour accéder à votre espace WikiLerni.",
validationMessageAdmin: "Le compte a bien été validé.", validationMessageAdmin: "Le compte a bien été validé.",
validationAlreadyMessage: "Il semble que vous ayez déjà validé votre compte.", validationAlreadyMessage: "Il semble que vous ayez déjà validé votre compte.",
validationAlreadyMessageAdmin: "Ce compte a déjà été validé.", validationAlreadyMessageAdmin: "Ce compte a déjà été validé.",
mailWelcomeSubject : "Bienvenue !", mailWelcomeSubject : "Bienvenue !",
mailWelcomeLinkTxt : "Me connecter à mon compte.", mailWelcomeLinkTxt : "Me connecter à mon compte.",
mailWelcomeBodyTxt : "Bonjour USER_NAME,\n\nVous venez de valider votre inscription à NOM_SITE. Merci et bienvenue !\n\nSi vous avez la moindre question ou suggestion concernant NOM_SITE, n'hésitez pas à me contacter en écrivant à EMAIL.\n\nJe vous conseille d'ailleurs d'ajouter EMAIL à votre carnet d'adresses pour éviter que les prochains envois du site n'arrivent en \"spam\".\n\nPar ailleurs, pour gérer votre abonnement, accéder à vos informations ou encore chercher plus facilement parmi les quizs du site, vous pouvez à tout moment vous connecter à votre compte utilisateur.\n\nPour ce faire, utilisez le lien suivant : LINK_URL\n\nEncore merci et à bientôt.", mailWelcomeBodyTxt : "Bonjour USER_NAME,\n\nVous venez de valider votre inscription à NOM_SITE. Merci et bienvenue !\n\nSi vous avez la moindre question ou suggestion concernant NOM_SITE, n'hésitez pas à me contacter en écrivant à EMAIL.\n\nJe vous conseille d'ailleurs d'ajouter EMAIL à votre carnet d'adresses pour éviter que les prochains envois du site n'arrivent en \"spam\".\n\nPar ailleurs, pour gérer votre abonnement, accéder à vos informations ou encore chercher plus facilement parmi les quizs du site, vous pouvez à tout moment vous connecter à votre compte utilisateur.\n\nPour ce faire, utilisez le lien suivant : LINK_URL\n\nÀ bientôt sur NOM_SITE.",
mailWelcomeBodyHTML : "<h3>Bonjour USER_NAME,</h3><p>Vous venez de valider votre inscription à NOM_SITE. Merci et bienvenue !<br><br>Si vous avez la moindre question ou suggestion concernant NOM_SITE, n'hésitez pas à me contacter en écrivant à <b>EMAIL</b>.<br><br>Je vous conseille d'ailleurs d'ajouter <b>EMAIL</b> à votre carnet d'adresses pour éviter que les prochains envois du site n'arrivent en <i>spam</i>.<br><br>Par ailleurs, pour gérer votre abonnement, accéder à vos informations ou encore chercher plus facilement parmi les quizs du site, vous pouvez à tout moment vous connecter à votre compte utilisateur.<br><br>Pour ce faire, utilisez le lien ci-dessous.<br><br>Encore merci et à bientôt.", mailWelcomeBodyHTML : "<h3>Bonjour USER_NAME,</h3><p>Vous venez de valider votre inscription à NOM_SITE. Merci et bienvenue !<br><br>Si vous avez la moindre question ou suggestion concernant NOM_SITE, n'hésitez pas à me contacter en écrivant à <b>EMAIL</b>.<br><br>Je vous conseille d'ailleurs d'ajouter <b>EMAIL</b> à votre carnet d'adresses pour éviter que les prochains envois du site n'arrivent en <i>spam</i>.<br><br>Par ailleurs, pour gérer votre abonnement, accéder à vos informations ou encore chercher plus facilement parmi les quizs du site, vous pouvez à tout moment vous connecter à votre compte utilisateur.<br><br>Pour ce faire, utilisez le lien ci-dessous.<br><br>À bientôt sur NOM_SITE.",
mailThankGodfatherSubject : "Merci !", mailThankGodfatherSubject : "Merci !",
mailThankGodfatherLinkTxt : "Me connecter à mon compte.", mailThankGodfatherLinkTxt : "Me connecter à mon compte.",
mailThankGodfatherBodyTxt : "Bonjour USER_NAME,\nGrâce à vous un nouvel utilisateur (EMAIL) vient de s'inscrire sur NOM_SITE.\nMerci et à bientôt !", mailThankGodfatherBodyTxt : "Bonjour USER_NAME,\nGrâce à vous, un nouvel utilisateur (EMAIL) vient de s'inscrire sur NOM_SITE.\nSi dans l'avenir cette personne souscrit un abonnement prémium, votre propre abonnement sera prolongé de 30 jours.\nEncore merci et à bientôt !",
mailThankGodfatherBodyHTML : "<h3>Bonjour USER_NAME,</h3><p>Grâce à vous un nouvel utilisateur (EMAIL) vient de s'inscrire sur NOM_SITE.</p><p>Merci et à bientôt !</p>", mailThankGodfatherBodyHTML : "<h3>Bonjour USER_NAME,</h3><p>Grâce à vous, un nouvel utilisateur (EMAIL) vient de s'inscrire sur NOM_SITE.<br>Si dans l'avenir cette personne souscrit un abonnement prémium, votre propre abonnement sera prolongé de 30 jours.</p><p>Encore merci et à bientôt !</p>",
badLinkValidationMessage: "Votre lien de confirmation ne semble pas valide ou bien il a expiré. Vous pouvez en recevoir un nouveau <a href='#URL'>en cliquant ici</a>.", badLinkValidationMessage: "Votre lien de confirmation ne semble pas valide ou bien il a expiré. Vous pouvez en recevoir un nouveau <a href='#URL'>en cliquant ici</a>.",
emailNotFound: "Aucun compte utilisateur n'a été trouvé pour cette adresse e-mail.", emailNotFound: "Aucun compte utilisateur n'a été trouvé pour cette adresse e-mail.",
alreadyConnected: "Vous êtes déjà connecté au site !", alreadyConnected: "Vous êtes déjà connecté au site !",

View File

@ -40,7 +40,7 @@ module.exports =
homeP1: "Avec WikiLerni, vous apprenez chaque jour de nouvelles choses.<br>Des articles de Wikipédia sont sélectionnés pour vous et sont suivis d'un quiz vous permettant de tester ce que vous en avez retenu.<br>De jour en jour de nouvelles graines de savoir sont ainsi semées dans votre \"jardin\".", homeP1: "Avec WikiLerni, vous apprenez chaque jour de nouvelles choses.<br>Des articles de Wikipédia sont sélectionnés pour vous et sont suivis d'un quiz vous permettant de tester ce que vous en avez retenu.<br>De jour en jour de nouvelles graines de savoir sont ainsi semées dans votre \"jardin\".",
homeTitle2: "La culture en liberté", homeTitle2: "La culture en liberté",
homeP2: "Tout comme sur Wikipédia <span class='postscriptum'>(*)</span>, le logiciel et le contenu partagé sur WikiLerni <a href=\"/credits.html\" title=\"En savoir plus\">sont libres</a>.<br>Sur WikiLerni, pas de publicité, ni de commercialisation de vos données personnelles.<br>Vous pouvez venir y \"cultiver votre jardin\" en toute tranquillité.<br><br><span class='postscriptum'>(*) Bien que partageant ses valeurs, WikiLerni est un projet indépendant de la fondation Wikipédia.</span>", homeP2: "Tout comme sur Wikipédia <span class='postscriptum'>(*)</span>, le logiciel et le contenu partagé sur WikiLerni <a href=\"/credits.html\" title=\"En savoir plus\">sont libres</a>.<br>Sur WikiLerni, pas de publicité, ni de commercialisation de vos données personnelles.<br>Vous pouvez venir y \"cultiver votre jardin\" en toute tranquillité.<br><br><span class='postscriptum'>(*) Bien que partageant ses valeurs, WikiLerni est un projet indépendant de la fondation Wikipédia.</span>",
homeBtnAboutTxt: "En savoir plus sur WikiLerni !", homeBtnAboutTxt: "En savoir plus sur WikiLerni ?",
homeBtnSubscribeTxt: "Tester WikiLerni gratuitement.", homeBtnSubscribeTxt: "Tester WikiLerni gratuitement.",
newQuestionnairesTitle: "Les derniers quizs publiés sur WikiLerni", newQuestionnairesTitle: "Les derniers quizs publiés sur WikiLerni",
newQuestionnairesIntro: "Liste des derniers quizs publiés sur WikiLerni.", newQuestionnairesIntro: "Liste des derniers quizs publiés sur WikiLerni.",