mirror of
https://github.com/minetest/contentdb.git
synced 2024-11-08 08:33:45 +01:00
Add ability to translate tags and content warnings
This commit is contained in:
parent
7d00a5b969
commit
d2c5779301
@ -217,11 +217,12 @@ def download(package):
|
||||
return redirect(release.get_download_url())
|
||||
|
||||
|
||||
def makeLabel(obj):
|
||||
if obj.description:
|
||||
return "{}: {}".format(obj.title, obj.description)
|
||||
def make_label(obj: Tag | ContentWarning):
|
||||
translated = obj.get_translated()
|
||||
if translated["description"]:
|
||||
return "{}: {}".format(translated["title"], translated["description"])
|
||||
else:
|
||||
return obj.title
|
||||
return translated["title"]
|
||||
|
||||
|
||||
class PackageForm(FlaskForm):
|
||||
@ -232,8 +233,8 @@ class PackageForm(FlaskForm):
|
||||
|
||||
dev_state = SelectField(lazy_gettext("Maintenance State"), [InputRequired()], choices=PackageDevState.choices(with_none=True), coerce=PackageDevState.coerce)
|
||||
|
||||
tags = QuerySelectMultipleField(lazy_gettext('Tags'), query_factory=lambda: Tag.query.order_by(db.asc(Tag.name)), get_pk=lambda a: a.id, get_label=makeLabel)
|
||||
content_warnings = QuerySelectMultipleField(lazy_gettext('Content Warnings'), query_factory=lambda: ContentWarning.query.order_by(db.asc(ContentWarning.name)), get_pk=lambda a: a.id, get_label=makeLabel)
|
||||
tags = QuerySelectMultipleField(lazy_gettext('Tags'), query_factory=lambda: Tag.query.order_by(db.asc(Tag.name)), get_pk=lambda a: a.id, get_label=make_label)
|
||||
content_warnings = QuerySelectMultipleField(lazy_gettext('Content Warnings'), query_factory=lambda: ContentWarning.query.order_by(db.asc(ContentWarning.name)), get_pk=lambda a: a.id, get_label=make_label)
|
||||
license = QuerySelectField(lazy_gettext("License"), [DataRequired()], allow_blank=True, query_factory=lambda: License.query.order_by(db.asc(License.name)), get_pk=lambda a: a.id, get_label=lambda a: a.name)
|
||||
media_license = QuerySelectField(lazy_gettext("Media License"), [DataRequired()], allow_blank=True, query_factory=lambda: License.query.order_by(db.asc(License.name)), get_pk=lambda a: a.id, get_label=lambda a: a.name)
|
||||
|
||||
|
@ -906,6 +906,13 @@ class ContentWarning(db.Model):
|
||||
regex = re.compile("[^a-z_]")
|
||||
self.name = regex.sub("", self.title.lower().replace(" ", "_"))
|
||||
|
||||
def get_translated(self):
|
||||
# Translations are automated on dynamic data using `extract_translations.py`
|
||||
return {
|
||||
"title": gettext(self.title),
|
||||
"description": gettext(self.description),
|
||||
}
|
||||
|
||||
def as_dict(self):
|
||||
description = self.description if self.description != "" else None
|
||||
return { "name": self.name, "title": self.title, "description": description }
|
||||
@ -931,6 +938,13 @@ class Tag(db.Model):
|
||||
regex = re.compile("[^a-z_]")
|
||||
self.name = regex.sub("", self.title.lower().replace(" ", "_"))
|
||||
|
||||
def get_translated(self):
|
||||
# Translations are automated on dynamic data using `extract_translations.py`
|
||||
return {
|
||||
"title": gettext(self.title),
|
||||
"description": gettext(self.description),
|
||||
}
|
||||
|
||||
def as_dict(self):
|
||||
description = self.description if self.description != "" else None
|
||||
return {
|
||||
|
@ -60,9 +60,9 @@ class QueryBuilder:
|
||||
if len(self.tags) == 0:
|
||||
ret = package_type
|
||||
elif len(self.tags) == 1:
|
||||
ret = self.tags[0].title + " " + package_type
|
||||
ret = self.tags[0].get_translated()["title"] + " " + package_type
|
||||
else:
|
||||
tags = ", ".join([tag.title for tag in self.tags])
|
||||
tags = ", ".join([tag.get_translated()["title"] for tag in self.tags])
|
||||
ret = f"{tags} - {package_type}"
|
||||
|
||||
if self.search:
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{% block title %}
|
||||
{% if tag %}
|
||||
Edit {{ tag.title }}
|
||||
Edit {{ tag.get_translated().title }}
|
||||
{% else %}
|
||||
New tag
|
||||
{% endif %}
|
||||
|
@ -166,9 +166,9 @@
|
||||
{% set tag = pair[1] %}
|
||||
|
||||
<a class="btn btn-sm btn-secondary m-1" rel="nofollow"
|
||||
title="{{ tag.description or '' }}"
|
||||
title="{{ tag.get_translated().description or '' }}"
|
||||
href="{{ url_for('packages.list_all', tag=tag.name) }}">
|
||||
{{ tag.title }}
|
||||
{{ tag.get_translated().title }}
|
||||
<span class="badge rounded-pill bg-light text-dark ms-1">{{ count }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
|
@ -31,16 +31,16 @@
|
||||
|
||||
{% if tag in selected_tags %}
|
||||
<a class="btn btn-sm btn-primary m-1" rel="nofollow"
|
||||
title="{{ tag.description or '' }}"
|
||||
title="{{ tag.get_translated().description or '' }}"
|
||||
href="{{ url_set_query(page=1, _remove={ 'tag': tag.name }) }}">
|
||||
{{ tag.title }}
|
||||
{{ tag.get_translated().title }}
|
||||
<span class="badge rounded-pill bg-light text-dark ms-1">{{ count }}</span>
|
||||
</a>
|
||||
{% else %}
|
||||
<a class="btn btn-sm btn-secondary m-1" rel="nofollow"
|
||||
title="{{ tag.description or '' }}"
|
||||
title="{{ tag.get_translated().description or '' }}"
|
||||
href="{{ url_set_query(page=1, _add={ 'tag': tag.name }) }}">
|
||||
{{ tag.title }}
|
||||
{{ tag.get_translated().title }}
|
||||
<span class="badge rounded-pill bg-light text-dark ms-1">{{ count }}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
@ -163,11 +163,11 @@
|
||||
{{ _("Work in Progress") }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% for t in package.tags %}
|
||||
{% for tag in package.tags %}
|
||||
<a class="badge bg-primary" rel="nofollow"
|
||||
title="{{ t.description or '' }}"
|
||||
href="{{ url_for('packages.list_all', tag=t.name) }}">
|
||||
{{ t.title }}
|
||||
title="{{ tag.get_translated().description or '' }}"
|
||||
href="{{ url_for('packages.list_all', tag=tag.name) }}">
|
||||
{{ tag.get_translated().title }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</p>
|
||||
|
@ -57,7 +57,7 @@
|
||||
{% for tag in package.tags %}
|
||||
<a class="badge bg-primary me-1"
|
||||
href="{{ url_set_query(_add={ 'tag': tag.name }) }}">
|
||||
{{ tag.title }}
|
||||
{{ tag.get_translated().title }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
<!-- <a class="badge bg-secondary add-btn px-2" href="#">
|
||||
|
@ -261,7 +261,7 @@ def package_info_as_hypertext(package: Package, formspec_version: int = 7):
|
||||
body += "</b>\n\n"
|
||||
|
||||
add_value(gettext("Type"), package.type.text)
|
||||
add_list(gettext("Tags"), [tag.title for tag in package.tags])
|
||||
add_list(gettext("Tags"), [tag.get_translated()["title"] for tag in package.tags])
|
||||
|
||||
if package.type != PackageType.GAME:
|
||||
def make_game_link(game):
|
||||
|
37
utils/extract_translations.py
Executable file
37
utils/extract_translations.py
Executable file
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import subprocess
|
||||
from typing import List
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
base_url = "https://content.minetest.net"
|
||||
translations = set()
|
||||
|
||||
|
||||
def add_translations_from_api_array(path: str, fields: List[str]):
|
||||
print(f"Extracting translations from {path}")
|
||||
url = base_url + path
|
||||
req = requests.get(url)
|
||||
json = req.json()
|
||||
for i, row in enumerate(json):
|
||||
for field in fields:
|
||||
if row.get(field) is not None:
|
||||
translations.add(row[field])
|
||||
|
||||
|
||||
add_translations_from_api_array("/api/tags/", ["title", "description"])
|
||||
add_translations_from_api_array("/api/content_warnings/", ["title", "description"])
|
||||
|
||||
|
||||
with open("app/_translations.py", "w") as f:
|
||||
f.write("# THIS FILE IS AUTOGENERATED: utils/extract_translations.py\n\n")
|
||||
f.write("from flask_babel import gettext\n\n")
|
||||
for translation in translations:
|
||||
escaped = translation.replace('\n', '\\n').replace("\"", "\\\"")
|
||||
f.write(f"gettext(\"{escaped}\")\n")
|
||||
|
||||
|
||||
subprocess.run(["pybabel", "extract", "-F", "babel.cfg", "-k", "lazy_gettext", "-o", "translations/messages.pot", "."])
|
||||
subprocess.run(["pybabel", "update", "-i", "translations/messages.pot", "-d", "translations", "--no-fuzzy-matching"])
|
Loading…
Reference in New Issue
Block a user