From 9173d3c5783e94fe33d5bd6b59266bd31059db97 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sun, 25 Feb 2024 18:43:27 +0000 Subject: [PATCH] Use package translation in API --- app/blueprints/api/endpoints.py | 17 ++++++++++++----- app/models/packages.py | 26 ++++++++++++++++---------- app/querybuilder.py | 8 +++++--- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/app/blueprints/api/endpoints.py b/app/blueprints/api/endpoints.py index 7224d0d5..f9db0dfd 100644 --- a/app/blueprints/api/endpoints.py +++ b/app/blueprints/api/endpoints.py @@ -21,6 +21,7 @@ from typing import List import flask_sqlalchemy from flask import request, jsonify, current_app, Response +from flask_babel import gettext from flask_login import current_user, login_required from sqlalchemy import and_, or_ from sqlalchemy.orm import joinedload @@ -31,7 +32,7 @@ from app.logic.graphs import get_package_stats, get_package_stats_for_user, get_ from app.markdown import render_markdown from app.models import Tag, PackageState, PackageType, Package, db, PackageRelease, Permission, ForumTopic, \ MinetestRelease, APIToken, PackageScreenshot, License, ContentWarning, User, PackageReview, Thread, Collection, \ - PackageAlias + PackageAlias, Language from app.querybuilder import QueryBuilder from app.utils import is_package_page, get_int_or_abort, url_set_query, abs_url, is_yes, get_request_date from app.utils.minetest_hypertext import html_to_minetest @@ -68,7 +69,10 @@ def cached(max_age: int): @cors_allowed @cached(300) def packages(): - qb = QueryBuilder(request.args) + allowed_languages = set([x[0] for x in db.session.query(Language.id).all()]) + lang = request.accept_languages.best_match(allowed_languages) + + qb = QueryBuilder(request.args, lang=lang) query = qb.build_package_query() if request.args.get("fmt") == "keys": @@ -88,7 +92,7 @@ def packages(): Package.collections.any(and_(Collection.name == "featured", Collection.author.has(username="ContentDB")))).all()) for pkg in featured: featured_lut.add(f"{pkg['author']}/{pkg['name']}") - pkg["short_description"] = "Featured. " + pkg["short_description"] + pkg["short_description"] = gettext("Featured") + ". " + pkg["short_description"] not_featured = [pkg for pkg in pkgs if f"{pkg['author']}/{pkg['name']}" not in featured_lut] pkgs = featured + not_featured @@ -100,11 +104,14 @@ def packages(): @is_package_page @cors_allowed def package_view(package): - data = package.as_dict(current_app.config["BASE_URL"]) + allowed_languages = set([x[0] for x in db.session.query(Language.id).all()]) + lang = request.accept_languages.best_match(allowed_languages) + + data = package.as_dict(current_app.config["BASE_URL"], lang=lang) if "formspec_version" in request.args: formspec_version = request.args["formspec_version"] include_images = is_yes(request.args.get("include_images", "true")) - html = render_markdown(package.desc) + html = render_markdown(data["long_description"]) data["long_description"] = html_to_minetest(html, formspec_version, include_images) return jsonify(data) diff --git a/app/models/packages.py b/app/models/packages.py index d61487bc..a5054dac 100644 --- a/app/models/packages.py +++ b/app/models/packages.py @@ -21,7 +21,7 @@ import os import typing from flask import url_for -from flask_babel import lazy_gettext, get_locale +from flask_babel import lazy_gettext, get_locale, gettext from flask_sqlalchemy import BaseQuery from sqlalchemy import or_, func from sqlalchemy.dialects.postgresql import insert @@ -502,7 +502,10 @@ class Package(db.Model): else: lang = "en" - translation: typing.Optional[PackageTranslation] = self.translations.filter_by(language_id=lang).first() + translation: typing.Optional[PackageTranslation] = None + if lang != "en": + translation = self.translations.filter_by(language_id=lang).first() + if translation is None: return { "title": self.title, @@ -556,20 +559,21 @@ class Package(db.Model): "type": self.type.to_name(), } - def as_short_dict(self, base_url, version=None, release_id=None, no_load=False): + def as_short_dict(self, base_url, version=None, release_id=None, no_load=False, lang="en"): tnurl = self.get_thumb_url(1, format="png") if release_id is None and no_load == False: release = self.get_download_release(version=version) release_id = release and release.id - short_desc = self.short_desc + meta = self.get_translated(lang, load_desc=False) + short_desc = meta["short_desc"] if self.dev_state == PackageDevState.WIP: - short_desc = "Work in Progress. " + self.short_desc + short_desc = gettext("Work in Progress") + ". " + self.short_desc ret = { "name": self.name, - "title": self.title, + "title": meta["title"], "author": self.author.username, "short_description": short_desc, "type": self.type.to_name(), @@ -583,9 +587,11 @@ class Package(db.Model): return ret - def as_dict(self, base_url, version=None): + def as_dict(self, base_url, version=None, lang="en"): tnurl = self.get_thumb_url(1, format="png") release = self.get_download_release(version=version) + meta = self.get_translated(lang) + return { "author": self.author.username, "maintainers": [x.username for x in self.maintainers], @@ -594,9 +600,9 @@ class Package(db.Model): "dev_state": self.dev_state.name if self.dev_state else None, "name": self.name, - "title": self.title, - "short_description": self.short_desc, - "long_description": self.desc, + "title": meta["title"], + "short_description": meta["short_desc"], + "long_description": meta["desc"], "type": self.type.to_name(), "created_at": self.created_at.isoformat(), diff --git a/app/querybuilder.py b/app/querybuilder.py index 1582fbea..d6d7f37e 100644 --- a/app/querybuilder.py +++ b/app/querybuilder.py @@ -27,7 +27,8 @@ from .utils import is_yes, get_int_or_abort class QueryBuilder: - types = None + lang: str = "en" + types = None search = None only_approved = True @@ -59,7 +60,8 @@ class QueryBuilder: return (self.search is not None or len(self.tags) > 1 or len(self.types) > 1 or len(self.hide_flags) > 0 or self.random or self.lucky or self.author or self.version or self.game) - def __init__(self, args, cookies=False): + def __init__(self, args, cookies=False, lang="en"): + self.lang = lang # Get request types types = args.getlist("type") @@ -153,7 +155,7 @@ class QueryBuilder: def to_json(package: Package): release_id = releases.get(package.id) - return package.as_short_dict(current_app.config["BASE_URL"], release_id=release_id, no_load=True) + return package.as_short_dict(current_app.config["BASE_URL"], release_id=release_id, no_load=True, lang=self.lang) return [to_json(pkg) for pkg in packages]