mirror of
https://github.com/LibreTranslate/LibreTranslate.git
synced 2024-11-25 17:31:00 +00:00
Tagged all strings
This commit is contained in:
parent
19c3c04ca6
commit
edd3d6931d
8 changed files with 492 additions and 102 deletions
|
@ -9,7 +9,7 @@ if __name__ == "__main__":
|
||||||
os.makedirs(locales_dir)
|
os.makedirs(locales_dir)
|
||||||
|
|
||||||
print("Compiling locales")
|
print("Compiling locales")
|
||||||
sys.argv = ["", "compile", "-d", locales_dir]
|
sys.argv = ["", "compile", "-f", "-d", locales_dir]
|
||||||
pybabel()
|
pybabel()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,11 @@ from flask_swagger_ui import get_swaggerui_blueprint
|
||||||
from translatehtml import translate_html
|
from translatehtml import translate_html
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
from werkzeug.exceptions import HTTPException
|
from werkzeug.exceptions import HTTPException
|
||||||
from flask_babel import Babel, gettext as _
|
from flask_babel import Babel
|
||||||
|
|
||||||
from libretranslate import flood, remove_translated_files, security
|
from libretranslate import flood, remove_translated_files, security
|
||||||
from libretranslate.language import detect_languages, improve_translation_formatting
|
from libretranslate.language import detect_languages, improve_translation_formatting
|
||||||
from libretranslate.locales import get_available_locales, gettext_escaped, gettext_html
|
from libretranslate.locales import _, _lazy, get_available_locales, gettext_escaped, gettext_html
|
||||||
|
|
||||||
from .api_keys import Database, RemoteDatabase
|
from .api_keys import Database, RemoteDatabase
|
||||||
from .suggestions import Database as SuggestionsDatabase
|
from .suggestions import Database as SuggestionsDatabase
|
||||||
|
@ -188,7 +188,7 @@ def create_app(args):
|
||||||
if args.metrics_auth_token:
|
if args.metrics_auth_token:
|
||||||
authorization = request.headers.get('Authorization')
|
authorization = request.headers.get('Authorization')
|
||||||
if authorization != "Bearer " + args.metrics_auth_token:
|
if authorization != "Bearer " + args.metrics_auth_token:
|
||||||
abort(401, description="Unauthorized")
|
abort(401, description=_("Unauthorized"))
|
||||||
|
|
||||||
registry = CollectorRegistry()
|
registry = CollectorRegistry()
|
||||||
multiprocess.MultiProcessCollector(registry)
|
multiprocess.MultiProcessCollector(registry)
|
||||||
|
@ -206,7 +206,7 @@ def create_app(args):
|
||||||
ip = get_remote_address()
|
ip = get_remote_address()
|
||||||
|
|
||||||
if flood.is_banned(ip):
|
if flood.is_banned(ip):
|
||||||
abort(403, description="Too many request limits violations")
|
abort(403, description=_("Too many request limits violations"))
|
||||||
|
|
||||||
if args.api_keys:
|
if args.api_keys:
|
||||||
ak = get_req_api_key()
|
ak = get_req_api_key()
|
||||||
|
@ -215,16 +215,16 @@ def create_app(args):
|
||||||
):
|
):
|
||||||
abort(
|
abort(
|
||||||
403,
|
403,
|
||||||
description="Invalid API key",
|
description=_("Invalid API key"),
|
||||||
)
|
)
|
||||||
elif (
|
elif (
|
||||||
args.require_api_key_origin
|
args.require_api_key_origin
|
||||||
and api_keys_db.lookup(ak) is None
|
and api_keys_db.lookup(ak) is None
|
||||||
and request.headers.get("Origin") != args.require_api_key_origin
|
and request.headers.get("Origin") != args.require_api_key_origin
|
||||||
):
|
):
|
||||||
description = "Please contact the server operator to get an API key"
|
description = _("Please contact the server operator to get an API key")
|
||||||
if args.get_api_key_link:
|
if args.get_api_key_link:
|
||||||
description = "Visit %s to get an API key" % args.get_api_key_link
|
description = _("Visit %(url)s to get an API key", url=args.get_api_key_link)
|
||||||
abort(
|
abort(
|
||||||
403,
|
403,
|
||||||
description=description,
|
description=description,
|
||||||
|
@ -264,7 +264,7 @@ def create_app(args):
|
||||||
@bp.errorhandler(429)
|
@bp.errorhandler(429)
|
||||||
def slow_down_error(e):
|
def slow_down_error(e):
|
||||||
flood.report(get_remote_address())
|
flood.report(get_remote_address())
|
||||||
return jsonify({"error": "Slowdown: " + str(e.description)}), 429
|
return jsonify({"error": _("Slowdown:") + " " + str(e.description)}), 429
|
||||||
|
|
||||||
@bp.errorhandler(403)
|
@bp.errorhandler(403)
|
||||||
def denied(e):
|
def denied(e):
|
||||||
|
@ -294,7 +294,8 @@ def create_app(args):
|
||||||
if args.disable_web_ui:
|
if args.disable_web_ui:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
return render_template("app.js.template")
|
return render_template("app.js.template",
|
||||||
|
get_api_key_link=args.get_api_key_link)
|
||||||
|
|
||||||
@bp.get("/languages")
|
@bp.get("/languages")
|
||||||
@limiter.exempt
|
@limiter.exempt
|
||||||
|
@ -325,7 +326,7 @@ def create_app(args):
|
||||||
type: string
|
type: string
|
||||||
description: Supported target language codes
|
description: Supported target language codes
|
||||||
"""
|
"""
|
||||||
return jsonify([{"code": l.code, "name": l.name, "targets": language_pairs.get(l.code, [])} for l in languages])
|
return jsonify([{"code": l.code, "name": _lazy(l.name), "targets": language_pairs.get(l.code, [])} for l in languages])
|
||||||
|
|
||||||
# Add cors
|
# Add cors
|
||||||
@bp.after_request
|
@bp.after_request
|
||||||
|
@ -454,11 +455,11 @@ def create_app(args):
|
||||||
text_format = request.values.get("format")
|
text_format = request.values.get("format")
|
||||||
|
|
||||||
if not q:
|
if not q:
|
||||||
abort(400, description="Invalid request: missing q parameter")
|
abort(400, description=_("Invalid request: missing %(name)s parameter", name='q'))
|
||||||
if not source_lang:
|
if not source_lang:
|
||||||
abort(400, description="Invalid request: missing source parameter")
|
abort(400, description=_("Invalid request: missing %(name)s parameter", name='source'))
|
||||||
if not target_lang:
|
if not target_lang:
|
||||||
abort(400, description="Invalid request: missing target parameter")
|
abort(400, description=_("Invalid request: missing %(name)s parameter", name='target'))
|
||||||
|
|
||||||
batch = isinstance(q, list)
|
batch = isinstance(q, list)
|
||||||
|
|
||||||
|
@ -467,8 +468,7 @@ def create_app(args):
|
||||||
if args.batch_limit < batch_size:
|
if args.batch_limit < batch_size:
|
||||||
abort(
|
abort(
|
||||||
400,
|
400,
|
||||||
description="Invalid request: Request (%d) exceeds text limit (%d)"
|
description=_("Invalid request: request (%(size)s) exceeds text limit (%(limit)s)", size=batch_size, limit=args.batch_limit),
|
||||||
% (batch_size, args.batch_limit),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if args.char_limit != -1:
|
if args.char_limit != -1:
|
||||||
|
@ -480,8 +480,7 @@ def create_app(args):
|
||||||
if args.char_limit < chars:
|
if args.char_limit < chars:
|
||||||
abort(
|
abort(
|
||||||
400,
|
400,
|
||||||
description="Invalid request: Request (%d) exceeds character limit (%d)"
|
description=_("Invalid request: request (%(size)s) exceeds text limit (%(limit)s)", size=chars, limit=args.char_limit),
|
||||||
% (chars, args.char_limit),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if source_lang == "auto":
|
if source_lang == "auto":
|
||||||
|
@ -514,18 +513,18 @@ def create_app(args):
|
||||||
|
|
||||||
for idx, lang in enumerate(src_langs):
|
for idx, lang in enumerate(src_langs):
|
||||||
if lang is None:
|
if lang is None:
|
||||||
abort(400, description="%s is not supported" % source_langs[idx])
|
abort(400, description=_("%(lang)s is not supported", lang=source_langs[idx]))
|
||||||
|
|
||||||
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 tgt_lang is None:
|
if tgt_lang is None:
|
||||||
abort(400, description="%s is not supported" % target_lang)
|
abort(400, description=_("%(lang)s is not supported",lang=target_lang))
|
||||||
|
|
||||||
if not text_format:
|
if not text_format:
|
||||||
text_format = "text"
|
text_format = "text"
|
||||||
|
|
||||||
if text_format not in ["text", "html"]:
|
if text_format not in ["text", "html"]:
|
||||||
abort(400, description="%s format is not supported" % text_format)
|
abort(400, description=_("%(format)s format is not supported", format=text_format))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if batch:
|
if batch:
|
||||||
|
@ -533,7 +532,7 @@ def create_app(args):
|
||||||
for idx, text in enumerate(q):
|
for idx, text in enumerate(q):
|
||||||
translator = src_langs[idx].get_translation(tgt_lang)
|
translator = src_langs[idx].get_translation(tgt_lang)
|
||||||
if translator is None:
|
if translator is None:
|
||||||
abort(400, description="%s (%s) is not available as a target language from %s (%s)" % (tgt_lang.name, tgt_lang.code, src_langs[idx].name, src_langs[idx].code))
|
abort(400, description=_("%(tname)s (%(tcode)s) is not available as a target language from %(sname)s (%(scode)s)", tname=_lazy(tgt_lang.name), tcode=tgt_lang.code, sname=_lazy(src_langs[idx].name), scode=src_langs[idx].code))
|
||||||
|
|
||||||
if text_format == "html":
|
if text_format == "html":
|
||||||
translated_text = str(translate_html(translator, text))
|
translated_text = str(translate_html(translator, text))
|
||||||
|
@ -557,7 +556,7 @@ def create_app(args):
|
||||||
else:
|
else:
|
||||||
translator = src_langs[0].get_translation(tgt_lang)
|
translator = src_langs[0].get_translation(tgt_lang)
|
||||||
if translator is None:
|
if translator is None:
|
||||||
abort(400, description="%s (%s) is not available as a target language from %s (%s)" % (tgt_lang.name, tgt_lang.code, src_langs[0].name, src_langs[0].code))
|
abort(400, description=_("%(tname)s (%(tcode)s) is not available as a target language from %(sname)s (%(scode)s)", tname=_lazy(tgt_lang.name), tcode=tgt_lang.code, sname=_lazy(src_langs[0].name), scode=src_langs[0].code))
|
||||||
|
|
||||||
if text_format == "html":
|
if text_format == "html":
|
||||||
translated_text = str(translate_html(translator, q))
|
translated_text = str(translate_html(translator, q))
|
||||||
|
@ -578,7 +577,7 @@ def create_app(args):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
abort(500, description="Cannot translate text: %s" % str(e))
|
abort(500, description=_("Cannot translate text: %(text)s", text=str(e)))
|
||||||
|
|
||||||
@bp.post("/translate_file")
|
@bp.post("/translate_file")
|
||||||
@access_check
|
@access_check
|
||||||
|
@ -665,36 +664,36 @@ def create_app(args):
|
||||||
description: Error message
|
description: Error message
|
||||||
"""
|
"""
|
||||||
if args.disable_files_translation:
|
if args.disable_files_translation:
|
||||||
abort(403, description="Files translation are disabled on this server.")
|
abort(403, description=_("Files translation are disabled on this server."))
|
||||||
|
|
||||||
source_lang = request.form.get("source")
|
source_lang = request.form.get("source")
|
||||||
target_lang = request.form.get("target")
|
target_lang = request.form.get("target")
|
||||||
file = request.files['file']
|
file = request.files['file']
|
||||||
|
|
||||||
if not file:
|
if not file:
|
||||||
abort(400, description="Invalid request: missing file parameter")
|
abort(400, description=_("Invalid request: missing %(name)s parameter", name='file'))
|
||||||
if not source_lang:
|
if not source_lang:
|
||||||
abort(400, description="Invalid request: missing source parameter")
|
abort(400, description=_("Invalid request: missing %(name)s parameter", name='source'))
|
||||||
if not target_lang:
|
if not target_lang:
|
||||||
abort(400, description="Invalid request: missing target parameter")
|
abort(400, description=_("Invalid request: missing %(name)s parameter", name='target'))
|
||||||
|
|
||||||
if file.filename == '':
|
if file.filename == '':
|
||||||
abort(400, description="Invalid request: empty file")
|
abort(400, description=_("Invalid request: empty file"))
|
||||||
|
|
||||||
if os.path.splitext(file.filename)[1] not in frontend_argos_supported_files_format:
|
if os.path.splitext(file.filename)[1] not in frontend_argos_supported_files_format:
|
||||||
abort(400, description="Invalid request: file format not supported")
|
abort(400, description=_("Invalid request: file format not supported"))
|
||||||
|
|
||||||
source_langs = [source_lang]
|
source_langs = [source_lang]
|
||||||
src_langs = [next(iter([l for l in languages if l.code == source_lang]), None) for source_lang in source_langs]
|
src_langs = [next(iter([l for l in languages if l.code == source_lang]), None) for source_lang in source_langs]
|
||||||
|
|
||||||
for idx, lang in enumerate(src_langs):
|
for idx, lang in enumerate(src_langs):
|
||||||
if lang is None:
|
if lang is None:
|
||||||
abort(400, description="%s is not supported" % source_langs[idx])
|
abort(400, description=_("%(lang)s is not supported", lang=source_langs[idx]))
|
||||||
|
|
||||||
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 tgt_lang is None:
|
if tgt_lang is None:
|
||||||
abort(400, description="%s is not supported" % target_lang)
|
abort(400, description=_("%(lang)s is not supported", lang=target_lang))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
filename = str(uuid.uuid4()) + '.' + secure_filename(file.filename)
|
filename = str(uuid.uuid4()) + '.' + secure_filename(file.filename)
|
||||||
|
@ -719,7 +718,7 @@ def create_app(args):
|
||||||
Download a translated file
|
Download a translated file
|
||||||
"""
|
"""
|
||||||
if args.disable_files_translation:
|
if args.disable_files_translation:
|
||||||
abort(400, description="Files translation are disabled on this server.")
|
abort(400, description=_("Files translation are disabled on this server."))
|
||||||
|
|
||||||
filepath = os.path.join(get_upload_dir(), filename)
|
filepath = os.path.join(get_upload_dir(), filename)
|
||||||
try:
|
try:
|
||||||
|
@ -727,7 +726,7 @@ def create_app(args):
|
||||||
if os.path.isfile(checked_filepath):
|
if os.path.isfile(checked_filepath):
|
||||||
filepath = checked_filepath
|
filepath = checked_filepath
|
||||||
except security.SuspiciousFileOperation:
|
except security.SuspiciousFileOperation:
|
||||||
abort(400, description="Invalid filename")
|
abort(400, description=_("Invalid filename"))
|
||||||
|
|
||||||
return_data = io.BytesIO()
|
return_data = io.BytesIO()
|
||||||
with open(filepath, 'rb') as fo:
|
with open(filepath, 'rb') as fo:
|
||||||
|
@ -820,9 +819,6 @@ def create_app(args):
|
||||||
type: string
|
type: string
|
||||||
description: Error message
|
description: Error message
|
||||||
"""
|
"""
|
||||||
if flood.is_banned(get_remote_address()):
|
|
||||||
abort(403, description="Too many request limits violations")
|
|
||||||
|
|
||||||
if request.is_json:
|
if request.is_json:
|
||||||
json = get_json_dict(request)
|
json = get_json_dict(request)
|
||||||
q = json.get("q")
|
q = json.get("q")
|
||||||
|
@ -830,7 +826,7 @@ def create_app(args):
|
||||||
q = request.values.get("q")
|
q = request.values.get("q")
|
||||||
|
|
||||||
if not q:
|
if not q:
|
||||||
abort(400, description="Invalid request: missing q parameter")
|
abort(400, description=_("Invalid request: missing %(name)s parameter", name='q'))
|
||||||
|
|
||||||
return jsonify(detect_languages(q))
|
return jsonify(detect_languages(q))
|
||||||
|
|
||||||
|
@ -903,11 +899,11 @@ def create_app(args):
|
||||||
"language": {
|
"language": {
|
||||||
"source": {
|
"source": {
|
||||||
"code": frontend_argos_language_source.code,
|
"code": frontend_argos_language_source.code,
|
||||||
"name": frontend_argos_language_source.name,
|
"name": _lazy(frontend_argos_language_source.name),
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"code": frontend_argos_language_target.code,
|
"code": frontend_argos_language_target.code,
|
||||||
"name": frontend_argos_language_target.name,
|
"name": _lazy(frontend_argos_language_target.name),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -971,7 +967,7 @@ def create_app(args):
|
||||||
description: Error message
|
description: Error message
|
||||||
"""
|
"""
|
||||||
if not args.suggestions:
|
if not args.suggestions:
|
||||||
abort(403, description="Suggestions are disabled on this server.")
|
abort(403, description=_("Suggestions are disabled on this server."))
|
||||||
|
|
||||||
q = request.values.get("q")
|
q = request.values.get("q")
|
||||||
s = request.values.get("s")
|
s = request.values.get("s")
|
||||||
|
@ -979,13 +975,13 @@ def create_app(args):
|
||||||
target_lang = request.values.get("target")
|
target_lang = request.values.get("target")
|
||||||
|
|
||||||
if not q:
|
if not q:
|
||||||
abort(400, description="Invalid request: missing q parameter")
|
abort(400, description=_("Invalid request: missing %(name)s parameter", name='q'))
|
||||||
if not s:
|
if not s:
|
||||||
abort(400, description="Invalid request: missing s parameter")
|
abort(400, description=_("Invalid request: missing %(name)s parameter", name='s'))
|
||||||
if not source_lang:
|
if not source_lang:
|
||||||
abort(400, description="Invalid request: missing source parameter")
|
abort(400, description=_("Invalid request: missing %(name)s parameter", name='source'))
|
||||||
if not target_lang:
|
if not target_lang:
|
||||||
abort(400, description="Invalid request: missing target parameter")
|
abort(400, description=_("Invalid request: missing %(name)s parameter", name='target'))
|
||||||
|
|
||||||
SuggestionsDatabase().add(q, s, source_lang, target_lang)
|
SuggestionsDatabase().add(q, s, source_lang, target_lang)
|
||||||
return jsonify({"success": True})
|
return jsonify({"success": True})
|
||||||
|
@ -1016,8 +1012,6 @@ def create_app(args):
|
||||||
def get_locale():
|
def get_locale():
|
||||||
return request.accept_languages.best_match(get_available_locales())
|
return request.accept_languages.best_match(get_available_locales())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.jinja_env.globals.update(_e=gettext_escaped, _h=gettext_html)
|
app.jinja_env.globals.update(_e=gettext_escaped, _h=gettext_html)
|
||||||
|
|
||||||
# Call factory function to create our blueprint
|
# Call factory function to create our blueprint
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import os
|
import os
|
||||||
|
import json
|
||||||
from functools import cache
|
from functools import cache
|
||||||
from flask_babel import gettext as _
|
from flask_babel import gettext as _
|
||||||
|
from flask_babel import lazy_gettext as _lazy
|
||||||
|
|
||||||
from markupsafe import escape, Markup
|
from markupsafe import escape, Markup
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
|
@ -12,7 +15,7 @@ def get_available_locales():
|
||||||
|
|
||||||
# Javascript code should use _e instead of _
|
# Javascript code should use _e instead of _
|
||||||
def gettext_escaped(text, **variables):
|
def gettext_escaped(text, **variables):
|
||||||
return _(text, **variables).replace("'", "\\'")
|
return json.dumps(_(text, **variables))
|
||||||
|
|
||||||
# HTML should be escaped using _h instead of _
|
# HTML should be escaped using _h instead of _
|
||||||
def gettext_html(text, **variables):
|
def gettext_html(text, **variables):
|
||||||
|
|
1
libretranslate/locales/.gitignore
vendored
1
libretranslate/locales/.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
**/*.mo
|
**/*.mo
|
||||||
|
.langs.py
|
|
@ -1,52 +1,309 @@
|
||||||
# Italian translations for PROJECT.
|
# Italian translations for LibreTranslate.
|
||||||
# Copyright (C) 2023 ORGANIZATION
|
# Copyright (C) 2023 LibreTranslate Authors
|
||||||
# This file is distributed under the same license as the PROJECT project.
|
# This file is distributed under the same license as the LibreTranslate
|
||||||
|
# project.
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PROJECT VERSION\n"
|
"Project-Id-Version: LibreTranslate 1.3.8\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2023-01-04 16:34-0500\n"
|
"POT-Creation-Date: 2023-01-05 13:11-0500\n"
|
||||||
"PO-Revision-Date: 2023-01-04 12:27-0500\n"
|
"PO-Revision-Date: 2023-01-05 13:11-0500\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language: it\n"
|
|
||||||
"Language-Team: it <LL@li.org>\n"
|
"Language-Team: it <LL@li.org>\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Language: it\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=utf-8\n"
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
"Generated-By: Babel 2.11.0\n"
|
"Generated-By: Babel 2.11.0\n"
|
||||||
|
|
||||||
#: libretranslate/app.py:58
|
#: libretranslate/app.py:58
|
||||||
msgid "Invalid JSON format"
|
msgid "Invalid JSON format"
|
||||||
msgstr "Formato JSON non valido"
|
msgstr "Formato JSON non valido"
|
||||||
|
|
||||||
#: libretranslate/app.py:126
|
#: libretranslate/app.py:126 libretranslate/templates/app.js.template:427
|
||||||
msgid "Auto Detect"
|
msgid "Auto Detect"
|
||||||
msgstr "Rilevamento automatico"
|
msgstr "Rilevamento automatico"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:191
|
||||||
|
msgid "Unauthorized"
|
||||||
|
msgstr "Non autorizzato"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:209
|
||||||
|
msgid "Too many request limits violations"
|
||||||
|
msgstr "Troppe richieste limitano le violazioni"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:218
|
||||||
|
msgid "Invalid API key"
|
||||||
|
msgstr "Chiave API non valida"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:225
|
||||||
|
msgid "Please contact the server operator to get an API key"
|
||||||
|
msgstr ""
|
||||||
|
"Si prega di contattare l'operatore del server per ottenere una chiave API"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:227
|
||||||
|
#, python-format
|
||||||
|
msgid "Visit %(url)s to get an API key"
|
||||||
|
msgstr "Visita %(url)s per ottenere una chiave API"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:267
|
||||||
|
msgid "Slowdown:"
|
||||||
|
msgstr "Rallenta:"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:458 libretranslate/app.py:460
|
||||||
|
#: libretranslate/app.py:462 libretranslate/app.py:674
|
||||||
|
#: libretranslate/app.py:676 libretranslate/app.py:678
|
||||||
|
#: libretranslate/app.py:829 libretranslate/app.py:978
|
||||||
|
#: libretranslate/app.py:980 libretranslate/app.py:982
|
||||||
|
#: libretranslate/app.py:984
|
||||||
|
#, python-format
|
||||||
|
msgid "Invalid request: missing %(name)s parameter"
|
||||||
|
msgstr "Richiesta non valida: mancante %(name)s parametro"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:471 libretranslate/app.py:483
|
||||||
|
#, python-format
|
||||||
|
msgid "Invalid request: request (%(size)s) exceeds text limit (%(limit)s)"
|
||||||
|
msgstr ""
|
||||||
|
"Richiesta non valida: richiesta (%(size)s) supera il limite di testo "
|
||||||
|
"(%(limit)s)"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:516 libretranslate/app.py:521
|
||||||
|
#: libretranslate/app.py:691 libretranslate/app.py:696
|
||||||
|
#, python-format
|
||||||
|
msgid "%(lang)s is not supported"
|
||||||
|
msgstr "%(lang)s non è supportato"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:527
|
||||||
|
#, python-format
|
||||||
|
msgid "%(format)s format is not supported"
|
||||||
|
msgstr "%(format)s formato non è supportato"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:535 libretranslate/app.py:559
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"%(tname)s (%(tcode)s) is not available as a target language from %(sname)s "
|
||||||
|
"(%(scode)s)"
|
||||||
|
msgstr ""
|
||||||
|
"%(tname)s (%(tcode)s) non è disponibile come lingua di destinazione "
|
||||||
|
"%(sname)s (%(scode)s)"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:580
|
||||||
|
#, python-format
|
||||||
|
msgid "Cannot translate text: %(text)s"
|
||||||
|
msgstr "Non può tradurre il testo: %(text)s"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:667 libretranslate/app.py:721
|
||||||
|
msgid "Files translation are disabled on this server."
|
||||||
|
msgstr "La traduzione dei file è disabilitata su questo server."
|
||||||
|
|
||||||
|
#: libretranslate/app.py:681
|
||||||
|
msgid "Invalid request: empty file"
|
||||||
|
msgstr "Richiesta non valida: file vuoto"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:684
|
||||||
|
msgid "Invalid request: file format not supported"
|
||||||
|
msgstr "Richiesta non valida: formato file non supportato"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:729
|
||||||
|
msgid "Invalid filename"
|
||||||
|
msgstr "Invalid filename"
|
||||||
|
|
||||||
|
#: libretranslate/app.py:970
|
||||||
|
msgid "Suggestions are disabled on this server."
|
||||||
|
msgstr "I suggerimenti sono disabilitati su questo server."
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:1
|
||||||
|
msgid "English"
|
||||||
|
msgstr "Inglese"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:2
|
||||||
|
msgid "Arabic"
|
||||||
|
msgstr "Arabo"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:3
|
||||||
|
msgid "Azerbaijani"
|
||||||
|
msgstr "Azerbaigian"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:4
|
||||||
|
msgid "Chinese"
|
||||||
|
msgstr "Cinese"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:5
|
||||||
|
msgid "Czech"
|
||||||
|
msgstr "Ceco"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:6
|
||||||
|
msgid "Danish"
|
||||||
|
msgstr "Danese"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:7
|
||||||
|
msgid "Dutch"
|
||||||
|
msgstr "Paesi Bassi"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:8
|
||||||
|
msgid "Esperanto"
|
||||||
|
msgstr "Esperanto"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:9
|
||||||
|
msgid "Finnish"
|
||||||
|
msgstr "Finlandia"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:10
|
||||||
|
msgid "French"
|
||||||
|
msgstr "Francese"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:11
|
||||||
|
msgid "German"
|
||||||
|
msgstr "Germania"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:12
|
||||||
|
msgid "Greek"
|
||||||
|
msgstr "Greco"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:13
|
||||||
|
msgid "Hebrew"
|
||||||
|
msgstr "Ebraico"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:14
|
||||||
|
msgid "Hindi"
|
||||||
|
msgstr "Hindi"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:15
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr "Ungherese"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:16
|
||||||
|
msgid "Indonesian"
|
||||||
|
msgstr "Indonesiano"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:17
|
||||||
|
msgid "Irish"
|
||||||
|
msgstr "Irlanda"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:18
|
||||||
|
msgid "Italian"
|
||||||
|
msgstr "Italiano"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:19
|
||||||
|
msgid "Japanese"
|
||||||
|
msgstr "Giappone"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:20
|
||||||
|
msgid "Korean"
|
||||||
|
msgstr "Coreano"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:21
|
||||||
|
msgid "Persian"
|
||||||
|
msgstr "Persiano"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:22
|
||||||
|
msgid "Polish"
|
||||||
|
msgstr "Polacco"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:23
|
||||||
|
msgid "Portuguese"
|
||||||
|
msgstr "Portoghese"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:24
|
||||||
|
msgid "Russian"
|
||||||
|
msgstr "Russo"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:25
|
||||||
|
msgid "Slovak"
|
||||||
|
msgstr "Slovacchia"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:26
|
||||||
|
msgid "Spanish"
|
||||||
|
msgstr "Spagnolo"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:27
|
||||||
|
msgid "Swedish"
|
||||||
|
msgstr "Svezia"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:28
|
||||||
|
msgid "Turkish"
|
||||||
|
msgstr "Turco"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:29
|
||||||
|
msgid "Ukranian"
|
||||||
|
msgstr "Ucraina"
|
||||||
|
|
||||||
|
#: libretranslate/locales/.langs.py:30
|
||||||
|
msgid "Vietnamese"
|
||||||
|
msgstr "Vietnamita"
|
||||||
|
|
||||||
#: libretranslate/templates/app.js.template:31
|
#: libretranslate/templates/app.js.template:31
|
||||||
|
#: libretranslate/templates/app.js.template:279
|
||||||
msgid "Copy text"
|
msgid "Copy text"
|
||||||
msgstr "Copia testo"
|
msgstr "Copia testo"
|
||||||
|
|
||||||
#: libretranslate/templates/app.js.template:72
|
#: libretranslate/templates/app.js.template:72
|
||||||
|
#: libretranslate/templates/app.js.template:78
|
||||||
|
#: libretranslate/templates/app.js.template:83
|
||||||
|
#: libretranslate/templates/app.js.template:262
|
||||||
|
#: libretranslate/templates/app.js.template:332
|
||||||
|
#: libretranslate/templates/app.js.template:402
|
||||||
|
#: libretranslate/templates/app.js.template:447
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Cannot load %(url)s"
|
msgid "Cannot load %(url)s"
|
||||||
msgstr "Non riesco a caricare %(url)s"
|
msgstr "Non riesco a caricare %(url)s"
|
||||||
|
|
||||||
#: libretranslate/templates/index.html:6 libretranslate/templates/index.html:26
|
#: libretranslate/templates/app.js.template:253
|
||||||
msgid "LibreTranslate - Free and Open Source Machine Translation API"
|
#: libretranslate/templates/app.js.template:323
|
||||||
msgstr "API di traduzione automatica open source < ' a"
|
#: libretranslate/templates/app.js.template:385
|
||||||
|
#: libretranslate/templates/app.js.template:395
|
||||||
|
msgid "Unknown error"
|
||||||
|
msgstr "Errore sconosciuto"
|
||||||
|
|
||||||
#: libretranslate/templates/index.html:8 libretranslate/templates/index.html:30
|
#: libretranslate/templates/app.js.template:276
|
||||||
|
msgid "Copied"
|
||||||
|
msgstr "Copie"
|
||||||
|
|
||||||
|
#: libretranslate/templates/app.js.template:320
|
||||||
msgid ""
|
msgid ""
|
||||||
"Free and Open Source Machine Translation API. Self-hosted, offline "
|
"Thanks for your correction. Note the suggestion will not take effect right "
|
||||||
"capable and easy to setup. Run your own API server in just a few minutes."
|
"away."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"API di traduzione automatica gratuita e open source. Auto-hosted, offline"
|
"Grazie per la sua correzione. Si noti che il suggerimento non avrà effetto "
|
||||||
" in grado e facile da configurare. Eseguire il proprio server API in "
|
"subito."
|
||||||
"pochi minuti."
|
|
||||||
|
#: libretranslate/templates/app.js.template:423
|
||||||
|
msgid "No languages available. Did you install the models correctly?"
|
||||||
|
msgstr "Nessuna lingua disponibile. Hai installato correttamente i modelli?"
|
||||||
|
|
||||||
|
#: libretranslate/templates/app.js.template:479
|
||||||
|
#, python-format
|
||||||
|
msgid "Type in your API Key. If you need an API key, %(instructions)s"
|
||||||
|
msgstr ""
|
||||||
|
"Digitare nella chiave API. Se hai bisogno di una chiave API, "
|
||||||
|
"%(instructions)s"
|
||||||
|
|
||||||
|
#: libretranslate/templates/app.js.template:479
|
||||||
|
msgid "press the \"Get API Key\" link."
|
||||||
|
msgstr "premere il link \"Get API Key\"."
|
||||||
|
|
||||||
|
#: libretranslate/templates/app.js.template:479
|
||||||
|
msgid "contact the server operator."
|
||||||
|
msgstr "contattare l'operatore del server."
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:6
|
||||||
|
#: libretranslate/templates/index.html:26
|
||||||
|
#: libretranslate/templates/index.html:297
|
||||||
|
msgid "Free and Open Source Machine Translation API"
|
||||||
|
msgstr "API di traduzione automatica gratuita e open source"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:8
|
||||||
|
#: libretranslate/templates/index.html:30
|
||||||
|
msgid ""
|
||||||
|
"Free and Open Source Machine Translation API. Self-hosted, offline capable "
|
||||||
|
"and easy to setup. Run your own API server in just a few minutes."
|
||||||
|
msgstr ""
|
||||||
|
"API di traduzione automatica gratuita e open source. Auto-hosted, offline in"
|
||||||
|
" grado e facile da configurare. Eseguire il proprio server API in pochi "
|
||||||
|
"minuti."
|
||||||
|
|
||||||
#: libretranslate/templates/index.html:9
|
#: libretranslate/templates/index.html:9
|
||||||
msgid "translation"
|
msgid "translation"
|
||||||
|
@ -56,3 +313,132 @@ msgstr "traduzione"
|
||||||
msgid "api"
|
msgid "api"
|
||||||
msgstr "api"
|
msgstr "api"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:64
|
||||||
|
#: libretranslate/templates/index.html:75
|
||||||
|
msgid "API Docs"
|
||||||
|
msgstr "API"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:66
|
||||||
|
#: libretranslate/templates/index.html:77
|
||||||
|
msgid "Get API Key"
|
||||||
|
msgstr "Ottieni API Chiave"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:68
|
||||||
|
#: libretranslate/templates/index.html:79
|
||||||
|
msgid "GitHub"
|
||||||
|
msgstr "GitHub"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:81
|
||||||
|
msgid "Set API Key"
|
||||||
|
msgstr "Set API Chiave"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:118
|
||||||
|
msgid "Dismiss"
|
||||||
|
msgstr "Oggetto"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:132
|
||||||
|
msgid "Translation API"
|
||||||
|
msgstr "API di traduzione"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:136
|
||||||
|
msgid "Translate Text"
|
||||||
|
msgstr "Traduzione"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:140
|
||||||
|
msgid "Translate Files"
|
||||||
|
msgstr "Traduci file"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:146
|
||||||
|
msgid "Translate from"
|
||||||
|
msgstr "Traduttore da"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:159
|
||||||
|
msgid "Translate into"
|
||||||
|
msgstr "Traduzione"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:171
|
||||||
|
msgid "Text to translate"
|
||||||
|
msgstr "Testo da tradurre"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:183
|
||||||
|
msgid "Translated text"
|
||||||
|
msgstr "Tradotto testo"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:191
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Annulla"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:194
|
||||||
|
msgid "Send"
|
||||||
|
msgstr "Invia"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:210
|
||||||
|
msgid "Supported file formats:"
|
||||||
|
msgstr "Formati di file supportati:"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:214
|
||||||
|
msgid "File"
|
||||||
|
msgstr "File"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:236
|
||||||
|
msgid "Translate"
|
||||||
|
msgstr "Traduttore"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:237
|
||||||
|
#: libretranslate/templates/index.html:281
|
||||||
|
msgid "Download"
|
||||||
|
msgstr "Scarica"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:256
|
||||||
|
msgid "Request"
|
||||||
|
msgstr "Richiesta"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:261
|
||||||
|
msgid "Response"
|
||||||
|
msgstr "Risposta"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:276
|
||||||
|
msgid "Open Source Machine Translation API"
|
||||||
|
msgstr "API di traduzione automatica Open Source"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:277
|
||||||
|
msgid "Self-Hosted. Offline Capable. Easy to Setup."
|
||||||
|
msgstr "Ossessionato. Offline Capable. Facile da configurare."
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:296
|
||||||
|
msgid "LibreTranslate"
|
||||||
|
msgstr "LibreTranslate"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:298
|
||||||
|
msgid "License:"
|
||||||
|
msgstr "Licenza:"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:301
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"This public API should be used for testing, personal or infrequent use. If "
|
||||||
|
"you're going to run an application in production, please %(host_server)s or "
|
||||||
|
"%(get_api_key)s."
|
||||||
|
msgstr ""
|
||||||
|
"Questa API pubblica dovrebbe essere utilizzata per il test, uso personale o "
|
||||||
|
"infrequente. Se hai intenzione di eseguire un'applicazione in produzione, "
|
||||||
|
"per favore %(host_server)s o %(get_api_key)s."
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:301
|
||||||
|
msgid "host your own server"
|
||||||
|
msgstr "host tuo server"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:301
|
||||||
|
msgid "get an API key"
|
||||||
|
msgstr "ottenere una chiave API"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:309
|
||||||
|
#, python-format
|
||||||
|
msgid "Made with %(heart)s by %(contributors)s and powered by %(engine)s"
|
||||||
|
msgstr ""
|
||||||
|
"Realizzato con %(heart)s di %(contributors)s e alimentato da %(engine)s"
|
||||||
|
|
||||||
|
#: libretranslate/templates/index.html:309
|
||||||
|
#, python-format
|
||||||
|
msgid "%(libretranslate)s Contributors"
|
||||||
|
msgstr "%(libretranslate)s Contributori"
|
||||||
|
|
|
@ -28,7 +28,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||||
|
|
||||||
detectedLangText: "",
|
detectedLangText: "",
|
||||||
|
|
||||||
copyTextLabel: '{{ _e("Copy text") }}',
|
copyTextLabel: {{ _e("Copy text") }},
|
||||||
|
|
||||||
suggestions: false,
|
suggestions: false,
|
||||||
isSuggesting: false,
|
isSuggesting: false,
|
||||||
|
@ -69,18 +69,18 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.error = '{{ _e("Cannot load %(url)s", url="/frontend/settings") }}';
|
self.error = {{ _e("Cannot load %(url)s", url="/frontend/settings") }};
|
||||||
self.loading = false;
|
self.loading = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
settingsRequest.onerror = function() {
|
settingsRequest.onerror = function() {
|
||||||
self.error = "Error while calling /frontend/settings";
|
self.error = {{ _e("Cannot load %(url)s", url="/frontend/settings") }};
|
||||||
self.loading = false;
|
self.loading = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
langsRequest.onerror = function() {
|
langsRequest.onerror = function() {
|
||||||
self.error = "Error while calling /languages";
|
self.error = {{ _e("Cannot load %(url)s", url="/languages") }};
|
||||||
self.loading = false;
|
self.loading = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||||
self.detectedLangText = ": " + (lang !== undefined ? lang.name : res.detectedLanguage.language) + " (" + res.detectedLanguage.confidence + "%)";
|
self.detectedLangText = ": " + (lang !== undefined ? lang.name : res.detectedLanguage.language) + " (" + res.detectedLanguage.confidence + "%)";
|
||||||
}
|
}
|
||||||
} else{
|
} else{
|
||||||
throw new Error(res.error || "Unknown error");
|
throw new Error(res.error || {{ _e("Unknown error") }});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
self.error = e.message;
|
self.error = e.message;
|
||||||
|
@ -259,7 +259,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||||
};
|
};
|
||||||
|
|
||||||
request.onerror = function() {
|
request.onerror = function() {
|
||||||
self.error = "Error while calling /translate";
|
self.error = {{ _e("Cannot load %(url)s", url="/translate") }};
|
||||||
self.loadingTranslation = false;
|
self.loadingTranslation = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -273,10 +273,10 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||||
document.execCommand("copy");
|
document.execCommand("copy");
|
||||||
|
|
||||||
if (this.copyTextLabel === "Copy text"){
|
if (this.copyTextLabel === "Copy text"){
|
||||||
this.copyTextLabel = "Copied";
|
this.copyTextLabel = {{ _e("Copied") }};
|
||||||
var self = this;
|
var self = this;
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
self.copyTextLabel = "Copy text";
|
self.copyTextLabel = {{ _e("Copy text") }};
|
||||||
}, 1500);
|
}, 1500);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -317,10 +317,10 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||||
try{
|
try{
|
||||||
var res = JSON.parse(this.response);
|
var res = JSON.parse(this.response);
|
||||||
if (res.success){
|
if (res.success){
|
||||||
M.toast({html: 'Thanks for your correction. Note the suggestion will not take effect right away.'})
|
M.toast({html: {{ _e("Thanks for your correction. Note the suggestion will not take effect right away.") }} })
|
||||||
self.closeSuggestTranslation(e)
|
self.closeSuggestTranslation(e)
|
||||||
}else{
|
}else{
|
||||||
throw new Error(res.error || "Unknown error");
|
throw new Error(res.error || {{ _e("Unknown error") }});
|
||||||
}
|
}
|
||||||
}catch(e){
|
}catch(e){
|
||||||
self.error = e.message;
|
self.error = e.message;
|
||||||
|
@ -329,7 +329,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||||
};
|
};
|
||||||
|
|
||||||
request.onerror = function() {
|
request.onerror = function() {
|
||||||
self.error = "Error while calling /suggest";
|
self.error = {{ _e("Cannot load %(url)s", url="/suggest") }};
|
||||||
self.loadingTranslation = false;
|
self.loadingTranslation = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||||
link.href = self.translatedFileUrl;
|
link.href = self.translatedFileUrl;
|
||||||
link.click();
|
link.click();
|
||||||
}else{
|
}else{
|
||||||
throw new Error(res.error || "Unknown error");
|
throw new Error(res.error || {{ _e("Unknown error") }});
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch(e){
|
}catch(e){
|
||||||
|
@ -392,14 +392,14 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
let res = JSON.parse(this.response);
|
let res = JSON.parse(this.response);
|
||||||
self.error = res.error || "Unknown error";
|
self.error = res.error || {{ _e("Unknown error") }};
|
||||||
self.loadingFileTranslation = false;
|
self.loadingFileTranslation = false;
|
||||||
self.inputFile = false;
|
self.inputFile = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
translateFileRequest.onerror = function() {
|
translateFileRequest.onerror = function() {
|
||||||
self.error = "Error while calling /translate_file";
|
self.error = {{ _e("Cannot load %(url)s", url="/translate_file") }};
|
||||||
self.loadingFileTranslation = false;
|
self.loadingFileTranslation = false;
|
||||||
self.inputFile = false;
|
self.inputFile = false;
|
||||||
};
|
};
|
||||||
|
@ -420,11 +420,11 @@ function handleLangsResponse(self, response) {
|
||||||
|
|
||||||
if (self.langs.length === 0){
|
if (self.langs.length === 0){
|
||||||
self.loading = false;
|
self.loading = false;
|
||||||
self.error = "No languages available. Did you install the models correctly?"
|
self.error = {{ _e("No languages available. Did you install the models correctly?") }};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.langs.push({ name: "Auto Detect", code: "auto", targets: self.langs.map(l => l.code)})
|
self.langs.push({ name: {{ _e("Auto Detect") }}, code: "auto", targets: self.langs.map(l => l.code)})
|
||||||
|
|
||||||
const sourceLanguage = self.langs.find(l => l.code === self.getQueryParam("source"))
|
const sourceLanguage = self.langs.find(l => l.code === self.getQueryParam("source"))
|
||||||
const targetLanguage = self.langs.find(l => l.code === self.getQueryParam("target"))
|
const targetLanguage = self.langs.find(l => l.code === self.getQueryParam("target"))
|
||||||
|
@ -444,7 +444,7 @@ function handleLangsResponse(self, response) {
|
||||||
self.handleInput(new Event('none'))
|
self.handleInput(new Event('none'))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.error = "Cannot load /languages";
|
self.error = {{ _e("Cannot load %(url)s", url="/languages") }};
|
||||||
}
|
}
|
||||||
|
|
||||||
self.loading = false;
|
self.loading = false;
|
||||||
|
@ -476,9 +476,7 @@ function getTextWidth(text) {
|
||||||
function setApiKey(){
|
function setApiKey(){
|
||||||
var prevKey = localStorage.getItem("api_key") || "";
|
var prevKey = localStorage.getItem("api_key") || "";
|
||||||
var newKey = "";
|
var newKey = "";
|
||||||
var instructions = "contact the server operator.";
|
newKey = window.prompt({{ _e("Type in your API Key. If you need an API key, %(instructions)s", instructions=_e("press the \"Get API Key\" link.") if get_api_key_link else _e("contact the server operator.")) }}, prevKey);
|
||||||
if (window.getApiKeyLink) instructions = "press the \"Get API Key\" link."
|
|
||||||
newKey = window.prompt("Type in your API Key. If you need an API key, " + instructions, prevKey);
|
|
||||||
if (newKey === null) newKey = "";
|
if (newKey === null) newKey = "";
|
||||||
|
|
||||||
localStorage.setItem("api_key", newKey);
|
localStorage.setItem("api_key", newKey);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{{ _h("LibreTranslate - Free and Open Source Machine Translation API") }}</title>
|
<title>LibreTranslate - {{ _h("Free and Open Source Machine Translation API") }}</title>
|
||||||
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
<meta name="description" content="{{ _h('Free and Open Source Machine Translation API. Self-hosted, offline capable and easy to setup. Run your own API server in just a few minutes.') }}">
|
<meta name="description" content="{{ _h('Free and Open Source Machine Translation API. Self-hosted, offline capable and easy to setup. Run your own API server in just a few minutes.') }}">
|
||||||
<meta name="keywords" content="{{ _h('translation') }},{{ _h('api') }}">
|
<meta name="keywords" content="{{ _h('translation') }},{{ _h('api') }}">
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<link rel="preload" href="{{ url_for('static', filename='css/main.css') }}?v={{ version }}" as="style"/>
|
<link rel="preload" href="{{ url_for('static', filename='css/main.css') }}?v={{ version }}" as="style"/>
|
||||||
<link rel="preload" href="{{ url_for('static', filename='css/dark-theme.css') }}" as="style"/>
|
<link rel="preload" href="{{ url_for('static', filename='css/dark-theme.css') }}" as="style"/>
|
||||||
|
|
||||||
<meta property="og:title" content="{{ _h('LibreTranslate - Free and Open Source Machine Translation API') }}" />
|
<meta property="og:title" content="LibreTranslate - {{ _h('Free and Open Source Machine Translation API') }}" />
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
<meta property="og:url" content="https://libretranslate.com" />
|
<meta property="og:url" content="https://libretranslate.com" />
|
||||||
<meta property="og:image" content="https://user-images.githubusercontent.com/1951843/102724116-32a6df00-42db-11eb-8cc0-129ab39cdfb5.png" />
|
<meta property="og:image" content="https://user-images.githubusercontent.com/1951843/102724116-32a6df00-42db-11eb-8cc0-129ab39cdfb5.png" />
|
||||||
|
@ -57,14 +57,13 @@
|
||||||
<div class="nav-wrapper container">
|
<div class="nav-wrapper container">
|
||||||
<button data-target="nav-mobile" class="sidenav-trigger"><i class="material-icons">menu</i></button>
|
<button data-target="nav-mobile" class="sidenav-trigger"><i class="material-icons">menu</i></button>
|
||||||
<a id="logo-container" href="/" class="brand-logo">
|
<a id="logo-container" href="/" class="brand-logo">
|
||||||
<img src="{{ url_for('static', filename='icon.svg') }}" alt="Logo for LibreTranslate" class="logo">
|
<img src="{{ url_for('static', filename='icon.svg') }}" alt="LibreTranslate" class="logo">
|
||||||
<span>{{ _h("LibreTranslate") }}</span>
|
<span>LibreTranslate</span>
|
||||||
</a>
|
</a>
|
||||||
<ul class="right hide-on-med-and-down">
|
<ul class="right hide-on-med-and-down">
|
||||||
<li><a href="{{ swagger_url }}">{{ _h("API Docs") }}</a></li>
|
<li><a href="{{ swagger_url }}">{{ _h("API Docs") }}</a></li>
|
||||||
{% if get_api_key_link %}
|
{% if get_api_key_link %}
|
||||||
<li><a href="{{ get_api_key_link }}">{{ _h("Get API Key") }}</a></li>
|
<li><a href="{{ get_api_key_link }}">{{ _h("Get API Key") }}</a></li>
|
||||||
<script>window.getApiKeyLink = "{{ get_api_key_link }}";</script>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li><a href="https://github.com/LibreTranslate/LibreTranslate" rel="noopener noreferrer">{{ _h("GitHub") }}</a></li>
|
<li><a href="https://github.com/LibreTranslate/LibreTranslate" rel="noopener noreferrer">{{ _h("GitHub") }}</a></li>
|
||||||
{% if api_keys %}
|
{% if api_keys %}
|
||||||
|
@ -296,7 +295,7 @@
|
||||||
<div class="col l12 s12">
|
<div class="col l12 s12">
|
||||||
<h5 class="white-text">{{ _h("LibreTranslate") }}</h5>
|
<h5 class="white-text">{{ _h("LibreTranslate") }}</h5>
|
||||||
<p class="grey-text text-lighten-4">{{ _h("Free and Open Source Machine Translation API") }}</p>
|
<p class="grey-text text-lighten-4">{{ _h("Free and Open Source Machine Translation API") }}</p>
|
||||||
<p>License: <a class="grey-text text-lighten-4" href="https://www.gnu.org/licenses/agpl-3.0.en.html" rel="noopener noreferrer">AGPLv3</a></p>
|
<p>{{ _h("License:") }} <a class="grey-text text-lighten-4" href="https://www.gnu.org/licenses/agpl-3.0.en.html" rel="noopener noreferrer">AGPLv3</a></p>
|
||||||
{% if web_version %}
|
{% if web_version %}
|
||||||
<p>
|
<p>
|
||||||
{{ _h("This public API should be used for testing, personal or infrequent use. If you're going to run an application in production, please %(host_server)s or %(get_api_key)s.", host_server='<a href="https://github.com/LibreTranslate/LibreTranslate" class="grey-text text-lighten-4" rel="noopener noreferrer">' + _h("host your own server") + '</a>', get_api_key='<a class="grey-text text-lighten-4" href="' + (get_api_key_link if get_api_key_link else "https://github.com/LibreTranslate/LibreTranslate#mirrors") + '" rel="noopener noreferrer">' + _h("get an API key") + '</a>') }}
|
{{ _h("This public API should be used for testing, personal or infrequent use. If you're going to run an application in production, please %(host_server)s or %(get_api_key)s.", host_server='<a href="https://github.com/LibreTranslate/LibreTranslate" class="grey-text text-lighten-4" rel="noopener noreferrer">' + _h("host your own server") + '</a>', get_api_key='<a class="grey-text text-lighten-4" href="' + (get_api_key_link if get_api_key_link else "https://github.com/LibreTranslate/LibreTranslate#mirrors") + '" rel="noopener noreferrer">' + _h("get an API key") + '</a>') }}
|
||||||
|
@ -307,7 +306,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="footer-copyright center">
|
<div class="footer-copyright center">
|
||||||
<p class="white-text">
|
<p class="white-text">
|
||||||
{{ _h("Made with %(heart)s by %(contributors)s and powered by %(engine)s", heart='❤', contributors='<a class="white-text" href="https://github.com/LibreTranslate/LibreTranslate/graphs/contributors" rel="noopener noreferrer">%s</a>' % _h("LibreTranslate Contributors"), engine='<a class="white-text text-lighten-3" href="https://github.com/argosopentech/argos-translate/" rel="noopener noreferrer">%s</a>' % _h('Argos Translate')) }}
|
{{ _h("Made with %(heart)s by %(contributors)s and powered by %(engine)s", heart='❤', contributors='<a class="white-text" href="https://github.com/LibreTranslate/LibreTranslate/graphs/contributors" rel="noopener noreferrer">%s</a>' % _h("%(libretranslate)s Contributors", libretranslate="LibreTranslate"), engine='<a class="white-text text-lighten-3" href="https://github.com/argosopentech/argos-translate/" rel="noopener noreferrer">Argos Translate</a>') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import sys
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import polib
|
import polib
|
||||||
|
import json
|
||||||
from babel.messages.frontend import main as pybabel
|
from babel.messages.frontend import main as pybabel
|
||||||
from libretranslate.language import load_languages, improve_translation_formatting
|
from libretranslate.language import load_languages, improve_translation_formatting
|
||||||
from libretranslate.locales import get_available_locales
|
from libretranslate.locales import get_available_locales
|
||||||
|
@ -11,10 +12,24 @@ from libretranslate.app import get_version
|
||||||
|
|
||||||
# Update strings
|
# Update strings
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
print("Loading languages")
|
||||||
|
languages = load_languages()
|
||||||
|
en_lang = next((l for l in languages if l.code == 'en'), None)
|
||||||
|
if en_lang is None:
|
||||||
|
print("Error: English model not found. You need it to run this script.")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
locales_dir = os.path.join("libretranslate", "locales")
|
locales_dir = os.path.join("libretranslate", "locales")
|
||||||
if not os.path.isdir(locales_dir):
|
if not os.path.isdir(locales_dir):
|
||||||
os.makedirs(locales_dir)
|
os.makedirs(locales_dir)
|
||||||
|
|
||||||
|
# Dump language list so it gets picked up by pybabel
|
||||||
|
langs_file = os.path.join(locales_dir, ".langs.py")
|
||||||
|
with open(langs_file, 'w') as f:
|
||||||
|
for l in languages:
|
||||||
|
f.write("_(%s)\n" % json.dumps(l.name))
|
||||||
|
print("Wrote %s" % langs_file)
|
||||||
|
|
||||||
messagespot = os.path.join(locales_dir, "messages.pot")
|
messagespot = os.path.join(locales_dir, "messages.pot")
|
||||||
print("Updating %s" % messagespot)
|
print("Updating %s" % messagespot)
|
||||||
sys.argv = ["", "extract", "-F", "babel.cfg", "-k", "_e _h",
|
sys.argv = ["", "extract", "-F", "babel.cfg", "-k", "_e _h",
|
||||||
|
@ -24,13 +39,7 @@ if __name__ == "__main__":
|
||||||
"-o", messagespot, "libretranslate"]
|
"-o", messagespot, "libretranslate"]
|
||||||
pybabel()
|
pybabel()
|
||||||
|
|
||||||
# Load list of languages
|
|
||||||
print("Loading languages")
|
|
||||||
languages = load_languages()
|
|
||||||
en_lang = next((l for l in languages if l.code == 'en'), None)
|
|
||||||
if en_lang is None:
|
|
||||||
print("Error: English model not found. You need it to run this script.")
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
lang_codes = [l.code for l in languages if l != "en"]
|
lang_codes = [l.code for l in languages if l != "en"]
|
||||||
lang_codes = ["it"] # TODO REMOVE
|
lang_codes = ["it"] # TODO REMOVE
|
||||||
|
@ -70,7 +79,7 @@ if __name__ == "__main__":
|
||||||
text = entry.msgid
|
text = entry.msgid
|
||||||
|
|
||||||
# Extract placeholders
|
# Extract placeholders
|
||||||
placeholders = re.findall(r'%\(?.*?\)?s', text)
|
placeholders = re.findall(r'%\(?[^\)]*\)?s', text)
|
||||||
|
|
||||||
for p in range(0, len(placeholders)):
|
for p in range(0, len(placeholders)):
|
||||||
text = text.replace(placeholders[p], "<x>%s</x>" % p)
|
text = text.replace(placeholders[p], "<x>%s</x>" % p)
|
||||||
|
|
Loading…
Reference in a new issue