Merge pull request #830 from SuperSandro2000/fix-prefix

Fix --url-prefix
This commit is contained in:
Piero Toffanin 2025-07-28 00:27:21 -04:00 committed by GitHub
commit 17f0d4ba89
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 46 additions and 36 deletions

View File

@ -173,11 +173,11 @@ def filter_unique(seq, extra):
def detect_translatable(src_texts):
if isinstance(src_texts, list):
return any(detect_translatable(t) for t in src_texts)
for ch in src_texts:
if not (ord(ch) in emojis):
return True
# All emojis
return False
@ -190,7 +190,7 @@ def create_app(args):
from libretranslate.language import load_languages
swagger_url = args.url_prefix + "/docs" # Swagger UI (w/o trailing '/')
api_url = args.url_prefix + "/spec"
api_url = "/spec"
bp = Blueprint('Main app', __name__)
@ -259,7 +259,7 @@ def create_app(args):
return max(req_cost, int(math.ceil(getattr(request, 'duration', 0) / args.req_time_cost)))
else:
return req_cost
def get_limits_key_func():
if args.api_keys:
def func():
@ -358,7 +358,7 @@ def create_app(args):
'alternatives': [],
'detectedLanguage': { 'confidence': 100, 'language': 'en' }
}), 200))
if (args.require_api_key_fingerprint
and key_missing):
if flood.fingerprint_mismatch(ip, get_fingerprint()):
@ -470,7 +470,7 @@ def create_app(args):
api_secret = secret.get_current_secret_js()
else:
api_secret = secret.get_bogus_secret_js()
response = Response(render_template("app.js.template",
url_prefix=args.url_prefix,
get_api_key_link=args.get_api_key_link,
@ -516,8 +516,8 @@ def create_app(args):
type: string
description: Supported target language codes
"""
return jsonify([{"code": model2iso(l.code),
"name": _lazy(l.name),
return jsonify([{"code": model2iso(l.code),
"name": _lazy(l.name),
"targets": model2iso(language_pairs.get(l.code, []))
} for l in languages])
@ -586,7 +586,7 @@ def create_app(args):
default: 0
example: 3
required: false
description: Preferred number of alternative translations
description: Preferred number of alternative translations
- in: formData
name: api_key
schema:
@ -704,7 +704,7 @@ def create_app(args):
abort(400, description=_("Invalid request: missing %(name)s parameter", name='source'))
if not target_lang:
abort(400, description=_("Invalid request: missing %(name)s parameter", name='target'))
try:
num_alternatives = max(0, int(num_alternatives))
except ValueError:
@ -743,7 +743,7 @@ def create_app(args):
if batch:
request.req_cost = max(1, len(q))
translatable = detect_translatable(src_texts)
if translatable:
if source_lang == "auto":
@ -753,7 +753,7 @@ def create_app(args):
detected_src_lang = {"confidence": 100.0, "language": source_lang}
else:
detected_src_lang = {"confidence": 0.0, "language": "en"}
src_lang = next(iter([l for l in languages if l.code == detected_src_lang["language"]]), None)
if src_lang is None:
@ -790,10 +790,10 @@ def create_app(args):
else:
translated_text = text # Cannot translate, send the original text back
alternatives = []
batch_results.append(translated_text)
batch_alternatives.append(alternatives)
result = {"translatedText": batch_results}
if source_lang == "auto":
@ -818,7 +818,7 @@ def create_app(args):
else:
translated_text = q # Cannot translate, send the original text back
alternatives = []
result = {"translatedText": translated_text}
if source_lang == "auto":
@ -1270,14 +1270,13 @@ def create_app(args):
if args.debug:
app.config["TEMPLATES_AUTO_RELOAD"] = True
if args.url_prefix:
app.register_blueprint(bp, url_prefix=args.url_prefix)
else:
app.register_blueprint(bp)
app.register_blueprint(bp)
limiter.init_app(app)
swag = swagger(app)
swag["basePath"] = args.url_prefix if args.url_prefix != "" else "/"
swag["info"]["version"] = get_version()
swag["info"]["title"] = "LibreTranslate"
swag["info"]["description"] = "Free and Open Source Machine Translation API."
@ -1301,10 +1300,9 @@ def create_app(args):
app.jinja_env.globals.update(_e=gettext_escaped, _h=gettext_html)
# Call factory function to create our blueprint
swaggerui_blueprint = get_swaggerui_blueprint(swagger_url, api_url)
if args.url_prefix:
app.register_blueprint(swaggerui_blueprint, url_prefix=swagger_url)
else:
app.register_blueprint(swaggerui_blueprint)
# The Blueprint is not using url_for which means the middleware does not work properly and we need to manually fix things
swaggerui_blueprint = get_swaggerui_blueprint(swagger_url, args.url_prefix + api_url)
swaggerui_blueprint.url_prefix = "/docs"
app.register_blueprint(swaggerui_blueprint)
return app

View File

@ -4,6 +4,8 @@ import sys
from libretranslate.app import create_app
from libretranslate.default_values import DEFAULT_ARGUMENTS as DEFARGS
from werkzeug.serving import run_simple
from werkzeug.middleware.dispatcher import DispatcherMiddleware
def get_args():
@ -245,7 +247,7 @@ def get_args():
"--url-prefix",
default=DEFARGS['URL_PREFIX'],
type=str,
help="Add prefix to URL: example.com:5000/url-prefix/",
help="Add a prefix like /url-prefix to URL: example.com:5000/url-prefix/",
)
args = parser.parse_args()
if args.url_prefix and not args.url_prefix.startswith('/'):
@ -255,7 +257,17 @@ def get_args():
def main():
args = get_args()
app = create_app(args)
if args.url_prefix:
def redirect(environ, start_response):
start_response("301 REDIRECT", [("Content-Type", "text/plain"), ("Location", args.url_prefix)])
yield b"Redirect..."
app = DispatcherMiddleware(redirect, {
args.url_prefix: create_app(args)
})
else:
app = DispatcherMiddleware(create_app(args))
if '--wsgi' in sys.argv:
return app
@ -265,7 +277,7 @@ def main():
args.host = "::"
if args.debug:
app.run(host=args.host, port=args.port)
run_simple(args.host, args.port, app)
else:
from waitress import serve

View File

@ -54,7 +54,7 @@ document.addEventListener('DOMContentLoaded', function(){
const langsRequest = new XMLHttpRequest();
langsRequest.open("GET", BaseUrl + "/languages", true);
settingsRequest.onload = function() {
if (this.status >= 200 && this.status < 400) {
self.settings = JSON.parse(this.response);
@ -79,18 +79,18 @@ document.addEventListener('DOMContentLoaded', function(){
}
}
} else {
self.error = {{ _e("Cannot load %(url)s", url="/frontend/settings") }};
self.error = {{ _e("Cannot load %(url)s", url=url_prefix + "/frontend/settings") }};
self.loading = false;
}
};
settingsRequest.onerror = function() {
self.error = {{ _e("Cannot load %(url)s", url="/frontend/settings") }};
self.error = {{ _e("Cannot load %(url)s", url=url_prefix + "/frontend/settings") }};
self.loading = false;
};
langsRequest.onerror = function() {
self.error = {{ _e("Cannot load %(url)s", url="/languages") }};
self.error = {{ _e("Cannot load %(url)s", url=url_prefix + "/languages") }};
self.loading = false;
};
@ -284,7 +284,7 @@ document.addEventListener('DOMContentLoaded', function(){
};
request.onerror = function() {
self.error = {{ _e("Cannot load %(url)s", url="/translate") }};
self.error = {{ _e("Cannot load %(url)s", url=url_prefix + "/translate") }};
self.loadingTranslation = false;
};
@ -354,7 +354,7 @@ document.addEventListener('DOMContentLoaded', function(){
};
request.onerror = function() {
self.error = {{ _e("Cannot load %(url)s", url="/suggest") }};
self.error = {{ _e("Cannot load %(url)s", url=url_prefix + "/suggest") }};
self.loadingTranslation = false;
};
@ -443,7 +443,7 @@ document.addEventListener('DOMContentLoaded', function(){
}
translateFileRequest.onerror = function() {
const message = {{ _e("Cannot load %(url)s", url="/translate_file") }};
const message = {{ _e("Cannot load %(url)s", url=url_prefix + "/translate_file") }};
self.error = message;
self.loadingFileTranslation = false;
self.inputFile = false;
@ -497,7 +497,7 @@ function handleLangsResponse(self, response) {
self.handleInput(new Event('none'))
}
} else {
self.error = {{ _e("Cannot load %(url)s", url="/languages") }};
self.error = {{ _e("Cannot load %(url)s", url=url_prefix + "/languages") }};
}
self.loading = false;

View File

@ -60,7 +60,7 @@
<nav role="navigation">
<div class="nav-wrapper container">
<button data-target="nav-mobile" class="sidenav-trigger"><i class="material-icons">menu</i></button>
<a id="logo-container" href="/" class="brand-logo noline">
<a id="logo-container" href="{{ url_for('Main app.index') }}" class="brand-logo noline">
<img src="{{ url_for('static', filename='icon.svg') }}" alt="" class="logo">
<span>LibreTranslate</span>
</a>