diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/i18n/ExposedReloadableResourceMessageBundleSource.java b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/ExposedReloadableResourceMessageBundleSource.java
new file mode 100644
index 000000000..bfa3d1ff8
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/ExposedReloadableResourceMessageBundleSource.java
@@ -0,0 +1,24 @@
+package org.owasp.webgoat.i18n;
+
+import org.springframework.context.support.ReloadableResourceBundleMessageSource;
+
+import java.util.Locale;
+import java.util.Properties;
+
+/**
+ *
ExposedReloadableResourceMessageBundleSource class.
+ * Extends the reloadable message source with a way to get all messages
+ *
+ * @author zupzup
+ */
+
+public class ExposedReloadableResourceMessageBundleSource extends ReloadableResourceBundleMessageSource {
+ /**
+ * Gets all messages for presented Locale.
+ * @param locale user request's locale
+ * @return all messages
+ */
+ public Properties getMessages(Locale locale) {
+ return getMergedProperties(locale).getProperties();
+ }
+}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java
index c1fa62ae0..79057df49 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java
@@ -9,9 +9,7 @@ import org.springframework.stereotype.Component;
import java.net.MalformedURLException;
import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
+import java.util.*;
/**
@@ -52,8 +50,8 @@ public class LabelProvider {
private static final List SUPPORTED = Arrays.asList(Locale.GERMAN, Locale.FRENCH, Locale.ENGLISH,
Locale.forLanguageTag("ru"));
- private final ReloadableResourceBundleMessageSource labels = new ReloadableResourceBundleMessageSource();
- private static final ReloadableResourceBundleMessageSource pluginLabels = new ReloadableResourceBundleMessageSource();
+ private final ExposedReloadableResourceMessageBundleSource labels = new ExposedReloadableResourceMessageBundleSource();
+ private static final ExposedReloadableResourceMessageBundleSource pluginLabels = new ExposedReloadableResourceMessageBundleSource();
/**
* Constructor for LabelProvider.
@@ -104,7 +102,27 @@ public class LabelProvider {
}
private Locale useLocaleOrFallbackToEnglish(Locale locale) {
- return SUPPORTED.contains(locale) ? Locale.ENGLISH : locale;
+ return SUPPORTED.contains(locale) ? locale : Locale.ENGLISH;
+ }
+
+ /**
+ * getLabels.
+ * Returns a merged map of all the labels for a specified language or the
+ * default language, if the given language is not supported
+ *
+ * @param locale The Locale to get all the labels for
+ * @return A Map of all properties with their values
+ */
+ public Map getLabels(Locale locale) {
+ Properties messages = labels.getMessages(locale);
+ messages.putAll(pluginLabels.getMessages(useLocaleOrFallbackToEnglish(locale)));
+ Map labelsMap = new HashMap<>();
+ for (Map.Entry entry : messages.entrySet()) {
+ if (entry.getKey() != null && entry.getValue() != null) {
+ labelsMap.put(entry.getKey().toString(), entry.getValue().toString());
+ }
+ }
+ return labelsMap;
}
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LabelService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LabelService.java
new file mode 100644
index 000000000..508d4813c
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LabelService.java
@@ -0,0 +1,63 @@
+package org.owasp.webgoat.service;
+
+import org.owasp.webgoat.i18n.LabelProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+
+/**
+ * LabelService class.
+ *
+ * @author zupzup
+ */
+
+@Controller
+public class LabelService {
+
+ private static final String URL_LABELS_MVC = "/service/labels.mvc";
+
+ private static final Logger logger = LoggerFactory.getLogger(LabelService.class);
+
+ @Autowired
+ private LabelProvider labelProvider;
+
+ /**
+ * Fetches labels for given language
+ * If no language is provided, the language is determined from the request headers
+ * Otherwise, fall back to default language
+ *
+ * @param lang the language to fetch labels for (optional)
+ * @return a map of labels
+ * @throws Exception
+ */
+ @RequestMapping(path = URL_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE)
+ public @ResponseBody
+ ResponseEntity> fetchLabels(@RequestParam(value = "lang", required = false) String lang, HttpServletRequest request) throws Exception {
+ Locale locale;
+ if (StringUtils.isEmpty(lang)) {
+ logger.debug("No language provided, determining from request headers");
+ locale = request.getLocale();
+ if (locale != null) {
+ logger.debug("Locale set to {}", locale);
+ }
+ } else {
+ locale = Locale.forLanguageTag(lang);
+ logger.debug("Language provided: {} leads to Locale: {}", lang, locale);
+ }
+ return new ResponseEntity<>(labelProvider.getLabels(locale), HttpStatus.OK);
+ }
+}
diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/util/LabelProviderTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/util/LabelProviderTest.java
index 79f2b7f74..8b5874519 100644
--- a/webgoat-container/src/test/java/org/owasp/webgoat/util/LabelProviderTest.java
+++ b/webgoat-container/src/test/java/org/owasp/webgoat/util/LabelProviderTest.java
@@ -17,4 +17,18 @@ public class LabelProviderTest {
"Congratulations. You have successfully completed this lesson."));
}
+ @Test
+ public void shouldFallBackToEnglishIfLanguageNotSupported() {
+ LabelProvider labelProvider = new LabelProvider();
+ assertThat(labelProvider.get(Locale.CHINESE, "LessonCompleted"), CoreMatchers.equalTo(
+ "Congratulations. You have successfully completed this lesson."));
+ }
+
+ @Test
+ public void shouldUseProvidedLanguageIfSupported() {
+ LabelProvider labelProvider = new LabelProvider();
+ assertThat(labelProvider.get(Locale.GERMAN, "RestartLesson"), CoreMatchers.equalTo(
+ "Lektion neu beginnen"));
+ }
+
}
\ No newline at end of file