forked from Icycoide/searxng
Merge pull request 'master' (#2) from Icycoide/searxng:master into master
Reviewed-on: #2
This commit is contained in:
commit
7182190057
186 changed files with 4107 additions and 3923 deletions
10
.github/workflows/cleanup.yml
vendored
10
.github/workflows/cleanup.yml
vendored
|
@ -5,7 +5,7 @@ name: Cleanup
|
|||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "4 4 * * 0"
|
||||
- cron: "4 4 * * *"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
|
@ -16,6 +16,8 @@ permissions:
|
|||
|
||||
jobs:
|
||||
container-cache:
|
||||
# FIXME: On forks it fails with "Failed to fetch packages: missing field `id` at line 1 column 141"
|
||||
if: github.repository_owner == 'searxng' || github.event_name == 'workflow_dispatch'
|
||||
name: Container cache
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
|
@ -28,7 +30,7 @@ jobs:
|
|||
with:
|
||||
account: "${{ github.repository_owner }}"
|
||||
token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
image-names: "cache"
|
||||
image-tags: "!searxng-*"
|
||||
cut-off: "1w"
|
||||
image-names: "cache base"
|
||||
image-tags: "!searxng*"
|
||||
cut-off: "1d"
|
||||
keep-n-most-recent: "100"
|
||||
|
|
75
.github/workflows/container.yml
vendored
75
.github/workflows/container.yml
vendored
|
@ -25,10 +25,83 @@ env:
|
|||
PYTHON_VERSION: "3.13"
|
||||
|
||||
jobs:
|
||||
build-base:
|
||||
if: |
|
||||
(github.repository_owner == 'searxng' && github.event.workflow_run.conclusion == 'success')
|
||||
|| github.event_name == 'workflow_dispatch'
|
||||
name: Build base
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
# Organization GHCR
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- if: github.repository_owner == 'searxng'
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: "false"
|
||||
|
||||
- if: github.repository_owner == 'searxng'
|
||||
name: Get date
|
||||
id: date
|
||||
run: echo "date=$(date +'%Y%m%d')" >>$GITHUB_OUTPUT
|
||||
|
||||
- if: github.repository_owner == 'searxng'
|
||||
name: Check cache apko
|
||||
id: cache-apko
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
# yamllint disable-line rule:line-length
|
||||
key: "apko-${{ steps.date.outputs.date }}-${{ hashFiles('./container/base.yml', './container/base-builder.yml') }}"
|
||||
path: "/tmp/.apko/"
|
||||
lookup-only: true
|
||||
|
||||
- if: github.repository_owner == 'searxng' && steps.cache-apko.outputs.cache-hit != 'true'
|
||||
name: Setup cache apko
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
# yamllint disable-line rule:line-length
|
||||
key: "apko-${{ steps.date.outputs.date }}-${{ hashFiles('./container/base.yml', './container/base-builder.yml') }}"
|
||||
restore-keys: "apko-${{ steps.date.outputs.date }}-"
|
||||
path: "/tmp/.apko/"
|
||||
|
||||
- if: github.repository_owner == 'searxng' && steps.cache-apko.outputs.cache-hit != 'true'
|
||||
name: Setup apko
|
||||
run: |
|
||||
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
|
||||
brew install apko
|
||||
|
||||
- if: github.repository_owner == 'searxng' && steps.cache-apko.outputs.cache-hit != 'true'
|
||||
name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: "ghcr.io"
|
||||
username: "${{ github.repository_owner }}"
|
||||
password: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
- if: github.repository_owner == 'searxng' && steps.cache-apko.outputs.cache-hit != 'true'
|
||||
name: Build
|
||||
run: |
|
||||
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
|
||||
|
||||
apko publish ./container/base.yml ghcr.io/${{ github.repository_owner }}/base:searxng \
|
||||
--cache-dir=/tmp/.apko/ \
|
||||
--sbom=false \
|
||||
--vcs=false \
|
||||
--log-level=debug
|
||||
|
||||
apko publish ./container/base-builder.yml ghcr.io/${{ github.repository_owner }}/base:searxng-builder \
|
||||
--cache-dir=/tmp/.apko/ \
|
||||
--sbom=false \
|
||||
--vcs=false \
|
||||
--log-level=debug
|
||||
|
||||
build:
|
||||
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
|
||||
if: github.repository_owner == 'searxng' || github.event_name == 'workflow_dispatch'
|
||||
name: Build (${{ matrix.arch }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: build-base
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
3
.github/workflows/security.yml
vendored
3
.github/workflows/security.yml
vendored
|
@ -16,6 +16,7 @@ permissions:
|
|||
|
||||
jobs:
|
||||
container:
|
||||
if: github.repository_owner == 'searxng'
|
||||
name: Container
|
||||
runs-on: ubuntu-24.04-arm
|
||||
permissions:
|
||||
|
@ -30,7 +31,7 @@ jobs:
|
|||
- name: Run Trivy scanner
|
||||
uses: aquasecurity/trivy-action@0.30.0
|
||||
with:
|
||||
image-ref: "docker.io/searxng/searxng:latest"
|
||||
image-ref: "ghcr.io/searxng/searxng:latest"
|
||||
vuln-type: "os,library"
|
||||
severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
|
||||
ignore-unfixed: "false"
|
||||
|
|
2
Makefile
2
Makefile
|
@ -54,7 +54,7 @@ ci.test: test.yamllint test.black test.types.ci test.pylint test.unit test.robo
|
|||
test: test.yamllint test.black test.types.dev test.pylint test.unit test.robot test.rst test.shell
|
||||
test.shell:
|
||||
$(Q)shellcheck -x -s dash \
|
||||
container/docker-entrypoint.sh
|
||||
container/entrypoint.sh
|
||||
$(Q)shellcheck -x -s bash \
|
||||
utils/brand.sh \
|
||||
$(MTOOLS) \
|
||||
|
|
1214
client/simple/package-lock.json
generated
1214
client/simple/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -9,33 +9,30 @@
|
|||
"icons.html": "node theme_icons.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.26.0",
|
||||
"@eslint/js": "^9.27.0",
|
||||
"copy-webpack-plugin": "^13.0.0",
|
||||
"css-loader": "^7.1.2",
|
||||
"edge.js": "^6.2.1",
|
||||
"eslint": "^9.26.0",
|
||||
"eslint": "^9.27.0",
|
||||
"filemanager-webpack-plugin": "^8.0.0",
|
||||
"globals": "^16.1.0",
|
||||
"globals": "^16.2.0",
|
||||
"ionicons": "^8.0.8",
|
||||
"leaflet": "^1.9.4",
|
||||
"less": "^4.3.0",
|
||||
"less-loader": "^12.3.0",
|
||||
"normalize.css": "^8.0.1",
|
||||
"sharp": "^0.34.1",
|
||||
"sharp": "^0.34.2",
|
||||
"style-loader": "^4.0.0",
|
||||
"stylelint": "^16.19.1",
|
||||
"stylelint": "^16.20.0",
|
||||
"stylelint-config-standard": "^38.0.0",
|
||||
"stylelint-config-standard-less": "^3.0.1",
|
||||
"stylelint-prettier": "^5.0.3",
|
||||
"svgo": "^3.3.2",
|
||||
"swiped-events": "^1.2.0",
|
||||
"vite": "^6.3.5",
|
||||
"vite-plugin-static-copy": "^2.3.1",
|
||||
"vite-plugin-static-copy": "^3.0.0",
|
||||
"vite-plugin-stylelint": "^6.0.0",
|
||||
"webpack": "^5.99.8",
|
||||
"webpack": "^5.99.9",
|
||||
"webpack-cli": "^6.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"autocomplete-js": "^2.7.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
||||
/* exported AutoComplete */
|
||||
|
||||
import AutoComplete from "../../../node_modules/autocomplete-js/dist/autocomplete.js";
|
||||
|
||||
(function (w, d, searxng) {
|
||||
'use strict';
|
||||
|
||||
var qinput_id = "q", qinput;
|
||||
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 50em)").matches;
|
||||
const isResultsPage = document.querySelector("main").id == "main_results";
|
||||
|
||||
function submitIfQuery () {
|
||||
if (qinput.value.length > 0) {
|
||||
|
@ -38,8 +37,62 @@ import AutoComplete from "../../../node_modules/autocomplete-js/dist/autocomple
|
|||
qinput.addEventListener('input', updateClearButton, false);
|
||||
}
|
||||
|
||||
const fetchResults = async (query) => {
|
||||
let request;
|
||||
if (searxng.settings.method === 'GET') {
|
||||
const reqParams = new URLSearchParams();
|
||||
reqParams.append("q", query);
|
||||
request = fetch("./autocompleter?" + reqParams.toString());
|
||||
} else {
|
||||
const formData = new FormData();
|
||||
formData.append("q", query);
|
||||
request = fetch("./autocompleter", {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
}
|
||||
|
||||
request.then(async function (response) {
|
||||
const results = await response.json();
|
||||
|
||||
if (!results) return;
|
||||
|
||||
const autocomplete = d.querySelector(".autocomplete");
|
||||
const autocompleteList = d.querySelector(".autocomplete ul");
|
||||
autocomplete.classList.add("open");
|
||||
autocompleteList.innerHTML = "";
|
||||
|
||||
// show an error message that no result was found
|
||||
if (!results[1] || results[1].length == 0) {
|
||||
const noItemFoundMessage = document.createElement("li");
|
||||
noItemFoundMessage.classList.add('no-item-found');
|
||||
noItemFoundMessage.innerHTML = searxng.settings.translations.no_item_found;
|
||||
autocompleteList.appendChild(noItemFoundMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
for (let result of results[1]) {
|
||||
const li = document.createElement("li");
|
||||
li.innerText = result;
|
||||
|
||||
searxng.on(li, 'mousedown', () => {
|
||||
qinput.value = result;
|
||||
const form = d.querySelector("#search");
|
||||
form.submit();
|
||||
autocomplete.classList.remove('open');
|
||||
});
|
||||
autocompleteList.appendChild(li);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
searxng.ready(function () {
|
||||
// focus search input on large screens
|
||||
if (!isMobile && !isResultsPage) document.getElementById("q").focus();
|
||||
|
||||
qinput = d.getElementById(qinput_id);
|
||||
const autocomplete = d.querySelector(".autocomplete");
|
||||
const autocompleteList = d.querySelector(".autocomplete ul");
|
||||
|
||||
if (qinput !== null) {
|
||||
// clear button
|
||||
|
@ -47,109 +100,45 @@ import AutoComplete from "../../../node_modules/autocomplete-js/dist/autocomple
|
|||
|
||||
// autocompleter
|
||||
if (searxng.settings.autocomplete) {
|
||||
searxng.autocomplete = AutoComplete.call(w, {
|
||||
Url: "./autocompleter",
|
||||
EmptyMessage: searxng.settings.translations.no_item_found,
|
||||
HttpMethod: searxng.settings.method,
|
||||
HttpHeaders: {
|
||||
"Content-type": "application/x-www-form-urlencoded",
|
||||
"X-Requested-With": "XMLHttpRequest"
|
||||
},
|
||||
MinChars: searxng.settings.autocomplete_min,
|
||||
Delay: 300,
|
||||
_Position: function () {},
|
||||
_Open: function () {
|
||||
var params = this;
|
||||
Array.prototype.forEach.call(this.DOMResults.getElementsByTagName("li"), function (li) {
|
||||
if (li.getAttribute("class") != "locked") {
|
||||
li.onmousedown = function () {
|
||||
params._Select(li);
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
_Select: function (item) {
|
||||
AutoComplete.defaults._Select.call(this, item);
|
||||
var form = item.closest('form');
|
||||
if (form) {
|
||||
form.submit();
|
||||
searxng.on(qinput, 'input', () => {
|
||||
const query = qinput.value;
|
||||
if (query.length < searxng.settings.autocomplete_min) return;
|
||||
|
||||
setTimeout(() => {
|
||||
if (query == qinput.value) fetchResults(query);
|
||||
}, 300);
|
||||
});
|
||||
|
||||
searxng.on(qinput, 'keyup', (e) => {
|
||||
let currentIndex = -1;
|
||||
const listItems = autocompleteList.children;
|
||||
for (let i = 0; i < listItems.length; i++) {
|
||||
if (listItems[i].classList.contains('active')) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
},
|
||||
_MinChars: function () {
|
||||
if (this.Input.value.indexOf('!') > -1) {
|
||||
return 0;
|
||||
} else {
|
||||
return AutoComplete.defaults._MinChars.call(this);
|
||||
}
|
||||
},
|
||||
KeyboardMappings: Object.assign({}, AutoComplete.defaults.KeyboardMappings, {
|
||||
"KeyUpAndDown_up": Object.assign({}, AutoComplete.defaults.KeyboardMappings.KeyUpAndDown_up, {
|
||||
Callback: function (event) {
|
||||
AutoComplete.defaults.KeyboardMappings.KeyUpAndDown_up.Callback.call(this, event);
|
||||
var liActive = this.DOMResults.querySelector("li.active");
|
||||
if (liActive) {
|
||||
AutoComplete.defaults._Select.call(this, liActive);
|
||||
}
|
||||
},
|
||||
}),
|
||||
"Tab": Object.assign({}, AutoComplete.defaults.KeyboardMappings.Enter, {
|
||||
Conditions: [{
|
||||
Is: 9,
|
||||
Not: false
|
||||
}],
|
||||
Callback: function (event) {
|
||||
if (this.DOMResults.getAttribute("class").indexOf("open") != -1) {
|
||||
var liActive = this.DOMResults.querySelector("li.active");
|
||||
if (liActive !== null) {
|
||||
AutoComplete.defaults._Select.call(this, liActive);
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}),
|
||||
}, "#" + qinput_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Monkey patch autocomplete.js to fix a bug
|
||||
With the POST method, the values are not URL encoded: query like "1 + 1" are sent as "1 1" since space are URL encoded as plus.
|
||||
See HTML specifications:
|
||||
* HTML5: https://url.spec.whatwg.org/#concept-urlencoded-serializer
|
||||
* HTML4: https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
|
||||
|
||||
autocomplete.js does not URL encode the name and values:
|
||||
https://github.com/autocompletejs/autocomplete.js/blob/87069524f3b95e68f1b54d8976868e0eac1b2c83/src/autocomplete.ts#L665
|
||||
|
||||
The monkey patch overrides the compiled version of the ajax function.
|
||||
See https://github.com/autocompletejs/autocomplete.js/blob/87069524f3b95e68f1b54d8976868e0eac1b2c83/dist/autocomplete.js#L143-L158
|
||||
The patch changes only the line 156 from
|
||||
params.Request.send(params._QueryArg() + "=" + params._Pre());
|
||||
to
|
||||
params.Request.send(encodeURIComponent(params._QueryArg()) + "=" + encodeURIComponent(params._Pre()));
|
||||
|
||||
Related to:
|
||||
* https://github.com/autocompletejs/autocomplete.js/issues/78
|
||||
* https://github.com/searxng/searxng/issues/1695
|
||||
*/
|
||||
AutoComplete.prototype.ajax = function (params, request, timeout) {
|
||||
if (timeout === void 0) { timeout = true; }
|
||||
if (params.$AjaxTimer) {
|
||||
window.clearTimeout(params.$AjaxTimer);
|
||||
}
|
||||
if (timeout === true) {
|
||||
params.$AjaxTimer = window.setTimeout(AutoComplete.prototype.ajax.bind(null, params, request, false), params.Delay);
|
||||
} else {
|
||||
if (params.Request) {
|
||||
params.Request.abort();
|
||||
}
|
||||
params.Request = request;
|
||||
params.Request.send(encodeURIComponent(params._QueryArg()) + "=" + encodeURIComponent(params._Pre()));
|
||||
}
|
||||
};
|
||||
|
||||
if (!isMobile && document.querySelector('.index_endpoint')) {
|
||||
qinput.focus();
|
||||
let newCurrentIndex = -1;
|
||||
if (e.key === "ArrowUp") {
|
||||
if (currentIndex >= 0) listItems[currentIndex].classList.remove('active');
|
||||
// we need to add listItems.length to the index calculation here because the JavaScript modulos
|
||||
// operator doesn't work with negative numbers
|
||||
newCurrentIndex = (currentIndex - 1 + listItems.length) % listItems.length;
|
||||
} else if (e.key === "ArrowDown") {
|
||||
if (currentIndex >= 0) listItems[currentIndex].classList.remove('active');
|
||||
newCurrentIndex = (currentIndex + 1) % listItems.length;
|
||||
} else if (e.key === "Tab" || e.key === "Enter") {
|
||||
autocomplete.classList.remove('open');
|
||||
}
|
||||
|
||||
if (newCurrentIndex != -1) {
|
||||
const selectedItem = listItems[newCurrentIndex];
|
||||
selectedItem.classList.add('active');
|
||||
|
||||
if (!selectedItem.classList.contains('no-item-found')) qinput.value = selectedItem.innerText;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +173,7 @@ import AutoComplete from "../../../node_modules/autocomplete-js/dist/autocomple
|
|||
categoryButton.classList.remove("selected");
|
||||
}
|
||||
button.classList.add("selected");
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// override form submit action to update the actually selected categories
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
.autocomplete {
|
||||
position: absolute;
|
||||
width: @search-width;
|
||||
max-width: calc(100% - 2 * @search-padding-horizontal);
|
||||
max-height: 0;
|
||||
overflow-y: hidden;
|
||||
.ltr-text-align-left();
|
||||
|
@ -65,8 +66,6 @@
|
|||
|
||||
@media screen and (max-width: @phone) {
|
||||
.autocomplete {
|
||||
width: 100%;
|
||||
|
||||
> ul > li {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
|
|
@ -287,8 +287,9 @@
|
|||
@results-image-row-height: 12rem;
|
||||
@results-image-row-height-phone: 10rem;
|
||||
@search-width: 44rem;
|
||||
// heigh of #search, see detail.less
|
||||
// height of #search, see detail.less
|
||||
@search-height: 13rem;
|
||||
@search-padding-horizontal: 0.5rem;
|
||||
|
||||
/// Device Size
|
||||
/// @desktop > @tablet
|
||||
|
|
|
@ -131,7 +131,7 @@ button.category_button {
|
|||
}
|
||||
|
||||
#search_view {
|
||||
padding: 0.5rem 0.3rem 0 0.5rem;
|
||||
padding: 0.5rem @search-padding-horizontal 0 @search-padding-horizontal;
|
||||
grid-area: search;
|
||||
|
||||
body.results_endpoint & {
|
||||
|
@ -141,7 +141,8 @@ button.category_button {
|
|||
|
||||
.search_box {
|
||||
border-radius: 0.8rem;
|
||||
width: @search-width;
|
||||
width: 100%;
|
||||
max-width: @search-width;
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
white-space: nowrap;
|
||||
|
@ -291,8 +292,7 @@ html.no-js #clear_search.hide_if_nojs {
|
|||
}
|
||||
|
||||
.search_box {
|
||||
width: 98%;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#q {
|
||||
|
|
|
@ -1,14 +1,4 @@
|
|||
FROM docker.io/library/python:3.13-slim AS builder
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
brotli \
|
||||
# uwsgi
|
||||
libpcre3-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /usr/local/searxng/
|
||||
FROM ghcr.io/searxng/base:searxng-builder AS builder
|
||||
|
||||
COPY ./requirements.txt ./requirements.txt
|
||||
|
||||
|
@ -19,38 +9,15 @@ RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \
|
|||
|
||||
COPY ./searx/ ./searx/
|
||||
|
||||
ARG TIMESTAMP_SETTINGS=0
|
||||
ARG TIMESTAMP_UWSGI=0
|
||||
ARG TIMESTAMP_SETTINGS="0"
|
||||
|
||||
RUN python -m compileall -q searx \
|
||||
&& touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \
|
||||
&& touch -c --date=@$TIMESTAMP_UWSGI ./container/uwsgi.ini \
|
||||
&& find /usr/local/searxng/searx/static \
|
||||
\( -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \
|
||||
&& find ./searx/static \
|
||||
\( -name "*.html" -o -name "*.css" -o -name "*.js" -o -name "*.svg" -o -name "*.ttf" -o -name "*.eot" \) \
|
||||
-type f -exec gzip -9 -k {} + -exec brotli --best {} +
|
||||
|
||||
ARG SEARXNG_UID=977
|
||||
ARG SEARXNG_GID=977
|
||||
|
||||
RUN grep -m1 root /etc/group > /tmp/.searxng.group \
|
||||
&& grep -m1 root /etc/passwd > /tmp/.searxng.passwd \
|
||||
&& echo "searxng:x:$SEARXNG_GID:" >> /tmp/.searxng.group \
|
||||
&& echo "searxng:x:$SEARXNG_UID:$SEARXNG_GID:searxng:/usr/local/searxng:/bin/bash" >> /tmp/.searxng.passwd
|
||||
|
||||
FROM docker.io/library/python:3.13-slim
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
# healthcheck
|
||||
wget \
|
||||
# uwsgi
|
||||
libpcre3 \
|
||||
libxml2 \
|
||||
mailcap \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --chown=root:root --from=builder /tmp/.searxng.passwd /etc/passwd
|
||||
COPY --chown=root:root --from=builder /tmp/.searxng.group /etc/group
|
||||
FROM ghcr.io/searxng/base:searxng AS dist
|
||||
|
||||
ARG LABEL_DATE="0001-01-01T00:00:00Z"
|
||||
ARG GIT_URL="unspecified"
|
||||
|
@ -58,37 +25,35 @@ ARG SEARXNG_GIT_VERSION="unspecified"
|
|||
ARG LABEL_VCS_REF="unspecified"
|
||||
ARG LABEL_VCS_URL="unspecified"
|
||||
|
||||
WORKDIR /usr/local/searxng/
|
||||
|
||||
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/venv/ ./venv/
|
||||
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/searx/ ./searx/
|
||||
COPY --chown=searxng:searxng ./container/ ./container/
|
||||
COPY --chown=searxng:searxng ./container/config/ ./.template/
|
||||
COPY --chown=searxng:searxng ./container/entrypoint.sh ./entrypoint.sh
|
||||
|
||||
ARG TIMESTAMP_UWSGI="0"
|
||||
|
||||
RUN touch -c --date=@$TIMESTAMP_UWSGI ./.template/uwsgi.ini
|
||||
|
||||
LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \
|
||||
org.opencontainers.image.created=$LABEL_DATE \
|
||||
org.opencontainers.image.created="$LABEL_DATE" \
|
||||
org.opencontainers.image.description="A privacy-respecting, hackable metasearch engine" \
|
||||
org.opencontainers.image.documentation="https://github.com/searxng/searxng-docker" \
|
||||
org.opencontainers.image.licenses="AGPL-3.0-or-later" \
|
||||
org.opencontainers.image.revision=$LABEL_VCS_REF \
|
||||
org.opencontainers.image.source=$LABEL_VCS_URL \
|
||||
org.opencontainers.image.revision="$LABEL_VCS_REF" \
|
||||
org.opencontainers.image.source="$LABEL_VCS_URL" \
|
||||
org.opencontainers.image.title="searxng" \
|
||||
org.opencontainers.image.url=$LABEL_VCS_URL \
|
||||
org.opencontainers.image.version=$SEARXNG_GIT_VERSION
|
||||
org.opencontainers.image.url="$LABEL_VCS_URL" \
|
||||
org.opencontainers.image.version="$SEARXNG_GIT_VERSION"
|
||||
|
||||
ENV CONFIG_PATH=/etc/searxng \
|
||||
DATA_PATH=/var/cache/searxng
|
||||
|
||||
ENV SEARXNG_VERSION=$SEARXNG_GIT_VERSION \
|
||||
INSTANCE_NAME=searxng \
|
||||
ENV SEARXNG_VERSION="$SEARXNG_GIT_VERSION" \
|
||||
INSTANCE_NAME="SearXNG" \
|
||||
AUTOCOMPLETE="" \
|
||||
BASE_URL="" \
|
||||
BIND_ADDRESS=[::]:8080 \
|
||||
MORTY_KEY="" \
|
||||
MORTY_URL="" \
|
||||
SEARXNG_SETTINGS_PATH=$CONFIG_PATH/settings.yml \
|
||||
UWSGI_SETTINGS_PATH=$CONFIG_PATH/uwsgi.ini \
|
||||
UWSGI_WORKERS=%k \
|
||||
UWSGI_THREADS=4
|
||||
BIND_ADDRESS="[::]:8080" \
|
||||
SEARXNG_SETTINGS_PATH="$CONFIG_PATH/settings.yml" \
|
||||
UWSGI_SETTINGS_PATH="$CONFIG_PATH/uwsgi.ini" \
|
||||
UWSGI_WORKERS="%k" \
|
||||
UWSGI_THREADS="4"
|
||||
|
||||
VOLUME $CONFIG_PATH
|
||||
VOLUME $DATA_PATH
|
||||
|
@ -97,4 +62,4 @@ EXPOSE 8080
|
|||
|
||||
HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1
|
||||
|
||||
ENTRYPOINT ["/usr/local/searxng/container/docker-entrypoint.sh"]
|
||||
ENTRYPOINT ["/usr/local/searxng/entrypoint.sh"]
|
||||
|
|
25
container/base-builder.yml
Normal file
25
container/base-builder.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
contents:
|
||||
keyring:
|
||||
- https://packages.wolfi.dev/os/wolfi-signing.rsa.pub
|
||||
repositories:
|
||||
- https://packages.wolfi.dev/os
|
||||
packages:
|
||||
- wolfi-base
|
||||
- build-base
|
||||
- python-3.13-dev
|
||||
- py3-pip
|
||||
- brotli
|
||||
|
||||
entrypoint:
|
||||
command: /bin/sh -l
|
||||
|
||||
work-dir: /usr/local/searxng/
|
||||
|
||||
environment:
|
||||
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
|
||||
HISTFILE: /dev/null
|
||||
|
||||
archs:
|
||||
- x86_64
|
||||
- aarch64
|
61
container/base.yml
Normal file
61
container/base.yml
Normal file
|
@ -0,0 +1,61 @@
|
|||
contents:
|
||||
keyring:
|
||||
- https://packages.wolfi.dev/os/wolfi-signing.rsa.pub
|
||||
repositories:
|
||||
- https://packages.wolfi.dev/os
|
||||
packages:
|
||||
- wolfi-baselayout
|
||||
- ca-certificates-bundle
|
||||
- busybox
|
||||
- python-3.13
|
||||
# healthcheck
|
||||
- wget
|
||||
# uwsgi
|
||||
- mailcap
|
||||
|
||||
entrypoint:
|
||||
command: /bin/sh -l
|
||||
|
||||
work-dir: /usr/local/searxng/
|
||||
|
||||
accounts:
|
||||
groups:
|
||||
- groupname: searxng
|
||||
gid: 977
|
||||
users:
|
||||
- username: searxng
|
||||
uid: 977
|
||||
shell: /bin/ash
|
||||
|
||||
environment:
|
||||
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
|
||||
HISTFILE: /dev/null
|
||||
CONFIG_PATH: /etc/searxng
|
||||
DATA_PATH: /var/cache/searxng
|
||||
|
||||
paths:
|
||||
# Workdir
|
||||
- path: /usr/local/searxng/
|
||||
type: directory
|
||||
uid: 977
|
||||
gid: 977
|
||||
permissions: 0o755
|
||||
|
||||
# Config volume
|
||||
- path: /etc/searxng/
|
||||
type: directory
|
||||
uid: 977
|
||||
gid: 977
|
||||
permissions: 0o755
|
||||
|
||||
# Data volume
|
||||
- path: /var/cache/searxng/
|
||||
type: directory
|
||||
uid: 977
|
||||
gid: 977
|
||||
permissions: 0o755
|
||||
|
||||
archs:
|
||||
- x86_64
|
||||
- aarch64
|
|
@ -1,126 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
help() {
|
||||
cat <<EOF
|
||||
Command line:
|
||||
-h Display this help
|
||||
-d Dry run to update the configuration files.
|
||||
-f Always update on the configuration files (existing files are renamed with
|
||||
the .old suffix). Without this option, the new configuration files are
|
||||
copied with the .new suffix
|
||||
Environment variables:
|
||||
INSTANCE_NAME settings.yml : general.instance_name
|
||||
AUTOCOMPLETE settings.yml : search.autocomplete
|
||||
BASE_URL settings.yml : server.base_url
|
||||
|
||||
Volume:
|
||||
/etc/searxng the docker entry point copies settings.yml and uwsgi.ini in
|
||||
this directory (see the -f command line option)"
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Parse command line
|
||||
FORCE_CONF_UPDATE=0
|
||||
DRY_RUN=0
|
||||
|
||||
while getopts "fdh" option
|
||||
do
|
||||
case $option in
|
||||
|
||||
f) FORCE_CONF_UPDATE=1 ;;
|
||||
d) DRY_RUN=1 ;;
|
||||
|
||||
h)
|
||||
help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "unknow option ${option}"
|
||||
exit 42
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "SearXNG version $SEARXNG_VERSION"
|
||||
|
||||
# helpers to update the configuration files
|
||||
patch_uwsgi_settings() {
|
||||
CONF="$1"
|
||||
|
||||
# update uwsg.ini
|
||||
sed -i \
|
||||
-e "s|workers = .*|workers = ${UWSGI_WORKERS:-%k}|g" \
|
||||
-e "s|threads = .*|threads = ${UWSGI_THREADS:-4}|g" \
|
||||
"${CONF}"
|
||||
}
|
||||
|
||||
patch_searxng_settings() {
|
||||
CONF="$1"
|
||||
|
||||
# Make sure that there is trailing slash at the end of BASE_URL
|
||||
# see https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion
|
||||
export BASE_URL="${BASE_URL%/}/"
|
||||
|
||||
# update settings.yml
|
||||
sed -i \
|
||||
-e "s|base_url: false|base_url: ${BASE_URL}|g" \
|
||||
-e "s/instance_name: \"SearXNG\"/instance_name: \"${INSTANCE_NAME}\"/g" \
|
||||
-e "s/autocomplete: \"\"/autocomplete: \"${AUTOCOMPLETE}\"/g" \
|
||||
-e "s/ultrasecretkey/$(head -c 24 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9')/g" \
|
||||
"${CONF}"
|
||||
}
|
||||
|
||||
update_conf() {
|
||||
FORCE_CONF_UPDATE=$1
|
||||
CONF="$2"
|
||||
NEW_CONF="${2}.new"
|
||||
OLD_CONF="${2}.old"
|
||||
REF_CONF="$3"
|
||||
PATCH_REF_CONF="$4"
|
||||
|
||||
if [ -f "${CONF}" ]; then
|
||||
if [ "${REF_CONF}" -nt "${CONF}" ]; then
|
||||
# There is a new version
|
||||
if [ "$FORCE_CONF_UPDATE" -ne 0 ]; then
|
||||
# Replace the current configuration
|
||||
printf '⚠️ Automatically update %s to the new version\n' "${CONF}"
|
||||
if [ ! -f "${OLD_CONF}" ]; then
|
||||
printf 'The previous configuration is saved to %s\n' "${OLD_CONF}"
|
||||
mv "${CONF}" "${OLD_CONF}"
|
||||
fi
|
||||
cp "${REF_CONF}" "${CONF}"
|
||||
$PATCH_REF_CONF "${CONF}"
|
||||
else
|
||||
# Keep the current configuration
|
||||
printf '⚠️ Check new version %s to make sure SearXNG is working properly\n' "${NEW_CONF}"
|
||||
cp "${REF_CONF}" "${NEW_CONF}"
|
||||
$PATCH_REF_CONF "${NEW_CONF}"
|
||||
fi
|
||||
else
|
||||
printf 'Use existing %s\n' "${CONF}"
|
||||
fi
|
||||
else
|
||||
printf 'Create %s\n' "${CONF}"
|
||||
cp "${REF_CONF}" "${CONF}"
|
||||
$PATCH_REF_CONF "${CONF}"
|
||||
fi
|
||||
}
|
||||
|
||||
# make sure there are uwsgi settings
|
||||
update_conf "${FORCE_CONF_UPDATE}" "${UWSGI_SETTINGS_PATH}" "/usr/local/searxng/container/uwsgi.ini" "patch_uwsgi_settings"
|
||||
|
||||
# make sure there are searxng settings
|
||||
update_conf "${FORCE_CONF_UPDATE}" "${SEARXNG_SETTINGS_PATH}" "/usr/local/searxng/searx/settings.yml" "patch_searxng_settings"
|
||||
|
||||
# dry run (to update configuration files, then inspect them)
|
||||
if [ $DRY_RUN -eq 1 ]; then
|
||||
printf 'Dry run\n'
|
||||
exit
|
||||
fi
|
||||
|
||||
printf 'Listen on %s\n' "${BIND_ADDRESS}"
|
||||
|
||||
# Start uwsgi
|
||||
# TODO: "--http-socket" will be removed in the future (see uwsgi.ini.new config file): https://github.com/searxng/searxng/pull/4578
|
||||
exec /usr/local/searxng/venv/bin/uwsgi --http-socket "${BIND_ADDRESS}" "${UWSGI_SETTINGS_PATH}"
|
166
container/entrypoint.sh
Executable file
166
container/entrypoint.sh
Executable file
|
@ -0,0 +1,166 @@
|
|||
#!/bin/sh
|
||||
# shellcheck shell=dash
|
||||
set -u
|
||||
|
||||
check_file() {
|
||||
local target="$1"
|
||||
|
||||
if [ ! -f "$target" ]; then
|
||||
cat <<EOF
|
||||
!!!
|
||||
!!! ERROR
|
||||
!!! "$target" is not a valid file, exiting...
|
||||
!!!
|
||||
EOF
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
|
||||
check_directory() {
|
||||
local target="$1"
|
||||
|
||||
if [ ! -d "$target" ]; then
|
||||
cat <<EOF
|
||||
!!!
|
||||
!!! ERROR
|
||||
!!! "$target" is not a valid directory, exiting...
|
||||
!!!
|
||||
EOF
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
|
||||
setup_ownership() {
|
||||
local target="$1"
|
||||
local type="$2"
|
||||
|
||||
case "$type" in
|
||||
file | directory) ;;
|
||||
*)
|
||||
cat <<EOF
|
||||
!!!
|
||||
!!! ERROR
|
||||
!!! "$type" is not a valid type, exiting...
|
||||
!!!
|
||||
EOF
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$(stat -c %U:%G "$target")" != "searxng:searxng" ]; then
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
chown -R searxng:searxng "$target"
|
||||
else
|
||||
cat <<EOF
|
||||
!!!
|
||||
!!! WARNING
|
||||
!!! "$target" $type is not owned by "searxng"
|
||||
!!! This may cause issues when running SearXNG
|
||||
!!!
|
||||
!!! Run the container as root to fix this issue automatically
|
||||
!!! Alternatively, you can chown the $type manually:
|
||||
!!! $ chown -R searxng:searxng "$target"
|
||||
!!!
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Apply envs to uwsgi.ini
|
||||
setup_uwsgi() {
|
||||
local timestamp
|
||||
|
||||
timestamp=$(stat -c %Y "$UWSGI_SETTINGS_PATH")
|
||||
|
||||
sed -i \
|
||||
-e "s|workers = .*|workers = ${UWSGI_WORKERS:-%k}|g" \
|
||||
-e "s|threads = .*|threads = ${UWSGI_THREADS:-4}|g" \
|
||||
"$UWSGI_SETTINGS_PATH"
|
||||
|
||||
# Restore timestamp
|
||||
touch -c -d "@$timestamp" "$UWSGI_SETTINGS_PATH"
|
||||
}
|
||||
|
||||
# Apply envs to settings.yml
|
||||
setup_searxng() {
|
||||
local timestamp
|
||||
|
||||
timestamp=$(stat -c %Y "$SEARXNG_SETTINGS_PATH")
|
||||
|
||||
# Ensure trailing slash in BASE_URL
|
||||
# https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion
|
||||
export BASE_URL="${BASE_URL%/}/"
|
||||
|
||||
sed -i \
|
||||
-e "s|base_url: false|base_url: ${BASE_URL:-false}|g" \
|
||||
-e "s/instance_name: \"SearXNG\"/instance_name: \"${INSTANCE_NAME:-SearXNG}\"/g" \
|
||||
-e "s/autocomplete: \"\"/autocomplete: \"${AUTOCOMPLETE:-}\"/g" \
|
||||
-e "s/ultrasecretkey/$(head -c 24 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9')/g" \
|
||||
"$SEARXNG_SETTINGS_PATH"
|
||||
|
||||
# Restore timestamp
|
||||
touch -c -d "@$timestamp" "$SEARXNG_SETTINGS_PATH"
|
||||
}
|
||||
|
||||
# Handle volume mounts
|
||||
volume_handler() {
|
||||
local target="$1"
|
||||
|
||||
# Check if it's a valid directory
|
||||
check_directory "$target"
|
||||
setup_ownership "$target" "directory"
|
||||
}
|
||||
|
||||
# Handle configuration file updates
|
||||
config_handler() {
|
||||
local target="$1"
|
||||
local template="$2"
|
||||
local new_template_target="$target.new"
|
||||
|
||||
# Create/Update the configuration file
|
||||
if [ -f "$target" ]; then
|
||||
setup_ownership "$target" "file"
|
||||
|
||||
if [ "$template" -nt "$target" ]; then
|
||||
cp -pfT "$template" "$new_template_target"
|
||||
|
||||
cat <<EOF
|
||||
...
|
||||
... INFORMATION
|
||||
... Update available for "$target"
|
||||
... It is recommended to update the configuration file to ensure proper functionality
|
||||
...
|
||||
... New version placed at "$new_template_target"
|
||||
... Please review and merge changes
|
||||
...
|
||||
EOF
|
||||
fi
|
||||
else
|
||||
cat <<EOF
|
||||
...
|
||||
... INFORMATION
|
||||
... "$target" does not exist, creating from template...
|
||||
...
|
||||
EOF
|
||||
cp -pfT "$template" "$target"
|
||||
fi
|
||||
|
||||
# Check if it's a valid file
|
||||
check_file "$target"
|
||||
}
|
||||
|
||||
echo "SearXNG $SEARXNG_VERSION"
|
||||
|
||||
# Check for volume mounts
|
||||
volume_handler "$CONFIG_PATH"
|
||||
volume_handler "$DATA_PATH"
|
||||
|
||||
# Check for updates in files
|
||||
config_handler "$UWSGI_SETTINGS_PATH" "/usr/local/searxng/.template/uwsgi.ini"
|
||||
config_handler "$SEARXNG_SETTINGS_PATH" "/usr/local/searxng/searx/settings.yml"
|
||||
|
||||
# Update files
|
||||
setup_uwsgi
|
||||
setup_searxng
|
||||
|
||||
exec /usr/local/searxng/venv/bin/uwsgi --http-socket "$BIND_ADDRESS" "$UWSGI_SETTINGS_PATH"
|
|
@ -1,5 +1,3 @@
|
|||
# For armv7 architecture
|
||||
|
||||
FROM docker.io/library/python:3.13-slim AS builder
|
||||
|
||||
RUN apt-get update \
|
||||
|
@ -26,11 +24,9 @@ RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \
|
|||
COPY ./searx/ ./searx/
|
||||
|
||||
ARG TIMESTAMP_SETTINGS=0
|
||||
ARG TIMESTAMP_UWSGI=0
|
||||
|
||||
RUN python -m compileall -q searx \
|
||||
&& touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \
|
||||
&& touch -c --date=@$TIMESTAMP_UWSGI ./container/uwsgi.ini \
|
||||
&& find /usr/local/searxng/searx/static \
|
||||
\( -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \
|
||||
-type f -exec gzip -9 -k {} + -exec brotli --best {} +
|
||||
|
@ -70,7 +66,12 @@ WORKDIR /usr/local/searxng/
|
|||
|
||||
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/venv/ ./venv/
|
||||
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/searx/ ./searx/
|
||||
COPY --chown=searxng:searxng ./container/ ./container/
|
||||
COPY --chown=searxng:searxng ./container/config/ ./.template/
|
||||
COPY --chown=searxng:searxng ./container/entrypoint.sh ./entrypoint.sh
|
||||
|
||||
ARG TIMESTAMP_UWSGI="0"
|
||||
|
||||
RUN touch -c --date=@$TIMESTAMP_UWSGI ./.template/uwsgi.ini
|
||||
|
||||
LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \
|
||||
org.opencontainers.image.created=$LABEL_DATE \
|
||||
|
@ -103,4 +104,4 @@ EXPOSE 8080
|
|||
|
||||
HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1
|
||||
|
||||
ENTRYPOINT ["/usr/local/searxng/container/docker-entrypoint.sh"]
|
||||
ENTRYPOINT ["/usr/local/searxng/entrypoint.sh"]
|
||||
|
|
|
@ -181,10 +181,10 @@ Command line
|
|||
<https://docs.docker.com/engine/reference/run/#foreground>`__.
|
||||
|
||||
In the :origin:`Dockerfile` the ENTRYPOINT_ is defined as
|
||||
:origin:`container/docker-entrypoint.sh`
|
||||
:origin:`container/entrypoint.sh`
|
||||
|
||||
.. code:: sh
|
||||
|
||||
docker run --rm -it searxng/searxng -h
|
||||
|
||||
.. program-output:: ../container/docker-entrypoint.sh -h
|
||||
.. program-output:: ../container/entrypoint.sh -h
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
- ``duckduckgo``
|
||||
- ``google``
|
||||
- ``mwmbl``
|
||||
- ``naver``
|
||||
- ``quark``
|
||||
- ``qwant``
|
||||
- ``seznam``
|
||||
|
|
|
@ -4,7 +4,7 @@ cov-core==1.15.0
|
|||
black==24.3.0
|
||||
pylint==3.3.7
|
||||
splinter==0.21.0
|
||||
selenium==4.32.0
|
||||
selenium==4.33.0
|
||||
Pallets-Sphinx-Themes==2.3.0
|
||||
Sphinx==7.4.7
|
||||
sphinx-issues==5.0.1
|
||||
|
|
|
@ -7,15 +7,15 @@ lxml==5.4.0
|
|||
pygments==2.19.1
|
||||
python-dateutil==2.9.0.post0
|
||||
pyyaml==6.0.2
|
||||
httpx[http2]==0.24.1
|
||||
httpx[http2]==0.28.1
|
||||
httpx-socks[asyncio]==0.10.0
|
||||
Brotli==1.1.0
|
||||
uvloop==0.21.0
|
||||
httpx-socks[asyncio]==0.7.7
|
||||
setproctitle==1.3.6
|
||||
redis==5.2.1
|
||||
markdown-it-py==3.0.0
|
||||
fasttext-predict==0.9.2.4
|
||||
tomli==2.2.1; python_version < '3.11'
|
||||
msgspec==0.19.0
|
||||
typer-slim==0.15.3
|
||||
typer-slim==0.16.0
|
||||
isodate==0.7.2
|
||||
|
|
|
@ -21,7 +21,7 @@ log: logging.Logger = logging.getLogger("searx.answerers")
|
|||
|
||||
@dataclass
|
||||
class AnswererInfo:
|
||||
"""Object that holds informations about an answerer, these infos are shown
|
||||
"""Object that holds information about an answerer, these infos are shown
|
||||
to the user in the Preferences menu.
|
||||
|
||||
To be able to translate the information into other languages, the text must
|
||||
|
@ -53,7 +53,7 @@ class Answerer(abc.ABC):
|
|||
|
||||
@abc.abstractmethod
|
||||
def info(self) -> AnswererInfo:
|
||||
"""Informations about the *answerer*, see :py:obj:`AnswererInfo`."""
|
||||
"""Information about the *answerer*, see :py:obj:`AnswererInfo`."""
|
||||
|
||||
|
||||
class ModuleAnswerer(Answerer):
|
||||
|
|
|
@ -149,6 +149,21 @@ def mwmbl(query, _lang):
|
|||
return [result for result in results if not result.startswith("go: ") and not result.startswith("search: ")]
|
||||
|
||||
|
||||
def naver(query, _lang):
|
||||
# Naver search autocompleter
|
||||
url = f"https://ac.search.naver.com/nx/ac?{urlencode({'q': query, 'r_format': 'json', 'st': 0})}"
|
||||
response = get(url)
|
||||
|
||||
results = []
|
||||
|
||||
if response.ok:
|
||||
data = response.json()
|
||||
if data.get('items'):
|
||||
for item in data['items'][0]:
|
||||
results.append(item[0])
|
||||
return results
|
||||
|
||||
|
||||
def qihu360search(query, _lang):
|
||||
# 360Search search autocompleter
|
||||
url = f"https://sug.so.360.cn/suggest?{urlencode({'format': 'json', 'word': query})}"
|
||||
|
@ -300,6 +315,7 @@ backends = {
|
|||
'duckduckgo': duckduckgo,
|
||||
'google': google_complete,
|
||||
'mwmbl': mwmbl,
|
||||
'naver': naver,
|
||||
'quark': quark,
|
||||
'qwant': qwant,
|
||||
'seznam': seznam,
|
||||
|
|
|
@ -319,9 +319,9 @@ def dict_deepupdate(base_dict: dict, upd_dict: dict, names=None):
|
|||
"""
|
||||
# pylint: disable=too-many-branches
|
||||
if not isinstance(base_dict, dict):
|
||||
raise TypeError("argument 'base_dict' is not a ditionary type")
|
||||
raise TypeError("argument 'base_dict' is not a dictionary type")
|
||||
if not isinstance(upd_dict, dict):
|
||||
raise TypeError("argument 'upd_dict' is not a ditionary type")
|
||||
raise TypeError("argument 'upd_dict' is not a dictionary type")
|
||||
|
||||
if names is None:
|
||||
names = []
|
||||
|
|
|
@ -42,7 +42,7 @@ class ExpireCacheCfg(msgspec.Struct): # pylint: disable=too-few-public-methods
|
|||
DB will be created in `/tmp/sxng_cache_{self.name}.db`"""
|
||||
|
||||
MAX_VALUE_LEN: int = 1024 * 10
|
||||
"""Max lenght of a *serialized* value."""
|
||||
"""Max length of a *serialized* value."""
|
||||
|
||||
MAXHOLD_TIME: int = 60 * 60 * 24 * 7 # 7 days
|
||||
"""Hold time (default in sec.), after which a value is removed from the cache."""
|
||||
|
@ -80,7 +80,7 @@ class ExpireCacheCfg(msgspec.Struct): # pylint: disable=too-few-public-methods
|
|||
|
||||
@dataclasses.dataclass
|
||||
class ExpireCacheStats:
|
||||
"""Dataclass wich provides information on the status of the cache."""
|
||||
"""Dataclass which provides information on the status of the cache."""
|
||||
|
||||
cached_items: dict[str, list[tuple[str, typing.Any, int]]]
|
||||
"""Values in the cache mapped by context name.
|
||||
|
|
|
@ -4,29 +4,65 @@
|
|||
make data.all
|
||||
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
__all__ = [
|
||||
'ENGINE_TRAITS',
|
||||
'CURRENCIES',
|
||||
'USER_AGENTS',
|
||||
'EXTERNAL_URLS',
|
||||
'WIKIDATA_UNITS',
|
||||
'EXTERNAL_BANGS',
|
||||
'OSM_KEYS_TAGS',
|
||||
'ENGINE_DESCRIPTIONS',
|
||||
'LOCALES',
|
||||
'ahmia_blacklist_loader',
|
||||
]
|
||||
__all__ = ["ahmia_blacklist_loader"]
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
import typing
|
||||
|
||||
data_dir = Path(__file__).parent
|
||||
from .core import log, data_dir
|
||||
from .currencies import CurrenciesDB
|
||||
|
||||
CURRENCIES: CurrenciesDB
|
||||
USER_AGENTS: dict[str, typing.Any]
|
||||
EXTERNAL_URLS: dict[str, typing.Any]
|
||||
WIKIDATA_UNITS: dict[str, typing.Any]
|
||||
EXTERNAL_BANGS: dict[str, typing.Any]
|
||||
OSM_KEYS_TAGS: dict[str, typing.Any]
|
||||
ENGINE_DESCRIPTIONS: dict[str, typing.Any]
|
||||
ENGINE_TRAITS: dict[str, typing.Any]
|
||||
LOCALES: dict[str, typing.Any]
|
||||
|
||||
lazy_globals = {
|
||||
"CURRENCIES": CurrenciesDB(),
|
||||
"USER_AGENTS": None,
|
||||
"EXTERNAL_URLS": None,
|
||||
"WIKIDATA_UNITS": None,
|
||||
"EXTERNAL_BANGS": None,
|
||||
"OSM_KEYS_TAGS": None,
|
||||
"ENGINE_DESCRIPTIONS": None,
|
||||
"ENGINE_TRAITS": None,
|
||||
"LOCALES": None,
|
||||
}
|
||||
|
||||
data_json_files = {
|
||||
"USER_AGENTS": "useragents.json",
|
||||
"EXTERNAL_URLS": "external_urls.json",
|
||||
"WIKIDATA_UNITS": "wikidata_units.json",
|
||||
"EXTERNAL_BANGS": "external_bangs.json",
|
||||
"OSM_KEYS_TAGS": "osm_keys_tags.json",
|
||||
"ENGINE_DESCRIPTIONS": "engine_descriptions.json",
|
||||
"ENGINE_TRAITS": "engine_traits.json",
|
||||
"LOCALES": "locales.json",
|
||||
}
|
||||
|
||||
|
||||
def _load(filename):
|
||||
with open(data_dir / filename, encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
def __getattr__(name):
|
||||
# lazy init of the global objects
|
||||
if name not in lazy_globals:
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
|
||||
data = lazy_globals[name]
|
||||
if data is not None:
|
||||
return data
|
||||
|
||||
log.debug("init searx.data.%s", name)
|
||||
|
||||
with open(data_dir / data_json_files[name], encoding='utf-8') as f:
|
||||
lazy_globals[name] = json.load(f)
|
||||
|
||||
return lazy_globals[name]
|
||||
|
||||
|
||||
def ahmia_blacklist_loader():
|
||||
|
@ -40,14 +76,3 @@ def ahmia_blacklist_loader():
|
|||
"""
|
||||
with open(data_dir / 'ahmia_blacklist.txt', encoding='utf-8') as f:
|
||||
return f.read().split()
|
||||
|
||||
|
||||
CURRENCIES = _load('currencies.json')
|
||||
USER_AGENTS = _load('useragents.json')
|
||||
EXTERNAL_URLS = _load('external_urls.json')
|
||||
WIKIDATA_UNITS = _load('wikidata_units.json')
|
||||
EXTERNAL_BANGS = _load('external_bangs.json')
|
||||
OSM_KEYS_TAGS = _load('osm_keys_tags.json')
|
||||
ENGINE_DESCRIPTIONS = _load('engine_descriptions.json')
|
||||
ENGINE_TRAITS = _load('engine_traits.json')
|
||||
LOCALES = _load('locales.json')
|
||||
|
|
File diff suppressed because it is too large
Load diff
29
searx/data/core.py
Normal file
29
searx/data/core.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# pylint: disable=missing-module-docstring
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
|
||||
from searx import logger
|
||||
from searx.cache import ExpireCacheCfg, ExpireCacheSQLite
|
||||
|
||||
log = logger.getChild("data")
|
||||
|
||||
data_dir = pathlib.Path(__file__).parent
|
||||
|
||||
_DATA_CACHE: ExpireCacheSQLite = None # type: ignore
|
||||
|
||||
|
||||
def get_cache():
|
||||
|
||||
global _DATA_CACHE # pylint: disable=global-statement
|
||||
|
||||
if _DATA_CACHE is None:
|
||||
_DATA_CACHE = ExpireCacheSQLite.build_cache(
|
||||
ExpireCacheCfg(
|
||||
name="DATA_CACHE",
|
||||
# MAX_VALUE_LEN=1024 * 200, # max. 200kB length for a *serialized* value.
|
||||
# MAXHOLD_TIME=60 * 60 * 24 * 7 * 4, # 4 weeks
|
||||
)
|
||||
)
|
||||
return _DATA_CACHE
|
|
@ -1428,7 +1428,7 @@
|
|||
},
|
||||
"CZK": {
|
||||
"ar": "كرونة تشيكية",
|
||||
"bg": "крони",
|
||||
"bg": "Чешка крона",
|
||||
"bn": "চেক কোরুনা",
|
||||
"ca": "corona txeca",
|
||||
"cs": "koruna česká",
|
||||
|
@ -2687,7 +2687,7 @@
|
|||
"uk": "Йорданський динар"
|
||||
},
|
||||
"JPY": {
|
||||
"af": "Jen",
|
||||
"af": "jen",
|
||||
"ar": "ين ياباني",
|
||||
"bg": "японска йена",
|
||||
"bn": "জাপানি ইয়েন",
|
||||
|
@ -4329,7 +4329,7 @@
|
|||
"PLN": {
|
||||
"af": "Złoty",
|
||||
"ar": "زواتي بولندي",
|
||||
"bg": "Полска злотаПолска злота",
|
||||
"bg": "Полска злота",
|
||||
"ca": "złoty",
|
||||
"cs": "zlotý",
|
||||
"da": "zloty",
|
||||
|
@ -4375,7 +4375,7 @@
|
|||
"PLZ": {
|
||||
"af": "Złoty",
|
||||
"ar": "زواتي بولندي",
|
||||
"bg": "Полска злотаПолска злота",
|
||||
"bg": "Полска злота",
|
||||
"ca": "złoty",
|
||||
"cs": "zlotý",
|
||||
"da": "zloty",
|
||||
|
@ -5881,6 +5881,10 @@
|
|||
"tt": "самоа таласы",
|
||||
"uk": "Самоанська тала"
|
||||
},
|
||||
"XAD": {
|
||||
"en": "Arab accounting dinar",
|
||||
"fr": "dinar arabe"
|
||||
},
|
||||
"XAF": {
|
||||
"ar": "فرنك وسط إفريقي",
|
||||
"bg": "Централноафрикански CFA франк",
|
||||
|
@ -6375,6 +6379,7 @@
|
|||
"$usd": "USD",
|
||||
"1000 lira": "LBP",
|
||||
"100ドル紙幣": "NIO",
|
||||
"1億ベネズエラ・ボリバル": "VES",
|
||||
"2019 zimbabwean dollar": "ZWL",
|
||||
"5th zimbabwean dollar": "ZWL",
|
||||
"A$": "AUD",
|
||||
|
@ -6511,6 +6516,7 @@
|
|||
"Z$": "ZWL",
|
||||
"ZK": "ZMW",
|
||||
"a$": "AUD",
|
||||
"aad": "XAD",
|
||||
"abd doları": "USD",
|
||||
"adb unit of account": "XUA",
|
||||
"ae92 0530 0000 1514 1185 002": "AED",
|
||||
|
@ -6610,6 +6616,7 @@
|
|||
"aoa": "AOA",
|
||||
"apvienotās karalistes sterliņu mārciņa": "GBP",
|
||||
"ar": "MGA",
|
||||
"arab accounting dinar": "XAD",
|
||||
"arabiemiraattien dirhami": "AED",
|
||||
"arany mint befektetés": "XAU",
|
||||
"arg$": "ARS",
|
||||
|
@ -7438,6 +7445,7 @@
|
|||
"dinar algierski": "DZD",
|
||||
"dinar aljazair": "DZD",
|
||||
"dinar alxeriano": "DZD",
|
||||
"dinar arabe": "XAD",
|
||||
"dinar argelino": "DZD",
|
||||
"dinar bahrain": "BHD",
|
||||
"dinar bahraini": "BHD",
|
||||
|
@ -7458,6 +7466,7 @@
|
|||
"dinar bhairéin": "BHD",
|
||||
"dinar chuáit": "KWD",
|
||||
"dinar coaitiano": "KWD",
|
||||
"dinar comptable arabe": "XAD",
|
||||
"dinar couaitiano": "KWD",
|
||||
"dinar covaitiano": "KWD",
|
||||
"dinar coveiteano": "KWD",
|
||||
|
@ -9162,7 +9171,6 @@
|
|||
"jordán dinár": "JOD",
|
||||
"jordánsky dinár": "JOD",
|
||||
"jordánský dinár": "JOD",
|
||||
"jpy": "JPY",
|
||||
"juan": "CNY",
|
||||
"juanis": "CNY",
|
||||
"juaņa": "CNY",
|
||||
|
@ -9813,7 +9821,6 @@
|
|||
"livre de sainte hélène": "SHP",
|
||||
"livre des îles falkland": "FKP",
|
||||
"livre des îles malouines": "FKP",
|
||||
"livre egyptienne": "EGP",
|
||||
"livre égyptienne": "EGP",
|
||||
"livre libanaise": "LBP",
|
||||
"livre soudanaise": "SDG",
|
||||
|
@ -13367,7 +13374,6 @@
|
|||
],
|
||||
"крона чеська": "CZK",
|
||||
"крона швеции": "SEK",
|
||||
"крони": "CZK",
|
||||
"куба писысы": "CUP",
|
||||
"кубански пезос": "CUP",
|
||||
"кубански песо": "CUP",
|
||||
|
@ -13645,10 +13651,6 @@
|
|||
"PLZ",
|
||||
"PLN"
|
||||
],
|
||||
"полска злотаполска злота": [
|
||||
"PLZ",
|
||||
"PLN"
|
||||
],
|
||||
"польский злотый": [
|
||||
"PLZ",
|
||||
"PLN"
|
||||
|
|
55
searx/data/currencies.py
Normal file
55
searx/data/currencies.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""Simple implementation to store currencies data in a SQL database."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
__all__ = ["CurrenciesDB"]
|
||||
|
||||
import json
|
||||
import pathlib
|
||||
|
||||
from .core import get_cache, log
|
||||
|
||||
|
||||
class CurrenciesDB:
|
||||
# pylint: disable=missing-class-docstring
|
||||
|
||||
ctx_names = "data_currencies_names"
|
||||
ctx_iso4217 = "data_currencies_iso4217"
|
||||
|
||||
json_file = pathlib.Path(__file__).parent / "currencies.json"
|
||||
|
||||
def __init__(self):
|
||||
self.cache = get_cache()
|
||||
|
||||
def init(self):
|
||||
if self.cache.properties("currencies loaded") != "OK":
|
||||
self.load()
|
||||
self.cache.properties.set("currencies loaded", "OK")
|
||||
# F I X M E:
|
||||
# do we need a maintenance .. rember: database is stored
|
||||
# in /tmp and will be rebuild during the reboot anyway
|
||||
|
||||
def load(self):
|
||||
log.debug("init searx.data.CURRENCIES")
|
||||
with open(self.json_file, encoding="utf-8") as f:
|
||||
data_dict = json.load(f)
|
||||
for key, value in data_dict["names"].items():
|
||||
self.cache.set(key=key, value=value, ctx=self.ctx_names, expire=None)
|
||||
for key, value in data_dict["iso4217"].items():
|
||||
self.cache.set(key=key, value=value, ctx=self.ctx_iso4217, expire=None)
|
||||
|
||||
def name_to_iso4217(self, name):
|
||||
self.init()
|
||||
|
||||
ret_val = self.cache.get(key=name, default=name, ctx=self.ctx_names)
|
||||
if isinstance(ret_val, list):
|
||||
# if more alternatives, use the last in the list
|
||||
ret_val = ret_val[-1]
|
||||
return ret_val
|
||||
|
||||
def iso4217_to_name(self, iso4217, language):
|
||||
self.init()
|
||||
|
||||
iso4217_languages: dict = self.cache.get(key=iso4217, default={}, ctx=self.ctx_iso4217)
|
||||
return iso4217_languages.get(language, iso4217)
|
File diff suppressed because one or more lines are too long
|
@ -7381,7 +7381,6 @@
|
|||
"ko": "korean",
|
||||
"ks": "kashmiri",
|
||||
"ku": "kurdish",
|
||||
"kw": "cornish",
|
||||
"la": "latin",
|
||||
"lb": "luxembourgish",
|
||||
"ln": "lingala",
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
],
|
||||
"ua": "Mozilla/5.0 ({os}; rv:{version}) Gecko/20100101 Firefox/{version}",
|
||||
"versions": [
|
||||
"138.0",
|
||||
"137.0"
|
||||
"139.0",
|
||||
"138.0"
|
||||
]
|
||||
}
|
|
@ -4199,11 +4199,6 @@
|
|||
"symbol": "St",
|
||||
"to_si_factor": 13450.0
|
||||
},
|
||||
"Q235729": {
|
||||
"si_name": "Q11574",
|
||||
"symbol": "y (365 days)",
|
||||
"to_si_factor": 31536000.0
|
||||
},
|
||||
"Q23823681": {
|
||||
"si_name": "Q25236",
|
||||
"symbol": "TW",
|
||||
|
|
|
@ -79,7 +79,7 @@ class EngineCache:
|
|||
<searx.cache.ExpireCacheSQLite>`).
|
||||
|
||||
In the :origin:`searx/engines/demo_offline.py` engine you can find an
|
||||
exemplary implementation of such a cache other exaples are implemeted
|
||||
exemplary implementation of such a cache other examples are implemented
|
||||
in:
|
||||
|
||||
- :origin:`searx/engines/radio_browser.py`
|
||||
|
|
|
@ -156,7 +156,7 @@ def parse_image_item(item):
|
|||
def parse_video_item(item):
|
||||
|
||||
# in video items, the title is more or less a "content description", we try
|
||||
# to reduce the lenght of the title ..
|
||||
# to reduce the length of the title ..
|
||||
|
||||
title = item["title"]
|
||||
content = ""
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"""
|
||||
|
||||
import json
|
||||
from searx.result_types import EngineResults
|
||||
|
||||
# about
|
||||
about = {
|
||||
|
@ -28,13 +29,15 @@ def request(_query, params):
|
|||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
def response(resp) -> EngineResults:
|
||||
res = EngineResults()
|
||||
|
||||
# remove first and last lines to get only json
|
||||
json_resp = resp.text[resp.text.find('\n') + 1 : resp.text.rfind('\n') - 2]
|
||||
try:
|
||||
conversion_rate = float(json.loads(json_resp)["to"][0]["mid"])
|
||||
except IndexError:
|
||||
return []
|
||||
return res
|
||||
answer = '{0} {1} = {2} {3}, 1 {1} ({5}) = {4} {3} ({6})'.format(
|
||||
resp.search_params['amount'],
|
||||
resp.search_params['from'],
|
||||
|
@ -46,5 +49,5 @@ def response(resp):
|
|||
)
|
||||
|
||||
url = f"https://duckduckgo.com/?q={resp.search_params['from']}+to+{resp.search_params['to']}"
|
||||
|
||||
return [{"answer": answer, "url": url}]
|
||||
res.add(res.types.Answer(answer=answer, url=url))
|
||||
return res
|
||||
|
|
|
@ -58,19 +58,21 @@ paging = True
|
|||
time_range_support = True
|
||||
safesearch = True # user can't select but the results are filtered
|
||||
|
||||
url = "https://html.duckduckgo.com/html"
|
||||
url = "https://html.duckduckgo.com/html/"
|
||||
|
||||
time_range_dict = {'day': 'd', 'week': 'w', 'month': 'm', 'year': 'y'}
|
||||
form_data = {'v': 'l', 'api': 'd.js', 'o': 'json'}
|
||||
|
||||
CACHE: EngineCache
|
||||
_CACHE: EngineCache = None # type: ignore
|
||||
"""Persistent (SQLite) key/value cache that deletes its values after ``expire``
|
||||
seconds."""
|
||||
|
||||
|
||||
def init(_): # pylint: disable=unused-argument
|
||||
global CACHE # pylint: disable=global-statement
|
||||
CACHE = EngineCache("duckduckgo") # type:ignore
|
||||
def get_cache():
|
||||
global _CACHE # pylint: disable=global-statement
|
||||
if _CACHE is None:
|
||||
_CACHE = EngineCache("duckduckgo") # type:ignore
|
||||
return _CACHE
|
||||
|
||||
|
||||
def get_vqd(query: str, region: str, force_request: bool = False) -> str:
|
||||
|
@ -105,8 +107,9 @@ def get_vqd(query: str, region: str, force_request: bool = False) -> str:
|
|||
seems the block list is a sliding window: to get my IP rid from the bot list
|
||||
I had to cool down my IP for 1h (send no requests from that IP to DDG).
|
||||
"""
|
||||
key = CACHE.secret_hash(f"{query}//{region}")
|
||||
value = CACHE.get(key=key)
|
||||
cache = get_cache()
|
||||
key = cache.secret_hash(f"{query}//{region}")
|
||||
value = cache.get(key=key)
|
||||
if value is not None and not force_request:
|
||||
logger.debug("vqd: re-use cached value: %s", value)
|
||||
return value
|
||||
|
@ -124,15 +127,16 @@ def get_vqd(query: str, region: str, force_request: bool = False) -> str:
|
|||
logger.error("vqd: got HTTP %s from duckduckgo.com", resp.status_code)
|
||||
|
||||
if value:
|
||||
CACHE.set(key=key, value=value)
|
||||
cache.set(key=key, value=value)
|
||||
else:
|
||||
logger.error("vqd value from duckduckgo.com ", resp.status_code)
|
||||
return value
|
||||
|
||||
|
||||
def set_vqd(query: str, region: str, value: str):
|
||||
key = CACHE.secret_hash(f"{query}//{region}")
|
||||
CACHE.set(key=key, value=value, expire=3600)
|
||||
cache = get_cache()
|
||||
key = cache.secret_hash(f"{query}//{region}")
|
||||
cache.set(key=key, value=value, expire=3600)
|
||||
|
||||
|
||||
def get_ddg_lang(eng_traits: EngineTraits, sxng_locale, default='en_US'):
|
||||
|
@ -244,7 +248,6 @@ def quote_ddg_bangs(query):
|
|||
|
||||
|
||||
def request(query, params):
|
||||
|
||||
query = quote_ddg_bangs(query)
|
||||
|
||||
if len(query) >= 500:
|
||||
|
@ -252,93 +255,79 @@ def request(query, params):
|
|||
params["url"] = None
|
||||
return
|
||||
|
||||
# Advanced search syntax ends in CAPTCHA
|
||||
# https://duckduckgo.com/duckduckgo-help-pages/results/syntax/
|
||||
query = " ".join(
|
||||
[
|
||||
x.removeprefix("site:").removeprefix("intitle:").removeprefix("inurl:").removeprefix("filetype:")
|
||||
for x in query.split()
|
||||
]
|
||||
)
|
||||
eng_region: str = traits.get_region(params['searxng_locale'], traits.all_locale) # type: ignore
|
||||
if eng_region == "wt-wt":
|
||||
# https://html.duckduckgo.com/html sets an empty value for "all".
|
||||
eng_region = ""
|
||||
|
||||
params['data']['kl'] = eng_region
|
||||
params['cookies']['kl'] = eng_region
|
||||
# Note: The API is reverse-engineered from DuckDuckGo's HTML webpage
|
||||
# (https://html.duckduckgo.com/html/) and may be subject to additional bot detection mechanisms
|
||||
# and breaking changes in the future.
|
||||
#
|
||||
# The params['data'] dictionary can have the following key parameters, in this order:
|
||||
# - q (str): Search query string
|
||||
# - b (str): Beginning parameter - empty string for first page requests
|
||||
# - s (int): Search offset for pagination
|
||||
# - nextParams (str): Continuation parameters from previous page response, typically empty
|
||||
# - v (str): Typically 'l' for subsequent pages
|
||||
# - o (str): Output format, typically 'json'
|
||||
# - dc (int): Display count - value equal to offset (s) + 1
|
||||
# - api (str): API endpoint identifier, typically 'd.js'
|
||||
# - vqd (str): Validation query digest
|
||||
# - kl (str): Keyboard language/region code (e.g., 'en-us')
|
||||
# - df (str): Time filter, maps to values like 'd' (day), 'w' (week), 'm' (month), 'y' (year)
|
||||
|
||||
# eng_lang = get_ddg_lang(traits, params['searxng_locale'])
|
||||
|
||||
params['url'] = url
|
||||
params['method'] = 'POST'
|
||||
params['data']['q'] = query
|
||||
|
||||
# The API is not documented, so we do some reverse engineering and emulate
|
||||
# what https://html.duckduckgo.com/html does when you press "next Page" link
|
||||
# again and again ..
|
||||
|
||||
params['headers']['Content-Type'] = 'application/x-www-form-urlencoded'
|
||||
|
||||
params['headers']['Sec-Fetch-Dest'] = "document"
|
||||
params['headers']['Sec-Fetch-Mode'] = "navigate" # at least this one is used by ddg's bot detection
|
||||
params['headers']['Sec-Fetch-Site'] = "same-origin"
|
||||
params['headers']['Sec-Fetch-User'] = "?1"
|
||||
|
||||
# Form of the initial search page does have empty values in the form
|
||||
if params['pageno'] == 1:
|
||||
|
||||
params['data']['b'] = ""
|
||||
|
||||
params['data']['df'] = ''
|
||||
if params['time_range'] in time_range_dict:
|
||||
|
||||
params['data']['df'] = time_range_dict[params['time_range']]
|
||||
params['cookies']['df'] = time_range_dict[params['time_range']]
|
||||
|
||||
if params['pageno'] == 2:
|
||||
|
||||
# second page does have an offset of 20
|
||||
offset = (params['pageno'] - 1) * 20
|
||||
elif params['pageno'] >= 2:
|
||||
offset = 10 + (params['pageno'] - 2) * 15 # Page 2 = 10, Page 3+ = 10 + n*15
|
||||
params['data']['s'] = offset
|
||||
params['data']['dc'] = offset + 1
|
||||
|
||||
elif params['pageno'] > 2:
|
||||
|
||||
# third and following pages do have an offset of 20 + n*50
|
||||
offset = 20 + (params['pageno'] - 2) * 50
|
||||
params['data']['s'] = offset
|
||||
params['data']['dc'] = offset + 1
|
||||
|
||||
if params['pageno'] > 1:
|
||||
|
||||
# initial page does not have these additional data in the input form
|
||||
params['data']['o'] = form_data.get('o', 'json')
|
||||
params['data']['api'] = form_data.get('api', 'd.js')
|
||||
params['data']['nextParams'] = form_data.get('nextParams', '')
|
||||
params['data']['v'] = form_data.get('v', 'l')
|
||||
params['headers']['Referer'] = url
|
||||
params['data']['o'] = form_data.get('o', 'json')
|
||||
params['data']['dc'] = offset + 1
|
||||
params['data']['api'] = form_data.get('api', 'd.js')
|
||||
|
||||
# vqd is required to request other pages after the first one
|
||||
vqd = get_vqd(query, eng_region, force_request=False)
|
||||
|
||||
# Certain conditions must be met in order to call up one of the
|
||||
# following pages ...
|
||||
|
||||
if vqd:
|
||||
params['data']['vqd'] = vqd # follow up pages / requests needs a vqd argument
|
||||
params['data']['vqd'] = vqd
|
||||
else:
|
||||
# Don't try to call follow up pages without a vqd value. DDG
|
||||
# recognizes this as a request from a bot. This lowers the
|
||||
# Don't try to call follow up pages without a vqd value.
|
||||
# DDG recognizes this as a request from a bot. This lowers the
|
||||
# reputation of the SearXNG IP and DDG starts to activate CAPTCHAs.
|
||||
params["url"] = None
|
||||
return
|
||||
|
||||
if params['searxng_locale'].startswith("zh"):
|
||||
# Some locales (at least China) do not have a "next page" button and ddg
|
||||
# Some locales (at least China) do not have a "next page" button and DDG
|
||||
# will return a HTTP/2 403 Forbidden for a request of such a page.
|
||||
params["url"] = None
|
||||
return
|
||||
|
||||
# Put empty kl in form data if language/region set to all
|
||||
if eng_region == "wt-wt":
|
||||
params['data']['kl'] = ""
|
||||
else:
|
||||
params['data']['kl'] = eng_region
|
||||
|
||||
params['data']['df'] = ''
|
||||
if params['time_range'] in time_range_dict:
|
||||
params['data']['df'] = time_range_dict[params['time_range']]
|
||||
params['cookies']['df'] = time_range_dict[params['time_range']]
|
||||
|
||||
params['cookies']['kl'] = eng_region
|
||||
|
||||
params['url'] = url
|
||||
params['method'] = 'POST'
|
||||
|
||||
params['headers']['Content-Type'] = 'application/x-www-form-urlencoded'
|
||||
params['headers']['Referer'] = url
|
||||
params['headers']['Sec-Fetch-Dest'] = "document"
|
||||
params['headers']['Sec-Fetch-Mode'] = "navigate" # at least this one is used by ddg's bot detection
|
||||
params['headers']['Sec-Fetch-Site'] = "same-origin"
|
||||
params['headers']['Sec-Fetch-User'] = "?1"
|
||||
|
||||
logger.debug("param headers: %s", params['headers'])
|
||||
logger.debug("param data: %s", params['data'])
|
||||
logger.debug("param cookies: %s", params['cookies'])
|
||||
|
||||
|
@ -383,8 +372,9 @@ def response(resp) -> EngineResults:
|
|||
continue
|
||||
item["title"] = extract_text(title)
|
||||
item["url"] = eval_xpath(div_result, './/h2/a/@href')[0]
|
||||
item["content"] = extract_text(eval_xpath(div_result, './/a[contains(@class, "result__snippet")]')[0])
|
||||
|
||||
item["content"] = extract_text(
|
||||
eval_xpath_getindex(div_result, './/a[contains(@class, "result__snippet")]', 0, [])
|
||||
)
|
||||
results.append(item)
|
||||
|
||||
zero_click_info_xpath = '//div[@id="zero_click_abstract"]'
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""Invidious (Videos)
|
||||
|
||||
If you want to use invidious with SearXNG you should setup one locally.
|
||||
No public instance offer a public API now
|
||||
|
||||
- https://github.com/searxng/searxng/issues/2722#issuecomment-2884993248
|
||||
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
import random
|
||||
|
@ -13,7 +20,7 @@ from searx.utils import humanize_number
|
|||
about = {
|
||||
"website": 'https://api.invidious.io/',
|
||||
"wikidata_id": 'Q79343316',
|
||||
"official_api_documentation": 'https://github.com/iv-org/documentation/blob/master/API.md',
|
||||
"official_api_documentation": 'https://docs.invidious.io/api/',
|
||||
"use_official_api": True,
|
||||
"require_api_key": False,
|
||||
"results": 'JSON',
|
||||
|
@ -25,7 +32,12 @@ paging = True
|
|||
time_range_support = True
|
||||
|
||||
# base_url can be overwritten by a list of URLs in the settings.yml
|
||||
base_url = 'https://vid.puffyan.us'
|
||||
base_url: list | str = []
|
||||
|
||||
|
||||
def init(_):
|
||||
if not base_url:
|
||||
raise ValueError("missing invidious base_url")
|
||||
|
||||
|
||||
def request(query, params):
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""Material Icons (images)
|
||||
|
||||
"""
|
||||
"""Material Icons (icons)"""
|
||||
|
||||
import re
|
||||
from json import loads
|
||||
|
@ -14,6 +12,8 @@ about = {
|
|||
"require_api_key": False,
|
||||
"results": 'JSON',
|
||||
}
|
||||
categories = ['images', 'icons']
|
||||
|
||||
search_url = "https://fonts.google.com/metadata/icons?key=material_symbols&incomplete=true"
|
||||
result_url = "https://fonts.google.com/icons?icon.query={query}&selected=Material+Symbols+Outlined:{icon_name}:FILL@0{fill};wght@400;GRAD@0;opsz@24" # pylint: disable=line-too-long
|
||||
img_src_url = "https://fonts.gstatic.com/s/i/short-term/release/materialsymbolsoutlined/{icon_name}/{svg_type}/24px.svg"
|
||||
|
@ -46,7 +46,7 @@ def response(resp):
|
|||
continue
|
||||
|
||||
tags = [tag.title() for tag in result["tags"]]
|
||||
categories = [category.title() for category in result["categories"]]
|
||||
icon_categories = [category.title() for category in result["categories"]]
|
||||
|
||||
results.append(
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ def response(resp):
|
|||
'url': result_url.format(icon_name=result["name"], query=result["name"], fill=0 if outlined else 1),
|
||||
'img_src': img_src_url.format(icon_name=result["name"], svg_type=svg_type),
|
||||
'title': result["name"].replace("_", "").title(),
|
||||
'content': ", ".join(tags) + " / " + ", ".join(categories),
|
||||
'content': ", ".join(tags) + " / " + ", ".join(icon_categories),
|
||||
}
|
||||
)
|
||||
|
||||
|
|
210
searx/engines/naver.py
Normal file
210
searx/engines/naver.py
Normal file
|
@ -0,0 +1,210 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# pylint: disable=line-too-long
|
||||
"""Naver for SearXNG"""
|
||||
|
||||
from urllib.parse import urlencode
|
||||
from lxml import html
|
||||
|
||||
from searx.exceptions import SearxEngineAPIException, SearxEngineXPathException
|
||||
from searx.result_types import EngineResults, MainResult
|
||||
from searx.utils import (
|
||||
eval_xpath_getindex,
|
||||
eval_xpath_list,
|
||||
eval_xpath,
|
||||
extract_text,
|
||||
extr,
|
||||
html_to_text,
|
||||
parse_duration_string,
|
||||
js_variable_to_python,
|
||||
)
|
||||
|
||||
# engine metadata
|
||||
about = {
|
||||
"website": "https://search.naver.com",
|
||||
"wikidata_id": "Q485639",
|
||||
"use_official_api": False,
|
||||
"require_api_key": False,
|
||||
"results": "HTML",
|
||||
"language": "ko",
|
||||
}
|
||||
|
||||
categories = []
|
||||
paging = True
|
||||
|
||||
time_range_support = True
|
||||
time_range_dict = {"day": "1d", "week": "1w", "month": "1m", "year": "1y"}
|
||||
|
||||
base_url = "https://search.naver.com"
|
||||
|
||||
naver_category = "general"
|
||||
"""Naver supports general, images, news, videos search.
|
||||
|
||||
- ``general``: search for general
|
||||
- ``images``: search for images
|
||||
- ``news``: search for news
|
||||
- ``videos``: search for videos
|
||||
"""
|
||||
|
||||
# Naver cannot set the number of results on one page, set default value for paging
|
||||
naver_category_dict = {
|
||||
"general": {
|
||||
"start": 15,
|
||||
"where": "web",
|
||||
},
|
||||
"images": {
|
||||
"start": 50,
|
||||
"where": "image",
|
||||
},
|
||||
"news": {
|
||||
"start": 10,
|
||||
"where": "news",
|
||||
},
|
||||
"videos": {
|
||||
"start": 48,
|
||||
"where": "video",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def init(_):
|
||||
if naver_category not in ('general', 'images', 'news', 'videos'):
|
||||
raise SearxEngineAPIException(f"Unsupported category: {naver_category}")
|
||||
|
||||
|
||||
def request(query, params):
|
||||
query_params = {
|
||||
"query": query,
|
||||
}
|
||||
|
||||
if naver_category in naver_category_dict:
|
||||
query_params["start"] = (params["pageno"] - 1) * naver_category_dict[naver_category]["start"] + 1
|
||||
query_params["where"] = naver_category_dict[naver_category]["where"]
|
||||
|
||||
if params["time_range"] in time_range_dict:
|
||||
query_params["nso"] = f"p:{time_range_dict[params['time_range']]}"
|
||||
|
||||
params["url"] = f"{base_url}/search.naver?{urlencode(query_params)}"
|
||||
return params
|
||||
|
||||
|
||||
def response(resp) -> EngineResults:
|
||||
parsers = {'general': parse_general, 'images': parse_images, 'news': parse_news, 'videos': parse_videos}
|
||||
|
||||
return parsers[naver_category](resp.text)
|
||||
|
||||
|
||||
def parse_general(data):
|
||||
results = EngineResults()
|
||||
|
||||
dom = html.fromstring(data)
|
||||
|
||||
for item in eval_xpath_list(dom, "//ul[contains(@class, 'lst_total')]/li[contains(@class, 'bx')]"):
|
||||
thumbnail = None
|
||||
try:
|
||||
thumbnail = eval_xpath_getindex(item, ".//div[contains(@class, 'thumb_single')]//img/@data-lazysrc", 0)
|
||||
except (ValueError, TypeError, SearxEngineXPathException):
|
||||
pass
|
||||
|
||||
results.add(
|
||||
MainResult(
|
||||
title=extract_text(eval_xpath(item, ".//a[contains(@class, 'link_tit')]")),
|
||||
url=eval_xpath_getindex(item, ".//a[contains(@class, 'link_tit')]/@href", 0),
|
||||
content=extract_text(
|
||||
eval_xpath(item, ".//div[contains(@class, 'total_dsc_wrap')]//a[contains(@class, 'api_txt_lines')]")
|
||||
),
|
||||
thumbnail=thumbnail,
|
||||
)
|
||||
)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def parse_images(data):
|
||||
results = []
|
||||
|
||||
match = extr(data, '<script>var imageSearchTabData=', '</script>')
|
||||
if match:
|
||||
json = js_variable_to_python(match.strip())
|
||||
items = json.get('content', {}).get('items', [])
|
||||
|
||||
for item in items:
|
||||
results.append(
|
||||
{
|
||||
"template": "images.html",
|
||||
"url": item.get('link'),
|
||||
"thumbnail_src": item.get('thumb'),
|
||||
"img_src": item.get('originalUrl'),
|
||||
"title": html_to_text(item.get('title')),
|
||||
"source": item.get('source'),
|
||||
"resolution": f"{item.get('orgWidth')} x {item.get('orgHeight')}",
|
||||
}
|
||||
)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def parse_news(data):
|
||||
results = EngineResults()
|
||||
dom = html.fromstring(data)
|
||||
|
||||
for item in eval_xpath_list(
|
||||
dom, "//div[contains(@class, 'sds-comps-base-layout') and contains(@class, 'sds-comps-full-layout')]"
|
||||
):
|
||||
title = extract_text(eval_xpath(item, ".//span[contains(@class, 'sds-comps-text-type-headline1')]/text()"))
|
||||
|
||||
url = eval_xpath_getindex(item, ".//a[@href and @nocr='1']/@href", 0)
|
||||
|
||||
content = extract_text(eval_xpath(item, ".//span[contains(@class, 'sds-comps-text-type-body1')]"))
|
||||
|
||||
thumbnail = None
|
||||
try:
|
||||
thumbnail = eval_xpath_getindex(
|
||||
item,
|
||||
".//div[contains(@class, 'sds-comps-image') and contains(@class, 'sds-rego-thumb-overlay')]//img[@src]/@src",
|
||||
0,
|
||||
)
|
||||
except (ValueError, TypeError, SearxEngineXPathException):
|
||||
pass
|
||||
|
||||
if title and content and url:
|
||||
results.add(
|
||||
MainResult(
|
||||
title=title,
|
||||
url=url,
|
||||
content=content,
|
||||
thumbnail=thumbnail,
|
||||
)
|
||||
)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def parse_videos(data):
|
||||
results = []
|
||||
|
||||
dom = html.fromstring(data)
|
||||
|
||||
for item in eval_xpath_list(dom, "//li[contains(@class, 'video_item')]"):
|
||||
thumbnail = None
|
||||
try:
|
||||
thumbnail = eval_xpath_getindex(item, ".//img[contains(@class, 'thumb')]/@src", 0)
|
||||
except (ValueError, TypeError, SearxEngineXPathException):
|
||||
pass
|
||||
|
||||
length = None
|
||||
try:
|
||||
length = parse_duration_string(extract_text(eval_xpath(item, ".//span[contains(@class, 'time')]")))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
results.append(
|
||||
{
|
||||
"template": "videos.html",
|
||||
"title": extract_text(eval_xpath(item, ".//a[contains(@class, 'info_title')]")),
|
||||
"url": eval_xpath_getindex(item, ".//a[contains(@class, 'info_title')]/@href", 0),
|
||||
"thumbnail": thumbnail,
|
||||
'length': length,
|
||||
}
|
||||
)
|
||||
|
||||
return results
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""Pinterest (images)
|
||||
"""
|
||||
"""Pinterest (images)"""
|
||||
|
||||
from json import dumps
|
||||
|
||||
|
@ -28,6 +27,11 @@ def request(query, params):
|
|||
'context': {},
|
||||
}
|
||||
params['url'] = f"{base_url}/resource/BaseSearchResource/get/?data={dumps(args)}"
|
||||
params['headers'] = {
|
||||
'X-Pinterest-AppState': 'active',
|
||||
'X-Pinterest-Source-Url': '/ideas/',
|
||||
'X-Pinterest-PWS-Handler': 'www/ideas.js',
|
||||
}
|
||||
|
||||
return params
|
||||
|
||||
|
|
|
@ -137,19 +137,20 @@ def _get_request_id(query, params):
|
|||
if l.territory:
|
||||
headers['Accept-Language'] = f"{l.language}-{l.territory},{l.language};" "q=0.9,*;" "q=0.5"
|
||||
|
||||
resp_text = get(url, headers=headers).text # type: ignore
|
||||
resp = get(url, headers=headers)
|
||||
|
||||
for line in resp_text.split("\n"):
|
||||
for line in resp.text.split("\n"):
|
||||
if "window.searchId = " in line:
|
||||
return line.split("= ")[1][:-1].replace('"', "")
|
||||
return line.split("= ")[1][:-1].replace('"', ""), resp.cookies
|
||||
|
||||
return None
|
||||
raise RuntimeError("Couldn't find any request id for presearch")
|
||||
|
||||
|
||||
def request(query, params):
|
||||
request_id = _get_request_id(query, params)
|
||||
request_id, cookies = _get_request_id(query, params)
|
||||
params["headers"]["Accept"] = "application/json"
|
||||
params["url"] = f"{base_url}/results?id={request_id}"
|
||||
params["cookies"] = cookies
|
||||
|
||||
return params
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ about = {
|
|||
"require_api_key": False,
|
||||
"results": 'JSON',
|
||||
}
|
||||
categories = ['images']
|
||||
categories = ['images', 'icons']
|
||||
|
||||
|
||||
icons_list_url = 'https://cdn.selfh.st/directory/icons.json'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""Svgrepo (images)
|
||||
"""Svgrepo (icons)
|
||||
"""
|
||||
|
||||
from lxml import html
|
||||
|
@ -14,7 +14,7 @@ about = {
|
|||
}
|
||||
|
||||
paging = True
|
||||
categories = ['images']
|
||||
categories = ['images', 'icons']
|
||||
base_url = "https://www.svgrepo.com"
|
||||
|
||||
results_xpath = "//div[@class='style_nodeListing__7Nmro']/div"
|
||||
|
|
|
@ -77,7 +77,7 @@ def response(resp):
|
|||
elif item_type == 'video':
|
||||
results.append(_video(item))
|
||||
else:
|
||||
logger.error("unknow result type: %s", item_type)
|
||||
logger.error("unknown result type: %s", item_type)
|
||||
|
||||
return results
|
||||
|
||||
|
|
50
searx/engines/uxwing.py
Normal file
50
searx/engines/uxwing.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""UXwing (images)"""
|
||||
|
||||
from urllib.parse import quote_plus
|
||||
from lxml import html
|
||||
|
||||
from searx.utils import eval_xpath, eval_xpath_list, extract_text
|
||||
|
||||
about = {
|
||||
"website": 'https://uxwing.com',
|
||||
"wikidata_id": None,
|
||||
"official_api_documentation": None,
|
||||
"use_official_api": False,
|
||||
"require_api_key": False,
|
||||
"results": 'HTML',
|
||||
}
|
||||
categories = ['images', 'icons']
|
||||
|
||||
base_url = "https://uxwing.com"
|
||||
|
||||
|
||||
def request(query, params):
|
||||
params['url'] = f"{base_url}/?s={quote_plus(query)}"
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
|
||||
doc = html.fromstring(resp.text)
|
||||
for result in eval_xpath_list(doc, "//article[starts-with(@id, 'post')]"):
|
||||
classes = extract_text(eval_xpath(result, "./@class")).split(" ")
|
||||
tags = []
|
||||
for css_class in classes:
|
||||
for prefix in ("category", "tag"):
|
||||
if css_class.startswith(prefix):
|
||||
tag = css_class.removeprefix(prefix)
|
||||
tags.append(tag.replace("-", " ").title())
|
||||
|
||||
results.append(
|
||||
{
|
||||
'template': 'images.html',
|
||||
'url': extract_text(eval_xpath(result, "./a/@href")),
|
||||
'img_src': extract_text(eval_xpath(result, ".//img/@src")),
|
||||
'title': extract_text(eval_xpath(result, ".//img/@alt")),
|
||||
'content': ', '.join(tags),
|
||||
}
|
||||
)
|
||||
|
||||
return results
|
|
@ -44,6 +44,29 @@ time_range_dict = {
|
|||
'month': ('1m', 'm'),
|
||||
}
|
||||
|
||||
region2domain = {
|
||||
"CO": "co.search.yahoo.com", # Colombia
|
||||
"TH": "th.search.yahoo.com", # Thailand
|
||||
"VE": "ve.search.yahoo.com", # Venezuela
|
||||
"CL": "cl.search.yahoo.com", # Chile
|
||||
"HK": "hk.search.yahoo.com", # Hong Kong
|
||||
"PE": "pe.search.yahoo.com", # Peru
|
||||
"CA": "ca.search.yahoo.com", # Canada
|
||||
"DE": "de.search.yahoo.com", # Germany
|
||||
"FR": "fr.search.yahoo.com", # France
|
||||
"TW": "tw.search.yahoo.com", # Taiwan
|
||||
"GB": "uk.search.yahoo.com", # United Kingdom
|
||||
"UK": "uk.search.yahoo.com",
|
||||
"BR": "br.search.yahoo.com", # Brazil
|
||||
"IN": "in.search.yahoo.com", # India
|
||||
"ES": "espanol.search.yahoo.com", # Espanol
|
||||
"PH": "ph.search.yahoo.com", # Philippines
|
||||
"AR": "ar.search.yahoo.com", # Argentina
|
||||
"MX": "mx.search.yahoo.com", # Mexico
|
||||
"SG": "sg.search.yahoo.com", # Singapore
|
||||
}
|
||||
"""Map regions to domain"""
|
||||
|
||||
lang2domain = {
|
||||
'zh_chs': 'hk.search.yahoo.com',
|
||||
'zh_cht': 'tw.search.yahoo.com',
|
||||
|
@ -65,40 +88,40 @@ lang2domain = {
|
|||
|
||||
yahoo_languages = {
|
||||
"all": "any",
|
||||
"ar": "ar",
|
||||
"bg": "bg",
|
||||
"cs": "cs",
|
||||
"da": "da",
|
||||
"de": "de",
|
||||
"el": "el",
|
||||
"en": "en",
|
||||
"es": "es",
|
||||
"et": "et",
|
||||
"fi": "fi",
|
||||
"fr": "fr",
|
||||
"he": "he",
|
||||
"hr": "hr",
|
||||
"hu": "hu",
|
||||
"it": "it",
|
||||
"ja": "ja",
|
||||
"ko": "ko",
|
||||
"lt": "lt",
|
||||
"lv": "lv",
|
||||
"nl": "nl",
|
||||
"no": "no",
|
||||
"pl": "pl",
|
||||
"pt": "pt",
|
||||
"ro": "ro",
|
||||
"ru": "ru",
|
||||
"sk": "sk",
|
||||
"sl": "sl",
|
||||
"sv": "sv",
|
||||
"th": "th",
|
||||
"tr": "tr",
|
||||
"zh": "zh_chs",
|
||||
"ar": "ar", # Arabic
|
||||
"bg": "bg", # Bulgarian
|
||||
"cs": "cs", # Czech
|
||||
"da": "da", # Danish
|
||||
"de": "de", # German
|
||||
"el": "el", # Greek
|
||||
"en": "en", # English
|
||||
"es": "es", # Spanish
|
||||
"et": "et", # Estonian
|
||||
"fi": "fi", # Finnish
|
||||
"fr": "fr", # French
|
||||
"he": "he", # Hebrew
|
||||
"hr": "hr", # Croatian
|
||||
"hu": "hu", # Hungarian
|
||||
"it": "it", # Italian
|
||||
"ja": "ja", # Japanese
|
||||
"ko": "ko", # Korean
|
||||
"lt": "lt", # Lithuanian
|
||||
"lv": "lv", # Latvian
|
||||
"nl": "nl", # Dutch
|
||||
"no": "no", # Norwegian
|
||||
"pl": "pl", # Polish
|
||||
"pt": "pt", # Portuguese
|
||||
"ro": "ro", # Romanian
|
||||
"ru": "ru", # Russian
|
||||
"sk": "sk", # Slovak
|
||||
"sl": "sl", # Slovenian
|
||||
"sv": "sv", # Swedish
|
||||
"th": "th", # Thai
|
||||
"tr": "tr", # Turkish
|
||||
"zh": "zh_chs", # Chinese (Simplified)
|
||||
"zh_Hans": "zh_chs",
|
||||
'zh-CN': "zh_chs",
|
||||
"zh_Hant": "zh_cht",
|
||||
"zh_Hant": "zh_cht", # Chinese (Traditional)
|
||||
"zh-HK": "zh_cht",
|
||||
'zh-TW': "zh_cht",
|
||||
}
|
||||
|
@ -107,7 +130,7 @@ yahoo_languages = {
|
|||
def request(query, params):
|
||||
"""build request"""
|
||||
|
||||
lang = params["language"].split("-")[0]
|
||||
lang, region = (params["language"].split("-") + [None])[:2]
|
||||
lang = yahoo_languages.get(lang, "any")
|
||||
|
||||
offset = (params['pageno'] - 1) * 7 + 1
|
||||
|
@ -127,9 +150,11 @@ def request(query, params):
|
|||
}
|
||||
)
|
||||
|
||||
domain = lang2domain.get(lang, '%s.search.yahoo.com' % lang)
|
||||
domain = region2domain.get(region)
|
||||
if not domain:
|
||||
domain = lang2domain.get(lang, '%s.search.yahoo.com' % lang)
|
||||
params['url'] = 'https://%s/search?%s' % (domain, args)
|
||||
return params
|
||||
params['domain'] = domain
|
||||
|
||||
|
||||
def parse_url(url_string):
|
||||
|
@ -157,14 +182,22 @@ def response(resp):
|
|||
results = []
|
||||
dom = html.fromstring(resp.text)
|
||||
|
||||
url_xpath = './/div[contains(@class,"compTitle")]/h3/a/@href'
|
||||
title_xpath = './/h3//a/@aria-label'
|
||||
|
||||
domain = resp.search_params['domain']
|
||||
if domain == "search.yahoo.com":
|
||||
url_xpath = './/div[contains(@class,"compTitle")]/a/@href'
|
||||
title_xpath = './/div[contains(@class,"compTitle")]/a/h3/span'
|
||||
|
||||
# parse results
|
||||
for result in eval_xpath_list(dom, '//div[contains(@class,"algo-sr")]'):
|
||||
url = eval_xpath_getindex(result, './/h3/a/@href', 0, default=None)
|
||||
url = eval_xpath_getindex(result, url_xpath, 0, default=None)
|
||||
if url is None:
|
||||
continue
|
||||
url = parse_url(url)
|
||||
|
||||
title = eval_xpath_getindex(result, './/h3//a/@aria-label', 0, default='')
|
||||
title = eval_xpath_getindex(result, title_xpath, 0, default='')
|
||||
title: str = extract_text(title)
|
||||
content = eval_xpath_getindex(result, './/div[contains(@class, "compText")]', 0, default='')
|
||||
content: str = extract_text(content, allow_none=True)
|
||||
|
|
|
@ -180,6 +180,8 @@ def fetch_traits(engine_traits: EngineTraits) -> None:
|
|||
# pylint: disable=import-outside-toplevel, too-many-branches
|
||||
|
||||
import babel
|
||||
import httpx
|
||||
|
||||
from searx.network import get # see https://github.com/searxng/searxng/issues/762
|
||||
from searx.locales import language_tag
|
||||
|
||||
|
@ -191,7 +193,7 @@ def fetch_traits(engine_traits: EngineTraits) -> None:
|
|||
|
||||
try:
|
||||
resp = get(base_url, verify=False)
|
||||
except SearxException as exc:
|
||||
except (SearxException, httpx.ConnectError) as exc:
|
||||
print(f"ERROR: zlibrary domain '{base_url}' is seized?")
|
||||
print(f" --> {exc}")
|
||||
_use_old_values()
|
||||
|
|
|
@ -42,7 +42,7 @@ class SXNG_Request(flask.Request):
|
|||
"""list of searx.plugins.Plugin.id (the id of the plugins)"""
|
||||
|
||||
preferences: "searx.preferences.Preferences"
|
||||
"""The prefernces of the request."""
|
||||
"""The preferences of the request."""
|
||||
|
||||
errors: list[str]
|
||||
"""A list of errors (translated text) added by :py:obj:`searx.webapp` in
|
||||
|
|
|
@ -140,7 +140,7 @@ class FaviconCacheConfig(msgspec.Struct): # pylint: disable=too-few-public-meth
|
|||
|
||||
@dataclasses.dataclass
|
||||
class FaviconCacheStats:
|
||||
"""Dataclass wich provides information on the status of the cache."""
|
||||
"""Dataclass which provides information on the status of the cache."""
|
||||
|
||||
favicons: int | None = None
|
||||
bytes: int | None = None
|
||||
|
@ -387,7 +387,7 @@ CREATE TABLE IF NOT EXISTS blob_map (
|
|||
self.properties.set("LAST_MAINTENANCE", "") # hint: this (also) sets the m_time of the property!
|
||||
|
||||
# Do maintenance tasks. This can be take a little more time, to avoid
|
||||
# DB locks, etablish a new DB connecton.
|
||||
# DB locks, establish a new DB connection.
|
||||
|
||||
with self.connect() as conn:
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ LOOP = None
|
|||
SSLCONTEXTS: Dict[Any, SSLContext] = {}
|
||||
|
||||
|
||||
def shuffle_ciphers(ssl_context):
|
||||
def shuffle_ciphers(ssl_context: SSLContext):
|
||||
"""Shuffle httpx's default ciphers of a SSL context randomly.
|
||||
|
||||
From `What Is TLS Fingerprint and How to Bypass It`_
|
||||
|
@ -41,16 +41,16 @@ def shuffle_ciphers(ssl_context):
|
|||
https://www.zenrows.com/blog/what-is-tls-fingerprint#how-to-bypass-tls-fingerprinting
|
||||
|
||||
"""
|
||||
c_list = httpx._config.DEFAULT_CIPHERS.split(':') # pylint: disable=protected-access
|
||||
c_list = [cipher["name"] for cipher in ssl_context.get_ciphers()]
|
||||
sc_list, c_list = c_list[:3], c_list[3:]
|
||||
random.shuffle(c_list)
|
||||
ssl_context.set_ciphers(":".join(sc_list + c_list))
|
||||
|
||||
|
||||
def get_sslcontexts(proxy_url=None, cert=None, verify=True, trust_env=True, http2=False):
|
||||
key = (proxy_url, cert, verify, trust_env, http2)
|
||||
def get_sslcontexts(proxy_url=None, cert=None, verify=True, trust_env=True):
|
||||
key = (proxy_url, cert, verify, trust_env)
|
||||
if key not in SSLCONTEXTS:
|
||||
SSLCONTEXTS[key] = httpx.create_ssl_context(cert, verify, trust_env, http2)
|
||||
SSLCONTEXTS[key] = httpx.create_ssl_context(verify, cert, trust_env)
|
||||
shuffle_ciphers(SSLCONTEXTS[key])
|
||||
return SSLCONTEXTS[key]
|
||||
|
||||
|
@ -120,7 +120,7 @@ def get_transport_for_socks_proxy(verify, http2, local_address, proxy_url, limit
|
|||
rdns = True
|
||||
|
||||
proxy_type, proxy_host, proxy_port, proxy_username, proxy_password = parse_proxy_url(proxy_url)
|
||||
verify = get_sslcontexts(proxy_url, None, verify, True, http2) if verify is True else verify
|
||||
verify = get_sslcontexts(proxy_url, None, verify, True) if verify is True else verify
|
||||
return AsyncProxyTransportFixed(
|
||||
proxy_type=proxy_type,
|
||||
proxy_host=proxy_host,
|
||||
|
@ -138,7 +138,7 @@ def get_transport_for_socks_proxy(verify, http2, local_address, proxy_url, limit
|
|||
|
||||
|
||||
def get_transport(verify, http2, local_address, proxy_url, limit, retries):
|
||||
verify = get_sslcontexts(None, None, verify, True, http2) if verify is True else verify
|
||||
verify = get_sslcontexts(None, None, verify, True) if verify is True else verify
|
||||
return httpx.AsyncHTTPTransport(
|
||||
# pylint: disable=protected-access
|
||||
verify=verify,
|
||||
|
|
|
@ -180,7 +180,7 @@ class Network:
|
|||
Network._TOR_CHECK_RESULT[proxies] = result
|
||||
return result
|
||||
|
||||
async def get_client(self, verify=None, max_redirects=None):
|
||||
async def get_client(self, verify=None, max_redirects=None) -> httpx.AsyncClient:
|
||||
verify = self.verify if verify is None else verify
|
||||
max_redirects = self.max_redirects if max_redirects is None else max_redirects
|
||||
local_address = next(self._local_addresses_cycle)
|
||||
|
@ -269,6 +269,8 @@ class Network:
|
|||
kwargs_clients = Network.extract_kwargs_clients(kwargs)
|
||||
while retries >= 0: # pragma: no cover
|
||||
client = await self.get_client(**kwargs_clients)
|
||||
cookies = kwargs.pop("cookies", None)
|
||||
client.cookies = httpx.Cookies(cookies)
|
||||
try:
|
||||
if stream:
|
||||
response = client.stream(method, url, **kwargs)
|
||||
|
|
|
@ -8,7 +8,7 @@ class OpenMetricsFamily: # pylint: disable=too-few-public-methods
|
|||
The type_hint parameter must be one of 'counter', 'gauge', 'histogram', 'summary'.
|
||||
The help_hint parameter is a short string explaining the metric.
|
||||
The data_info parameter is a dictionary of descriptionary parameters for the data point (e.g. request method/path).
|
||||
The data parameter is a flat list of the actual data in shape of a primive type.
|
||||
The data parameter is a flat list of the actual data in shape of a primitive type.
|
||||
|
||||
See https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md for more information.
|
||||
"""
|
||||
|
|
|
@ -26,7 +26,7 @@ log: logging.Logger = logging.getLogger("searx.plugins")
|
|||
|
||||
@dataclass
|
||||
class PluginInfo:
|
||||
"""Object that holds informations about a *plugin*, these infos are shown to
|
||||
"""Object that holds information about a *plugin*, these infos are shown to
|
||||
the user in the Preferences menu.
|
||||
|
||||
To be able to translate the information into other languages, the text must
|
||||
|
@ -85,7 +85,7 @@ class Plugin(abc.ABC):
|
|||
constructor (if not already set in the subclass)."""
|
||||
|
||||
info: PluginInfo
|
||||
"""Informations about the *plugin*, see :py:obj:`PluginInfo`."""
|
||||
"""Information about the *plugin*, see :py:obj:`PluginInfo`."""
|
||||
|
||||
fqn: str = ""
|
||||
|
||||
|
@ -129,8 +129,8 @@ class Plugin(abc.ABC):
|
|||
def init(self, app: "flask.Flask") -> bool: # pylint: disable=unused-argument
|
||||
"""Initialization of the plugin, the return value decides whether this
|
||||
plugin is active or not. Initialization only takes place once, at the
|
||||
time the WEB application is set up. The base methode always returns
|
||||
``True``, the methode can be overwritten in the inheritances,
|
||||
time the WEB application is set up. The base method always returns
|
||||
``True``, the method can be overwritten in the inheritances,
|
||||
|
||||
- ``True`` plugin is active
|
||||
- ``False`` plugin is inactive
|
||||
|
|
|
@ -12,24 +12,13 @@ from .online import OnlineProcessor
|
|||
parser_re = re.compile('.*?(\\d+(?:\\.\\d+)?) ([^.0-9]+) (?:in|to) ([^.0-9]+)', re.I)
|
||||
|
||||
|
||||
def normalize_name(name):
|
||||
def normalize_name(name: str):
|
||||
name = name.strip()
|
||||
name = name.lower().replace('-', ' ').rstrip('s')
|
||||
name = re.sub(' +', ' ', name)
|
||||
return unicodedata.normalize('NFKD', name).lower()
|
||||
|
||||
|
||||
def name_to_iso4217(name):
|
||||
name = normalize_name(name)
|
||||
currency = CURRENCIES['names'].get(name, [name])
|
||||
if isinstance(currency, str):
|
||||
return currency
|
||||
return currency[-1]
|
||||
|
||||
|
||||
def iso4217_to_name(iso4217, language):
|
||||
return CURRENCIES['iso4217'].get(iso4217, {}).get(language, iso4217)
|
||||
|
||||
|
||||
class OnlineCurrencyProcessor(OnlineProcessor):
|
||||
"""Processor class used by ``online_currency`` engines."""
|
||||
|
||||
|
@ -52,14 +41,15 @@ class OnlineCurrencyProcessor(OnlineProcessor):
|
|||
amount = float(amount_str)
|
||||
except ValueError:
|
||||
return None
|
||||
from_currency = name_to_iso4217(from_currency.strip())
|
||||
to_currency = name_to_iso4217(to_currency.strip())
|
||||
|
||||
from_currency = CURRENCIES.name_to_iso4217(normalize_name(from_currency))
|
||||
to_currency = CURRENCIES.name_to_iso4217(normalize_name(to_currency))
|
||||
|
||||
params['amount'] = amount
|
||||
params['from'] = from_currency
|
||||
params['to'] = to_currency
|
||||
params['from_name'] = iso4217_to_name(from_currency, 'en')
|
||||
params['to_name'] = iso4217_to_name(to_currency, 'en')
|
||||
params['from_name'] = CURRENCIES.iso4217_to_name(from_currency, "en")
|
||||
params['to_name'] = CURRENCIES.iso4217_to_name(to_currency, "en")
|
||||
return params
|
||||
|
||||
def get_default_tests(self):
|
||||
|
|
|
@ -34,7 +34,7 @@ search:
|
|||
# Filter results. 0: None, 1: Moderate, 2: Strict
|
||||
safe_search: 0
|
||||
# Existing autocomplete backends: "360search", "baidu", "brave", "dbpedia", "duckduckgo", "google", "yandex",
|
||||
# "mwmbl", "seznam", "sogou", "stract", "swisscows", "quark", "qwant", "wikipedia" -
|
||||
# "mwmbl", "naver", "seznam", "sogou", "stract", "swisscows", "quark", "qwant", "wikipedia" -
|
||||
# leave blank to turn it off by default.
|
||||
autocomplete: ""
|
||||
# minimun characters to type before autocompleter starts
|
||||
|
@ -252,8 +252,8 @@ plugins:
|
|||
#
|
||||
# hostnames:
|
||||
# replace:
|
||||
# '(.*\.)?youtube\.com$': 'invidious.example.com'
|
||||
# '(.*\.)?youtu\.be$': 'invidious.example.com'
|
||||
# '(.*\.)?youtube\.com$': 'yt.example.com'
|
||||
# '(.*\.)?youtu\.be$': 'yt.example.com'
|
||||
# '(.*\.)?reddit\.com$': 'teddit.example.com'
|
||||
# '(.*\.)?redd\.it$': 'teddit.example.com'
|
||||
# '(www\.)?twitter\.com$': 'nitter.example.com'
|
||||
|
@ -270,8 +270,8 @@ plugins:
|
|||
# replace: 'rewrite-hosts.yml'
|
||||
#
|
||||
# Content of 'rewrite-hosts.yml' (place the file in the same directory as 'settings.yml'):
|
||||
# '(.*\.)?youtube\.com$': 'invidious.example.com'
|
||||
# '(.*\.)?youtu\.be$': 'invidious.example.com'
|
||||
# '(.*\.)?youtube\.com$': 'yt.example.com'
|
||||
# '(.*\.)?youtu\.be$': 'yt.example.com'
|
||||
#
|
||||
|
||||
checker:
|
||||
|
@ -1053,7 +1053,6 @@ engines:
|
|||
|
||||
- name: material icons
|
||||
engine: material_icons
|
||||
categories: images
|
||||
shortcut: mi
|
||||
disabled: true
|
||||
|
||||
|
@ -1117,6 +1116,7 @@ engines:
|
|||
- name: il post
|
||||
engine: il_post
|
||||
shortcut: pst
|
||||
disabled: true
|
||||
|
||||
- name: huggingface
|
||||
engine: huggingface
|
||||
|
@ -1152,16 +1152,15 @@ engines:
|
|||
timeout: 6.0
|
||||
disabled: true
|
||||
|
||||
- name: invidious
|
||||
engine: invidious
|
||||
# Instanes will be selected randomly, see https://api.invidious.io/ for
|
||||
# instances that are stable (good uptime) and close to you.
|
||||
base_url:
|
||||
- https://invidious.adminforge.de
|
||||
- https://inv.nadeko.net
|
||||
shortcut: iv
|
||||
timeout: 3.0
|
||||
disabled: true
|
||||
# - name: invidious
|
||||
# engine: invidious
|
||||
# # if you want to use invidious with SearXNG you should setup one locally
|
||||
# # https://github.com/searxng/searxng/issues/2722#issuecomment-2884993248
|
||||
# base_url:
|
||||
# - https://invidious.example1.com
|
||||
# - https://invidious.example2.com
|
||||
# shortcut: iv
|
||||
# timeout: 3.0
|
||||
|
||||
- name: ipernity
|
||||
engine: ipernity
|
||||
|
@ -1237,11 +1236,13 @@ engines:
|
|||
shortcut: zlib
|
||||
categories: files
|
||||
timeout: 7.0
|
||||
disabled: true
|
||||
|
||||
- name: library of congress
|
||||
engine: loc
|
||||
shortcut: loc
|
||||
categories: images
|
||||
disabled: true
|
||||
|
||||
- name: libretranslate
|
||||
engine: libretranslate
|
||||
|
@ -1708,6 +1709,7 @@ engines:
|
|||
engine: qwant
|
||||
shortcut: qw
|
||||
categories: [general, web]
|
||||
disabled: true
|
||||
additional_tests:
|
||||
rosebud: *test_rosebud
|
||||
|
||||
|
@ -2359,25 +2361,31 @@ engines:
|
|||
disabled: true
|
||||
|
||||
- name: naver
|
||||
shortcut: nvr
|
||||
categories: [general, web]
|
||||
engine: xpath
|
||||
paging: true
|
||||
search_url: https://search.naver.com/search.naver?where=webkr&sm=osp_hty&ie=UTF-8&query={query}&start={pageno}
|
||||
url_xpath: //a[@class="link_tit"]/@href
|
||||
title_xpath: //a[@class="link_tit"]
|
||||
content_xpath: //div[@class="total_dsc_wrap"]/a
|
||||
first_page_num: 1
|
||||
page_size: 10
|
||||
engine: naver
|
||||
shortcut: nvr
|
||||
disabled: true
|
||||
|
||||
- name: naver images
|
||||
naver_category: images
|
||||
categories: [images]
|
||||
engine: naver
|
||||
shortcut: nvri
|
||||
disabled: true
|
||||
|
||||
- name: naver news
|
||||
naver_category: news
|
||||
categories: [news]
|
||||
engine: naver
|
||||
shortcut: nvrn
|
||||
disabled: true
|
||||
|
||||
- name: naver videos
|
||||
naver_category: videos
|
||||
categories: [videos]
|
||||
engine: naver
|
||||
shortcut: nvrv
|
||||
disabled: true
|
||||
about:
|
||||
website: https://www.naver.com/
|
||||
wikidata_id: Q485639
|
||||
official_api_documentation: https://developers.naver.com/docs/nmt/examples/
|
||||
use_official_api: false
|
||||
require_api_key: false
|
||||
results: HTML
|
||||
language: ko
|
||||
|
||||
- name: rubygems
|
||||
shortcut: rbg
|
||||
|
@ -2524,6 +2532,11 @@ engines:
|
|||
engine: tootfinder
|
||||
shortcut: toot
|
||||
|
||||
- name: uxwing
|
||||
engine: uxwing
|
||||
shortcut: ux
|
||||
disabled: true
|
||||
|
||||
- name: voidlinux
|
||||
engine: voidlinux
|
||||
shortcut: void
|
||||
|
|
|
@ -114,7 +114,7 @@ class SQLiteAppl(abc.ABC):
|
|||
"""
|
||||
|
||||
SQLITE_JOURNAL_MODE = "WAL"
|
||||
"""``SQLiteAppl`` applications are optimzed for WAL_ mode, its not recommend
|
||||
"""``SQLiteAppl`` applications are optimized for WAL_ mode, its not recommend
|
||||
to change the journal mode (see :py:obj:`SQLiteAppl.tear_down`).
|
||||
|
||||
.. _WAL: https://sqlite.org/wal.html
|
||||
|
@ -145,7 +145,7 @@ class SQLiteAppl(abc.ABC):
|
|||
- https://github.com/python/cpython/issues/118172
|
||||
- https://github.com/python/cpython/issues/123873
|
||||
|
||||
The workaround for SQLite3 multithreading cache inconsistency ist to set
|
||||
The workaround for SQLite3 multithreading cache inconsistency is to set
|
||||
option ``cached_statements`` to ``0`` by default.
|
||||
"""
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
searx/static/themes/simple/js/searxng.min.js
vendored
4
searx/static/themes/simple/js/searxng.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -64,7 +64,7 @@
|
|||
</main>
|
||||
<footer>
|
||||
<p>
|
||||
{{ _('Powered by') }} <a href="{{ url_for('info', pagename='about') }}">searxng</a> - {{ searx_version }} — {{ _('a privacy-respecting, open metasearch engine') }}<br>
|
||||
{{ _('Powered by') }} <a href="{{ url_for('info', pagename='about') }}">SearXNG</a> - {{ searx_version }} — {{ _('a privacy-respecting, open metasearch engine') }}<br>
|
||||
<a href="{{ searx_git_url }}">{{ _('Source code') }}</a>
|
||||
| <a href="{{ get_setting('brand.issue_url') }}">{{ _('Issue tracker') }}</a>
|
||||
{% if enable_metrics %}| <a href="{{ url_for('stats') }}">{{ _('Engine stats') }}</a>{% endif %}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" tabindex="1" autocomplete="off" autocapitalize="none" spellcheck="false" autocorrect="off" dir="auto" value="{{ q or '' }}">
|
||||
<button id="clear_search" type="reset" aria-label="{{ _('clear') }}" class="hide_if_nojs"><span>{{ icon_big('close') }}</span><span class="show_if_nojs">{{ _('clear') }}</span></button>
|
||||
<button id="send_search" type="submit" {%- if search_on_category_select -%}name="category_{{ selected_categories[0]|replace(' ', '_') }}"{%- endif -%} aria-label="{{ _('search') }}"><span class="hide_if_nojs">{{ icon_big('search') }}</span><span class="show_if_nojs">{{ _('search') }}</span></button>
|
||||
<div class="autocomplete hide_if_nojs"><ul></ul></div>
|
||||
</div>
|
||||
</div>
|
||||
{% set display_tooltip = true %}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" autocomplete="off" autocapitalize="none" spellcheck="false" autocorrect="off" dir="auto" value="{{ q or '' }}">
|
||||
<button id="clear_search" type="reset" aria-label="{{ _('clear') }}"><span class="hide_if_nojs">{{ icon_big('close') }}</span><span class="show_if_nojs">{{ _('clear') }}</span></button>
|
||||
<button id="send_search" type="submit" aria-label="{{ _('search') }}"><span class="hide_if_nojs">{{ icon_big('search') }}</span><span class="show_if_nojs">{{ _('search') }}</span></button>
|
||||
<div class="autocomplete hide_if_nojs"><ul></ul></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Binary file not shown.
|
@ -19,7 +19,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-01-28 06:11+0000\n"
|
||||
"Last-Translator: return42 <return42@users.noreply.translate.codeberg.org>"
|
||||
"\n"
|
||||
|
@ -73,7 +73,7 @@ msgid "videos"
|
|||
msgstr "video's"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "draadloos"
|
||||
|
||||
|
@ -350,93 +350,93 @@ msgstr "toe"
|
|||
msgid "answered"
|
||||
msgstr "geantwoord"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "Geen item gevind"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "Bron"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "Fout met die laai van die volgende bladsy"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "Ongeldige opstellings, redigeer asb jou voorkeure"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "Ongeldige opstellings"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "soekfout"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "tydsverloop"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "ontledingsfout"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "HTTP protokol fout"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "netwerk fout"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "SSL vout: Kon nie sertifikaat verifieer nie"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "onverwagse breek"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "HTTP fout"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "HTTP koppelingsfout"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "proksie fout"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "te veel versoeke"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "toegang geweier"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "bediener API fout"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "Opgehef"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "{minutes} minute terug"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "{hours} ure, {minutes} minute terug"
|
||||
|
@ -467,15 +467,15 @@ msgstr "Hierdie inskrywing was vervang deur"
|
|||
msgid "Channel"
|
||||
msgstr "Kanaal"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "bitsnelheid"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "stemme"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "klikke"
|
||||
|
||||
|
@ -484,7 +484,7 @@ msgstr "klikke"
|
|||
msgid "Language"
|
||||
msgstr "Taal"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -711,10 +711,6 @@ msgstr "Outeur"
|
|||
msgid "cached"
|
||||
msgstr "gekas"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "gevolmagtig"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Begin om 'n nuwe probleem op GitHub in te dien"
|
||||
|
@ -1826,3 +1822,6 @@ msgstr "versteek video"
|
|||
#~ "gebruik word om voorkeure oor toestelle"
|
||||
#~ " heen te sinkroniseer."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "gevolmagtig"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -28,20 +28,19 @@
|
|||
# DZDevelopers <dzdevelopers@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: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-04-15 10:37+0000\n"
|
||||
"Last-Translator: DZDevelopers <dzdevelopers@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 5.10.2\n"
|
||||
"Generated-By: Babel 2.17.0\n"
|
||||
|
||||
#. CONSTANT_NAMES['NO_SUBGROUPING']
|
||||
|
@ -85,7 +84,7 @@ msgid "videos"
|
|||
msgstr "ڤيديوهات"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "راديو"
|
||||
|
||||
|
@ -362,93 +361,93 @@ msgstr "مغلق"
|
|||
msgid "answered"
|
||||
msgstr "أُجيبت"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "تعذر العثور على عناصر"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "المصدر"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "حدث خلل أثناء تحميل الصفحة التالية"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "إنّ الإعدادات خاطئة، يرجى تعديل خياراتك"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "إعدادات غير صالحة"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "خطأ في البحث"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "نفذ الوقت"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "خطأ تحليل"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "خطأ في بروتوكول HTTP"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "خطأ في الشبكة"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "خطأ SSL: فشل التحقق من صحة الشهادة"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "تعطل غير متوقع"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "خطأ HTTP"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "خطأ في اتصال HTTP"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "خطأ في وكيل البروكسي"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "أسئلة التحقق"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "الكثير من الطلبات"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "الدخول مرفوض"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "خطأ في API الخادم"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "معلق"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "{minutes} minute(s) ago"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "قبل {hours} ساعات، {minutes} دقائق"
|
||||
|
@ -479,15 +478,15 @@ msgstr "هذا الإدخال تم استبداله بـ"
|
|||
msgid "Channel"
|
||||
msgstr "القناة"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "معدل البت"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "تصويتات"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "نقرات"
|
||||
|
||||
|
@ -496,7 +495,7 @@ msgstr "نقرات"
|
|||
msgid "Language"
|
||||
msgstr "اللغة"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -724,10 +723,6 @@ msgstr "الكاتب"
|
|||
msgid "cached"
|
||||
msgstr "النسخة المخبأة"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "المخدم البروكسي"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "ابدأ بتقديم قضية جديدة على GitHub"
|
||||
|
@ -1191,8 +1186,8 @@ msgid ""
|
|||
"A URL containing your preferences. This URL can be used to restore your "
|
||||
"settings on a different device."
|
||||
msgstr ""
|
||||
"رابط يحتوي على تفضيلاتك. يمكن استخدام هذا الرابط لاستعادة إعداداتك على جهاز "
|
||||
"مختلف."
|
||||
"رابط يحتوي على تفضيلاتك. يمكن استخدام هذا الرابط لاستعادة إعداداتك على "
|
||||
"جهاز مختلف."
|
||||
|
||||
#: searx/templates/simple/preferences/cookies.html:46
|
||||
msgid "Copy preferences hash"
|
||||
|
@ -2084,3 +2079,7 @@ msgstr "إخفاء الفيديو"
|
|||
#~ "يمكن استخدام تحديد الإعدادات المخصصة في"
|
||||
#~ " تفضيلات URL لمزامنة التفضيلات عبر "
|
||||
#~ "الأجهزة."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "المخدم البروكسي"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -16,20 +16,22 @@
|
|||
# Anonymous <anonymous@users.noreply.translate.codeberg.org>, 2025.
|
||||
# thenack0 <thenack0@users.noreply.translate.codeberg.org>, 2025.
|
||||
# return42 <return42@noreply.codeberg.org>, 2025.
|
||||
# devrimer <devrimer@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: 2025-03-29 09:21+0000\n"
|
||||
"PO-Revision-Date: 2025-03-14 07:09+0000\n"
|
||||
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-05-16 04:04+0000\n"
|
||||
"Last-Translator: devrimer <devrimer@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 5.11.4\n"
|
||||
"Generated-By: Babel 2.17.0\n"
|
||||
|
||||
#. CONSTANT_NAMES['NO_SUBGROUPING']
|
||||
|
@ -73,7 +75,7 @@ msgid "videos"
|
|||
msgstr "видео"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "радио"
|
||||
|
||||
|
@ -350,93 +352,93 @@ msgstr "Затворено"
|
|||
msgid "answered"
|
||||
msgstr "Отговорено"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "Не е намерен артикул"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "Източник"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "Грешка при зареждането на следващата страница"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "Неправилни настройки, моля редактирайте предпочитанията си"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "Невалидни настройки"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "Грешка при търсенето"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "изчакване"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "грешка при анализа"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "Грешка в протокола HTTP"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "мрежова грешка"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "SSL грешка: проверката на сертификата е неуспешна"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "неочакван срив"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "HTTP грешка"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "HTTP грешка във връзката"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "прокси грешка"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "твърде много повиквания"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "отказан достъп"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "грешка в API на сървъра"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "преустановен"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "преди {minutes} минута(минути)"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "преди {hours} час(ове), {minutes} минута(минути)"
|
||||
|
@ -448,7 +450,7 @@ msgstr "Генерирайте различни произволни стойн
|
|||
#: searx/answerers/statistics.py:36
|
||||
#, python-brace-format
|
||||
msgid "Compute {func} of the arguments"
|
||||
msgstr ""
|
||||
msgstr "Изчислете {func} на аргументите"
|
||||
|
||||
#: searx/engines/openstreetmap.py:158
|
||||
msgid "Show route in map .."
|
||||
|
@ -467,15 +469,15 @@ msgstr "Този запис е заменен от"
|
|||
msgid "Channel"
|
||||
msgstr "Канал"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "Скорост"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "Гласове"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "клика"
|
||||
|
||||
|
@ -484,7 +486,7 @@ msgstr "клика"
|
|||
msgid "Language"
|
||||
msgstr "Език"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -712,10 +714,6 @@ msgstr "Автор"
|
|||
msgid "cached"
|
||||
msgstr "кеширана"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "прекарана"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Предявете нов проблем в GitHub"
|
||||
|
@ -2083,3 +2081,5 @@ msgstr "скрий видеото"
|
|||
#~ "позволи синхронизация между различни "
|
||||
#~ "устройства."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "прекарана"
|
||||
|
|
Binary file not shown.
|
@ -26,7 +26,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-03-06 09:54+0000\n"
|
||||
"Last-Translator: MonsoonFire <monsoonfire@noreply.codeberg.org>\n"
|
||||
"Language: bn\n"
|
||||
|
@ -79,7 +79,7 @@ msgid "videos"
|
|||
msgstr "ভিডিও"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "বেতার"
|
||||
|
||||
|
@ -356,93 +356,93 @@ msgstr "বন্ধ"
|
|||
msgid "answered"
|
||||
msgstr "উত্তরকৃত"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "কোন আইটেম পাওয়া যায়নি"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "উৎস"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "পরবর্তী পৃষ্ঠাটি লোড করায় ত্রুটি দেখা যাচ্ছে"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "অকেজো সেটিংস, অনুগ্রহ করে আপনার পছন্দগুলি সম্পাদনা করুন"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "অকেজো সেটিংস"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "সার্চ ত্রুটি"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "সময় শেষ"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "পার্স ত্রুটি"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "HTTP প্রোটোকল ত্রুটি"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "নেটওয়ার্ক ত্রুটি"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "SSL ত্রুটি: সার্টিফিকেট বৈধতা ব্যর্থ হয়েছে৷"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "অপ্রত্যাশিত ক্র্যাশ"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "HTTP ত্রুটি"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "HTTP সংযোগ ত্রুটি"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "প্রক্সি ত্রুটি"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "ক্যাপচা"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "অনেক বেশি অনুরোধ"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "প্রবেশ অগ্রাহ্য করা হল"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "সার্ভার API ত্রুটি"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "স্থগিত"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "{minutes} মিনিট আগে"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "{hours} ঘণ্টা, {minutes} মিনিট আগে"
|
||||
|
@ -473,15 +473,15 @@ msgstr "এই এনট্রিটি দ্বারা বাতিল ক
|
|||
msgid "Channel"
|
||||
msgstr "চ্যানেল"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "বিটরেট"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "ভোট"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "ক্লিক সংখ্যা"
|
||||
|
||||
|
@ -490,7 +490,7 @@ msgstr "ক্লিক সংখ্যা"
|
|||
msgid "Language"
|
||||
msgstr "ভাষা"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -716,10 +716,6 @@ msgstr "লেখক"
|
|||
msgid "cached"
|
||||
msgstr "ক্যাশকৃত"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "প্রক্সিকৃত"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "GitHub এ একটি নতুন সমস্যা জমা দেওয়া শুরু করুন"
|
||||
|
@ -1843,3 +1839,6 @@ msgstr "ভিডিও লুকিয়ে ফেলুন"
|
|||
#~ "প্রেফারেন্সগুলি ডিভাইস জুড়ে সিঙ্ক করে "
|
||||
#~ "ব্যবহার করতে পারেন।"
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "প্রক্সিকৃত"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -12,7 +12,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: searx\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-01-06 15:52+0000\n"
|
||||
"Last-Translator: return42 <return42@users.noreply.translate.codeberg.org>"
|
||||
"\n"
|
||||
|
@ -66,7 +66,7 @@ msgid "videos"
|
|||
msgstr "བརྙན་ཟློས།"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr ""
|
||||
|
||||
|
@ -343,93 +343,93 @@ msgstr ""
|
|||
msgid "answered"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "རྣམ་གྲངས་གང་ཡང་རྙེད་རྒྱུ་མ་བྱུང་།"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "ནུས་མེད་ཀྱི་སྒྲིག་འགོད།ཁྱེད་ཀྱིས་གདམ་ཀ་ལ་བཅོས་སྒྲིག་གཏོང་རོགས།"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "ནུས་མེད་ཀྱི་སྒྲིག་འགོད།"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "འཚོལ་བཤེར་ལ་ནོར་འཁྲུལ་བྱུང་།"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "སྐར་མ་ {minutes} སྔོན་ལ།"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "ཆུ་ཚོད་ {hours} དང་སྐར་མ {minutes} སྔོན་ལ།"
|
||||
|
@ -460,15 +460,15 @@ msgstr "འཚོལ་བྱང་འདི་གཞན་གྱིས་ཚབ
|
|||
msgid "Channel"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr ""
|
||||
|
||||
|
@ -477,7 +477,7 @@ msgstr ""
|
|||
msgid "Language"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -689,10 +689,6 @@ msgstr ""
|
|||
msgid "cached"
|
||||
msgstr "འདྲ་བཤུས་རྒྱབ་ཚར།"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "མངག་བཅོལ་བྱེད་ཟིན།"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr ""
|
||||
|
@ -1994,3 +1990,6 @@ msgstr "རྙན་ཟློས་སྦས།"
|
|||
#~ "sync preferences across devices."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "མངག་བཅོལ་བྱེད་ཟིན།"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -26,7 +26,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: searx\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-01-06 15:52+0000\n"
|
||||
"Last-Translator: sserra <sserra@users.noreply.translate.codeberg.org>\n"
|
||||
"Language: ca\n"
|
||||
|
@ -79,7 +79,7 @@ msgid "videos"
|
|||
msgstr "vídeos"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "radio"
|
||||
|
||||
|
@ -356,93 +356,93 @@ msgstr "tancat"
|
|||
msgid "answered"
|
||||
msgstr "contestat"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "No s'ha trobat cap element"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "Origen"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "S'ha produït un error en carregar la següent pàgina"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "La configuració no és vàlida, editeu-la"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "La configuració no és vàlida"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "error de cerca"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "expirat"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "error de processament"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "error del protocol HTTP"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "error de xarxa"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "error de SSL: la validació del certificat ha fallat"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "error inesperat"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "error de HTTP"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "error de connexió HTTP"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "error del servidor intermediari"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "masses peticions"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "accés denegat"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "error en l'API del servidor"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "Suspès"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "fa {minutes} minut(s)"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "fa {hours} hores i {minutes} minut(s)"
|
||||
|
@ -473,15 +473,15 @@ msgstr "Aquesta entrada ha estat substituïda per"
|
|||
msgid "Channel"
|
||||
msgstr "Canal"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "tasa de bits"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "vots"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "clics"
|
||||
|
||||
|
@ -490,7 +490,7 @@ msgstr "clics"
|
|||
msgid "Language"
|
||||
msgstr "Llengua"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -716,10 +716,6 @@ msgstr "Autor"
|
|||
msgid "cached"
|
||||
msgstr "en memòria cau"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "en servidor intermediari"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Obriu una incidència a GitHub"
|
||||
|
@ -2100,3 +2096,6 @@ msgstr "oculta el vídeo"
|
|||
#~ " l'URL de preferències pot usar-se"
|
||||
#~ " per sincronitzar entre dispositius."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "en servidor intermediari"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -22,20 +22,19 @@
|
|||
# Fjuro <fjuro@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: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-03-30 16:28+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 5.10.2\n"
|
||||
"Generated-By: Babel 2.17.0\n"
|
||||
|
||||
#. CONSTANT_NAMES['NO_SUBGROUPING']
|
||||
|
@ -79,7 +78,7 @@ msgid "videos"
|
|||
msgstr "videa"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "rádio"
|
||||
|
||||
|
@ -356,93 +355,93 @@ msgstr "zavřené"
|
|||
msgid "answered"
|
||||
msgstr "zodpovězené"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "Nic nenalezeno"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "zdroj"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "Chyba při načítání další stránky"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "Neplatné nastavení, upravte své předvolby"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "Neplatné nastavení"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "chyba vyhledávání"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "čas vypršel"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "chyba parsování"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "chyba HTTP protokolu"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "síťová chyba"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "chyba SSL: ověření certifikátu selhalo"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "nečekaná chyba"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "chyba HTTP"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "Chyba spojení HTTP"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "chyba proxy"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "příliš mnoho požadavků"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "přístup odepřen"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "chyba API serveru"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "Pozastaveno"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "před {minutes} minutami"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "před {hours} hodinami, {minutes} minutami"
|
||||
|
@ -473,15 +472,15 @@ msgstr "Tato položka byla nahrazena položkou"
|
|||
msgid "Channel"
|
||||
msgstr "Kanál"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "datový tok"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "hlasy"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "kliknutí"
|
||||
|
||||
|
@ -490,7 +489,7 @@ msgstr "kliknutí"
|
|||
msgid "Language"
|
||||
msgstr "Jazyk"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -608,9 +607,9 @@ msgid ""
|
|||
"This plugin checks if the address of the request is a Tor exit-node, and "
|
||||
"informs the user if it is; like check.torproject.org, but from SearXNG."
|
||||
msgstr ""
|
||||
"Tento doplněk kontroluje, zda je adresa požadavku výstupním uzlem sítě Tor, "
|
||||
"a informuje uživatele, pokud tomu tak je; jako check.torproject.org, ale od "
|
||||
"SearXNG."
|
||||
"Tento doplněk kontroluje, zda je adresa požadavku výstupním uzlem sítě "
|
||||
"Tor, a informuje uživatele, pokud tomu tak je; jako check.torproject.org,"
|
||||
" ale od SearXNG."
|
||||
|
||||
#: searx/plugins/tor_check.py:65
|
||||
msgid "Could not download the list of Tor exit-nodes from"
|
||||
|
@ -718,10 +717,6 @@ msgstr "Autor"
|
|||
msgid "cached"
|
||||
msgstr "archivovaná verze"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "přes proxy"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Začněte přidávat novou chybu na Githubu"
|
||||
|
@ -2089,3 +2084,7 @@ msgstr "skrýt video"
|
|||
#~ "Zadání vlastních nastavení v URL "
|
||||
#~ "předvoleb lze použít k synchronizaci "
|
||||
#~ "předvoleb mezi zařízeními."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "přes proxy"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -19,7 +19,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: searx\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-03-07 00:07+0000\n"
|
||||
"Last-Translator: DanielBoone <danielboone@noreply.codeberg.org>\n"
|
||||
"Language: cy\n"
|
||||
|
@ -73,7 +73,7 @@ msgid "videos"
|
|||
msgstr "fideos"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "radio"
|
||||
|
||||
|
@ -350,93 +350,93 @@ msgstr "ar gau"
|
|||
msgid "answered"
|
||||
msgstr "wedi'i ateb"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "Ni chanfuwyd eitem"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "Ffynhonnell"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "Gwall wrth lwytho'r dudalen nesaf"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "Gosodiadau annilys, golygwch eich dewisiadau"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "Gosodiadau annilys"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "gwall chwilio"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "terfyn amser"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "gwall dosrannu"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "gwall protocol HTTP"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "gwall rhwydwaith"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "Gwall SSL: dilysu tystysgrif wedi methu"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "damwain annisgwyl"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "gwall HTTP"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "gwall cysylltiad HTTP"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "gwall dirprwy"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "gormod o geisiadau"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "mynediad wedi ei wrthod"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "gwall API gweinydd"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "Atal"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "{minutes} munud yn ôl"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "{hours} awr, {minutes} munud yn ôl"
|
||||
|
@ -467,15 +467,15 @@ msgstr "Mae'r cofnod hwn wedi ei ddisodli gan"
|
|||
msgid "Channel"
|
||||
msgstr "Sianel"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "cyfradd didau"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "pleidleisiau"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "cliciau"
|
||||
|
||||
|
@ -484,7 +484,7 @@ msgstr "cliciau"
|
|||
msgid "Language"
|
||||
msgstr "Iaith"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -711,10 +711,6 @@ msgstr "Awdur"
|
|||
msgid "cached"
|
||||
msgstr "wedi'i storio"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "wedi'i ddirprwyo"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Dechrau cyflwyno problem newydd ar GitHub"
|
||||
|
@ -2052,3 +2048,6 @@ msgstr "cuddio'r fideo"
|
|||
#~ "gysoni eich dewisiadau ar draws "
|
||||
#~ "dyfeisiau."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "wedi'i ddirprwyo"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -16,19 +16,18 @@
|
|||
# AndersNordh <andersnordh@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: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-03-31 14:03+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 5.10.2\n"
|
||||
"Generated-By: Babel 2.17.0\n"
|
||||
|
||||
#. CONSTANT_NAMES['NO_SUBGROUPING']
|
||||
|
@ -72,7 +71,7 @@ msgid "videos"
|
|||
msgstr "videoer"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "Radio"
|
||||
|
||||
|
@ -349,93 +348,93 @@ msgstr "lukket"
|
|||
msgid "answered"
|
||||
msgstr "svaret"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "Intet fundet"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "Kilde"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "Fejl ved indlæsning af den næste side"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "Ugyldige indstillinger, redigér venligst dine valg"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "Ugyldig indstilling"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "søgefejl"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "udløbstid"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "fortolkningsfejl"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "HTTP-protokolfejl"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "netværksfejl"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "SSL-fejl: certifikatvalidering mislykkedes"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "uventet nedbrud"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "HTTP-fejl"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "HTTP-tilkoblingsfejl"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "proxyfejl"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "for mange forespørgsler"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "adgang nægtet"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "server-API-fejl"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "Suspenderet"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "for {minutes} minut(ter) siden"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "for {hours} time(r) og {minutes} minut(ter) siden"
|
||||
|
@ -466,15 +465,15 @@ msgstr "Denne værdi er blevet overskrevet af"
|
|||
msgid "Channel"
|
||||
msgstr "Kanal"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "Bitrate"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "Stemmer"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "Klik"
|
||||
|
||||
|
@ -483,7 +482,7 @@ msgstr "Klik"
|
|||
msgid "Language"
|
||||
msgstr "Sprog"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -712,10 +711,6 @@ msgstr "Forfatter"
|
|||
msgid "cached"
|
||||
msgstr "cachet"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "viderestillet"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Begynd at indsende et nyt problem på GitHub"
|
||||
|
@ -2089,3 +2084,7 @@ msgstr "skjul video"
|
|||
#~ "Specificere brugertilpassede indstillinger i "
|
||||
#~ "præference-URL'en kan bruges til at "
|
||||
#~ "synkronisere præference over flere enheder."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "viderestillet"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -27,19 +27,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: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-03-30 07:37+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 5.10.2\n"
|
||||
"Generated-By: Babel 2.17.0\n"
|
||||
|
||||
#. CONSTANT_NAMES['NO_SUBGROUPING']
|
||||
|
@ -83,7 +82,7 @@ msgid "videos"
|
|||
msgstr "Videos"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "Radio"
|
||||
|
||||
|
@ -360,93 +359,93 @@ msgstr "geschlossen"
|
|||
msgid "answered"
|
||||
msgstr "beantwortet"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "Keine Einträge gefunden"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "Quelle"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "Fehler beim Laden der nächsten Seite"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "Ungültige Einstellungen, bitte Einstellungen ändern"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "Ungültige Einstellungen"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "Suchfehler"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "Zeitüberschreitung"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "Fehler beim Parsen"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "HTTP-Protokollfehler"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "Netzwerkfehler"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "SSL Fehler: Zertifikatsprüfung ist fehlgeschlagen"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "unerwarteter Absturz"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "HTTP-Fehler"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "HTTP-Verbindungsfehler"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "Proxy-Fehler"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "zu viele Anfragen"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "Zugriff verweigert"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "Server-API-Fehler"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "Ausgesetzt"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "vor {minutes} Minute(n)"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "vor {hours} Stunde(n), {minutes} Minute(n)"
|
||||
|
@ -477,15 +476,15 @@ msgstr "Dieser Eintrag wurde überschrieben von"
|
|||
msgid "Channel"
|
||||
msgstr "Kanal"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "Bitrate"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "Stimmen"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "Clicks"
|
||||
|
||||
|
@ -494,7 +493,7 @@ msgstr "Clicks"
|
|||
msgid "Language"
|
||||
msgstr "Sprache"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -540,8 +539,7 @@ msgstr "Ahmia blacklist"
|
|||
|
||||
#: searx/plugins/ahmia_filter.py:33
|
||||
msgid "Filter out onion results that appear in Ahmia's blacklist."
|
||||
msgstr ""
|
||||
"Filtern der Onion Links, die in der schwarzen Liste von Ahmia erscheinen."
|
||||
msgstr "Filtern der Onion Links, die in der schwarzen Liste von Ahmia erscheinen."
|
||||
|
||||
#: searx/plugins/calculator.py:38
|
||||
msgid "Basic Calculator"
|
||||
|
@ -726,10 +724,6 @@ msgstr "Autor"
|
|||
msgid "cached"
|
||||
msgstr "Im Cache"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "proxy"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Fehlerbericht auf GitHub erstellen"
|
||||
|
@ -1200,8 +1194,8 @@ msgid ""
|
|||
"A URL containing your preferences. This URL can be used to restore your "
|
||||
"settings on a different device."
|
||||
msgstr ""
|
||||
"URL die Ihre Einstellungen enthält. Diese URL kann verwendet werden, um Ihre "
|
||||
"Einstellungen auf einem anderen Gerät wiederherzustellen"
|
||||
"URL die Ihre Einstellungen enthält. Diese URL kann verwendet werden, um "
|
||||
"Ihre Einstellungen auf einem anderen Gerät wiederherzustellen"
|
||||
|
||||
#: searx/templates/simple/preferences/cookies.html:46
|
||||
msgid "Copy preferences hash"
|
||||
|
@ -2129,3 +2123,7 @@ msgstr "Video verstecken"
|
|||
#~ "anderen Browser werden die aktuellen "
|
||||
#~ "Einstellungen in dem anderen Browser "
|
||||
#~ "gespeichert (Cookie)."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "proxy"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-01-06 15:52+0000\n"
|
||||
"Last-Translator: Anonymous "
|
||||
"<anonymous@users.noreply.translate.codeberg.org>\n"
|
||||
|
@ -62,7 +62,7 @@ msgid "videos"
|
|||
msgstr "ވީޑިޔޯތައް"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr ""
|
||||
|
||||
|
@ -339,93 +339,93 @@ msgstr ""
|
|||
msgid "answered"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
@ -456,15 +456,15 @@ msgstr ""
|
|||
msgid "Channel"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr ""
|
||||
|
||||
|
@ -473,7 +473,7 @@ msgstr ""
|
|||
msgid "Language"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -685,10 +685,6 @@ msgstr ""
|
|||
msgid "cached"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr ""
|
||||
|
@ -1723,3 +1719,6 @@ msgstr ""
|
|||
#~ "sync preferences across devices."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr ""
|
||||
|
||||
|
|
Binary file not shown.
|
@ -22,19 +22,18 @@
|
|||
# sakistzimas <sakistzimas@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: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-04-03 21:59+0000\n"
|
||||
"Last-Translator: sakistzimas <sakistzimas@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 5.10.2\n"
|
||||
"Generated-By: Babel 2.17.0\n"
|
||||
|
||||
#. CONSTANT_NAMES['NO_SUBGROUPING']
|
||||
|
@ -78,7 +77,7 @@ msgid "videos"
|
|||
msgstr "Βίντεο"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "ράδιο"
|
||||
|
||||
|
@ -355,93 +354,93 @@ msgstr "κλειστό"
|
|||
msgid "answered"
|
||||
msgstr "απάντησε"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "Δεν βρέθηκαν αντικείμενα"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "Πηγή"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "Σφάλμα φόρτωσης της επόμενης σελίδας"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "Μη έγκυρες ρυθμίσεις, παρακαλούμε ελέγξτε τις προτιμήσεις σας"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "Μη έγκυρες ρυθμίσεις"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "σφάλμα αναζήτησης"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "Λήξη χρόνου"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "σφάλμα ανάλυσης"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "Σφάλμα πρωτοκόλλου HTTP"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "Σφάλμα δικτύου"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "Σφάλμα SSL: η επικύρωση του πιστοποιητικού απέτυχε"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "Απροσδόκητο σφάλμα"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "Σφάλμα HTTP"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "Σφάλμα σύνδεσης HTTP"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "Σφάλμα διακομιστή μεσολάβησης"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "υπέρβαση ορίου αιτημάτων"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "Άρνηση πρόσβασης"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "Σφάλμα API διακομιστή"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "Σε αναστολή"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "{minutes} λεπτά πριν"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "{hours} ώρα(-ες), {minutes} λεπτό(-ά) πριν"
|
||||
|
@ -472,15 +471,15 @@ msgstr "Αυτή η καταχώριση έχει αντικατασταθεί
|
|||
msgid "Channel"
|
||||
msgstr "Κανάλι"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "ρυθμός μετάδοσης"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "ψήφους"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "κλικ"
|
||||
|
||||
|
@ -489,7 +488,7 @@ msgstr "κλικ"
|
|||
msgid "Language"
|
||||
msgstr "Γλώσσα"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -720,10 +719,6 @@ msgstr "Συγγραφέας"
|
|||
msgid "cached"
|
||||
msgstr "προσωρινά αποθηκευμένο"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "Διαμεσολαβημένα"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Ξεκινήστε την υποβολή ενός νέου ζητήματος στο GitHub"
|
||||
|
@ -1197,7 +1192,8 @@ msgid ""
|
|||
"settings on a different device."
|
||||
msgstr ""
|
||||
"Ένα URL που περιέχει τις προτιμήσεις σας. Αυτό το URL μπορεί να "
|
||||
"χρησιμοποιηθεί για να επαναφέρει τις ρυθμίσεις σας σε διαφορετική συσκευή."
|
||||
"χρησιμοποιηθεί για να επαναφέρει τις ρυθμίσεις σας σε διαφορετική "
|
||||
"συσκευή."
|
||||
|
||||
#: searx/templates/simple/preferences/cookies.html:46
|
||||
msgid "Copy preferences hash"
|
||||
|
@ -2108,3 +2104,7 @@ msgstr "απόκρυψη βίντεο"
|
|||
#~ "σύνδεσμο προτιμήσεων μπορεί να χρησιμοποιηθεί"
|
||||
#~ " για το συγχρονισμό των προτιμήσεων "
|
||||
#~ "σας σε όλες τις συσκευές."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "Διαμεσολαβημένα"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+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:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr ""
|
||||
|
||||
|
@ -336,93 +336,93 @@ msgstr ""
|
|||
msgid "answered"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
@ -453,15 +453,15 @@ msgstr ""
|
|||
msgid "Channel"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr ""
|
||||
|
||||
|
@ -470,7 +470,7 @@ msgstr ""
|
|||
msgid "Language"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -682,10 +682,6 @@ msgstr ""
|
|||
msgid "cached"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr ""
|
||||
|
@ -1988,3 +1984,6 @@ msgstr ""
|
|||
#~ "sync preferences across devices."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr ""
|
||||
|
||||
|
|
Binary file not shown.
|
@ -21,19 +21,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: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-05-09 07:09+0000\n"
|
||||
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
|
||||
"Language-Team: Esperanto <https://translate.codeberg.org/projects/searxng/"
|
||||
"searxng/eo/>\n"
|
||||
"Language: eo\n"
|
||||
"Language-Team: Esperanto "
|
||||
"<https://translate.codeberg.org/projects/searxng/searxng/eo/>\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 5.10.2\n"
|
||||
"Generated-By: Babel 2.17.0\n"
|
||||
|
||||
#. CONSTANT_NAMES['NO_SUBGROUPING']
|
||||
|
@ -77,7 +76,7 @@ msgid "videos"
|
|||
msgstr "videoj"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "radio"
|
||||
|
||||
|
@ -354,93 +353,93 @@ msgstr ""
|
|||
msgid "answered"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "Nenio trovita"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "Fonto"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "Eraro dum la ŝarĝado de la sekvan paĝon"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "Nevalidaj agordoj, bonvolu redaktu viajn agordojn"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "Nevalidaj agordoj"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "serĉa eraro"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "eltempiĝo"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "analiza eraro"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "HTTP-protokolo-eraro"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "reta eraro"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "SSL-eraro: atestila validigo malsukcesis"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "neatendita kraŝo"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "HTTP-eraro"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "HTTP-konekto-eraro"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "prokurilo-eraro"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "tro da petoj"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "aliro rifuzita"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "servilo-API-eraro"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "Suspendigita"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "antaŭ {minutes} minuto(j)"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "antaŭ {hours} horo(j), {minutes} minuto(j)"
|
||||
|
@ -471,15 +470,15 @@ msgstr "Tiu ĉi enigo estis anstataŭigita per"
|
|||
msgid "Channel"
|
||||
msgstr "Kanalo"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "bito-rapido"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "voĉoj"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "klakoj"
|
||||
|
||||
|
@ -488,7 +487,7 @@ msgstr "klakoj"
|
|||
msgid "Language"
|
||||
msgstr "Lingvo"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -712,10 +711,6 @@ msgstr "Verkisto"
|
|||
msgid "cached"
|
||||
msgstr "kaŝmemorigita"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "prokurata"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Komencu sendi novan numeron en GitHub"
|
||||
|
@ -2068,3 +2063,7 @@ msgstr "kaŝi videojn"
|
|||
#~ "Specifante kutimajn agordojn en la URL"
|
||||
#~ " de preferoj povas esti uzata por "
|
||||
#~ "sinkronigi preferojn tra aparatoj."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "prokurata"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -44,13 +44,14 @@
|
|||
# curtwheeler <curtwheeler@users.noreply.translate.codeberg.org>, 2025.
|
||||
# return42 <return42@noreply.codeberg.org>, 2025.
|
||||
# Atul_Eterno <atul_eterno@noreply.codeberg.org>, 2025.
|
||||
# realkendrick_fr <realkendrick_fr@noreply.codeberg.org>, 2025.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: searx\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
|
||||
"PO-Revision-Date: 2025-04-24 14:06+0000\n"
|
||||
"Last-Translator: Atul_Eterno <atul_eterno@noreply.codeberg.org>\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-05-27 03:58+0000\n"
|
||||
"Last-Translator: realkendrick_fr <realkendrick_fr@noreply.codeberg.org>\n"
|
||||
"Language-Team: Spanish <https://translate.codeberg.org/projects/searxng/"
|
||||
"searxng/es/>\n"
|
||||
"Language: es\n"
|
||||
|
@ -58,7 +59,7 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.10.2\n"
|
||||
"X-Generator: Weblate 5.11.4\n"
|
||||
"Generated-By: Babel 2.17.0\n"
|
||||
|
||||
#. CONSTANT_NAMES['NO_SUBGROUPING']
|
||||
|
@ -102,7 +103,7 @@ msgid "videos"
|
|||
msgstr "vídeos"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "radio"
|
||||
|
||||
|
@ -379,93 +380,93 @@ msgstr "cerrar"
|
|||
msgid "answered"
|
||||
msgstr "contestado"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "Ningún artículo encontrado"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "Fuente"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "Error al cargar la siguiente página"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "Ajustes inválidos, por favor, cambia tus preferencias"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "Ajustes inválidos"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "error en la búsqueda"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "expirado"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "error de análisis"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "Error de protocolo HTTP"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "error de red"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "Error SSL: la validación del certificado ha fallado"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "cierre inesperado"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "Error de HTTP"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "Error de conexión HTTP"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "error de proxy"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "demasiadas peticiones"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "acceso denegado"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "error en la API del servidor"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "Suspendido"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "hace {minutes} minuto(s)"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "hace {hours} hora(s) y {minutes} minuto(s)"
|
||||
|
@ -496,15 +497,15 @@ msgstr "Esta entrada ha sido sustituida por"
|
|||
msgid "Channel"
|
||||
msgstr "Canal"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "bitrate"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "votos"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "clics"
|
||||
|
||||
|
@ -513,7 +514,7 @@ msgstr "clics"
|
|||
msgid "Language"
|
||||
msgstr "Idioma"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -558,7 +559,7 @@ msgstr "Lista negra de Ahmia"
|
|||
|
||||
#: searx/plugins/ahmia_filter.py:33
|
||||
msgid "Filter out onion results that appear in Ahmia's blacklist."
|
||||
msgstr ""
|
||||
msgstr "Filtrar resultados de onion que aparezcan en la lista negra de Ahmia."
|
||||
|
||||
#: searx/plugins/calculator.py:38
|
||||
msgid "Basic Calculator"
|
||||
|
@ -741,10 +742,6 @@ msgstr "Autor"
|
|||
msgid "cached"
|
||||
msgstr "en caché"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "por un proxy"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Enviar un nuevo problema a GitHub"
|
||||
|
@ -2134,3 +2131,6 @@ msgstr "ocultar video"
|
|||
#~ "URL de preferencias puede usarse para"
|
||||
#~ " sincronizar las preferencias entre "
|
||||
#~ "dispositivos."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "por un proxy"
|
||||
|
|
Binary file not shown.
|
@ -20,8 +20,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: searx\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
|
||||
"PO-Revision-Date: 2025-03-30 01:58+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-05-23 07:10+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"
|
||||
|
@ -30,7 +30,7 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.10.2\n"
|
||||
"X-Generator: Weblate 5.11.4\n"
|
||||
"Generated-By: Babel 2.17.0\n"
|
||||
|
||||
#. CONSTANT_NAMES['NO_SUBGROUPING']
|
||||
|
@ -74,7 +74,7 @@ msgid "videos"
|
|||
msgstr "videod"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "raadio"
|
||||
|
||||
|
@ -351,93 +351,93 @@ msgstr "suletud"
|
|||
msgid "answered"
|
||||
msgstr "vastatud"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "Üksust ei leitud"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "Allikas"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "Viga järgmise lehekülje laadimisel"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "Sobimatud seaded, palun muuda oma eelistusi"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "Sobimatud seaded"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "otsingu viga"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "päring aegus"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "parsimise viga"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "HTTP-protokolli viga"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "võrguviga"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "SSL viga: sertifikaadi valideerimine ei õnnestunud"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "ootamatu krahh"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "HTTP-viga"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "HTTP-ühenduse viga"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "proksiserveri viga"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "ROBOTILÕKS"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "liiga palju päringuid"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "ligipääs keelatud"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "serveri API viga"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "Peatatud"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "{minutes} minut(it) tagasi"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "{hours} tund(i), {minutes} minut(it) tagasi"
|
||||
|
@ -468,15 +468,15 @@ msgstr "See üksus on asendatud"
|
|||
msgid "Channel"
|
||||
msgstr "Kanal"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "bitikiirus"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "hääled"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "klikid"
|
||||
|
||||
|
@ -485,7 +485,7 @@ msgstr "klikid"
|
|||
msgid "Language"
|
||||
msgstr "Keel"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -686,7 +686,7 @@ msgstr "Avalikud serverid"
|
|||
|
||||
#: searx/templates/simple/base.html:75
|
||||
msgid "Privacy policy"
|
||||
msgstr "Privaatsuspoliitika"
|
||||
msgstr "Andmekaitsepõhimõtted"
|
||||
|
||||
#: searx/templates/simple/base.html:78
|
||||
msgid "Contact instance maintainer"
|
||||
|
@ -715,10 +715,6 @@ msgstr "Autor"
|
|||
msgid "cached"
|
||||
msgstr "vahemälus"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "proksiserveris"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Alusta veateate või ettepaneku koostamist GitHubis"
|
||||
|
@ -2076,3 +2072,6 @@ msgstr "peida video"
|
|||
#~ "Kohandatud seadete määramine eelistuste URL-i"
|
||||
#~ " saad kasutada eelistuste sünkroniseerimiseks "
|
||||
#~ "eri seadmete vahel."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "proksiserveris"
|
||||
|
|
Binary file not shown.
|
@ -18,7 +18,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: searx\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
|
||||
"POT-Creation-Date: 2025-05-13 19:13+0000\n"
|
||||
"PO-Revision-Date: 2025-02-12 15:39+0000\n"
|
||||
"Last-Translator: alexgabi <alexgabi@users.noreply.translate.codeberg.org>"
|
||||
"\n"
|
||||
|
@ -72,7 +72,7 @@ msgid "videos"
|
|||
msgstr "bideoak"
|
||||
|
||||
#. CATEGORY_NAMES['RADIO']
|
||||
#: searx/engines/radio_browser.py:103 searx/searxng.msg
|
||||
#: searx/engines/radio_browser.py:151 searx/searxng.msg
|
||||
msgid "radio"
|
||||
msgstr "irratia"
|
||||
|
||||
|
@ -349,93 +349,93 @@ msgstr "itxita"
|
|||
msgid "answered"
|
||||
msgstr "erantzunda"
|
||||
|
||||
#: searx/webapp.py:312
|
||||
#: searx/webapp.py:291
|
||||
msgid "No item found"
|
||||
msgstr "Ez da elementurik aurkitu"
|
||||
|
||||
#: searx/engines/qwant.py:291
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:314
|
||||
#: searx/templates/simple/result_templates/images.html:23 searx/webapp.py:293
|
||||
msgid "Source"
|
||||
msgstr "Iturria"
|
||||
|
||||
#: searx/webapp.py:316
|
||||
#: searx/webapp.py:295
|
||||
msgid "Error loading the next page"
|
||||
msgstr "Errorea hurrengo orrialdea kargatzean"
|
||||
|
||||
#: searx/webapp.py:469 searx/webapp.py:875
|
||||
#: searx/webapp.py:446 searx/webapp.py:844
|
||||
msgid "Invalid settings, please edit your preferences"
|
||||
msgstr "Ezarpen baliogabeak, editatu zure hobespenak"
|
||||
|
||||
#: searx/webapp.py:485
|
||||
#: searx/webapp.py:462
|
||||
msgid "Invalid settings"
|
||||
msgstr "Ezarpen baliogabeak"
|
||||
|
||||
#: searx/webapp.py:562 searx/webapp.py:652
|
||||
#: searx/webapp.py:539 searx/webapp.py:629
|
||||
msgid "search error"
|
||||
msgstr "bilaketa akatsa"
|
||||
|
||||
#: searx/webutils.py:36
|
||||
#: searx/webutils.py:35
|
||||
msgid "timeout"
|
||||
msgstr "itxarote-denbora"
|
||||
|
||||
#: searx/webutils.py:37
|
||||
#: searx/webutils.py:36
|
||||
msgid "parsing error"
|
||||
msgstr "analizatze errorea"
|
||||
|
||||
#: searx/webutils.py:38
|
||||
#: searx/webutils.py:37
|
||||
msgid "HTTP protocol error"
|
||||
msgstr "HTTP protokoloaren errorea"
|
||||
|
||||
#: searx/webutils.py:39
|
||||
#: searx/webutils.py:38
|
||||
msgid "network error"
|
||||
msgstr "sareko errorea"
|
||||
|
||||
#: searx/webutils.py:40
|
||||
#: searx/webutils.py:39
|
||||
msgid "SSL error: certificate validation has failed"
|
||||
msgstr "SSL errorea: ziurtagiria baliozkotzeak huts egin du"
|
||||
|
||||
#: searx/webutils.py:42
|
||||
#: searx/webutils.py:41
|
||||
msgid "unexpected crash"
|
||||
msgstr "ustekabeko kraskatzea"
|
||||
|
||||
#: searx/webutils.py:49
|
||||
#: searx/webutils.py:48
|
||||
msgid "HTTP error"
|
||||
msgstr "HTTP errorea"
|
||||
|
||||
#: searx/webutils.py:50
|
||||
#: searx/webutils.py:49
|
||||
msgid "HTTP connection error"
|
||||
msgstr "HTTP konexioaren errorea"
|
||||
|
||||
#: searx/webutils.py:56
|
||||
#: searx/webutils.py:55
|
||||
msgid "proxy error"
|
||||
msgstr "proxy-aren errorea"
|
||||
|
||||
#: searx/webutils.py:57
|
||||
#: searx/webutils.py:56
|
||||
msgid "CAPTCHA"
|
||||
msgstr "CAPTCHA"
|
||||
|
||||
#: searx/webutils.py:58
|
||||
#: searx/webutils.py:57
|
||||
msgid "too many requests"
|
||||
msgstr "eskaera gehiegi"
|
||||
|
||||
#: searx/webutils.py:59
|
||||
#: searx/webutils.py:58
|
||||
msgid "access denied"
|
||||
msgstr "sarbidea ukatua"
|
||||
|
||||
#: searx/webutils.py:60
|
||||
#: searx/webutils.py:59
|
||||
msgid "server API error"
|
||||
msgstr "API zerbitzariaren errorea"
|
||||
|
||||
#: searx/webutils.py:79
|
||||
#: searx/webutils.py:78
|
||||
msgid "Suspended"
|
||||
msgstr "Etenda"
|
||||
|
||||
#: searx/webutils.py:314
|
||||
#: searx/webutils.py:313
|
||||
#, python-brace-format
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "duela {minutes} minutu"
|
||||
|
||||
#: searx/webutils.py:315
|
||||
#: searx/webutils.py:314
|
||||
#, python-brace-format
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "duela {hours} ordu eta {minutes} minutu"
|
||||
|
@ -466,15 +466,15 @@ msgstr "Sarrera hau hurrengoarekin ordezkatu da"
|
|||
msgid "Channel"
|
||||
msgstr "Kanala"
|
||||
|
||||
#: searx/engines/radio_browser.py:105
|
||||
#: searx/engines/radio_browser.py:153
|
||||
msgid "bitrate"
|
||||
msgstr "bit emaria"
|
||||
|
||||
#: searx/engines/radio_browser.py:106
|
||||
#: searx/engines/radio_browser.py:154
|
||||
msgid "votes"
|
||||
msgstr "botoak"
|
||||
|
||||
#: searx/engines/radio_browser.py:107
|
||||
#: searx/engines/radio_browser.py:155
|
||||
msgid "clicks"
|
||||
msgstr "klikak"
|
||||
|
||||
|
@ -483,7 +483,7 @@ msgstr "klikak"
|
|||
msgid "Language"
|
||||
msgstr "Hizkuntza"
|
||||
|
||||
#: searx/engines/semantic_scholar.py:79
|
||||
#: searx/engines/semantic_scholar.py:101
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||
|
@ -711,10 +711,6 @@ msgstr "Egilea"
|
|||
msgid "cached"
|
||||
msgstr "cachean gordeta"
|
||||
|
||||
#: searx/templates/simple/macros.html:50
|
||||
msgid "proxied"
|
||||
msgstr "proxyan gordeta"
|
||||
|
||||
#: searx/templates/simple/new_issue.html:64
|
||||
msgid "Start submitting a new issue on GitHub"
|
||||
msgstr "Hasi gai -issue- berri bat bidaltzen GitHub-en"
|
||||
|
@ -2072,3 +2068,6 @@ msgstr "ezkutatu bideoa"
|
|||
#~ "zehaztea erabil daiteke gailuen hobespenak "
|
||||
#~ "sinkronizatzeko."
|
||||
|
||||
#~ msgid "proxied"
|
||||
#~ msgstr "proxyan gordeta"
|
||||
|
||||
|
|
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue