summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/integration.yml62
-rw-r--r--.github/workflows/translations-update.yml11
-rw-r--r--Dockerfile1
-rw-r--r--docs/admin/engines/settings.rst17
-rw-r--r--requirements.txt2
-rw-r--r--searx/engines/duckduckgo_weather.py4
-rw-r--r--searx/engines/metacpan.py79
-rw-r--r--searx/locales.py21
-rw-r--r--searx/network/network.py2
-rw-r--r--searx/plugins/limiter.py5
-rw-r--r--searx/search/checker/__init__.py2
-rw-r--r--searx/search/checker/background.py116
-rw-r--r--searx/search/checker/scheduler.lua36
-rw-r--r--searx/search/checker/scheduler.py57
-rw-r--r--searx/settings.yml8
-rw-r--r--searx/settings_defaults.py5
-rw-r--r--searx/shared/__init__.py41
-rw-r--r--searx/shared/redisdb.py49
-rw-r--r--searx/shared/shared_abstract.py22
-rw-r--r--searx/shared/shared_simple.py40
-rw-r--r--searx/shared/shared_uwsgi.py64
-rw-r--r--searx/translations/bn/LC_MESSAGES/messages.mobin9840 -> 11992 bytes
-rw-r--r--searx/translations/bn/LC_MESSAGES/messages.po26
-rw-r--r--searx/translations/ca/LC_MESSAGES/messages.mobin18192 -> 18293 bytes
-rw-r--r--searx/translations/ca/LC_MESSAGES/messages.po16
-rw-r--r--searx/translations/dv/LC_MESSAGES/messages.mobin0 -> 1467 bytes
-rw-r--r--searx/translations/dv/LC_MESSAGES/messages.po1172
-rw-r--r--searx/translations/hr/LC_MESSAGES/messages.mobin16664 -> 17919 bytes
-rw-r--r--searx/translations/hr/LC_MESSAGES/messages.po68
-rw-r--r--searx/translations/lv/LC_MESSAGES/messages.mobin7629 -> 8384 bytes
-rw-r--r--searx/translations/lv/LC_MESSAGES/messages.po35
-rw-r--r--searx/translations/ta/LC_MESSAGES/messages.mobin24219 -> 24229 bytes
-rw-r--r--searx/translations/ta/LC_MESSAGES/messages.po8
-rw-r--r--searx/translations/te/LC_MESSAGES/messages.mobin22896 -> 22992 bytes
-rw-r--r--searx/translations/te/LC_MESSAGES/messages.po14
-rw-r--r--searx/translations/zh_Hant_TW/LC_MESSAGES/messages.mobin16393 -> 16488 bytes
-rw-r--r--searx/translations/zh_Hant_TW/LC_MESSAGES/messages.po16
-rwxr-xr-xsearx/webapp.py2
-rwxr-xr-xutils/searxng.sh4
-rw-r--r--utils/searxng_check.py2
40 files changed, 1632 insertions, 375 deletions
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index f43f467e5..b66b5f865 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -6,6 +6,9 @@ on:
pull_request:
branches: ["master"]
+permissions:
+ contents: read
+
jobs:
python:
name: Python ${{ matrix.python-version }}
@@ -13,7 +16,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-20.04]
- python-version: ["3.7", "3.8", "3.9", "3.10"]
+ python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -22,15 +25,18 @@ jobs:
sudo ./utils/searxng.sh install packages
sudo apt install firefox
- name: Set up Python
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
- path: ./local
+ path: |
+ ./local
+ ./.nvm
+ ./node_modules
key: python-${{ matrix.os }}-${{ matrix.python-version }}-${{ hashFiles('requirements*.txt', 'setup.py') }}
- name: Install Python dependencies
if: steps.cache-python.outputs.cache-hit != 'true'
@@ -57,16 +63,19 @@ jobs:
- name: Install Ubuntu packages
run: sudo ./utils/searxng.sh install buildhost
- name: Set up Python
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
- path: ./local
- key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py') }}
+ path: |
+ ./local
+ ./.nvm
+ ./node_modules
+ key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: Install node dependencies
run: make V=1 node.env
- name: Build themes
@@ -75,6 +84,8 @@ jobs:
documentation:
name: Documentation
runs-on: ubuntu-20.04
+ permissions:
+ contents: write # for JamesIves/github-pages-deploy-action to push changes in repo
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -84,16 +95,19 @@ jobs:
- name: Install Ubuntu packages
run: sudo ./utils/searxng.sh install buildhost
- name: Set up Python
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
- path: ./local
- key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py') }}
+ path: |
+ ./local
+ ./.nvm
+ ./node_modules
+ key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: Build documentation
run: |
make V=1 docs.clean docs.html
@@ -116,6 +130,8 @@ jobs:
- python
- themes
- documentation
+ permissions:
+ contents: write # for make V=1 weblate.push.translations
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -123,16 +139,19 @@ jobs:
fetch-depth: '0'
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- name: Set up Python
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
- path: ./local
- key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py') }}
+ path: |
+ ./local
+ ./.nvm
+ ./node_modules
+ key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: weblate & git setup
env:
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
@@ -165,16 +184,19 @@ jobs:
# make sure "make docker.push" can get the git history
fetch-depth: '0'
- name: Set up Python
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
- path: ./local
- key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py') }}
+ path: |
+ ./local
+ ./.nvm
+ ./node_modules
+ key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: Set up QEMU
if: env.DOCKERHUB_USERNAME != null
uses: docker/setup-qemu-action@v1
diff --git a/.github/workflows/translations-update.yml b/.github/workflows/translations-update.yml
index c3120ce1e..bf1e11813 100644
--- a/.github/workflows/translations-update.yml
+++ b/.github/workflows/translations-update.yml
@@ -16,16 +16,19 @@ jobs:
fetch-depth: '0'
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- name: Set up Python
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
- path: ./local
- key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py') }}
+ path: |
+ ./local
+ ./.nvm
+ ./node_modules
+ key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: weblate & git setup
env:
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
diff --git a/Dockerfile b/Dockerfile
index 4509eea6e..64aa8bcef 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,6 @@
FROM alpine:3.16
ENTRYPOINT ["/sbin/tini","--","/usr/local/searxng/dockerfiles/docker-entrypoint.sh"]
EXPOSE 8080
-VOLUME /etc/searx
VOLUME /etc/searxng
ARG SEARXNG_GID=977
diff --git a/docs/admin/engines/settings.rst b/docs/admin/engines/settings.rst
index 086b3ccbe..3ac992d3e 100644
--- a/docs/admin/engines/settings.rst
+++ b/docs/admin/engines/settings.rst
@@ -314,20 +314,21 @@ developer) account needs to be added to the *searxng-redis* group.
.. admonition:: Tip for developers
- To set up a local redis instance using sockets simply use::
-
- $ ./manage redis.build
- $ sudo -H ./manage redis.install
- $ sudo -H ./manage redis.addgrp "${USER}"
- # don't forget to logout & login to get member of group
-
- The YAML setting for such a redis instance is:
+ To set up a local redis instance, first set the socket path of the Redis DB
+ in your YAML setting:
.. code:: yaml
redis:
url: unix:///usr/local/searxng-redis/run/redis.sock?db=0
+ Then use the following commands to install the redis instance ::
+
+ $ ./manage redis.build
+ $ sudo -H ./manage redis.install
+ $ sudo -H ./manage redis.addgrp "${USER}"
+ # don't forget to logout & login to get member of group
+
.. _settings outgoing:
diff --git a/requirements.txt b/requirements.txt
index aa3bdeb52..0bfeaf53f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,5 @@
certifi==2022.9.24
-babel==2.10.3
+babel==2.11.0
flask-babel==2.0.0
flask==2.2.2
jinja2==3.1.2
diff --git a/searx/engines/duckduckgo_weather.py b/searx/engines/duckduckgo_weather.py
index d0f34d60f..0540cbcb5 100644
--- a/searx/engines/duckduckgo_weather.py
+++ b/searx/engines/duckduckgo_weather.py
@@ -39,12 +39,12 @@ def generate_condition_table(condition):
res += (
f"<tr><td>{gettext('Wind')}</td><td>{condition['windBearing']}° — "
- f"{'%.2f' % (condition['windSpeed'] * 1.6093440006147)} km/h / {condition['windSpeed']} mph</td></tr>"
+ f"{(condition['windSpeed'] * 1.6093440006147):.2f} km/h / {condition['windSpeed']} mph</td></tr>"
)
res += f"<tr><td>{gettext('Visibility')}</td><td>{condition['visibility']} km</td>"
- res += f"<tr><td>{gettext('Humidity')}</td><td>{condition['humidity'] * 100}%</td></tr>"
+ res += f"<tr><td>{gettext('Humidity')}</td><td>{(condition['humidity'] * 100):.1f}%</td></tr>"
return res
diff --git a/searx/engines/metacpan.py b/searx/engines/metacpan.py
new file mode 100644
index 000000000..9d7f539e9
--- /dev/null
+++ b/searx/engines/metacpan.py
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+# lint: pylint
+"""metacpan
+"""
+
+from urllib.parse import urlunparse
+from json import dumps
+
+# about
+about = {
+ "website": 'https://metacpan.org/',
+ "wikidata_id": 'Q841507',
+ "official_api_documentation": 'https://github.com/metacpan/metacpan-api/blob/master/docs/API-docs.md',
+ "use_official_api": True,
+ "require_api_key": False,
+ "results": 'JSON',
+}
+
+# engine dependent config
+number_of_results = 20 # Don't put this over 5000
+categories = ["it", "packages"]
+disabled = True
+shortcut = "cpan"
+paging = True
+
+query_data_template = {
+ 'query': {
+ 'multi_match': {
+ 'type': 'most_fields',
+ 'fields': ['documentation', 'documentation.*'],
+ 'analyzer': 'camelcase',
+ }
+ },
+ 'filter': {
+ 'bool': {
+ 'must': [
+ {'exists': {'field': 'documentation'}},
+ {'term': {'status': 'latest'}},
+ {'term': {'indexed': 1}},
+ {'term': {'authorized': 1}},
+ ]
+ }
+ },
+ "sort": [
+ {"_score": {"order": "desc"}},
+ {"date": {"order": "desc"}},
+ ],
+ '_source': ['documentation', "abstract"],
+ 'size': number_of_results,
+}
+search_url = urlunparse(["https", "fastapi.metacpan.org", "/v1/file/_search", "", "", ""])
+
+
+def request(query, params):
+ params["url"] = search_url
+ params["method"] = "POST"
+ query_data = query_data_template
+ query_data["query"]["multi_match"]["query"] = query
+ query_data["from"] = (params["pageno"] - 1) * number_of_results
+ params["data"] = dumps(query_data)
+ return params
+
+
+def response(resp):
+ results = []
+
+ search_results = resp.json()["hits"]["hits"]
+ for result in search_results:
+ fields = result["_source"]
+ module = fields["documentation"]
+ results.append(
+ {
+ "url": "https://metacpan.org/pod/" + module,
+ "title": module,
+ "content": fields.get("abstract", ""),
+ }
+ )
+
+ return results
diff --git a/searx/locales.py b/searx/locales.py
index 620132340..8547e7fa7 100644
--- a/searx/locales.py
+++ b/searx/locales.py
@@ -35,6 +35,7 @@ RTL_LOCALES: Set[str] = set()
:py:obj:`locales_initialize`)."""
ADDITIONAL_TRANSLATIONS = {
+ "dv": "ދިވެހި (Dhivehi)",
"oc": "Occitan",
"szl": "Ślōnski (Silesian)",
"pap": "Papiamento",
@@ -43,6 +44,7 @@ ADDITIONAL_TRANSLATIONS = {
python-babel (see :py:obj:`locales_initialize`)."""
LOCALE_BEST_MATCH = {
+ "dv": "si",
"oc": 'fr-FR',
"szl": "pl",
"nl-BE": "nl",
@@ -80,15 +82,11 @@ def localeselector():
def get_translations():
"""Monkey patch of :py:obj:`flask_babel.get_translations`"""
- if has_request_context() and flask.request.form.get('use-translation') == 'oc':
- babel_ext = flask_babel.current_app.extensions['babel']
- return Translations.load(next(babel_ext.translation_directories), 'oc')
- if has_request_context() and flask.request.form.get('use-translation') == 'szl':
- babel_ext = flask_babel.current_app.extensions['babel']
- return Translations.load(next(babel_ext.translation_directories), 'szl')
- if has_request_context() and flask.request.form.get('use-translation') == 'pap':
- babel_ext = flask_babel.current_app.extensions['babel']
- return Translations.load(next(babel_ext.translation_directories), 'pap')
+ if has_request_context():
+ use_translation = flask.request.form.get('use-translation')
+ if use_translation in ADDITIONAL_TRANSLATIONS:
+ babel_ext = flask_babel.current_app.extensions['babel']
+ return Translations.load(next(babel_ext.translation_directories), use_translation)
return _flask_babel_get_translations()
@@ -136,13 +134,18 @@ def locales_initialize(directory=None):
flask_babel.get_translations = get_translations
for tag, descr in ADDITIONAL_TRANSLATIONS.items():
+ locale = Locale.parse(LOCALE_BEST_MATCH[tag], sep='-')
LOCALE_NAMES[tag] = descr
+ if locale.text_direction == 'rtl':
+ RTL_LOCALES.add(tag)
for tag in LOCALE_BEST_MATCH:
descr = LOCALE_NAMES.get(tag)
if not descr:
locale = Locale.parse(tag, sep='-')
LOCALE_NAMES[tag] = get_locale_descr(locale, tag.replace('-', '_'))
+ if locale.text_direction == 'rtl':
+ RTL_LOCALES.add(tag)
for dirname in sorted(os.listdir(directory)):
# Based on https://flask-babel.tkte.ch/_modules/flask_babel.html#Babel.list_translations
diff --git a/searx/network/network.py b/searx/network/network.py
index 87c077f23..6e1825dd9 100644
--- a/searx/network/network.py
+++ b/searx/network/network.py
@@ -173,7 +173,7 @@ class Network:
):
continue
return False
- response = await client.get("https://check.torproject.org/api/ip", timeout=10)
+ response = await client.get("https://check.torproject.org/api/ip", timeout=60)
if not response.json()["IsTor"]:
result = False
Network._TOR_CHECK_RESULT[proxies] = result
diff --git a/searx/plugins/limiter.py b/searx/plugins/limiter.py
index c6f5d6a0f..c11fd506b 100644
--- a/searx/plugins/limiter.py
+++ b/searx/plugins/limiter.py
@@ -93,9 +93,8 @@ def init(app, settings):
if not settings['server']['limiter']:
return False
- logger.debug("init limiter DB") # pylint: disable=undefined-variable
- if not redisdb.init():
- logger.error("init limiter DB failed!!!") # pylint: disable=undefined-variable
+ if not redisdb.client():
+ logger.error("The limiter requires Redis") # pylint: disable=undefined-variable
return False
app.before_request(pre_request)
diff --git a/searx/search/checker/__init__.py b/searx/search/checker/__init__.py
index 85b9178df..7d779a282 100644
--- a/searx/search/checker/__init__.py
+++ b/searx/search/checker/__init__.py
@@ -2,3 +2,5 @@
from .impl import Checker
from .background import initialize, get_result
+
+__all__ = ('Checker', 'initialize', 'get_result')
diff --git a/searx/search/checker/background.py b/searx/search/checker/background.py
index 3908245f8..e5bd642c0 100644
--- a/searx/search/checker/background.py
+++ b/searx/search/checker/background.py
@@ -1,26 +1,28 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# lint: pylint
# pylint: disable=missing-module-docstring
-# pyright: strict
+# pyright: basic
import json
-import random
import time
import threading
import os
import signal
-from typing import Dict, Union, List, Any, Tuple
+from typing import Dict, Union, List, Any, Tuple, Optional
from typing_extensions import TypedDict, Literal
+import redis.exceptions
+
from searx import logger, settings, searx_debug
+from searx.shared.redisdb import client as get_redis_client
from searx.exceptions import SearxSettingsException
from searx.search.processors import PROCESSORS
from searx.search.checker import Checker
-from searx.shared import schedule, storage # pyright: ignore
+from searx.search.checker.scheduler import scheduler_function
-CHECKER_RESULT = 'CHECKER_RESULT'
-running = threading.Lock()
+REDIS_RESULT_KEY = 'SearXNG_checker_result'
+REDIS_LOCK_KEY = 'SearXNG_checker_lock'
CheckerResult = Union['CheckerOk', 'CheckerErr', 'CheckerOther']
@@ -77,20 +79,24 @@ def _get_interval(every: Any, error_msg: str) -> Tuple[int, int]:
return (every[0], every[1])
-def _get_every():
- every = settings.get('checker', {}).get('scheduling', {}).get('every', (300, 1800))
- return _get_interval(every, 'checker.scheduling.every is not a int or list')
-
-
def get_result() -> CheckerResult:
- serialized_result = storage.get_str(CHECKER_RESULT)
- if serialized_result is not None:
- return json.loads(serialized_result)
- return {'status': 'unknown'}
+ client = get_redis_client()
+ if client is None:
+ # without Redis, the checker is disabled
+ return {'status': 'disabled'}
+ serialized_result: Optional[bytes] = client.get(REDIS_RESULT_KEY)
+ if serialized_result is None:
+ # the Redis key does not exist
+ return {'status': 'unknown'}
+ return json.loads(serialized_result)
def _set_result(result: CheckerResult):
- storage.set_str(CHECKER_RESULT, json.dumps(result))
+ client = get_redis_client()
+ if client is None:
+ # without Redis, the function does nothing
+ return
+ client.set(REDIS_RESULT_KEY, json.dumps(result))
def _timestamp():
@@ -98,41 +104,29 @@ def _timestamp():
def run():
- if not running.acquire(blocking=False): # pylint: disable=consider-using-with
- return
try:
- logger.info('Starting checker')
- result: CheckerOk = {'status': 'ok', 'engines': {}, 'timestamp': _timestamp()}
- for name, processor in PROCESSORS.items():
- logger.debug('Checking %s engine', name)
- checker = Checker(processor)
- checker.run()
- if checker.test_results.successful:
- result['engines'][name] = {'success': True}
- else:
- result['engines'][name] = {'success': False, 'errors': checker.test_results.errors}
-
- _set_result(result)
- logger.info('Check done')
+ # use a Redis lock to make sure there is no checker running at the same time
+ # (this should not happen, this is a safety measure)
+ with get_redis_client().lock(REDIS_LOCK_KEY, blocking_timeout=60, timeout=3600):
+ logger.info('Starting checker')
+ result: CheckerOk = {'status': 'ok', 'engines': {}, 'timestamp': _timestamp()}
+ for name, processor in PROCESSORS.items():
+ logger.debug('Checking %s engine', name)
+ checker = Checker(processor)
+ checker.run()
+ if checker.test_results.successful:
+ result['engines'][name] = {'success': True}
+ else:
+ result['engines'][name] = {'success': False, 'errors': checker.test_results.errors}
+
+ _set_result(result)
+ logger.info('Check done')
+ except redis.exceptions.LockError:
+ _set_result({'status': 'error', 'timestamp': _timestamp()})
+ logger.exception('Error while running the checker')
except Exception: # pylint: disable=broad-except
_set_result({'status': 'error', 'timestamp': _timestamp()})
logger.exception('Error while running the checker')
- finally:
- running.release()
-
-
-def _run_with_delay():
- every = _get_every()
- delay = random.randint(0, every[1] - every[0])
- logger.debug('Start checker in %i seconds', delay)
- time.sleep(delay)
- run()
-
-
-def _start_scheduling():
- every = _get_every()
- if schedule(every[0], _run_with_delay):
- run()
def _signal_handler(_signum: int, _frame: Any):
@@ -147,27 +141,31 @@ def initialize():
logger.info('Send SIGUSR1 signal to pid %i to start the checker', os.getpid())
signal.signal(signal.SIGUSR1, _signal_handler)
- # disabled by default
- _set_result({'status': 'disabled'})
-
# special case when debug is activate
- if searx_debug and settings.get('checker', {}).get('off_when_debug', True):
+ if searx_debug and settings['checker']['off_when_debug']:
logger.info('debug mode: checker is disabled')
return
# check value of checker.scheduling.every now
- scheduling = settings.get('checker', {}).get('scheduling', None)
+ scheduling = settings['checker']['scheduling']
if scheduling is None or not scheduling:
logger.info('Checker scheduler is disabled')
return
- #
- _set_result({'status': 'unknown'})
+ # make sure there is a Redis connection
+ if get_redis_client() is None:
+ logger.error('The checker requires Redis')
+ return
- start_after = scheduling.get('start_after', (300, 1800))
- start_after = _get_interval(start_after, 'checker.scheduling.start_after is not a int or list')
- delay = random.randint(start_after[0], start_after[1])
- logger.info('Start checker in %i seconds', delay)
- t = threading.Timer(delay, _start_scheduling)
+ # start the background scheduler
+ every_range = _get_interval(scheduling.get('every', (300, 1800)), 'checker.scheduling.every is not a int or list')
+ start_after_range = _get_interval(
+ scheduling.get('start_after', (300, 1800)), 'checker.scheduling.start_after is not a int or list'
+ )
+ t = threading.Thread(
+ target=scheduler_function,
+ args=(start_after_range[0], start_after_range[1], every_range[0], every_range[1], run),
+ name='checker_scheduler',
+ )
t.daemon = True
t.start()
diff --git a/searx/search/checker/scheduler.lua b/searx/search/checker/scheduler.lua
new file mode 100644
index 000000000..c5ebb05bc
--- /dev/null
+++ b/searx/search/checker/scheduler.lua
@@ -0,0 +1,36 @@
+-- SPDX-License-Identifier: AGPL-3.0-or-later
+--
+-- This script is not a string in scheduler.py, so editors can provide syntax highlighting.
+
+-- The Redis KEY is defined here and not in Python on purpose:
+-- only this LUA script can read and update this key to avoid lock and concurrency issues.
+local redis_key = 'SearXNG_checker_next_call_ts'
+
+local now = redis.call('TIME')[1]
+local start_after_from = ARGV[1]
+local start_after_to = ARGV[2]
+local every_from = ARGV[3]
+local every_to = ARGV[4]
+
+local next_call_ts = redis.call('GET', redis_key)
+
+if (next_call_ts == false or next_call_ts == nil) then
+ -- the scheduler has never run on this Redis instance, so:
+ -- 1/ the scheduler does not run now
+ -- 2/ the next call is a random time between start_after_from and start_after_to
+ local initial_delay = math.random(start_after_from, start_after_to)
+ redis.call('SET', redis_key, now + initial_delay)
+ return { false, delay }
+end
+
+-- next_call_ts is defined
+-- --> if now is lower than next_call_ts then we don't run the embedded checker
+-- --> if now is higher then we update next_call_ts and ask to run the embedded checker now.
+local call_now = next_call_ts <= now
+if call_now then
+ -- the checker runs now, define the timestamp of the next call:
+ -- this is a random delay between every_from and every_to
+ local periodic_delay = math.random(every_from, every_to)
+ next_call_ts = redis.call('INCRBY', redis_key, periodic_delay)
+end
+return { call_now, next_call_ts - now }
diff --git a/searx/search/checker/scheduler.py b/searx/search/checker/scheduler.py
new file mode 100644
index 000000000..1ae635951
--- /dev/null
+++ b/searx/search/checker/scheduler.py
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+# lint: pylint
+# pylint: disable=missing-module-docstring
+"""Lame scheduler which use Redis as a source of truth:
+* the Redis key SearXNG_checker_next_call_ts contains the next time the embedded checker should run.
+* to avoid lock, a unique Redis script reads and updates the Redis key SearXNG_checker_next_call_ts.
+* this Redis script returns a list of two elements:
+ * the first one is a boolean. If True, the embedded checker must run now in this worker.
+ * the second element is the delay in second to wait before the next call to the Redis script.
+
+This scheduler is not generic on purpose: if more feature are required, a dedicate scheduler must be used
+(= a better scheduler should not use the web workers)
+"""
+
+import logging
+import time
+import importlib
+from typing import Callable
+
+from searx.shared.redisdb import client as get_redis_client
+from searx.redislib import lua_script_storage
+
+
+logger = logging.getLogger('searx.search.checker')
+
+
+def scheduler_function(start_after_from: int, start_after_to: int, every_from: int, every_to: int, callback: Callable):
+ """Run the checker periodically. The function never returns.
+
+ Parameters:
+ * start_after_from and start_after_to: when to call "callback" for the first on the Redis instance
+ * every_from and every_to: after the first call, how often to call "callback"
+
+ There is no issue:
+ * to call this function is multiple workers
+ * to kill workers at any time as long there is one at least one worker
+ """
+ scheduler_now_script = importlib.resources.read_text(__package__, "scheduler.lua")
+ while True:
+ # ask the Redis script what to do
+ # the script says
+ # * if the checker must run now.
+ # * how to long to way before calling the script again (it can be call earlier, but not later).
+ script = lua_script_storage(get_redis_client(), scheduler_now_script)
+ call_now, wait_time = script(args=[start_after_from, start_after_to, every_from, every_to])
+
+ # does the worker run the checker now?
+ if call_now:
+ # run the checker
+ try:
+ callback()
+ except Exception: # pylint: disable=broad-except
+ logger.exception("Error calling the embedded checker")
+ # only worker display the wait_time
+ logger.info("Next call to the checker in %s seconds", wait_time)
+ # wait until the next call
+ time.sleep(wait_time)
diff --git a/searx/settings.yml b/searx/settings.yml
index 2304c6fe7..59df409a8 100644
--- a/searx/settings.yml
+++ b/searx/settings.yml
@@ -78,7 +78,7 @@ server:
redis:
# https://redis-py.readthedocs.io/en/stable/connections.html#redis.client.Redis.from_url
- url: unix:///usr/local/searxng-redis/run/redis.sock?db=0
+ url: false
ui:
# Custom static path - leave it blank if you didn't change
@@ -950,6 +950,12 @@ engines:
require_api_key: false
results: HTML
+ - name: metacpan
+ engine: metacpan
+ shortcut: cpan
+ disabled: true
+ number_of_results: 20
+
# - name: meilisearch
# engine: meilisearch
# shortcut: mes
diff --git a/searx/settings_defaults.py b/searx/settings_defaults.py
index 6575b0b0c..470290f92 100644
--- a/searx/settings_defaults.py
+++ b/searx/settings_defaults.py
@@ -174,7 +174,7 @@ SCHEMA = {
'default_http_headers': SettingsValue(dict, {}),
},
'redis': {
- 'url': SettingsValue(str, 'unix:///usr/local/searxng-redis/run/redis.sock?db=0'),
+ 'url': SettingsValue((None, False, str), False),
},
'ui': {
'static_path': SettingsDirectoryValue(str, os.path.join(searx_dir, 'static')),
@@ -225,7 +225,8 @@ SCHEMA = {
'plugins': SettingsValue(list, []),
'enabled_plugins': SettingsValue((None, list), None),
'checker': {
- 'off_when_debug': SettingsValue(bool, True),
+ 'off_when_debug': SettingsValue(bool, True, None),
+ 'scheduling': SettingsValue((None, dict), None, None),
},
'categories_as_tabs': SettingsValue(dict, CATEGORIES_AS_TABS),
'engines': SettingsValue(list, []),
diff --git a/searx/shared/__init__.py b/searx/shared/__init__.py
index d10ddb33d..2c7fc9f8b 100644
--- a/searx/shared/__init__.py
+++ b/searx/shared/__init__.py
@@ -1,39 +1,6 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
+# lint: pylint
+"""Initialization of a *shared* storage.
+"""
-import logging
-import importlib
-
-logger = logging.getLogger('searx.shared')
-
-__all__ = ['SharedDict', 'schedule']
-
-try:
- uwsgi = importlib.import_module('uwsgi')
-except:
- # no uwsgi
- from .shared_simple import SimpleSharedDict as SharedDict, schedule
-
- logger.info('Use shared_simple implementation')
-else:
- try:
- uwsgi.cache_update('dummy', b'dummy')
- if uwsgi.cache_get('dummy') != b'dummy':
- raise Exception()
- except:
- # uwsgi.ini configuration problem: disable all scheduling
- logger.error(
- 'uwsgi.ini configuration error, add this line to your uwsgi.ini\n'
- 'cache2 = name=searxngcache,items=2000,blocks=2000,blocksize=4096,bitmap=1'
- )
- from .shared_simple import SimpleSharedDict as SharedDict
-
- def schedule(delay, func, *args):
- return False
-
- else:
- # uwsgi
- from .shared_uwsgi import UwsgiCacheSharedDict as SharedDict, schedule
-
- logger.info('Use shared_uwsgi implementation')
-
-storage = SharedDict()
+from . import redisdb
diff --git a/searx/shared/redisdb.py b/searx/shared/redisdb.py
index bb7a0eeb4..ba4a76baa 100644
--- a/searx/shared/redisdb.py
+++ b/searx/shared/redisdb.py
@@ -26,26 +26,45 @@ import redis
from searx import get_setting
-logger = logging.getLogger('searx.shared.redis')
-_client = None
+OLD_REDIS_URL_DEFAULT_URL = 'unix:///usr/local/searxng-redis/run/redis.sock?db=0'
+"""This was the default Redis URL in settings.yml."""
+_CLIENT = None
+logger = logging.getLogger('searx.shared.redisdb')
-def client():
- global _client # pylint: disable=global-statement
- if _client is None:
- # not thread safe: in the worst case scenario, two or more clients are
- # initialized only one is kept, the others are garbage collected.
- _client = redis.Redis.from_url(get_setting('redis.url'))
- return _client
+def client() -> redis.Redis:
+ return _CLIENT
-def init():
+
+def initialize():
+ global _CLIENT # pylint: disable=global-statement
+ redis_url = get_setting('redis.url')
+ if not redis_url:
+ return False
try:
- c = client()
- logger.info("connected redis DB --> %s", c.acl_whoami())
+ # create a client, but no connection is done
+ _CLIENT = redis.Redis.from_url(redis_url)
+
+ # log the parameters as seen by the redis lib, without the password
+ kwargs = _CLIENT.get_connection_kwargs()
+ kwargs.pop('password', None)
+ kwargs = ' '.join([f'{k}={v!r}' for k, v in kwargs.items()])
+ logger.info("connecting to Redis %s", kwargs)
+
+ # check the connection
+ _CLIENT.ping()
+
+ # no error: the redis connection is working
+ logger.info("connected to Redis")
return True
- except redis.exceptions.ConnectionError as exc:
+ except redis.exceptions.RedisError as e:
+ _CLIENT = None
_pw = pwd.getpwuid(os.getuid())
- logger.error("[%s (%s)] can't connect redis DB ...", _pw.pw_name, _pw.pw_uid)
- logger.error(" %s", exc)
+ logger.exception("[%s (%s)] can't connect redis DB ...", _pw.pw_name, _pw.pw_uid)
+ if redis_url == OLD_REDIS_URL_DEFAULT_URL and isinstance(e, redis.exceptions.ConnectionError):
+ logger.info(
+ "You can safely ignore the above Redis error if you don't use Redis. "
+ "You can remove this error by setting redis.url to false in your settings.yml."
+ )
return False
diff --git a/searx/shared/shared_abstract.py b/searx/shared/shared_abstract.py
deleted file mode 100644
index af4be30ae..000000000
--- a/searx/shared/shared_abstract.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# SPDX-License-Identifier: AGPL-3.0-or-later
-# pyright: strict
-from abc import ABC, abstractmethod
-from typing import Optional
-
-
-class SharedDict(ABC):
- @abstractmethod
- def get_int(self, key: str) -> Optional[int]:
- pass
-
- @abstractmethod
- def set_int(self, key: str, value: int):
- pass
-
- @abstractmethod
- def get_str(self, key: str) -> Optional[str]:
- pass
-
- @abstractmethod
- def set_str(self, key: str, value: str):
- pass
diff --git a/searx/shared/shared_simple.py b/searx/shared/shared_simple.py
deleted file mode 100644
index 2b9d4c2da..000000000
--- a/searx/shared/shared_simple.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# SPDX-License-Identifier: AGPL-3.0-or-later
-
-import threading
-from typing import Optional
-
-from . import shared_abstract
-
-
-class SimpleSharedDict(shared_abstract.SharedDict):
-
- __slots__ = ('d',)
-
- def __init__(self):
- self.d = {}
-
- def get_int(self, key: str) -> Optional[int]:
- return self.d.get(key, None)
-
- def set_int(self, key: str, value: int):
- self.d[key] = value
-
- def get_str(self, key: str) -> Optional[str]:
- return self.d.get(key, None)
-
- def set_str(self, key: str, value: str):
- self.d[key] = value
-
-
-def schedule(delay, func, *args):
- def call_later():
- t = threading.Timer(delay, wrapper)
- t.daemon = True
- t.start()
-
- def wrapper():
- call_later()
- func(*args)
-
- call_later()
- return True
diff --git a/searx/shared/shared_uwsgi.py b/searx/shared/shared_uwsgi.py
deleted file mode 100644
index 0248c6234..000000000
--- a/searx/shared/shared_uwsgi.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# SPDX-License-Identifier: AGPL-3.0-or-later
-
-import time
-from typing import Optional
-import uwsgi # pyright: ignore # pylint: disable=E0401
-from . import shared_abstract
-
-
-_last_signal = 10
-
-
-class UwsgiCacheSharedDict(shared_abstract.SharedDict):
- def get_int(self, key: str) -> Optional[int]:
- value = uwsgi.cache_get(key)
- if value is None:
- return value
- else:
- return int.from_bytes(value, 'big')
-
- def set_int(self, key: str, value: int):
- b = value.to_bytes(4, 'big')
- uwsgi.cache_update(key, b)
-
- def get_str(self, key: str) -> Optional[str]:
- value = uwsgi.cache_get(key)
- if value is None:
- return value
- else:
- return value.decode('utf-8')
-
- def set_str(self, key: str, value: str):
- b = value.encode('utf-8')
- uwsgi.cache_update(key, b)
-
-
-def schedule(delay, func, *args):
- """
- Can be implemented using a spooler.
- https://uwsgi-docs.readthedocs.io/en/latest/PythonDecorators.html
-
- To make the uwsgi configuration simple, use the alternative implementation.
- """
- global _last_signal
-
- def sighandler(signum):
- now = int(time.time())
- key = 'scheduler_call_time_signal_' + str(signum)
- uwsgi.lock()
- try:
- updating = uwsgi.cache_get(key)
- if updating is not None:
- updating = int.from_bytes(updating, 'big')
- if now - updating < delay:
- return
- uwsgi.cache_update(key, now.to_bytes(4, 'big'))
- finally:
- uwsgi.unlock()
- func(*args)
-
- signal_num = _last_signal
- _last_signal += 1
- uwsgi.register_signal(signal_num, 'worker', sighandler)
- uwsgi.add_timer(signal_num, delay)
- return True
diff --git a/searx/translations/bn/LC_MESSAGES/messages.mo b/searx/translations/bn/LC_MESSAGES/messages.mo
index 5fd1ad74c..ab0ddae97 100644
--- a/searx/translations/bn/LC_MESSAGES/messages.mo
+++ b/searx/translations/bn/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/searx/translations/bn/LC_MESSAGES/messages.po b/searx/translations/bn/LC_MESSAGES/messages.po
index 03530ba31..604fbebd9 100644
--- a/searx/translations/bn/LC_MESSAGES/messages.po
+++ b/searx/translations/bn/LC_MESSAGES/messages.po
@@ -9,15 +9,16 @@ msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-10-14 14:11+0000\n"
-"PO-Revision-Date: 2022-10-11 13:31+0000\n"
+"PO-Revision-Date: 2022-11-04 07:18+0000\n"
"Last-Translator: Markus Heiser <markus.heiser@darmarit.de>\n"
+"Language-Team: Bengali <https://weblate.bubu1.eu/projects/searxng/searxng/bn/"
+">\n"
"Language: bn\n"
-"Language-Team: Bengali "
-"<https://weblate.bubu1.eu/projects/searxng/searxng/bn/>\n"
-"Plural-Forms: nplurals=2; plural=n > 1;\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+"X-Generator: Weblate 4.14.1\n"
"Generated-By: Babel 2.10.3\n"
#. CONSTANT_NAMES['DEFAULT_GROUP_NAME']
@@ -163,7 +164,7 @@ msgstr "নেটওয়ার্ক ত্রুটি"
#: searx/webapp.py:168
msgid "SSL error: certificate validation has failed"
-msgstr ""
+msgstr "SSL ত্রুটি: শংসাপত্রের বৈধতা ব্যর্থ হয়েছে৷"
#: searx/webapp.py:170
msgid "unexpected crash"
@@ -361,6 +362,8 @@ msgid ""
"Displays your IP if the query is \"ip\" and your user agent if the query "
"contains \"user agent\"."
msgstr ""
+"ক্যোয়ারীটি \"ip\" হলে আপনার আইপি এবং যদি ক্যোয়ারীতে \"ব্যবহারকারী এজেন্ট\" "
+"থাকে তাহলে আপনার ব্যবহারকারী এজেন্ট প্রদর্শন করে।"
#: searx/plugins/tor_check.py:25
msgid "Tor check plugin"
@@ -371,28 +374,34 @@ msgid ""
"This plugin checks if the address of the request is a TOR exit node, and "
"informs the user if it is, like check.torproject.org but from searxng."
msgstr ""
+"এই প্লাগইনটি চেক করে যে অনুরোধের ঠিকানাটি একটি TOR প্রস্থান নোড কিনা এবং "
+"ব্যবহারকারীকে জানিয়ে দেয় যে এটি কিনা, যেমন check.torproject.org কিন্তু "
+"searxng থেকে।"
#: searx/plugins/tor_check.py:62
msgid ""
"The TOR exit node list (https://check.torproject.org/exit-addresses) is "
"unreachable."
msgstr ""
+"TOR প্রস্থান নোড তালিকা (https://check.torproject.org/exit-addresses) পৌঁছানো"
+" যায় না।"
#: searx/plugins/tor_check.py:78
msgid "You are using TOR. Your IP address seems to be: {ip_address}."
-msgstr ""
+msgstr "আপনি TOR ব্যবহার করছেন। আপনার আইপি ঠিকানা বলে মনে হচ্ছে: {ip_address}।"
#: searx/plugins/tor_check.py:84
msgid "You are not using TOR. Your IP address seems to be: {ip_address}."
msgstr ""
+"আপনি TOR ব্যবহার করছেন না। আপনার আইপি ঠিকানা বলে মনে হচ্ছে: {ip_address}।"
#: searx/plugins/tracker_url_remover.py:29
msgid "Tracker URL remover"
-msgstr ""
+msgstr "ট্র্যাকার URL রিমুভার"
#: searx/plugins/tracker_url_remover.py:30
msgid "Remove trackers arguments from the returned URL"
-msgstr ""
+msgstr "ফিরে আসা URL থেকে ট্র্যাকার আর্গুমেন্টগুলি সরান৷"
#: searx/plugins/vim_hotkeys.py:3
msgid "Vim-like hotkeys"
@@ -1209,4 +1218,3 @@ msgstr ""
#~ " rel=\"external\">learn more about request "
#~ "methods</a>"
#~ msgstr ""
-
diff --git a/searx/translations/ca/LC_MESSAGES/messages.mo b/searx/translations/ca/LC_MESSAGES/messages.mo
index df86fe9db..36de2e753 100644
--- a/searx/translations/ca/LC_MESSAGES/messages.mo
+++ b/searx/translations/ca/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/searx/translations/ca/LC_MESSAGES/messages.po b/searx/translations/ca/LC_MESSAGES/messages.po
index 88b89bf91..71bc38261 100644
--- a/searx/translations/ca/LC_MESSAGES/messages.po
+++ b/searx/translations/ca/LC_MESSAGES/messages.po
@@ -13,18 +13,19 @@
# Markus Heiser <markus.heiser@darmarit.de>, 2022.
msgid ""
msgstr ""
-"Project-Id-Version: searx\n"
+"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-10-14 14:11+0000\n"
-"PO-Revision-Date: 2022-09-30 07:43+0000\n"
-"Last-Translator: Markus Heiser <markus.heiser@darmarit.de>\n"
+"PO-Revision-Date: 2022-11-04 07:18+0000\n"
+"Last-Translator: alexfs2015 <alex04fs@gmail.com>\n"
+"Language-Team: Catalan <https://weblate.bubu1.eu/projects/searxng/searxng/ca/"
+">\n"
"Language: ca\n"
-"Language-Team: Catalan "
-"<https://weblate.bubu1.eu/projects/searxng/searxng/ca/>\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.14.1\n"
"Generated-By: Babel 2.10.3\n"
#. CONSTANT_NAMES['DEFAULT_GROUP_NAME']
@@ -170,7 +171,7 @@ msgstr "error de xarxa"
#: searx/webapp.py:168
msgid "SSL error: certificate validation has failed"
-msgstr ""
+msgstr "Error SSL: la validació del certificat ha fallat"
#: searx/webapp.py:170
msgid "unexpected crash"
@@ -1501,4 +1502,3 @@ msgstr "amaga el vídeo"
#~ "href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\""
#~ " rel=\"external\">més informació sobre els "
#~ "mètodes de petició</a>"
-
diff --git a/searx/translations/dv/LC_MESSAGES/messages.mo b/searx/translations/dv/LC_MESSAGES/messages.mo
new file mode 100644
index 000000000..77d20d2ec
--- /dev/null
+++ b/searx/translations/dv/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/searx/translations/dv/LC_MESSAGES/messages.po b/searx/translations/dv/LC_MESSAGES/messages.po
new file mode 100644
index 000000000..6fc11810f
--- /dev/null
+++ b/searx/translations/dv/LC_MESSAGES/messages.po
@@ -0,0 +1,1172 @@
+# Translations template for PROJECT.
+# Copyright (C) 2022 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
+# Landhoo School Students <landhooschoolstudents@gmail.com>, 2022.
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2022-10-14 14:11+0000\n"
+"PO-Revision-Date: 2022-11-04 07:18+0000\n"
+"Last-Translator: Landhoo School Students <landhooschoolstudents@gmail.com>\n"
+"Language-Team: Dhivehi <https://weblate.bubu1.eu/projects/searxng/searxng/dv/"
+">\n"
+"Language: dv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.14.1\n"
+"Generated-By: Babel 2.10.3\n"
+
+#. 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"
+msgstr "ފައިލްތައް"
+
+#. CATEGORY_NAMES['GENERAL']
+#: searx/searxng.msg
+msgid "general"
+msgstr "އާންމުގޮތެއްގައި"
+
+#. CATEGORY_NAMES['MUSIC']
+#: searx/searxng.msg
+msgid "music"
+msgstr "މިއުޒިކު"
+
+#. CATEGORY_NAMES['SOCIAL_MEDIA']
+#: searx/searxng.msg
+msgid "social media"
+msgstr "ސޯސަލްމީޑިއާ"
+
+#. CATEGORY_NAMES['IMAGES']
+#: searx/searxng.msg
+msgid "images"
+msgstr "ފޮޓޯ"
+
+#. CATEGORY_NAMES['VIDEOS']
+#: searx/searxng.msg
+msgid "videos"
+msgstr "ވީޑިޔޯތައް"
+
+#. CATEGORY_NAMES['IT']
+#: searx/searxng.msg
+msgid "it"
+msgstr "އައިޓީ"
+
+#. CATEGORY_NAMES['NEWS']
+#: searx/searxng.msg
+msgid "news"
+msgstr "ޚަބަރު"
+
+#. CATEGORY_NAMES['MAP']
+#: searx/searxng.msg
+msgid "map"
+msgstr "މެޕް"
+
+#. CATEGORY_NAMES['ONIONS']
+#: searx/searxng.msg
+msgid "onions"
+msgstr "ފިޔާތައް"
+
+#. CATEGORY_NAMES['SCIENCE']
+#: searx/searxng.msg
+msgid "science"
+msgstr "ސައިންސް"
+
+#. CATEGORY_GROUPS['APPS']
+#: searx/searxng.msg
+msgid "apps"
+msgstr "އެޕްތައް"
+
+#. CATEGORY_GROUPS['DICTIONARIES']
+#: searx/searxng.msg
+msgid "dictionaries"
+msgstr "ބަސްފޮތްތައް"
+
+#. CATEGORY_GROUPS['LYRICS']
+#: searx/searxng.msg
+msgid "lyrics"
+msgstr "ލިރިކްސް"
+
+#. CATEGORY_GROUPS['PACKAGES']
+#: searx/searxng.msg
+msgid "packages"
+msgstr "ޕެކޭޖްތައް"
+
+#. CATEGORY_GROUPS['Q_A']
+#: searx/searxng.msg
+msgid "q&a"
+msgstr "ސުވާލެއި ޖަވާބް"
+
+#. CATEGORY_GROUPS['REPOS']
+#: searx/searxng.msg
+msgid "repos"
+msgstr ""
+
+#. CATEGORY_GROUPS['SOFTWARE_WIKIS']
+#: searx/searxng.msg
+msgid "software wikis"
+msgstr ""
+
+#. CATEGORY_GROUPS['WEB']
+#: searx/searxng.msg
+msgid "web"
+msgstr "ވެބް"
+
+#. CATEGORY_GROUPS['SCIENTIFIC PUBLICATIONS']
+#: searx/searxng.msg
+msgid "scientific publications"
+msgstr "ސައިންޓިފިކް އީޖާދުތައް"
+
+#. STYLE_NAMES['AUTO']
+#: searx/searxng.msg
+msgid "auto"
+msgstr "އަމިއްލައަށް"
+
+#. STYLE_NAMES['LIGHT']
+#: searx/searxng.msg
+msgid "light"
+msgstr "އަލި"
+
+#. STYLE_NAMES['DARK']
+#: searx/searxng.msg
+msgid "dark"
+msgstr "އަނދިރި"
+
+#: searx/webapp.py:164
+msgid "timeout"
+msgstr ""
+
+#: searx/webapp.py:165
+msgid "parsing error"
+msgstr ""
+
+#: searx/webapp.py:166
+msgid "HTTP protocol error"
+msgstr ""
+
+#: searx/webapp.py:167
+msgid "network error"
+msgstr ""
+
+#: searx/webapp.py:168
+msgid "SSL error: certificate validation has failed"
+msgstr ""
+
+#: searx/webapp.py:170
+msgid "unexpected crash"
+msgstr ""
+
+#: searx/webapp.py:177
+msgid "HTTP error"
+msgstr ""
+
+#: searx/webapp.py:178
+msgid "HTTP connection error"
+msgstr ""
+
+#: searx/webapp.py:184
+msgid "proxy error"
+msgstr ""
+
+#: searx/webapp.py:185
+msgid "CAPTCHA"
+msgstr ""
+
+#: searx/webapp.py:186
+msgid "too many requests"
+msgstr ""
+
+#: searx/webapp.py:187
+msgid "access denied"
+msgstr ""
+
+#: searx/webapp.py:188
+msgid "server API error"
+msgstr ""
+
+#: searx/webapp.py:365
+msgid "No item found"
+msgstr ""
+
+#: searx/engines/qwant.py:217
+#: searx/templates/simple/result_templates/images.html:20 searx/webapp.py:367
+msgid "Source"
+msgstr ""
+
+#: searx/webapp.py:369
+msgid "Error loading the next page"
+msgstr ""
+
+#: searx/webapp.py:521 searx/webapp.py:953
+msgid "Invalid settings, please edit your preferences"
+msgstr ""
+
+#: searx/webapp.py:537
+msgid "Invalid settings"
+msgstr ""
+
+#: searx/webapp.py:614 searx/webapp.py:690
+msgid "search error"
+msgstr ""
+
+#: searx/webapp.py:852
+msgid "Suspended"
+msgstr ""
+
+#: searx/webutils.py:161
+msgid "{minutes} minute(s) ago"
+msgstr ""
+
+#: searx/webutils.py:162
+msgid "{hours} hour(s), {minutes} minute(s) ago"
+msgstr ""
+
+#: searx/answerers/random/answerer.py:67
+msgid "Random value generator"
+msgstr ""
+
+#: searx/answerers/random/answerer.py:68
+msgid "Generate different random values"
+msgstr ""
+
+#: searx/answerers/statistics/answerer.py:47
+msgid "Statistics functions"
+msgstr ""
+
+#: searx/answerers/statistics/answerer.py:48
+msgid "Compute {functions} of the arguments"
+msgstr ""
+
+#: searx/engines/openstreetmap.py:160
+msgid "Get directions"
+msgstr ""
+
+#: searx/engines/pdbe.py:96
+msgid "{title} (OBSOLETE)"
+msgstr ""
+
+#: searx/engines/pdbe.py:103
+msgid "This entry has been superseded by"
+msgstr ""
+
+#: searx/engines/qwant.py:219
+msgid "Channel"
+msgstr ""
+
+#: searx/engines/semantic_scholar.py:81
+msgid ""
+"{numCitations} citations from the year {firstCitationVelocityYear} to "
+"{lastCitationVelocityYear}"
+msgstr ""
+
+#: searx/engines/tineye.py:40
+msgid ""
+"Could not read that image url. This may be due to an unsupported file "
+"format. TinEye only supports images that are JPEG, PNG, GIF, BMP, TIFF or"
+" WebP."
+msgstr ""
+
+#: searx/engines/tineye.py:46
+msgid ""
+"The image is too simple to find matches. TinEye requires a basic level of"
+" visual detail to successfully identify matches."
+msgstr ""
+
+#: searx/engines/tineye.py:52
+msgid "The image could not be downloaded."
+msgstr ""
+
+#: searx/engines/wttr.py:101
+msgid "Morning"
+msgstr ""
+
+#: searx/engines/wttr.py:101
+msgid "Noon"
+msgstr ""
+
+#: searx/engines/wttr.py:101
+msgid "Evening"
+msgstr ""
+
+#: searx/engines/wttr.py:101
+msgid "Night"
+msgstr ""
+
+#: searx/plugins/hash_plugin.py:24
+msgid "Converts strings to different hash digests."
+msgstr ""
+
+#: searx/plugins/hash_plugin.py:52
+msgid "hash digest"
+msgstr ""
+
+#: searx/plugins/hostname_replace.py:9
+msgid "Hostname replace"
+msgstr ""
+
+#: searx/plugins/hostname_replace.py:10
+msgid "Rewrite result hostnames or remove results based on the hostname"
+msgstr ""
+
+#: searx/plugins/oa_doi_rewrite.py:9
+msgid "Open Access DOI rewrite"
+msgstr ""
+
+#: searx/plugins/oa_doi_rewrite.py:10
+msgid ""
+"Avoid paywalls by redirecting to open-access versions of publications "
+"when available"
+msgstr ""
+
+#: searx/plugins/search_on_category_select.py:19
+msgid "Search on category select"
+msgstr ""
+
+#: searx/plugins/search_on_category_select.py:20
+msgid ""
+"Perform search immediately if a category selected. Disable to select "
+"multiple categories. (JavaScript required)"
+msgstr ""
+
+#: searx/plugins/self_info.py:20
+msgid "Self Information"
+msgstr ""
+
+#: searx/plugins/self_info.py:21
+msgid ""
+"Displays your IP if the query is \"ip\" and your user agent if the query "
+"contains \"user agent\"."
+msgstr ""
+
+#: searx/plugins/tor_check.py:25
+msgid "Tor check plugin"
+msgstr ""
+
+#: searx/plugins/tor_check.py:28
+msgid ""
+"This plugin checks if the address of the request is a TOR exit node, and "
+"informs the user if it is, like check.torproject.org but from searxng."
+msgstr ""
+
+#: searx/plugins/tor_check.py:62
+msgid ""
+"The TOR exit node list (https://check.torproject.org/exit-addresses) is "
+"unreachable."
+msgstr ""
+
+#: searx/plugins/tor_check.py:78
+msgid "You are using TOR. Your IP address seems to be: {ip_address}."
+msgstr ""
+
+#: searx/plugins/tor_check.py:84
+msgid "You are not using TOR. Your IP address seems to be: {ip_address}."
+msgstr ""
+
+#: searx/plugins/tracker_url_remover.py:29
+msgid "Tracker URL remover"
+msgstr ""
+
+#: searx/plugins/tracker_url_remover.py:30
+msgid "Remove trackers arguments from the returned URL"
+msgstr ""
+
+#: searx/plugins/vim_hotkeys.py:3
+msgid "Vim-like hotkeys"
+msgstr ""
+
+#: searx/plugins/vim_hotkeys.py:4
+msgid ""
+"Navigate search results with Vim-like hotkeys (JavaScript required). "
+"Press \"h\" key on main or result page to get help."
+msgstr ""
+
+#: searx/templates/simple/404.html:4
+msgid "Page not found"
+msgstr ""
+
+#: searx/templates/simple/404.html:6
+#, python-format
+msgid "Go to %(search_page)s."
+msgstr ""
+
+#: searx/templates/simple/404.html:6
+msgid "search page"
+msgstr ""
+
+#: searx/templates/simple/base.html:46
+msgid "About"
+msgstr ""
+
+#: searx/templates/simple/base.html:50
+msgid "Donate"
+msgstr ""
+
+#: searx/templates/simple/base.html:54
+#: searx/templates/simple/preferences.html:99
+msgid "Preferences"
+msgstr ""
+
+#: searx/templates/simple/base.html:64
+msgid "Powered by"
+msgstr ""
+
+#: searx/templates/simple/base.html:64
+msgid "a privacy-respecting, open metasearch engine"
+msgstr ""
+
+#: searx/templates/simple/base.html:65
+msgid "Source code"
+msgstr ""
+
+#: searx/templates/simple/base.html:66
+msgid "Issue tracker"
+msgstr ""
+
+#: searx/templates/simple/base.html:67 searx/templates/simple/stats.html:18
+msgid "Engine stats"
+msgstr ""
+
+#: searx/templates/simple/base.html:69
+#: searx/templates/simple/messages/no_results.html:15
+msgid "Public instances"
+msgstr ""
+
+#: searx/templates/simple/base.html:72
+msgid "Privacy policy"
+msgstr ""
+
+#: searx/templates/simple/base.html:75
+msgid "Contact instance maintainer"
+msgstr ""
+
+#: searx/templates/simple/categories.html:24
+msgid "Click on the magnifier to perform search"
+msgstr ""
+
+#: searx/templates/simple/macros.html:36
+msgid "Length"
+msgstr ""
+
+#: searx/templates/simple/macros.html:37
+#: searx/templates/simple/result_templates/images.html:18
+#: searx/templates/simple/result_templates/paper.html:6
+msgid "Author"
+msgstr ""
+
+#: searx/templates/simple/macros.html:45
+msgid "cached"
+msgstr ""
+
+#: searx/templates/simple/macros.html:45
+msgid "proxied"
+msgstr ""
+
+#: searx/templates/simple/new_issue.html:64
+msgid "Start submiting a new issue on GitHub"
+msgstr ""
+
+#: searx/templates/simple/new_issue.html:66
+msgid "Please check for existing bugs about this engine on GitHub"
+msgstr ""
+
+#: searx/templates/simple/new_issue.html:69
+msgid "I confirm there is no existing bug about the issue I encounter"
+msgstr ""
+
+#: searx/templates/simple/new_issue.html:71
+msgid "If this is a public instance, please specify the URL in the bug report"
+msgstr ""
+
+#: searx/templates/simple/new_issue.html:72
+msgid "Submit a new issue on Github including the above information"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:29
+msgid "No HTTPS"
+msgstr ""
+
+#: searx/templates/simple/messages/no_results.html:10
+#: searx/templates/simple/preferences.html:31
+#: searx/templates/simple/preferences.html:32
+#: searx/templates/simple/results.html:49
+msgid "View error logs and submit a bug report"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:53
+#: searx/templates/simple/stats.html:64
+msgid "Median"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:54
+#: searx/templates/simple/stats.html:70
+msgid "P80"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:55
+#: searx/templates/simple/stats.html:76
+msgid "P95"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:83
+msgid "Failed checker test(s): "
+msgstr ""
+
+#: searx/templates/simple/preferences.html:85
+msgid "Errors:"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:105
+msgid "General"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:108
+msgid "Default categories"
+msgstr ""
+
+#: searx/templates/simple/filters/languages.html:1
+#: searx/templates/simple/preferences.html:115
+msgid "Search language"
+msgstr ""
+
+#: searx/templates/simple/filters/languages.html:2
+#: searx/templates/simple/preferences.html:118
+msgid "Default language"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:124
+msgid "What language do you prefer for search?"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:129
+msgid "Autocomplete"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:138
+msgid "Find stuff as you type"
+msgstr ""
+
+#: searx/templates/simple/filters/safesearch.html:1
+#: searx/templates/simple/filters/safesearch.html:2
+#: searx/templates/simple/filters/safesearch.html:3
+#: searx/templates/simple/filters/safesearch.html:4
+#: searx/templates/simple/preferences.html:143
+#: searx/templates/simple/preferences.html:311
+msgid "SafeSearch"
+msgstr ""
+
+#: searx/templates/simple/filters/safesearch.html:2
+#: searx/templates/simple/preferences.html:146
+msgid "Strict"
+msgstr ""
+
+#: searx/templates/simple/filters/safesearch.html:3
+#: searx/templates/simple/preferences.html:147
+msgid "Moderate"
+msgstr ""
+
+#: searx/templates/simple/filters/safesearch.html:4
+#: searx/templates/simple/preferences.html:148
+msgid "None"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:151
+msgid "Filter content"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:157
+msgid "Open Access DOI resolver"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:167
+msgid ""
+"Redirect to open-access versions of publications when available (plugin "
+"required)"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:171
+msgid "Engine tokens"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:175
+msgid "Access tokens for private engines"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:179
+msgid "User interface"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:182
+msgid "Interface language"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:190
+msgid "Change the language of the layout"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:195
+msgid "Theme"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:203
+msgid "Change SearXNG layout"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:206
+msgid "Theme style"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:214
+msgid "Choose auto to follow your browser settings"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:217
+msgid "Center Alignment"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:220
+#: searx/templates/simple/preferences.html:232
+#: searx/templates/simple/preferences.html:244
+msgid "On"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:221
+#: searx/templates/simple/preferences.html:233
+#: searx/templates/simple/preferences.html:245
+msgid "Off"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:224
+msgid "Displays results in the center of the page (Oscar layout)."
+msgstr ""
+
+#: searx/templates/simple/preferences.html:229
+msgid "Results on new tabs"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:236
+msgid "Open result links on new browser tabs"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:241
+msgid "Infinite scroll"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:248
+msgid "Automatically load next page when scrolling to bottom of current page"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:254
+msgid "Privacy"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:257
+msgid "HTTP Method"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:264
+msgid ""
+"Change how forms are submitted, <a "
+"href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\""
+" rel=\"external\">learn more about request methods</a>"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:269
+msgid "Image proxy"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:272
+#: searx/templates/simple/preferences.html:284
+msgid "Enabled"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:273
+#: searx/templates/simple/preferences.html:285
+msgid "Disabled"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:276
+msgid "Proxying image results through SearXNG"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:281
+msgid "Query in the page's title"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:288
+msgid ""
+"When enabled, the result page's title contains your query. Your browser "
+"can record this title"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:294
+msgid "Engines"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:295
+msgid "Currently used search engines"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:302
+msgid ""
+"This tab does not show up for search results, but you can search the "
+"engines listed here via bangs."
+msgstr ""
+
+#: searx/templates/simple/preferences.html:307
+#: searx/templates/simple/preferences.html:358
+msgid "Allow"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:308
+#: searx/templates/simple/stats.html:25
+msgid "Engine name"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:309
+msgid "Shortcut"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:310
+msgid "Supports selected language"
+msgstr ""
+
+#: searx/templates/simple/filters/time_range.html:1
+#: searx/templates/simple/preferences.html:312
+msgid "Time range"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:313
+#: searx/templates/simple/stats.html:28
+msgid "Response time"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:314
+msgid "Max time"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:315
+#: searx/templates/simple/stats.html:29
+msgid "Reliability"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:353
+msgid "Special Queries"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:359
+msgid "Keywords"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:360
+msgid "Name"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:361
+msgid "Description"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:362
+msgid "Examples"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:365
+msgid "This is the list of SearXNG's instant answering modules."
+msgstr ""
+
+#: searx/templates/simple/preferences.html:376
+msgid "This is the list of plugins."
+msgstr ""
+
+#: searx/templates/simple/preferences.html:393
+msgid "Cookies"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:395
+msgid ""
+"This is the list of cookies and their values SearXNG is storing on your "
+"computer."
+msgstr ""
+
+#: searx/templates/simple/preferences.html:396
+msgid "With that list, you can assess SearXNG transparency."
+msgstr ""
+
+#: searx/templates/simple/preferences.html:401
+msgid "Cookie name"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:402
+msgid "Value"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:414
+msgid "Search URL of the currently saved preferences"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:418
+msgid ""
+"Note: specifying custom settings in the search URL can reduce privacy by "
+"leaking data to the clicked result sites."
+msgstr ""
+
+#: searx/templates/simple/preferences.html:419
+msgid "URL to restore your preferences in another browser"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:423
+msgid ""
+"Specifying custom settings in the preferences URL can be used to sync "
+"preferences across devices."
+msgstr ""
+
+#: searx/templates/simple/preferences.html:428
+msgid ""
+"These settings are stored in your cookies, this allows us not to store "
+"this data about you."
+msgstr ""
+
+#: searx/templates/simple/preferences.html:430
+msgid ""
+"These cookies serve your sole convenience, we don't use these cookies to "
+"track you."
+msgstr ""
+
+#: searx/templates/simple/preferences.html:433
+msgid "Save"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:434
+msgid "Reset defaults"
+msgstr ""
+
+#: searx/templates/simple/preferences.html:435
+msgid "Back"
+msgstr ""
+
+#: searx/templates/simple/results.html:23
+msgid "Answers"
+msgstr ""
+
+#: searx/templates/simple/results.html:39
+msgid "Number of results"
+msgstr ""
+
+#: searx/templates/simple/messages/no_results.html:6
+#: searx/templates/simple/results.html:46
+msgid "Error!"
+msgstr ""
+
+#: searx/templates/simple/results.html:46
+msgid "Engines cannot retrieve results"
+msgstr ""
+
+#: searx/templates/simple/results.html:68
+msgid "Suggestions"
+msgstr ""
+
+#: searx/templates/simple/results.html:90
+msgid "Search URL"
+msgstr ""
+
+#: searx/templates/simple/results.html:96
+msgid "Download results"
+msgstr ""
+
+#: searx/templates/simple/results.html:120
+msgid "Try searching for:"
+msgstr ""
+
+#: searx/templates/simple/results.html:152
+msgid "Back to top"
+msgstr ""
+
+#: searx/templates/simple/results.html:170
+msgid "Previous page"
+msgstr ""
+
+#: searx/templates/simple/results.html:187
+msgid "Next page"
+msgstr ""
+
+#: searx/templates/simple/search.html:3
+msgid "Display the front page"
+msgstr ""
+
+#: searx/templates/simple/search.html:9
+#: searx/templates/simple/simple_search.html:5
+msgid "Search for..."
+msgstr ""
+
+#: searx/templates/simple/search.html:10
+#: searx/templates/simple/simple_search.html:6
+msgid "clear"
+msgstr ""
+
+#: searx/templates/simple/search.html:11
+#: searx/templates/simple/simple_search.html:7
+msgid "search"
+msgstr ""
+
+#: searx/templates/simple/stats.html:21
+msgid "There is currently no data available. "
+msgstr ""
+
+#: searx/templates/simple/stats.html:26
+msgid "Scores"
+msgstr ""
+
+#: searx/templates/simple/stats.html:27
+msgid "Result count"
+msgstr ""
+
+#: searx/templates/simple/stats.html:59
+msgid "Total"
+msgstr ""
+
+#: searx/templates/simple/stats.html:60
+msgid "HTTP"
+msgstr ""
+
+#: searx/templates/simple/stats.html:61
+msgid "Processing"
+msgstr ""
+
+#: searx/templates/simple/stats.html:99
+msgid "Warnings"
+msgstr ""
+
+#: searx/templates/simple/stats.html:99
+msgid "Errors and exceptions"
+msgstr ""
+
+#: searx/templates/simple/stats.html:105
+msgid "Exception"
+msgstr ""
+
+#: searx/templates/simple/stats.html:107
+msgid "Message"
+msgstr ""
+
+#: searx/templates/simple/stats.html:109
+msgid "Percentage"
+msgstr ""
+
+#: searx/templates/simple/stats.html:111
+msgid "Parameter"
+msgstr ""
+
+#: searx/templates/simple/stats.html:119
+msgid "Filename"
+msgstr ""
+
+#: searx/templates/simple/stats.html:120
+msgid "Function"
+msgstr ""
+
+#: searx/templates/simple/stats.html:121
+msgid "Code"
+msgstr ""
+
+#: searx/templates/simple/stats.html:128
+msgid "Checker"
+msgstr ""
+
+#: searx/templates/simple/stats.html:131
+msgid "Failed test"
+msgstr ""
+
+#: searx/templates/simple/stats.html:132
+msgid "Comment(s)"
+msgstr ""
+
+#: searx/templates/simple/filters/time_range.html:3
+msgid "Anytime"
+msgstr ""
+
+#: searx/templates/simple/filters/time_range.html:6
+msgid "Last day"
+msgstr ""
+
+#: searx/templates/simple/filters/time_range.html:9
+msgid "Last week"
+msgstr ""
+
+#: searx/templates/simple/filters/time_range.html:12
+msgid "Last month"
+msgstr ""
+
+#: searx/templates/simple/filters/time_range.html:15
+msgid "Last year"
+msgstr ""
+
+#: searx/templates/simple/messages/no_cookies.html:3
+msgid "Information!"
+msgstr ""
+
+#: searx/templates/simple/messages/no_cookies.html:4
+msgid "currently, there are no cookies defined."
+msgstr ""
+
+#: searx/templates/simple/messages/no_results.html:6
+msgid "Engines cannot retrieve results."
+msgstr ""
+
+#: searx/templates/simple/messages/no_results.html:15
+msgid "Please, try again later or find another SearXNG instance."
+msgstr ""
+
+#: searx/templates/simple/messages/no_results.html:20
+msgid "Sorry!"
+msgstr ""
+
+#: searx/templates/simple/messages/no_results.html:21
+msgid ""
+"we didn't find any results. Please use another query or search in more "
+"categories."
+msgstr ""
+
+#: searx/templates/simple/result_templates/default.html:6
+msgid "show media"
+msgstr ""
+
+#: searx/templates/simple/result_templates/default.html:6
+msgid "hide media"
+msgstr ""
+
+#: searx/templates/simple/result_templates/default.html:14
+#: searx/templates/simple/result_templates/videos.html:14
+msgid "This site did not provide any description."
+msgstr ""
+
+#: searx/templates/simple/result_templates/images.html:19
+msgid "Format"
+msgstr ""
+
+#: searx/templates/simple/result_templates/images.html:21
+msgid "Engine"
+msgstr ""
+
+#: searx/templates/simple/result_templates/images.html:22
+msgid "View source"
+msgstr ""
+
+#: searx/templates/simple/result_templates/map.html:12
+msgid "address"
+msgstr ""
+
+#: searx/templates/simple/result_templates/map.html:43
+msgid "show map"
+msgstr ""
+
+#: searx/templates/simple/result_templates/map.html:43
+msgid "hide map"
+msgstr ""
+
+#: searx/templates/simple/result_templates/paper.html:5
+msgid "Published date"
+msgstr ""
+
+#: searx/templates/simple/result_templates/paper.html:9
+msgid "Journal"
+msgstr ""
+
+#: searx/templates/simple/result_templates/paper.html:22
+msgid "Editor"
+msgstr ""
+
+#: searx/templates/simple/result_templates/paper.html:23
+msgid "Publisher"
+msgstr ""
+
+#: searx/templates/simple/result_templates/paper.html:24
+msgid "Type"
+msgstr ""
+
+#: searx/templates/simple/result_templates/paper.html:25
+msgid "Tags"
+msgstr ""
+
+#: searx/templates/simple/result_templates/paper.html:26
+msgid "DOI"
+msgstr ""
+
+#: searx/templates/simple/result_templates/paper.html:27
+msgid "ISSN"
+msgstr ""
+
+#: searx/templates/simple/result_templates/paper.html:28
+msgid "ISBN"
+msgstr ""
+
+#: searx/templates/simple/result_templates/paper.html:33
+msgid "PDF"
+msgstr ""
+
+#: searx/templates/simple/result_templates/paper.html:34
+msgid "HTML"
+msgstr ""
+
+#: searx/templates/simple/result_templates/torrent.html:6
+msgid "magnet link"
+msgstr ""
+
+#: searx/templates/simple/result_templates/torrent.html:7
+msgid "torrent file"
+msgstr ""
+
+#: searx/templates/simple/result_templates/torrent.html:9
+msgid "Seeder"
+msgstr ""
+
+#: searx/templates/simple/result_templates/torrent.html:9
+msgid "Leecher"
+msgstr ""
+
+#: searx/templates/simple/result_templates/torrent.html:11
+msgid "Filesize"
+msgstr ""
+
+#: searx/templates/simple/result_templates/torrent.html:12
+msgid "Bytes"
+msgstr ""
+
+#: searx/templates/simple/result_templates/torrent.html:13
+msgid "kiB"
+msgstr ""
+
+#: searx/templates/simple/result_templates/torrent.html:14
+msgid "MiB"
+msgstr ""
+
+#: searx/templates/simple/result_templates/torrent.html:15
+msgid "GiB"
+msgstr ""
+
+#: searx/templates/simple/result_templates/torrent.html:16
+msgid "TiB"
+msgstr ""
+
+#: searx/templates/simple/result_templates/torrent.html:20
+msgid "Number of Files"
+msgstr ""
+
+#: searx/templates/simple/result_templates/videos.html:6
+msgid "show video"
+msgstr ""
+
+#: searx/templates/simple/result_templates/videos.html:6
+msgid "hide video"
+msgstr ""
diff --git a/searx/translations/hr/LC_MESSAGES/messages.mo b/searx/translations/hr/LC_MESSAGES/messages.mo
index a1e226ecd..2deeb0b0d 100644
--- a/searx/translations/hr/LC_MESSAGES/messages.mo
+++ b/searx/translations/hr/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/searx/translations/hr/LC_MESSAGES/messages.po b/searx/translations/hr/LC_MESSAGES/messages.po
index 3488e138e..09b37330c 100644
--- a/searx/translations/hr/LC_MESSAGES/messages.po
+++ b/searx/translations/hr/LC_MESSAGES/messages.po
@@ -9,13 +9,14 @@
# Markus Heiser <markus.heiser@darmarit.de>, 2022.
# SecularSteve <fairfull.playing@gmail.com>, 2022.
# prljav <marin.ruskica@gmail.com>, 2022.
+# ptomljanovic <phill2605@gmail.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-10-14 14:11+0000\n"
-"PO-Revision-Date: 2022-10-20 07:00+0000\n"
-"Last-Translator: prljav <marin.ruskica@gmail.com>\n"
+"PO-Revision-Date: 2022-11-04 07:18+0000\n"
+"Last-Translator: ptomljanovic <phill2605@gmail.com>\n"
"Language-Team: Croatian <https://weblate.bubu1.eu/projects/searxng/searxng/"
"hr/>\n"
"Language: hr\n"
@@ -30,12 +31,12 @@ msgstr ""
#. CONSTANT_NAMES['DEFAULT_GROUP_NAME']
#: searx/searxng.msg
msgid "others"
-msgstr "aviti"
+msgstr "drugi"
#. CONSTANT_NAMES['OTHER_CATEGORY']
#: searx/searxng.msg
msgid "other"
-msgstr "avite"
+msgstr "drugo"
#. CATEGORY_NAMES['FILES']
#: searx/searxng.msg
@@ -55,7 +56,7 @@ msgstr "glazba"
#. CATEGORY_NAMES['SOCIAL_MEDIA']
#: searx/searxng.msg
msgid "social media"
-msgstr "društveni mediji"
+msgstr "društvene mreže"
#. CATEGORY_NAMES['IMAGES']
#: searx/searxng.msg
@@ -70,7 +71,7 @@ msgstr "video zapisi"
#. CATEGORY_NAMES['IT']
#: searx/searxng.msg
msgid "it"
-msgstr "it"
+msgstr "IT"
#. CATEGORY_NAMES['NEWS']
#: searx/searxng.msg
@@ -95,17 +96,17 @@ msgstr "znanost"
#. CATEGORY_GROUPS['APPS']
#: searx/searxng.msg
msgid "apps"
-msgstr "ôcenti"
+msgstr "aplikacije"
#. CATEGORY_GROUPS['DICTIONARIES']
#: searx/searxng.msg
msgid "dictionaries"
-msgstr "drzûlknvuti"
+msgstr "rječnici"
#. CATEGORY_GROUPS['LYRICS']
#: searx/searxng.msg
msgid "lyrics"
-msgstr "lirike"
+msgstr "tekst"
#. CATEGORY_GROUPS['PACKAGES']
#: searx/searxng.msg
@@ -120,7 +121,7 @@ msgstr "pitanja i odgovori"
#. CATEGORY_GROUPS['REPOS']
#: searx/searxng.msg
msgid "repos"
-msgstr "spremišta"
+msgstr "repozitoriji"
#. CATEGORY_GROUPS['SOFTWARE_WIKIS']
#: searx/searxng.msg
@@ -135,7 +136,7 @@ msgstr "mreža"
#. CATEGORY_GROUPS['SCIENTIFIC PUBLICATIONS']
#: searx/searxng.msg
msgid "scientific publications"
-msgstr ""
+msgstr "znanstvene publikacije"
#. STYLE_NAMES['AUTO']
#: searx/searxng.msg
@@ -158,11 +159,11 @@ msgstr "pauza"
#: searx/webapp.py:165
msgid "parsing error"
-msgstr "parsing greška"
+msgstr "pogreška pri raščlanjivanju"
#: searx/webapp.py:166
msgid "HTTP protocol error"
-msgstr "HTTP protokol greška"
+msgstr "greška HTTP protokola"
#: searx/webapp.py:167
msgid "network error"
@@ -170,11 +171,11 @@ msgstr "greška u mreži"
#: searx/webapp.py:168
msgid "SSL error: certificate validation has failed"
-msgstr ""
+msgstr "SSL pogreška: provjera valjanosti certifikata nije uspjela"
#: searx/webapp.py:170
msgid "unexpected crash"
-msgstr "neočekivan izlaz"
+msgstr "neočekivano rušenje"
#: searx/webapp.py:177
msgid "HTTP error"
@@ -182,11 +183,11 @@ msgstr "HTTP greška"
#: searx/webapp.py:178
msgid "HTTP connection error"
-msgstr "HTTP veza greška"
+msgstr "greška HTTP veze"
#: searx/webapp.py:184
msgid "proxy error"
-msgstr "greška zastupnika"
+msgstr "proxy greška"
#: searx/webapp.py:185
msgid "CAPTCHA"
@@ -219,7 +220,7 @@ msgstr "Greška u učitavnju sljedeće stranice"
#: searx/webapp.py:521 searx/webapp.py:953
msgid "Invalid settings, please edit your preferences"
-msgstr "Nevažeće postavke, uredite svoje postavke"
+msgstr "Nevažeće postavke, molimo uredite svoje postavke"
#: searx/webapp.py:537
msgid "Invalid settings"
@@ -278,6 +279,8 @@ msgid ""
"{numCitations} citations from the year {firstCitationVelocityYear} to "
"{lastCitationVelocityYear}"
msgstr ""
+"{numCitations} citati iz godine {firstCitationVelocityYear} do "
+"{lastCitationVelocityYear}"
#: searx/engines/tineye.py:40
msgid ""
@@ -357,7 +360,7 @@ msgstr ""
#: searx/plugins/self_info.py:20
msgid "Self Information"
-msgstr ""
+msgstr "Informacije o sebi"
#: searx/plugins/self_info.py:21
msgid ""
@@ -449,7 +452,7 @@ msgstr "Pokreće"
#: searx/templates/simple/base.html:64
msgid "a privacy-respecting, open metasearch engine"
-msgstr ""
+msgstr "otvoreni metapretraživač koji poštuje privatnost"
#: searx/templates/simple/base.html:65
msgid "Source code"
@@ -710,6 +713,9 @@ msgid ""
"href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\""
" rel=\"external\">learn more about request methods</a>"
msgstr ""
+"Promijenite način slanja obrazaca, <a href=\"http://en.wikipedia.org/wiki/"
+"Hypertext_Transfer_Protocol#Request_methods\" rel=\"external\">saznajte više "
+"o metodama zahtjeva</a>"
#: searx/templates/simple/preferences.html:269
msgid "Image proxy"
@@ -1124,47 +1130,47 @@ msgstr "sakrij kartu"
#: searx/templates/simple/result_templates/paper.html:5
msgid "Published date"
-msgstr ""
+msgstr "Datum objave"
#: searx/templates/simple/result_templates/paper.html:9
msgid "Journal"
-msgstr ""
+msgstr "Časopis"
#: searx/templates/simple/result_templates/paper.html:22
msgid "Editor"
-msgstr ""
+msgstr "Urednik"
#: searx/templates/simple/result_templates/paper.html:23
msgid "Publisher"
-msgstr ""
+msgstr "Izdavač"
#: searx/templates/simple/result_templates/paper.html:24
msgid "Type"
-msgstr ""
+msgstr "Tip"
#: searx/templates/simple/result_templates/paper.html:25
msgid "Tags"
-msgstr ""
+msgstr "Oznake"
#: searx/templates/simple/result_templates/paper.html:26
msgid "DOI"
-msgstr ""
+msgstr "DOI"
#: searx/templates/simple/result_templates/paper.html:27
msgid "ISSN"
-msgstr ""
+msgstr "ISSN"
#: searx/templates/simple/result_templates/paper.html:28
msgid "ISBN"
-msgstr ""
+msgstr "ISBN"
#: searx/templates/simple/result_templates/paper.html:33
msgid "PDF"
-msgstr ""
+msgstr "PDF"
#: searx/templates/simple/result_templates/paper.html:34
msgid "HTML"
-msgstr ""
+msgstr "HTML"
#: searx/templates/simple/result_templates/torrent.html:6
msgid "magnet link"
diff --git a/searx/translations/lv/LC_MESSAGES/messages.mo b/searx/translations/lv/LC_MESSAGES/messages.mo
index dfcb41f8e..b66759c35 100644
--- a/searx/translations/lv/LC_MESSAGES/messages.mo
+++ b/searx/translations/lv/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/searx/translations/lv/LC_MESSAGES/messages.po b/searx/translations/lv/LC_MESSAGES/messages.po
index db584eada..0f6f06793 100644
--- a/searx/translations/lv/LC_MESSAGES/messages.po
+++ b/searx/translations/lv/LC_MESSAGES/messages.po
@@ -3,21 +3,23 @@
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
# visiks-vs <vls@visiks.lv>, 2022.
+# Markus Heiser <markus.heiser@darmarit.de>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-10-14 14:11+0000\n"
-"PO-Revision-Date: 2022-07-08 07:17+0000\n"
-"Last-Translator: visiks-vs <vls@visiks.lv>\n"
+"PO-Revision-Date: 2022-11-04 07:18+0000\n"
+"Last-Translator: Markus Heiser <markus.heiser@darmarit.de>\n"
+"Language-Team: Latvian <https://weblate.bubu1.eu/projects/searxng/searxng/lv/"
+">\n"
"Language: lv\n"
-"Language-Team: Latvian "
-"<https://weblate.bubu1.eu/projects/searxng/searxng/lv/>\n"
-"Plural-Forms: nplurals=3; plural=(n % 10 == 0 || n % 100 >= 11 && n % 100"
-" <= 19) ? 0 : ((n % 10 == 1 && n % 100 != 11) ? 1 : 2);\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n % 10 == 0 || n % 100 >= 11 && n % 100 <= "
+"19) ? 0 : ((n % 10 == 1 && n % 100 != 11) ? 1 : 2);\n"
+"X-Generator: Weblate 4.14.1\n"
"Generated-By: Babel 2.10.3\n"
#. CONSTANT_NAMES['DEFAULT_GROUP_NAME']
@@ -128,7 +130,7 @@ msgstr "tīmeklis"
#. CATEGORY_GROUPS['SCIENTIFIC PUBLICATIONS']
#: searx/searxng.msg
msgid "scientific publications"
-msgstr ""
+msgstr "zinātnisku publikāciji"
#. STYLE_NAMES['AUTO']
#: searx/searxng.msg
@@ -271,6 +273,8 @@ msgid ""
"{numCitations} citations from the year {firstCitationVelocityYear} to "
"{lastCitationVelocityYear}"
msgstr ""
+"{numCitations} citāti no {firstCitationVelocityYear} līdz "
+"{lastCitationVelocityYear} gada"
#: searx/engines/tineye.py:40
msgid ""
@@ -291,19 +295,19 @@ msgstr ""
#: searx/engines/wttr.py:101
msgid "Morning"
-msgstr ""
+msgstr "Rīts"
#: searx/engines/wttr.py:101
msgid "Noon"
-msgstr ""
+msgstr "Pusdiena"
#: searx/engines/wttr.py:101
msgid "Evening"
-msgstr ""
+msgstr "Vakara"
#: searx/engines/wttr.py:101
msgid "Night"
-msgstr ""
+msgstr "Nakts"
#: searx/plugins/hash_plugin.py:24
msgid "Converts strings to different hash digests."
@@ -371,11 +375,11 @@ msgstr ""
#: searx/plugins/tor_check.py:78
msgid "You are using TOR. Your IP address seems to be: {ip_address}."
-msgstr ""
+msgstr "Jūs izlieto TOR. Jūsu IP adrese šķist būtu: {ip_address}."
#: searx/plugins/tor_check.py:84
msgid "You are not using TOR. Your IP address seems to be: {ip_address}."
-msgstr ""
+msgstr "Jūs neizlieto TOR. Jūsu IP adrese šķist būtu: {ip_address}."
#: searx/plugins/tracker_url_remover.py:29
msgid "Tracker URL remover"
@@ -410,7 +414,7 @@ msgstr ""
#: searx/templates/simple/base.html:46
msgid "About"
-msgstr ""
+msgstr "Par"
#: searx/templates/simple/base.html:50
msgid "Donate"
@@ -419,7 +423,7 @@ msgstr ""
#: searx/templates/simple/base.html:54
#: searx/templates/simple/preferences.html:99
msgid "Preferences"
-msgstr ""
+msgstr "Opcijas"
#: searx/templates/simple/base.html:64
msgid "Powered by"
@@ -1210,4 +1214,3 @@ msgstr "slēpt video"
#~ "href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\""
#~ " rel=\"external\">uzzināt vairāk par pieprasījuma"
#~ " metodēm</a>"
-
diff --git a/searx/translations/ta/LC_MESSAGES/messages.mo b/searx/translations/ta/LC_MESSAGES/messages.mo
index 242994e4a..0a882fcf9 100644
--- a/searx/translations/ta/LC_MESSAGES/messages.mo
+++ b/searx/translations/ta/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/searx/translations/ta/LC_MESSAGES/messages.po b/searx/translations/ta/LC_MESSAGES/messages.po
index 2ee82f528..b94c4df54 100644
--- a/searx/translations/ta/LC_MESSAGES/messages.po
+++ b/searx/translations/ta/LC_MESSAGES/messages.po
@@ -15,7 +15,7 @@ msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-10-14 14:11+0000\n"
-"PO-Revision-Date: 2022-10-28 07:18+0000\n"
+"PO-Revision-Date: 2022-11-04 07:18+0000\n"
"Last-Translator: Markus Heiser <markus.heiser@darmarit.de>\n"
"Language-Team: Tamil <https://weblate.bubu1.eu/projects/searxng/searxng/ta/>"
"\n"
@@ -40,7 +40,7 @@ msgstr "மற்றவை"
#. CATEGORY_NAMES['FILES']
#: searx/searxng.msg
msgid "files"
-msgstr "கோப்புகள்"
+msgstr "தரவுகள்"
#. CATEGORY_NAMES['GENERAL']
#: searx/searxng.msg
@@ -110,12 +110,12 @@ msgstr "பாடல் வரிகள்"
#. CATEGORY_GROUPS['PACKAGES']
#: searx/searxng.msg
msgid "packages"
-msgstr "Thokkupu"
+msgstr "தொகுப்புகள்"
#. CATEGORY_GROUPS['Q_A']
#: searx/searxng.msg
msgid "q&a"
-msgstr "கேள்வி பதில்"
+msgstr "வினா விடை"
#. CATEGORY_GROUPS['REPOS']
#: searx/searxng.msg
diff --git a/searx/translations/te/LC_MESSAGES/messages.mo b/searx/translations/te/LC_MESSAGES/messages.mo
index 863e42361..73b2fcee0 100644
--- a/searx/translations/te/LC_MESSAGES/messages.mo
+++ b/searx/translations/te/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/searx/translations/te/LC_MESSAGES/messages.po b/searx/translations/te/LC_MESSAGES/messages.po
index f9c889851..2bba5a7f5 100644
--- a/searx/translations/te/LC_MESSAGES/messages.po
+++ b/searx/translations/te/LC_MESSAGES/messages.po
@@ -8,18 +8,19 @@
# networkneil <shankyneil1@gmail.com>, 2022.
msgid ""
msgstr ""
-"Project-Id-Version: searx\n"
+"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-10-14 14:11+0000\n"
-"PO-Revision-Date: 2022-07-15 07:19+0000\n"
+"PO-Revision-Date: 2022-11-04 07:18+0000\n"
"Last-Translator: Markus Heiser <markus.heiser@darmarit.de>\n"
+"Language-Team: Telugu <https://weblate.bubu1.eu/projects/searxng/searxng/te/>"
+"\n"
"Language: te\n"
-"Language-Team: Telugu "
-"<https://weblate.bubu1.eu/projects/searxng/searxng/te/>\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.14.1\n"
"Generated-By: Babel 2.10.3\n"
#. CONSTANT_NAMES['DEFAULT_GROUP_NAME']
@@ -130,7 +131,7 @@ msgstr "వెబ్"
#. CATEGORY_GROUPS['SCIENTIFIC PUBLICATIONS']
#: searx/searxng.msg
msgid "scientific publications"
-msgstr ""
+msgstr "శాస్త్రీయ ప్రచురణలు"
#. STYLE_NAMES['AUTO']
#: searx/searxng.msg
@@ -1464,4 +1465,3 @@ msgstr "వీడియోను దాచిపెట్టు"
#~ "href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\""
#~ " rel=\"external\">అభ్యర్థన పద్ధతుల గురించి మరింత"
#~ " తెలుసుకోండి</a>"
-
diff --git a/searx/translations/zh_Hant_TW/LC_MESSAGES/messages.mo b/searx/translations/zh_Hant_TW/LC_MESSAGES/messages.mo
index b685f00af..7809d7be2 100644
--- a/searx/translations/zh_Hant_TW/LC_MESSAGES/messages.mo
+++ b/searx/translations/zh_Hant_TW/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/searx/translations/zh_Hant_TW/LC_MESSAGES/messages.po b/searx/translations/zh_Hant_TW/LC_MESSAGES/messages.po
index 24a8985c1..a3e13ae12 100644
--- a/searx/translations/zh_Hant_TW/LC_MESSAGES/messages.po
+++ b/searx/translations/zh_Hant_TW/LC_MESSAGES/messages.po
@@ -13,18 +13,19 @@
# tjvfxtiwdr <tjvfxtiwdr@daimashili.com>, 2022.
msgid ""
msgstr ""
-"Project-Id-Version: searx\n"
+"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-10-14 14:11+0000\n"
-"PO-Revision-Date: 2022-10-02 18:01+0000\n"
-"Last-Translator: tjvfxtiwdr <tjvfxtiwdr@daimashili.com>\n"
+"PO-Revision-Date: 2022-11-04 07:18+0000\n"
+"Last-Translator: Markus Heiser <markus.heiser@darmarit.de>\n"
+"Language-Team: Chinese (Traditional) <https://weblate.bubu1.eu/projects/"
+"searxng/searxng/zh_Hant/>\n"
"Language: zh_Hant_TW\n"
-"Language-Team: Chinese (Traditional) "
-"<https://weblate.bubu1.eu/projects/searxng/searxng/zh_Hant/>\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Weblate 4.14.1\n"
"Generated-By: Babel 2.10.3\n"
#. CONSTANT_NAMES['DEFAULT_GROUP_NAME']
@@ -170,7 +171,7 @@ msgstr "網絡錯誤"
#: searx/webapp.py:168
msgid "SSL error: certificate validation has failed"
-msgstr ""
+msgstr "SSL錯誤:証書驗證失敗"
#: searx/webapp.py:170
msgid "unexpected crash"
@@ -1439,4 +1440,3 @@ msgstr "隱藏影片"
#~ msgstr ""
#~ "變更遞交形式,<a href=\"https://zh.wikipedia.org/wiki/超文本传输协议#请求方法\""
#~ " rel=\"external\">看看更多關於請求方法的介紹</a>"
-
diff --git a/searx/webapp.py b/searx/webapp.py
index 5c3fbae8b..4f334a9d0 100755
--- a/searx/webapp.py
+++ b/searx/webapp.py
@@ -120,6 +120,7 @@ from searx.locales import (
# renaming names from searx imports ...
from searx.autocomplete import search_autocomplete, backends as autocomplete_backends
from searx.languages import language_codes as languages
+from searx.shared.redisdb import initialize as redis_initialize
from searx.search import SearchWithPlugins, initialize as search_initialize
from searx.network import stream as http_stream, set_context_network_name
from searx.search.checker import get_result as checker_get_result
@@ -1384,6 +1385,7 @@ werkzeug_reloader = flask_run_development or (searx_debug and __name__ == "__mai
if not werkzeug_reloader or (werkzeug_reloader and os.environ.get("WERKZEUG_RUN_MAIN") == "true"):
locales_initialize()
_INFO_PAGES = infopage.InfoPageSet()
+ redis_initialize()
plugin_initialize(app)
search_initialize(enable_checker=True, check_network=True, enable_metrics=settings['general']['enable_metrics'])
diff --git a/utils/searxng.sh b/utils/searxng.sh
index 58f220e1f..e7aa8ed15 100755
--- a/utils/searxng.sh
+++ b/utils/searxng.sh
@@ -295,7 +295,7 @@ In your instance, redis DB connector is configured at:
${redis_url}
"
- if searxng.instance.exec python -c "from searx.shared import redisdb; redisdb.init() or exit(42)"; then
+ if searxng.instance.exec python -c "from searx.shared import redisdb; redisdb.initialize() or exit(42)"; then
info_msg "SearXNG instance is able to connect redis DB."
return
fi
@@ -684,7 +684,7 @@ To install uWSGI use::
die 42 "SearXNG's uWSGI app not available"
fi
- if ! searxng.instance.exec python -c "from searx.shared import redisdb; redisdb.init() or exit(42)"; then
+ if ! searxng.instance.exec python -c "from searx.shared import redisdb; redisdb.initialize() or exit(42)"; then
rst_para "\
The configured redis DB is not available: If your server is public to the
internet, you should setup a bot protection to block excessively bot queries.
diff --git a/utils/searxng_check.py b/utils/searxng_check.py
index 39e774340..bd2d60288 100644
--- a/utils/searxng_check.py
+++ b/utils/searxng_check.py
@@ -29,6 +29,6 @@ if os.path.isfile(OLD_SETTING):
from searx.shared import redisdb
from searx import get_setting
-if not redisdb.init():
+if not redisdb.initialize():
warnings.warn("can't connect to redis DB at: %s" % get_setting('redis.url'), RuntimeWarning, stacklevel=2)
warnings.warn("--> no bot protection without redis DB", RuntimeWarning, stacklevel=2)