From 9ee5379c38addbe230f01db6e93b9174521e7352 Mon Sep 17 00:00:00 2001 From: VogelT Date: Tue, 21 Apr 2026 10:42:01 +0200 Subject: [PATCH] all in --- .classpath | 41 ++++++++++++++++ .gitignore | 1 + .project | 37 ++++++++++++++ .settings/.jsdtscope | 13 +++++ .settings/org.eclipse.core.resources.prefs | 4 ++ .settings/org.eclipse.jdt.core.prefs | 11 +++++ .settings/org.eclipse.m2e.core.prefs | 4 ++ .settings/org.eclipse.wst.common.component | 10 ++++ ....eclipse.wst.common.project.facet.core.xml | 7 +++ ...rg.eclipse.wst.jsdt.ui.superType.container | 1 + .../org.eclipse.wst.jsdt.ui.superType.name | 1 + .settings/org.eclipse.wst.validation.prefs | 2 + docker-compose.yml | 14 ++++++ docker/Dockerfile | 5 ++ pom.xml | 19 ++++++++ sql/init.sql | 1 + .../translator/TranslatorApplication.java | 11 +++++ .../translator/config/SecurityConfig.java | 16 +++++++ .../controller/AdminController.java | 21 ++++++++ .../controller/TranslationController.java | 25 ++++++++++ .../translator/entity/TranslationLog.java | 18 +++++++ .../repository/TranslationLogRepository.java | 7 +++ .../service/TranslationService.java | 48 +++++++++++++++++++ src/main/resources/application.yml | 13 +++++ src/main/resources/templates/admin.html | 1 + 25 files changed, 331 insertions(+) create mode 100644 .classpath create mode 100644 .gitignore create mode 100644 .project create mode 100644 .settings/.jsdtscope create mode 100644 .settings/org.eclipse.core.resources.prefs create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.eclipse.m2e.core.prefs create mode 100644 .settings/org.eclipse.wst.common.component create mode 100644 .settings/org.eclipse.wst.common.project.facet.core.xml create mode 100644 .settings/org.eclipse.wst.jsdt.ui.superType.container create mode 100644 .settings/org.eclipse.wst.jsdt.ui.superType.name create mode 100644 .settings/org.eclipse.wst.validation.prefs create mode 100644 docker-compose.yml create mode 100644 docker/Dockerfile create mode 100644 pom.xml create mode 100644 sql/init.sql create mode 100644 src/main/java/de/example/translator/TranslatorApplication.java create mode 100644 src/main/java/de/example/translator/config/SecurityConfig.java create mode 100644 src/main/java/de/example/translator/controller/AdminController.java create mode 100644 src/main/java/de/example/translator/controller/TranslationController.java create mode 100644 src/main/java/de/example/translator/entity/TranslationLog.java create mode 100644 src/main/java/de/example/translator/repository/TranslationLogRepository.java create mode 100644 src/main/java/de/example/translator/service/TranslationService.java create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/templates/admin.html diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..5fb8c72 --- /dev/null +++ b/.classpath @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/.project b/.project new file mode 100644 index 0000000..76f2a83 --- /dev/null +++ b/.project @@ -0,0 +1,37 @@ + + + translator + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/.settings/.jsdtscope b/.settings/.jsdtscope new file mode 100644 index 0000000..1ef54ab --- /dev/null +++ b/.settings/.jsdtscope @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..abdea9a --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..412b9be --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.compliance=21 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=21 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..44f5df1 --- /dev/null +++ b/.settings/org.eclipse.wst.common.component @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..3134a21 --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.container b/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.name b/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/.settings/org.eclipse.wst.validation.prefs b/.settings/org.eclipse.wst.validation.prefs new file mode 100644 index 0000000..04cad8c --- /dev/null +++ b/.settings/org.eclipse.wst.validation.prefs @@ -0,0 +1,2 @@ +disabled=06target +eclipse.preferences.version=1 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..a0dd385 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +version: '3.9' +services: + mariadb: + image: mariadb:11 + environment: + MYSQL_DATABASE: translator + MYSQL_USER: translator + MYSQL_PASSWORD: translator + MYSQL_ROOT_PASSWORD: root + volumes: ["./sql:/docker-entrypoint-initdb.d"] + tomcat: + build: docker + ports: ['8080:8080'] + depends_on: [mariadb] \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..cd09e0d --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,5 @@ +FROM eclipse-temurin:21-jre +RUN apt-get update && apt-get install -y python3-pip && pip install argostranslate && argos-translate-cli --download de en +COPY target/translator.war /app.war +EXPOSE 8080 +CMD ["java","-jar","/app.war"] \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..15a31c9 --- /dev/null +++ b/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + de.example + translator + 2.0.0 + war + 21 + org.springframework.bootspring-boot-starter-parent3.2.5 + + org.springframework.bootspring-boot-starter-web + org.springframework.bootspring-boot-starter-data-jpa + org.springframework.bootspring-boot-starter-security + org.springframework.bootspring-boot-starter-thymeleaf + org.mariadb.jdbcmariadb-java-clientruntime + com.github.ben-manes.caffeinecaffeine + \ No newline at end of file diff --git a/sql/init.sql b/sql/init.sql new file mode 100644 index 0000000..c9a5c88 --- /dev/null +++ b/sql/init.sql @@ -0,0 +1 @@ +CREATE DATABASE IF NOT EXISTS translator; \ No newline at end of file diff --git a/src/main/java/de/example/translator/TranslatorApplication.java b/src/main/java/de/example/translator/TranslatorApplication.java new file mode 100644 index 0000000..924c217 --- /dev/null +++ b/src/main/java/de/example/translator/TranslatorApplication.java @@ -0,0 +1,11 @@ +package de.example.translator; + +import org.springframework.boot.*; +import org.springframework.boot.autoconfigure.*; + +@SpringBootApplication +public class TranslatorApplication { + public static void main(String[] a) { + SpringApplication.run(TranslatorApplication.class, a); + } +} \ No newline at end of file diff --git a/src/main/java/de/example/translator/config/SecurityConfig.java b/src/main/java/de/example/translator/config/SecurityConfig.java new file mode 100644 index 0000000..16eb86c --- /dev/null +++ b/src/main/java/de/example/translator/config/SecurityConfig.java @@ -0,0 +1,16 @@ +package de.example.translator.config; + +import org.springframework.context.annotation.*; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.*; + +@Configuration +public class SecurityConfig { + @Bean + SecurityFilterChain f(HttpSecurity h) throws Exception { + h.csrf(c -> c.disable()) + .authorizeHttpRequests(a -> a.requestMatchers("/admin").authenticated().anyRequest().permitAll()) + .httpBasic(); + return h.build(); + } +} \ No newline at end of file diff --git a/src/main/java/de/example/translator/controller/AdminController.java b/src/main/java/de/example/translator/controller/AdminController.java new file mode 100644 index 0000000..146d356 --- /dev/null +++ b/src/main/java/de/example/translator/controller/AdminController.java @@ -0,0 +1,21 @@ +package de.example.translator.controller; + +import org.springframework.stereotype.*; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; +import de.example.translator.repository.*; + +@Controller +public class AdminController { + private final TranslationLogRepository r; + + public AdminController(TranslationLogRepository r) { + this.r = r; + } + + @GetMapping("/admin") + public String a(Model m) { + m.addAttribute("logs", r.findAll()); + return "admin"; + } +} \ No newline at end of file diff --git a/src/main/java/de/example/translator/controller/TranslationController.java b/src/main/java/de/example/translator/controller/TranslationController.java new file mode 100644 index 0000000..a951011 --- /dev/null +++ b/src/main/java/de/example/translator/controller/TranslationController.java @@ -0,0 +1,25 @@ +package de.example.translator.controller; + +import org.springframework.web.bind.annotation.*; +import java.util.*; +import de.example.translator.service.*; + +@RestController +@RequestMapping("/api") +public class TranslationController { + private final TranslationService s; + + public TranslationController(TranslationService s) { + this.s = s; + } + + @GetMapping("/translate") + public String t(@RequestParam String from, @RequestParam String to, @RequestParam String text) { + return s.translate(from, to, text); + } + + @PostMapping("/batch") + public List b(@RequestParam String from, @RequestParam String to, @RequestBody List texts) { + return s.batch(from, to, texts); + } +} \ No newline at end of file diff --git a/src/main/java/de/example/translator/entity/TranslationLog.java b/src/main/java/de/example/translator/entity/TranslationLog.java new file mode 100644 index 0000000..8114612 --- /dev/null +++ b/src/main/java/de/example/translator/entity/TranslationLog.java @@ -0,0 +1,18 @@ +package de.example.translator.entity; + +import jakarta.persistence.*; +import java.time.*; + +@Entity +public class TranslationLog { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + public Long id; + public String sourceLang; + public String targetLang; + @Column(columnDefinition = "TEXT") + public String sourceText; + @Column(columnDefinition = "TEXT") + public String translatedText; + public LocalDateTime createdAt = LocalDateTime.now(); +} \ No newline at end of file diff --git a/src/main/java/de/example/translator/repository/TranslationLogRepository.java b/src/main/java/de/example/translator/repository/TranslationLogRepository.java new file mode 100644 index 0000000..57381e5 --- /dev/null +++ b/src/main/java/de/example/translator/repository/TranslationLogRepository.java @@ -0,0 +1,7 @@ +package de.example.translator.repository; + +import org.springframework.data.jpa.repository.*; +import de.example.translator.entity.*; + +public interface TranslationLogRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/de/example/translator/service/TranslationService.java b/src/main/java/de/example/translator/service/TranslationService.java new file mode 100644 index 0000000..f3f7990 --- /dev/null +++ b/src/main/java/de/example/translator/service/TranslationService.java @@ -0,0 +1,48 @@ +package de.example.translator.service; + +import org.springframework.stereotype.*; +import com.github.benmanes.caffeine.cache.*; +import java.util.*; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.stream.*; +import de.example.translator.repository.*; +import de.example.translator.entity.*; + +@Service +public class TranslationService { + private final TranslationLogRepository r; + private final Cache cache = Caffeine.newBuilder().maximumSize(1000).build(); + + public TranslationService(TranslationLogRepository r) { + this.r = r; + } + + public String translate(String f, String t, String x) { + String k = f + t + x; + return cache.get(k, kk -> { + String tr = argos(f, t, x); + TranslationLog l = new TranslationLog(); + l.sourceLang = f; + l.targetLang = t; + l.sourceText = x; + l.translatedText = tr; + r.save(l); + return tr; + }); + } + + public List batch(String f, String t, List xs) { + return xs.stream().map(x -> translate(f, t, x)).toList(); + } + + private String argos(String f, String t, String x) { + try { + Process p = new ProcessBuilder("argos-translate", "--from-lang", f, "--to-lang", t, "--text", x).start(); + return new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8)).lines() + .collect(Collectors.joining()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..7998823 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,13 @@ +spring: + datasource: + url: jdbc:mariadb://mariadb:3306/translator + username: translator + password: translator + jpa: + hibernate: + ddl-auto: update + show-sql: false +server: + port: 8080 +api: + key: secret123 diff --git a/src/main/resources/templates/admin.html b/src/main/resources/templates/admin.html new file mode 100644 index 0000000..e3a14c8 --- /dev/null +++ b/src/main/resources/templates/admin.html @@ -0,0 +1 @@ +

Translation Logs

IDFromToTextResult
\ No newline at end of file