diff options
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 Binary files differindex 5fd1ad74c..ab0ddae97 100644 --- a/searx/translations/bn/LC_MESSAGES/messages.mo +++ b/searx/translations/bn/LC_MESSAGES/messages.mo 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 Binary files differindex df86fe9db..36de2e753 100644 --- a/searx/translations/ca/LC_MESSAGES/messages.mo +++ b/searx/translations/ca/LC_MESSAGES/messages.mo 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 Binary files differnew file mode 100644 index 000000000..77d20d2ec --- /dev/null +++ b/searx/translations/dv/LC_MESSAGES/messages.mo 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 Binary files differindex a1e226ecd..2deeb0b0d 100644 --- a/searx/translations/hr/LC_MESSAGES/messages.mo +++ b/searx/translations/hr/LC_MESSAGES/messages.mo 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 Binary files differindex dfcb41f8e..b66759c35 100644 --- a/searx/translations/lv/LC_MESSAGES/messages.mo +++ b/searx/translations/lv/LC_MESSAGES/messages.mo 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 Binary files differindex 242994e4a..0a882fcf9 100644 --- a/searx/translations/ta/LC_MESSAGES/messages.mo +++ b/searx/translations/ta/LC_MESSAGES/messages.mo 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 Binary files differindex 863e42361..73b2fcee0 100644 --- a/searx/translations/te/LC_MESSAGES/messages.mo +++ b/searx/translations/te/LC_MESSAGES/messages.mo 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 Binary files differindex b685f00af..7809d7be2 100644 --- a/searx/translations/zh_Hant_TW/LC_MESSAGES/messages.mo +++ b/searx/translations/zh_Hant_TW/LC_MESSAGES/messages.mo 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) |