diff --git a/DEVELOPERS_MANUAL.md b/DEVELOPERS_MANUAL.md
index 476d5f4a..89bf5a55 100644
--- a/DEVELOPERS_MANUAL.md
+++ b/DEVELOPERS_MANUAL.md
@@ -62,6 +62,8 @@ With a look at [Building-Block View](https://github.com/StefanSchubert/sabi/wiki
YOUR_API_KEY
+* If you work with IntelliJ: Install the "Jakarta Server Faces (JSF)" Plugin
+
#### Prepare your local docker environment
Do some maven builds in the following order:
diff --git a/captcha/pom.xml b/captcha/pom.xml
index 7246197f..c53c2704 100644
--- a/captcha/pom.xml
+++ b/captcha/pom.xml
@@ -11,14 +11,14 @@
org.springframework.boot
spring-boot-starter-parent
- 3.2.1
+ 3.2.2
4.0.0
de.bluewhale
captcha-light
- 1.2.4
+ 1.2.5
jar
A REST-full microservice service for CAPTCHA running as spring boot application
@@ -46,9 +46,9 @@
UTF-8
UTF-8
2.3.0
- 1.12.1
- 9.0.7
- 3.2.3
+ 1.12.3
+ 9.0.9
+ 3.2.5
2.16.2
diff --git a/captcha/src/main/java/de/bluewhale/captcha/rest/CaptchaController.java b/captcha/src/main/java/de/bluewhale/captcha/rest/CaptchaController.java
index a22be542..5bf1e8f6 100644
--- a/captcha/src/main/java/de/bluewhale/captcha/rest/CaptchaController.java
+++ b/captcha/src/main/java/de/bluewhale/captcha/rest/CaptchaController.java
@@ -44,7 +44,7 @@ public class CaptchaController {
@ResponseStatus(HttpStatus.OK)
public ResponseEntity getNewCaptchaChallenge(
@PathVariable(value = "language", required = true)
- @Parameter(name = "language", description = "ISO-639-1 language code - used for i18n in communication.") String language) {
+ @Parameter(name = "language", description = "ISO-639-1 language code - used for i18n in communication. English will be used as fallback, if language is not available.") String language) {
ResponseEntity response;
diff --git a/captcha/src/main/java/de/bluewhale/captcha/service/QAGenerator.java b/captcha/src/main/java/de/bluewhale/captcha/service/QAGenerator.java
index 565c1a55..a144fcb3 100644
--- a/captcha/src/main/java/de/bluewhale/captcha/service/QAGenerator.java
+++ b/captcha/src/main/java/de/bluewhale/captcha/service/QAGenerator.java
@@ -38,174 +38,131 @@ public class QAGenerator {
// -------------------------- STATIC METHODS --------------------------
- // FIXME: 30.09.18 These data shuld be json config, which is loaded as runtime.
-
static {
- // This pattern challenge1 could be dynamically generated on the fly
- // as this is nonsense as the source is open...but for the start it's fine
- ChallengeData challenge1 = new ChallengeData();
- challenge1.questionMap.put(Locale.GERMAN, "Welches passt nicht zum Muster?");
- challenge1.questionMap.put(Locale.ENGLISH, "Which one does not fit to the pattern?");
+ // The questions from the ressource bundle will be combined with the possible answers in this step.
+ // The criteria for new questions is, that the possible answers are as language agnostic as possible.
+
+ ChallengeData challenge1 = new ChallengeData(1);
challenge1.answerMap.put("A1-B2-C2D", FALSE);
challenge1.answerMap.put("K8-V4-W7H", FALSE);
challenge1.answerMap.put("J6-N8-9T9", TRUE);
challenge1.answerMap.put("V1-J3-Q2P", FALSE);
- ChallengeData challenge2 = new ChallengeData();
- challenge2.questionMap.put(Locale.GERMAN, "Was passt nicht?");
- challenge2.questionMap.put(Locale.ENGLISH, "Which option does not fit?");
+ ChallengeData challenge2 = new ChallengeData(2);
challenge2.answerMap.put("Saturn", FALSE);
challenge2.answerMap.put("Jupiter", FALSE);
challenge2.answerMap.put("Moon", TRUE);
challenge2.answerMap.put("Venus", FALSE);
- ChallengeData challenge3 = new ChallengeData();
- challenge3.questionMap.put(Locale.GERMAN, "Welcher Wert muss gering gehalten werden?");
- challenge3.questionMap.put(Locale.ENGLISH, "Which value is to be minimized?");
+ ChallengeData challenge3 = new ChallengeData(3);
challenge3.answerMap.put("PO4", TRUE);
challenge3.answerMap.put("Ca", FALSE);
challenge3.answerMap.put("Mg", FALSE);
challenge3.answerMap.put("NO3", FALSE);
- ChallengeData challenge4 = new ChallengeData();
- challenge4.questionMap.put(Locale.GERMAN, "Was gibt es davon sprachlich?");
- challenge4.questionMap.put(Locale.ENGLISH, "Which one exists likely as spoken words?");
+ ChallengeData challenge4 = new ChallengeData(4);
challenge4.answerMap.put("+-0", TRUE);
challenge4.answerMap.put("#-#", FALSE);
challenge4.answerMap.put("+##", FALSE);
challenge4.answerMap.put("##0", FALSE);
- ChallengeData challenge5 = new ChallengeData();
- challenge5.questionMap.put(Locale.GERMAN, "Wen würdest du aufmuntern?");
- challenge5.questionMap.put(Locale.ENGLISH, "Who needs a little support?");
+ ChallengeData challenge5 = new ChallengeData(5);
challenge5.answerMap.put(":-)", FALSE);
challenge5.answerMap.put(";-)", FALSE);
challenge5.answerMap.put(":-(", TRUE);
challenge5.answerMap.put(":-x", FALSE);
- ChallengeData challenge6 = new ChallengeData();
- challenge6.questionMap.put(Locale.GERMAN, "Platform 9 3/4 was passt dazu am besten?");
- challenge6.questionMap.put(Locale.ENGLISH, "Platform 9 3/4 which association fits best?");
+ ChallengeData challenge6 = new ChallengeData(6);
challenge6.answerMap.put("@@@@@", FALSE);
challenge6.answerMap.put("#####", FALSE);
challenge6.answerMap.put("+++++", FALSE);
challenge6.answerMap.put("=====", TRUE);
- ChallengeData challenge7 = new ChallengeData();
- challenge7.questionMap.put(Locale.GERMAN, "Was würdest du vermehren?");
- challenge7.questionMap.put(Locale.ENGLISH, "Which one would you increase?");
+ ChallengeData challenge7 = new ChallengeData(7);
challenge7.answerMap.put("@@@", FALSE);
challenge7.answerMap.put("§§§", FALSE);
challenge7.answerMap.put("%%%", FALSE);
challenge7.answerMap.put("$$$", TRUE);
- ChallengeData challenge8 = new ChallengeData();
- challenge8.questionMap.put(Locale.GERMAN, "Was nimmt mehr Fläche ein?");
- challenge8.questionMap.put(Locale.ENGLISH, "Which one occupies the bigger space?");
+ ChallengeData challenge8 = new ChallengeData(8);
challenge8.answerMap.put("C", FALSE);
challenge8.answerMap.put("W", TRUE);
challenge8.answerMap.put("I", FALSE);
challenge8.answerMap.put("L", FALSE);
- ChallengeData challenge9 = new ChallengeData();
- challenge9.questionMap.put(Locale.GERMAN, "Wenn jeder Strich ein Bleistift wäre und du diese nun in eine Linie setzt, was gibt die längere Strecke?");
- challenge9.questionMap.put(Locale.ENGLISH, "If each line is a pencil and you set them in a line, which one would result in the max line?");
+ ChallengeData challenge9 = new ChallengeData(9);
challenge9.answerMap.put("=====", FALSE);
challenge9.answerMap.put("#####", TRUE);
challenge9.answerMap.put("NNNNN", FALSE);
challenge9.answerMap.put("XXXXX", FALSE);
- ChallengeData challenge10 = new ChallengeData();
- challenge10.questionMap.put(Locale.GERMAN, "Was wird immer besser erreichbar?");
- challenge10.questionMap.put(Locale.ENGLISH, "Which one gets more and more reachable?");
+ ChallengeData challenge10 = new ChallengeData(10);
challenge10.answerMap.put("Jupiter", FALSE);
challenge10.answerMap.put("Mars", TRUE);
challenge10.answerMap.put("Venus", FALSE);
challenge10.answerMap.put("Saturn", FALSE);
- ChallengeData challenge11 = new ChallengeData();
- challenge11.questionMap.put(Locale.GERMAN, "Welche Box passt 27 mal in eine 15x15x15 Box?");
- challenge11.questionMap.put(Locale.ENGLISH, "Which box fits 27 times in a 15x15x15 box?");
+ ChallengeData challenge11 = new ChallengeData(11);
challenge11.answerMap.put("10x10x10 Box", FALSE);
challenge11.answerMap.put("5x5x5 Box", TRUE);
challenge11.answerMap.put("4x8x12 Box", FALSE);
challenge11.answerMap.put("20x20x20 Box", FALSE);
- ChallengeData challenge12 = new ChallengeData();
- challenge12.questionMap.put(Locale.GERMAN, "Welcher Ball rollt am ehesten durch ein Mäuseloch?");
- challenge12.questionMap.put(Locale.ENGLISH, "Which ball is likely to be rolling through a mouse hole?");
+ ChallengeData challenge12 = new ChallengeData(12);
challenge12.answerMap.put("5cm Ball", TRUE);
challenge12.answerMap.put("10cm Ball", FALSE);
challenge12.answerMap.put("15cm Ball", FALSE);
challenge12.answerMap.put("20cm Ball", FALSE);
- ChallengeData challenge13 = new ChallengeData();
- challenge13.questionMap.put(Locale.GERMAN, "Hinter dir kollidieren zwei schnelle Objekte, wo wirst du es am geringsten bemerken?");
- challenge13.questionMap.put(Locale.ENGLISH, "Two fast objects are colliding behind you, where will you hardly recognize it?");
+ ChallengeData challenge13 = new ChallengeData(13);
challenge13.answerMap.put("500km NN", TRUE);
challenge13.answerMap.put("10km NN", FALSE);
challenge13.answerMap.put("-50m NN (sea)", FALSE);
challenge13.answerMap.put("5m NN", FALSE);
- ChallengeData challenge14 = new ChallengeData();
- challenge14.questionMap.put(Locale.GERMAN, "Welches davon kippen manche in ihr Riff-Aquarium?");
- challenge14.questionMap.put(Locale.ENGLISH, "Which one of these will be added by some of us to the reef-tank?");
+ ChallengeData challenge14 = new ChallengeData(14);
challenge14.answerMap.put("Blue Curaçao", FALSE);
challenge14.answerMap.put("Vodka", TRUE);
challenge14.answerMap.put("Campari", FALSE);
challenge14.answerMap.put("Ginger Ale", FALSE);
- ChallengeData challenge15 = new ChallengeData();
- challenge15.questionMap.put(Locale.GERMAN, "Wer fällt aus der Reihe?");
- challenge15.questionMap.put(Locale.ENGLISH, "Who does not fit here?");
+ ChallengeData challenge15 = new ChallengeData(15);
challenge15.answerMap.put("Wall-E", FALSE);
challenge15.answerMap.put("E.T.", TRUE);
challenge15.answerMap.put("R2D2", FALSE);
challenge15.answerMap.put("No.5", FALSE);
- ChallengeData challenge16 = new ChallengeData();
- challenge16.questionMap.put(Locale.GERMAN, "Welche Eigenschaften von Seegraswiesen können uns zukünftig helfen?");
- challenge16.questionMap.put(Locale.ENGLISH, "What are the best capabilities of Seaweed-Cultures for our furture?");
+ ChallengeData challenge16 = new ChallengeData(16);
challenge16.answerMap.put("\\|/\\|/", FALSE);
challenge16.answerMap.put("Superfood", FALSE);
challenge16.answerMap.put("C02-Storage", TRUE);
challenge16.answerMap.put("=~=~=~~", FALSE);
- ChallengeData challenge17 = new ChallengeData();
- challenge17.questionMap.put(Locale.GERMAN, "Welche Zahl ist nur durch eins und sich selbst teilbar, so dass das Ergebnis wieder eine Ganze Zahl ergibt?");
- challenge17.questionMap.put(Locale.ENGLISH, "If the result must be a whole number, which one of those can be divided only by 1 and itself?");
+ ChallengeData challenge17 = new ChallengeData(17);
challenge17.answerMap.put("9", FALSE);
challenge17.answerMap.put("4", FALSE);
challenge17.answerMap.put("22", FALSE);
challenge17.answerMap.put("5", TRUE);
- ChallengeData challenge18 = new ChallengeData();
- challenge18.questionMap.put(Locale.GERMAN, "Was geschieht mit Korallen bei einer durchschnittlichen Wassertemperatur vom 30°C");
- challenge18.questionMap.put(Locale.ENGLISH, "What happens to corals if the average water temperature is around 86°F?");
+ ChallengeData challenge18 = new ChallengeData(18);
challenge18.answerMap.put("☠️", TRUE);
challenge18.answerMap.put("🦐", FALSE);
challenge18.answerMap.put("🐡", FALSE);
challenge18.answerMap.put("🧜🏽", FALSE);
- ChallengeData challenge19 = new ChallengeData();
- challenge19.questionMap.put(Locale.GERMAN, "Was geschieht wahrscheinlich mit den nützlichen Bakterien in deinem Riff, wenn der KH-Wert sinkt?");
- challenge19.questionMap.put(Locale.ENGLISH, "What is likely to happen to the useful bacteria in your reef if the carbonate level decreases?");
+ ChallengeData challenge19 = new ChallengeData(19);
challenge19.answerMap.put("🦐", FALSE);
challenge19.answerMap.put("🐡", FALSE);
challenge19.answerMap.put("🧜🏽", FALSE);
challenge19.answerMap.put("☠️", TRUE);
- ChallengeData challenge20 = new ChallengeData();
- challenge20.questionMap.put(Locale.GERMAN, "Wer von den gezeigten hat die Chance älter als die anderen zu werden?");
- challenge20.questionMap.put(Locale.ENGLISH, "Who among those shown has the chance to become older than the others?");
+ ChallengeData challenge20 = new ChallengeData(20);
challenge20.answerMap.put("🐬", FALSE);
challenge20.answerMap.put("🐒", FALSE);
challenge20.answerMap.put("🐢", TRUE);
challenge20.answerMap.put("🦉", FALSE);
- ChallengeData challenge21 = new ChallengeData();
- challenge21.questionMap.put(Locale.GERMAN, "Emotie Rätsel: Welche Kombination repräsentiert den Song Titel 'Walking this way'?");
- challenge21.questionMap.put(Locale.ENGLISH, "Emotie quiz: Which combination represents the song 'Walking this way'?");
+ ChallengeData challenge21 = new ChallengeData(21);
challenge21.answerMap.put("🪢👀", FALSE);
challenge21.answerMap.put("🚶➡️", TRUE);
challenge21.answerMap.put("🏄💨", FALSE);
@@ -245,24 +202,42 @@ public class QAGenerator {
*/
public ChallengeTo provideChallengeFor(final String pLanguage) {
- int questionIndex = random.nextInt(dataSet.size());
-
- Object[] challenges = dataSet.toArray();
- ChallengeData challengeData = (ChallengeData) challenges[questionIndex];
-
- ChallengeTo challengeTo = new ChallengeTo();
-
- Map questionMap = challengeData.questionMap;
Locale locale;
try {
- locale = new Locale(pLanguage);
+
+ // check for supported locales and set "en" as fallback
+ switch (pLanguage) {
+ case "de":
+ case "en":
+ case "fr":
+ case "es":
+ case "it":
+ locale = new Locale(pLanguage);
+ break;
+ default: locale = Locale.ENGLISH;
+ }
+
locale.getISO3Language(); // semantic check
+
} catch (MissingResourceException pE) {
locale = Locale.ENGLISH;
}
+
+ ResourceBundle bundle = ResourceBundle.getBundle("i18n/ChallengeSamples", locale);
+
+ int questionIndex = random.nextInt(dataSet.size());
+
+ Object[] challenges = dataSet.toArray();
+ ChallengeData challengeData = (ChallengeData) challenges[questionIndex];
+
+ ChallengeTo challengeTo = new ChallengeTo();
+
challengeTo.setLanguage(locale.getLanguage());
- challengeTo.setQuestion(questionMap.get(locale));
+
+ String localedQuestion = bundle.getString(challengeData.questionKey);
+
+ challengeTo.setQuestion(localedQuestion);
// As for the answer map, we generate answer tokens and for the right one
// we register it with the ValidationCache.
@@ -293,11 +268,11 @@ private String createToken(int pTOKEN_SIZE) {
// -------------------------- INNER CLASSES --------------------------
private static class ChallengeData {
- protected Map questionMap;
+ protected String questionKey;
protected Map answerMap; // the one marked with true is the right answer.
- public ChallengeData() {
- this.questionMap = new HashMap();
+ public ChallengeData(int challengeNumber) {
+ this.questionKey = "challenge."+challengeNumber+".question";
this.answerMap = new HashMap();
}
}
diff --git a/captcha/src/main/resources/i18n/ChallengeSamples.properties b/captcha/src/main/resources/i18n/ChallengeSamples.properties
new file mode 100644
index 00000000..03934deb
--- /dev/null
+++ b/captcha/src/main/resources/i18n/ChallengeSamples.properties
@@ -0,0 +1,21 @@
+challenge.1.question="Which one does not match the pattern?"
+challenge.2.question="What does not fit?"
+challenge.3.question="Which value must be kept low?"
+challenge.4.question="What is there linguistically?"
+challenge.5.question="Who would you cheer up?"
+challenge.6.question="Platform 9 3/4 what fits best?"
+challenge.7.question="What would you increase?"
+challenge.8.question="What takes up more space?"
+challenge.9.question="If each line were a pencil and you now put them in a line, what gives the longer distance?"
+challenge.10.question="What is becoming more accessible?"
+challenge.11.question="Which box fits 27 times into a 15x15x15 box?"
+challenge.12.question="Which ball is most likely to roll through a mouse hole?"
+challenge.13.question="Two fast objects collide behind you, where will you notice it the least?"
+challenge.14.question="Which of these do some people tip into their reef aquarium?"
+challenge.15.question="Who falls out of line?"
+challenge.16.question="Which characteristics of seagrass meadows can help us in the future?"
+challenge.17.question="Which number can only be divided by one and itself, so that the result is a whole number again?"
+challenge.18.question="What happens to corals at an average water temperature of 30\u00B0C"
+challenge.19.question="What is likely to happen to the beneficial bacteria in your reef when the KH value drops?"
+challenge.20.question="Which of those shown has the chance to grow older than the others?"
+challenge.21.question="Emotie riddle: Which combination represents the song title 'Walking this way'?"
\ No newline at end of file
diff --git a/captcha/src/main/resources/i18n/ChallengeSamples_de.properties b/captcha/src/main/resources/i18n/ChallengeSamples_de.properties
new file mode 100644
index 00000000..6beebbd6
--- /dev/null
+++ b/captcha/src/main/resources/i18n/ChallengeSamples_de.properties
@@ -0,0 +1,21 @@
+challenge.1.question="Welches passt nicht zum Muster?"
+challenge.2.question="Was passt nicht?"
+challenge.3.question="Welcher Wert muss gering gehalten werden?"
+challenge.4.question="Was gibt es davon sprachlich?"
+challenge.5.question="Wen w\u00FCrdest du aufmuntern?"
+challenge.6.question="Platform 9 3/4 was passt dazu am besten?"
+challenge.7.question="Was w\u00FCrdest du vermehren?"
+challenge.8.question="Was nimmt mehr Fl\u00E4che ein?"
+challenge.9.question="Wenn jeder Strich ein Bleistift w\u00E4re und du diese nun in eine Linie setzt, was gibt die l\u00E4ngere Strecke?"
+challenge.10.question="Was wird immer besser erreichbar?"
+challenge.11.question="Welche Box passt 27 mal in eine 15x15x15 Box?"
+challenge.12.question="Welcher Ball rollt am ehesten durch ein M\u00E4useloch?"
+challenge.13.question="Hinter dir kollidieren zwei schnelle Objekte, wo wirst du es am geringsten bemerken?"
+challenge.14.question="Welches davon kippen manche in ihr Riff-Aquarium?"
+challenge.15.question="Wer f\u00E4llt aus der Reihe?"
+challenge.16.question="Welche Eigenschaften von Seegraswiesen k\u00F6nnen uns zuk\u00FCnftig helfen?"
+challenge.17.question="Welche Zahl ist nur durch eins und sich selbst teilbar, so dass das Ergebnis wieder eine Ganze Zahl ergibt?"
+challenge.18.question="Was geschieht mit Korallen bei einer durchschnittlichen Wassertemperatur vom 30\u00B0C"
+challenge.19.question="Was geschieht wahrscheinlich mit den n\u00FCtzlichen Bakterien in deinem Riff, wenn der KH-Wert sinkt?"
+challenge.20.question="Wer von den gezeigten hat die Chance \u00E4lter als die anderen zu werden?"
+challenge.21.question="Emotie R\u00E4tsel: Welche Kombination repr\u00E4sentiert den Song Titel 'Walking this way'?"
\ No newline at end of file
diff --git a/captcha/src/main/resources/i18n/ChallengeSamples_en.properties b/captcha/src/main/resources/i18n/ChallengeSamples_en.properties
new file mode 100644
index 00000000..03934deb
--- /dev/null
+++ b/captcha/src/main/resources/i18n/ChallengeSamples_en.properties
@@ -0,0 +1,21 @@
+challenge.1.question="Which one does not match the pattern?"
+challenge.2.question="What does not fit?"
+challenge.3.question="Which value must be kept low?"
+challenge.4.question="What is there linguistically?"
+challenge.5.question="Who would you cheer up?"
+challenge.6.question="Platform 9 3/4 what fits best?"
+challenge.7.question="What would you increase?"
+challenge.8.question="What takes up more space?"
+challenge.9.question="If each line were a pencil and you now put them in a line, what gives the longer distance?"
+challenge.10.question="What is becoming more accessible?"
+challenge.11.question="Which box fits 27 times into a 15x15x15 box?"
+challenge.12.question="Which ball is most likely to roll through a mouse hole?"
+challenge.13.question="Two fast objects collide behind you, where will you notice it the least?"
+challenge.14.question="Which of these do some people tip into their reef aquarium?"
+challenge.15.question="Who falls out of line?"
+challenge.16.question="Which characteristics of seagrass meadows can help us in the future?"
+challenge.17.question="Which number can only be divided by one and itself, so that the result is a whole number again?"
+challenge.18.question="What happens to corals at an average water temperature of 30\u00B0C"
+challenge.19.question="What is likely to happen to the beneficial bacteria in your reef when the KH value drops?"
+challenge.20.question="Which of those shown has the chance to grow older than the others?"
+challenge.21.question="Emotie riddle: Which combination represents the song title 'Walking this way'?"
\ No newline at end of file
diff --git a/captcha/src/main/resources/i18n/ChallengeSamples_es.properties b/captcha/src/main/resources/i18n/ChallengeSamples_es.properties
new file mode 100644
index 00000000..d574fd0a
--- /dev/null
+++ b/captcha/src/main/resources/i18n/ChallengeSamples_es.properties
@@ -0,0 +1,21 @@
+challenge.1.question="\u00BFCu\u00E1l no encaja en el patr\u00F3n?"
+challenge.2.question="\u00BFCu\u00E1l no encaja?"
+challenge.3.question="\u00BFQu\u00E9 valor debe mantenerse bajo?"
+challenge.4.question="\u00BFQu\u00E9 hay ling\u00FC\u00EDsticamente?"
+challenge.5.question="\u00BFA qui\u00E9n animar\u00EDas?"
+challenge.6.question="Plataforma 9 3/4 \u00BFqu\u00E9 encaja mejor?"
+challenge.7.question="\u00BFQu\u00E9 aumentar\u00EDas?"
+challenge.8.question="\u00BFQu\u00E9 ocupa m\u00E1s espacio?"
+challenge.9.question="Si cada l\u00EDnea fuera un l\u00E1piz y ahora los pusieras en fila, \u00BFqu\u00E9 da m\u00E1s distancia?"
+challenge.10.question="\u00BFQu\u00E9 es cada vez m\u00E1s accesible?"
+challenge.11.question="\u00BFQu\u00E9 caja cabe 27 veces en una caja de 15x15x15?"
+challenge.12.question="\u00BFQu\u00E9 bola tiene m\u00E1s probabilidades de pasar por el agujero de un rat\u00F3n?"
+challenge.13.question="Dos objetos r\u00E1pidos chocan detr\u00E1s de ti, \u00BFd\u00F3nde lo notar\u00E1s menos?"
+challenge.14.question="\u00BFCu\u00E1l de estos objetos vuelcan algunas personas en su acuario de arrecife?"
+challenge.15.question="\u00BFQui\u00E9n se cae de la fila?"
+challenge.16.question="\u00BFQu\u00E9 caracter\u00EDsticas de las praderas marinas pueden ayudarnos en el futuro?"
+challenge.17.question="\u00BFQu\u00E9 n\u00FAmero s\u00F3lo se puede dividir por uno y por s\u00ED mismo, de modo que el resultado vuelva a ser un n\u00FAmero entero?"
+challenge.18.question="\u00BFQu\u00E9 les ocurre a los corales cuando la temperatura media del agua es de 30\u00BAC?
+challenge.19.question="\u00BFQu\u00E9 les puede pasar a las bacterias beneficiosas de tu arrecife cuando baja el valor de KH?"
+challenge.20.question="\u00BFCu\u00E1l de los que se muestran tiene m\u00E1s posibilidades de envejecer que los dem\u00E1s?"
+challenge.21.question="Adivinanza Emotie: \u00BFQu\u00E9 combinaci\u00F3n representa el t\u00EDtulo de la canci\u00F3n 'Walking this way'?"
\ No newline at end of file
diff --git a/captcha/src/main/resources/i18n/ChallengeSamples_fr.properties b/captcha/src/main/resources/i18n/ChallengeSamples_fr.properties
new file mode 100644
index 00000000..f5dabf02
--- /dev/null
+++ b/captcha/src/main/resources/i18n/ChallengeSamples_fr.properties
@@ -0,0 +1,21 @@
+challenge.1.question="Lequel ne correspond pas au mod\u00E8le ?"
+challenge.2.question="Qu'est-ce qui ne correspond pas ?"
+challenge.3.question="Quelle valeur doit \u00EAtre maintenue \u00E0 un niveau bas ?"
+challenge.4.question="Qu'est-ce qui existe au niveau linguistique ?"
+challenge.5.question="Qui encouragerais-tu ?"
+challenge.6.question="Plateforme 9 3/4 qu'est-ce qui convient le mieux ?"
+challenge.7.question="Que multiplierais-tu ?"
+challenge.8.question="Qu'est-ce qui prend le plus de place ?"
+challenge.9.question="Si chaque trait \u00E9tait un crayon et que tu les pla\u00E7ais maintenant sur une ligne, qu'est-ce qui donnerait la plus longue distance ?"
+challenge.10.question="Qu'est-ce qui devient de plus en plus accessible ?"
+challenge.11.question="Quelle bo\u00EEte tient 27 fois dans une bo\u00EEte de 15x15x15 ?"
+challenge.12.question="Quelle balle a le plus de chances de rouler dans un trou de souris ?"
+challenge.13.question="Derri\u00E8re toi, deux objets rapides entrent en collision, o\u00F9 le remarqueras-tu le moins ?"
+challenge.14.question="Lequel des deux renverse-t-on dans son aquarium r\u00E9cifal ?"
+challenge.15.question="Qui sort du lot ?"
+challenge.16.question="Quelles sont les caract\u00E9ristiques des herbiers marins qui peuvent nous aider \u00E0 l'avenir ?"
+challenge.17.question="Quel nombre n'est divisible que par un et par lui-m\u00EAme, de sorte que le r\u00E9sultat soit \u00E0 nouveau un nombre entier ?"
+challenge.18.question="Que se passe-t-il pour les coraux lorsque la temp\u00E9rature moyenne de l'eau est de 30\u00B0C ?"
+challenge.19.question="Qu'arrive-t-il probablement aux bact\u00E9ries utiles dans ton r\u00E9cif lorsque le KH diminue ?"
+challenge.20.question="Qui, parmi ceux pr\u00E9sent\u00E9s, a une chance de devenir plus vieux que les autres ?"
+challenge.21.question="Enigme d'\u00E9motivit\u00E9 : quelle combinaison repr\u00E9sente le titre de la chanson 'Walking this way' ?"
\ No newline at end of file
diff --git a/captcha/src/main/resources/i18n/ChallengeSamples_it.properties b/captcha/src/main/resources/i18n/ChallengeSamples_it.properties
new file mode 100644
index 00000000..24852e5f
--- /dev/null
+++ b/captcha/src/main/resources/i18n/ChallengeSamples_it.properties
@@ -0,0 +1,21 @@
+challenge.1.question="Quale non corrisponde al modello?".
+challenge.2.question="Cosa non corrisponde?".
+challenge.3.question="Quale valore deve essere mantenuto basso?".
+challenge.4.question="Cosa c'\u00E8 a livello linguistico?".
+challenge.5.question="Chi vuoi tirar su di morale?".
+challenge.6.question="Piattaforma 9 3/4 cosa si adatta meglio?"
+challenge.7.question="Cosa aumenteresti?"
+challenge.8.question="Cosa occupa pi\u00F9 spazio?"
+challenge.9.question="Se ogni linea fosse una matita e le metteste in fila, quale sarebbe la distanza maggiore?".
+challenge.10.question="Che cosa sta diventando pi\u00F9 accessibile?".
+challenge.11.question="Quale scatola entra 27 volte in una scatola 15x15x15?".
+challenge.12.question="Qual \u00E8 la palla che ha pi\u00F9 probabilit\u00E0 di rotolare attraverso il buco di un topo?".
+challenge.13.question="Due oggetti veloci si scontrano dietro di te, dove lo noterai di meno?".
+challenge.14.question="Quale di questi oggetti alcune persone rovesciano nel loro acquario di barriera?".
+challenge.15.question="Chi cade fuori dalle righe?".
+challenge.16.question="Quali caratteristiche delle praterie di fanerogame possono aiutarci in futuro?".
+challenge.17.question="Quale numero pu\u00F2 essere diviso solo per uno e per se stesso, in modo che il risultato sia di nuovo un numero intero?".
+challenge.18.question="Cosa succede ai coralli a una temperatura media dell'acqua di 30\u00B0C".
+challenge.19.question="Cosa pu\u00F2 succedere ai batteri benefici della barriera corallina quando il valore del KH si abbassa?"
+challenge.20.question="Quale di quelli mostrati ha la possibilit\u00E0 di invecchiare rispetto agli altri?"
+challenge.21.question="Indovinello di Emotie: quale combinazione rappresenta il titolo della canzone 'Walking this way'?".
\ No newline at end of file
diff --git a/sabi-webclient/src/main/resources/META-INF/resources/secured/userProfile.xhtml b/sabi-webclient/src/main/resources/META-INF/resources/secured/userProfile.xhtml
index 091b84d7..c59595b8 100644
--- a/sabi-webclient/src/main/resources/META-INF/resources/secured/userProfile.xhtml
+++ b/sabi-webclient/src/main/resources/META-INF/resources/secured/userProfile.xhtml
@@ -104,8 +104,9 @@
/>
-
+
@@ -133,7 +134,7 @@
+ action="#{userProfileView.save}"/>