mirror of
https://github.com/LibreTranslate/LibreTranslate.git
synced 2024-12-18 08:27:03 +02:00
Merge pull request #22 from caugner/batch-translation
Add support for batch translation
This commit is contained in:
commit
5b0cdae2e7
@ -92,6 +92,7 @@ docker-compose up -d --build
|
|||||||
| --port | Set port to bind the server to | `5000` |
|
| --port | Set port to bind the server to | `5000` |
|
||||||
| --char-limit | Set character limit | `No limit` |
|
| --char-limit | Set character limit | `No limit` |
|
||||||
| --req-limit | Set maximum number of requests per minute per client | `No limit` |
|
| --req-limit | Set maximum number of requests per minute per client | `No limit` |
|
||||||
|
| --batch-limit | Set maximum number of texts to translate in a batch request | `No limit` |
|
||||||
| --ga-id | Enable Google Analytics on the API client page by providing an ID | `No tracking` |
|
| --ga-id | Enable Google Analytics on the API client page by providing an ID | `No tracking` |
|
||||||
| --debug | Enable debug environment | `False` |
|
| --debug | Enable debug environment | `False` |
|
||||||
| --ssl | Whether to enable SSL | `False` |
|
| --ssl | Whether to enable SSL | `False` |
|
||||||
|
48
app/app.py
48
app/app.py
@ -13,10 +13,10 @@ def get_remote_address():
|
|||||||
|
|
||||||
return ip
|
return ip
|
||||||
|
|
||||||
def create_app(char_limit=-1, req_limit=-1, ga_id=None, debug=False, frontend_language_source="en", frontend_language_target="en"):
|
def create_app(char_limit=-1, req_limit=-1, batch_limit=-1, ga_id=None, debug=False, frontend_language_source="en", frontend_language_target="en"):
|
||||||
from app.init import boot
|
from app.init import boot
|
||||||
boot()
|
boot()
|
||||||
|
|
||||||
from app.language import languages
|
from app.language import languages
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@ -36,9 +36,9 @@ def create_app(char_limit=-1, req_limit=-1, ga_id=None, debug=False, frontend_la
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
frontend_argos_language_source = next(iter([l for l in languages if l.code == frontend_language_source]), None)
|
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)
|
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.
|
# Raise AttributeError to prevent app startup if user input is not valid.
|
||||||
if frontend_argos_language_source is None:
|
if frontend_argos_language_source is None:
|
||||||
raise AttributeError(f"{frontend_language_source} as frontend source language is not supported.")
|
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
|
- in: formData
|
||||||
name: q
|
name: q
|
||||||
schema:
|
schema:
|
||||||
type: string
|
oneOf:
|
||||||
example: Hello world!
|
- type: string
|
||||||
|
example: Hello world!
|
||||||
|
- type: array
|
||||||
|
example: ['Hello world!']
|
||||||
required: true
|
required: true
|
||||||
description: Text to translate
|
description: Text(s) to translate
|
||||||
- in: formData
|
- in: formData
|
||||||
name: source
|
name: source
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: en
|
example: en
|
||||||
required: true
|
required: true
|
||||||
description: Source language code
|
description: Source language code
|
||||||
- in: formData
|
- in: formData
|
||||||
name: target
|
name: target
|
||||||
schema:
|
schema:
|
||||||
@ -152,8 +155,10 @@ def create_app(char_limit=-1, req_limit=-1, ga_id=None, debug=False, frontend_la
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
translatedText:
|
translatedText:
|
||||||
type: string
|
oneOf:
|
||||||
description: Translated text
|
- type: string
|
||||||
|
- type: array
|
||||||
|
description: Translated text(s)
|
||||||
400:
|
400:
|
||||||
description: Invalid request
|
description: Invalid request
|
||||||
schema:
|
schema:
|
||||||
@ -200,8 +205,21 @@ def create_app(char_limit=-1, req_limit=-1, ga_id=None, debug=False, frontend_la
|
|||||||
if not target_lang:
|
if not target_lang:
|
||||||
abort(400, description="Invalid request: missing target parameter")
|
abort(400, description="Invalid request: missing target parameter")
|
||||||
|
|
||||||
|
batch = isinstance(q, list)
|
||||||
|
|
||||||
|
if batch and batch_limit != -1:
|
||||||
|
batch_size = len(q)
|
||||||
|
if batch_limit < batch_size:
|
||||||
|
abort(400, description="Invalid request: Request (%d) exceeds text limit (%d)" % (batch_size, batch_limit))
|
||||||
|
|
||||||
if char_limit != -1:
|
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':
|
if source_lang == 'auto':
|
||||||
candidate_langs = list(filter(lambda l: l.lang in language_map, detect_langs(q)))
|
candidate_langs = list(filter(lambda l: l.lang in language_map, detect_langs(q)))
|
||||||
@ -217,20 +235,24 @@ def create_app(char_limit=-1, req_limit=-1, ga_id=None, debug=False, frontend_la
|
|||||||
source_lang = 'en'
|
source_lang = 'en'
|
||||||
else:
|
else:
|
||||||
source_lang = 'en'
|
source_lang = 'en'
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
print("Auto detected: %s" % source_lang)
|
print("Auto detected: %s" % source_lang)
|
||||||
|
|
||||||
src_lang = next(iter([l for l in languages if l.code == source_lang]), None)
|
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)
|
tgt_lang = next(iter([l for l in languages if l.code == target_lang]), None)
|
||||||
|
|
||||||
if src_lang is None:
|
if src_lang is None:
|
||||||
abort(400, description="%s is not supported" % source_lang)
|
abort(400, description="%s is not supported" % source_lang)
|
||||||
if tgt_lang is None:
|
if tgt_lang is None:
|
||||||
abort(400, description="%s is not supported" % target_lang)
|
abort(400, description="%s is not supported" % target_lang)
|
||||||
|
|
||||||
translator = src_lang.get_translation(tgt_lang)
|
translator = src_lang.get_translation(tgt_lang)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if batch:
|
||||||
|
return jsonify({"translatedText": [translator.translate(text) for text in q] })
|
||||||
|
else:
|
||||||
return jsonify({"translatedText": translator.translate(q) })
|
return jsonify({"translatedText": translator.translate(q) })
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
abort(500, description="Cannot translate text: %s" % str(e))
|
abort(500, description="Cannot translate text: %s" % str(e))
|
||||||
|
@ -247,9 +247,9 @@
|
|||||||
window.Prism = window.Prism || {};
|
window.Prism = window.Prism || {};
|
||||||
window.Prism.manual = true;
|
window.Prism.manual = true;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/prism.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/prism.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// API host/endpoint
|
// API host/endpoint
|
||||||
var BaseUrl = window.location.protocol + "//" + window.location.host;
|
var BaseUrl = window.location.protocol + "//" + window.location.host;
|
||||||
@ -317,7 +317,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.loading = false;
|
self.loading = false;
|
||||||
} else {
|
} else {
|
||||||
self.error = "Cannot load /languages";
|
self.error = "Cannot load /languages";
|
||||||
self.loading = false;
|
self.loading = false;
|
||||||
@ -346,8 +346,8 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
if (this.charactersLimit !== -1 && this.inputText.length >= this.charactersLimit){
|
if (this.charactersLimit !== -1 && this.inputText.length >= this.charactersLimit){
|
||||||
this.inputText = this.inputText.substring(0, this.charactersLimit);
|
this.inputText = this.inputText.substring(0, this.charactersLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
requestCode: function(){
|
requestCode: function(){
|
||||||
@ -423,7 +423,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
var res = JSON.parse(this.response);
|
var res = JSON.parse(this.response);
|
||||||
// Success!
|
// Success!
|
||||||
if (res.translatedText !== undefined){
|
if (res.translatedText !== undefined){
|
||||||
self.translatedText = res.translatedText;
|
self.translatedText = res.translatedText;
|
||||||
self.loadingTranslation = false;
|
self.loadingTranslation = false;
|
||||||
self.output = JSON.stringify(res, null, 4);
|
self.output = JSON.stringify(res, null, 4);
|
||||||
}else{
|
}else{
|
||||||
@ -450,7 +450,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
this.$refs.translatedTextarea.select();
|
this.$refs.translatedTextarea.select();
|
||||||
this.$refs.translatedTextarea.setSelectionRange(0, 9999999); /* For mobile devices */
|
this.$refs.translatedTextarea.setSelectionRange(0, 9999999); /* For mobile devices */
|
||||||
document.execCommand("copy");
|
document.execCommand("copy");
|
||||||
|
|
||||||
if (this.copyTextLabel === "Copy Text"){
|
if (this.copyTextLabel === "Copy Text"){
|
||||||
this.copyTextLabel = "Copied!";
|
this.copyTextLabel = "Copied!";
|
||||||
var self = this;
|
var self = this;
|
||||||
|
5
main.py
5
main.py
@ -10,6 +10,8 @@ parser.add_argument('--char-limit', default=-1, type=int, metavar="<number of ch
|
|||||||
help='Set character limit (%(default)s)')
|
help='Set character limit (%(default)s)')
|
||||||
parser.add_argument('--req-limit', default=-1, type=int, metavar="<number>",
|
parser.add_argument('--req-limit', default=-1, type=int, metavar="<number>",
|
||||||
help='Set maximum number of requests per minute per client (%(default)s)')
|
help='Set maximum number of requests per minute per client (%(default)s)')
|
||||||
|
parser.add_argument('--batch-limit', default=-1, type=int, metavar="<number of texts>",
|
||||||
|
help='Set maximum number of texts to translate in a batch request (%(default)s)')
|
||||||
parser.add_argument('--ga-id', type=str, default=None, metavar="<GA ID>",
|
parser.add_argument('--ga-id', type=str, default=None, metavar="<GA ID>",
|
||||||
help='Enable Google Analytics on the API client page by providing an ID (%(default)s)')
|
help='Enable Google Analytics on the API client page by providing an ID (%(default)s)')
|
||||||
parser.add_argument('--debug', default=False, action="store_true",
|
parser.add_argument('--debug', default=False, action="store_true",
|
||||||
@ -25,8 +27,9 @@ args = parser.parse_args()
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = create_app(char_limit=args.char_limit,
|
app = create_app(char_limit=args.char_limit,
|
||||||
req_limit=args.req_limit,
|
req_limit=args.req_limit,
|
||||||
|
batch_limit=args.batch_limit,
|
||||||
ga_id=args.ga_id,
|
ga_id=args.ga_id,
|
||||||
debug=args.debug,
|
debug=args.debug,
|
||||||
frontend_language_source=args.frontend_language_source,
|
frontend_language_source=args.frontend_language_source,
|
||||||
|
Loading…
Reference in New Issue
Block a user