36 Commits

Author SHA1 Message Date
searxng-bot
c129bda190 [l10n] update translations from Weblate
b498ffaf1 - 2026-07-17 - return42 <return42@noreply.codeberg.org>
341dacc88 - 2026-07-17 - impar <impar@noreply.codeberg.org>
2650a73a9 - 2026-07-17 - return42 <return42@noreply.codeberg.org>
37d2751a8 - 2026-07-17 - return42 <return42@noreply.codeberg.org>
2026-07-17 12:20:39 +00:00
Bnyro
9f9c00819e [fix] tiger: remember auth cookie for 2 months, not 1 day 2026-07-16 23:31:59 +02:00
Bnyro
b72a87676f [fix] public domain image archive: crashes upon response
The code used here has always been "bad" because `about` shouldn't be used
as data source, but the engine probably broke when type checks / dataclasses
for the about parameter in engines has been added with
<https://github.com/searxng/searxng/pull/6258>.

Error log:
```
WARNING searx.engines.public domain im: ErrorContext('searx/engines/public_domain_image_archive.py', 143, '\'url\': _clean_url(f"{about[\'website\']}/images/{result[\'objectID\']}"),', 'TypeError', None, ("'EngineAbout' object is not subscriptable",)) False
ERROR   searx.engines.public domain im: exception : 'EngineAbout' object is not subscriptable
Traceback (most recent call last):
  File "/home/bnyro/Projects/searxng/searx/search/processors/online.py", line 253, in search
    search_results = self._search_basic(query, params)
  File "/home/bnyro/Projects/searxng/searx/search/processors/online.py", line 239, in _search_basic
    return self.engine.response(response)
           ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
  File "/home/bnyro/Projects/searxng/searx/engines/public_domain_image_archive.py", line 143, in response
    'url': _clean_url(f"{about['website']}/images/{result['objectID']}"),
                         ~~~~~^^^^^^^^^^^
TypeError: 'EngineAbout' object is not subscriptable
```
2026-07-16 15:50:58 +02:00
Bnyro
f2432e33d6 [fix] engine cache: return default value when cache entry expired
It's possible that it's expired but has not yet been automatically deleted
by the periodic maintenance because that, by default, runs only every 2 hours.

Related:
- see https://github.com/searxng/searxng/pull/6409#discussion_r3584712601
2026-07-16 12:37:26 +02:00
vojkovic
7b2199ecdf [fix] autocomplete suggestrelevance scores for chromium 2026-07-15 23:45:25 +08:00
Bnyro
4a9c19d7bf [mod] images.html: display all engines that found the result, not only the first one 2026-07-15 17:44:11 +02:00
Bnyro
5cb4cb2bc5 [fix] qwant: engine blocked with captcha
Qwant now requires a `datadome` cookie that it returns
in the first search response as a `Set-Cookie`.

This cookie has to be sent for all requests, otherwise they
will be blocked.

This means that now, the first search request is blocked (results in CAPTCHA),
and only the subsequent searches work (same happens on the Qwant website for me).

However, I don't think it's worth repeating the same
search request multiple times very quickly because
that also makes us more suspicious.
2026-07-15 17:39:10 +02:00
Bnyro
5a448596ab [feat] engines: add avalw.org (general)
The index is very small, so it often doesn't find anything.

It also has news support, but the results are unusable.
2026-07-15 17:38:46 +02:00
Bnyro
9c49b7e0d7 [fix] results: display internationalized domain names human-friendly
Some search engines encode domains that contain special characters
in the IDN format, i.e. by using Punycode (https://en.wikipedia.org/wiki/Punycode).

This means that domains formatted like that are not human readable
and thus very unintuive.

Also, as only some engines use Punycode, this often causes a result
to appear multiple times, once with a Punycode domain (e.g. xn--allestrungen-9ib.de),
and once with a normal domain (e.g. allestörungen.de).

Always formatting the domains nicely has the caveat that the official sites
are harder to distinguish from malicious clones that just swapped out some
characters by using Punycode, e.g. replaced `a` with `á`. I don't think
that will be much of an issue though - I don't think Punycode results
previously stopped users from clicking the link, and I also think that
most search engines filter out such bad results or don't even have them
indexed.
2026-07-15 17:38:04 +02:00
Bnyro
58e02a01ae [fix] tusksearch: fix engine blocked by bot protection
Changes:
- the `embed.js` request now requires a user agent header
- we include a user agent in the "actual" request (I dropped it by accident)
- we only send the first 4 decimal places of the location
  instead of 7+ (not required, but harder to detect)
2026-07-14 20:32:31 +02:00
Bnyro
7fa9f16225 [fix] heexy: blocked by cloudflare 2026-07-14 20:32:18 +02:00
Onev
9e25585aec [refactor] engines: use datetime.fromisoformat instead of datetime.strptime where possible (#6394)
Refactor engines that parse ISO 8601 dates with strptime to use
fromisoformat instead. In most cases this is a direct replacement of
strptime(text, "format") with fromisoformat(text).

For engines where the source has a trailing "Z" that strptime consumed
as a literal (e.g. "%Y-%m-%dT%H:%M:%S.%fZ" in huggingface.py), add
rstrip("Z") to keep the output naive and preserve the existing behavior.

In sogou.py the date is extracted with a regular expression, which can
yield strings like "2026-7-11". strptime accepts this via its format
string, but fromisoformat does not. To preserve the existing behavior
and satisfy the format fromisoformat expects, add zero-padding for the
month and day.

Closes: #6098
---------
Signed-off-by: OneVth <onebrotravel@gmail.com>
2026-07-13 17:46:56 +02:00
Ivan Gabaldon
c19d86faa3 [mod] ci: remove security (#6400)
Manage alerts directly from Docker Hub
2026-07-12 13:09:19 +02:00
Ivan Gabaldon
21fa7b0be1 [mod] ci: rework workflows (#6401)
* [mod] ci: rework workflows

mod: ubuntu 26.04 runners
mod: remove podman-static
mod: longer container cache
mod: remove useless pr information
mod: sort steps
fix: use commit ref on workflow_run children
fix: missing container workflow_run check
fix: nodejs cache

* [fix] ci: apply suggestions

https://github.com/searxng/searxng/pull/6401#discussion_r3566147961
https://github.com/searxng/searxng/pull/6401#discussion_r3566147970
2026-07-12 13:04:11 +02:00
dependabot[bot]
74b4e7c8d1 [upd] web-client (simple): Bump the minor group across 1 directory with 5 updates (#6399)
Bumps the minor group with 5 updates in the /client/simple directory:

| Package | From | To |
| --- | --- | --- |
| [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.5.2` | `2.5.3` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.1.0` | `26.1.1` |
| [browserslist](https://github.com/browserslist/browserslist) | `4.28.4` | `4.28.6` |
| [svgo](https://github.com/svg/svgo) | `4.0.1` | `4.0.2` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.1.3` | `8.1.4` |

Updates `@biomejs/biome` from 2.5.2 to 2.5.3
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.5.3/packages/@biomejs/biome)

Updates `@types/node` from 26.1.0 to 26.1.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `browserslist` from 4.28.4 to 4.28.6
- [Release notes](https://github.com/browserslist/browserslist/releases)
- [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/browserslist/browserslist/compare/4.28.4...4.28.6)

Updates `svgo` from 4.0.1 to 4.0.2
- [Release notes](https://github.com/svg/svgo/releases)
- [Commits](https://github.com/svg/svgo/compare/v4.0.1...v4.0.2)

Updates `vite` from 8.1.3 to 8.1.4
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.1.4/packages/vite)

---
updated-dependencies:
- dependency-name: "@biomejs/biome"
  dependency-version: 2.5.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: minor
- dependency-name: "@types/node"
  dependency-version: 26.1.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: minor
- dependency-name: browserslist
  dependency-version: 4.28.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: minor
- dependency-name: svgo
  dependency-version: 4.0.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: minor
- dependency-name: vite
  dependency-version: 8.1.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-12 08:56:35 +02:00
dependabot[bot]
39f4dd24a5 [upd] web-client (simple): Bump typescript in /client/simple (#6391)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 6.0.3 to 7.0.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/commits)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 7.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-12 08:44:34 +02:00
dependabot[bot]
62a1ab7edd [upd] pypi: Bump granian from 2.7.8 to 2.7.9 in the minor group (#6392)
Bumps the minor group with 1 update: [granian](https://github.com/emmett-framework/granian).


Updates `granian` from 2.7.8 to 2.7.9
- [Release notes](https://github.com/emmett-framework/granian/releases)
- [Commits](https://github.com/emmett-framework/granian/compare/v2.7.8...v2.7.9)

---
updated-dependencies:
- dependency-name: granian
  dependency-version: 2.7.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-11 09:13:34 +02:00
github-actions[bot]
4abac08de5 [l10n] update translations from Weblate (#6393)
493c1d2a7 - 2026-07-07 - lukisko <lukisko@noreply.codeberg.org>
a67b467e5 - 2026-07-06 - marc-lopez <marc-lopez@noreply.codeberg.org>

Co-authored-by: searxng-bot <searxng-bot@users.noreply.github.com>
2026-07-10 23:19:38 +02:00
dependabot[bot]
6a4d5148d6 [upd] github-actions: Bump github/codeql-action/upload-sarif (#6389)
Bumps [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) from 4.36.3 to 4.37.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](54f647b7e1...99df26d4f1)

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-10 14:17:57 +02:00
dependabot[bot]
799086874d [upd] github-actions: Bump docker/login-action from 4.3.0 to 4.4.0 (#6387)
Bumps [docker/login-action](https://github.com/docker/login-action) from 4.3.0 to 4.4.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](c99871dec2...af1e73f918)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-10 14:15:21 +02:00
dependabot[bot]
83139c26b3 [upd] github-actions: Bump docker/scout-action from 1.23.0 to 1.23.1 (#6388)
Bumps [docker/scout-action](https://github.com/docker/scout-action) from 1.23.0 to 1.23.1.
- [Release notes](https://github.com/docker/scout-action/releases)
- [Commits](ce97ec1bb8...2688993af7)

---
updated-dependencies:
- dependency-name: docker/scout-action
  dependency-version: 1.23.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-10 14:14:09 +02:00
Markus Heiser
8456831a04 [mod] show img_load_error.svg if thumbnail fails to load (#6368)
* [mod] show img_load_error.svg if thumbnail fails to load (#6368)

Brave and a few other engines occasionally provide dead URLs for the thumbnails,
which looks pretty ugly in the UI.  As already with the image search, in case of
an error img_load_error.svg should be displayed here.

Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>

* [build] /static (#6368)

---------

Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
2026-07-09 18:37:41 +02:00
Bnyro
b512eaa272 [feat] engines: add kovunka.net (general) 2026-07-09 12:11:41 +02:00
Jayant Sharma
1412926f5c [fix] braveapi: strip HTML tags and filter favicon thumbnails (#6381) 2026-07-08 21:19:11 +02:00
Bnyro
3b573e0f89 [fix] heexy: use cookies for cacheft token
Heexy now passes the cacheft token via cookies and no
longer via HTTP headers.

Hence, the engine is broken without that change.
2026-07-08 21:01:11 +02:00
Bnyro
da6a230413 [fix] autocomplete: google autocompleter crashes
`engines` only contains active engines. Since `google` was set to
inactive, it's no longer part of the , making the engine crash.

With this workaround, we directly load the engine traits from the data
dictionary instead of going the intermediate step with the Google engine.
2026-07-08 20:48:15 +02:00
Bnyro
f69b22c45c [fix] kagi: crashes when there are no results 2026-07-07 10:49:54 +02:00
Patrick Evans
f930443726 [fix] kagi: safely access unpromised result properties
I was testing the new Kagi engine and found for some queries I was getting a
`KeyError` exception from the result parsing.

This PR ensures we only assumes the `url` key exists, and we use `.get()` to
retrieve values for keys that may not be present.

Their API documentation [1] clarifies that only the `url` and `title` properties
are required/guaranteed in the search result object, but this is not correct:

    File "/home/patrick/code/searxng/searx/engines/kagi.py", line 161, in response
        title=html.unescape(result["title"]),
                            ~~~~~~^^^^^^^^^
    KeyError: 'title

Heard back from Kagi support:

> The image results "title' should be marked as optional, as many images likely
> don't have titles - as you've noticed.  The only required field there should be
> the "url" field.

[1] https://kagi.redocly.app/api/docs/openapi/search/search#search/search/t=response&c=200&path=data/search
[2] https://github.com/searxng/searxng/issues/2247#issuecomment-4692976877
2026-07-07 10:49:54 +02:00
Bnyro
d58ced8f71 [fix] kagi: results contain HTML tags 2026-07-07 10:35:06 +02:00
Markus Heiser
556d08c395 [fix] google CSE - leftover from PR #6364 (#6369)
The `ZZ` issue has been fixed in the google.py and the default lang_code is
already `en`:

- https://github.com/searxng/searxng/pull/6364#discussion_r3524461287

Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
2026-07-06 09:23:28 +02:00
Bnyro
1017631800 [chore] make data.traits (#6369) 2026-07-06 09:23:28 +02:00
Bnyro
b64e6ee44a [feat] google CSE engine: add support for images (#6369)
Add support for Google CSE images, the normal google images engine doesn't work
anymore, so this is a good workaround for now.
2026-07-06 09:23:28 +02:00
Austin-Olacsi
a6438586a5 [feat] engine: add neocities.org 2026-07-05 13:15:29 +02:00
Markus Heiser
fd5eb84a37 [chore] Google (HTML) engine: remove obsolete GSA User-Agents (#6366)
The GSA headers that were introduced in PR #5644 unfortunately no longer
work (#6359).

The Google engines

- google.py
- google_videos.py

do not work anymore either, but we'll leave it in the code for now:

- In google.py, central functions like get_google_info(..) are provided, which
  are also used by other modules.
- We will probably need a Google HTML (and video) engine again very soon.

Related:

- https://github.com/searxng/searxng/issues/6359
- https://github.com/searxng/searxng/pull/6364

Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
2026-07-05 12:07:23 +02:00
vojkovic
888364c1ce [chore] update traits for google cse (#6364) 2026-07-05 11:50:23 +02:00
vojkovic
1cdf01a719 [feat] engines: add google cse engine (#6364)
Adds a new google cse engine as an alternative to the currently broken html
google engine.

It works by generating a token which is cached for 1 hour and it only uses the
public CSE id from blackle.com.  We do have two others but I think just
hardcoding one will be enough.

Will be broken in 2027 due to google deprecating it but I it will be good while
it lasts.

I found I can get up to 20 results per page. Setting safesearch and language
works and I just copied the traits from the google engine.

Also set old google engine as inactive as it is completely broken for now.
2026-07-05 11:50:23 +02:00
182 changed files with 3359 additions and 6897 deletions

View File

@@ -25,25 +25,21 @@ env:
jobs:
build:
if: github.repository_owner == 'searxng' || github.event_name == 'workflow_dispatch'
if: |
github.event_name == 'workflow_dispatch'
|| (github.repository_owner == 'searxng' && github.event.workflow_run.conclusion == 'success')
name: Build (${{ matrix.arch }})
runs-on: ${{ matrix.os }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
march: amd64
os: ubuntu-24.04
emulation: false
- arch: arm64
march: arm64
os: ubuntu-24.04-arm
emulation: false
- arch: armv7
march: arm64
os: ubuntu-24.04-arm
emulation: true
- runner: ubuntu-26.04
arch: amd64
- runner: ubuntu-26.04-arm
arch: arm64
- runner: ubuntu-26.04-arm
arch: armv7
permissions:
packages: write
@@ -53,33 +49,25 @@ jobs:
git_url: ${{ steps.build.outputs.git_url }}
steps:
# yamllint disable rule:line-length
- name: Setup podman
env:
PODMAN_VERSION: "v5.7.1"
run: |
sudo apt-get purge -y podman runc crun conmon
curl -fsSLO "https://github.com/mgoltzsche/podman-static/releases/download/${{ env.PODMAN_VERSION }}/podman-linux-${{ matrix.march }}.tar.gz"
curl -fsSLO "https://github.com/mgoltzsche/podman-static/releases/download/${{ env.PODMAN_VERSION }}/podman-linux-${{ matrix.march }}.tar.gz.asc"
gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 0CCF102C4F95D89E583FF1D4F8B5AF50344BB503
gpg --batch --verify "podman-linux-${{ matrix.march }}.tar.gz.asc" "podman-linux-${{ matrix.march }}.tar.gz"
tar -xzf "podman-linux-${{ matrix.march }}.tar.gz"
sudo cp -rfv ./podman-linux-${{ matrix.march }}/etc/. /etc/
sudo cp -rfv ./podman-linux-${{ matrix.march }}/usr/. /usr/
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
# yamllint enable rule:line-length
- name: Login to GHCR
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: "ghcr.io"
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: Setup Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Setup QEMU
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: "${{ github.event.workflow_run.head_sha || github.sha }}"
persist-credentials: "false"
fetch-depth: "0"
@@ -91,71 +79,52 @@ jobs:
python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-
path: "./local/"
- name: Get date
id: date
run: echo "date=$(date +'%Y%m%d')" >>$GITHUB_OUTPUT
- name: Setup cache container
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
key: "container-${{ matrix.arch }}-${{ steps.date.outputs.date }}-${{ hashFiles('./requirements*.txt') }}"
key: "container-${{ matrix.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: |
container-${{ matrix.arch }}-${{ steps.date.outputs.date }}-
container-${{ matrix.arch }}-
path: "/var/tmp/buildah-cache-*/*"
- if: ${{ matrix.emulation }}
name: Setup QEMU
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- name: Login to GHCR
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
with:
registry: "ghcr.io"
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: Build
id: build
env:
OVERRIDE_ARCH: "${{ matrix.arch }}"
run: make podman.build
run: make container.build
test:
name: Test (${{ matrix.arch }})
runs-on: ${{ matrix.os }}
runs-on: ${{ matrix.runner }}
needs: build
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
os: ubuntu-24.04
emulation: false
- arch: arm64
os: ubuntu-24.04-arm
emulation: false
- arch: armv7
os: ubuntu-24.04-arm
emulation: true
- runner: ubuntu-26.04
arch: amd64
- runner: ubuntu-26.04-arm
arch: arm64
- runner: ubuntu-26.04-arm
arch: armv7
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: "false"
- if: ${{ matrix.emulation }}
name: Setup QEMU
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- name: Login to GHCR
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: "ghcr.io"
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: Setup QEMU
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: "${{ github.event.workflow_run.head_sha || github.sha }}"
persist-credentials: "false"
- name: Test
env:
OVERRIDE_ARCH: "${{ matrix.arch }}"
@@ -165,7 +134,7 @@ jobs:
release:
if: github.repository_owner == 'searxng' && github.ref_name == 'master'
name: Release
runs-on: ubuntu-24.04-arm
runs-on: ubuntu-26.04-arm
needs:
- build
- test
@@ -174,24 +143,25 @@ jobs:
packages: write
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Login to Docker Hub
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
persist-credentials: "false"
registry: "docker.io"
username: "${{ secrets.DOCKER_USER }}"
password: "${{ secrets.DOCKER_TOKEN }}"
- name: Login to GHCR
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: "ghcr.io"
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: Login to Docker Hub
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
registry: "docker.io"
username: "${{ secrets.DOCKER_USER }}"
password: "${{ secrets.DOCKER_TOKEN }}"
ref: "${{ github.event.workflow_run.head_sha || github.sha }}"
persist-credentials: "false"
- name: Release
env:

View File

@@ -21,7 +21,7 @@ jobs:
data:
if: github.repository_owner == 'searxng'
name: ${{ matrix.fetch }}
runs-on: ubuntu-24.04-arm
runs-on: ubuntu-26.04-arm
strategy:
fail-fast: false
matrix:
@@ -33,7 +33,6 @@ jobs:
- update_engine_traits.py
- update_wikidata_units.py
- update_engine_descriptions.py
- update_gsa_useragents.py
permissions:
contents: write
@@ -65,23 +64,17 @@ jobs:
run: V=1 ./manage pyenv.cmd python "./searxng_extra/update/${{ matrix.fetch }}"
- name: Create PR
id: cpr
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
author: "searxng-bot <searxng-bot@users.noreply.github.com>"
committer: "searxng-bot <searxng-bot@users.noreply.github.com>"
title: "[data] update searx.data - ${{ matrix.fetch }}"
commit-message: "[data] update searx.data - ${{ matrix.fetch }}"
branch: "update_data_${{ matrix.fetch }}"
title: "[mod] data: update searx.data - ${{ matrix.fetch }}"
commit-message: "[mod] data: update searx.data - ${{ matrix.fetch }}"
branch: "ci-data-${{ matrix.fetch }}"
delete-branch: "true"
draft: "false"
signoff: "false"
body: |
[data] update searx.data - ${{ matrix.fetch }}
Update searx.data - ${{ matrix.fetch }}
labels: |
data
- name: Display information
run: |
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"

View File

@@ -25,7 +25,7 @@ jobs:
release:
if: github.repository_owner == 'searxng' || github.event_name == 'workflow_dispatch'
name: Release
runs-on: ubuntu-24.04-arm
runs-on: ubuntu-26.04-arm
permissions:
# for JamesIves/github-pages-deploy-action to push
contents: write
@@ -65,7 +65,7 @@ jobs:
with:
folder: "dist/docs"
branch: "gh-pages"
commit-message: "[doc] build from commit ${{ github.sha }}"
commit-message: "[mod] docs: build from commit ${{ github.sha }}"
# Automatically remove deleted files from the deploy branch
clean: "true"
single-commit: "true"

View File

@@ -23,7 +23,7 @@ env:
jobs:
test:
name: Python ${{ matrix.python-version }}
runs-on: ubuntu-24.04
runs-on: ubuntu-26.04
strategy:
matrix:
python-version:
@@ -59,29 +59,24 @@ jobs:
theme:
name: Theme
runs-on: ubuntu-24.04-arm
runs-on: ubuntu-26.04-arm
steps:
- name: Setup Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "26"
check-latest: "true"
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: "false"
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: "./.nvmrc"
- name: Setup cache Node.js
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
key: "nodejs-${{ runner.arch }}-${{ hashFiles('./.nvmrc', './package.json') }}"
path: "./client/simple/node_modules/"
- name: Setup cache Python
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
@@ -90,6 +85,14 @@ jobs:
python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-
path: "./local/"
- name: Setup cache Node.js
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
key: "nodejs-${{ runner.arch }}-${{ hashFiles('**/package-lock.json') }}"
restore-keys: |
nodejs-${{ runner.arch }}-
path: "./client/simple/node_modules/"
- name: Setup venv
run: make V=1 install

View File

@@ -26,9 +26,9 @@ env:
jobs:
update:
if: github.repository_owner == 'searxng' && github.event.workflow_run.conclusion == 'success'
if: github.event.workflow_run.conclusion == 'success' && github.repository_owner == 'searxng'
name: Update
runs-on: ubuntu-24.04-arm
runs-on: ubuntu-26.04-arm
permissions:
# For "make V=1 weblate.push.translations"
contents: write
@@ -59,7 +59,7 @@ jobs:
- name: Setup Weblate
run: |
mkdir -p ~/.config
echo "${{ secrets.WEBLATE_CONFIG }}" > ~/.config/weblate
echo "${{ secrets.WEBLATE_CONFIG }}" >~/.config/weblate
- name: Setup Git
run: |
@@ -74,7 +74,7 @@ jobs:
github.repository_owner == 'searxng'
&& (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule')
name: Pull Request
runs-on: ubuntu-24.04-arm
runs-on: ubuntu-26.04-arm
permissions:
# For "make V=1 weblate.translations.commit"
contents: write
@@ -107,7 +107,7 @@ jobs:
- name: Setup Weblate
run: |
mkdir -p ~/.config
echo "${{ secrets.WEBLATE_CONFIG }}" > ~/.config/weblate
echo "${{ secrets.WEBLATE_CONFIG }}" >~/.config/weblate
- name: Setup Git
run: |
@@ -118,23 +118,17 @@ jobs:
run: make V=1 weblate.translations.commit
- name: Create PR
id: cpr
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
author: "searxng-bot <searxng-bot@users.noreply.github.com>"
committer: "searxng-bot <searxng-bot@users.noreply.github.com>"
title: "[l10n] update translations from Weblate"
commit-message: "[l10n] update translations from Weblate"
title: "[mod] i18n: update translations from Weblate"
commit-message: "[mod] i18n: update translations from Weblate"
branch: "translations_update"
delete-branch: "true"
draft: "false"
signoff: "false"
body: |
[l10n] update translations from Weblate
Update translations from Weblate
labels: |
area:i18n
- name: Display information
run: |
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"

View File

@@ -1,46 +0,0 @@
---
name: Security
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
schedule:
- cron: "42 05 * * *"
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
jobs:
container:
if: github.repository_owner == 'searxng'
name: Container
runs-on: ubuntu-24.04-arm
permissions:
security-events: write
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: "false"
- name: Sync GHCS from Docker Scout
uses: docker/scout-action@ce97ec1bb85613e8eb35d086fad0c77a6cedf983 # v1.23.0
with:
organization: "searxng"
dockerhub-user: "${{ secrets.DOCKER_USER }}"
dockerhub-password: "${{ secrets.DOCKER_TOKEN }}"
image: "registry://ghcr.io/searxng/searxng:latest"
command: "cves"
sarif-file: "./scout.sarif"
exit-code: "false"
write-comment: "false"
- name: Upload SARIFs
uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
with:
sarif_file: "./scout.sarif"

View File

@@ -63,7 +63,7 @@ format: format.python format.shell
# wrap ./manage script
MANAGE += weblate.translations.commit weblate.push.translations
MANAGE += data.all data.traits data.useragents data.gsa_useragents data.locales data.currencies
MANAGE += data.all data.traits data.useragents data.locales data.currencies
MANAGE += docs.html docs.live docs.gh-pages docs.prebuild docs.clean
MANAGE += podman.build
MANAGE += docker.build docker.buildx

View File

@@ -15,9 +15,9 @@
"swiped-events": "1.2.0"
},
"devDependencies": {
"@biomejs/biome": "2.5.2",
"@types/node": "^26.1.0",
"browserslist": "^4.28.4",
"@biomejs/biome": "2.5.3",
"@types/node": "^26.1.1",
"browserslist": "^4.28.6",
"browserslist-to-esbuild": "^2.1.1",
"edge.js": "^6.5.1",
"less": "^4.6.7",
@@ -27,9 +27,9 @@
"stylelint": "^17.14.0",
"stylelint-config-standard-less": "^4.1.0",
"stylelint-prettier": "^5.0.3",
"svgo": "^4.0.1",
"typescript": "~6.0.3",
"vite": "^8.1.3",
"svgo": "^4.0.2",
"typescript": "~7.0.2",
"vite": "^8.1.4",
"vite-bundle-analyzer": "^1.3.8"
}
},
@@ -69,9 +69,9 @@
}
},
"node_modules/@biomejs/biome": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.2.tgz",
"integrity": "sha512-VQ3RCqr7JmDIX+w6stWYl+g/3bYofN3q2wDBHUKKc/c7i5QWrFKFBZYCYPWTE6agsUPMIZZe6/CMmVUfUAhkKA==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.3.tgz",
"integrity": "sha512-MrJswFdei9EfDwwUy2tQrPDpK0AO+RmMFvBoaaJ6ayBc3sUbHdCE+XG5N8vp+5So41ZupZJQm0roHFFhMGVD7A==",
"dev": true,
"license": "MIT OR Apache-2.0",
"bin": {
@@ -85,20 +85,20 @@
"url": "https://opencollective.com/biome"
},
"optionalDependencies": {
"@biomejs/cli-darwin-arm64": "2.5.2",
"@biomejs/cli-darwin-x64": "2.5.2",
"@biomejs/cli-linux-arm64": "2.5.2",
"@biomejs/cli-linux-arm64-musl": "2.5.2",
"@biomejs/cli-linux-x64": "2.5.2",
"@biomejs/cli-linux-x64-musl": "2.5.2",
"@biomejs/cli-win32-arm64": "2.5.2",
"@biomejs/cli-win32-x64": "2.5.2"
"@biomejs/cli-darwin-arm64": "2.5.3",
"@biomejs/cli-darwin-x64": "2.5.3",
"@biomejs/cli-linux-arm64": "2.5.3",
"@biomejs/cli-linux-arm64-musl": "2.5.3",
"@biomejs/cli-linux-x64": "2.5.3",
"@biomejs/cli-linux-x64-musl": "2.5.3",
"@biomejs/cli-win32-arm64": "2.5.3",
"@biomejs/cli-win32-x64": "2.5.3"
}
},
"node_modules/@biomejs/cli-darwin-arm64": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.2.tgz",
"integrity": "sha512-e7P3P7EkwFc/KiX2AHw4YDLIBOMfG9CPCAwy52k5Bp0dfhkozx9hf6wCmIr2QeXy2XeccJ3V/Sg+hDmzYEqxSg==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.3.tgz",
"integrity": "sha512-QhYP9muVQ0nUO5zztFuPbEwi4+94sJWVjaZds9aMi1l/KNZBiUjdiSUrGHsTaMGDXrYl+r4AS2sUKfgH3w+V3g==",
"cpu": [
"arm64"
],
@@ -113,9 +113,9 @@
}
},
"node_modules/@biomejs/cli-darwin-x64": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.2.tgz",
"integrity": "sha512-ymzMvjC1Jg0b9K0D26ZdARqFQXs7MocfLC5FOCGfkC0Ss+ACUJkX5364ZM5nT4NLZanHRZNVrZEy+Ibwcvux/g==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.3.tgz",
"integrity": "sha512-NC1Ss13UaW7QZX+y8j44bF7AP0jSJdBl6iRhe0MAkvaSqZy+mWg3GaXsrb+eSoHoGDBtaXWEbMVV0iVN2cZ7cQ==",
"cpu": [
"x64"
],
@@ -130,9 +130,9 @@
}
},
"node_modules/@biomejs/cli-linux-arm64": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.2.tgz",
"integrity": "sha512-t7sseOmqND57uUWTwlawU6BYj+J06T/9EkydzBhkrgw/FK3QVhjU2wsJR0frljrKZ0/I8A/rYw7284QgqjQfIQ==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.3.tgz",
"integrity": "sha512-ksx1KWeyYW18ILL04msF/J4ZBtBDN33znYK8Z/aNv/vlBVxL9/g3mGP+omgHJKy4+KWbK87vcmmpmurfNjSgiA==",
"cpu": [
"arm64"
],
@@ -150,9 +150,9 @@
}
},
"node_modules/@biomejs/cli-linux-arm64-musl": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.2.tgz",
"integrity": "sha512-w+ANG0ZvTu9IeEg9QnstoOnk6L0fpwJifW6aHR18+cb5Z39bkANItYjAfMrnvce5tmMK+IQ6nPX7/kQFdam5iw==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.3.tgz",
"integrity": "sha512-fccix0w6xp6csCXgxeC0dU/3ecgRQal0y+cv2SP9ajNlhe7Yrk2Ug7UDe2j9AT9ZDYitkXpvUKgZjjuoYeP4Vg==",
"cpu": [
"arm64"
],
@@ -170,9 +170,9 @@
}
},
"node_modules/@biomejs/cli-linux-x64": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.2.tgz",
"integrity": "sha512-M/lOZrewzTCRDINbjhQ1gYYru37KlD3kJBQwwKCG0ckz5E9IZwIoJ3X0wBwRXA+yBDIwWUuPBHS67HzJY4dTfA==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.3.tgz",
"integrity": "sha512-yMkJtilsgvILDcVkh187aVLTb64xYsrxYajx5kym+r1ULkO5HUOfu9AYKLGQbOVLwJtT2utNw7hhFNg+17mUYA==",
"cpu": [
"x64"
],
@@ -190,9 +190,9 @@
}
},
"node_modules/@biomejs/cli-linux-x64-musl": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.2.tgz",
"integrity": "sha512-VArNLAzND063tF+XY0yPyM+DyahpzOMzOAvb7qs259nhjJWRjvjZdssuA+Rfl+l07+NOesKZ0Xu2yFrXyBMtzw==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.3.tgz",
"integrity": "sha512-O/yU9YKRUiHhmcjF2f38PSjseVk3G4VLWYc0G2HWpzdBVREV6G8IGWIVEFf7MFPfWIzNUIvPsEjeAZQIOgnLcQ==",
"cpu": [
"x64"
],
@@ -210,9 +210,9 @@
}
},
"node_modules/@biomejs/cli-win32-arm64": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.2.tgz",
"integrity": "sha512-kbjFFKyZlzYnAuw7sRy5qDoFG6zrP40UK08oPQsWK0ct3NMnGSt+Bs1iviEEyEIP57N5MrykGXdO/wRiaR4lww==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.3.tgz",
"integrity": "sha512-cX5z+GYwRcqEok0AH3KSfQGgqYd0Nomfp6Fbe1uiTtELE38hdH2k842wQ9wLNaF/JJ7r4rjJQ4VR+ce+fRmQbw==",
"cpu": [
"arm64"
],
@@ -227,9 +227,9 @@
}
},
"node_modules/@biomejs/cli-win32-x64": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.2.tgz",
"integrity": "sha512-4InchVpdVmdkkkgjQqKpgvyu+VPnoF/7RPSw5YATgEVpt2j72wcCAeV5TwaE9ZGJUZWZn7v2CwSAj6CrMJEx8A==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.3.tgz",
"integrity": "sha512-ExSaJWi4/u6+GXCszlSKpWSjKNbDseAYqqkCznsCsZ/4uidZ/BEqsCc5/3ctlq6dfIubdIIRSVLC/PG9xPl70Q==",
"cpu": [
"x64"
],
@@ -1648,9 +1648,9 @@
}
},
"node_modules/@types/node": {
"version": "26.1.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.0.tgz",
"integrity": "sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==",
"version": "26.1.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz",
"integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1670,6 +1670,346 @@
"integrity": "sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==",
"license": "MIT"
},
"node_modules/@typescript/typescript-aix-ppc64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz",
"integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-darwin-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz",
"integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-darwin-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz",
"integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==",
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-freebsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz",
"integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-freebsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz",
"integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==",
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-arm": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz",
"integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==",
"cpu": [
"arm"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz",
"integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-loong64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz",
"integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==",
"cpu": [
"loong64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-mips64el": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz",
"integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-ppc64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz",
"integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-riscv64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz",
"integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-s390x": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz",
"integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==",
"cpu": [
"s390x"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz",
"integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==",
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-netbsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz",
"integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-netbsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz",
"integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==",
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-openbsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz",
"integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-openbsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz",
"integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==",
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-sunos-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz",
"integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==",
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-win32-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz",
"integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-win32-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz",
"integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==",
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@zarrita/storage": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@zarrita/storage/-/storage-0.2.0.tgz",
@@ -1767,9 +2107,9 @@
}
},
"node_modules/baseline-browser-mapping": {
"version": "2.10.41",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.41.tgz",
"integrity": "sha512-WwS7MHhqGHHlaVsqRZnhvCEMS0owDX+SxRlve7JkuH7My1Ara3ZriTmCQupPfYjxMZ8I/tgxtJYr2t7taHaH4A==",
"version": "2.10.43",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.43.tgz",
"integrity": "sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -1800,9 +2140,9 @@
}
},
"node_modules/browserslist": {
"version": "4.28.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz",
"integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==",
"version": "4.28.6",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.6.tgz",
"integrity": "sha512-FQBYNK15VMslhLHpA7+n+n1GOlF1kId2xcCg7/j95f24AOF6VDYMNH4mFxF7KuaTdv627faazpOAjFzMrfJOUw==",
"dev": true,
"funding": [
{
@@ -1820,10 +2160,10 @@
],
"license": "MIT",
"dependencies": {
"baseline-browser-mapping": "^2.10.38",
"caniuse-lite": "^1.0.30001799",
"electron-to-chromium": "^1.5.376",
"node-releases": "^2.0.48",
"baseline-browser-mapping": "^2.10.42",
"caniuse-lite": "^1.0.30001803",
"electron-to-chromium": "^1.5.389",
"node-releases": "^2.0.51",
"update-browserslist-db": "^1.2.3"
},
"bin": {
@@ -1877,9 +2217,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001800",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001800.tgz",
"integrity": "sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==",
"version": "1.0.30001805",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001805.tgz",
"integrity": "sha512-52noaS3DubycKSXaU30TwPGIp+POyQSUVa5jBEq3vkRkY0kjyb3LQgvhU6WGyCcyXqVLWO0Cw0Q6BSdD0kUfVA==",
"dev": true,
"funding": [
{
@@ -2295,9 +2635,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.385",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.385.tgz",
"integrity": "sha512-78sa/M08MNAYHQfjoWMvOlKQqZ0ElhSm/L5HNUc96VZ3b+KvDVnngFm8sYQy0XrhTRgAhggHr5abA7yTvRdo4Q==",
"version": "1.5.389",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.389.tgz",
"integrity": "sha512-cEto7aeOqBfU1D+c5py5pE+ooscKE75JifxLBdFUZsqAxRS6y7kebtxAZvICszSl05gPjYHDTjY+lXpyGvpJbg==",
"dev": true,
"license": "ISC"
},
@@ -3430,9 +3770,9 @@
}
},
"node_modules/node-releases": {
"version": "2.0.50",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz",
"integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==",
"version": "2.0.51",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz",
"integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4388,9 +4728,9 @@
"dev": true
},
"node_modules/svgo": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.1.tgz",
"integrity": "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.2.tgz",
"integrity": "sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4561,17 +4901,38 @@
}
},
"node_modules/typescript": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz",
"integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
"tsc": "bin/tsc"
},
"engines": {
"node": ">=14.17"
"node": ">=16.20.0"
},
"optionalDependencies": {
"@typescript/typescript-aix-ppc64": "7.0.2",
"@typescript/typescript-darwin-arm64": "7.0.2",
"@typescript/typescript-darwin-x64": "7.0.2",
"@typescript/typescript-freebsd-arm64": "7.0.2",
"@typescript/typescript-freebsd-x64": "7.0.2",
"@typescript/typescript-linux-arm": "7.0.2",
"@typescript/typescript-linux-arm64": "7.0.2",
"@typescript/typescript-linux-loong64": "7.0.2",
"@typescript/typescript-linux-mips64el": "7.0.2",
"@typescript/typescript-linux-ppc64": "7.0.2",
"@typescript/typescript-linux-riscv64": "7.0.2",
"@typescript/typescript-linux-s390x": "7.0.2",
"@typescript/typescript-linux-x64": "7.0.2",
"@typescript/typescript-netbsd-arm64": "7.0.2",
"@typescript/typescript-netbsd-x64": "7.0.2",
"@typescript/typescript-openbsd-arm64": "7.0.2",
"@typescript/typescript-openbsd-x64": "7.0.2",
"@typescript/typescript-sunos-x64": "7.0.2",
"@typescript/typescript-win32-arm64": "7.0.2",
"@typescript/typescript-win32-x64": "7.0.2"
}
},
"node_modules/undici-types": {
@@ -4642,16 +5003,16 @@
"license": "MIT"
},
"node_modules/vite": {
"version": "8.1.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.1.3.tgz",
"integrity": "sha512-Ds+gBRbj0lwRO2Y5hwnUBdxSwlAve9LeRyU4sNnAr0ewW0gWF0n5bgXgUzbgZ49MV9BVUAQUFYVcDUcilUExMA==",
"version": "8.1.4",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.1.4.tgz",
"integrity": "sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"lightningcss": "^1.32.0",
"picomatch": "^4.0.4",
"picomatch": "^4.0.5",
"postcss": "^8.5.16",
"rolldown": "~1.1.3",
"rolldown": "~1.1.4",
"tinyglobby": "^0.2.17"
},
"bin": {
@@ -4730,9 +5091,9 @@
}
},
"node_modules/vite/node_modules/picomatch": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
"integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
"dev": true,
"license": "MIT",
"engines": {

View File

@@ -29,9 +29,9 @@
"swiped-events": "1.2.0"
},
"devDependencies": {
"@biomejs/biome": "2.5.2",
"@types/node": "^26.1.0",
"browserslist": "^4.28.4",
"@biomejs/biome": "2.5.3",
"@types/node": "^26.1.1",
"browserslist": "^4.28.6",
"browserslist-to-esbuild": "^2.1.1",
"edge.js": "^6.5.1",
"less": "^4.6.7",
@@ -41,9 +41,9 @@
"stylelint": "^17.14.0",
"stylelint-config-standard-less": "^4.1.0",
"stylelint-prettier": "^5.0.3",
"svgo": "^4.0.1",
"typescript": "~6.0.3",
"vite": "^8.1.3",
"svgo": "^4.0.2",
"typescript": "~7.0.2",
"vite": "^8.1.4",
"vite-bundle-analyzer": "^1.3.8"
}
}

View File

@@ -35,8 +35,9 @@ const imageLoader = (resultElement: HTMLElement): void => {
}, 1000) as unknown as number;
};
const imageThumbnails: NodeListOf<HTMLImageElement> =
document.querySelectorAll<HTMLImageElement>("#urls img.image_thumbnail");
const imageThumbnails: NodeListOf<HTMLImageElement> = document.querySelectorAll<HTMLImageElement>(
"#urls img.image_thumbnail, img.thumbnail"
);
for (const thumbnail of imageThumbnails) {
if (thumbnail.complete && thumbnail.naturalWidth === 0) {
thumbnail.src = `${settings.theme_static_path}/img/img_load_error.svg`;

View File

@@ -23,6 +23,6 @@ coloredlogs==15.0.1
docutils>=0.21.2;python_version <= "3.11"
docutils>=0.22.4; python_version > "3.11"
parameterized==0.9.0
granian[reload]==2.7.8
granian[reload]==2.7.9
basedpyright==1.39.9
types-lxml==2026.2.16

View File

@@ -1,2 +1,2 @@
granian==2.7.8
granian[pname]==2.7.8
granian==2.7.9
granian[pname]==2.7.9

View File

@@ -21,6 +21,8 @@ from searx.engines import (
from searx.network import get as http_get, post as http_post
from searx.exceptions import SearxEngineResponseException
from searx.utils import extr, gen_useragent
from searx.data import ENGINE_TRAITS
from searx.enginelib.traits import EngineTraits
if t.TYPE_CHECKING:
from searx.extended_types import SXNG_Response
@@ -133,7 +135,9 @@ def google_complete(query: str, sxng_locale: str) -> list[str]:
"""
google_info: dict[str, t.Any] = google.get_google_info({'searxng_locale': sxng_locale}, engines['google'].traits)
data = ENGINE_TRAITS.get("google") or {}
traits = EngineTraits(**data)
google_info: dict[str, t.Any] = google.get_google_info({'searxng_locale': sxng_locale}, traits)
url = 'https://{subdomain}/complete/search?{args}'
args = urlencode(
{

View File

@@ -458,12 +458,22 @@ class ExpireCacheSQLite(sqlitedb.SQLiteAppl, ExpireCache):
# Before values are taken from the table, a maintenance interval may
# need to be carried out.
self.maintenance()
sql = f"SELECT value FROM {table} WHERE key = ?"
sql = f"SELECT value, expire FROM {table} WHERE key = ?"
row = self.DB.execute(sql, (key,)).fetchone()
if row is None:
return default
return self.deserialize(row[0])
# Check if value is expired. It's possible that it's expired but has not
# yet been automatically deleted by the periodic maintenance
(value, expire) = row
now = time.time()
if expire < now:
# The record is deleted during the maintenance interval. Deleting
# the record at this point offers no advantage, as a SELECT
# statement must be executed for every cache.get request anyways.
return default
return self.deserialize(value)
def pairs(self, ctx: str) -> Iterator[tuple[str, typing.Any]]:
"""Iterate over key/value pairs from table given by argument ``ctx``.

View File

@@ -6,7 +6,7 @@ make data.all
"""
# pylint: disable=invalid-name
__all__ = ["ahmia_blacklist_loader", "gsa_useragents_loader", "data_dir", "get_cache"]
__all__ = ["ahmia_blacklist_loader", "data_dir", "get_cache"]
import json
import typing as t
@@ -63,7 +63,6 @@ lazy_globals = {
"ENGINE_TRAITS": None,
"LOCALES": None,
"TRACKER_PATTERNS": TrackerPatternsDB(),
"GSA_USER_AGENTS": None,
}
data_json_files = {
@@ -106,24 +105,3 @@ def ahmia_blacklist_loader() -> list[str]:
"""
with open(data_dir / 'ahmia_blacklist.txt', encoding='utf-8') as f:
return f.read().split()
def gsa_useragents_loader() -> list[str]:
"""Load data from `gsa_useragents.txt` and return a list of user agents
suitable for Google. The user agents are fetched by::
searxng_extra/update/update_gsa_useragents.py
This function is used by :py:mod:`searx.engines.google`.
"""
data = lazy_globals["GSA_USER_AGENTS"]
if data is not None:
return data
log.debug("init searx.data.%s", "GSA_USER_AGENTS")
with open(data_dir / 'gsa_useragents.txt', encoding='utf-8') as f:
lazy_globals["GSA_USER_AGENTS"] = f.read().splitlines()
return lazy_globals["GSA_USER_AGENTS"]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -83,7 +83,7 @@ def extract_video_data(video_block):
published_date = None
if create_time:
try:
published_date = datetime.strptime(create_time.strip(), "%Y-%m-%d")
published_date = datetime.fromisoformat(create_time.strip())
except (ValueError, TypeError):
pass

View File

@@ -109,7 +109,7 @@ def response(resp: "SXNG_Response") -> EngineResults:
comments_elements = eval_xpath_getindex(entry, xpath_comment, 0, default=None)
comments: str = "" if comments_elements is None else comments_elements.text
publishedDate = datetime.strptime(eval_xpath_getindex(entry, xpath_published, 0).text, "%Y-%m-%dT%H:%M:%SZ")
publishedDate = datetime.fromisoformat(eval_xpath_getindex(entry, xpath_published, 0).text.rstrip("Z"))
res.add(
res.types.Paper(

View File

@@ -186,7 +186,7 @@ def parse_images(data):
img_date = item.get("bdImgnewsDate")
publishedDate = None
if img_date:
publishedDate = datetime.strptime(img_date, "%Y-%m-%d %H:%M")
publishedDate = datetime.fromisoformat(img_date)
results.append(
{
"template": "images.html",

View File

@@ -44,7 +44,7 @@ def response(resp):
"url": 'https://www.bitchute.com/video/' + item['video_id'],
"content": html_to_text(item['description']),
"author": item['channel']['channel_name'],
"publishedDate": datetime.strptime(item["date_published"], "%Y-%m-%dT%H:%M:%S.%fZ"),
"publishedDate": datetime.fromisoformat(item["date_published"].rstrip("Z")),
"length": item['duration'],
"views": item['view_count'],
"thumbnail": item['thumbnail_url'],

View File

@@ -104,7 +104,7 @@ def response(resp: "SXNG_Response") -> EngineResults:
title=_remove_keyword_marker(result["Subject"]),
content=_remove_keyword_marker(result["Text"]),
url=result["Url"],
publishedDate=datetime.strptime(result["Published"], "%Y-%m-%d %H:%M:%S"),
publishedDate=datetime.fromisoformat(result["Published"]),
metadata=gettext.gettext("Posted by {author}").format(author=result["Author"]),
)
)

View File

@@ -31,6 +31,7 @@ from dateutil import parser
from searx.exceptions import SearxEngineAPIException
from searx.result_types import EngineResults
from searx.utils import html_to_text
if t.TYPE_CHECKING:
from searx.extended_types import SXNG_Response
@@ -75,6 +76,7 @@ def request(query: str, params: "OnlineParams") -> None:
"q": query,
"count": results_per_page,
"offset": (params["pageno"] - 1) * results_per_page,
"text_decorations": False,
}
# Apply time filter if specified
@@ -112,14 +114,19 @@ def response(resp: "SXNG_Response") -> EngineResults:
res = EngineResults()
data = resp.json()
for result in data.get("web", {}).get("results", []):
for result in (data.get("web") or {}).get("results", []):
thumbnail_obj = result.get("thumbnail")
thumbnail = ""
if thumbnail_obj and not thumbnail_obj.get("logo", False):
thumbnail = thumbnail_obj.get("src") or ""
res.add(
res.types.MainResult(
url=result["url"],
title=result["title"],
content=result.get("description", ""),
title=html_to_text(result["title"]),
content=html_to_text(result.get("description", "")),
publishedDate=_extract_published_date(result.get("age")),
thumbnail=result.get("thumbnail", {}).get("src"),
thumbnail=thumbnail,
),
)

View File

@@ -43,7 +43,7 @@ def response(resp):
publishedDate = None
if recipe['submissionDate']:
publishedDate = datetime.strptime(result['recipe']['submissionDate'][:19], "%Y-%m-%dT%H:%M:%S")
publishedDate = datetime.fromisoformat(result['recipe']['submissionDate'][:19])
content = [
f"Schwierigkeitsstufe (1-3): {recipe['difficulty']}",

View File

@@ -37,7 +37,7 @@ def response(resp):
for item in search_res:
img = 'https://s3.thehackerblog.com/findthatmeme/' + item['image_path']
thumb = 'https://s3.thehackerblog.com/findthatmeme/thumb/' + item.get('thumbnail', '')
date = datetime.strptime(item["updated_at"].split("T")[0], "%Y-%m-%d")
date = datetime.fromisoformat(item["updated_at"].split("T")[0])
formatted_date = datetime.fromtimestamp(date.timestamp())
results.append(

View File

@@ -47,7 +47,7 @@ def response(resp: "SXNG_Response"):
title=result["title"],
content=result["description"],
thumbnail=result["smallImageURL"],
publishedDate=datetime.strptime(result["status_since"], "%Y-%m-%d %H:%M:%S"),
publishedDate=datetime.fromisoformat(result["status_since"]),
metadata=f"Rank: {result['rank']} || {result['episode_count']} episodes",
)
)

View File

@@ -32,7 +32,6 @@ from searx.utils import (
eval_xpath_getindex,
eval_xpath_list,
extract_text,
gen_gsa_useragent,
)
if t.TYPE_CHECKING:
@@ -197,7 +196,7 @@ def get_google_info(params: "OnlineParams", eng_traits: EngineTraits) -> dict[st
# https://developers.google.com/custom-search/docs/xml_results_appendices#interfaceLanguages
# https://github.com/searxng/searxng/issues/2515#issuecomment-1607150817
ret_val["params"]["hl"] = f"{lang_code}-{country}"
ret_val["params"]["hl"] = f"{lang_code}"
# lr parameter:
# The lr (language restrict) parameter restricts search results to
@@ -268,7 +267,6 @@ def get_google_info(params: "OnlineParams", eng_traits: EngineTraits) -> dict[st
# HTTP headers
ret_val["headers"]["Accept"] = "*/*"
ret_val["headers"]["User-Agent"] = gen_gsa_useragent()
# Cookies

190
searx/engines/google_cse.py Normal file
View File

@@ -0,0 +1,190 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Google Custom Search Engine"""
import datetime
import typing as t
from json import loads
from urllib.parse import urlencode
from searx.enginelib import EngineCache
from searx.exceptions import SearxEngineAPIException, SearxEngineTooManyRequestsException
from searx.network import get
from searx.result_types import EngineResults, Result, MainResult, Image
from searx.engines.google import fetch_traits # pylint: disable=unused-import
from searx.engines.google import filter_mapping, get_google_info
if t.TYPE_CHECKING:
from searx.extended_types import SXNG_Response
from searx.search.processors import OnlineParams
about = {
"website": "https://www.google.com",
"wikidata_id": "Q2233943",
"official_api_documentation": "https://developers.google.com/custom-search/docs/element",
"use_official_api": False,
"require_api_key": False,
"results": "JSONP",
"description": "Platform for creating custom search engines based on Google Search.",
}
categories = ["general", "web"]
paging = True
max_page = 5
page_size = 20
time_range_support = True
language_support = True
safesearch = True
GoogleCategType = t.Literal["", "image"]
google_categ: GoogleCategType = ""
"""Google CSE category. Set to ``""`` for web search."""
CX = "partner-pub-8993703457585266:4862972284" # blackle.com
CACHE: EngineCache
def setup(engine_settings: dict[str, t.Any]) -> bool:
global CACHE # pylint: disable=global-statement
if google_categ not in t.get_args(GoogleCategType):
raise ValueError("invalid google cse category: %s" % google_categ)
CACHE = EngineCache(engine_settings["name"])
return True
def _cse_token() -> dict[str, str]:
token: dict[str, str] = CACHE.get(CX)
if token:
return token
resp = get(f"https://www.google.com/cse/cse.js?cx={CX}", timeout=10)
if not resp.ok:
raise SearxEngineAPIException("failed to obtain cse token")
end = resp.text.rfind("});")
start = resp.text.rfind("({")
opts: dict[str, str] = loads(resp.text[start + 1 : end + 1])
cse_tok = opts.get("cse_token")
if not cse_tok:
raise SearxEngineAPIException("failed to obtain cse token")
exp = opts.get("exp")
token = {
"cse_tok": cse_tok,
"cselibv": opts.get("cselibVersion", ""),
"exp": ",".join(exp) if exp else "",
}
CACHE.set(CX, token, expire=3600)
return token
def _get_start_and_end_date_str(time_range: str) -> tuple[str, str]:
time_range_map = {"day": 1, "week": 7, "month": 30, "year": 365}
end_date = datetime.datetime.now()
start_date = end_date - datetime.timedelta(days=time_range_map[time_range])
return start_date.strftime("%Y%m%d"), end_date.strftime("%Y%m%d")
def request(query: str, params: "OnlineParams") -> None:
token = _cse_token()
google_info = get_google_info(params, traits)
info: dict[str, str] = google_info["params"]
args = {
"rsz": "filtered_cse",
"num": str(page_size),
"hl": info["hl"],
"cselibv": token["cselibv"],
"cx": CX,
"q": query,
"safe": filter_mapping[params["safesearch"]],
"cse_tok": token["cse_tok"],
"callback": "_",
"rurl": "",
"searchtype": google_categ,
}
if params["time_range"]:
start_date, end_date = _get_start_and_end_date_str(params["time_range"])
args["sort"] = f"date:r:{start_date}:{end_date}"
if info.get("lr"):
args["lr"] = info["lr"]
if info.get("cr"):
args["cr"] = info["cr"]
if google_info["country"] not in (None, "ZZ"):
args["gl"] = google_info["country"]
if token["exp"]:
args["exp"] = token["exp"]
start = (params["pageno"] - 1) * page_size
if start:
args["start"] = str(start)
params["url"] = "https://cse.google.com/cse/element/v1?" + urlencode(args)
params["cookies"] = google_info["cookies"]
params["headers"].update(google_info["headers"])
params["headers"]["Referer"] = "https://cse.google.com/"
def response(resp: "SXNG_Response") -> EngineResults:
json_resp = resp.text[resp.text.find("{") : resp.text.rfind("}") + 1]
data = loads(json_resp)
# not the real types, but a sufficient approximation
item: dict[str, str]
error: dict[str, str | int]
if error := data.get("error"):
message = error.get("message", "unknown error")
if error.get("code") == 429:
raise SearxEngineTooManyRequestsException(message=f"google cse: {message}")
raise SearxEngineAPIException(f"google cse: {message}")
results = EngineResults()
for item in data.get("results", []):
res: Result | None
if google_categ == "":
res = web_item(item)
elif google_categ == "image":
res = img_item(item)
if res is not None:
results.add(res)
return results
def web_item(item: dict[str, str]) -> MainResult | None:
url = item.get("unescapedUrl")
if not url:
return None
return MainResult(
url=url,
title=item.get("titleNoFormatting", ""),
content=item.get("contentNoFormatting", ""),
thumbnail=item.get("richSnippet", {}).get("cseThumbnail", {}).get("src", ""), # type: ignore
)
def img_item(item: dict[str, str]) -> Image | None:
resolution = ""
if item.get("height") and item.get("width"):
resolution = f"{item['width']}x{item['height']}"
return Image(
url=item["originalContextUrl"],
title=item.get("titleNoFormatting", ""),
content=item.get("contentNoFormatting", ""),
img_src=item["unescapedUrl"],
thumbnail_src=item["tbUrl"],
resolution=resolution,
img_format=item["fileFormat"].split("/")[-1],
)

View File

@@ -13,13 +13,12 @@ It seems to use Bing internally, as the image thumbnails are loaded from Bing.
from urllib.parse import urlencode
import typing as t
from lxml import html
from searx.enginelib import EngineCache
from searx.network import get
from searx.exceptions import SearxEngineAPIException, SearxEngineAccessDeniedException
from searx.result_types import EngineResults
from searx.utils import eval_xpath, extract_text, gen_useragent
from searx.utils import gen_useragent
if t.TYPE_CHECKING:
from searx.extended_types import SXNG_Response
@@ -69,16 +68,17 @@ def _get_api_token(query: str) -> str:
if cached_token:
return cached_token
resp = get(f"{base_url}/search?q={query}", headers={"User-Agent": gen_useragent()})
resp = get(
f"{base_url}/search?q={query}", headers={"User-Agent": gen_useragent(), "Accept-Language": "en-US,en:q=0.9"}
)
if not resp.ok:
raise SearxEngineAPIException("failed to obtain request token: invalid response code")
doc = html.fromstring(resp.text)
token = extract_text(eval_xpath(doc, "//html/@data-cacheft"))
token = resp.cookies["cacheft"]
if not token:
raise SearxEngineAPIException("failed to obtain request token: no token found")
CACHE.set("token", token)
CACHE.set("token", token, expire=3 * 60)
return token
@@ -92,8 +92,9 @@ def request(query: str, params: "OnlineParams") -> None:
args["lang"] = params["searxng_locale"].split("-")[0]
params["url"] = f"{api_url}/search/{heexy_categ}?{urlencode(args)}"
params["headers"]["X-Data-Cacheft"] = _get_api_token(query)
params["headers"]["Origin"] = api_url
params["cookies"]["cacheft"] = _get_api_token(query)
def response(resp: "SXNG_Response"):

View File

@@ -91,7 +91,7 @@ def response(resp) -> EngineResults:
published_date = None
try:
published_date = datetime.strptime(entry["createdAt"], "%Y-%m-%dT%H:%M:%S.%fZ")
published_date = datetime.fromisoformat(entry["createdAt"].rstrip("Z"))
except (ValueError, TypeError):
pass

View File

@@ -43,7 +43,7 @@ def _result(video: dict[str, typing.Any], album_info: dict[str, typing.Any]):
release_time = album_info.get("releaseTime", {}).get("value")
if release_time:
try:
published_date = datetime.strptime(release_time, "%Y-%m-%d")
published_date = datetime.fromisoformat(release_time)
except (ValueError, TypeError):
pass

View File

@@ -42,15 +42,14 @@ To enable Kagi, add the following to the ``engines`` seciton of
.. _Api Portal: https://help.kagi.com/kagi/api/overview.html
"""
from datetime import datetime, timedelta
import typing as t
import html
from searx.extended_types import SXNG_Response
from searx.result_types import EngineResults
from searx.utils import parse_duration_string
from searx.utils import html_to_text, parse_duration_string
if t.TYPE_CHECKING:
from searx.search.processors import OnlineParams
@@ -77,7 +76,12 @@ kagi_categ: t.Literal["search", "images", "news", "videos"] = "search"
base_url = "https://kagi.com"
safe_search_map = {0: False, 1: True, 2: True}
time_range_to_days_map: dict[TimeRangeType, int] = {"day": 1, "week": 7, "month": 30, "year": 365}
time_range_to_days_map: dict[TimeRangeType, int] = {
"day": 1,
"week": 7,
"month": 30,
"year": 365,
}
api_key = ""
"""Kagi API key. Required for using this engine."""
@@ -135,9 +139,13 @@ def response(resp: "SXNG_Response") -> EngineResults:
if kagi_categ in ("images", "videos"):
# the JSON key is "image" for "images" and "video" for "videos"
json_results = json_data["data"][kagi_categ[:-1]]
json_results = json_data["data"].get(kagi_categ[:-1])
else:
json_results = json_data["data"][kagi_categ]
json_results = json_data["data"].get(kagi_categ)
# if no results were found, the response doesn't contain the results field
if not json_results:
return res
for result in json_results:
published_date: datetime | None = None
@@ -148,8 +156,8 @@ def response(resp: "SXNG_Response") -> EngineResults:
res.add(
res.types.MainResult(
url=result["url"],
title=html.unescape(result["title"]),
content=html.unescape(result["snippet"]),
title=html_to_text(result.get("title", "no title available")),
content=html_to_text(result.get("snippet", "")),
thumbnail=result.get("image", {}).get("url") or "",
publishedDate=published_date,
)
@@ -158,15 +166,15 @@ def response(resp: "SXNG_Response") -> EngineResults:
res.add(
res.types.Image(
url=result["url"],
title=html.unescape(result.get("title")),
title=html_to_text(result.get("title", "no title available")),
img_src=result.get("image", {}).get("url"),
resolution=f"{result['image']['width']}x{result['image']['height']}",
resolution=f"{result.get('image', {}).get('width')}x{result.get('image', {}).get('height')}",
thumbnail_src=result.get("props", {}).get("thumbnail", {}).get("url"),
)
)
elif kagi_categ == "videos":
length: timedelta | None = None
if result["props"].get("duration"):
if result.get("props", {}).get("duration"):
length = parse_duration_string(result["props"]["duration"])
res.add(
@@ -174,11 +182,11 @@ def response(resp: "SXNG_Response") -> EngineResults:
{
"template": "videos.html",
"url": result["url"],
"title": html.unescape(result["title"]),
"content": html.unescape(result["snippet"]),
"title": html_to_text(result.get("title", "no title available")),
"content": html_to_text(result.get("snippet", "")),
"thumbnail": result.get("image", {}).get("url"),
"publishedDate": published_date,
"author": result["props"].get("creator_name"),
"author": result.get("props", {}).get("creator_name"),
"length": length,
}
)

View File

@@ -92,7 +92,7 @@ def _get_communities(json):
'title': result['community']['title'],
'content': markdown_to_text(result['community'].get('description', '')),
'thumbnail': result['community'].get('icon', result['community'].get('banner')),
'publishedDate': datetime.strptime(counts['published'][:19], '%Y-%m-%dT%H:%M:%S'),
'publishedDate': datetime.fromisoformat(counts['published'][:19]),
'metadata': metadata,
}
)
@@ -141,7 +141,7 @@ def _get_posts(json):
'title': result['post']['name'],
'content': content,
'thumbnail': thumbnail,
'publishedDate': datetime.strptime(result['post']['published'][:19], '%Y-%m-%dT%H:%M:%S'),
'publishedDate': datetime.fromisoformat(result['post']['published'][:19]),
'metadata': metadata,
}
)
@@ -170,7 +170,7 @@ def _get_comments(json):
'url': result['comment']['ap_id'],
'title': result['post']['name'],
'content': markdown_to_text(result['comment']['content']),
'publishedDate': datetime.strptime(result['comment']['published'][:19], '%Y-%m-%dT%H:%M:%S'),
'publishedDate': datetime.fromisoformat(result['comment']['published'][:19]),
'metadata': metadata,
}
)

View File

@@ -60,7 +60,7 @@ def response(resp):
'title': result['username'] + f" ({result['followers_count']} followers)",
'content': result['note'],
'thumbnail': result.get('avatar'),
'publishedDate': datetime.strptime(result['created_at'][:10], "%Y-%m-%d"),
'publishedDate': datetime.fromisoformat(result['created_at'][:10]),
}
)
elif mastodon_type == "hashtags":

View File

@@ -0,0 +1,66 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Neocities_ is open source software for creating blogs.
.. _Neocities : https://github.com/neocities/neocities
"""
from urllib.parse import urlencode
import typing as t
from lxml import html
from searx.utils import eval_xpath, eval_xpath_list, extract_text
from searx.result_types import EngineResults
if t.TYPE_CHECKING:
from extended_types import SXNG_Response
from search.processors import OnlineParams
# Engine metadata
about = {
"website": "https://neocities.org/",
"wikidata_id": "Q17071099",
"official_api_documentation": None,
"use_official_api": False,
"require_api_key": False,
"results": "HTML",
}
# Engine configuration
categories = ["general", "blogs"]
paging = True
# Search URL
base_url = "https://neocities.org"
results_xpath = "//div[@class='result-item']"
url_xpath = './/div[@class="result-url"]/a/@href'
title_xpath = './/h3[@class="result-title"]/a/text()'
content_xpath = './/p[@class="result-snippet"]//text()'
screenshot_xpath = './/a[@class="result-screenshot"]/img/@src'
def request(query: str, params: "OnlineParams") -> None:
query_params: dict[str, t.Any] = {"q": query}
if params['pageno'] > 1:
offset = (params["pageno"] - 1) * 100
query_params["start"] = offset
params["url"] = f"{base_url}/search?{urlencode(query_params)}"
def response(resp: "SXNG_Response") -> EngineResults:
results = EngineResults()
dom = html.fromstring(resp.text)
for result in eval_xpath_list(dom, results_xpath):
results.add(
results.types.MainResult(
url=extract_text(eval_xpath(result, url_xpath)),
title=extract_text(eval_xpath(result, title_xpath)) or "",
content=extract_text(eval_xpath(result, content_xpath)) or "",
thumbnail=base_url + (extract_text(eval_xpath(result, screenshot_xpath)) or ""),
)
)
return results

View File

@@ -44,7 +44,7 @@ def response(resp) -> EngineResults:
cve_id = item["cve"]["id"]
description = item["cve"]["descriptions"][0]["value"]
date = datetime.strptime(item["cve"]["published"], "%Y-%m-%dT%H:%M:%S.%f")
date = datetime.fromisoformat(item["cve"]["published"])
# Extract severity (Low, Medium, High, or Critical) and CVSS score, if available
info = item["cve"].get("metrics", {}).get("cvssMetricV31", [{}])[0].get("cvssData", {})

View File

@@ -76,7 +76,7 @@ def response(resp):
release_time = item["release_time"]
duration = item["duration"]
release_date = datetime.strptime(release_time.split("T")[0], "%Y-%m-%d")
release_date = datetime.fromisoformat(release_time.split("T")[0])
formatted_date = datetime.fromtimestamp(release_date.timestamp())
url = f"https://odysee.com/{name}:{claim_id}"

View File

@@ -54,7 +54,7 @@ def response(resp: "SXNG_Response"):
title=result["title"],
content=result["description"],
thumbnail=result["image_url"],
publishedDate=datetime.strptime(result["created_at"], "%Y-%m-%d %H:%M:%S"),
publishedDate=datetime.fromisoformat(result["created_at"]),
metadata=" | ".join(metadata),
)
)

View File

@@ -140,7 +140,7 @@ def response(resp):
results.append(
{
'template': 'images.html',
'url': _clean_url(f"{about['website']}/images/{result['objectID']}"),
'url': _clean_url(f"{pdia_base_url}/images/{result['objectID']}"),
'img_src': _clean_url(base_image_url),
'thumbnail_src': _clean_url(base_image_url + THUMBNAIL_SUFFIX),
'title': f"{result['title'].strip()} by {result['artist']} {result.get('displayYear', '')}",

View File

@@ -292,7 +292,7 @@ def parse_news_uchq(data):
results = []
for item in data.get('feed', []):
try:
published_date = datetime.strptime(item.get('time'), "%Y-%m-%d")
published_date = datetime.fromisoformat(item.get('time'))
except (ValueError, TypeError):
# Sometime Quark will return non-standard format like "1天前", set published_date as None
published_date = None

View File

@@ -51,6 +51,7 @@ from urllib.parse import urlencode
import babel
from flask_babel import gettext # pyright: ignore[reportUnknownVariableType]
from searx.enginelib import EngineCache
from searx.enginelib.traits import EngineTraits
from searx.exceptions import (
SearxEngineAccessDeniedException,
@@ -105,9 +106,19 @@ qwant_news_locales = [
]
# fmt: on
base_url = "https://www.qwant.com"
api_url = "https://api.qwant.com/v3/search/"
"""URL of Qwant's API (JSON)"""
CACHE: EngineCache
"""Cache for storing the ``datadome`` cookie."""
def setup(engine_settings: dict[str, t.Any]) -> bool:
global CACHE # pylint: disable=global-statement
CACHE = EngineCache(engine_settings["name"])
return True
def request(query: str, params: "OnlineParams") -> None:
"""Qwant search request"""
@@ -129,24 +140,29 @@ def request(query: str, params: "OnlineParams") -> None:
"tgp": test_group_value,
"device": "desktop",
"safesearch": params["safesearch"],
"display": True,
"llm": True,
# True would be encoded to "True", instead of "true", which makes the request
# easier to detect and block
"displayed": "true",
"llm": "true",
}
# shuffle query parameters to be harder to fingerprint
args = list(args.items())
random.shuffle(args)
args = dict(args)
params["raise_for_httperror"] = False
params["url"] = f"{api_url}{qwant_categ}?{urlencode(args)}"
params["cookies"]["datadome"] = CACHE.get("datadome")
params["headers"].update({"Accept": "application/json", "Referer": f"{base_url}/", "Origin": base_url})
def response(resp: "SXNG_Response") -> EngineResults:
"""Parse results from Qwant's API"""
# pylint: disable=too-many-locals, too-many-branches, too-many-statements
# cache datadome cookie - changes on each request
datadome = resp.cookies.get("datadome")
if datadome:
CACHE.set("datadome", datadome)
res = EngineResults()
# Try to load JSON result
@@ -163,8 +179,8 @@ def response(resp: "SXNG_Response") -> EngineResults:
error_code = data.get("error_code")
if error_code == 24:
raise SearxEngineTooManyRequestsException()
if search_results.get("data", {}).get("error_data", {}).get("captchaUrl") is not None:
raise SearxEngineCaptchaException()
if search_results.get("url") is not None:
raise SearxEngineCaptchaException(suspended_time=0)
if resp.status_code == 403:
raise SearxEngineAccessDeniedException()
msg = ",".join(data.get("message", ["unknown"]))

View File

@@ -58,7 +58,7 @@ def response(resp):
title = extract_text(result_dom.xpath(title_xpath))
p_date = extract_text(result_dom.xpath(published_date))
# fix offset date for line 644 webapp.py check
fixed_date = datetime.strptime(p_date, '%Y-%m-%dT%H:%M:%S%z')
fixed_date = datetime.fromisoformat(p_date)
earned = extract_text(result_dom.xpath(earned_xpath))
views = extract_text(result_dom.xpath(views_xpath))
rumbles = extract_text(result_dom.xpath(rumbles_xpath))

View File

@@ -120,7 +120,7 @@ def response(resp: "SXNG_Response") -> EngineResults:
publishedDate: datetime | None
if "pubDate" in result:
publishedDate = datetime.strptime(result["pubDate"], "%Y-%m-%d")
publishedDate = datetime.fromisoformat(result["pubDate"])
else:
publishedDate = None

View File

@@ -95,7 +95,8 @@ def _parse_date(text):
date_match = re.search(r"(\d{4}-\d{1,2}-\d{1,2})", text)
if date_match:
try:
return datetime.strptime(date_match.group(1), "%Y-%m-%d")
y, m, d = date_match.group(1).split("-")
return datetime(year=int(y), month=int(m), day=int(d))
except (ValueError, TypeError):
pass
return None

View File

@@ -54,7 +54,7 @@ def response(resp):
published_date = None
if entry.get("date") and entry.get("duration"):
try:
published_date = datetime.strptime(entry['date'], "%Y-%m-%d")
published_date = datetime.fromisoformat(entry['date'])
except (ValueError, TypeError):
published_date = None

View File

@@ -134,7 +134,7 @@ def response(resp: "SXNG_Response") -> EngineResults:
return str(record.get(k, ""))
for record in json_data["records"]:
published = datetime.strptime(record["publicationDate"], "%Y-%m-%d")
published = datetime.fromisoformat(record["publicationDate"])
authors: list[str] = [" ".join(author["creator"].split(", ")[::-1]) for author in record["creators"]]
pdf_url = ""

View File

@@ -81,7 +81,7 @@ def _story(item):
return {
'title': item['title'],
'thumbnail': item.get('teaserImage', {}).get('imageVariants', {}).get('16x9-256'),
'publishedDate': datetime.strptime(item['date'][:19], '%Y-%m-%dT%H:%M:%S'),
'publishedDate': datetime.fromisoformat(item['date'][:19]),
'content': item.get('firstSentence'),
'url': item['shareURL'] if use_source_url else item['detailsweb'],
}
@@ -103,7 +103,7 @@ def _video(item):
'template': 'videos.html',
'title': title,
'thumbnail': item.get('teaserImage', {}).get('imageVariants', {}).get('16x9-256'),
'publishedDate': datetime.strptime(item['date'][:19], '%Y-%m-%dT%H:%M:%S'),
'publishedDate': datetime.fromisoformat(item['date'][:19]),
'content': item.get('firstSentence', ''),
'iframe_src': video_url,
'url': url,

View File

@@ -117,7 +117,7 @@ def _obtain_session_code() -> str:
if not code:
raise SearxEngineAPIException("failed to obtain session code")
CACHE.set("session", code, expire=60 * 24 * 60) # cookie is valid for two months
CACHE.set("session", code, expire=60 * 24 * 60 * 60) # cookie is valid for two months
return code

View File

@@ -121,7 +121,7 @@ def parse_tineye_match(match_json):
crawl_date = backlink_json.get("crawl_date")
if crawl_date:
crawl_date = datetime.strptime(crawl_date, '%Y-%m-%d')
crawl_date = datetime.fromisoformat(crawl_date)
else:
crawl_date = datetime.min

View File

@@ -51,7 +51,7 @@ def response(resp):
'title': title,
'content': html_to_text(result['content']),
'thumbnail': thumbnail,
'publishedDate': datetime.strptime(result['created_at'], '%Y-%m-%d %H:%M:%S'),
'publishedDate': datetime.fromisoformat(result['created_at']),
}
)

View File

@@ -13,7 +13,7 @@ from dateutil import parser
from searx.exceptions import SearxEngineAPIException
from searx.network import get
from searx.utils import html_to_text
from searx.utils import gen_useragent, html_to_text
from searx.result_types import EngineResults
if t.TYPE_CHECKING:
@@ -52,7 +52,7 @@ def _obtain_x_sid() -> tuple[str, str]:
The header key is usually called `x-sid-{UUIDv4}`, and the value is
usually a plain UUIDv4 (but a different one than in the header key).
"""
resp = get(f"{api_url}/revcontent/embed.js")
resp = get(f"{api_url}/revcontent/embed.js", headers={"User-Agent": gen_useragent()})
if not resp.ok:
raise SearxEngineAPIException("failed to obtain request x-sid token")
@@ -89,12 +89,14 @@ def request(query: str, params: "OnlineParams") -> None:
params["url"] = f"{api_url}/Search/Web?{urlencode(args)}"
x_sid_header, x_sid_value = _obtain_x_sid()
params["headers"] = {
x_sid_header: x_sid_value,
# required - we send a random longitude and latitude instead of the actual user location
'x-lon': str(random.random() * 90),
'x-lat': str(random.random() * 90),
}
params["headers"].update(
{
x_sid_header: x_sid_value,
# required - we send a random longitude and latitude instead of the actual user location
"x-lon": str(round(random.random() * 90, 4)),
"x-lat": str(round(random.random() * 90, 4)),
}
)
def response(resp: "SXNG_Response"):

View File

@@ -79,7 +79,7 @@ def response(resp):
'img_src': result['path'],
'thumbnail_src': result['thumbs']['small'],
'resolution': result['resolution'].replace('x', ' x '),
'publishedDate': datetime.strptime(result['created_at'], '%Y-%m-%d %H:%M:%S'),
'publishedDate': datetime.fromisoformat(result['created_at']),
'img_format': result['file_type'],
'filesize': humanize_bytes(result['file_size']),
}

View File

@@ -52,6 +52,12 @@ def _normalize_url_fields(result: "Result | LegacyResult"):
result.parsed_url = urllib.parse.urlparse(result.url)
if result.parsed_url:
# properly format special characters (e.g. "ä", "ö") in IDN domains
# e.g. "xn--strung-xxa.de" becomes "störung.de"
if result.parsed_url.netloc.startswith("xn--"):
netloc = result.parsed_url.netloc.encode().decode("idna")
result.parsed_url = result.parsed_url._replace(netloc=netloc)
result.parsed_url = result.parsed_url._replace(
# if the result has no scheme, use http as default
scheme=result.parsed_url.scheme or "http",

View File

@@ -477,6 +477,24 @@ engines:
engine: arxiv
shortcut: arx
- name: avalw
engine: json_engine
shortcut: av
categories: general
paging: true
search_url: https://avalw.org/api/search?q={query}&page={pageno}&limit=10&tbm=all
results_query: results
url_query: url
title_query: title
content_query: snippet
thumbnail: image_url
disabled: true
inactive: true
about:
website: https://avalw.com
description: "Search engine from the Romanian news company AVALW S.R.L."
results: JSON
- name: ayo
engine: xpath
categories: general
@@ -1199,10 +1217,12 @@ engines:
- name: google
engine: google
shortcut: go
inactive: true
- name: google images
engine: google_images
shortcut: goi
inactive: true
- name: google news
engine: google_news
@@ -1211,6 +1231,17 @@ engines:
- name: google videos
engine: google_videos
shortcut: gov
inactive: true
- name: google cse
engine: google_cse
shortcut: goc
- name: google cse images
engine: google_cse
categories: [images, web]
google_categ: image
shortcut: goci
- name: google scholar
engine: google_scholar
@@ -1409,6 +1440,27 @@ engines:
# api_key: "" # required
# kagi_categ: videos
- name: kavunka demo
engine: xpath
categories: general
paging: true
shortcut: kav
search_url: https://kavunka.net/search/kavunka-srv.php
method: POST
request_body: request={query}&np={pageno}
headers:
Content-Type: application/x-www-form-urlencoded
disabled: true
inactive: true
results_xpath: //div[contains(@class, "issue")]
url_xpath: .//h2/a/@href
title_xpath: .//h2
content_xpath: .//div[contains(@class, "snip")]
about:
website: https://kavunka.net
description: "Demo index of Kavunka, a statistical search engine"
results: HTML
- name: kozmonavt
engine: xpath
search_url: https://kozmonavt.su/s?q={query}
@@ -1691,6 +1743,12 @@ engines:
shortcut: mwm
disabled: true
- name: neocities
engine: neocities
shortcut: nc
disabled: true
inactive: true
- name: niconico
engine: niconico
shortcut: nico

View File

@@ -1,11 +0,0 @@
import{i as e,n as t,r as n}from"../sxng-core.min.js";import{t as r}from"./DK4yUVpy.min.js";
/*!
* swiped-events.js - v@version@
* Pure JavaScript swipe events
* https://github.com/john-doherty/swiped-events
* @inspiration https://stackoverflow.com/questions/16348031/disable-scrolling-when-touch-moving-certain-element
* @author John Doherty <www.johndoherty.info>
* @license MIT
*/
(function(e,t){typeof e.CustomEvent!=`function`&&(e.CustomEvent=function(e,n){n||={bubbles:!1,cancelable:!1,detail:void 0};var r=t.createEvent(`CustomEvent`);return r.initCustomEvent(e,n.bubbles,n.cancelable,n.detail),r},e.CustomEvent.prototype=e.Event.prototype),t.addEventListener(`touchstart`,u,!1),t.addEventListener(`touchmove`,d,!1),t.addEventListener(`touchend`,l,!1);var n=null,r=null,i=null,a=null,o=null,s=null,c=0;function l(e){if(s===e.target){var l=parseInt(f(s,`data-swipe-threshold`,`20`),10),u=f(s,`data-swipe-unit`,`px`),d=parseInt(f(s,`data-swipe-timeout`,`500`),10),p=Date.now()-o,m=``,h=e.changedTouches||e.touches||[];if(u===`vh`&&(l=Math.round(l/100*t.documentElement.clientHeight)),u===`vw`&&(l=Math.round(l/100*t.documentElement.clientWidth)),Math.abs(i)>Math.abs(a)?Math.abs(i)>l&&p<d&&(m=i>0?`swiped-left`:`swiped-right`):Math.abs(a)>l&&p<d&&(m=a>0?`swiped-up`:`swiped-down`),m!==``){var g={dir:m.replace(/swiped-/,``),touchType:(h[0]||{}).touchType||`direct`,fingers:c,xStart:parseInt(n,10),xEnd:parseInt((h[0]||{}).clientX||-1,10),yStart:parseInt(r,10),yEnd:parseInt((h[0]||{}).clientY||-1,10)};s.dispatchEvent(new CustomEvent(`swiped`,{bubbles:!0,cancelable:!0,detail:g})),s.dispatchEvent(new CustomEvent(m,{bubbles:!0,cancelable:!0,detail:g}))}n=null,r=null,o=null}}function u(e){e.target.getAttribute(`data-swipe-ignore`)!==`true`&&(s=e.target,o=Date.now(),n=e.touches[0].clientX,r=e.touches[0].clientY,i=0,a=0,c=e.touches.length)}function d(e){if(!(!n||!r)){var t=e.touches[0].clientX,o=e.touches[0].clientY;i=n-t,a=r-o}}function f(e,n,r){for(;e&&e!==t.documentElement;){var i=e.getAttribute(n);if(i)return i;e=e.parentNode}return r}})(window,document);var i,a=t=>{i&&clearTimeout(i);let n=t.querySelector(`.result-images-source img`);if(!n)return;let r=t.querySelector(`.image_thumbnail`);if(r){if(r.src===`${e.theme_static_path}/img/img_load_error.svg`)return;n.onerror=()=>{n.src=r.src},n.src=r.src}let a=n.getAttribute(`data-src`);a&&(i=setTimeout(()=>{n.src=a,n.removeAttribute(`data-src`)},1e3))},o=document.querySelectorAll(`#urls img.image_thumbnail`);for(let t of o)t.complete&&t.naturalWidth===0&&(t.src=`${e.theme_static_path}/img/img_load_error.svg`),t.onerror=()=>{t.src=`${e.theme_static_path}/img/img_load_error.svg`};document.querySelector(`#search_url button#copy_url`)?.style.setProperty(`display`,`block`),n.selectImage=e=>{document.getElementById(`results`)?.classList.add(`image-detail-open`),window.location.hash=`#image-viewer`,n.scrollPageToSelected?.(),e&&a(e)},n.closeDetail=()=>{document.getElementById(`results`)?.classList.remove(`image-detail-open`),window.location.hash===`#image-viewer`&&window.history.back(),n.scrollPageToSelected?.()},t(`click`,`.btn-collapse`,function(){let e=this.getAttribute(`data-btn-text-collapsed`),t=this.getAttribute(`data-btn-text-not-collapsed`),n=this.getAttribute(`data-target`);if(!(n&&e&&t))return;let i=document.querySelector(n);r(i);let a=this.classList.contains(`collapsed`),o=a?t:e,s=a?e:t;this.innerHTML=this.innerHTML.replace(s,o),this.classList.toggle(`collapsed`),i.classList.toggle(`invisible`)}),t(`click`,`.media-loader`,function(){let e=this.getAttribute(`data-target`);if(!e)return;let t=document.querySelector(`${e} > iframe`);if(r(t),!t.getAttribute(`src`)){let e=t.getAttribute(`data-src`);e&&t.setAttribute(`src`,e)}}),t(`click`,`#copy_url`,async function(){let e=this.parentElement?.querySelector(`pre`);if(r(e),window.isSecureContext)await navigator.clipboard.writeText(e.innerText);else{let t=window.getSelection();if(t){let n=document.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n),document.execCommand(`copy`)}}this.dataset.copiedText&&(this.innerText=this.dataset.copiedText)}),t(`click`,`.result-detail-close`,e=>{e.preventDefault(),n.closeDetail?.()}),t(`click`,`.result-detail-previous`,e=>{e.preventDefault(),n.selectPrevious?.(!1)}),t(`click`,`.result-detail-next`,e=>{e.preventDefault(),n.selectNext?.(!1)}),window.addEventListener(`hashchange`,()=>{window.location.hash!==`#image-viewer`&&n.closeDetail?.()});var s=document.querySelectorAll(`.swipe-horizontal`);for(let e of s)t(`swiped-left`,e,()=>{n.selectNext?.(!1)}),t(`swiped-right`,e,()=>{n.selectPrevious?.(!1)});window.addEventListener(`scroll`,()=>{let e=document.getElementById(`backToTop`),t=document.getElementById(`results`);if(e&&t){let e=(document.documentElement.scrollTop||document.body.scrollTop)>=100;t.classList.toggle(`scrolling`,e)}},!0);
//# sourceMappingURL=B8prKeWj.min.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
import{i as e,n as t,r as n}from"../sxng-core.min.js";import{t as r}from"./DK4yUVpy.min.js";
/*!
* swiped-events.js - v@version@
* Pure JavaScript swipe events
* https://github.com/john-doherty/swiped-events
* @inspiration https://stackoverflow.com/questions/16348031/disable-scrolling-when-touch-moving-certain-element
* @author John Doherty <www.johndoherty.info>
* @license MIT
*/
(function(e,t){typeof e.CustomEvent!=`function`&&(e.CustomEvent=function(e,n){n||={bubbles:!1,cancelable:!1,detail:void 0};var r=t.createEvent(`CustomEvent`);return r.initCustomEvent(e,n.bubbles,n.cancelable,n.detail),r},e.CustomEvent.prototype=e.Event.prototype),t.addEventListener(`touchstart`,u,!1),t.addEventListener(`touchmove`,d,!1),t.addEventListener(`touchend`,l,!1);var n=null,r=null,i=null,a=null,o=null,s=null,c=0;function l(e){if(s===e.target){var l=parseInt(f(s,`data-swipe-threshold`,`20`),10),u=f(s,`data-swipe-unit`,`px`),d=parseInt(f(s,`data-swipe-timeout`,`500`),10),p=Date.now()-o,m=``,h=e.changedTouches||e.touches||[];if(u===`vh`&&(l=Math.round(l/100*t.documentElement.clientHeight)),u===`vw`&&(l=Math.round(l/100*t.documentElement.clientWidth)),Math.abs(i)>Math.abs(a)?Math.abs(i)>l&&p<d&&(m=i>0?`swiped-left`:`swiped-right`):Math.abs(a)>l&&p<d&&(m=a>0?`swiped-up`:`swiped-down`),m!==``){var g={dir:m.replace(/swiped-/,``),touchType:(h[0]||{}).touchType||`direct`,fingers:c,xStart:parseInt(n,10),xEnd:parseInt((h[0]||{}).clientX||-1,10),yStart:parseInt(r,10),yEnd:parseInt((h[0]||{}).clientY||-1,10)};s.dispatchEvent(new CustomEvent(`swiped`,{bubbles:!0,cancelable:!0,detail:g})),s.dispatchEvent(new CustomEvent(m,{bubbles:!0,cancelable:!0,detail:g}))}n=null,r=null,o=null}}function u(e){e.target.getAttribute(`data-swipe-ignore`)!==`true`&&(s=e.target,o=Date.now(),n=e.touches[0].clientX,r=e.touches[0].clientY,i=0,a=0,c=e.touches.length)}function d(e){if(!(!n||!r)){var t=e.touches[0].clientX,o=e.touches[0].clientY;i=n-t,a=r-o}}function f(e,n,r){for(;e&&e!==t.documentElement;){var i=e.getAttribute(n);if(i)return i;e=e.parentNode}return r}})(window,document);var i,a=t=>{i&&clearTimeout(i);let n=t.querySelector(`.result-images-source img`);if(!n)return;let r=t.querySelector(`.image_thumbnail`);if(r){if(r.src===`${e.theme_static_path}/img/img_load_error.svg`)return;n.onerror=()=>{n.src=r.src},n.src=r.src}let a=n.getAttribute(`data-src`);a&&(i=setTimeout(()=>{n.src=a,n.removeAttribute(`data-src`)},1e3))},o=document.querySelectorAll(`#urls img.image_thumbnail, img.thumbnail`);for(let t of o)t.complete&&t.naturalWidth===0&&(t.src=`${e.theme_static_path}/img/img_load_error.svg`),t.onerror=()=>{t.src=`${e.theme_static_path}/img/img_load_error.svg`};document.querySelector(`#search_url button#copy_url`)?.style.setProperty(`display`,`block`),n.selectImage=e=>{document.getElementById(`results`)?.classList.add(`image-detail-open`),window.location.hash=`#image-viewer`,n.scrollPageToSelected?.(),e&&a(e)},n.closeDetail=()=>{document.getElementById(`results`)?.classList.remove(`image-detail-open`),window.location.hash===`#image-viewer`&&window.history.back(),n.scrollPageToSelected?.()},t(`click`,`.btn-collapse`,function(){let e=this.getAttribute(`data-btn-text-collapsed`),t=this.getAttribute(`data-btn-text-not-collapsed`),n=this.getAttribute(`data-target`);if(!(n&&e&&t))return;let i=document.querySelector(n);r(i);let a=this.classList.contains(`collapsed`),o=a?t:e,s=a?e:t;this.innerHTML=this.innerHTML.replace(s,o),this.classList.toggle(`collapsed`),i.classList.toggle(`invisible`)}),t(`click`,`.media-loader`,function(){let e=this.getAttribute(`data-target`);if(!e)return;let t=document.querySelector(`${e} > iframe`);if(r(t),!t.getAttribute(`src`)){let e=t.getAttribute(`data-src`);e&&t.setAttribute(`src`,e)}}),t(`click`,`#copy_url`,async function(){let e=this.parentElement?.querySelector(`pre`);if(r(e),window.isSecureContext)await navigator.clipboard.writeText(e.innerText);else{let t=window.getSelection();if(t){let n=document.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n),document.execCommand(`copy`)}}this.dataset.copiedText&&(this.innerText=this.dataset.copiedText)}),t(`click`,`.result-detail-close`,e=>{e.preventDefault(),n.closeDetail?.()}),t(`click`,`.result-detail-previous`,e=>{e.preventDefault(),n.selectPrevious?.(!1)}),t(`click`,`.result-detail-next`,e=>{e.preventDefault(),n.selectNext?.(!1)}),window.addEventListener(`hashchange`,()=>{window.location.hash!==`#image-viewer`&&n.closeDetail?.()});var s=document.querySelectorAll(`.swipe-horizontal`);for(let e of s)t(`swiped-left`,e,()=>{n.selectNext?.(!1)}),t(`swiped-right`,e,()=>{n.selectPrevious?.(!1)});window.addEventListener(`scroll`,()=>{let e=document.getElementById(`backToTop`),t=document.getElementById(`results`);if(e&&t){let e=(document.documentElement.scrollTop||document.body.scrollTop)>=100;t.classList.toggle(`scrolling`,e)}},!0);
//# sourceMappingURL=od7pNHfk.min.js.map

File diff suppressed because one or more lines are too long

View File

@@ -57,7 +57,7 @@
]
},
"src/js/main/results.ts": {
"file": "chunk/B8prKeWj.min.js",
"file": "chunk/od7pNHfk.min.js",
"name": "results",
"src": "src/js/main/results.ts",
"isDynamicEntry": true,

View File

@@ -1,3 +1,3 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./chunk/BnnvKC7b.min.js","./sxng-mapview.min.css","./chunk/DpvWr1cn.min.js","./chunk/DK4yUVpy.min.js","./chunk/DcK-mo-Y.min.js","./chunk/C8c7HJzp.min.js","./chunk/C93hSkpT.min.js","./chunk/5Ako-qGW.min.js","./chunk/DvCYLbJr.min.js","./chunk/B8prKeWj.min.js","./chunk/e2-9fzwE.min.js"])))=>i.map(i=>d[i]);
var e=class{id;constructor(e){this.id=e,queueMicrotask(()=>this.invoke())}async invoke(){try{console.debug(`[PLUGIN] ${this.id}: Running...`);let e=await this.run();if(!e)return;console.debug(`[PLUGIN] ${this.id}: Running post-exec...`),await this.post(e)}catch(e){console.error(`[PLUGIN] ${this.id}:`,e)}finally{console.debug(`[PLUGIN] ${this.id}: Done.`)}}},t={index:`index`,results:`results`,preferences:`preferences`,unknown:`unknown`},n={closeDetail:void 0,scrollPageToSelected:void 0,selectImage:void 0,selectNext:void 0,selectPrevious:void 0},r=()=>{let e=document.querySelector(`meta[name="endpoint"]`)?.getAttribute(`content`);return e&&e in t?e:t.unknown},i=()=>{let e=document.querySelector(`script[client_settings]`)?.getAttribute(`client_settings`);if(!e)return{};try{return JSON.parse(atob(e))}catch(e){return console.error(`Failed to load client_settings:`,e),{}}},a=async(e,t,n)=>{let r=new AbortController,i=setTimeout(()=>r.abort(),n?.timeout??3e4),a=await fetch(t,{body:n?.body,method:e,signal:r.signal}).finally(()=>clearTimeout(i));if(!a.ok)throw Error(a.statusText);return a},o=(e,t,n,r)=>{if(typeof t!=`string`){t.addEventListener(e,n,r);return}document.addEventListener(e,e=>{for(let r of e.composedPath())if(r instanceof HTMLElement&&r.matches(t)){try{n.call(r,e)}catch(e){console.error(e)}break}},r)},s=(e,t)=>{for(let e of t?.on??[])if(!e)return;document.readyState===`loading`?o(`DOMContentLoaded`,document,e,{once:!0}):e()},c=r(),l=i(),u=(e,t)=>{d(t)&&e()},d=e=>{switch(e.on){case`global`:return!0;case`endpoint`:return!!e.where.includes(c)}},f=`modulepreload`,p=function(e,t){return new URL(e,t).href},m={},h=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,new URL(`../../../src/node/plugins/importAnalysisBuild.ts`,import.meta.url)).href}r=o(t.map(t=>{if(t=p(t,n),t=s(t),t in m)return;m[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:f,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})};s(()=>{document.documentElement.classList.remove(`no-js`),document.documentElement.classList.add(`js`),o(`click`,`.close`,function(){this.parentNode?.classList.add(`invisible`)}),o(`click`,`.searxng_init_map`,async function(e){e.preventDefault(),this.classList.remove(`searxng_init_map`),u(()=>h(async()=>{let{default:e}=await import(`./chunk/BnnvKC7b.min.js`);return{default:e}},__vite__mapDeps([0,1]),import.meta.url).then(({default:e})=>new e(this)),{on:`endpoint`,where:[t.results]})}),l.plugins?.includes(`infiniteScroll`)&&u(()=>h(async()=>{let{default:e}=await import(`./chunk/DpvWr1cn.min.js`);return{default:e}},__vite__mapDeps([2,3,4]),import.meta.url).then(({default:e})=>new e),{on:`endpoint`,where:[t.results]}),l.plugins?.includes(`calculator`)&&u(()=>h(async()=>{let{default:e}=await import(`./chunk/C8c7HJzp.min.js`);return{default:e}},__vite__mapDeps([5,4,3]),import.meta.url).then(({default:e})=>new e),{on:`endpoint`,where:[t.results]})}),s(()=>{h(()=>import(`./chunk/C93hSkpT.min.js`),__vite__mapDeps([6,3]),import.meta.url),h(()=>import(`./chunk/5Ako-qGW.min.js`),__vite__mapDeps([7,4,3]),import.meta.url),l.autocomplete&&h(()=>import(`./chunk/DvCYLbJr.min.js`),__vite__mapDeps([8,3]),import.meta.url)},{on:[c===t.index]}),s(()=>{h(()=>import(`./chunk/C93hSkpT.min.js`),__vite__mapDeps([6,3]),import.meta.url),h(()=>import(`./chunk/B8prKeWj.min.js`),__vite__mapDeps([9,3]),import.meta.url),h(()=>import(`./chunk/5Ako-qGW.min.js`),__vite__mapDeps([7,4,3]),import.meta.url),l.autocomplete&&h(()=>import(`./chunk/DvCYLbJr.min.js`),__vite__mapDeps([8,3]),import.meta.url)},{on:[c===t.results]}),s(()=>{h(()=>import(`./chunk/e2-9fzwE.min.js`),__vite__mapDeps([10,3]),import.meta.url)},{on:[c===t.preferences]});export{e as a,l as i,o as n,n as r,a as t};
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./chunk/BnnvKC7b.min.js","./sxng-mapview.min.css","./chunk/DpvWr1cn.min.js","./chunk/DK4yUVpy.min.js","./chunk/DcK-mo-Y.min.js","./chunk/C8c7HJzp.min.js","./chunk/C93hSkpT.min.js","./chunk/5Ako-qGW.min.js","./chunk/DvCYLbJr.min.js","./chunk/od7pNHfk.min.js","./chunk/e2-9fzwE.min.js"])))=>i.map(i=>d[i]);
var e=class{id;constructor(e){this.id=e,queueMicrotask(()=>this.invoke())}async invoke(){try{console.debug(`[PLUGIN] ${this.id}: Running...`);let e=await this.run();if(!e)return;console.debug(`[PLUGIN] ${this.id}: Running post-exec...`),await this.post(e)}catch(e){console.error(`[PLUGIN] ${this.id}:`,e)}finally{console.debug(`[PLUGIN] ${this.id}: Done.`)}}},t={index:`index`,results:`results`,preferences:`preferences`,unknown:`unknown`},n={closeDetail:void 0,scrollPageToSelected:void 0,selectImage:void 0,selectNext:void 0,selectPrevious:void 0},r=()=>{let e=document.querySelector(`meta[name="endpoint"]`)?.getAttribute(`content`);return e&&e in t?e:t.unknown},i=()=>{let e=document.querySelector(`script[client_settings]`)?.getAttribute(`client_settings`);if(!e)return{};try{return JSON.parse(atob(e))}catch(e){return console.error(`Failed to load client_settings:`,e),{}}},a=async(e,t,n)=>{let r=new AbortController,i=setTimeout(()=>r.abort(),n?.timeout??3e4),a=await fetch(t,{body:n?.body,method:e,signal:r.signal}).finally(()=>clearTimeout(i));if(!a.ok)throw Error(a.statusText);return a},o=(e,t,n,r)=>{if(typeof t!=`string`){t.addEventListener(e,n,r);return}document.addEventListener(e,e=>{for(let r of e.composedPath())if(r instanceof HTMLElement&&r.matches(t)){try{n.call(r,e)}catch(e){console.error(e)}break}},r)},s=(e,t)=>{for(let e of t?.on??[])if(!e)return;document.readyState===`loading`?o(`DOMContentLoaded`,document,e,{once:!0}):e()},c=r(),l=i(),u=(e,t)=>{d(t)&&e()},d=e=>{switch(e.on){case`global`:return!0;case`endpoint`:return!!e.where.includes(c)}},f=`modulepreload`,p=function(e,t){return new URL(e,t).href},m={},h=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=p(t,n),t=s(t),t in m)return;m[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:f,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})};s(()=>{document.documentElement.classList.remove(`no-js`),document.documentElement.classList.add(`js`),o(`click`,`.close`,function(){this.parentNode?.classList.add(`invisible`)}),o(`click`,`.searxng_init_map`,async function(e){e.preventDefault(),this.classList.remove(`searxng_init_map`),u(()=>h(async()=>{let{default:e}=await import(`./chunk/BnnvKC7b.min.js`);return{default:e}},__vite__mapDeps([0,1]),import.meta.url).then(({default:e})=>new e(this)),{on:`endpoint`,where:[t.results]})}),l.plugins?.includes(`infiniteScroll`)&&u(()=>h(async()=>{let{default:e}=await import(`./chunk/DpvWr1cn.min.js`);return{default:e}},__vite__mapDeps([2,3,4]),import.meta.url).then(({default:e})=>new e),{on:`endpoint`,where:[t.results]}),l.plugins?.includes(`calculator`)&&u(()=>h(async()=>{let{default:e}=await import(`./chunk/C8c7HJzp.min.js`);return{default:e}},__vite__mapDeps([5,4,3]),import.meta.url).then(({default:e})=>new e),{on:`endpoint`,where:[t.results]})}),s(()=>{h(()=>import(`./chunk/C93hSkpT.min.js`),__vite__mapDeps([6,3]),import.meta.url),h(()=>import(`./chunk/5Ako-qGW.min.js`),__vite__mapDeps([7,4,3]),import.meta.url),l.autocomplete&&h(()=>import(`./chunk/DvCYLbJr.min.js`),__vite__mapDeps([8,3]),import.meta.url)},{on:[c===t.index]}),s(()=>{h(()=>import(`./chunk/C93hSkpT.min.js`),__vite__mapDeps([6,3]),import.meta.url),h(()=>import(`./chunk/od7pNHfk.min.js`),__vite__mapDeps([9,3]),import.meta.url),h(()=>import(`./chunk/5Ako-qGW.min.js`),__vite__mapDeps([7,4,3]),import.meta.url),l.autocomplete&&h(()=>import(`./chunk/DvCYLbJr.min.js`),__vite__mapDeps([8,3]),import.meta.url)},{on:[c===t.results]}),s(()=>{h(()=>import(`./chunk/e2-9fzwE.min.js`),__vite__mapDeps([10,3]),import.meta.url)},{on:[c===t.preferences]});export{e as a,l as i,o as n,n as r,a as t};
//# sourceMappingURL=sxng-core.min.js.map

File diff suppressed because one or more lines are too long

View File

@@ -60,7 +60,7 @@
</p>
<p class="result-filesize">{{ _label(_("Filesize"), result.filesize) }}</p>
<p class="result-source">{{ _label(_("Source"), result.source) }}</p>
<p class="result-engine">{{ _label(_("Engine"), result.engine) }}</p>
<p class="result-engines">{{ _label(_("Engines"), ", ".join(result.engines)) }}</p>
<p class="result-url"><span>{{ _("View source") }}:</span>{{- "" -}}
<a {{ _target(results_on_new_tab) }} href="{{ result.url }}">{{ result.url }}</a>
</p>

View File

@@ -23,17 +23,16 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-06-19 05:08+0000\n"
"Last-Translator: Raithlin <raithlin@noreply.codeberg.org>\n"
"Language-Team: Afrikaans <https://translate.codeberg.org/projects/searxng/"
"searxng/af/>\n"
"Language: af\n"
"Language-Team: Afrikaans "
"<https://translate.codeberg.org/projects/searxng/searxng/af/>\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 2026.6.1\n"
"Generated-By: Babel 2.18.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -77,7 +76,7 @@ msgid "videos"
msgstr "videos"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "radio"
@@ -551,7 +550,7 @@ msgstr "geantwoord"
msgid "No item found"
msgstr "Geen item gevind"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Bron"
@@ -647,7 +646,7 @@ msgstr "Genereer verskillende ewekansige waardes"
msgid "Compute {func} of the arguments"
msgstr "Bereken {func} van die opsies"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr "Geplaas deur {author}"
@@ -665,19 +664,19 @@ msgstr "{title} (UITGEDIEN)"
msgid "This entry has been superseded by"
msgstr "Hierdie inskrywing was vervang deur"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Kanaal"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "bitsnelheid"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "stemme"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "klikke"
@@ -713,15 +712,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "Die prent kon nie afgelaai word nie."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Taal"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "boekgradering"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Lêer kwaliteit"
@@ -1014,6 +1013,7 @@ msgid "Privacy"
msgstr "Privaatheid"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Enjins"
@@ -1656,10 +1656,6 @@ msgstr "Beeldformate"
msgid "original format"
msgstr "oorspronklike formaat"
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Enjin"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Bekyk bron"
@@ -2166,3 +2162,7 @@ msgstr "versteek video"
#~ msgid "Format"
#~ msgstr "Formaat"
#~ msgid "Engine"
#~ msgstr "Enjin"

View File

@@ -31,20 +31,19 @@
# nebras <nebras@noreply.codeberg.org>, 2026.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-06-28 18:07+0000\n"
"Last-Translator: nebras <nebras@noreply.codeberg.org>\n"
"Language-Team: Arabic <https://translate.codeberg.org/projects/searxng/"
"searxng/ar/>\n"
"Language: ar\n"
"Language-Team: Arabic "
"<https://translate.codeberg.org/projects/searxng/searxng/ar/>\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : "
"n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
"X-Generator: Weblate 2026.6.1\n"
"Generated-By: Babel 2.18.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -88,7 +87,7 @@ msgid "videos"
msgstr "ڤيديوهات"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "إذاعة"
@@ -562,7 +561,7 @@ msgstr "تمت الإجابة"
msgid "No item found"
msgstr "لم يتم العثور على عنصر"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "مصدر"
@@ -658,7 +657,7 @@ msgstr "توليد قِيم عشوائية مختلفة"
msgid "Compute {func} of the arguments"
msgstr "حساب {func} من الحجج"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr "منشور بواسطة {author}"
@@ -676,19 +675,19 @@ msgstr "{title} (قديم)"
msgid "This entry has been superseded by"
msgstr "تم استبدال هذا الإدخال بـ"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "القناة"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "معدل البت"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "تصويتات"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "نقرات"
@@ -722,15 +721,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "لا يمكن تنزيل الصورة."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "اللغة"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "تقييم الكتاب"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "جودة الملف"
@@ -1022,6 +1021,7 @@ msgid "Privacy"
msgstr "الخصوصية"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "المحركات"
@@ -1661,10 +1661,6 @@ msgstr "صيغ الصور"
msgid "original format"
msgstr "الصيغة الاصلية"
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "محرك"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "عرض المصدر"
@@ -2404,3 +2400,7 @@ msgstr "إخفاء الفيديو"
#~ msgid "Format"
#~ msgstr "صيغة"
#~ msgid "Engine"
#~ msgstr "محرك"

View File

@@ -21,18 +21,19 @@
# muha7a <muha7a@noreply.codeberg.org>, 2025.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"PO-Revision-Date: 2026-05-19 12:07+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-07-17 12:20+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language-Team: Bulgarian <https://translate.codeberg.org/projects/searxng/"
"searxng/bg/>\n"
"Language: bg\n"
"Language-Team: Bulgarian "
"<https://translate.codeberg.org/projects/searxng/searxng/bg/>\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 2026.6.1\n"
"Generated-By: Babel 2.18.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -76,7 +77,7 @@ msgid "videos"
msgstr "видео"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "радио"
@@ -550,7 +551,7 @@ msgstr "Отговорено"
msgid "No item found"
msgstr "Не е намерен артикул"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Източник"
@@ -646,7 +647,7 @@ msgstr "Генерирайте различни произволни стойн
msgid "Compute {func} of the arguments"
msgstr "Изчислете {func} на аргументите"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr ""
@@ -664,19 +665,19 @@ msgstr "{title} (ОСТАРЯЛО)"
msgid "This entry has been superseded by"
msgstr "Този запис е заменен от"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Канал"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "Скорост"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "Гласове"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "клика"
@@ -712,15 +713,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "Снимката не може да бъде свалена."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Език"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Рейтинг на книги"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Качество на файл"
@@ -1006,6 +1007,7 @@ msgid "Privacy"
msgstr "Поверителност"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Търсачки"
@@ -1015,7 +1017,7 @@ msgstr "Използвани търсачки в момента"
#: searx/templates/simple/preferences.html:246
msgid "Special Queries"
msgstr "Специялни Запитвания"
msgstr "Специални Запитвания"
#: searx/templates/simple/preferences.html:254
msgid "Cookies"
@@ -1657,10 +1659,6 @@ msgstr ""
msgid "original format"
msgstr ""
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Търсачка"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Покажи източник"
@@ -2404,3 +2402,5 @@ msgstr "скрий видеото"
#~ msgid "Format"
#~ msgstr "Формат"
#~ msgid "Engine"
#~ msgstr "Търсачка"

View File

@@ -29,7 +29,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-05-19 12:07+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language: bn\n"
@@ -82,7 +82,7 @@ msgid "videos"
msgstr "ভিডিও"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "বেতার"
@@ -556,7 +556,7 @@ msgstr "উত্তরকৃত"
msgid "No item found"
msgstr "কোন আইটেম পাওয়া যায়নি"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "উৎস"
@@ -652,7 +652,7 @@ msgstr "বিভিন্ন এলোমেলো মান তৈরি ক
msgid "Compute {func} of the arguments"
msgstr "{func} এই আদেশ কম্পিউট করো"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr ""
@@ -670,19 +670,19 @@ msgstr "{title} (অচল)"
msgid "This entry has been superseded by"
msgstr "এই এনট্রিটি দ্বারা বাতিল করা হয়েছে৷"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "চ্যানেল"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "বিটরেট"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "ভোট"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "ক্লিক সংখ্যা"
@@ -717,15 +717,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "ছবিটি ডাউনলোড করা যায়নি ।"
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "ভাষা"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "বই পর্যালোচনা"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "নথি মান"
@@ -1013,6 +1013,7 @@ msgid "Privacy"
msgstr "গোপনীয়তা"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "ইঞ্জিন"
@@ -1649,10 +1650,6 @@ msgstr ""
msgid "original format"
msgstr ""
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "ইঞ্জিন"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "উৎস দেখুন"
@@ -2162,3 +2159,6 @@ msgstr "ভিডিও লুকিয়ে ফেলুন"
#~ msgid "Format"
#~ msgstr "সজ্জা"
#~ msgid "Engine"
#~ msgstr "ইঞ্জিন"

View File

@@ -13,7 +13,7 @@ msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-05-19 12:07+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language: bo\n"
@@ -66,7 +66,7 @@ msgid "videos"
msgstr "བརྙན་ཟློས།"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr ""
@@ -540,7 +540,7 @@ msgstr ""
msgid "No item found"
msgstr "རྣམ་གྲངས་གང་ཡང་རྙེད་རྒྱུ་མ་བྱུང་།"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr ""
@@ -636,7 +636,7 @@ msgstr "ངེས་མེད་གྲངས་ཀ་ཁ་ཤས་ཐོབ་
msgid "Compute {func} of the arguments"
msgstr ""
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr ""
@@ -654,19 +654,19 @@ msgstr ""
msgid "This entry has been superseded by"
msgstr "འཚོལ་བྱང་འདི་གཞན་གྱིས་ཚབ་བྱེད་འདུག"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr ""
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr ""
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr ""
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr ""
@@ -694,15 +694,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr ""
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr ""
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr ""
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr ""
@@ -980,6 +980,7 @@ msgid "Privacy"
msgstr "མི་སྒེར་གསང་དོན།"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "སྒུལ་བྱེད།"
@@ -1606,10 +1607,6 @@ msgstr ""
msgid "original format"
msgstr ""
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr ""
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "ཡོངས་ཁུངས་ལ་ལྟ།"
@@ -2295,3 +2292,6 @@ msgstr "རྙན་ཟློས་སྦས།"
#~ msgid "Format"
#~ msgstr ""
#~ msgid "Engine"
#~ msgstr ""

View File

@@ -29,19 +29,18 @@
# MaCl0wSt <macl0wst@noreply.codeberg.org>, 2026.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-06-17 20:19+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language-Team: Catalan <https://translate.codeberg.org/projects/searxng/"
"searxng/ca/>\n"
"Language: ca\n"
"Language-Team: Catalan "
"<https://translate.codeberg.org/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 2026.6.1\n"
"Generated-By: Babel 2.18.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -85,7 +84,7 @@ msgid "videos"
msgstr "vídeos"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "radio"
@@ -559,7 +558,7 @@ msgstr "contestat"
msgid "No item found"
msgstr "No s'ha trobat cap element"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Origen"
@@ -655,7 +654,7 @@ msgstr "Genera diferents valors aleatoris"
msgid "Compute {func} of the arguments"
msgstr ""
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr ""
@@ -673,19 +672,19 @@ msgstr "{title} (OBSOLET)"
msgid "This entry has been superseded by"
msgstr "Aquesta entrada ha estat substituïda per"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Canal"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "tasa de bits"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "vots"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "clics"
@@ -720,15 +719,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "No s'ha pogut baixar la imatge."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Llengua"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Valoració de llibre"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Qualitat del fitxer"
@@ -1013,6 +1012,7 @@ msgid "Privacy"
msgstr "Privadesa"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Motors de cerca"
@@ -1658,10 +1658,6 @@ msgstr ""
msgid "original format"
msgstr "format original"
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Cercador"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Veure el codi font"
@@ -2424,3 +2420,7 @@ msgstr "oculta el vídeo"
#~ msgid "Format"
#~ msgstr "Format"
#~ msgid "Engine"
#~ msgstr "Cercador"

View File

@@ -25,20 +25,19 @@
# radekjuthner <radekjuthner@noreply.codeberg.org>, 2025.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-06-16 07:07+0000\n"
"Last-Translator: Fjuro <fjuro@noreply.codeberg.org>\n"
"Language-Team: Czech <https://translate.codeberg.org/projects/searxng/"
"searxng/cs/>\n"
"Language: cs\n"
"Language-Team: Czech "
"<https://translate.codeberg.org/projects/searxng/searxng/cs/>\n"
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && "
"n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n "
"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
"X-Generator: Weblate 2026.6.1\n"
"Generated-By: Babel 2.18.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -82,7 +81,7 @@ msgid "videos"
msgstr "videa"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "rádio"
@@ -556,7 +555,7 @@ msgstr "zodpovězené"
msgid "No item found"
msgstr "Nic nenalezeno"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "zdroj"
@@ -652,7 +651,7 @@ msgstr "Generování náhodných hodnot"
msgid "Compute {func} of the arguments"
msgstr "Vypočítat {func} argumentů"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr "Autor: {author}"
@@ -670,19 +669,19 @@ msgstr "{title} (ZASTARALÉ)"
msgid "This entry has been superseded by"
msgstr "Tato položka byla nahrazena položkou"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Kanál"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "datový tok"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "hlasy"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "kliknutí"
@@ -717,15 +716,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "Obrázek se nepodařilo stáhnout."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Jazyk"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Hodnocení knih"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Množství souborů"
@@ -1016,6 +1015,7 @@ msgid "Privacy"
msgstr "Soukromí"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Vyhledávače"
@@ -1659,10 +1659,6 @@ msgstr "Formáty obrázků"
msgid "original format"
msgstr "původní formát"
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Vyhledávač"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Zobrazit zdroj"
@@ -2410,3 +2406,7 @@ msgstr "skrýt video"
#~ msgid "Format"
#~ msgstr "Formát"
#~ msgid "Engine"
#~ msgstr "Vyhledávač"

View File

@@ -20,7 +20,7 @@ msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-05-19 12:07+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language: cy\n"
@@ -74,7 +74,7 @@ msgid "videos"
msgstr "fideos"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "radio"
@@ -548,7 +548,7 @@ msgstr "wedi'i ateb"
msgid "No item found"
msgstr "Ni chanfuwyd eitem"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Ffynhonnell"
@@ -644,7 +644,7 @@ msgstr "Cynhyrchu gwahanol werthoedd ar hap"
msgid "Compute {func} of the arguments"
msgstr ""
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr ""
@@ -662,19 +662,19 @@ msgstr "{title} (OBSOLETE)"
msgid "This entry has been superseded by"
msgstr "Mae'r cofnod hwn wedi ei ddisodli gan"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Sianel"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "cyfradd didau"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "pleidleisiau"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "cliciau"
@@ -710,15 +710,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "Doedd dim modd islwytho'r ddelwedd."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Iaith"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Gradd llyfr"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "ansawdd ffeil"
@@ -1003,6 +1003,7 @@ msgid "Privacy"
msgstr "Preifatrwydd"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Peiriannau"
@@ -1638,10 +1639,6 @@ msgstr ""
msgid "original format"
msgstr ""
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Peiriant"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Gweld y ffynhonnell"
@@ -2363,3 +2360,6 @@ msgstr "cuddio'r fideo"
#~ msgid "Format"
#~ msgstr "Fformat"
#~ msgid "Engine"
#~ msgstr "Peiriant"

View File

@@ -17,19 +17,18 @@
# return42 <return42@noreply.codeberg.org>, 2025, 2026.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-06-16 07:07+0000\n"
"Last-Translator: AndersNordh <andersnordh@noreply.codeberg.org>\n"
"Language-Team: Danish <https://translate.codeberg.org/projects/searxng/"
"searxng/da/>\n"
"Language: da\n"
"Language-Team: Danish "
"<https://translate.codeberg.org/projects/searxng/searxng/da/>\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 2026.6.1\n"
"Generated-By: Babel 2.18.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -73,7 +72,7 @@ msgid "videos"
msgstr "videoer"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "Radio"
@@ -547,7 +546,7 @@ msgstr "svaret"
msgid "No item found"
msgstr "Intet fundet"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Kilde"
@@ -643,7 +642,7 @@ msgstr "Generér forskellige tilfældige værdier"
msgid "Compute {func} of the arguments"
msgstr "Beregn {func} af argumenterne"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr "Indsendt af {author}"
@@ -661,19 +660,19 @@ msgstr "{title} (FORÆLDET)"
msgid "This entry has been superseded by"
msgstr "Denne værdi er blevet overskrevet af"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Kanal"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "Bitrate"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "Stemmer"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "Klik"
@@ -709,15 +708,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "Dette billede kunne ikke downloades."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Sprog"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Bogbedømmelse"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Filkvalitet"
@@ -1010,6 +1009,7 @@ msgid "Privacy"
msgstr "Privatliv"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Søgemaskiner"
@@ -1655,10 +1655,6 @@ msgstr "Billedformater"
msgid "original format"
msgstr "originalt format"
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Maskine"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Vis kilde"
@@ -2419,3 +2415,7 @@ msgstr "skjul video"
#~ msgid "Format"
#~ msgstr "Format"
#~ msgid "Engine"
#~ msgstr "Maskine"

View File

@@ -32,19 +32,18 @@
# Serpensin <serpensin@noreply.codeberg.org>, 2026.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-06-17 20:19+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language-Team: German <https://translate.codeberg.org/projects/searxng/"
"searxng/de/>\n"
"Language: de\n"
"Language-Team: German "
"<https://translate.codeberg.org/projects/searxng/searxng/de/>\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 2026.6.1\n"
"Generated-By: Babel 2.18.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -88,7 +87,7 @@ msgid "videos"
msgstr "Videos"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "Radio"
@@ -562,7 +561,7 @@ msgstr "beantwortet"
msgid "No item found"
msgstr "Keine Einträge gefunden"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Quelle"
@@ -658,7 +657,7 @@ msgstr "Erzeugt diverse Zufallswerte"
msgid "Compute {func} of the arguments"
msgstr "Berechne {func} zu den Argumenten"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr "Beitrag von {author}"
@@ -676,19 +675,19 @@ msgstr "{title} (OBSOLET)"
msgid "This entry has been superseded by"
msgstr "Dieser Eintrag wurde überschrieben von"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Kanal"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "Bitrate"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "Stimmen"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "Clicks"
@@ -724,15 +723,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "Das Bild konnte nicht heruntergeladen werden."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Sprache"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Buchbewertung"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Dateiqualität"
@@ -1031,6 +1030,7 @@ msgid "Privacy"
msgstr "Privatsphäre"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Suchmaschinen"
@@ -1674,10 +1674,6 @@ msgstr "Bildformate"
msgid "original format"
msgstr "Originalformat"
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Suchmaschine"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Seite besuchen"
@@ -2466,3 +2462,7 @@ msgstr "Video verstecken"
#~ msgid "Format"
#~ msgstr "Format"
#~ msgid "Engine"
#~ msgstr "Suchmaschine"

View File

@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2025-08-13 08:09+0000\n"
"Last-Translator: ijxp <ijxp@noreply.codeberg.org>\n"
"Language: dv\n"
@@ -63,7 +63,7 @@ msgid "videos"
msgstr "ވީޑިޔޯތައް"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "ރޭޑިއޯ އިންނެވެ"
@@ -537,7 +537,7 @@ msgstr ""
msgid "No item found"
msgstr ""
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr ""
@@ -633,7 +633,7 @@ msgstr ""
msgid "Compute {func} of the arguments"
msgstr ""
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr ""
@@ -651,19 +651,19 @@ msgstr ""
msgid "This entry has been superseded by"
msgstr ""
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr ""
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr ""
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr ""
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr ""
@@ -691,15 +691,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr ""
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr ""
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr ""
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr ""
@@ -977,6 +977,7 @@ msgid "Privacy"
msgstr ""
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr ""
@@ -1601,10 +1602,6 @@ msgstr ""
msgid "original format"
msgstr ""
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr ""
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr ""
@@ -2026,3 +2023,6 @@ msgstr ""
#~ msgid "Format"
#~ msgstr ""
#~ msgid "Engine"
#~ msgstr ""

View File

@@ -23,19 +23,18 @@
# gkalathas <gkalathas@noreply.codeberg.org>, 2025.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-06-17 20:19+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language-Team: Greek <https://translate.codeberg.org/projects/searxng/"
"searxng/el/>\n"
"Language: el_GR\n"
"Language-Team: Greek "
"<https://translate.codeberg.org/projects/searxng/searxng/el/>\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 2026.6.1\n"
"Generated-By: Babel 2.18.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -79,7 +78,7 @@ msgid "videos"
msgstr "Βίντεο"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "ράδιο"
@@ -553,7 +552,7 @@ msgstr "απάντησε"
msgid "No item found"
msgstr "Δεν βρέθηκαν αντικείμενα"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Πηγή"
@@ -649,7 +648,7 @@ msgstr "Δημιουργία διαφορετικών τυχαίων τιμών"
msgid "Compute {func} of the arguments"
msgstr "Υπολογίστε τη {func} των ορισμάτων"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr "Δημοσιεύτηκε απο {author}"
@@ -667,19 +666,19 @@ msgstr "{title} (ΠΑΡΩΧΗΜΕΝΟΣ)"
msgid "This entry has been superseded by"
msgstr "Αυτή η καταχώριση έχει αντικατασταθεί από"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Κανάλι"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "ρυθμός μετάδοσης"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "ψήφους"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "κλικ"
@@ -715,15 +714,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "Αποτυχία μεταφόρτωσης εικόνας."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Γλώσσα"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Βαθμολογία βιβλίου"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Ποιότητα αρχείου"
@@ -1016,6 +1015,7 @@ msgid "Privacy"
msgstr "Ιδιωτικότητα"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Μηχανές"
@@ -1669,10 +1669,6 @@ msgstr ""
msgid "original format"
msgstr ""
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Μηχανή"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Προβολή πηγής"
@@ -2439,3 +2435,7 @@ msgstr "απόκρυψη βίντεο"
#~ msgid "Format"
#~ msgstr "Μορφή"
#~ msgid "Engine"
#~ msgstr "Μηχανή"

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2014-01-30 15:22+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n"
@@ -59,7 +59,7 @@ msgid "videos"
msgstr ""
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr ""
@@ -533,7 +533,7 @@ msgstr ""
msgid "No item found"
msgstr ""
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr ""
@@ -629,7 +629,7 @@ msgstr ""
msgid "Compute {func} of the arguments"
msgstr ""
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr ""
@@ -647,19 +647,19 @@ msgstr ""
msgid "This entry has been superseded by"
msgstr ""
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr ""
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr ""
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr ""
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr ""
@@ -687,15 +687,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr ""
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr ""
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr ""
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr ""
@@ -973,6 +973,7 @@ msgid "Privacy"
msgstr ""
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr ""
@@ -1597,10 +1598,6 @@ msgstr ""
msgid "original format"
msgstr ""
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr ""
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr ""
@@ -2287,3 +2284,6 @@ msgstr ""
#~ msgid "Format"
#~ msgstr ""
#~ msgid "Engine"
#~ msgstr ""

View File

@@ -23,7 +23,7 @@ msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-05-19 12:07+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language: eo\n"
@@ -76,7 +76,7 @@ msgid "videos"
msgstr "videoj"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "radio"
@@ -550,7 +550,7 @@ msgstr ""
msgid "No item found"
msgstr "Nenio trovita"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Fonto"
@@ -646,7 +646,7 @@ msgstr "Generi diversajn hazardajn valorojn"
msgid "Compute {func} of the arguments"
msgstr ""
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr ""
@@ -664,19 +664,19 @@ msgstr "{title} (MALAKTUALA)"
msgid "This entry has been superseded by"
msgstr "Tiu ĉi enigo estis anstataŭigita per"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Kanalo"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "bito-rapido"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "voĉoj"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "klakoj"
@@ -711,15 +711,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "La bildo ne eblis elŝuti."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Lingvo"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Taksado de libro"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Dosiera kvalito"
@@ -1002,6 +1002,7 @@ msgid "Privacy"
msgstr "Privateco"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Serĉiloj"
@@ -1640,10 +1641,6 @@ msgstr ""
msgid "original format"
msgstr ""
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Serĉilo"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Vidi fonton"
@@ -2375,3 +2372,6 @@ msgstr "kaŝi videojn"
#~ msgid "Format"
#~ msgstr "Formato"
#~ msgid "Engine"
#~ msgstr "Serĉilo"

View File

@@ -50,19 +50,18 @@
# gallegonovato <gallegonovato@noreply.codeberg.org>, 2025, 2026.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-06-14 13:07+0000\n"
"Last-Translator: gallegonovato <gallegonovato@noreply.codeberg.org>\n"
"Language-Team: Spanish <https://translate.codeberg.org/projects/searxng/"
"searxng/es/>\n"
"Language: es\n"
"Language-Team: Spanish "
"<https://translate.codeberg.org/projects/searxng/searxng/es/>\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 2026.6.1\n"
"Generated-By: Babel 2.18.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -106,7 +105,7 @@ msgid "videos"
msgstr "vídeos"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "radio"
@@ -580,7 +579,7 @@ msgstr "contestado"
msgid "No item found"
msgstr "Ningún artículo encontrado"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Fuente"
@@ -676,7 +675,7 @@ msgstr "Generar varios valores aleatorios"
msgid "Compute {func} of the arguments"
msgstr "Calcular {func} de los argumentos"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr "Publicado por {author}"
@@ -694,19 +693,19 @@ msgstr "{title} (OBSOLETO)"
msgid "This entry has been superseded by"
msgstr "Esta entrada ha sido sustituida por"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Canal"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "bitrate"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "votos"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "clics"
@@ -741,15 +740,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "No se pudo descargar la imagen."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Idioma"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Valoración del libro"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Calidad del archivo"
@@ -1042,6 +1041,7 @@ msgid "Privacy"
msgstr "Privacidad"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Motores"
@@ -1688,10 +1688,6 @@ msgstr "Formatos de imagen"
msgid "original format"
msgstr "formato original"
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Motor"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Ver fuente"
@@ -2463,3 +2459,7 @@ msgstr "ocultar video"
#~ msgid "Format"
#~ msgstr "Formato"
#~ msgid "Engine"
#~ msgstr "Motor"

View File

@@ -19,19 +19,18 @@
# return42 <return42@noreply.codeberg.org>, 2025.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-06-14 13:07+0000\n"
"Last-Translator: Priit Jõerüüt <jrtcdbrg@noreply.codeberg.org>\n"
"Language-Team: Estonian <https://translate.codeberg.org/projects/searxng/"
"searxng/et/>\n"
"Language: et\n"
"Language-Team: Estonian "
"<https://translate.codeberg.org/projects/searxng/searxng/et/>\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 2026.6.1\n"
"Generated-By: Babel 2.18.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -75,7 +74,7 @@ msgid "videos"
msgstr "videod"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "raadio"
@@ -549,7 +548,7 @@ msgstr "vastatud"
msgid "No item found"
msgstr "Üksust ei leitud"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Allikas"
@@ -645,7 +644,7 @@ msgstr "Genereeri erinevaid juhuslikke väärtusi"
msgid "Compute {func} of the arguments"
msgstr "Arvuta argumentidest {func}"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr "Postituse autor on {author}"
@@ -663,19 +662,19 @@ msgstr "{title} (VANANENUD)"
msgid "This entry has been superseded by"
msgstr "See üksus on asendatud"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Kanal"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "bitikiirus"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "hääled"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "klikid"
@@ -710,15 +709,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "Pilti ei saanud alla laadida."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Keel"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Raamatu hinnang"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Faili kvaliteet"
@@ -1011,6 +1010,7 @@ msgid "Privacy"
msgstr "Privaatsus"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Otsingumootorid"
@@ -1653,10 +1653,6 @@ msgstr "Pildivormingud"
msgid "original format"
msgstr "algne vorming"
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Otsingumootor"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Vaata lähtekoodi"
@@ -2397,3 +2393,7 @@ msgstr "peida video"
#~ msgid "Format"
#~ msgstr "Vorming"
#~ msgid "Engine"
#~ msgstr "Otsingumootor"

View File

@@ -20,7 +20,7 @@ msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-05-01 07:50+0000\n"
"Last-Translator: alexgabi <alexgabi@noreply.codeberg.org>\n"
"Language: eu\n"
@@ -73,7 +73,7 @@ msgid "videos"
msgstr "bideoak"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "irratia"
@@ -547,7 +547,7 @@ msgstr "erantzunda"
msgid "No item found"
msgstr "Ez da elementurik aurkitu"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Iturria"
@@ -643,7 +643,7 @@ msgstr "Ausazko balio ezberdinak sortu"
msgid "Compute {func} of the arguments"
msgstr "Kalkulatu argumentuen {func}"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr "{author}-k argitaratuta"
@@ -661,19 +661,19 @@ msgstr "{title} (ZAHARKITUA)"
msgid "This entry has been superseded by"
msgstr "Sarrera hau hurrengoarekin ordezkatu da"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Kanala"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "bit emaria"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "botoak"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "klikak"
@@ -708,15 +708,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "Ezin izan da deskargatu irudia."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Hizkuntza"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Liburuaren balorazioa"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Fitxategiaren kalitatea"
@@ -1007,6 +1007,7 @@ msgid "Privacy"
msgstr "Pribatutasuna"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Bilatzaileak"
@@ -1651,10 +1652,6 @@ msgstr ""
msgid "original format"
msgstr ""
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Bilatzailea"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Ikusi iturria"
@@ -2395,3 +2392,6 @@ msgstr "ezkutatu bideoa"
#~ msgid "Format"
#~ msgstr "Formatua"
#~ msgid "Engine"
#~ msgstr "Bilatzailea"

View File

@@ -29,7 +29,7 @@ msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-05-19 12:07+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language: fa_IR\n"
@@ -82,7 +82,7 @@ msgid "videos"
msgstr "ویدیوها"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "رادیو"
@@ -556,7 +556,7 @@ msgstr "جواب داده شده"
msgid "No item found"
msgstr "چیزی پیدا نشد"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "منبع"
@@ -652,7 +652,7 @@ msgstr "ایجاد مقادیر تصادفی متفاوت"
msgid "Compute {func} of the arguments"
msgstr "Compute {func} of the arguments"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr ""
@@ -670,19 +670,19 @@ msgstr "{title} (منسوخ شده)"
msgid "This entry has been superseded by"
msgstr "این ورودی معلق شده است، توسط"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "کانال"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "بیت ریت"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "رای ها"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "کلیک ها"
@@ -717,15 +717,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "تصویر نمیتواند دانلود شود."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "زبان"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "رتبه بندی کتاب"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "کیفیت فایل"
@@ -1010,6 +1010,7 @@ msgid "Privacy"
msgstr "حریم شخصی"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "موتورها"
@@ -1650,10 +1651,6 @@ msgstr ""
msgid "original format"
msgstr ""
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "موتور"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "نمایش منبع"
@@ -2407,3 +2404,6 @@ msgstr "پنهان‌سازی ویدئو"
#~ msgid "Format"
#~ msgstr "قالب"
#~ msgid "Engine"
#~ msgstr "موتور"

View File

@@ -23,7 +23,7 @@ msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-13 11:31+0000\n"
"POT-Creation-Date: 2026-07-15 15:45+0000\n"
"PO-Revision-Date: 2026-05-19 12:07+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language: fi\n"
@@ -76,7 +76,7 @@ msgid "videos"
msgstr "videot"
#. CATEGORY_NAMES['RADIO']
#: searx/engines/radio_browser.py:159 searx/searxng.msg
#: searx/engines/radio_browser.py:160 searx/searxng.msg
msgid "radio"
msgstr "radio"
@@ -550,7 +550,7 @@ msgstr "vastattu"
msgid "No item found"
msgstr "Tietuetta ei löytynyt"
#: searx/engines/qwant.py:258
#: searx/engines/qwant.py:286
#: searx/templates/simple/result_templates/images.html:62 searx/webapp.py:328
msgid "Source"
msgstr "Lähde"
@@ -646,7 +646,7 @@ msgstr "Generoi satunnaislukuja"
msgid "Compute {func} of the arguments"
msgstr "Laske argumenteista {func}"
#: searx/engines/boardreader.py:107
#: searx/engines/boardreader.py:108
#, python-brace-format
msgid "Posted by {author}"
msgstr "Lähettäjä {author}"
@@ -664,19 +664,19 @@ msgstr "{title} (VANHENTUNUT)"
msgid "This entry has been superseded by"
msgstr "Tämän kohdan on korvannut"
#: searx/engines/qwant.py:260
#: searx/engines/qwant.py:288
msgid "Channel"
msgstr "Kanava"
#: searx/engines/radio_browser.py:161
#: searx/engines/radio_browser.py:162
msgid "bitrate"
msgstr "bittinopeus"
#: searx/engines/radio_browser.py:162
#: searx/engines/radio_browser.py:163
msgid "votes"
msgstr "ääntä"
#: searx/engines/radio_browser.py:163
#: searx/engines/radio_browser.py:164
msgid "clicks"
msgstr "klikkaukset"
@@ -711,15 +711,15 @@ msgstr ""
msgid "The image could not be downloaded."
msgstr "Tätä kuvaa ei voida ladata."
#: searx/engines/zlibrary.py:79
#: searx/engines/zlibrary.py:80
msgid "Language"
msgstr "Kieli"
#: searx/engines/zlibrary.py:80
#: searx/engines/zlibrary.py:81
msgid "Book rating"
msgstr "Kirjan arvostelu"
#: searx/engines/zlibrary.py:81
#: searx/engines/zlibrary.py:82
msgid "File quality"
msgstr "Tiedoston laatu"
@@ -1012,6 +1012,7 @@ msgid "Privacy"
msgstr "Yksityisyys"
#: searx/templates/simple/preferences.html:235
#: searx/templates/simple/result_templates/images.html:63
msgid "Engines"
msgstr "Hakukoneet"
@@ -1655,10 +1656,6 @@ msgstr ""
msgid "original format"
msgstr ""
#: searx/templates/simple/result_templates/images.html:63
msgid "Engine"
msgstr "Hakukone"
#: searx/templates/simple/result_templates/images.html:64
msgid "View source"
msgstr "Näytä lähde"
@@ -2414,3 +2411,6 @@ msgstr "piilota video"
#~ msgid "Format"
#~ msgstr "Muoto"
#~ msgid "Engine"
#~ msgstr "Hakukone"

Some files were not shown because too many files have changed in this diff Show More