From 2c5eba14b40f7bea72541c8cfa34f9c5ea0bc8f6 Mon Sep 17 00:00:00 2001
From: Claas Augner <github@caugner.de>
Date: Tue, 19 Jan 2021 17:51:10 +0100
Subject: [PATCH] feat: support batch translation

---
 app/app.py               | 41 ++++++++++++++++++++++++++++------------
 app/templates/index.html | 14 +++++++-------
 2 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/app/app.py b/app/app.py
index fcc2909..f398b8b 100644
--- a/app/app.py
+++ b/app/app.py
@@ -16,7 +16,7 @@ def get_remote_address():
 def create_app(char_limit=-1, req_limit=-1, ga_id=None, debug=False, frontend_language_source="en", frontend_language_target="en"):
     from app.init import boot
     boot()
-    
+
     from app.language import languages
     app = Flask(__name__)
 
@@ -36,9 +36,9 @@ def create_app(char_limit=-1, req_limit=-1, ga_id=None, debug=False, frontend_la
         })
     else:
         frontend_argos_language_source = next(iter([l for l in languages if l.code == frontend_language_source]), None)
-    
+
     frontend_argos_language_target = next(iter([l for l in languages if l.code == frontend_language_target]), None)
-    
+
     # Raise AttributeError to prevent app startup if user input is not valid.
     if frontend_argos_language_source is None:
         raise AttributeError(f"{frontend_language_source} as frontend source language is not supported.")
@@ -126,17 +126,20 @@ def create_app(char_limit=-1, req_limit=-1, ga_id=None, debug=False, frontend_la
           - in: formData
             name: q
             schema:
-              type: string
-              example: Hello world!
+              oneOf:
+                - type: string
+                  example: Hello world!
+                - type: array
+                  example: ['Hello world!']
             required: true
-            description: Text to translate
+            description: Text(s) to translate
           - in: formData
             name: source
             schema:
               type: string
               example: en
             required: true
-            description: Source language code      
+            description: Source language code
           - in: formData
             name: target
             schema:
@@ -152,8 +155,10 @@ def create_app(char_limit=-1, req_limit=-1, ga_id=None, debug=False, frontend_la
               type: object
               properties:
                 translatedText:
-                  type: string
-                  description: Translated text
+                  oneOf:
+                    - type: string
+                    - type: array
+                  description: Translated text(s)
           400:
             description: Invalid request
             schema:
@@ -200,8 +205,16 @@ def create_app(char_limit=-1, req_limit=-1, ga_id=None, debug=False, frontend_la
         if not target_lang:
             abort(400, description="Invalid request: missing target parameter")
 
+        batch = isinstance(q, list)
+
         if char_limit != -1:
-            q = q[:char_limit]
+            if batch:
+              chars = sum([len(text) for text in q])
+            else:
+              chars = len(q)
+
+            if char_limit < chars:
+              abort(400, description="Invalid request: Request (%d) exceeds character limit (%d)" % (chars, char_limit))
 
         if source_lang == 'auto':
             candidate_langs = list(filter(lambda l: l.lang in language_map, detect_langs(q)))
@@ -217,20 +230,24 @@ def create_app(char_limit=-1, req_limit=-1, ga_id=None, debug=False, frontend_la
                     source_lang = 'en'
             else:
                 source_lang = 'en'
-            
+
             if debug:
                 print("Auto detected: %s" % source_lang)
 
         src_lang = next(iter([l for l in languages if l.code == source_lang]), None)
         tgt_lang = next(iter([l for l in languages if l.code == target_lang]), None)
-        
+
         if src_lang is None:
             abort(400, description="%s is not supported" % source_lang)
         if tgt_lang is None:
             abort(400, description="%s is not supported" % target_lang)
 
         translator = src_lang.get_translation(tgt_lang)
+
         try:
+          if batch:
+            return jsonify({"translatedText": [translator.translate(text) for text in q] })
+          else:
             return jsonify({"translatedText": translator.translate(q) })
         except Exception as e:
             abort(500, description="Cannot translate text: %s" % str(e))
diff --git a/app/templates/index.html b/app/templates/index.html
index 76d2c27..3fbe89a 100644
--- a/app/templates/index.html
+++ b/app/templates/index.html
@@ -247,9 +247,9 @@
 window.Prism = window.Prism || {};
 window.Prism.manual = true;
 </script>
-	
+
 <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/prism.min.js"></script>
-	
+
 <script>
 // API host/endpoint
 var BaseUrl = window.location.protocol + "//" + window.location.host;
@@ -317,7 +317,7 @@ document.addEventListener('DOMContentLoaded', function(){
 				return;
 			}
 
-		    self.loading = false;			
+		    self.loading = false;
 		  } else {
 			self.error = "Cannot load /languages";
 			self.loading = false;
@@ -346,8 +346,8 @@ document.addEventListener('DOMContentLoaded', function(){
 			if (this.charactersLimit !== -1 && this.inputText.length >= this.charactersLimit){
 				this.inputText = this.inputText.substring(0, this.charactersLimit);
 			}
-            
-			
+
+
 	  },
 	  computed: {
 	  	requestCode: function(){
@@ -423,7 +423,7 @@ document.addEventListener('DOMContentLoaded', function(){
 				  	var res = JSON.parse(this.response);
 					// Success!
 					if (res.translatedText !== undefined){
-						self.translatedText = res.translatedText; 
+						self.translatedText = res.translatedText;
 					    self.loadingTranslation = false;
 					    self.output = JSON.stringify(res, null, 4);
 					}else{
@@ -450,7 +450,7 @@ document.addEventListener('DOMContentLoaded', function(){
 			this.$refs.translatedTextarea.select();
 			this.$refs.translatedTextarea.setSelectionRange(0, 9999999); /* For mobile devices */
 			document.execCommand("copy");
-			
+
 			if (this.copyTextLabel === "Copy Text"){
 				this.copyTextLabel = "Copied!";
 				var self = this;
-- 
GitLab