From: Alexander Goussas
Date: Tue, 2 Jun 2026 03:32:19 +0000 (-0500)
Subject: feat: add support for multilang definitions
X-Git-Url: http://git.frustrated-labs.net/?a=commitdiff_plain;h=d54e8103ea72b6027ebff7b02768d40deab739e6;p=larousseapi
feat: add support for multilang definitions
---
diff --git a/collections/larousse API/Define a word.yml b/collections/larousse API/Define a word.yml
index 96fcef1..905fda1 100644
--- a/collections/larousse API/Define a word.yml
+++ b/collections/larousse API/Define a word.yml
@@ -5,8 +5,11 @@ info:
http:
method: GET
- url: "{{api.base_url}}/words/:word/definition"
+ url: "{{api.base_url}}/words/:word/definition?lang=de"
params:
+ - name: lang
+ value: de
+ type: query
- name: word
value: voiture
type: path
diff --git a/collections/larousse API/Translate a word.yml b/collections/larousse API/Translate a word.yml
index 9f08930..9e31518 100644
--- a/collections/larousse API/Translate a word.yml
+++ b/collections/larousse API/Translate a word.yml
@@ -5,8 +5,11 @@ info:
http:
method: GET
- url: "{{api.base_url}}/words/:word/translation"
+ url: "{{api.base_url}}/words/:word/translation?lang=de"
params:
+ - name: lang
+ value: de
+ type: query
- name: word
value: voiture
type: path
diff --git a/src/main/java/net/frustratedfunctor/core/Lang.java b/src/main/java/net/frustratedfunctor/core/Lang.java
new file mode 100644
index 0000000..a58a4ae
--- /dev/null
+++ b/src/main/java/net/frustratedfunctor/core/Lang.java
@@ -0,0 +1,28 @@
+package net.frustratedfunctor.core;
+
+import java.util.Optional;
+
+public enum Lang {
+ French("fr"),
+ German("de");
+
+ public final String code;
+
+ public final static Lang DEFAULT = French;
+
+ Lang(String code) {
+ this.code = code;
+ }
+
+ public static Optional parse(String s) {
+ return Optional.ofNullable(switch (s.toLowerCase()) {
+ case "fr" -> Lang.French;
+ case "de" -> Lang.German;
+ default -> null;
+ });
+ }
+
+ public static Lang parseOrDefault(String s) {
+ return parse(s).orElse(DEFAULT);
+ }
+}
diff --git a/src/main/java/net/frustratedfunctor/definitions/FrenchWordDefinitionRepository.java b/src/main/java/net/frustratedfunctor/definitions/FrenchWordDefinitionRepository.java
new file mode 100644
index 0000000..0b26252
--- /dev/null
+++ b/src/main/java/net/frustratedfunctor/definitions/FrenchWordDefinitionRepository.java
@@ -0,0 +1,29 @@
+package net.frustratedfunctor.definitions;
+
+import io.quarkus.logging.Log;
+import jakarta.enterprise.context.ApplicationScoped;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Element;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+@ApplicationScoped
+public class FrenchWordDefinitionRepository implements WordDefinitionRepository {
+ @Override
+ public List definitionsForWord(String word) {
+ try {
+ final var larousseUrl = URI.create("https://www.larousse.fr/dictionnaires/francais/" + word).toURL();
+ final var doc = Jsoup.parse(larousseUrl, 10_000);
+ return doc
+ .select("li.DivisionDefinition")
+ .stream()
+ .map(Element::ownText)
+ .toList();
+ } catch (Exception e) {
+ Log.error("Error while fetching word translations", e);
+ return new ArrayList<>();
+ }
+ }
+}
diff --git a/src/main/java/net/frustratedfunctor/definitions/JsoupWordDefinitionRepository.java b/src/main/java/net/frustratedfunctor/definitions/JsoupWordDefinitionRepository.java
deleted file mode 100644
index 96e7d78..0000000
--- a/src/main/java/net/frustratedfunctor/definitions/JsoupWordDefinitionRepository.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package net.frustratedfunctor.definitions;
-
-import io.quarkus.logging.Log;
-import jakarta.enterprise.context.ApplicationScoped;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Element;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-
-@ApplicationScoped
-public class JsoupWordDefinitionRepository implements WordDefinitionRepository {
- @Override
- public List definitionsForWord(String word) {
- try {
- final var larousseUrl = URI.create("https://www.larousse.fr/dictionnaires/francais/" + word).toURL();
- final var doc = Jsoup.parse(larousseUrl, 10_000);
- return doc
- .select("li.DivisionDefinition")
- .stream()
- .map(Element::ownText)
- .toList();
- } catch (Exception e) {
- Log.error("Error while fetching word translations", e);
- return new ArrayList<>();
- }
- }
-}
diff --git a/src/main/java/net/frustratedfunctor/definitions/LanguageAwareDefinitionsRepository.java b/src/main/java/net/frustratedfunctor/definitions/LanguageAwareDefinitionsRepository.java
new file mode 100644
index 0000000..fd43308
--- /dev/null
+++ b/src/main/java/net/frustratedfunctor/definitions/LanguageAwareDefinitionsRepository.java
@@ -0,0 +1,29 @@
+package net.frustratedfunctor.definitions;
+
+import jakarta.annotation.Priority;
+import jakarta.enterprise.context.ApplicationScoped;
+import net.frustratedfunctor.core.Lang;
+
+import java.util.List;
+
+@Priority(1)
+@ApplicationScoped
+public class LanguageAwareDefinitionsRepository implements WordDefinitionRepository {
+ private final FrenchWordDefinitionRepository french;
+
+ public LanguageAwareDefinitionsRepository(FrenchWordDefinitionRepository french) {
+ this.french = french;
+ }
+
+ @Override
+ public List definitionsForWord(String word) {
+ return french.definitionsForWord(word);
+ }
+
+ public List definitionsForWord(String word, String lang) {
+ return switch (Lang.parseOrDefault(lang)) {
+ case French -> french.definitionsForWord(word);
+ case German -> List.of("OOPS! NOT IMPLEMENTED");
+ };
+ }
+}
diff --git a/src/main/java/net/frustratedfunctor/definitions/WordDefinitionResource.java b/src/main/java/net/frustratedfunctor/definitions/WordDefinitionResource.java
index 6f3b78d..7e9e9b1 100644
--- a/src/main/java/net/frustratedfunctor/definitions/WordDefinitionResource.java
+++ b/src/main/java/net/frustratedfunctor/definitions/WordDefinitionResource.java
@@ -1,9 +1,6 @@
package net.frustratedfunctor.definitions;
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.PathParam;
-import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
@Path("/words")
@@ -18,8 +15,11 @@ public class WordDefinitionResource {
@Path("/{word}/definition")
@GET
@Produces(MediaType.APPLICATION_JSON)
- public WordDefinition definition(@PathParam("word") String word) {
- return definitions.define(word);
+ public WordDefinition definition(
+ @PathParam("word") String word,
+ @QueryParam("lang") String lang
+ ) {
+ return definitions.define(word, lang);
}
}
diff --git a/src/main/java/net/frustratedfunctor/definitions/WordDefinitionService.java b/src/main/java/net/frustratedfunctor/definitions/WordDefinitionService.java
index 44696e2..564aafa 100644
--- a/src/main/java/net/frustratedfunctor/definitions/WordDefinitionService.java
+++ b/src/main/java/net/frustratedfunctor/definitions/WordDefinitionService.java
@@ -5,17 +5,15 @@ import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class WordDefinitionService {
- private final WordDefinitionRepository definitions;
+ private final LanguageAwareDefinitionsRepository definitions;
- public WordDefinitionService(WordDefinitionRepository definitions) {
+ public WordDefinitionService(LanguageAwareDefinitionsRepository definitions) {
this.definitions = definitions;
}
- public WordDefinition define(String word) {
- return new WordDefinition(
- word,
- definitions.definitionsForWord(word)
- );
+ public WordDefinition define(String word, String lang) {
+ final var defs = definitions.definitionsForWord(word, lang);
+ return new WordDefinition(word, defs);
}
}
diff --git a/src/main/java/net/frustratedfunctor/ui/UiResource.java b/src/main/java/net/frustratedfunctor/ui/UiResource.java
index 0fe5dc2..00e688d 100644
--- a/src/main/java/net/frustratedfunctor/ui/UiResource.java
+++ b/src/main/java/net/frustratedfunctor/ui/UiResource.java
@@ -28,10 +28,13 @@ public class UiResource {
@Path("getTranslationsDefinitions")
@POST
@Produces(MediaType.TEXT_HTML)
- public TemplateInstance getTranslationsDefinitions(@FormParam("word") String word) {
+ public TemplateInstance getTranslationsDefinitions(
+ @FormParam("word") String word,
+ @FormParam("lang") String lang
+ ) {
final var data = new WordTranslationsDefinitions(
translations.translate(word).translations(),
- definitions.define(word).definitions()
+ definitions.define(word, lang).definitions()
);
return index.data("translationsDefinitions", data);
}
diff --git a/src/main/resources/templates/pub/contributing.html b/src/main/resources/templates/pub/contributing.html
index 78b98b3..80d1079 100644
--- a/src/main/resources/templates/pub/contributing.html
+++ b/src/main/resources/templates/pub/contributing.html
@@ -56,8 +56,7 @@
You can send me a patch implementing support for your language. Take a look at the codebase.
I think everything is pretty self-explanatory. You should create a new implementation of the
- WordDefinitionRepository and WordTranslationRepository interfaces and add it to the
- corresponding composite classes.
+ WordDefinitionRepository and WordTranslationRepository interfaces.
The patches should be sent over email with the subject [larousseapi] PATCH: description
diff --git a/src/main/resources/templates/pub/index.html b/src/main/resources/templates/pub/index.html
index 34bcd6f..69ad8cb 100644
--- a/src/main/resources/templates/pub/index.html
+++ b/src/main/resources/templates/pub/index.html
@@ -54,6 +54,11 @@