Merge pull request #859 from return42/fix-814

[mod] add i18n infrastructure for SearXNG message files (searxng.msg)
This commit is contained in:
Markus Heiser 2022-03-20 08:31:07 +01:00 committed by GitHub
commit 3201aa1b3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 216 additions and 98 deletions

View File

@ -1,4 +1,7 @@
[extractors]
searxng_msg = searx.babel_extract.extract
[ignore: **/node_modules/**] [ignore: **/node_modules/**]
[python: **.py] [python: **.py]
[jinja2: **/templates/**.html] [jinja2: **/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_ extensions=jinja2.ext.autoescape,jinja2.ext.with_
[searxng_msg: **/searxng.msg]

View File

@ -16,6 +16,7 @@ Translation
.. sidebar:: |translated| .. sidebar:: |translated|
- :ref:`searx.babel_extract`
- Weblate_ - Weblate_
- SearXNG `translations branch`_ - SearXNG `translations branch`_
- SearXNG `Weblate repository`_ - SearXNG `Weblate repository`_

View File

@ -0,0 +1,8 @@
.. _searx.babel_extract:
===============================
Custom message extractor (i18n)
===============================
.. automodule:: searx.babel_extract
:members:

3
manage
View File

@ -30,7 +30,7 @@ GECKODRIVER_VERSION="v0.30.0"
export NODE_MINIMUM_VERSION="16.13.0" export NODE_MINIMUM_VERSION="16.13.0"
# SPHINXOPTS= # SPHINXOPTS=
BLACK_OPTIONS=("--target-version" "py37" "--line-length" "120" "--skip-string-normalization") BLACK_OPTIONS=("--target-version" "py37" "--line-length" "120" "--skip-string-normalization")
BLACK_TARGETS=("--exclude" "searx/static,searx/languages.py" "searx" "searxng_extra" "tests") BLACK_TARGETS=("--exclude" "searx/static,searx/languages.py" "--include" "searxng.msg" "searx" "searxng_extra" "tests")
pylint.FILES() { pylint.FILES() {
@ -41,6 +41,7 @@ pylint.FILES() {
# These py files are linted by test.pylint() # These py files are linted by test.pylint()
grep -l -r --include \*.py '^#[[:blank:]]*lint:[[:blank:]]*pylint' searx searxng_extra tests grep -l -r --include \*.py '^#[[:blank:]]*lint:[[:blank:]]*pylint' searx searxng_extra tests
find . -name searxng.msg
} }
YAMLLINT_FILES=() YAMLLINT_FILES=()

51
searx/babel_extract.py Normal file
View File

@ -0,0 +1,51 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# lint: pylint
"""This module implements the :origin:`searxng_msg <babel.cfg>` extractor to
extract messages from:
- :origin:`searx/searxng.msg`
The ``searxng.msg`` files are selected by Babel_, see Babel's configuration in
:origin:`babel.cfg`::
searxng_msg = searx.babel_extract.extract
...
[searxng_msg: **/searxng.msg]
A ``searxng.msg`` file is a python file that is *executed* by the
:py:obj:`extract` function. Additional ``searxng.msg`` files can be added by:
1. Adding a ``searxng.msg`` file in one of the SearXNG python packages and
2. implement a method in :py:obj:`extract` that yields messages from this file.
.. _Babel: https://babel.pocoo.org/en/latest/index.html
"""
from os import path
SEARXNG_MSG_FILE = "searxng.msg"
_MSG_FILES = [path.join(path.dirname(__file__), SEARXNG_MSG_FILE)]
def extract(
# pylint: disable=unused-argument
fileobj,
keywords,
comment_tags,
options,
):
"""Extract messages from ``searxng.msg`` files by a custom extractor_.
.. _extractor:
https://babel.pocoo.org/en/latest/messages.html#writing-extraction-methods
"""
if fileobj.name not in _MSG_FILES:
raise RuntimeError("don't know how to extract messages from %s" % fileobj.name)
namespace = {}
exec(fileobj.read(), {}, namespace) # pylint: disable=exec-used
for name in namespace['__all__']:
for k, v in namespace[name].items():
yield 0, '_', v, ["%s['%s']" % (name, k)]

52
searx/searxng.msg Normal file
View File

@ -0,0 +1,52 @@
# -*- mode: python -*-
# SPDX-License-Identifier: AGPL-3.0-or-later
"""A SearXNG message file, see :py:obj:`searx.babel`
"""
from searx import webutils
from searx import engines
__all__ = [
'CONSTANT_NAMES',
'CATEGORY_NAMES',
'CATEGORY_GROUPS',
'STYLE_NAMES',
]
CONSTANT_NAMES = {
# Constants defined in other modules
'DEFAULT_GROUP_NAME': webutils.DEFAULT_GROUP_NAME,
'OTHER_CATEGORY': engines.OTHER_CATEGORY,
}
CATEGORY_NAMES = {
'FILES': 'files',
'GENERAL': 'general',
'MUSIC': 'music',
'SOCIAL_MEDIA': 'social media',
'IMAGES': 'images',
'VIDEOS': 'videos',
'IT': 'it',
'NEWS': 'news',
'MAP': 'map',
'ONIONS': 'onions',
'SCIENCE': 'science',
}
CATEGORY_GROUPS = {
# non-tab categories
'APPS': 'apps',
'DICTIONARIES': 'dictionaries',
'LYRICS': 'lyrics',
'PACKAGES': 'packages',
'Q_A': 'q&a',
'REPOS': 'repos',
'SOFTWARE_WIKIS': 'software wikis',
'WEB': 'web',
}
STYLE_NAMES = {
'AUTO': 'auto',
'LIGHT': 'light',
'DARK': 'dark',
}

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-02-21 11:52+0000\n" "POT-Creation-Date: 2022-03-16 09:12+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,176 +17,208 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n" "Generated-By: Babel 2.9.1\n"
#: searx/webapp.py:170 #. CONSTANT_NAMES['DEFAULT_GROUP_NAME']
#: searx/searxng.msg
msgid "others"
msgstr ""
#. CONSTANT_NAMES['OTHER_CATEGORY']
#: searx/searxng.msg
msgid "other"
msgstr ""
#. CATEGORY_NAMES['FILES']
#: searx/searxng.msg
msgid "files" msgid "files"
msgstr "" msgstr ""
#: searx/webapp.py:171 #. CATEGORY_NAMES['GENERAL']
#: searx/searxng.msg
msgid "general" msgid "general"
msgstr "" msgstr ""
#: searx/webapp.py:172 #. CATEGORY_NAMES['MUSIC']
#: searx/searxng.msg
msgid "music" msgid "music"
msgstr "" msgstr ""
#: searx/webapp.py:173 #. CATEGORY_NAMES['SOCIAL_MEDIA']
#: searx/searxng.msg
msgid "social media" msgid "social media"
msgstr "" msgstr ""
#: searx/webapp.py:174 #. CATEGORY_NAMES['IMAGES']
#: searx/searxng.msg
msgid "images" msgid "images"
msgstr "" msgstr ""
#: searx/webapp.py:175 #. CATEGORY_NAMES['VIDEOS']
#: searx/searxng.msg
msgid "videos" msgid "videos"
msgstr "" msgstr ""
#: searx/webapp.py:176 #. CATEGORY_NAMES['IT']
#: searx/searxng.msg
msgid "it" msgid "it"
msgstr "" msgstr ""
#: searx/webapp.py:177 #. CATEGORY_NAMES['NEWS']
#: searx/searxng.msg
msgid "news" msgid "news"
msgstr "" msgstr ""
#: searx/webapp.py:178 #. CATEGORY_NAMES['MAP']
#: searx/searxng.msg
msgid "map" msgid "map"
msgstr "" msgstr ""
#: searx/webapp.py:179 #. CATEGORY_NAMES['ONIONS']
#: searx/searxng.msg
msgid "onions" msgid "onions"
msgstr "" msgstr ""
#: searx/webapp.py:180 #. CATEGORY_NAMES['SCIENCE']
#: searx/searxng.msg
msgid "science" msgid "science"
msgstr "" msgstr ""
#: searx/webapp.py:182 #. CATEGORY_GROUPS['APPS']
#: searx/searxng.msg
msgid "apps" msgid "apps"
msgstr "" msgstr ""
#: searx/webapp.py:183 #. CATEGORY_GROUPS['DICTIONARIES']
#: searx/searxng.msg
msgid "dictionaries" msgid "dictionaries"
msgstr "" msgstr ""
#: searx/webapp.py:184 #. CATEGORY_GROUPS['LYRICS']
#: searx/searxng.msg
msgid "lyrics" msgid "lyrics"
msgstr "" msgstr ""
#: searx/webapp.py:185 #. CATEGORY_GROUPS['PACKAGES']
#: searx/searxng.msg
msgid "packages" msgid "packages"
msgstr "" msgstr ""
#: searx/webapp.py:186 #. CATEGORY_GROUPS['Q_A']
#: searx/searxng.msg
msgid "q&a" msgid "q&a"
msgstr "" msgstr ""
#: searx/webapp.py:187 #. CATEGORY_GROUPS['REPOS']
#: searx/searxng.msg
msgid "repos" msgid "repos"
msgstr "" msgstr ""
#: searx/webapp.py:188 #. CATEGORY_GROUPS['SOFTWARE_WIKIS']
#: searx/searxng.msg
msgid "software wikis" msgid "software wikis"
msgstr "" msgstr ""
#: searx/webapp.py:189 #. CATEGORY_GROUPS['WEB']
#: searx/searxng.msg
msgid "web" msgid "web"
msgstr "" msgstr ""
#: searx/webapp.py:194 #. STYLE_NAMES['AUTO']
#: searx/searxng.msg
msgid "auto" msgid "auto"
msgstr "" msgstr ""
#: searx/webapp.py:194 #. STYLE_NAMES['LIGHT']
#: searx/searxng.msg
msgid "light" msgid "light"
msgstr "" msgstr ""
#: searx/webapp.py:194 #. STYLE_NAMES['DARK']
#: searx/searxng.msg
msgid "dark" msgid "dark"
msgstr "" msgstr ""
#: searx/webapp.py:197 #: searx/webapp.py:168
msgid "timeout" msgid "timeout"
msgstr "" msgstr ""
#: searx/webapp.py:198 #: searx/webapp.py:169
msgid "parsing error" msgid "parsing error"
msgstr "" msgstr ""
#: searx/webapp.py:199 #: searx/webapp.py:170
msgid "HTTP protocol error" msgid "HTTP protocol error"
msgstr "" msgstr ""
#: searx/webapp.py:200 #: searx/webapp.py:171
msgid "network error" msgid "network error"
msgstr "" msgstr ""
#: searx/webapp.py:202 #: searx/webapp.py:173
msgid "unexpected crash" msgid "unexpected crash"
msgstr "" msgstr ""
#: searx/webapp.py:209 #: searx/webapp.py:180
msgid "HTTP error" msgid "HTTP error"
msgstr "" msgstr ""
#: searx/webapp.py:210 #: searx/webapp.py:181
msgid "HTTP connection error" msgid "HTTP connection error"
msgstr "" msgstr ""
#: searx/webapp.py:216 #: searx/webapp.py:187
msgid "proxy error" msgid "proxy error"
msgstr "" msgstr ""
#: searx/webapp.py:217 #: searx/webapp.py:188
msgid "CAPTCHA" msgid "CAPTCHA"
msgstr "" msgstr ""
#: searx/webapp.py:218 #: searx/webapp.py:189
msgid "too many requests" msgid "too many requests"
msgstr "" msgstr ""
#: searx/webapp.py:219 #: searx/webapp.py:190
msgid "access denied" msgid "access denied"
msgstr "" msgstr ""
#: searx/webapp.py:220 #: searx/webapp.py:191
msgid "server API error" msgid "server API error"
msgstr "" msgstr ""
#: searx/webapp.py:431 #: searx/webapp.py:409
msgid "No item found" msgid "No item found"
msgstr "" msgstr ""
#: searx/engines/qwant.py:212 #: searx/engines/qwant.py:212
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:433 #: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:411
msgid "Source" msgid "Source"
msgstr "" msgstr ""
#: searx/webapp.py:435 #: searx/webapp.py:413
msgid "Error loading the next page" msgid "Error loading the next page"
msgstr "" msgstr ""
#: searx/webapp.py:547 searx/webapp.py:967 #: searx/webapp.py:525 searx/webapp.py:979
msgid "Invalid settings, please edit your preferences" msgid "Invalid settings, please edit your preferences"
msgstr "" msgstr ""
#: searx/webapp.py:563 #: searx/webapp.py:541
msgid "Invalid settings" msgid "Invalid settings"
msgstr "" msgstr ""
#: searx/webapp.py:639 searx/webapp.py:714 #: searx/webapp.py:617 searx/webapp.py:693
msgid "search error" msgid "search error"
msgstr "" msgstr ""
#: searx/webapp.py:757 #: searx/webapp.py:739
msgid "{minutes} minute(s) ago" msgid "{minutes} minute(s) ago"
msgstr "" msgstr ""
#: searx/webapp.py:759 #: searx/webapp.py:741
msgid "{hours} hour(s), {minutes} minute(s) ago" msgid "{hours} hour(s), {minutes} minute(s) ago"
msgstr "" msgstr ""
#: searx/webapp.py:875 #: searx/webapp.py:870
msgid "Suspended" msgid "Suspended"
msgstr "" msgstr ""
@ -390,7 +422,7 @@ msgstr ""
#: searx/templates/oscar/preferences.html:362 #: searx/templates/oscar/preferences.html:362
#: searx/templates/oscar/preferences.html:425 #: searx/templates/oscar/preferences.html:425
#: searx/templates/simple/preferences.html:295 #: searx/templates/simple/preferences.html:295
#: searx/templates/simple/preferences.html:344 #: searx/templates/simple/preferences.html:346
msgid "Allow" msgid "Allow"
msgstr "" msgstr ""
@ -496,13 +528,13 @@ msgid "Engines"
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:105 #: searx/templates/oscar/preferences.html:105
#: searx/templates/simple/preferences.html:339 #: searx/templates/simple/preferences.html:341
msgid "Special Queries" msgid "Special Queries"
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:106 #: searx/templates/oscar/preferences.html:106
#: searx/templates/oscar/preferences.html:465 #: searx/templates/oscar/preferences.html:465
#: searx/templates/simple/preferences.html:379 #: searx/templates/simple/preferences.html:381
msgid "Cookies" msgid "Cookies"
msgstr "" msgstr ""
@ -779,78 +811,78 @@ msgid "Query"
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:426 #: searx/templates/oscar/preferences.html:426
#: searx/templates/simple/preferences.html:345 #: searx/templates/simple/preferences.html:347
msgid "Keywords" msgid "Keywords"
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:427 #: searx/templates/oscar/preferences.html:427
#: searx/templates/simple/preferences.html:346 #: searx/templates/simple/preferences.html:348
msgid "Name" msgid "Name"
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:428 #: searx/templates/oscar/preferences.html:428
#: searx/templates/simple/preferences.html:347 #: searx/templates/simple/preferences.html:349
msgid "Description" msgid "Description"
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:429 #: searx/templates/oscar/preferences.html:429
#: searx/templates/simple/preferences.html:348 #: searx/templates/simple/preferences.html:350
msgid "Examples" msgid "Examples"
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:434 #: searx/templates/oscar/preferences.html:434
#: searx/templates/simple/preferences.html:351 #: searx/templates/simple/preferences.html:353
msgid "This is the list of SearXNG's instant answering modules." msgid "This is the list of SearXNG's instant answering modules."
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:447 #: searx/templates/oscar/preferences.html:447
#: searx/templates/simple/preferences.html:362 #: searx/templates/simple/preferences.html:364
msgid "This is the list of plugins." msgid "This is the list of plugins."
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:468 #: searx/templates/oscar/preferences.html:468
#: searx/templates/simple/preferences.html:381 #: searx/templates/simple/preferences.html:383
msgid "" msgid ""
"This is the list of cookies and their values SearXNG is storing on your " "This is the list of cookies and their values SearXNG is storing on your "
"computer." "computer."
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:469 #: searx/templates/oscar/preferences.html:469
#: searx/templates/simple/preferences.html:382 #: searx/templates/simple/preferences.html:384
msgid "With that list, you can assess SearXNG transparency." msgid "With that list, you can assess SearXNG transparency."
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:474 #: searx/templates/oscar/preferences.html:474
#: searx/templates/simple/preferences.html:387 #: searx/templates/simple/preferences.html:389
msgid "Cookie name" msgid "Cookie name"
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:475 #: searx/templates/oscar/preferences.html:475
#: searx/templates/simple/preferences.html:388 #: searx/templates/simple/preferences.html:390
msgid "Value" msgid "Value"
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:492 #: searx/templates/oscar/preferences.html:492
#: searx/templates/simple/preferences.html:409 #: searx/templates/simple/preferences.html:411
msgid "" msgid ""
"These settings are stored in your cookies, this allows us not to store " "These settings are stored in your cookies, this allows us not to store "
"this data about you." "this data about you."
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:493 #: searx/templates/oscar/preferences.html:493
#: searx/templates/simple/preferences.html:411 #: searx/templates/simple/preferences.html:413
msgid "" msgid ""
"These cookies serve your sole convenience, we don't use these cookies to " "These cookies serve your sole convenience, we don't use these cookies to "
"track you." "track you."
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:497 #: searx/templates/oscar/preferences.html:497
#: searx/templates/simple/preferences.html:400 #: searx/templates/simple/preferences.html:402
msgid "Search URL of the currently saved preferences" msgid "Search URL of the currently saved preferences"
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:498 #: searx/templates/oscar/preferences.html:498
#: searx/templates/simple/preferences.html:404 #: searx/templates/simple/preferences.html:406
msgid "" msgid ""
"Note: specifying custom settings in the search URL can reduce privacy by " "Note: specifying custom settings in the search URL can reduce privacy by "
"leaking data to the clicked result sites." "leaking data to the clicked result sites."
@ -865,7 +897,7 @@ msgid "back"
msgstr "" msgstr ""
#: searx/templates/oscar/preferences.html:505 #: searx/templates/oscar/preferences.html:505
#: searx/templates/simple/preferences.html:415 #: searx/templates/simple/preferences.html:417
msgid "Reset defaults" msgid "Reset defaults"
msgstr "" msgstr ""
@ -1210,7 +1242,7 @@ msgstr ""
msgid "Length" msgid "Length"
msgstr "" msgstr ""
#: searx/templates/simple/categories.html:16 #: searx/templates/simple/categories.html:24
msgid "Click on the magnifier to perform search" msgid "Click on the magnifier to perform search"
msgstr "" msgstr ""
@ -1238,11 +1270,11 @@ msgstr ""
msgid "Supports selected language" msgid "Supports selected language"
msgstr "" msgstr ""
#: searx/templates/simple/preferences.html:414 #: searx/templates/simple/preferences.html:416
msgid "Save" msgid "Save"
msgstr "" msgstr ""
#: searx/templates/simple/preferences.html:416 #: searx/templates/simple/preferences.html:418
msgid "Back" msgid "Back"
msgstr "" msgstr ""
@ -1250,11 +1282,11 @@ msgstr ""
msgid "Answers" msgid "Answers"
msgstr "" msgstr ""
#: searx/templates/simple/results.html:164 #: searx/templates/simple/results.html:162
msgid "Previous page" msgid "Previous page"
msgstr "" msgstr ""
#: searx/templates/simple/results.html:181 #: searx/templates/simple/results.html:179
msgid "Next page" msgid "Next page"
msgstr "" msgstr ""

View File

@ -80,7 +80,6 @@ from searx.webutils import (
new_hmac, new_hmac,
is_hmac_of, is_hmac_of,
is_flask_run_cmdline, is_flask_run_cmdline,
DEFAULT_GROUP_NAME,
group_engines_in_tab, group_engines_in_tab,
) )
from searx.webadapter import ( from searx.webadapter import (
@ -167,35 +166,6 @@ app.secret_key = settings['server']['secret_key']
babel = Babel(app) babel = Babel(app)
# used when translating category names
_category_names = (
gettext('files'),
gettext('general'),
gettext('music'),
gettext('social media'),
gettext('images'),
gettext('videos'),
gettext('it'),
gettext('news'),
gettext('map'),
gettext('onions'),
gettext('science'),
# non-tab categories
gettext('apps'),
gettext('dictionaries'),
gettext('lyrics'),
gettext('packages'),
gettext('q&a'),
gettext('repos'),
gettext('software wikis'),
gettext('web'),
gettext(DEFAULT_GROUP_NAME),
gettext(OTHER_CATEGORY),
)
_simple_style = (gettext('auto'), gettext('light'), gettext('dark'))
#
timeout_text = gettext('timeout') timeout_text = gettext('timeout')
parsing_error_text = gettext('parsing error') parsing_error_text = gettext('parsing error')
http_protocol_error_text = gettext('HTTP protocol error') http_protocol_error_text = gettext('HTTP protocol error')