Update version to 603ecbeb6e75b commit.

This commit is contained in:
opi 2016-04-24 17:08:05 +02:00
parent acec07ccc9
commit 5a6cd66ccf
193 changed files with 7362 additions and 1951 deletions

View File

@ -41,3 +41,6 @@ generally made searx better:
- @GreenLunar
- Noemi Vanyi
- Kang-min Liu
- Kirill Isakov
- Guilhem Bonnefille
- Marc Abonce Seguin

View File

@ -1,22 +1,54 @@
FROM python:2.7-slim
FROM alpine:3.3
MAINTAINER searx <https://github.com/asciimoo/searx>
LABEL description "A privacy-respecting, hackable metasearch engine."
WORKDIR /app
ENV BASE_URL=False IMAGE_PROXY=False
EXPOSE 8888
WORKDIR /usr/local/searx
CMD ["/usr/bin/tini","--","/usr/local/searx/run.sh"]
RUN useradd searx
RUN adduser -D -h /usr/local/searx -s /bin/sh searx searx \
&& echo '#!/bin/sh' >> run.sh \
&& echo 'sed -i "s|base_url : False|base_url : $BASE_URL|g" searx/settings.yml' >> run.sh \
&& echo 'sed -i "s/image_proxy : False/image_proxy : $IMAGE_PROXY/g" searx/settings.yml' >> run.sh \
&& echo 'sed -i "s/ultrasecretkey/`openssl rand -hex 16`/g" searx/settings.yml' >> run.sh \
&& echo 'python searx/webapp.py' >> run.sh \
&& chmod +x run.sh
EXPOSE 5000
CMD ["/usr/local/bin/uwsgi", "--uid", "searx", "--gid", "searx", "--http", ":5000", "-w", "searx.webapp"]
COPY requirements.txt ./requirements.txt
RUN apt-get update && \
apt-get install -y --no-install-recommends \
zlib1g-dev libxml2-dev libxslt1-dev libffi-dev build-essential \
libssl-dev openssl && \
rm -rf /var/lib/apt/lists/*
RUN echo "@commuedge http://nl.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
&& apk -U add \
build-base \
python \
python-dev \
py-pip \
libxml2 \
libxml2-dev \
libxslt \
libxslt-dev \
libffi-dev \
openssl \
openssl-dev \
ca-certificates \
tini@commuedge \
&& pip install --no-cache -r requirements.txt \
&& apk del \
build-base \
python-dev \
py-pip\
libffi-dev \
openssl-dev \
libxslt-dev \
libxml2-dev \
openssl-dev \
ca-certificates \
&& rm -f /var/cache/apk/*
RUN pip install --no-cache uwsgi
COPY . .
COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache -r requirements.txt
RUN chown -R searx:searx *
COPY . /app
RUN sed -i -e "s/ultrasecretkey/`openssl rand -hex 16`/g" searx/settings.yml
USER searx
RUN sed -i "s/127.0.0.1/0.0.0.0/g" searx/settings.yml

View File

@ -1,66 +0,0 @@
# convenience makefile to boostrap & run buildout
# use `make options=-v` to run buildout with extra options
version = 2.7
python = bin/python
options =
all: .installed.cfg
.installed.cfg: bin/buildout buildout.cfg setup.py
bin/buildout $(options)
bin/buildout: $(python) buildout.cfg bootstrap.py
$(python) bootstrap.py
@touch $@
$(python):
virtualenv -p python$(version) --no-site-packages .
@touch $@
robot: .installed.cfg
@bin/robot
flake8: .installed.cfg
@bin/flake8 setup.py
@bin/flake8 ./searx/
tests: .installed.cfg flake8
@bin/test
@grunt test --gruntfile searx/static/themes/oscar/gruntfile.js
coverage: .installed.cfg
@bin/coverage run bin/test
@bin/coverage report
@bin/coverage html
production: bin/buildout production.cfg setup.py
bin/buildout -c production.cfg $(options)
@echo "* Please modify `readlink --canonicalize-missing ./searx/settings.py`"
@echo "* Hint 1: on production, disable debug mode and change secret_key"
@echo "* Hint 2: searx will be executed at server startup by crontab"
@echo "* Hint 3: to run immediatley, execute 'bin/supervisord'"
minimal: bin/buildout minimal.cfg setup.py
bin/buildout -c minimal.cfg $(options)
styles:
@lessc -x searx/static/themes/default/less/style.less > searx/static/themes/default/css/style.css
@lessc -x searx/static/themes/default/less/style-rtl.less > searx/static/themes/default/css/style-rtl.css
@lessc -x searx/static/themes/courgette/less/style.less > searx/static/themes/courgette/css/style.css
@lessc -x searx/static/themes/courgette/less/style-rtl.less > searx/static/themes/courgette/css/style-rtl.css
@lessc -x searx/static/less/bootstrap/bootstrap.less > searx/static/css/bootstrap.min.css
@lessc -x searx/static/themes/oscar/less/oscar/oscar.less > searx/static/themes/oscar/css/oscar.min.css
@lessc -x searx/static/themes/pix-art/less/style.less > searx/static/themes/pix-art/css/style.css
grunt:
@grunt --gruntfile searx/static/themes/oscar/gruntfile.js
locales:
@pybabel compile -d searx/translations
clean:
@rm -rf .installed.cfg .mr.developer.cfg bin parts develop-eggs eggs \
searx.egg-info lib include .coverage coverage
.PHONY: all tests robot flake8 coverage production minimal styles locales clean

View File

@ -7,31 +7,16 @@ engine <https://en.wikipedia.org/wiki/Metasearch_engine>`__.
List of `running
instances <https://github.com/asciimoo/searx/wiki/Searx-instances>`__.
See the `wiki <https://github.com/asciimoo/searx/wiki>`__ for more information.
See the `documentation <https://asciimoo.github.io/searx>`__ and the `wiki <https://github.com/asciimoo/searx/wiki>`__ for more information.
|Flattr searx|
Features
~~~~~~~~
- Tracking free
- Supports multiple output formats
- json ``curl https://searx.me/?format=json&q=[query]``
- csv ``curl https://searx.me/?format=csv&q=[query]``
- opensearch/rss ``curl https://searx.me/?format=rss&q=[query]``
- Opensearch support (you can set as default search engine)
- Configurable search engines/categories
- Different search languages
- Duckduckgo like !bang functionality with engine shortcuts
- Parallel queries - relatively fast
Installation
~~~~~~~~~~~~
- clone source:
``git clone git@github.com:asciimoo/searx.git && cd searx``
- install dependencies: ``pip install -r requirements.txt``
- install dependencies: ``./manage.sh update_packages``
- edit your
`settings.yml <https://github.com/asciimoo/searx/blob/master/settings.yml>`__
(set your ``secret_key``!)
@ -40,104 +25,6 @@ Installation
For all the details, follow this `step by step
installation <https://github.com/asciimoo/searx/wiki/Installation>`__
Alternative (Recommended) Installation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- clone source:
``git clone git@github.com:asciimoo/searx.git && cd searx``
- build in current folder: ``make minimal``
- run ``bin/searx-run`` to start the application
Development
~~~~~~~~~~~
Just run ``make``. Versions of dependencies are pinned down inside
``versions.cfg`` to produce most stable build. Also remember, NO make
command should be run as root, not even ``make production``
Deployment
~~~~~~~~~~
- clone source:
``git clone git@github.com:asciimoo/searx.git && cd searx``
- build in current folder: ``make production``
- run ``bin/supervisord`` to start the application
Upgrading
~~~~~~~~~
- inside previously cloned searx directory run: ``git stash`` to
temporarily save any changes you have made
- pull source: ``git pull origin master``
- re-build in current folder: ``make production``
- run ``bin/supervisorctl stop searx`` to stop searx, if it does not,
then run ``fuser -k 8888/tcp``
- run ``bin/supervisorctl reload`` to re-read supervisor config and
start searx
Command make
~~~~~~~~~~~~
``make``
''''''''
Builds development environment with testing support.
``make tests``
''''''''''''''
Runs tests. You can write tests
`here <https://github.com/asciimoo/searx/tree/master/searx/tests>`__ and
remember 'untested code is broken code'.
``make robot``
''''''''''''''
Runs robot (Selenium) tests, you must have ``firefox`` installed because
this functional tests actually run the browser and perform operations on
it. Also searx is executed with
`settings\_robot <https://github.com/asciimoo/searx/blob/master/searx/settings_robot.yml>`__.
``make flake8``
'''''''''''''''
'pep8 is a tool to check your Python code against some of the style
conventions in `PEP 8 <http://www.python.org/dev/peps/pep-0008/>`__.'
``make coverage``
'''''''''''''''''
Checks coverage of tests, after running this, execute this:
``firefox ./coverage/index.html``
``make production``
'''''''''''''''''''
Used to make co-called production environment - without tests (you
should ran tests before deploying searx on the server). This installs
supervisord, so if searx crashes, it will try to pick itself up again.
And crontab entry is added to start supervisord at server boot.
``make minimal``
''''''''''''''''
Minimal build - without test frameworks, the quickest build option.
``make clean``
''''''''''''''
Deletes several folders and files (see ``Makefile`` for more), so that
next time you run any other ``make`` command it will rebuild everithing.
TODO
~~~~
- Moar engines
- Better ui
- Browser integration
- Documentation
- Tests
Bugs
~~~~

View File

@ -1,17 +0,0 @@
[buildout]
extends = versions.cfg
unzip = true
newest = false
prefer-final = true
develop = .
eggs =
searx
parts =
omelette
[omelette]
recipe = collective.recipe.omelette
eggs = ${buildout:eggs}

View File

@ -1,210 +0,0 @@
##############################################################################
#
# Copyright (c) 2006 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Bootstrap a buildout-based project
Simply run this script in a directory containing a buildout.cfg.
The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
"""
import os
import shutil
import sys
import tempfile
from optparse import OptionParser
__version__ = '2015-07-01'
# See zc.buildout's changelog if this version is up to date.
tmpeggs = tempfile.mkdtemp(prefix='bootstrap-')
usage = '''\
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
Bootstraps a buildout-based project.
Simply run this script in a directory containing a buildout.cfg, using the
Python that you want bin/buildout to use.
Note that by using --find-links to point to local resources, you can keep
this script from going over the network.
'''
parser = OptionParser(usage=usage)
parser.add_option("--version",
action="store_true", default=False,
help=("Return bootstrap.py version."))
parser.add_option("-t", "--accept-buildout-test-releases",
dest='accept_buildout_test_releases',
action="store_true", default=False,
help=("Normally, if you do not specify a --version, the "
"bootstrap script and buildout gets the newest "
"*final* versions of zc.buildout and its recipes and "
"extensions for you. If you use this flag, "
"bootstrap and buildout will get the newest releases "
"even if they are alphas or betas."))
parser.add_option("-c", "--config-file",
help=("Specify the path to the buildout configuration "
"file to be used."))
parser.add_option("-f", "--find-links",
help=("Specify a URL to search for buildout releases"))
parser.add_option("--allow-site-packages",
action="store_true", default=False,
help=("Let bootstrap.py use existing site packages"))
parser.add_option("--buildout-version",
help="Use a specific zc.buildout version")
parser.add_option("--setuptools-version",
help="Use a specific setuptools version")
parser.add_option("--setuptools-to-dir",
help=("Allow for re-use of existing directory of "
"setuptools versions"))
options, args = parser.parse_args()
if options.version:
print("bootstrap.py version %s" % __version__)
sys.exit(0)
######################################################################
# load/install setuptools
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
ez = {}
if os.path.exists('ez_setup.py'):
exec(open('ez_setup.py').read(), ez)
else:
exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
if not options.allow_site_packages:
# ez_setup imports site, which adds site packages
# this will remove them from the path to ensure that incompatible versions
# of setuptools are not in the path
import site
# inside a virtualenv, there is no 'getsitepackages'.
# We can't remove these reliably
if hasattr(site, 'getsitepackages'):
for sitepackage_path in site.getsitepackages():
# Strip all site-packages directories from sys.path that
# are not sys.prefix; this is because on Windows
# sys.prefix is a site-package directory.
if sitepackage_path != sys.prefix:
sys.path[:] = [x for x in sys.path
if sitepackage_path not in x]
setup_args = dict(to_dir=tmpeggs, download_delay=0)
if options.setuptools_version is not None:
setup_args['version'] = options.setuptools_version
if options.setuptools_to_dir is not None:
setup_args['to_dir'] = options.setuptools_to_dir
ez['use_setuptools'](**setup_args)
import setuptools
import pkg_resources
# This does not (always?) update the default working set. We will
# do it.
for path in sys.path:
if path not in pkg_resources.working_set.entries:
pkg_resources.working_set.add_entry(path)
######################################################################
# Install buildout
ws = pkg_resources.working_set
setuptools_path = ws.find(
pkg_resources.Requirement.parse('setuptools')).location
# Fix sys.path here as easy_install.pth added before PYTHONPATH
cmd = [sys.executable, '-c',
'import sys; sys.path[0:0] = [%r]; ' % setuptools_path +
'from setuptools.command.easy_install import main; main()',
'-mZqNxd', tmpeggs]
find_links = os.environ.get(
'bootstrap-testing-find-links',
options.find_links or
('http://downloads.buildout.org/'
if options.accept_buildout_test_releases else None)
)
if find_links:
cmd.extend(['-f', find_links])
requirement = 'zc.buildout'
version = options.buildout_version
if version is None and not options.accept_buildout_test_releases:
# Figure out the most recent final version of zc.buildout.
import setuptools.package_index
_final_parts = '*final-', '*final'
def _final_version(parsed_version):
try:
return not parsed_version.is_prerelease
except AttributeError:
# Older setuptools
for part in parsed_version:
if (part[:1] == '*') and (part not in _final_parts):
return False
return True
index = setuptools.package_index.PackageIndex(
search_path=[setuptools_path])
if find_links:
index.add_find_links((find_links,))
req = pkg_resources.Requirement.parse(requirement)
if index.obtain(req) is not None:
best = []
bestv = None
for dist in index[req.project_name]:
distv = dist.parsed_version
if _final_version(distv):
if bestv is None or distv > bestv:
best = [dist]
bestv = distv
elif distv == bestv:
best.append(dist)
if best:
best.sort()
version = best[-1].version
if version:
requirement = '=='.join((requirement, version))
cmd.append(requirement)
import subprocess
if subprocess.call(cmd) != 0:
raise Exception(
"Failed to execute command:\n%s" % repr(cmd)[1:-1])
######################################################################
# Import and run buildout
ws.add_entry(tmpeggs)
ws.require(requirement)
import zc.buildout.buildout
if not [a for a in args if '=' not in a]:
args.append('bootstrap')
# if -c was provided, we push it back into args for buildout' main function
if options.config_file is not None:
args[0:0] = ['-c', options.config_file]
zc.buildout.buildout.main(args)
shutil.rmtree(tmpeggs)

View File

@ -1,30 +0,0 @@
[buildout]
extends = base.cfg
develop = .
eggs =
searx [test]
parts +=
pyscripts
robot
test
[pyscripts]
recipe = zc.recipe.egg:script
eggs = ${buildout:eggs}
interpreter = py
dependent-scripts = true
[robot]
recipe = zc.recipe.testrunner
eggs = ${buildout:eggs}
defaults = ['--color', '--auto-progress', '--layer', 'SearxRobotLayer']
[test]
recipe = zc.recipe.testrunner
eggs = ${buildout:eggs}
defaults = ['--color', '--auto-progress', '--layer', 'SearxTestLayer', '--layer', '!SearxRobotLayer']

95
sources/manage.sh Executable file
View File

@ -0,0 +1,95 @@
#!/bin/sh
BASE_DIR=$(dirname `readlink -f $0`)
PYTHONPATH=$BASE_DIR
SEARX_DIR="$BASE_DIR/searx"
ACTION=$1
update_packages() {
pip install --upgrade -r "$BASE_DIR/requirements.txt"
}
update_dev_packages() {
update_packages
pip install --upgrade -r "$BASE_DIR/requirements-dev.txt"
}
pep8_check() {
echo '[!] Running pep8 check'
# ignored rules:
# E402 module level import not at top of file
# W503 line break before binary operator
pep8 --max-line-length=120 --ignore "E402,W503" "$SEARX_DIR" "$BASE_DIR/tests"
}
unit_tests() {
echo '[!] Running unit tests'
python -m nose2 -s "$BASE_DIR/tests/unit"
}
py_test_coverage() {
echo '[!] Running python test coverage'
PYTHONPATH=`pwd` python -m nose2 -C --coverage "$SEARX_DIR" -s "$BASE_DIR/tests/unit"
coverage report
coverage html
}
robot_tests() {
echo '[!] Running robot tests'
PYTHONPATH=`pwd` python "$SEARX_DIR/testing.py" robot
}
tests() {
set -e
pep8_check
unit_tests
robot_tests
set +e
}
build_style() {
lessc -x "$BASE_DIR/searx/static/$1" "$BASE_DIR/searx/static/$2"
}
styles() {
echo '[!] Building styles'
build_style themes/default/less/style.less themes/default/css/style.css
build_style themes/default/less/style-rtl.less themes/default/css/style-rtl.css
build_style themes/courgette/less/style.less themes/courgette/css/style.css
build_style themes/courgette/less/style-rtl.less themes/courgette/css/style-rtl.css
build_style less/bootstrap/bootstrap.less css/bootstrap.min.css
build_style themes/oscar/less/oscar/oscar.less themes/oscar/css/oscar.min.css
build_style themes/pix-art/less/style.less themes/pix-art/css/style.css
}
grunt_build() {
grunt --gruntfile "$SEARX_DIR/static/themes/oscar/gruntfile.js"
}
locales() {
pybabel compile -d "$SEARX_DIR/translations"
}
help() {
[ -z "$1" ] || printf "Error: $1\n"
echo "Searx manage.sh help
Commands
========
grunt_build - Build js files
help - This text
locales - Compile locales
pep8_check - Pep8 validation
py_test_coverage - Unit test coverage
robot_tests - Run selenium tests
styles - Build less files
tests - Run all python tests (pep8, unit, robot)
unit_tests - Run unit tests
update_dev_packages - Check & update development and production dependency changes
update_packages - Check & update dependency changes
"
}
[ "$(command -V "$ACTION" | grep ' function$')" = "" ] \
&& help "action not found" \
|| $ACTION

View File

@ -1,15 +0,0 @@
[buildout]
extends = base.cfg
develop = .
eggs =
searx
parts +=
pyscripts
[pyscripts]
recipe = zc.recipe.egg:script
eggs = ${buildout:eggs}
interpreter = py

View File

@ -1,34 +0,0 @@
[buildout]
extends = base.cfg
develop = .
eggs =
searx
parts +=
pyscripts
supervisor
crontab_reboot
[pyscripts]
recipe = zc.recipe.egg:script
eggs = ${buildout:eggs}
interpreter = py
[supervisor]
recipe = collective.recipe.supervisor
http-socket = unix
user = searxer
password = ohpleasedochangeme
file = /tmp/supervisor.sock
chmod = 0700
programs =
50 searx ${buildout:bin-directory}/searx-run
[crontab_reboot]
recipe = z3c.recipe.usercrontab
times = @reboot
command = ${buildout:bin-directory}/supervisord

View File

@ -0,0 +1,10 @@
babel==2.2.0
mock==1.0.1
nose2[coverage-plugin]
pep8==1.7.0
plone.testing==4.0.15
robotframework-selenium2library==1.7.4
robotsuite==1.7.0
transifex-client==0.11
unittest2==1.1.0
zope.testrunner==4.4.10

View File

@ -1,12 +1,12 @@
flask
flask-babel
requests
lxml
pyyaml
pygments
python-dateutil
ndg-httpsclient
pyopenssl
pyasn1
pyasn1-modules
certifi
certifi==2015.11.20.1
flask==0.10.1
flask-babel==0.9
lxml==3.5.0
ndg-httpsclient==0.4.0
pyasn1==0.1.9
pyasn1-modules==0.0.8
pygments==2.0.2
pyopenssl==0.15.1
python-dateutil==2.4.2
pyyaml==3.11
requests==2.9.1

View File

@ -15,9 +15,11 @@ along with searx. If not, see < http://www.gnu.org/licenses/ >.
(C) 2013- by Adam Tauber, <asciimoo@gmail.com>
'''
import certifi
import logging
from os import environ
from os.path import realpath, dirname, join, abspath
from ssl import OPENSSL_VERSION_INFO, OPENSSL_VERSION
try:
from yaml import load
except:
@ -47,4 +49,11 @@ else:
logger = logging.getLogger('searx')
# Workaround for openssl versions <1.0.2
# https://github.com/certifi/python-certifi/issues/26
if OPENSSL_VERSION_INFO[0:3] < (1, 0, 2):
if hasattr(certifi, 'old_where'):
environ['REQUESTS_CA_BUNDLE'] = certifi.old_where()
logger.warning('You are using an old openssl version({0}), please upgrade above 1.0.2!'.format(OPENSSL_VERSION))
logger.info('Initialisation done')

View File

@ -110,12 +110,11 @@ def searx_bang(full_query):
return list(result_set)
def dbpedia(query):
def dbpedia(query, lang):
# dbpedia autocompleter, no HTTPS
autocomplete_url = 'http://lookup.dbpedia.org/api/search.asmx/KeywordSearch?'
response = get(autocomplete_url
+ urlencode(dict(QueryString=query)))
response = get(autocomplete_url + urlencode(dict(QueryString=query)))
results = []
@ -127,7 +126,7 @@ def dbpedia(query):
return results
def duckduckgo(query):
def duckduckgo(query, lang):
# duckduckgo autocompleter
url = 'https://ac.duckduckgo.com/ac/?{0}&type=list'
@ -137,12 +136,11 @@ def duckduckgo(query):
return []
def google(query):
def google(query, lang):
# google autocompleter
autocomplete_url = 'https://suggestqueries.google.com/complete/search?client=toolbar&'
response = get(autocomplete_url
+ urlencode(dict(q=query)))
response = get(autocomplete_url + urlencode(dict(hl=lang, q=query)))
results = []
@ -153,8 +151,8 @@ def google(query):
return results
def startpage(query):
# wikipedia autocompleter
def startpage(query, lang):
# startpage autocompleter
url = 'https://startpage.com/do/suggest?{query}'
resp = get(url.format(query=urlencode({'query': query}))).text.split('\n')
@ -163,9 +161,26 @@ def startpage(query):
return []
def wikipedia(query):
def qwant(query, lang):
# qwant autocompleter (additional parameter : lang=en_en&count=xxx )
url = 'https://api.qwant.com/api/suggest?{query}'
resp = get(url.format(query=urlencode({'q': query, 'lang': lang})))
results = []
if resp.ok:
data = loads(resp.text)
if data['status'] == 'success':
for item in data['data']['items']:
results.append(item['value'])
return results
def wikipedia(query, lang):
# wikipedia autocompleter
url = 'https://en.wikipedia.org/w/api.php?action=opensearch&{0}&limit=10&namespace=0&format=json'
url = 'https://' + lang + '.wikipedia.org/w/api.php?action=opensearch&{0}&limit=10&namespace=0&format=json'
resp = loads(get(url.format(urlencode(dict(search=query)))).text)
if len(resp) > 1:
@ -177,5 +192,6 @@ backends = {'dbpedia': dbpedia,
'duckduckgo': duckduckgo,
'google': google,
'startpage': startpage,
'qwant': qwant,
'wikipedia': wikipedia
}

View File

@ -34,6 +34,15 @@ engines = {}
categories = {'general': []}
engine_shortcuts = {}
engine_default_args = {'paging': False,
'categories': ['general'],
'language_support': True,
'safesearch': False,
'timeout': settings['outgoing']['request_timeout'],
'shortcut': '-',
'disabled': False,
'suspend_end_time': 0,
'continuous_errors': 0}
def load_module(filename):
@ -62,26 +71,9 @@ def load_engine(engine_data):
continue
setattr(engine, param_name, engine_data[param_name])
if not hasattr(engine, 'paging'):
engine.paging = False
if not hasattr(engine, 'categories'):
engine.categories = ['general']
if not hasattr(engine, 'language_support'):
engine.language_support = True
if not hasattr(engine, 'safesearch'):
engine.safesearch = False
if not hasattr(engine, 'timeout'):
engine.timeout = settings['outgoing']['request_timeout']
if not hasattr(engine, 'shortcut'):
engine.shortcut = ''
if not hasattr(engine, 'disabled'):
engine.disabled = False
for arg_name, arg_value in engine_default_args.iteritems():
if not hasattr(engine, arg_name):
setattr(engine, arg_name, arg_value)
# checking required variables
for engine_attr in dir(engine):
@ -100,18 +92,15 @@ def load_engine(engine_data):
'errors': 0
}
if hasattr(engine, 'categories'):
for category_name in engine.categories:
categories.setdefault(category_name, []).append(engine)
else:
categories['general'].append(engine)
for category_name in engine.categories:
categories.setdefault(category_name, []).append(engine)
if engine.shortcut in engine_shortcuts:
logger.error('Engine config error: ambigious shortcut: {0}'.format(engine.shortcut))
sys.exit(1)
engine_shortcuts[engine.shortcut] = engine.name
if engine.shortcut:
if engine.shortcut in engine_shortcuts:
logger.error('Engine config error: ambigious shortcut: {0}'
.format(engine.shortcut))
sys.exit(1)
engine_shortcuts[engine.shortcut] = engine.name
return engine

View File

@ -0,0 +1,141 @@
# -*- coding: utf-8 -*-
"""
Arch Linux Wiki
@website https://wiki.archlinux.org
@provide-api no (Mediawiki provides API, but Arch Wiki blocks access to it
@using-api no
@results HTML
@stable no (HTML can change)
@parse url, title
"""
from urlparse import urljoin
from cgi import escape
from urllib import urlencode
from lxml import html
from searx.engines.xpath import extract_text
# engine dependent config
categories = ['it']
language_support = True
paging = True
base_url = 'https://wiki.archlinux.org'
# xpath queries
xpath_results = '//ul[@class="mw-search-results"]/li'
xpath_link = './/div[@class="mw-search-result-heading"]/a'
# cut 'en' from 'en_US', 'de' from 'de_CH', and so on
def locale_to_lang_code(locale):
if locale.find('_') >= 0:
locale = locale.split('_')[0]
return locale
# wikis for some languages were moved off from the main site, we need to make
# requests to correct URLs to be able to get results in those languages
lang_urls = {
'all': {
'base': 'https://wiki.archlinux.org',
'search': '/index.php?title=Special:Search&offset={offset}&{query}'
},
'de': {
'base': 'https://wiki.archlinux.de',
'search': '/index.php?title=Spezial:Suche&offset={offset}&{query}'
},
'fr': {
'base': 'https://wiki.archlinux.fr',
'search': '/index.php?title=Spécial:Recherche&offset={offset}&{query}'
},
'ja': {
'base': 'https://wiki.archlinuxjp.org',
'search': '/index.php?title=特別:検索&offset={offset}&{query}'
},
'ro': {
'base': 'http://wiki.archlinux.ro',
'search': '/index.php?title=Special:Căutare&offset={offset}&{query}'
},
'tr': {
'base': 'http://archtr.org/wiki',
'search': '/index.php?title=Özel:Ara&offset={offset}&{query}'
}
}
# get base & search URLs for selected language
def get_lang_urls(language):
if language in lang_urls:
return lang_urls[language]
return lang_urls['all']
# Language names to build search requests for
# those languages which are hosted on the main site.
main_langs = {
'ar': 'العربية',
'bg': 'Български',
'cs': 'Česky',
'da': 'Dansk',
'el': 'Ελληνικά',
'es': 'Español',
'he': 'עברית',
'hr': 'Hrvatski',
'hu': 'Magyar',
'it': 'Italiano',
'ko': '한국어',
'lt': 'Lietuviškai',
'nl': 'Nederlands',
'pl': 'Polski',
'pt': 'Português',
'ru': 'Русский',
'sl': 'Slovenský',
'th': 'ไทย',
'uk': 'Українська',
'zh': '简体中文'
}
# do search-request
def request(query, params):
# translate the locale (e.g. 'en_US') to language code ('en')
language = locale_to_lang_code(params['language'])
# if our language is hosted on the main site, we need to add its name
# to the query in order to narrow the results to that language
if language in main_langs:
query += '(' + main_langs[language] + ')'
# prepare the request parameters
query = urlencode({'search': query})
offset = (params['pageno'] - 1) * 20
# get request URLs for our language of choice
urls = get_lang_urls(language)
search_url = urls['base'] + urls['search']
params['url'] = search_url.format(query=query, offset=offset)
return params
# get response from search-request
def response(resp):
# get the base URL for the language in which request was made
language = locale_to_lang_code(resp.search_params['language'])
base_url = get_lang_urls(language)['base']
results = []
dom = html.fromstring(resp.text)
# parse results
for result in dom.xpath(xpath_results):
link = result.xpath(xpath_link)[0]
href = urljoin(base_url, link.attrib.get('href'))
title = escape(extract_text(link))
results.append({'url': href,
'title': title})
return results

122
sources/searx/engines/base.py Executable file
View File

@ -0,0 +1,122 @@
#!/usr/bin/env python
"""
BASE (Scholar publications)
@website https://base-search.net
@provide-api yes with authorization (https://api.base-search.net/)
@using-api yes
@results XML
@stable ?
@parse url, title, publishedDate, content
More info on api: http://base-search.net/about/download/base_interface.pdf
"""
from lxml import etree
from urllib import urlencode
from searx.utils import searx_useragent
from cgi import escape
from datetime import datetime
import re
categories = ['science']
base_url = 'https://api.base-search.net/cgi-bin/BaseHttpSearchInterface.fcgi'\
+ '?func=PerformSearch&{query}&boost=oa&hits={hits}&offset={offset}'
# engine dependent config
paging = True
number_of_results = 10
# shortcuts for advanced search
shorcut_dict = {
# user-friendly keywords
'format:': 'dcformat:',
'author:': 'dccreator:',
'collection:': 'dccollection:',
'hdate:': 'dchdate:',
'contributor:': 'dccontributor:',
'coverage:': 'dccoverage:',
'date:': 'dcdate:',
'abstract:': 'dcdescription:',
'urls:': 'dcidentifier:',
'language:': 'dclanguage:',
'publisher:': 'dcpublisher:',
'relation:': 'dcrelation:',
'rights:': 'dcrights:',
'source:': 'dcsource:',
'subject:': 'dcsubject:',
'title:': 'dctitle:',
'type:': 'dcdctype:'
}
def request(query, params):
# replace shortcuts with API advanced search keywords
for key in shorcut_dict.keys():
query = re.sub(str(key), str(shorcut_dict[key]), query)
# basic search
offset = (params['pageno'] - 1) * number_of_results
string_args = dict(query=urlencode({'query': query}),
offset=offset,
hits=number_of_results)
params['url'] = base_url.format(**string_args)
params['headers']['User-Agent'] = searx_useragent()
return params
def response(resp):
results = []
search_results = etree.XML(resp.content)
for entry in search_results.xpath('./result/doc'):
content = "No description available"
date = datetime.now() # needed in case no dcdate is available for an item
for item in entry:
if item.attrib["name"] == "dchdate":
harvestDate = item.text
elif item.attrib["name"] == "dcdate":
date = item.text
elif item.attrib["name"] == "dctitle":
title = item.text
elif item.attrib["name"] == "dclink":
url = item.text
elif item.attrib["name"] == "dcdescription":
content = escape(item.text[:300])
if len(item.text) > 300:
content += "..."
# dates returned by the BASE API are not several formats
publishedDate = None
for date_format in ['%Y-%m-%dT%H:%M:%SZ', '%Y-%m-%d', '%Y-%m', '%Y']:
try:
publishedDate = datetime.strptime(date, date_format)
break
except:
pass
if publishedDate is not None:
res_dict = {'url': url,
'title': title,
'publishedDate': publishedDate,
'content': content}
else:
res_dict = {'url': url,
'title': title,
'content': content}
results.append(res_dict)
return results

View File

@ -17,7 +17,7 @@
from urllib import urlencode
from lxml import html
from yaml import load
from json import loads
import re
# engine dependent config
@ -36,6 +36,9 @@ safesearch_types = {2: 'STRICT',
0: 'OFF'}
_quote_keys_regex = re.compile('({|,)([a-z][a-z0-9]*):(")', re.I | re.U)
# do search-request
def request(query, params):
offset = (params['pageno'] - 1) * 10 + 1
@ -65,22 +68,19 @@ def response(resp):
dom = html.fromstring(resp.text)
# init regex for yaml-parsing
p = re.compile('({|,)([a-z]+):(")')
# parse results
for result in dom.xpath('//div[@class="dg_u"]'):
for result in dom.xpath('//div[@class="dg_u"]/div'):
link = result.xpath('./a')[0]
# parse yaml-data (it is required to add a space, to make it parsable)
yaml_data = load(p.sub(r'\1\2: \3', link.attrib.get('m')))
# parse json-data (it is required to add a space, to make it parsable)
json_data = loads(_quote_keys_regex.sub(r'\1"\2": \3', link.attrib.get('m')))
title = link.attrib.get('t1')
ihk = link.attrib.get('ihk')
# url = 'http://' + link.attrib.get('t3')
url = yaml_data.get('surl')
img_src = yaml_data.get('imgurl')
url = json_data.get('surl')
img_src = json_data.get('imgurl')
# append result
results.append({'template': 'images.html',

View File

@ -37,7 +37,7 @@ def request(query, params):
c=c)
if params['pageno'] != 1:
params['url'] += '&page={pageno}'.format(pageno=(params['pageno']-1))
params['url'] += '&page={pageno}'.format(pageno=(params['pageno'] - 1))
# let Blekko know we wan't have profiling
params['cookies']['tag_lesslogging'] = '1'

View File

@ -29,7 +29,7 @@ search_url = url + '/search?q={search_term}&p={pageno}'
# do search-request
def request(query, params):
params['url'] = search_url.format(search_term=quote(query),
pageno=params['pageno']-1)
pageno=params['pageno'] - 1)
return params

View File

@ -24,7 +24,7 @@ paging = True
# search-url
base_url = 'https://www.deviantart.com/'
search_url = base_url+'browse/all/?offset={offset}&{query}'
search_url = base_url + 'browse/all/?offset={offset}&{query}'
# do search-request

View File

@ -22,7 +22,7 @@ paging = True
# search-url
base_url = 'https://digg.com/'
search_url = base_url+'api/search/{query}.json?position={position}&format=html'
search_url = base_url + 'api/search/{query}.json?position={position}&format=html'
# specific xpath variables
results_xpath = '//article'

View File

@ -0,0 +1,84 @@
# Doku Wiki
#
# @website https://www.dokuwiki.org/
# @provide-api yes
# (https://www.dokuwiki.org/devel:xmlrpc)
#
# @using-api no
# @results HTML
# @stable yes
# @parse (general) url, title, content
from urllib import urlencode
from lxml.html import fromstring
from searx.engines.xpath import extract_text
# engine dependent config
categories = ['general'] # TODO , 'images', 'music', 'videos', 'files'
paging = False
language_support = False
number_of_results = 5
# search-url
# Doku is OpenSearch compatible
base_url = 'http://localhost:8090'
search_url = '/?do=search'\
'&{query}'
# TODO '&startRecord={offset}'\
# TODO '&maximumRecords={limit}'\
# do search-request
def request(query, params):
params['url'] = base_url +\
search_url.format(query=urlencode({'id': query}))
return params
# get response from search-request
def response(resp):
results = []
doc = fromstring(resp.text)
# parse results
# Quickhits
for r in doc.xpath('//div[@class="search_quickresult"]/ul/li'):
try:
res_url = r.xpath('.//a[@class="wikilink1"]/@href')[-1]
except:
continue
if not res_url:
continue
title = extract_text(r.xpath('.//a[@class="wikilink1"]/@title'))
# append result
results.append({'title': title,
'content': "",
'url': base_url + res_url})
# Search results
for r in doc.xpath('//dl[@class="search_results"]/*'):
try:
if r.tag == "dt":
res_url = r.xpath('.//a[@class="wikilink1"]/@href')[-1]
title = extract_text(r.xpath('.//a[@class="wikilink1"]/@title'))
elif r.tag == "dd":
content = extract_text(r.xpath('.'))
# append result
results.append({'title': title,
'content': content,
'url': base_url + res_url})
except:
continue
if not res_url:
continue
# return results
return results

View File

@ -28,10 +28,10 @@ language_support = True
url = 'https://duckduckgo.com/html?{query}&s={offset}'
# specific xpath variables
result_xpath = '//div[@class="results_links results_links_deep web-result"]' # noqa
url_xpath = './/a[@class="large"]/@href'
title_xpath = './/a[@class="large"]'
content_xpath = './/div[@class="snippet"]'
result_xpath = '//div[@class="result results_links results_links_deep web-result "]' # noqa
url_xpath = './/a[@class="result__a"]/@href'
title_xpath = './/a[@class="result__a"]'
content_xpath = './/a[@class="result__snippet"]'
# do search-request

View File

@ -1,5 +1,6 @@
import json
from urllib import urlencode
from re import compile, sub
from lxml import html
from searx.utils import html_to_text
from searx.engines.xpath import extract_text
@ -7,6 +8,8 @@ from searx.engines.xpath import extract_text
url = 'https://api.duckduckgo.com/'\
+ '?{query}&format=json&pretty=0&no_redirect=1&d=1'
http_regex = compile(r'^http:')
def result_to_text(url, text, htmlResult):
# TODO : remove result ending with "Meaning" or "Category"
@ -19,8 +22,8 @@ def result_to_text(url, text, htmlResult):
def request(query, params):
# TODO add kl={locale}
params['url'] = url.format(query=urlencode({'q': query}))
params['headers']['Accept-Language'] = params['language']
return params
@ -103,6 +106,10 @@ def response(resp):
urls.append({'title': search_res.get('DefinitionSource'),
'url': definitionURL})
# to merge with wikidata's infobox
if infobox_id:
infobox_id = http_regex.sub('https:', infobox_id)
# entity
entity = search_res.get('Entity', None)
# TODO continent / country / department / location / waterfall /

View File

@ -88,7 +88,7 @@ def response(resp):
for result in search_res['results']:
if result['news']:
# timestamp (milliseconds since 1970)
publishedDate = datetime.datetime.fromtimestamp(result['date']/1000.0) # noqa
publishedDate = datetime.datetime.fromtimestamp(result['date'] / 1000.0) # noqa
# append news result
results.append({'url': result['url'],

View File

@ -0,0 +1,53 @@
"""
F-Droid (a repository of FOSS applications for Android)
@website https://f-droid.org/
@provide-api no
@using-api no
@results HTML
@stable no (HTML can change)
@parse url, title, content
"""
from cgi import escape
from urllib import urlencode
from searx.engines.xpath import extract_text
from lxml import html
# engine dependent config
categories = ['files']
paging = True
# search-url
base_url = 'https://f-droid.org/'
search_url = base_url + 'repository/browse/?{query}'
# do search-request
def request(query, params):
query = urlencode({'fdfilter': query,
'fdpage': params['pageno']})
params['url'] = search_url.format(query=query)
return params
# get response from search-request
def response(resp):
results = []
dom = html.fromstring(resp.text)
for app in dom.xpath('//div[@id="appheader"]'):
url = app.xpath('./ancestor::a/@href')[0]
title = app.xpath('./p/span/text()')[0]
img_src = app.xpath('.//img/@src')[0]
content = extract_text(app.xpath('./p')[0])
content = escape(content.replace(title, '', 1).strip())
results.append({'url': url,
'title': title,
'content': content,
'img_src': img_src})
return results

View File

@ -0,0 +1,44 @@
"""
Frinkiac (Images)
@website https://www.frinkiac.com
@provide-api no
@using-api no
@results JSON
@stable no
@parse url, title, img_src
"""
from json import loads
from urllib import urlencode
categories = ['images']
BASE = 'https://frinkiac.com/'
SEARCH_URL = '{base}api/search?{query}'
RESULT_URL = '{base}?{query}'
THUMB_URL = '{base}img/{episode}/{timestamp}/medium.jpg'
IMAGE_URL = '{base}img/{episode}/{timestamp}.jpg'
def request(query, params):
params['url'] = SEARCH_URL.format(base=BASE, query=urlencode({'q': query}))
return params
def response(resp):
results = []
response_data = loads(resp.text)
for result in response_data:
episode = result['Episode']
timestamp = result['Timestamp']
results.append({'template': 'images.html',
'url': RESULT_URL.format(base=BASE,
query=urlencode({'p': 'caption', 'e': episode, 't': timestamp})),
'title': episode,
'content': '',
'thumbnail_src': THUMB_URL.format(base=BASE, episode=episode, timestamp=timestamp),
'img_src': IMAGE_URL.format(base=BASE, episode=episode, timestamp=timestamp)})
return results

View File

@ -10,20 +10,30 @@
@parse url, title, content
"""
from urllib import urlencode
from cgi import escape
from lxml import etree
from json import loads
from random import randint
from time import time
from urllib import urlencode
# engine dependent config
categories = ['general']
paging = True
number_of_results = 5
number_of_results = 10
language_support = True
safesearch = True
# search-url, invalid HTTPS certificate
# search-url
base_url = 'https://gigablast.com/'
search_string = 'search?{query}&n={number_of_results}&s={offset}&format=xml&qh=0&rxiyd={rxiyd}&rand={rand}'
search_string = 'search?{query}'\
'&n={number_of_results}'\
'&c=main'\
'&s={offset}'\
'&format=json'\
'&qh=0'\
'&rxiwd={rxiwd}'\
'&qlang={lang}'\
'&ff={safesearch}'
# specific xpath variables
results_xpath = '//response//result'
@ -36,12 +46,23 @@ content_xpath = './/sum'
def request(query, params):
offset = (params['pageno'] - 1) * number_of_results
search_path = search_string.format(
query=urlencode({'q': query}),
offset=offset,
number_of_results=number_of_results,
rxiyd=randint(10000, 10000000),
rand=int(time()))
if params['language'] == 'all':
language = 'xx'
else:
language = params['language'][0:2]
if params['safesearch'] >= 1:
safesearch = 1
else:
safesearch = 0
search_path = search_string.format(query=urlencode({'q': query}),
offset=offset,
number_of_results=number_of_results,
rxiwd=1,
# rand=int(time()),
lang=language,
safesearch=safesearch)
params['url'] = base_url + search_path
@ -52,18 +73,14 @@ def request(query, params):
def response(resp):
results = []
dom = etree.fromstring(resp.content)
# parse results
for result in dom.xpath(results_xpath):
url = result.xpath(url_xpath)[0].text
title = result.xpath(title_xpath)[0].text
content = escape(result.xpath(content_xpath)[0].text)
response_json = loads(resp.text)
for result in response_json['results']:
# append result
results.append({'url': url,
'title': title,
'content': content})
results.append({'url': result['url'],
'title': escape(result['title']),
'content': escape(result['sum'])})
# return results
return results

View File

@ -46,11 +46,11 @@ country_to_hostname = {
'NZ': 'www.google.co.nz', # New Zealand
'PH': 'www.google.com.ph', # Philippines
'SG': 'www.google.com.sg', # Singapore
# 'US': 'www.google.us', # United State, redirect to .com
# 'US': 'www.google.us', # United States, redirect to .com
'ZA': 'www.google.co.za', # South Africa
'AR': 'www.google.com.ar', # Argentina
'CL': 'www.google.cl', # Chile
'ES': 'www.google.es', # Span
'ES': 'www.google.es', # Spain
'MX': 'www.google.com.mx', # Mexico
'EE': 'www.google.ee', # Estonia
'FI': 'www.google.fi', # Finland
@ -61,7 +61,7 @@ country_to_hostname = {
'HU': 'www.google.hu', # Hungary
'IT': 'www.google.it', # Italy
'JP': 'www.google.co.jp', # Japan
'KR': 'www.google.co.kr', # South Korean
'KR': 'www.google.co.kr', # South Korea
'LT': 'www.google.lt', # Lithuania
'LV': 'www.google.lv', # Latvia
'NO': 'www.google.no', # Norway
@ -76,9 +76,9 @@ country_to_hostname = {
'SE': 'www.google.se', # Sweden
'TH': 'www.google.co.th', # Thailand
'TR': 'www.google.com.tr', # Turkey
'UA': 'www.google.com.ua', # Ikraine
# 'CN': 'www.google.cn', # China, only from china ?
'HK': 'www.google.com.hk', # Hong kong
'UA': 'www.google.com.ua', # Ukraine
# 'CN': 'www.google.cn', # China, only from China ?
'HK': 'www.google.com.hk', # Hong Kong
'TW': 'www.google.com.tw' # Taiwan
}
@ -90,7 +90,7 @@ url_map = 'https://www.openstreetmap.org/'\
search_path = '/search'
search_url = ('https://{hostname}' +
search_path +
'?{query}&start={offset}&gbv=1&gws_rd=cr')
'?{query}&start={offset}&gws_rd=cr&gbv=1&lr={lang}&ei=x')
# other URLs
map_hostname_start = 'maps.google.'
@ -99,7 +99,7 @@ redirect_path = '/url'
images_path = '/images'
# specific xpath variables
results_xpath = '//li[@class="g"]'
results_xpath = '//div[@class="g"]'
url_xpath = './/h3/a/@href'
title_xpath = './/h3'
content_xpath = './/span[@class="st"]'
@ -160,6 +160,7 @@ def request(query, params):
if params['language'] == 'all':
language = 'en'
country = 'US'
url_lang = ''
else:
language_array = params['language'].lower().split('_')
if len(language_array) == 2:
@ -167,6 +168,7 @@ def request(query, params):
else:
country = 'US'
language = language_array[0] + ',' + language_array[0] + '-' + country
url_lang = 'lang_' + language_array[0]
if use_locale_domain:
google_hostname = country_to_hostname.get(country.upper(), default_hostname)
@ -175,7 +177,8 @@ def request(query, params):
params['url'] = search_url.format(offset=offset,
query=urlencode({'q': query}),
hostname=google_hostname)
hostname=google_hostname,
lang=url_lang)
params['headers']['Accept-Language'] = language
params['headers']['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
@ -209,29 +212,29 @@ def response(resp):
parsed_url = urlparse(url, google_hostname)
# map result
if ((parsed_url.netloc == google_hostname and parsed_url.path.startswith(maps_path))
or (parsed_url.netloc.startswith(map_hostname_start))):
x = result.xpath(map_near)
if len(x) > 0:
# map : near the location
results = results + parse_map_near(parsed_url, x, google_hostname)
else:
# map : detail about a location
results = results + parse_map_detail(parsed_url, result, google_hostname)
if parsed_url.netloc == google_hostname:
# TODO fix inside links
continue
# if parsed_url.path.startswith(maps_path) or parsed_url.netloc.startswith(map_hostname_start):
# print "yooooo"*30
# x = result.xpath(map_near)
# if len(x) > 0:
# # map : near the location
# results = results + parse_map_near(parsed_url, x, google_hostname)
# else:
# # map : detail about a location
# results = results + parse_map_detail(parsed_url, result, google_hostname)
# # google news
# elif parsed_url.path == search_path:
# # skipping news results
# pass
# google news
elif (parsed_url.netloc == google_hostname
and parsed_url.path == search_path):
# skipping news results
pass
# images result
elif (parsed_url.netloc == google_hostname
and parsed_url.path == images_path):
# only thumbnail image provided,
# so skipping image results
# results = results + parse_images(result, google_hostname)
pass
# # images result
# elif parsed_url.path == images_path:
# # only thumbnail image provided,
# # so skipping image results
# # results = results + parse_images(result, google_hostname)
# pass
else:
# normal result

View File

@ -49,8 +49,6 @@ def response(resp):
# parse results
for result in dom.xpath('//div[@data-ved]'):
data_url = result.xpath('./a/@href')[0]
data_query = {k: v[0] for k, v in parse_qs(data_url.split('?', 1)[1]).iteritems()}
metadata = loads(result.xpath('./div[@class="rg_meta"]/text()')[0])
@ -60,11 +58,11 @@ def response(resp):
thumbnail_src = thumbnail_src.replace("http://", "https://")
# append result
results.append({'url': data_query['imgrefurl'],
results.append({'url': metadata['ru'],
'title': metadata['pt'],
'content': metadata['s'],
'thumbnail_src': metadata['tu'],
'img_src': data_query['imgurl'],
'thumbnail_src': thumbnail_src,
'img_src': metadata['ou'],
'template': 'images.html'})
# return results

View File

@ -24,13 +24,13 @@ number_of_results = 1
# search-url
base_url = 'https://{language}.wikipedia.org/'
search_url = base_url + 'w/api.php?action=query'\
'&list=search'\
'&{query}'\
'&srprop=timestamp'\
'&format=json'\
'&sroffset={offset}'\
'&srlimit={limit}' # noqa
search_postfix = 'w/api.php?action=query'\
'&list=search'\
'&{query}'\
'&format=json'\
'&sroffset={offset}'\
'&srlimit={limit}'\
'&srwhat=nearmatch' # search for a near match in the title
# do search-request
@ -48,12 +48,15 @@ def request(query, params):
else:
language = params['language'].split('_')[0]
if len(format_strings) > 1:
# format_string [('https://', 'language', '', None), ('.wikipedia.org/', None, None, None)]
if any(x[1] == 'language' for x in format_strings):
string_args['language'] = language
# write search-language back to params, required in response
params['language'] = language
search_url = base_url + search_postfix
params['url'] = search_url.format(**string_args)
return params
@ -71,6 +74,8 @@ def response(resp):
# parse results
for result in search_results['query']['search']:
if result.get('snippet', '').startswith('#REDIRECT'):
continue
url = base_url.format(language=resp.search_params['language']) +\
'wiki/' + quote(result['title'].replace(' ', '_').encode('utf-8'))

View File

@ -0,0 +1,119 @@
"""
Nyaa.se (Anime Bittorrent tracker)
@website http://www.nyaa.se/
@provide-api no
@using-api no
@results HTML
@stable no (HTML can change)
@parse url, title, content, seed, leech, torrentfile
"""
from cgi import escape
from urllib import urlencode
from lxml import html
from searx.engines.xpath import extract_text
# engine dependent config
categories = ['files', 'images', 'videos', 'music']
paging = True
# search-url
base_url = 'http://www.nyaa.se/'
search_url = base_url + '?page=search&{query}&offset={offset}'
# xpath queries
xpath_results = '//table[@class="tlist"]//tr[contains(@class, "tlistrow")]'
xpath_category = './/td[@class="tlisticon"]/a'
xpath_title = './/td[@class="tlistname"]/a'
xpath_torrent_file = './/td[@class="tlistdownload"]/a'
xpath_filesize = './/td[@class="tlistsize"]/text()'
xpath_seeds = './/td[@class="tlistsn"]/text()'
xpath_leeches = './/td[@class="tlistln"]/text()'
xpath_downloads = './/td[@class="tlistdn"]/text()'
# convert a variable to integer or return 0 if it's not a number
def int_or_zero(num):
if isinstance(num, list):
if len(num) < 1:
return 0
num = num[0]
if num.isdigit():
return int(num)
return 0
# get multiplier to convert torrent size to bytes
def get_filesize_mul(suffix):
return {
'KB': 1024,
'MB': 1024 ** 2,
'GB': 1024 ** 3,
'TB': 1024 ** 4,
'KIB': 1024,
'MIB': 1024 ** 2,
'GIB': 1024 ** 3,
'TIB': 1024 ** 4
}[str(suffix).upper()]
# do search-request
def request(query, params):
query = urlencode({'term': query})
params['url'] = search_url.format(query=query, offset=params['pageno'])
return params
# get response from search-request
def response(resp):
results = []
dom = html.fromstring(resp.text)
for result in dom.xpath(xpath_results):
# category in which our torrent belongs
category = result.xpath(xpath_category)[0].attrib.get('title')
# torrent title
page_a = result.xpath(xpath_title)[0]
title = escape(extract_text(page_a))
# link to the page
href = page_a.attrib.get('href')
# link to the torrent file
torrent_link = result.xpath(xpath_torrent_file)[0].attrib.get('href')
# torrent size
try:
file_size, suffix = result.xpath(xpath_filesize)[0].split(' ')
file_size = int(float(file_size) * get_filesize_mul(suffix))
except Exception as e:
file_size = None
# seed count
seed = int_or_zero(result.xpath(xpath_seeds))
# leech count
leech = int_or_zero(result.xpath(xpath_leeches))
# torrent downloads count
downloads = int_or_zero(result.xpath(xpath_downloads))
# content string contains all information not included into template
content = 'Category: "{category}". Downloaded {downloads} times.'
content = content.format(category=category, downloads=downloads)
content = escape(content)
results.append({'url': href,
'title': title,
'content': content,
'seed': seed,
'leech': leech,
'filesize': file_size,
'torrentfile': torrent_link,
'template': 'torrent.html'})
return results

View File

@ -0,0 +1,79 @@
"""
Reddit
@website https://www.reddit.com/
@provide-api yes (https://www.reddit.com/dev/api)
@using-api yes
@results JSON
@stable yes
@parse url, title, content, thumbnail, publishedDate
"""
import json
from cgi import escape
from urllib import urlencode
from urlparse import urlparse, urljoin
from datetime import datetime
# engine dependent config
categories = ['general', 'images', 'news', 'social media']
page_size = 25
# search-url
base_url = 'https://www.reddit.com/'
search_url = base_url + 'search.json?{query}'
# do search-request
def request(query, params):
query = urlencode({'q': query,
'limit': page_size})
params['url'] = search_url.format(query=query)
return params
# get response from search-request
def response(resp):
img_results = []
text_results = []
search_results = json.loads(resp.text)
# return empty array if there are no results
if 'data' not in search_results:
return []
posts = search_results.get('data', {}).get('children', [])
# process results
for post in posts:
data = post['data']
# extract post information
params = {
'url': urljoin(base_url, data['permalink']),
'title': data['title']
}
# if thumbnail field contains a valid URL, we need to change template
thumbnail = data['thumbnail']
url_info = urlparse(thumbnail)
# netloc & path
if url_info[1] != '' and url_info[2] != '':
params['img_src'] = data['url']
params['thumbnail_src'] = thumbnail
params['template'] = 'images.html'
img_results.append(params)
else:
created = datetime.fromtimestamp(data['created_utc'])
content = escape(data['selftext'])
if len(content) > 500:
content = content[:500] + '...'
params['content'] = content
params['publishedDate'] = created
text_results.append(params)
# show images first and text results second
return img_results + text_results

View File

@ -20,7 +20,7 @@ paging = True
# search-url
url = 'https://searchcode.com/'
search_url = url+'api/codesearch_I/?{query}&p={pageno}'
search_url = url + 'api/codesearch_I/?{query}&p={pageno}'
# special code-endings which are not recognised by the file ending
code_endings = {'cs': 'c#',
@ -32,7 +32,7 @@ code_endings = {'cs': 'c#',
# do search-request
def request(query, params):
params['url'] = search_url.format(query=urlencode({'q': query}),
pageno=params['pageno']-1)
pageno=params['pageno'] - 1)
# Disable SSL verification
# error: (60) SSL certificate problem: unable to get local issuer

View File

@ -19,13 +19,13 @@ paging = True
# search-url
url = 'https://searchcode.com/'
search_url = url+'api/search_IV/?{query}&p={pageno}'
search_url = url + 'api/search_IV/?{query}&p={pageno}'
# do search-request
def request(query, params):
params['url'] = search_url.format(query=urlencode({'q': query}),
pageno=params['pageno']-1)
pageno=params['pageno'] - 1)
# Disable SSL verification
# error: (60) SSL certificate problem: unable to get local issuer

View File

@ -10,17 +10,19 @@
@parse url, title, content, publishedDate, embedded
"""
import re
from StringIO import StringIO
from json import loads
from lxml import etree
from urllib import urlencode, quote_plus
from dateutil import parser
from searx import logger
from searx.poolrequests import get as http_get
# engine dependent config
categories = ['music']
paging = True
# api-key
guest_client_id = 'b45b1aa10f1ac2941910a7f0d10f8e28'
# search-url
url = 'https://api.soundcloud.com/'
search_url = url + 'search?{query}'\
@ -35,6 +37,30 @@ embedded_url = '<iframe width="100%" height="166" ' +\
'data-src="https://w.soundcloud.com/player/?url={uri}"></iframe>'
def get_client_id():
response = http_get("https://soundcloud.com")
rx_namespace = {"re": "http://exslt.org/regular-expressions"}
if response.ok:
tree = etree.parse(StringIO(response.content), etree.HTMLParser())
script_tags = tree.xpath("//script[re:match(@src, '(.*app.*js)')]", namespaces=rx_namespace)
app_js_urls = [script_tag.get('src') for script_tag in script_tags if script_tag is not None]
# extracts valid app_js urls from soundcloud.com content
for app_js_url in app_js_urls:
# gets app_js and searches for the clientid
response = http_get(app_js_url)
if response.ok:
cids = re.search(r'client_id:"([^"]*)"', response.content, re.M | re.I)
if cids is not None and len(cids.groups()):
return cids.groups()[0]
logger.warning("Unable to fetch guest client_id from SoundCloud, check parser!")
return ""
# api-key
guest_client_id = get_client_id()
# do search-request
def request(query, params):
offset = (params['pageno'] - 1) * 20

View File

@ -22,7 +22,7 @@ paging = True
# search-url
url = 'https://stackoverflow.com/'
search_url = url+'search?{query}&page={pageno}'
search_url = url + 'search?{query}&page={pageno}'
# specific xpath variables
results_xpath = '//div[contains(@class,"question-summary")]'

View File

@ -90,8 +90,8 @@ def response(resp):
# check if search result starts with something like: "2 Sep 2014 ... "
if re.match("^([1-9]|[1-2][0-9]|3[0-1]) [A-Z][a-z]{2} [0-9]{4} \.\.\. ", content):
date_pos = content.find('...')+4
date_string = content[0:date_pos-5]
date_pos = content.find('...') + 4
date_string = content[0:date_pos - 5]
published_date = parser.parse(date_string, dayfirst=True)
# fix content string
@ -99,8 +99,8 @@ def response(resp):
# check if search result starts with something like: "5 days ago ... "
elif re.match("^[0-9]+ days? ago \.\.\. ", content):
date_pos = content.find('...')+4
date_string = content[0:date_pos-5]
date_pos = content.find('...') + 4
date_string = content[0:date_pos - 5]
# calculate datetime
published_date = datetime.now() - timedelta(days=int(re.match(r'\d+', date_string).group()))

View File

@ -10,6 +10,7 @@
@parse url, title, content
"""
from cgi import escape
from json import loads
from urllib import urlencode, unquote
import re
@ -77,7 +78,7 @@ def response(resp):
# append result
results.append({'url': result['SourceUrl'],
'title': result['Title'],
'title': escape(result['Title']),
'content': '',
'img_src': img_url,
'template': 'images.html'})
@ -89,8 +90,8 @@ def response(resp):
# append result
results.append({'url': result_url,
'title': result_title,
'content': result_content})
'title': escape(result_title),
'content': escape(result_content)})
# parse images
for result in json.get('Images', []):
@ -99,7 +100,7 @@ def response(resp):
# append result
results.append({'url': result['SourceUrl'],
'title': result['Title'],
'title': escape(result['Title']),
'content': '',
'img_src': img_url,
'template': 'images.html'})

View File

@ -0,0 +1,102 @@
"""
Tokyo Toshokan (A BitTorrent Library for Japanese Media)
@website https://www.tokyotosho.info/
@provide-api no
@using-api no
@results HTML
@stable no (HTML can change)
@parse url, title, publishedDate, seed, leech,
filesize, magnetlink, content
"""
import re
from cgi import escape
from urllib import urlencode
from lxml import html
from searx.engines.xpath import extract_text
from datetime import datetime
from searx.engines.nyaa import int_or_zero, get_filesize_mul
# engine dependent config
categories = ['files', 'videos', 'music']
paging = True
# search-url
base_url = 'https://www.tokyotosho.info/'
search_url = base_url + 'search.php?{query}'
# do search-request
def request(query, params):
query = urlencode({'page': params['pageno'],
'terms': query})
params['url'] = search_url.format(query=query)
return params
# get response from search-request
def response(resp):
results = []
dom = html.fromstring(resp.text)
rows = dom.xpath('//table[@class="listing"]//tr[contains(@class, "category_0")]')
# check if there are no results or page layout was changed so we cannot parse it
# currently there are two rows for each result, so total count must be even
if len(rows) == 0 or len(rows) % 2 != 0:
return []
# regular expression for parsing torrent size strings
size_re = re.compile('Size:\s*([\d.]+)(TB|GB|MB|B)', re.IGNORECASE)
# processing the results, two rows at a time
for i in xrange(0, len(rows), 2):
# parse the first row
name_row = rows[i]
links = name_row.xpath('./td[@class="desc-top"]/a')
params = {
'template': 'torrent.html',
'url': links[-1].attrib.get('href'),
'title': extract_text(links[-1])
}
# I have not yet seen any torrents without magnet links, but
# it's better to be prepared to stumble upon one some day
if len(links) == 2:
magnet = links[0].attrib.get('href')
if magnet.startswith('magnet'):
# okay, we have a valid magnet link, let's add it to the result
params['magnetlink'] = magnet
# no more info in the first row, start parsing the second one
info_row = rows[i + 1]
desc = extract_text(info_row.xpath('./td[@class="desc-bot"]')[0])
for item in desc.split('|'):
item = item.strip()
if item.startswith('Size:'):
try:
# ('1.228', 'GB')
groups = size_re.match(item).groups()
multiplier = get_filesize_mul(groups[1])
params['filesize'] = int(multiplier * float(groups[0]))
except Exception as e:
pass
elif item.startswith('Date:'):
try:
# Date: 2016-02-21 21:44 UTC
date = datetime.strptime(item, 'Date: %Y-%m-%d %H:%M UTC')
params['publishedDate'] = date
except Exception as e:
pass
elif item.startswith('Comment:'):
params['content'] = item
stats = info_row.xpath('./td[@class="stats"]/span')
# has the layout not changed yet?
if len(stats) == 3:
params['seed'] = int_or_zero(extract_text(stats[0]))
params['leech'] = int_or_zero(extract_text(stats[1]))
results.append(params)
return results

View File

@ -0,0 +1,93 @@
"""
Torrentz.eu (BitTorrent meta-search engine)
@website https://torrentz.eu/
@provide-api no
@using-api no
@results HTML
@stable no (HTML can change, although unlikely,
see https://torrentz.eu/torrentz.btsearch)
@parse url, title, publishedDate, seed, leech, filesize, magnetlink
"""
import re
from cgi import escape
from urllib import urlencode
from lxml import html
from searx.engines.xpath import extract_text
from datetime import datetime
from searx.engines.nyaa import int_or_zero, get_filesize_mul
# engine dependent config
categories = ['files', 'videos', 'music']
paging = True
# search-url
# https://torrentz.eu/search?f=EXAMPLE&p=6
base_url = 'https://torrentz.eu/'
search_url = base_url + 'search?{query}'
# do search-request
def request(query, params):
page = params['pageno'] - 1
query = urlencode({'q': query, 'p': page})
params['url'] = search_url.format(query=query)
return params
# get response from search-request
def response(resp):
results = []
dom = html.fromstring(resp.text)
for result in dom.xpath('//div[@class="results"]/dl'):
name_cell = result.xpath('./dt')[0]
title = extract_text(name_cell)
# skip rows that do not contain a link to a torrent
links = name_cell.xpath('./a')
if len(links) != 1:
continue
# extract url and remove a slash in the beginning
link = links[0].attrib.get('href').lstrip('/')
seed = result.xpath('./dd/span[@class="u"]/text()')[0].replace(',', '')
leech = result.xpath('./dd/span[@class="d"]/text()')[0].replace(',', '')
params = {
'url': base_url + link,
'title': title,
'seed': int_or_zero(seed),
'leech': int_or_zero(leech),
'template': 'torrent.html'
}
# let's try to calculate the torrent size
try:
size_str = result.xpath('./dd/span[@class="s"]/text()')[0]
size, suffix = size_str.split()
params['filesize'] = int(size) * get_filesize_mul(suffix)
except Exception as e:
pass
# does our link contain a valid SHA1 sum?
if re.compile('[0-9a-fA-F]{40}').match(link):
# add a magnet link to the result
params['magnetlink'] = 'magnet:?xt=urn:btih:' + link
# extract and convert creation date
try:
date_str = result.xpath('./dd/span[@class="a"]/span')[0].attrib.get('title')
# Fri, 25 Mar 2016 16:29:01
date = datetime.strptime(date_str, '%a, %d %b %Y %H:%M:%S')
params['publishedDate'] = date
except Exception as e:
pass
results.append(params)
return results

View File

@ -86,15 +86,15 @@ def getDetail(jsonresponse, wikidata_id, language, locale):
results.append({'title': title, 'url': official_website})
wikipedia_link_count = 0
if language != 'en':
wikipedia_link_count += add_url(urls,
'Wikipedia (' + language + ')',
get_wikilink(result, language +
'wiki'))
wikipedia_en_link = get_wikilink(result, 'enwiki')
wikipedia_link = get_wikilink(result, language + 'wiki')
wikipedia_link_count += add_url(urls,
'Wikipedia (en)',
wikipedia_en_link)
'Wikipedia (' + language + ')',
wikipedia_link)
if language != 'en':
wikipedia_en_link = get_wikilink(result, 'enwiki')
wikipedia_link_count += add_url(urls,
'Wikipedia (en)',
wikipedia_en_link)
if wikipedia_link_count == 0:
misc_language = get_wiki_firstlanguage(result, 'wiki')
if misc_language is not None:
@ -188,7 +188,7 @@ def getDetail(jsonresponse, wikidata_id, language, locale):
else:
results.append({
'infobox': title,
'id': wikipedia_en_link,
'id': wikipedia_link,
'content': description,
'attributes': attributes,
'urls': urls
@ -295,7 +295,7 @@ def get_geolink(claims, propertyName, defaultValue=''):
if precision < 0.0003:
zoom = 19
else:
zoom = int(15 - precision*8.8322 + precision*precision*0.625447)
zoom = int(15 - precision * 8.8322 + precision * precision * 0.625447)
url = url_map\
.replace('{latitude}', str(value.get('latitude', 0)))\
@ -318,6 +318,6 @@ def get_wikilink(result, wikiid):
def get_wiki_firstlanguage(result, wikipatternid):
for k in result.get('sitelinks', {}).keys():
if k.endswith(wikipatternid) and len(k) == (2+len(wikipatternid)):
if k.endswith(wikipatternid) and len(k) == (2 + len(wikipatternid)):
return k[0:2]
return None

View File

@ -0,0 +1,114 @@
"""
Wikipedia (Web)
@website https://{language}.wikipedia.org
@provide-api yes
@using-api yes
@results JSON
@stable yes
@parse url, infobox
"""
from json import loads
from urllib import urlencode, quote
# search-url
base_url = 'https://{language}.wikipedia.org/'
search_postfix = 'w/api.php?'\
'action=query'\
'&format=json'\
'&{query}'\
'&prop=extracts|pageimages'\
'&exintro'\
'&explaintext'\
'&pithumbsize=300'\
'&redirects'
# set language in base_url
def url_lang(lang):
if lang == 'all':
language = 'en'
else:
language = lang.split('_')[0]
return base_url.format(language=language)
# do search-request
def request(query, params):
if query.islower():
query += '|' + query.title()
params['url'] = url_lang(params['language']) \
+ search_postfix.format(query=urlencode({'titles': query}))
return params
# get first meaningful paragraph
# this should filter out disambiguation pages and notes above first paragraph
# "magic numbers" were obtained by fine tuning
def extract_first_paragraph(content, title, image):
first_paragraph = None
failed_attempts = 0
for paragraph in content.split('\n'):
starts_with_title = paragraph.lower().find(title.lower(), 0, len(title) + 35)
length = len(paragraph)
if length >= 200 or (starts_with_title >= 0 and (image or length >= 150)):
first_paragraph = paragraph
break
failed_attempts += 1
if failed_attempts > 3:
return None
return first_paragraph
# get response from search-request
def response(resp):
results = []
search_result = loads(resp.content)
# wikipedia article's unique id
# first valid id is assumed to be the requested article
for article_id in search_result['query']['pages']:
page = search_result['query']['pages'][article_id]
if int(article_id) > 0:
break
if int(article_id) < 0:
return []
title = page.get('title')
image = page.get('thumbnail')
if image:
image = image.get('source')
extract = page.get('extract')
summary = extract_first_paragraph(extract, title, image)
if not summary:
return []
# link to wikipedia article
# parenthesis are not quoted to make infobox mergeable with wikidata's
wikipedia_link = url_lang(resp.search_params['language']) \
+ 'wiki/' + quote(title.replace(' ', '_').encode('utf8')).replace('%28', '(').replace('%29', ')')
results.append({'url': wikipedia_link, 'title': title})
results.append({'infobox': title,
'id': wikipedia_link,
'content': summary,
'img_src': image,
'urls': [{'title': 'Wikipedia', 'url': wikipedia_link}]})
return results

View File

@ -0,0 +1,122 @@
# Wolfram Alpha (Science)
#
# @website https://www.wolframalpha.com
# @provide-api yes (https://api.wolframalpha.com/v2/)
#
# @using-api yes
# @results XML
# @stable yes
# @parse url, infobox
from urllib import urlencode
from lxml import etree
# search-url
search_url = 'https://api.wolframalpha.com/v2/query?appid={api_key}&{query}'
site_url = 'https://www.wolframalpha.com/input/?{query}'
api_key = '' # defined in settings.yml
# xpath variables
failure_xpath = '/queryresult[attribute::success="false"]'
answer_xpath = '//pod[attribute::primary="true"]/subpod/plaintext'
input_xpath = '//pod[starts-with(attribute::id, "Input")]/subpod/plaintext'
pods_xpath = '//pod'
subpods_xpath = './subpod'
pod_id_xpath = './@id'
pod_title_xpath = './@title'
plaintext_xpath = './plaintext'
image_xpath = './img'
img_src_xpath = './@src'
img_alt_xpath = './@alt'
# pods to display as image in infobox
# this pods do return a plaintext, but they look better and are more useful as images
image_pods = {'VisualRepresentation',
'Illustration'}
# do search-request
def request(query, params):
params['url'] = search_url.format(query=urlencode({'input': query}),
api_key=api_key)
params['headers']['Referer'] = site_url.format(query=urlencode({'i': query}))
return params
# replace private user area characters to make text legible
def replace_pua_chars(text):
pua_chars = {u'\uf522': u'\u2192', # rigth arrow
u'\uf7b1': u'\u2115', # set of natural numbers
u'\uf7b4': u'\u211a', # set of rational numbers
u'\uf7b5': u'\u211d', # set of real numbers
u'\uf7bd': u'\u2124', # set of integer numbers
u'\uf74c': 'd', # differential
u'\uf74d': u'\u212f', # euler's number
u'\uf74e': 'i', # imaginary number
u'\uf7d9': '='} # equals sign
for k, v in pua_chars.iteritems():
text = text.replace(k, v)
return text
# get response from search-request
def response(resp):
results = []
search_results = etree.XML(resp.content)
# return empty array if there are no results
if search_results.xpath(failure_xpath):
return []
try:
infobox_title = search_results.xpath(input_xpath)[0].text
except:
infobox_title = None
pods = search_results.xpath(pods_xpath)
result_chunks = []
for pod in pods:
pod_id = pod.xpath(pod_id_xpath)[0]
pod_title = pod.xpath(pod_title_xpath)[0]
subpods = pod.xpath(subpods_xpath)
if not subpods:
continue
# Appends either a text or an image, depending on which one is more suitable
for subpod in subpods:
content = subpod.xpath(plaintext_xpath)[0].text
image = subpod.xpath(image_xpath)
if content and pod_id not in image_pods:
# if no input pod was found, title is first plaintext pod
if not infobox_title:
infobox_title = content
content = replace_pua_chars(content)
result_chunks.append({'label': pod_title, 'value': content})
elif image:
result_chunks.append({'label': pod_title,
'image': {'src': image[0].xpath(img_src_xpath)[0],
'alt': image[0].xpath(img_alt_xpath)[0]}})
if not result_chunks:
return []
# append infobox
results.append({'infobox': infobox_title,
'attributes': result_chunks,
'urls': [{'title': 'Wolfram|Alpha', 'url': resp.request.headers['Referer'].decode('utf8')}]})
# append link to site
results.append({'url': resp.request.headers['Referer'].decode('utf8'),
'title': 'Wolfram|Alpha',
'content': infobox_title})
return results

View File

@ -0,0 +1,116 @@
# Wolfram|Alpha (Science)
#
# @website https://www.wolframalpha.com/
# @provide-api yes (https://api.wolframalpha.com/v2/)
#
# @using-api no
# @results JSON
# @stable no
# @parse url, infobox
from cgi import escape
from json import loads
from time import time
from urllib import urlencode
from lxml.etree import XML
from searx.poolrequests import get as http_get
# search-url
url = 'https://www.wolframalpha.com/'
search_url = url + 'input/json.jsp'\
'?async=false'\
'&banners=raw'\
'&debuggingdata=false'\
'&format=image,plaintext,imagemap,minput,moutput'\
'&formattimeout=2'\
'&{query}'\
'&output=JSON'\
'&parsetimeout=2'\
'&proxycode={token}'\
'&scantimeout=0.5'\
'&sponsorcategories=true'\
'&statemethod=deploybutton'
referer_url = url + 'input/?{query}'
token = {'value': '',
'last_updated': None}
# pods to display as image in infobox
# this pods do return a plaintext, but they look better and are more useful as images
image_pods = {'VisualRepresentation',
'Illustration',
'Symbol'}
# seems, wolframalpha resets its token in every hour
def obtain_token():
update_time = time() - (time() % 3600)
try:
token_response = http_get('https://www.wolframalpha.com/input/api/v1/code?ts=9999999999999999999', timeout=2.0)
token['value'] = loads(token_response.text)['code']
token['last_updated'] = update_time
except:
pass
return token
obtain_token()
# do search-request
def request(query, params):
# obtain token if last update was more than an hour
if time() - token['last_updated'] > 3600:
obtain_token()
params['url'] = search_url.format(query=urlencode({'input': query}), token=token['value'])
params['headers']['Referer'] = referer_url.format(query=urlencode({'i': query}))
return params
# get response from search-request
def response(resp):
results = []
resp_json = loads(resp.text)
if not resp_json['queryresult']['success']:
return []
# TODO handle resp_json['queryresult']['assumptions']
result_chunks = []
infobox_title = None
for pod in resp_json['queryresult']['pods']:
pod_id = pod.get('id', '')
pod_title = pod.get('title', '')
if 'subpods' not in pod:
continue
if pod_id == 'Input' or not infobox_title:
infobox_title = pod['subpods'][0]['plaintext']
for subpod in pod['subpods']:
if subpod['plaintext'] != '' and pod_id not in image_pods:
# append unless it's not an actual answer
if subpod['plaintext'] != '(requires interactivity)':
result_chunks.append({'label': pod_title, 'value': subpod['plaintext']})
elif 'img' in subpod:
result_chunks.append({'label': pod_title, 'image': subpod['img']})
if not result_chunks:
return []
results.append({'infobox': infobox_title,
'attributes': result_chunks,
'urls': [{'title': 'Wolfram|Alpha', 'url': resp.request.headers['Referer'].decode('utf8')}]})
results.append({'url': resp.request.headers['Referer'].decode('utf8'),
'title': 'Wolfram|Alpha',
'content': infobox_title})
return results

View File

@ -22,7 +22,7 @@ paging = False
# search-url
base_url = 'https://1x.com'
search_url = base_url+'/backend/search.php?{query}'
search_url = base_url + '/backend/search.php?{query}'
# do search-request

View File

@ -11,6 +11,14 @@ title_xpath = None
suggestion_xpath = ''
results_xpath = ''
# parameters for engines with paging support
#
# number of results on each page
# (only needed if the site requires not a page number, but an offset)
page_size = 1
# number of the first page (usually 0 or 1)
first_page_num = 1
'''
if xpath_results is list, extract the text from each result and concat the list
@ -43,7 +51,7 @@ def extract_url(xpath_results, search_url):
if url.startswith('//'):
# add http or https to this kind of url //example.com/
parsed_search_url = urlparse(search_url)
url = parsed_search_url.scheme+url
url = parsed_search_url.scheme + url
elif url.startswith('/'):
# fix relative url to the search engine
url = urljoin(search_url, url)
@ -69,15 +77,21 @@ def normalize_url(url):
p = parsed_url.path
mark = p.find('/**')
if mark != -1:
return unquote(p[mark+3:]).decode('utf-8')
return unquote(p[mark + 3:]).decode('utf-8')
return url
def request(query, params):
query = urlencode({'q': query})[2:]
params['url'] = search_url.format(query=query)
fp = {'query': query}
if paging and search_url.find('{pageno}') >= 0:
fp['pageno'] = (params['pageno'] + first_page_num - 1) * page_size
params['url'] = search_url.format(**fp)
params['query'] = query
return params

View File

@ -9,6 +9,7 @@
@parse url, title, content
"""
from cgi import escape
from urllib import urlencode
from lxml import html
from searx.search import logger
@ -38,7 +39,7 @@ content_xpath = './/div[@class="serp-item__text"]//text()'
def request(query, params):
lang = params['language'].split('_')[0]
host = base_url.format(tld=language_map.get(lang) or default_tld)
params['url'] = host + search_url.format(page=params['pageno']-1,
params['url'] = host + search_url.format(page=params['pageno'] - 1,
query=urlencode({'text': query}))
return params
@ -51,8 +52,8 @@ def response(resp):
for result in dom.xpath(results_xpath):
try:
res = {'url': result.xpath(url_xpath)[0],
'title': ''.join(result.xpath(title_xpath)),
'content': ''.join(result.xpath(content_xpath))}
'title': escape(''.join(result.xpath(title_xpath))),
'content': escape(''.join(result.xpath(content_xpath)))}
except:
logger.exception('yandex parse crash')
continue

View File

@ -20,10 +20,10 @@ language_codes = (
("ar_XA", "Arabic", "Arabia"),
("bg_BG", "Bulgarian", "Bulgaria"),
("cs_CZ", "Czech", "Czech Republic"),
("de_DE", "German", "Germany"),
("da_DK", "Danish", "Denmark"),
("de_AT", "German", "Austria"),
("de_CH", "German", "Switzerland"),
("de_DE", "German", "Germany"),
("el_GR", "Greek", "Greece"),
("en_AU", "English", "Australia"),
("en_CA", "English", "Canada"),
@ -61,6 +61,7 @@ language_codes = (
("nb_NO", "Norwegian", "Norway"),
("nl_BE", "Dutch", "Belgium"),
("nl_NL", "Dutch", "Netherlands"),
("oc_OC", "Occitan", "Occitan"),
("pl_PL", "Polish", "Poland"),
("pt_BR", "Portuguese", "Brazil"),
("pt_PT", "Portuguese", "Portugal"),

View File

@ -20,6 +20,7 @@ from searx import logger
logger = logger.getChild('plugins')
from searx.plugins import (https_rewrite,
open_results_on_new_tab,
self_info,
search_on_category_select,
tracker_url_remover)
@ -72,6 +73,7 @@ class PluginStore():
plugins = PluginStore()
plugins.register(https_rewrite)
plugins.register(open_results_on_new_tab)
plugins.register(self_info)
plugins.register(search_on_category_select)
plugins.register(tracker_url_remover)

View File

@ -103,10 +103,10 @@ def load_single_https_ruleset(rules_path):
# into a valid python regex group
rule_from = ruleset.attrib['from'].replace('$', '\\')
if rule_from.endswith('\\'):
rule_from = rule_from[:-1]+'$'
rule_from = rule_from[:-1] + '$'
rule_to = ruleset.attrib['to'].replace('$', '\\')
if rule_to.endswith('\\'):
rule_to = rule_to[:-1]+'$'
rule_to = rule_to[:-1] + '$'
# TODO, not working yet because of the hack above,
# currently doing that in webapp.py

View File

@ -0,0 +1,24 @@
'''
searx is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
searx is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with searx. If not, see < http://www.gnu.org/licenses/ >.
(C) 2016 by Adam Tauber, <asciimoo@gmail.com>
'''
from flask.ext.babel import gettext
name = gettext('Open result links on new browser tabs')
description = gettext('Results are opened in the same window by default. '
'This plugin overwrites the default behaviour to open links on new tabs/windows. '
'(JavaScript required)')
default_on = False
js_dependencies = ('plugins/js/open_results_on_new_tab.js',)

View File

@ -20,4 +20,4 @@ description = gettext('Perform search immediately if a category selected. '
'Disable to select multiple categories. (JavaScript required)')
default_on = True
js_dependencies = ('js/search_on_category_select.js',)
js_dependencies = ('plugins/js/search_on_category_select.js',)

View File

@ -92,7 +92,7 @@ def head(url, **kwargs):
return request('head', url, **kwargs)
def post(url, data=None, **kwargs):
def post(url, data=None, **kwargs):
return request('post', url, data=data, **kwargs)

View File

@ -0,0 +1,271 @@
from searx import settings, autocomplete
from searx.languages import language_codes as languages
COOKIE_MAX_AGE = 60 * 60 * 24 * 365 * 5 # 5 years
LANGUAGE_CODES = [l[0] for l in languages]
LANGUAGE_CODES.append('all')
DISABLED = 0
ENABLED = 1
class MissingArgumentException(Exception):
pass
class ValidationException(Exception):
pass
class Setting(object):
"""Base class of user settings"""
def __init__(self, default_value, **kwargs):
super(Setting, self).__init__()
self.value = default_value
for key, value in kwargs.iteritems():
setattr(self, key, value)
self._post_init()
def _post_init(self):
pass
def parse(self, data):
self.value = data
def get_value(self):
return self.value
def save(self, name, resp):
resp.set_cookie(name, bytes(self.value), max_age=COOKIE_MAX_AGE)
class StringSetting(Setting):
"""Setting of plain string values"""
pass
class EnumStringSetting(Setting):
"""Setting of a value which can only come from the given choices"""
def _post_init(self):
if not hasattr(self, 'choices'):
raise MissingArgumentException('Missing argument: choices')
if self.value != '' and self.value not in self.choices:
raise ValidationException('Invalid default value: {0}'.format(self.value))
def parse(self, data):
if data not in self.choices and data != self.value:
raise ValidationException('Invalid choice: {0}'.format(data))
self.value = data
class MultipleChoiceSetting(EnumStringSetting):
"""Setting of values which can only come from the given choices"""
def _post_init(self):
if not hasattr(self, 'choices'):
raise MissingArgumentException('Missing argument: choices')
for item in self.value:
if item not in self.choices:
raise ValidationException('Invalid default value: {0}'.format(self.value))
def parse(self, data):
if data == '':
self.value = []
return
elements = data.split(',')
for item in elements:
if item not in self.choices:
raise ValidationException('Invalid choice: {0}'.format(item))
self.value = elements
def parse_form(self, data):
self.value = []
for choice in data:
if choice in self.choices and choice not in self.value:
self.value.append(choice)
def save(self, name, resp):
resp.set_cookie(name, ','.join(self.value), max_age=COOKIE_MAX_AGE)
class MapSetting(Setting):
"""Setting of a value that has to be translated in order to be storable"""
def _post_init(self):
if not hasattr(self, 'map'):
raise MissingArgumentException('missing argument: map')
if self.value not in self.map.values():
raise ValidationException('Invalid default value')
def parse(self, data):
if data not in self.map:
raise ValidationException('Invalid choice: {0}'.format(data))
self.value = self.map[data]
self.key = data
def save(self, name, resp):
resp.set_cookie(name, bytes(self.key), max_age=COOKIE_MAX_AGE)
class SwitchableSetting(Setting):
""" Base class for settings that can be turned on && off"""
def _post_init(self):
self.disabled = set()
self.enabled = set()
if not hasattr(self, 'choices'):
raise MissingArgumentException('missing argument: choices')
def transform_form_items(self, items):
return items
def transform_values(self, values):
return values
def parse_cookie(self, data):
if data[DISABLED] != '':
self.disabled = set(data[DISABLED].split(','))
if data[ENABLED] != '':
self.enabled = set(data[ENABLED].split(','))
def parse_form(self, items):
items = self.transform_form_items(items)
self.disabled = set()
self.enabled = set()
for choice in self.choices:
if choice['default_on']:
if choice['id'] in items:
self.disabled.add(choice['id'])
else:
if choice['id'] not in items:
self.enabled.add(choice['id'])
def save(self, resp):
resp.set_cookie('disabled_{0}'.format(self.value), ','.join(self.disabled), max_age=COOKIE_MAX_AGE)
resp.set_cookie('enabled_{0}'.format(self.value), ','.join(self.enabled), max_age=COOKIE_MAX_AGE)
def get_disabled(self):
disabled = self.disabled
for choice in self.choices:
if not choice['default_on'] and choice['id'] not in self.enabled:
disabled.add(choice['id'])
return self.transform_values(disabled)
def get_enabled(self):
enabled = self.enabled
for choice in self.choices:
if choice['default_on'] and choice['id'] not in self.disabled:
enabled.add(choice['id'])
return self.transform_values(enabled)
class EnginesSetting(SwitchableSetting):
def _post_init(self):
super(EnginesSetting, self)._post_init()
transformed_choices = []
for engine_name, engine in self.choices.iteritems():
for category in engine.categories:
transformed_choice = dict()
transformed_choice['default_on'] = not engine.disabled
transformed_choice['id'] = '{}__{}'.format(engine_name, category)
transformed_choices.append(transformed_choice)
self.choices = transformed_choices
def transform_form_items(self, items):
return [item[len('engine_'):].replace('_', ' ').replace(' ', '__') for item in items]
def transform_values(self, values):
if len(values) == 1 and values[0] == '':
return list()
transformed_values = []
for value in values:
engine, category = value.split('__')
transformed_values.append((engine, category))
return transformed_values
class PluginsSetting(SwitchableSetting):
def _post_init(self):
super(PluginsSetting, self)._post_init()
transformed_choices = []
for plugin in self.choices:
transformed_choice = dict()
transformed_choice['default_on'] = plugin.default_on
transformed_choice['id'] = plugin.id
transformed_choices.append(transformed_choice)
self.choices = transformed_choices
def transform_form_items(self, items):
return [item[len('plugin_'):] for item in items]
class Preferences(object):
"""Stores, validates and saves preferences to cookies"""
def __init__(self, themes, categories, engines, plugins):
super(Preferences, self).__init__()
self.key_value_settings = {'categories': MultipleChoiceSetting(['general'], choices=categories),
'language': EnumStringSetting('all', choices=LANGUAGE_CODES),
'locale': EnumStringSetting(settings['ui']['default_locale'],
choices=settings['locales'].keys()),
'autocomplete': EnumStringSetting(settings['search']['autocomplete'],
choices=autocomplete.backends.keys()),
'image_proxy': MapSetting(settings['server']['image_proxy'],
map={'': settings['server']['image_proxy'],
'0': False,
'1': True}),
'method': EnumStringSetting('POST', choices=('GET', 'POST')),
'safesearch': MapSetting(settings['search']['safe_search'], map={'0': 0,
'1': 1,
'2': 2}),
'theme': EnumStringSetting(settings['ui']['default_theme'], choices=themes)}
self.engines = EnginesSetting('engines', choices=engines)
self.plugins = PluginsSetting('plugins', choices=plugins)
def parse_cookies(self, input_data):
for user_setting_name, user_setting in input_data.iteritems():
if user_setting_name in self.key_value_settings:
self.key_value_settings[user_setting_name].parse(user_setting)
elif user_setting_name == 'disabled_engines':
self.engines.parse_cookie((input_data.get('disabled_engines', ''),
input_data.get('enabled_engines', '')))
elif user_setting_name == 'disabled_plugins':
self.plugins.parse_cookie((input_data.get('disabled_plugins', ''),
input_data.get('enabled_plugins', '')))
def parse_form(self, input_data):
disabled_engines = []
enabled_categories = []
disabled_plugins = []
for user_setting_name, user_setting in input_data.iteritems():
if user_setting_name in self.key_value_settings:
self.key_value_settings[user_setting_name].parse(user_setting)
elif user_setting_name.startswith('engine_'):
disabled_engines.append(user_setting_name)
elif user_setting_name.startswith('category_'):
enabled_categories.append(user_setting_name[len('category_'):])
elif user_setting_name.startswith('plugin_'):
disabled_plugins.append(user_setting_name)
self.key_value_settings['categories'].parse_form(enabled_categories)
self.engines.parse_form(disabled_engines)
self.plugins.parse_form(disabled_plugins)
# cannot be used in case of engines or plugins
def get_value(self, user_setting_name):
if user_setting_name in self.key_value_settings:
return self.key_value_settings[user_setting_name].get_value()
def save(self, resp):
for user_setting_name, user_setting in self.key_value_settings.iteritems():
user_setting.save(user_setting_name, resp)
self.engines.save(resp)
self.plugins.save(resp)
return resp

View File

@ -28,12 +28,12 @@ import re
class Query(object):
"""parse query"""
def __init__(self, query, blocked_engines):
def __init__(self, query, disabled_engines):
self.query = query
self.blocked_engines = []
self.disabled_engines = []
if blocked_engines:
self.blocked_engines = blocked_engines
if disabled_engines:
self.disabled_engines = disabled_engines
self.query_parts = []
self.engines = []
@ -107,7 +107,7 @@ class Query(object):
self.engines.extend({'category': prefix,
'name': engine.name}
for engine in categories[prefix]
if (engine.name, prefix) not in self.blocked_engines)
if (engine.name, prefix) not in self.disabled_engines)
if query_part[0] == '!':
self.specific = True

View File

@ -37,7 +37,7 @@ def merge_two_infoboxes(infobox1, infobox2):
urls1 = infobox1.get('urls', None)
if urls1 is None:
urls1 = []
infobox1.set('urls', urls1)
infobox1['urls'] = urls1
urlSet = set()
for url in infobox1.get('urls', []):
@ -47,11 +47,17 @@ def merge_two_infoboxes(infobox1, infobox2):
if url.get('url', None) not in urlSet:
urls1.append(url)
if 'img_src' in infobox2:
img1 = infobox1.get('img_src', None)
img2 = infobox2.get('img_src')
if img1 is None:
infobox1['img_src'] = img2
if 'attributes' in infobox2:
attributes1 = infobox1.get('attributes', None)
if attributes1 is None:
attributes1 = []
infobox1.set('attributes', attributes1)
infobox1['attributes'] = attributes1
attributeSet = set()
for attribute in infobox1.get('attributes', []):
@ -68,7 +74,7 @@ def merge_two_infoboxes(infobox1, infobox2):
if result_content_len(content2) > result_content_len(content1):
infobox1['content'] = content2
else:
infobox1.set('content', content2)
infobox1['content'] = content2
def result_score(result):
@ -116,6 +122,10 @@ class ResultContainer(object):
self.results[engine_name].extend(results)
for i, result in enumerate(results):
try:
result['url'] = result['url'].decode('utf-8')
except:
pass
position = i + 1
self._merge_result(result, position)
@ -138,6 +148,7 @@ class ResultContainer(object):
# if the result has no scheme, use http as default
if not result['parsed_url'].scheme:
result['parsed_url'] = result['parsed_url']._replace(scheme="http")
result['url'] = result['parsed_url'].geturl()
result['host'] = result['parsed_url'].netloc

View File

@ -23,7 +23,7 @@ from searx.engines import (
categories, engines
)
from searx.languages import language_codes
from searx.utils import gen_useragent, get_blocked_engines
from searx.utils import gen_useragent
from searx.query import Query
from searx.results import ResultContainer
from searx import logger
@ -34,16 +34,23 @@ number_of_searches = 0
def search_request_wrapper(fn, url, engine_name, **kwargs):
ret = None
engine = engines[engine_name]
try:
return fn(url, **kwargs)
ret = fn(url, **kwargs)
with threading.RLock():
engine.continuous_errors = 0
engine.suspend_end_time = 0
except:
# increase errors stats
with threading.RLock():
engines[engine_name].stats['errors'] += 1
engine.stats['errors'] += 1
engine.continuous_errors += 1
engine.suspend_end_time = time() + min(60, engine.continuous_errors)
# print engine name and specific error message
logger.exception('engine crash: {0}'.format(engine_name))
return
return ret
def threaded_requests(requests):
@ -133,15 +140,13 @@ class Search(object):
self.lang = 'all'
# set blocked engines
self.blocked_engines = get_blocked_engines(engines, request.cookies)
self.disabled_engines = request.preferences.engines.get_disabled()
self.result_container = ResultContainer()
self.request_data = {}
# set specific language if set
if request.cookies.get('language')\
and request.cookies['language'] in (x[0] for x in language_codes):
self.lang = request.cookies['language']
self.lang = request.preferences.get_value('language')
# set request method
if request.method == 'POST':
@ -162,7 +167,7 @@ class Search(object):
# parse query, if tags are set, which change
# the serch engine or search-language
query_obj = Query(self.request_data['q'], self.blocked_engines)
query_obj = Query(self.request_data['q'], self.disabled_engines)
query_obj.parse_query()
# set query
@ -222,8 +227,7 @@ class Search(object):
# using user-defined default-configuration which
# (is stored in cookie)
if not self.categories:
cookie_categories = request.cookies.get('categories', '')
cookie_categories = cookie_categories.split(',')
cookie_categories = request.preferences.get_value('categories')
for ccateg in cookie_categories:
if ccateg in categories:
self.categories.append(ccateg)
@ -239,7 +243,11 @@ class Search(object):
self.engines.extend({'category': categ,
'name': engine.name}
for engine in categories[categ]
if (engine.name, categ) not in self.blocked_engines)
if (engine.name, categ) not in self.disabled_engines)
# remove suspended engines
self.engines = [e for e in self.engines
if engines[e['name']].suspend_end_time <= time()]
# do search-request
def search(self, request):
@ -283,11 +291,8 @@ class Search(object):
else:
request_params['language'] = self.lang
try:
# 0 = None, 1 = Moderate, 2 = Strict
request_params['safesearch'] = int(request.cookies.get('safesearch'))
except Exception:
request_params['safesearch'] = settings['search']['safe_search']
# 0 = None, 1 = Moderate, 2 = Strict
request_params['safesearch'] = request.preferences.get_value('safesearch')
# update request parameters dependent on
# search-engine (contained in engines folder)

View File

@ -1,5 +1,6 @@
general:
debug : False # Debug mode, only for development
instance_name : "searx" # displayed name
search:
safe_search : 0 # Filter results. 0: None, 1: Moderate, 2: Strict
@ -33,11 +34,18 @@ outgoing: # communication with search engines
# - 1.1.1.2
engines:
- name : arch linux wiki
engine : archlinux
shortcut : al
- name : base
engine : base
shortcut : bs
- name : wikipedia
engine : mediawiki
engine : wikipedia
shortcut : wp
base_url : 'https://{language}.wikipedia.org/'
number_of_results : 1
- name : bing
engine : bing
@ -51,6 +59,18 @@ engines:
engine : bing_news
shortcut : bin
- name : bitbucket
engine : xpath
paging : True
search_url : https://bitbucket.org/repo/all/{pageno}?name={query}
url_xpath : //article[@class="repo-summary"]//a[@class="repo-link"]/@href
title_xpath : //article[@class="repo-summary"]//a[@class="repo-link"]
content_xpath : //article[@class="repo-summary"]/p
categories : it
timeout : 4.0
disabled : True
shortcut : bb
- name : btdigg
engine : btdigg
shortcut : bt
@ -72,11 +92,25 @@ engines:
- name : ddg definitions
engine : duckduckgo_definitions
shortcut : ddd
disabled : True
- name : digg
engine : digg
shortcut : dg
- name : erowid
engine : xpath
paging : True
first_page_num : 0
page_size : 30
search_url : https://www.erowid.org/search.php?q={query}&s={pageno}
url_xpath : //dl[@class="results-list"]/dt[@class="result-title"]/a/@href
title_xpath : //dl[@class="results-list"]/dt[@class="result-title"]/a/text()
content_xpath : //dl[@class="results-list"]/dd[@class="result-details"]
categories : general
shortcut : ew
disabled : True
- name : wikidata
engine : wikidata
shortcut : wd
@ -100,6 +134,11 @@ engines:
shortcut : 1x
disabled : True
- name : fdroid
engine : fdroid
shortcut : fd
disabled : True
- name : flickr
categories : images
shortcut : fl
@ -110,11 +149,28 @@ engines:
# Or you can use the html non-stable engine, activated by default
engine : flickr_noapi
- name : frinkiac
engine : frinkiac
shortcut : frk
disabled : True
- name : gigablast
engine : gigablast
shortcut : gb
disabled: True
- name : gitlab
engine : xpath
paging : True
search_url : https://gitlab.com/search?page={pageno}&search={query}
url_xpath : //li[@class="project-row"]//a[@class="project"]/@href
title_xpath : //li[@class="project-row"]//span[contains(@class, "project-full-name")]
content_xpath : //li[@class="project-row"]//div[@class="description"]/p
categories : it
shortcut : gl
timeout : 5.0
disabled : True
- name : github
engine : github
shortcut : gh
@ -161,10 +217,39 @@ engines:
shortcut : gps
disabled : True
- name : geektimes
engine : xpath
paging : True
search_url : https://geektimes.ru/search/page{pageno}/?q={query}
url_xpath : //div[@class="search_results"]//a[@class="post_title"]/@href
title_xpath : //div[@class="search_results"]//a[@class="post_title"]
content_xpath : //div[@class="search_results"]//div[contains(@class, "content")]
categories : it
timeout : 4.0
disabled : True
shortcut : gt
- name : habrahabr
engine : xpath
paging : True
search_url : https://habrahabr.ru/search/page{pageno}/?q={query}
url_xpath : //div[@class="search_results"]//a[@class="post_title"]/@href
title_xpath : //div[@class="search_results"]//a[@class="post_title"]
content_xpath : //div[@class="search_results"]//div[contains(@class, "content")]
categories : it
timeout : 4.0
disabled : True
shortcut : habr
- name : mixcloud
engine : mixcloud
shortcut : mc
- name : nyaa
engine : nyaa
shortcut : nt
disabled : True
- name : openstreetmap
engine : openstreetmap
shortcut : osm
@ -199,6 +284,13 @@ engines:
shortcut : qws
categories : social media
- name : reddit
engine : reddit
shortcut : re
page_size : 25
timeout : 10.0
disabled : True
- name : kickass
engine : kickass
shortcut : ka
@ -250,6 +342,17 @@ engines:
shortcut : sw
disabled : True
- name : tokyotoshokan
engine : tokyotoshokan
shortcut : tt
timeout : 6.0
disabled : True
- name : torrentz
engine : torrentz
timeout : 5.0
shortcut : to
- name : twitter
engine : twitter
shortcut : tw
@ -300,6 +403,16 @@ engines:
engine : vimeo
shortcut : vm
- name : wolframalpha
shortcut : wa
# You can use the engine using the official stable API, but you need an API key
# See : http://products.wolframalpha.com/api/
# engine : wolframalpha_api
# api_key: '' # required!
engine : wolframalpha_noapi
timeout: 6.0
categories : science
#The blekko technology and team have joined IBM Watson! -> https://blekko.com/
# - name : blekko images
# engine : blekko_images
@ -313,18 +426,29 @@ engines:
# number_of_results : 5
# timeout : 3.0
# Doku engine lets you access to any Doku wiki instance:
# A public one or a privete/corporate one.
# - name : ubuntuwiki
# engine : doku
# shortcut : uw
# base_url : 'http://doc.ubuntu-fr.org'
locales:
en : English
de : Deutsch
he : עברית
hu : Magyar
fr : Français
es : Español
it : Italiano
nl : Nederlands
bg : Български (Bulgarian)
de : Deutsch (German)
el_GR : Ελληνικά (Greek_Greece)
eo : Esperanto (Esperanto)
es : Español (Spanish)
fr : Français (French)
he : עברית (Hebrew)
hu : Magyar (Hungarian)
it : Italiano (Italian)
ja : 日本語 (Japanese)
tr : Türkçe
pt : Português
ru : Russian
ro : Romanian
nl : Nederlands (Dutch)
pt : Português (Portuguese)
pt_BR : Português (Portuguese_Brazil)
ro : Română (Romanian)
ru : Русский (Russian)
tr : Türkçe (Turkish)
zh : 中文 (Chinese)

View File

@ -1,9 +1,10 @@
general:
debug : False
instance_name : "searx_test"
search:
safe_search : 0
autocomplete : 0
autocomplete : ""
server:
port : 11111
@ -25,10 +26,12 @@ engines:
- name : general_dummy
engine : dummy
categories : general
shortcut : gd
- name : dummy_dummy
engine : dummy
categories : dummy
shortcut : dd
locales:
en : English

View File

@ -0,0 +1,3 @@
$(document).ready(function() {
$('.result_header > a').attr('target', '_blank');
});

File diff suppressed because one or more lines are too long

View File

@ -476,6 +476,7 @@ color: @color-font-light;
margin: 0px 2px 5px 5px;
padding: 0px 2px 2px;
max-width: 21em;
word-wrap: break-word;
.infobox {
margin: 10px 0 10px;
@ -485,7 +486,7 @@ color: @color-font-light;
/* box-shadow: 0px 0px 5px #CCC; */
img {
max-width: 20em;
max-width: 90%;
max-heigt: 12em;
display: block;
margin: 5px;
@ -497,7 +498,7 @@ color: @color-font-light;
}
table {
width: auto;
table-layout: fixed;
td {
vertical-align: top;

View File

@ -17,7 +17,7 @@ input[type=checkbox]:not(:checked)+.label_hide_if_not_checked,input[type=checkbo
.result_download{margin-right:5px}
#pagination{margin-top:30px;padding-bottom:50px}
.label-default{color:#aaa;background:#fff}
.infobox .infobox_part{margin-bottom:20px;word-wrap:break-word}
.infobox .infobox_part{margin-bottom:20px;word-wrap:break-word;table-layout:fixed}
.infobox .infobox_part:last-child{margin-bottom:0}
.search_categories{margin:10px 0;text-transform:capitalize}
.cursor-text{cursor:text !important}

View File

@ -1,7 +1,8 @@
.infobox {
.infobox_part {
margin-bottom: 20px;
word-wrap: break-word;
word-wrap: break-word;
table-layout: fixed;
}
.infobox_part:last-child {

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>searx</ShortName>
<ShortName>{{ instance_name }}</ShortName>
<Description>a privacy-respecting, hackable metasearch engine</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image>{{ host }}{{ url_for('static', filename='img/favicon.png') | replace("/", "", 1) }}</Image>
<Image>{{ urljoin(host, url_for('static', filename='img/favicon.png')) }}</Image>
<LongName>searx metasearch</LongName>
{% if opensearch_method == 'get' %}
<Url type="text/html" method="get" template="{{ host }}search?q={searchTerms}"/>

View File

@ -109,7 +109,7 @@
<td>{{ search_engine.name }} ({{ shortcuts[search_engine.name] }})&lrm;</td>
<td>{{ _(categ) }}</td>
<td class="engine_checkbox">
<input type="checkbox" id="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}" name="engine_{{ search_engine.name }}__{{ categ }}"{% if (search_engine.name, categ) in blocked_engines %} checked="checked"{% endif %} />
<input type="checkbox" id="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}" name="engine_{{ search_engine.name }}__{{ categ }}"{% if (search_engine.name, categ) in disabled_engines %} checked="checked"{% endif %} />
<label class="allow" for="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Allow') }}</label>
<label class="deny" for="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Block') }}</label>
</td>

View File

@ -7,7 +7,14 @@
<div class="attributes">
<table>
{% for attribute in infobox.attributes %}
<tr><td>{{ attribute.label }}</td><td>{{ attribute.value }}</td></tr>
<tr>
<td>{{ attribute.label }}</td>
{% if attribute.image %}
<td><img src="{{ image_proxify(attribute.image.src) }}" alt="{{ attribute.image.alt }}" /></td>
{% else %}
<td>{{ attribute.value }}</td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>searx</ShortName>
<ShortName>{{ instance_name }}</ShortName>
<Description>a privacy-respecting, hackable metasearch engine</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image>{{ host }}{{ url_for('static', filename='img/favicon.png') | replace("/", "", 1) }}</Image>
<Image>{{ urljoin(host, url_for('static', filename='img/favicon.png')) }}</Image>
<LongName>searx metasearch</LongName>
{% if opensearch_method == 'get' %}
<Url type="text/html" method="get" template="{{ host }}search?q={searchTerms}"/>

View File

@ -97,7 +97,7 @@
<td>{{ search_engine.name }} ({{ shortcuts[search_engine.name] }})&lrm;</td>
<td>{{ _(categ) }}</td>
<td class="engine_checkbox">
<input type="checkbox" id="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}" name="engine_{{ search_engine.name }}__{{ categ }}"{% if (search_engine.name, categ) in blocked_engines %} checked="checked"{% endif %} />
<input type="checkbox" id="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}" name="engine_{{ search_engine.name }}__{{ categ }}"{% if (search_engine.name, categ) in disabled_engines %} checked="checked"{% endif %} />
<label class="allow" for="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Allow') }}</label>
<label class="deny" for="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Block') }}</label>
</td>

View File

@ -9,7 +9,7 @@
<meta name="referrer" content="no-referrer">
<meta name="viewport" content="width=device-width, initial-scale=1 , maximum-scale=1.0, user-scalable=1" />
{% block meta %}{% endblock %}
<title>{% block title %}{% endblock %}searx</title>
<title>{% block title %}{% endblock %}{{ instance_name }}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}" type="text/css" />
<link rel="stylesheet" href="{{ url_for('static', filename='css/oscar.min.css') }}" type="text/css" />
@ -31,7 +31,7 @@
{% block head %}
{% endblock %}
<link title="searx" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/>
<link title="{{ instance_name }}" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/>
<script type="text/javascript">
searx = {};
@ -75,7 +75,7 @@
<div class="container">
{% block footer %}
{% endblock %}
<p class="text-muted">{{ _('Powered by') }} <a href="https://github.com/asciimoo/searx">searx</a> - {{ searx_version }} - {{ _('a privacy-respecting, hackable metasearch engine') }}</p>
<p class="text-muted">{{ _('Powered by') }} <a href="https://asciimoo.github.io/searx/">searx</a> - {{ searx_version }} - {{ _('a privacy-respecting, hackable metasearch engine') }}</p>
</div>
</div>
<script src="{{ url_for('static', filename='js/jquery-1.11.1.min.js') }}"></script>
@ -86,5 +86,8 @@
{% for script in scripts %}
<script src="{{ url_for('static', filename=script) }}"></script>
{% endfor %}
<script type="text/javascript">
$(function() { $('a[data-toggle="modal"]').attr('href', '#'); });
</script>
</body>
</html>

View File

@ -1,8 +1,9 @@
<div class="panel panel-default infobox">
<div class="panel-heading">
<h4 class="panel-title">{{ infobox.infobox }}</h4>
<bdi><h4 class="panel-title infobox_part">{{ infobox.infobox }}</h4></bdi>
</div>
<div class="panel-body">
<bdi>
{% if infobox.img_src %}<img class="img-responsive center-block infobox_part" src="{{ image_proxify(infobox.img_src) }}" alt="{{ infobox.infobox }}" />{% endif %}
{% if infobox.content %}<p class="infobox_part">{{ infobox.content }}</p>{% endif %}
@ -11,7 +12,11 @@
{% for attribute in infobox.attributes %}
<tr>
<td>{{ attribute.label }}</td>
{% if attribute.image %}
<td><img class="img-responsive" src="{{ image_proxify(attribute.image.src) }}" alt="{{ attribute.image.alt }}" /></td>
{% else %}
<td>{{ attribute.value }}</td>
{% endif %}
</tr>
{% endfor %}
</table>
@ -24,5 +29,6 @@
{% endfor %}
</div>
{% endif %}
</bdi>
</div>
</div>

View File

@ -16,7 +16,7 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{{ url_for('index') }}">searx</a>
<a class="navbar-brand" href="{{ url_for('index') }}">{{ instance_name }}</a>
</div>
{% else %}
<div class="navbar-header">
@ -26,7 +26,7 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{{ url_for('index') }}">searx</a>
<a class="navbar-brand" href="{{ url_for('index') }}">{{ instance_name }}</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right"> <!-- results.html -->

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>searx</ShortName>
<ShortName>{{ instance_name }}</ShortName>
<Description>a privacy-respecting, hackable metasearch engine</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image>{{ host }}{{ url_for('static', filename='img/favicon.png') | replace("/", "", 1) }}</Image>
<Image>{{ urljoin(host, url_for('static', filename='img/favicon.png')) }}</Image>
<LongName>searx metasearch</LongName>
{% if opensearch_method == 'get' %}
<Url type="text/html" method="get" template="{{ host }}search?q={searchTerms}"/>

View File

@ -157,7 +157,7 @@
{% if not search_engine.private %}
<tr>
{% if not rtl %}
<td>{{ checkbox_toggle('engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_'), (search_engine.name, categ) in blocked_engines) }}</td>
<td>{{ checkbox_toggle('engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_'), (search_engine.name, categ) in disabled_engines) }}</td>
<th>{{ search_engine.name }}</th>
<td>{{ shortcuts[search_engine.name] }}</td>
<td><input type="checkbox" {{ "checked" if search_engine.safesearch==True else ""}} readonly="readonly" disabled="disabled"></td>
@ -169,7 +169,7 @@
<td><input type="checkbox" {{ "checked" if search_engine.safesearch==True else ""}} readonly="readonly" disabled="disabled"></td>
<td>{{ shortcuts[search_engine.name] }}</td>
<th>{{ search_engine.name }}</th>
<td>{{ checkbox_toggle('engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_'), (search_engine.name, categ) in blocked_engines) }}</td>
<td>{{ checkbox_toggle('engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_'), (search_engine.name, categ) in disabled_engines) }}</td>
{% endif %}
</tr>
{% endif %}
@ -191,10 +191,10 @@
{% for plugin in plugins %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{ plugin.name }}</h3>
<h3 class="panel-title">{{ _(plugin.name) }}</h3>
</div>
<div class="panel-body">
<div class="col-xs-6 col-sm-4 col-md-6">{{ plugin.description }}</div>
<div class="col-xs-6 col-sm-4 col-md-6">{{ _(plugin.description) }}</div>
<div class="col-xs-6 col-sm-4 col-md-6">
{{ checkbox_toggle('plugin_' + plugin.id, plugin.id not in allowed_plugins) }}
</div>

View File

@ -13,7 +13,16 @@
</div>
{% endif %}
{% if result.img_src %}
<div class="container-fluid">
<div class="row">
<img src="{{ image_proxify(result.img_src) }}" alt="{{ result.title|striptags }}" title="{{ result.title|striptags }}" style="width: auto; max-height: 60px; min-height: 60px;" class="col-xs-2 col-sm-4 col-md-4 result-content">
{% if result.content %}<p class="result-content col-xs-8 col-sm-8 col-md-8">{{ result.content|safe }}</p>{% endif %}
</div>
</div>
{% else %}
{% if result.content %}<p class="result-content">{{ result.content|safe }}</p>{% endif %}
{% endif %}
{% if rtl %}
{{ result_footer_rtl(result) }}

View File

@ -60,7 +60,7 @@
<tr>
<td>{{ search_engine.name }} ({{ shortcuts[search_engine.name] }})&lrm;</td>
<td class="engine_checkbox">
<input type="checkbox" id="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}" name="engine_{{ search_engine.name }}__{{ categ }}"{% if (search_engine.name, categ) in blocked_engines %} checked="checked"{% endif %} />
<input type="checkbox" id="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}" name="engine_{{ search_engine.name }}__{{ categ }}"{% if (search_engine.name, categ) in disabled_engines %} checked="checked"{% endif %} />
<label class="allow" for="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Allow') }}</label>
<label class="deny" for="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Block') }}</label>
</td>

View File

@ -3,6 +3,7 @@
from plone.testing import Layer
from unittest2 import TestCase
from os.path import dirname, join, abspath
import os
@ -42,11 +43,11 @@ class SearxRobotLayer(Layer):
os.path.abspath(os.path.dirname(os.path.realpath(__file__))),
'webapp.py'
)
exe = os.path.abspath(os.path.dirname(__file__) + '/../bin/py')
exe = 'python'
# set robot settings path
os.environ['SEARX_SETTINGS_PATH'] = os.path.abspath(
os.path.dirname(__file__) + '/settings_robot.yml')
os.environ['SEARX_SETTINGS_PATH'] = abspath(
dirname(__file__) + '/settings_robot.yml')
# run the server
self.server = subprocess.Popen(
@ -56,7 +57,7 @@ class SearxRobotLayer(Layer):
)
def tearDown(self):
os.kill(self.server.pid, 15)
os.kill(self.server.pid, 9)
# remove previously set environment variable
del os.environ['SEARX_SETTINGS_PATH']
@ -68,3 +69,20 @@ class SearxTestCase(TestCase):
"""Base test case for non-robot tests."""
layer = SearxTestLayer
if __name__ == '__main__':
from tests.test_robot import test_suite
import sys
from zope.testrunner.runner import Runner
base_dir = abspath(join(dirname(__file__), '../tests'))
if sys.argv[1] == 'robot':
r = Runner(['--color',
'--auto-progress',
'--stop-on-error',
'--path',
base_dir],
found_suites=[test_suite()])
r.run()
sys.exit(int(r.failed))

View File

@ -1,269 +0,0 @@
# -*- coding: utf-8 -*-
from collections import defaultdict
import mock
from searx.engines import bing_images
from searx.testing import SearxTestCase
class TestBingImagesEngine(SearxTestCase):
def test_request(self):
query = 'test_query'
dicto = defaultdict(dict)
dicto['pageno'] = 1
dicto['language'] = 'fr_FR'
dicto['safesearch'] = 1
params = bing_images.request(query, dicto)
self.assertTrue('url' in params)
self.assertTrue(query in params['url'])
self.assertTrue('bing.com' in params['url'])
self.assertTrue('SRCHHPGUSR' in params['cookies'])
self.assertTrue('fr' in params['cookies']['SRCHHPGUSR'])
dicto['language'] = 'all'
params = bing_images.request(query, dicto)
self.assertIn('SRCHHPGUSR', params['cookies'])
self.assertIn('en', params['cookies']['SRCHHPGUSR'])
def test_response(self):
self.assertRaises(AttributeError, bing_images.response, None)
self.assertRaises(AttributeError, bing_images.response, [])
self.assertRaises(AttributeError, bing_images.response, '')
self.assertRaises(AttributeError, bing_images.response, '[]')
response = mock.Mock(text='<html></html>')
self.assertEqual(bing_images.response(response), [])
response = mock.Mock(text='<html></html>')
self.assertEqual(bing_images.response(response), [])
html = """
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
"""
html = html.replace('\r\n', '').replace('\n', '').replace('\r', '')
response = mock.Mock(text=html)
results = bing_images.response(response)
self.assertEqual(type(results), list)
self.assertEqual(len(results), 1)
self.assertEqual(results[0]['title'], 'Test Query')
self.assertEqual(results[0]['url'], 'http://www.page.url/')
self.assertEqual(results[0]['content'], '')
self.assertEqual(results[0]['thumbnail_src'], 'https://www.bing.com/th?id=HN.608003696942779811')
self.assertEqual(results[0]['img_src'], 'http://test.url/Test%20Query.jpg')
html = """
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;59EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,
imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,oh:&quot;238&quot;,
tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
"""
response = mock.Mock(text=html)
results = bing_images.response(response)
self.assertEqual(type(results), list)
self.assertEqual(len(results), 0)
html = """
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px">
<a href="#" ihk="HN.608003696942779811"
m="{ns:&quot;images&quot;,k:&quot;5045&quot;,
mid:&quot;659EB92C317974F34517A1CCAEBEF76A578E08DEE&quot;,
surl:&quot;http://www.page.url/&quot;,imgurl:&quot;http://test.url/Test%20Query.jpg&quot;,
oh:&quot;238&quot;,tft:&quot;0&quot;,oi:&quot;http://www.image.url/Images/Test%20Query.jpg&quot;}"
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&amp;o=4&amp;pid=1.7"
style="height:144px;" width="178" height="144"/>
</a>
</div>
"""
html = html.replace('\r\n', '').replace('\n', '').replace('\r', '')
response = mock.Mock(text=html)
results = bing_images.response(response)
self.assertEqual(type(results), list)
self.assertEqual(len(results), 10)

View File

@ -1,91 +0,0 @@
# -*- coding: utf-8 -*-
from collections import defaultdict
import mock
from searx.engines import duckduckgo
from searx.testing import SearxTestCase
class TestDuckduckgoEngine(SearxTestCase):
def test_request(self):
query = 'test_query'
dicto = defaultdict(dict)
dicto['pageno'] = 1
dicto['language'] = 'fr_FR'
params = duckduckgo.request(query, dicto)
self.assertIn('url', params)
self.assertIn(query, params['url'])
self.assertIn('duckduckgo.com', params['url'])
self.assertIn('fr-fr', params['url'])
dicto['language'] = 'all'
params = duckduckgo.request(query, dicto)
self.assertIn('en-us', params['url'])
def test_response(self):
self.assertRaises(AttributeError, duckduckgo.response, None)
self.assertRaises(AttributeError, duckduckgo.response, [])
self.assertRaises(AttributeError, duckduckgo.response, '')
self.assertRaises(AttributeError, duckduckgo.response, '[]')
response = mock.Mock(text='<html></html>')
self.assertEqual(duckduckgo.response(response), [])
html = u"""
<div class="results_links results_links_deep web-result">
<div class="icon_fav" style="display: block;">
<a rel="nofollow" href="https://www.test.com/">
<img width="16" height="16" alt=""
src="/i/www.test.com.ico" style="visibility: visible;" name="i15" />
</a>
</div>
<div class="links_main links_deep"> <!-- This is the visible part -->
<a rel="nofollow" class="large" href="http://this.should.be.the.link/ű">
This <b>is</b> <b>the</b> title
</a>
<div class="snippet"><b>This</b> should be the content.</div>
<div class="url">
http://this.should.be.the.link/
</div>
</div>
</div>
"""
response = mock.Mock(text=html)
results = duckduckgo.response(response)
self.assertEqual(type(results), list)
self.assertEqual(len(results), 1)
self.assertEqual(results[0]['title'], 'This is the title')
self.assertEqual(results[0]['url'], u'http://this.should.be.the.link/ű')
self.assertEqual(results[0]['content'], 'This should be the content.')
html = """
<div class="results_links results_links_deep web-result">
<div class="icon_fav" style="display: block;">
</div>
<div class="links_main links_deep"> <!-- This is the visible part -->
<div class="snippet"><b>This</b> should be the content.</div>
<div class="url">
http://this.should.be.the.link/
</div>
</div>
</div>
<div class="results_links results_links_deep web-result">
<div class="icon_fav" style="display: block;">
<img width="16" height="16" alt=""
src="/i/www.test.com.ico" style="visibility: visible;" name="i15" />
</div>
<div class="links_main links_deep"> <!-- This is the visible part -->
<a rel="nofollow" class="large" href="">
This <b>is</b> <b>the</b> title
</a>
<div class="snippet"><b>This</b> should be the content.</div>
<div class="url">
http://this.should.be.the.link/
</div>
</div>
</div>
"""
response = mock.Mock(text=html)
results = duckduckgo.response(response)
self.assertEqual(type(results), list)
self.assertEqual(len(results), 0)

View File

@ -1,57 +0,0 @@
from collections import defaultdict
import mock
from searx.engines import gigablast
from searx.testing import SearxTestCase
class TestGigablastEngine(SearxTestCase):
def test_request(self):
query = 'test_query'
dicto = defaultdict(dict)
dicto['pageno'] = 0
params = gigablast.request(query, dicto)
self.assertTrue('url' in params)
self.assertTrue(query in params['url'])
self.assertTrue('gigablast.com' in params['url'])
def test_response(self):
self.assertRaises(AttributeError, gigablast.response, None)
self.assertRaises(AttributeError, gigablast.response, [])
self.assertRaises(AttributeError, gigablast.response, '')
self.assertRaises(AttributeError, gigablast.response, '[]')
response = mock.Mock(content='<response></response>')
self.assertEqual(gigablast.response(response), [])
response = mock.Mock(content='<response></response>')
self.assertEqual(gigablast.response(response), [])
xml = """<?xml version="1.0" encoding="UTF-8" ?>
<response>
<hits>5941888</hits>
<moreResultsFollow>1</moreResultsFollow>
<result>
<title><![CDATA[This should be the title]]></title>
<sum><![CDATA[This should be the content.]]></sum>
<url><![CDATA[http://this.should.be.the.link/]]></url>
<size>90.5</size>
<docId>145414002633</docId>
<siteId>2660021087</siteId>
<domainId>2660021087</domainId>
<spidered>1320519373</spidered>
<indexed>1320519373</indexed>
<pubdate>4294967295</pubdate>
<isModDate>0</isModDate>
<language><![CDATA[English]]></language>
<charset><![CDATA[UTF-8]]></charset>
</result>
</response>
"""
response = mock.Mock(content=xml)
results = gigablast.response(response)
self.assertEqual(type(results), list)
self.assertEqual(len(results), 1)
self.assertEqual(results[0]['title'], 'This should be the title')
self.assertEqual(results[0]['url'], 'http://this.should.be.the.link/')
self.assertEqual(results[0]['content'], 'This should be the content.')

View File

@ -1,44 +0,0 @@
*** Settings ***
Library Selenium2Library timeout=10 implicit_wait=0.5
Test Setup Open Browser http://localhost:11111/
Test Teardown Close All Browsers
*** Test Cases ***
Front page
Page Should Contain about
Page Should Contain preferences
About page
Click Element link=about
Page Should Contain Why use Searx?
Page Should Contain Element link=search engines
Preferences page
Click Element link=preferences
Page Should Contain Preferences
Page Should Contain Default categories
Page Should Contain Currently used search engines
Page Should Contain dummy_dummy
Page Should Contain general_dummy
Switch category
Go To http://localhost:11111/preferences
Page Should Contain Checkbox category_general
Page Should Contain Checkbox category_dummy
Click Element xpath=//*[.="general"]
Click Element xpath=//*[.="dummy"]
Submit Form id=search_form
Location Should Be http://localhost:11111/
Checkbox Should Not Be Selected category_general
Checkbox Should Be Selected category_dummy
Change language
Page Should Contain about
Page Should Contain preferences
Go To http://localhost:11111/preferences
Select From List locale hu
Submit Form id=search_form
Location Should Be http://localhost:11111/
Page Should Contain rólunk
Page Should Contain beállítások

View File

@ -1,45 +0,0 @@
from searx.tests.engines.test_bing import * # noqa
from searx.tests.engines.test_bing_images import * # noqa
from searx.tests.engines.test_bing_news import * # noqa
from searx.tests.engines.test_blekko_images import * # noqa
from searx.tests.engines.test_btdigg import * # noqa
from searx.tests.engines.test_currency_convert import * # noqa
from searx.tests.engines.test_dailymotion import * # noqa
from searx.tests.engines.test_deezer import * # noqa
from searx.tests.engines.test_deviantart import * # noqa
from searx.tests.engines.test_digg import * # noqa
from searx.tests.engines.test_duckduckgo import * # noqa
from searx.tests.engines.test_duckduckgo_definitions import * # noqa
from searx.tests.engines.test_dummy import * # noqa
from searx.tests.engines.test_faroo import * # noqa
from searx.tests.engines.test_flickr import * # noqa
from searx.tests.engines.test_flickr_noapi import * # noqa
from searx.tests.engines.test_gigablast import * # noqa
from searx.tests.engines.test_github import * # noqa
from searx.tests.engines.test_google import * # noqa
from searx.tests.engines.test_google_images import * # noqa
from searx.tests.engines.test_google_news import * # noqa
from searx.tests.engines.test_kickass import * # noqa
from searx.tests.engines.test_mediawiki import * # noqa
from searx.tests.engines.test_mixcloud import * # noqa
from searx.tests.engines.test_openstreetmap import * # noqa
from searx.tests.engines.test_photon import * # noqa
from searx.tests.engines.test_piratebay import * # noqa
from searx.tests.engines.test_qwant import * # noqa
from searx.tests.engines.test_searchcode_code import * # noqa
from searx.tests.engines.test_searchcode_doc import * # noqa
from searx.tests.engines.test_soundcloud import * # noqa
from searx.tests.engines.test_spotify import * # noqa
from searx.tests.engines.test_stackoverflow import * # noqa
from searx.tests.engines.test_startpage import * # noqa
from searx.tests.engines.test_subtitleseeker import * # noqa
from searx.tests.engines.test_swisscows import * # noqa
from searx.tests.engines.test_twitter import * # noqa
from searx.tests.engines.test_vimeo import * # noqa
from searx.tests.engines.test_www1x import * # noqa
from searx.tests.engines.test_www500px import * # noqa
from searx.tests.engines.test_yacy import * # noqa
from searx.tests.engines.test_yahoo import * # noqa
from searx.tests.engines.test_youtube_api import * # noqa
from searx.tests.engines.test_youtube_noapi import * # noqa
from searx.tests.engines.test_yahoo_news import * # noqa

Binary file not shown.

View File

@ -0,0 +1,686 @@
# Translations template for PROJECT.
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
# poke amom <van_ds_ff@mail.bg>, 2015
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-01-21 16:05+0100\n"
"PO-Revision-Date: 2016-01-21 15:06+0000\n"
"Last-Translator: Thomas Pointhuber\n"
"Language-Team: Bulgarian (http://www.transifex.com/asciimoo/searx/language/bg/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.2.0\n"
"Language: bg\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: searx/webapp.py:114
msgid "files"
msgstr "файлове"
#: searx/webapp.py:115
msgid "general"
msgstr "общ"
#: searx/webapp.py:116
msgid "music"
msgstr "музика"
#: searx/webapp.py:117
msgid "social media"
msgstr "социална мрежа"
#: searx/webapp.py:118
msgid "images"
msgstr "изображения"
#: searx/webapp.py:119
msgid "videos"
msgstr "видео"
#: searx/webapp.py:120
msgid "it"
msgstr "ай-ти"
#: searx/webapp.py:121
msgid "news"
msgstr "новини"
#: searx/webapp.py:122
msgid "map"
msgstr "карта"
#: searx/webapp.py:123
msgid "science"
msgstr ""
#: searx/webapp.py:415
msgid "{minutes} minute(s) ago"
msgstr "преди {minutes} минута(минути)"
#: searx/webapp.py:417
msgid "{hours} hour(s), {minutes} minute(s) ago"
msgstr "преди {hours} час(ове), {minutes} минута(минути)"
#: searx/engines/__init__.py:185
msgid "Page loads (sec)"
msgstr "Страницата зарежда (сек)"
#: searx/engines/__init__.py:189
msgid "Number of results"
msgstr "Брой резултати"
#: searx/engines/__init__.py:193
msgid "Scores"
msgstr ""
#: searx/engines/__init__.py:197
msgid "Scores per result"
msgstr ""
#: searx/engines/__init__.py:201
msgid "Errors"
msgstr "Грешки"
#: searx/plugins/https_rewrite.py:29
msgid "Rewrite HTTP links to HTTPS if possible"
msgstr "Поправи HTTP връзки на HTTPS, ако е възможно"
#: searx/plugins/search_on_category_select.py:18
msgid "Search on category select"
msgstr "Търси при избор на категория"
#: searx/plugins/search_on_category_select.py:19
msgid ""
"Perform search immediately if a category selected. Disable to select "
"multiple categories. (JavaScript required)"
msgstr "Търси веднага при избрана категория. Изключи за избор на няколко категории. (Необходим е JavaScript)"
#: searx/plugins/self_info.py:20
msgid ""
"Displays your IP if the query is \"ip\" and your user agent if the query "
"contains \"user agent\"."
msgstr ""
#: searx/plugins/tracker_url_remover.py:26
msgid "Tracker URL remover"
msgstr ""
#: searx/plugins/tracker_url_remover.py:27
msgid "Remove trackers arguments from the returned URL"
msgstr ""
#: searx/templates/courgette/index.html:9
#: searx/templates/courgette/index.html:13
#: searx/templates/courgette/results.html:5
#: searx/templates/default/index.html:8 searx/templates/default/index.html:12
#: searx/templates/oscar/navbar.html:7 searx/templates/oscar/navbar.html:35
#: searx/templates/oscar/preferences.html:3
#: searx/templates/pix-art/index.html:8
msgid "preferences"
msgstr "предпочитания"
#: searx/templates/courgette/index.html:11
#: searx/templates/default/index.html:10 searx/templates/oscar/about.html:3
#: searx/templates/oscar/navbar.html:8 searx/templates/oscar/navbar.html:34
#: searx/templates/pix-art/index.html:7
msgid "about"
msgstr "относно"
#: searx/templates/courgette/preferences.html:5
#: searx/templates/default/preferences.html:5
#: searx/templates/oscar/preferences.html:12
#: searx/templates/pix-art/preferences.html:5
msgid "Preferences"
msgstr "Предпочитания"
#: searx/templates/courgette/preferences.html:9
#: searx/templates/default/preferences.html:9
#: searx/templates/oscar/preferences.html:36
#: searx/templates/oscar/preferences.html:38
msgid "Default categories"
msgstr "Първоначални категории"
#: searx/templates/courgette/preferences.html:13
#: searx/templates/default/preferences.html:14
#: searx/templates/oscar/preferences.html:44
#: searx/templates/pix-art/preferences.html:9
msgid "Search language"
msgstr "Език на търсене"
#: searx/templates/courgette/preferences.html:16
#: searx/templates/default/preferences.html:17
#: searx/templates/oscar/preferences.html:48
#: searx/templates/pix-art/preferences.html:12
msgid "Automatic"
msgstr "Автоматично"
#: searx/templates/courgette/preferences.html:24
#: searx/templates/default/preferences.html:25
#: searx/templates/oscar/preferences.html:55
#: searx/templates/pix-art/preferences.html:20
msgid "Interface language"
msgstr "Език"
#: searx/templates/courgette/preferences.html:34
#: searx/templates/default/preferences.html:35
#: searx/templates/oscar/preferences.html:65
msgid "Autocomplete"
msgstr "Автоматично допълване"
#: searx/templates/courgette/preferences.html:45
#: searx/templates/default/preferences.html:46
#: searx/templates/oscar/preferences.html:76
msgid "Image proxy"
msgstr ""
#: searx/templates/courgette/preferences.html:48
#: searx/templates/default/preferences.html:49
#: searx/templates/oscar/preferences.html:80
msgid "Enabled"
msgstr "Включено"
#: searx/templates/courgette/preferences.html:49
#: searx/templates/default/preferences.html:50
#: searx/templates/oscar/preferences.html:81
msgid "Disabled"
msgstr "Изключено"
#: searx/templates/courgette/preferences.html:54
#: searx/templates/default/preferences.html:55
#: searx/templates/oscar/preferences.html:85
#: searx/templates/pix-art/preferences.html:30
msgid "Method"
msgstr "Метод"
#: searx/templates/courgette/preferences.html:63
#: searx/templates/default/preferences.html:64
#: searx/templates/oscar/preferences.html:94
#: searx/templates/oscar/preferences.html:144
#: searx/templates/oscar/preferences.html:150
msgid "SafeSearch"
msgstr "Безопасно търсене"
#: searx/templates/courgette/preferences.html:66
#: searx/templates/default/preferences.html:67
#: searx/templates/oscar/preferences.html:98
msgid "Strict"
msgstr "Стриктно"
#: searx/templates/courgette/preferences.html:67
#: searx/templates/default/preferences.html:68
#: searx/templates/oscar/preferences.html:99
msgid "Moderate"
msgstr "Умерено"
#: searx/templates/courgette/preferences.html:68
#: searx/templates/default/preferences.html:69
#: searx/templates/oscar/preferences.html:100
msgid "None"
msgstr "Нищо"
#: searx/templates/courgette/preferences.html:73
#: searx/templates/default/preferences.html:74
#: searx/templates/oscar/preferences.html:104
#: searx/templates/pix-art/preferences.html:39
msgid "Themes"
msgstr "Облик"
#: searx/templates/courgette/preferences.html:83
msgid "Color"
msgstr "Цвят"
#: searx/templates/courgette/preferences.html:86
msgid "Blue (default)"
msgstr "Синьо (първоначален)"
#: searx/templates/courgette/preferences.html:87
msgid "Violet"
msgstr "Виолетов"
#: searx/templates/courgette/preferences.html:88
msgid "Green"
msgstr "Зелено"
#: searx/templates/courgette/preferences.html:89
msgid "Cyan"
msgstr "зелено-синьо"
#: searx/templates/courgette/preferences.html:90
msgid "Orange"
msgstr "Оранжево"
#: searx/templates/courgette/preferences.html:91
msgid "Red"
msgstr "Червено"
#: searx/templates/courgette/preferences.html:96
#: searx/templates/default/preferences.html:84
#: searx/templates/pix-art/preferences.html:49
msgid "Currently used search engines"
msgstr "Използвани търсачки в момента "
#: searx/templates/courgette/preferences.html:100
#: searx/templates/default/preferences.html:88
#: searx/templates/oscar/preferences.html:142
#: searx/templates/oscar/preferences.html:152
#: searx/templates/pix-art/preferences.html:53
msgid "Engine name"
msgstr "Име на търсачка"
#: searx/templates/courgette/preferences.html:101
#: searx/templates/default/preferences.html:89
msgid "Category"
msgstr "Категория"
#: searx/templates/courgette/preferences.html:102
#: searx/templates/courgette/preferences.html:113
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:101
#: searx/templates/oscar/macros.html:71
#: searx/templates/oscar/preferences.html:141
#: searx/templates/oscar/preferences.html:153
#: searx/templates/pix-art/preferences.html:54
#: searx/templates/pix-art/preferences.html:64
msgid "Allow"
msgstr "Позволи"
#: searx/templates/courgette/preferences.html:102
#: searx/templates/courgette/preferences.html:114
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:102
#: searx/templates/oscar/macros.html:70
#: searx/templates/pix-art/preferences.html:54
#: searx/templates/pix-art/preferences.html:65
msgid "Block"
msgstr "Забрани"
#: searx/templates/courgette/preferences.html:122
#: searx/templates/default/preferences.html:110
#: searx/templates/oscar/preferences.html:235
#: searx/templates/pix-art/preferences.html:73
msgid ""
"These settings are stored in your cookies, this allows us not to store this "
"data about you."
msgstr "Тези настройки се съхраняват във вашите бисквитки. Това ни позволява да не съхраняваме тази информация за вас."
#: searx/templates/courgette/preferences.html:124
#: searx/templates/default/preferences.html:112
#: searx/templates/oscar/preferences.html:237
#: searx/templates/pix-art/preferences.html:75
msgid ""
"These cookies serve your sole convenience, we don't use these cookies to "
"track you."
msgstr "Тези бисквитки служат за ваше удобство. Ние не ги използваме, за да Ви следим."
#: searx/templates/courgette/preferences.html:127
#: searx/templates/default/preferences.html:115
#: searx/templates/oscar/preferences.html:240
#: searx/templates/pix-art/preferences.html:78
msgid "save"
msgstr "запази"
#: searx/templates/courgette/preferences.html:128
#: searx/templates/default/preferences.html:116
#: searx/templates/oscar/preferences.html:242
msgid "Reset defaults"
msgstr "Върни първоначалните"
#: searx/templates/courgette/preferences.html:129
#: searx/templates/default/preferences.html:117
#: searx/templates/oscar/preferences.html:241
#: searx/templates/pix-art/preferences.html:79
msgid "back"
msgstr "назад"
#: searx/templates/courgette/results.html:12
#: searx/templates/default/results.html:13
#: searx/templates/oscar/results.html:110
msgid "Search URL"
msgstr "Търси URL"
#: searx/templates/courgette/results.html:16
#: searx/templates/default/results.html:17
#: searx/templates/oscar/results.html:115
msgid "Download results"
msgstr "Свали резултатите"
#: searx/templates/courgette/results.html:34
#: searx/templates/default/results.html:35
msgid "Answers"
msgstr "Отговори"
#: searx/templates/courgette/results.html:42
#: searx/templates/default/results.html:43
#: searx/templates/oscar/results.html:90
msgid "Suggestions"
msgstr "Предложения"
#: searx/templates/courgette/results.html:70
#: searx/templates/default/results.html:81
#: searx/templates/oscar/results.html:51 searx/templates/oscar/results.html:63
msgid "previous page"
msgstr "предишна страница"
#: searx/templates/courgette/results.html:81
#: searx/templates/default/results.html:92
#: searx/templates/oscar/results.html:44 searx/templates/oscar/results.html:71
msgid "next page"
msgstr "следваща страница"
#: searx/templates/courgette/search.html:3
#: searx/templates/default/search.html:3 searx/templates/oscar/search.html:4
#: searx/templates/oscar/search_full.html:9
#: searx/templates/pix-art/search.html:3
msgid "Search for..."
msgstr "Търси за..."
#: searx/templates/courgette/stats.html:4 searx/templates/default/stats.html:4
#: searx/templates/oscar/stats.html:5 searx/templates/pix-art/stats.html:4
msgid "Engine stats"
msgstr "Статистика на търсачката"
#: searx/templates/courgette/result_templates/images.html:4
#: searx/templates/default/result_templates/images.html:4
#: searx/templates/pix-art/result_templates/images.html:4
msgid "original context"
msgstr "оригинален контекст"
#: searx/templates/courgette/result_templates/torrent.html:7
#: searx/templates/default/result_templates/torrent.html:11
#: searx/templates/oscar/result_templates/torrent.html:6
msgid "Seeder"
msgstr "Сийдър"
#: searx/templates/courgette/result_templates/torrent.html:7
#: searx/templates/default/result_templates/torrent.html:11
#: searx/templates/oscar/result_templates/torrent.html:6
msgid "Leecher"
msgstr "Лийчър"
#: searx/templates/courgette/result_templates/torrent.html:9
#: searx/templates/default/result_templates/torrent.html:9
#: searx/templates/oscar/macros.html:21
msgid "magnet link"
msgstr "магнитна връзка"
#: searx/templates/courgette/result_templates/torrent.html:10
#: searx/templates/default/result_templates/torrent.html:10
#: searx/templates/oscar/macros.html:22
msgid "torrent file"
msgstr "торент файл"
#: searx/templates/default/categories.html:8
msgid "Click on the magnifier to perform search"
msgstr "Кликнете лупичката, за да изпълните търсене"
#: searx/templates/default/result_templates/code.html:3
#: searx/templates/default/result_templates/default.html:3
#: searx/templates/default/result_templates/map.html:9
#: searx/templates/oscar/macros.html:20
msgid "cached"
msgstr "кеширана"
#: searx/templates/oscar/base.html:78
msgid "Powered by"
msgstr ""
#: searx/templates/oscar/base.html:78
msgid "a privacy-respecting, hackable metasearch engine"
msgstr ""
#: searx/templates/oscar/navbar.html:9 searx/templates/oscar/navbar.html:33
msgid "home"
msgstr "начало"
#: searx/templates/oscar/navbar.html:14 searx/templates/oscar/navbar.html:24
msgid "Toggle navigation"
msgstr ""
#: searx/templates/oscar/preferences.html:17
#: searx/templates/oscar/preferences.html:25
msgid "General"
msgstr "Общи"
#: searx/templates/oscar/preferences.html:18
#: searx/templates/oscar/preferences.html:126
msgid "Engines"
msgstr "Търсачки"
#: searx/templates/oscar/preferences.html:19
#: searx/templates/oscar/preferences.html:187
msgid "Plugins"
msgstr "Добавки"
#: searx/templates/oscar/preferences.html:20
#: searx/templates/oscar/preferences.html:210
msgid "Cookies"
msgstr "Бисквитки"
#: searx/templates/oscar/preferences.html:45
msgid "What language do you prefer for search?"
msgstr "Кой език предпочитате за търсене?"
#: searx/templates/oscar/preferences.html:56
msgid "Change the language of the layout"
msgstr "Промени езика на оформлението"
#: searx/templates/oscar/preferences.html:66
msgid "Find stuff as you type"
msgstr "Намери докато пишеш"
#: searx/templates/oscar/preferences.html:77
msgid "Proxying image results through searx"
msgstr ""
#: searx/templates/oscar/preferences.html:86
msgid ""
"Change how forms are submited, <a "
"href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\""
" rel=\"external\">learn more about request methods</a>"
msgstr ""
#: searx/templates/oscar/preferences.html:95
msgid "Filter content"
msgstr "Филтрирай съдържание"
#: searx/templates/oscar/preferences.html:105
msgid "Change searx layout"
msgstr "Промени оформлението на searx"
#: searx/templates/oscar/preferences.html:143
#: searx/templates/oscar/preferences.html:151
msgid "Shortcut"
msgstr "Пряк път"
#: searx/templates/oscar/preferences.html:145
#: searx/templates/oscar/preferences.html:149
msgid "Avg. time"
msgstr "Средно време"
#: searx/templates/oscar/preferences.html:146
#: searx/templates/oscar/preferences.html:148
msgid "Max time"
msgstr "Макс. време"
#: searx/templates/oscar/preferences.html:213
msgid ""
"This is the list of cookies and their values searx is storing on your "
"computer."
msgstr "Това е списък на бисквитки с техните стойности, които searx съхранява на вашия компютър."
#: searx/templates/oscar/preferences.html:214
msgid "With that list, you can assess searx transparency."
msgstr ""
#: searx/templates/oscar/preferences.html:219
msgid "Cookie name"
msgstr "Име на бисквитката"
#: searx/templates/oscar/preferences.html:220
msgid "Value"
msgstr "Стойност"
#: searx/templates/oscar/results.html:7
msgid "Search results"
msgstr "Резултати от търсенето"
#: searx/templates/oscar/results.html:105
msgid "Links"
msgstr "Връзки"
#: searx/templates/oscar/search.html:6
#: searx/templates/oscar/search_full.html:11
msgid "Start search"
msgstr "Започни търсене"
#: searx/templates/oscar/search_full.html:15
msgid "Show search filters"
msgstr "Покажи филтрите за търсене"
#: searx/templates/oscar/search_full.html:15
msgid "Hide search filters"
msgstr "Скрий филтрите за търсене"
#: searx/templates/oscar/stats.html:2
msgid "stats"
msgstr "статистики"
#: searx/templates/oscar/messages/first_time.html:4
#: searx/templates/oscar/messages/no_results.html:5
#: searx/templates/oscar/messages/save_settings_successfull.html:5
#: searx/templates/oscar/messages/unknow_error.html:5
msgid "Close"
msgstr "Затвори"
#: searx/templates/oscar/messages/first_time.html:6
#: searx/templates/oscar/messages/no_data_available.html:3
msgid "Heads up!"
msgstr "Внимание!"
#: searx/templates/oscar/messages/first_time.html:7
msgid "It look like you are using searx first time."
msgstr "Изглежда използвате searx за първи път."
#: searx/templates/oscar/messages/js_disabled.html:2
msgid "Warning!"
msgstr "Внимание!"
#: searx/templates/oscar/messages/js_disabled.html:3
msgid "Please enable JavaScript to use full functionality of this site."
msgstr "Моля включете JavaScript, за пълна използваемост на този сайт."
#: searx/templates/oscar/messages/no_cookies.html:3
msgid "Information!"
msgstr "Информация!"
#: searx/templates/oscar/messages/no_cookies.html:4
msgid "currently, there are no cookies defined."
msgstr "В момента няма налични бисквитки."
#: searx/templates/oscar/messages/no_data_available.html:4
msgid "There is currently no data available. "
msgstr "Няма налична достъпна информация."
#: searx/templates/oscar/messages/no_results.html:7
msgid "Sorry!"
msgstr "Съжалявам!"
#: searx/templates/oscar/messages/no_results.html:8
msgid ""
"we didn't find any results. Please use another query or search in more "
"categories."
msgstr "не намерихме резултати. Моля пробвайте други ключови думи или търсете в повече категории."
#: searx/templates/oscar/messages/save_settings_successfull.html:7
msgid "Well done!"
msgstr "Браво!"
#: searx/templates/oscar/messages/save_settings_successfull.html:8
msgid "Settings saved successfully."
msgstr "Настройките са успешно запазени."
#: searx/templates/oscar/messages/unknow_error.html:7
msgid "Oh snap!"
msgstr "Да му се не види!"
#: searx/templates/oscar/messages/unknow_error.html:8
msgid "Something went wrong."
msgstr "Нещо се обърка."
#: searx/templates/oscar/result_templates/default.html:7
msgid "show media"
msgstr "покажи медия"
#: searx/templates/oscar/result_templates/default.html:7
msgid "hide media"
msgstr "скрий медия"
#: searx/templates/oscar/result_templates/images.html:23
msgid "Get image"
msgstr "Вземи изображение"
#: searx/templates/oscar/result_templates/images.html:24
msgid "View source"
msgstr "Покажи източник"
#: searx/templates/oscar/result_templates/map.html:7
msgid "show map"
msgstr "покажи карта"
#: searx/templates/oscar/result_templates/map.html:7
msgid "hide map"
msgstr "скрий картата"
#: searx/templates/oscar/result_templates/map.html:11
msgid "show details"
msgstr "покажи детайлите"
#: searx/templates/oscar/result_templates/map.html:11
msgid "hide details"
msgstr "скрий детайлите"
#: searx/templates/oscar/result_templates/torrent.html:7
msgid "Filesize"
msgstr "Размер на файла"
#: searx/templates/oscar/result_templates/torrent.html:9
msgid "Bytes"
msgstr "Байта"
#: searx/templates/oscar/result_templates/torrent.html:10
msgid "kiB"
msgstr "килобайт"
#: searx/templates/oscar/result_templates/torrent.html:11
msgid "MiB"
msgstr "мегабайт"
#: searx/templates/oscar/result_templates/torrent.html:12
msgid "GiB"
msgstr "гигабайт"
#: searx/templates/oscar/result_templates/torrent.html:13
msgid "TiB"
msgstr "терабайт"
#: searx/templates/oscar/result_templates/torrent.html:15
msgid "Number of Files"
msgstr "Брой на Файлове"
#: searx/templates/oscar/result_templates/videos.html:7
msgid "show video"
msgstr "покажи видео"
#: searx/templates/oscar/result_templates/videos.html:7
msgid "hide video"
msgstr "скрий видеото"
#: searx/templates/pix-art/results.html:28
msgid "Load more..."
msgstr "Зареди още..."

View File

@ -1,27 +1,28 @@
# Translations template for PROJECT.
# Copyright (C) 2015 ORGANIZATION
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
# pointhi, 2014-2015
# Thomas Pointhuber, 2014-2015
# Max <theshirinzu@gmail.com>, 2015
# pointhi, 2014
# rike, 2014
# stf <stefan.marsiske@gmail.com>, 2014
# stf <stefan.marsiske@gmail.com>, 2014
# Thomas Pointhuber, 2016
# rike, 2014
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2015-08-24 11:44+0200\n"
"PO-Revision-Date: 2015-08-24 10:00+0000\n"
"Last-Translator: pointhi\n"
"POT-Creation-Date: 2016-01-21 16:05+0100\n"
"PO-Revision-Date: 2016-01-21 15:07+0000\n"
"Last-Translator: Thomas Pointhuber\n"
"Language-Team: German (http://www.transifex.com/asciimoo/searx/language/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"
"Generated-By: Babel 2.2.0\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@ -61,11 +62,15 @@ msgstr "Neuigkeiten"
msgid "map"
msgstr "Karte"
#: searx/webapp.py:414
#: searx/webapp.py:123
msgid "science"
msgstr "Wissenschaft"
#: searx/webapp.py:415
msgid "{minutes} minute(s) ago"
msgstr "vor {minutes} Minute(n)"
#: searx/webapp.py:416
#: searx/webapp.py:417
msgid "{hours} hour(s), {minutes} minute(s) ago"
msgstr "vor {hours} Stunde(n), {minutes} Minute(n)"
@ -284,7 +289,7 @@ msgstr "Kategorie"
#: searx/templates/courgette/preferences.html:113
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:101
#: searx/templates/oscar/macros.html:67
#: searx/templates/oscar/macros.html:71
#: searx/templates/oscar/preferences.html:141
#: searx/templates/oscar/preferences.html:153
#: searx/templates/pix-art/preferences.html:54
@ -296,7 +301,7 @@ msgstr "Erlauben"
#: searx/templates/courgette/preferences.html:114
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:102
#: searx/templates/oscar/macros.html:66
#: searx/templates/oscar/macros.html:70
#: searx/templates/pix-art/preferences.html:54
#: searx/templates/pix-art/preferences.html:65
msgid "Block"

View File

@ -0,0 +1,686 @@
# Translations template for PROJECT.
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
# Dimitris T. <dimitris@stinpriza.org>, 2015
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-01-21 16:05+0100\n"
"PO-Revision-Date: 2016-01-21 15:06+0000\n"
"Last-Translator: Thomas Pointhuber\n"
"Language-Team: Greek (Greece) (http://www.transifex.com/asciimoo/searx/language/el_GR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.2.0\n"
"Language: el_GR\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: searx/webapp.py:114
msgid "files"
msgstr "αρχεία"
#: searx/webapp.py:115
msgid "general"
msgstr "γενικά"
#: searx/webapp.py:116
msgid "music"
msgstr "μουσική"
#: searx/webapp.py:117
msgid "social media"
msgstr "κοινωνικά δίκτυα"
#: searx/webapp.py:118
msgid "images"
msgstr "εικόνες"
#: searx/webapp.py:119
msgid "videos"
msgstr ""
#: searx/webapp.py:120
msgid "it"
msgstr ""
#: searx/webapp.py:121
msgid "news"
msgstr "νέα"
#: searx/webapp.py:122
msgid "map"
msgstr "χάρτης"
#: searx/webapp.py:123
msgid "science"
msgstr ""
#: searx/webapp.py:415
msgid "{minutes} minute(s) ago"
msgstr ""
#: searx/webapp.py:417
msgid "{hours} hour(s), {minutes} minute(s) ago"
msgstr ""
#: searx/engines/__init__.py:185
msgid "Page loads (sec)"
msgstr ""
#: searx/engines/__init__.py:189
msgid "Number of results"
msgstr "Αριθμός αποτελεσμάτων"
#: searx/engines/__init__.py:193
msgid "Scores"
msgstr ""
#: searx/engines/__init__.py:197
msgid "Scores per result"
msgstr ""
#: searx/engines/__init__.py:201
msgid "Errors"
msgstr "Λάθη"
#: searx/plugins/https_rewrite.py:29
msgid "Rewrite HTTP links to HTTPS if possible"
msgstr ""
#: searx/plugins/search_on_category_select.py:18
msgid "Search on category select"
msgstr ""
#: searx/plugins/search_on_category_select.py:19
msgid ""
"Perform search immediately if a category selected. Disable to select "
"multiple categories. (JavaScript required)"
msgstr ""
#: searx/plugins/self_info.py:20
msgid ""
"Displays your IP if the query is \"ip\" and your user agent if the query "
"contains \"user agent\"."
msgstr ""
#: searx/plugins/tracker_url_remover.py:26
msgid "Tracker URL remover"
msgstr ""
#: searx/plugins/tracker_url_remover.py:27
msgid "Remove trackers arguments from the returned URL"
msgstr ""
#: searx/templates/courgette/index.html:9
#: searx/templates/courgette/index.html:13
#: searx/templates/courgette/results.html:5
#: searx/templates/default/index.html:8 searx/templates/default/index.html:12
#: searx/templates/oscar/navbar.html:7 searx/templates/oscar/navbar.html:35
#: searx/templates/oscar/preferences.html:3
#: searx/templates/pix-art/index.html:8
msgid "preferences"
msgstr "προτιμήσεις"
#: searx/templates/courgette/index.html:11
#: searx/templates/default/index.html:10 searx/templates/oscar/about.html:3
#: searx/templates/oscar/navbar.html:8 searx/templates/oscar/navbar.html:34
#: searx/templates/pix-art/index.html:7
msgid "about"
msgstr "σχετικά"
#: searx/templates/courgette/preferences.html:5
#: searx/templates/default/preferences.html:5
#: searx/templates/oscar/preferences.html:12
#: searx/templates/pix-art/preferences.html:5
msgid "Preferences"
msgstr "Προτιμήσεις"
#: searx/templates/courgette/preferences.html:9
#: searx/templates/default/preferences.html:9
#: searx/templates/oscar/preferences.html:36
#: searx/templates/oscar/preferences.html:38
msgid "Default categories"
msgstr ""
#: searx/templates/courgette/preferences.html:13
#: searx/templates/default/preferences.html:14
#: searx/templates/oscar/preferences.html:44
#: searx/templates/pix-art/preferences.html:9
msgid "Search language"
msgstr "Γλώσσα αναζήτησης"
#: searx/templates/courgette/preferences.html:16
#: searx/templates/default/preferences.html:17
#: searx/templates/oscar/preferences.html:48
#: searx/templates/pix-art/preferences.html:12
msgid "Automatic"
msgstr "Αυτόματα"
#: searx/templates/courgette/preferences.html:24
#: searx/templates/default/preferences.html:25
#: searx/templates/oscar/preferences.html:55
#: searx/templates/pix-art/preferences.html:20
msgid "Interface language"
msgstr ""
#: searx/templates/courgette/preferences.html:34
#: searx/templates/default/preferences.html:35
#: searx/templates/oscar/preferences.html:65
msgid "Autocomplete"
msgstr ""
#: searx/templates/courgette/preferences.html:45
#: searx/templates/default/preferences.html:46
#: searx/templates/oscar/preferences.html:76
msgid "Image proxy"
msgstr ""
#: searx/templates/courgette/preferences.html:48
#: searx/templates/default/preferences.html:49
#: searx/templates/oscar/preferences.html:80
msgid "Enabled"
msgstr "Ενεργοποιημένο"
#: searx/templates/courgette/preferences.html:49
#: searx/templates/default/preferences.html:50
#: searx/templates/oscar/preferences.html:81
msgid "Disabled"
msgstr "Απενεργοποιημένο"
#: searx/templates/courgette/preferences.html:54
#: searx/templates/default/preferences.html:55
#: searx/templates/oscar/preferences.html:85
#: searx/templates/pix-art/preferences.html:30
msgid "Method"
msgstr "Μέθοδος"
#: searx/templates/courgette/preferences.html:63
#: searx/templates/default/preferences.html:64
#: searx/templates/oscar/preferences.html:94
#: searx/templates/oscar/preferences.html:144
#: searx/templates/oscar/preferences.html:150
msgid "SafeSearch"
msgstr ""
#: searx/templates/courgette/preferences.html:66
#: searx/templates/default/preferences.html:67
#: searx/templates/oscar/preferences.html:98
msgid "Strict"
msgstr ""
#: searx/templates/courgette/preferences.html:67
#: searx/templates/default/preferences.html:68
#: searx/templates/oscar/preferences.html:99
msgid "Moderate"
msgstr ""
#: searx/templates/courgette/preferences.html:68
#: searx/templates/default/preferences.html:69
#: searx/templates/oscar/preferences.html:100
msgid "None"
msgstr ""
#: searx/templates/courgette/preferences.html:73
#: searx/templates/default/preferences.html:74
#: searx/templates/oscar/preferences.html:104
#: searx/templates/pix-art/preferences.html:39
msgid "Themes"
msgstr "Θέματα"
#: searx/templates/courgette/preferences.html:83
msgid "Color"
msgstr "Χρώμα"
#: searx/templates/courgette/preferences.html:86
msgid "Blue (default)"
msgstr "Μπλε (προεπιλεγμένο)"
#: searx/templates/courgette/preferences.html:87
msgid "Violet"
msgstr "Βιολετί"
#: searx/templates/courgette/preferences.html:88
msgid "Green"
msgstr "Πράσινο"
#: searx/templates/courgette/preferences.html:89
msgid "Cyan"
msgstr "Κυανό"
#: searx/templates/courgette/preferences.html:90
msgid "Orange"
msgstr "Πορτοκαλί"
#: searx/templates/courgette/preferences.html:91
msgid "Red"
msgstr "Κόκκινο"
#: searx/templates/courgette/preferences.html:96
#: searx/templates/default/preferences.html:84
#: searx/templates/pix-art/preferences.html:49
msgid "Currently used search engines"
msgstr ""
#: searx/templates/courgette/preferences.html:100
#: searx/templates/default/preferences.html:88
#: searx/templates/oscar/preferences.html:142
#: searx/templates/oscar/preferences.html:152
#: searx/templates/pix-art/preferences.html:53
msgid "Engine name"
msgstr ""
#: searx/templates/courgette/preferences.html:101
#: searx/templates/default/preferences.html:89
msgid "Category"
msgstr "Κατηγορία"
#: searx/templates/courgette/preferences.html:102
#: searx/templates/courgette/preferences.html:113
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:101
#: searx/templates/oscar/macros.html:71
#: searx/templates/oscar/preferences.html:141
#: searx/templates/oscar/preferences.html:153
#: searx/templates/pix-art/preferences.html:54
#: searx/templates/pix-art/preferences.html:64
msgid "Allow"
msgstr ""
#: searx/templates/courgette/preferences.html:102
#: searx/templates/courgette/preferences.html:114
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:102
#: searx/templates/oscar/macros.html:70
#: searx/templates/pix-art/preferences.html:54
#: searx/templates/pix-art/preferences.html:65
msgid "Block"
msgstr ""
#: searx/templates/courgette/preferences.html:122
#: searx/templates/default/preferences.html:110
#: searx/templates/oscar/preferences.html:235
#: searx/templates/pix-art/preferences.html:73
msgid ""
"These settings are stored in your cookies, this allows us not to store this "
"data about you."
msgstr ""
#: searx/templates/courgette/preferences.html:124
#: searx/templates/default/preferences.html:112
#: searx/templates/oscar/preferences.html:237
#: searx/templates/pix-art/preferences.html:75
msgid ""
"These cookies serve your sole convenience, we don't use these cookies to "
"track you."
msgstr ""
#: searx/templates/courgette/preferences.html:127
#: searx/templates/default/preferences.html:115
#: searx/templates/oscar/preferences.html:240
#: searx/templates/pix-art/preferences.html:78
msgid "save"
msgstr "αποθήκευση"
#: searx/templates/courgette/preferences.html:128
#: searx/templates/default/preferences.html:116
#: searx/templates/oscar/preferences.html:242
msgid "Reset defaults"
msgstr ""
#: searx/templates/courgette/preferences.html:129
#: searx/templates/default/preferences.html:117
#: searx/templates/oscar/preferences.html:241
#: searx/templates/pix-art/preferences.html:79
msgid "back"
msgstr "πίσω"
#: searx/templates/courgette/results.html:12
#: searx/templates/default/results.html:13
#: searx/templates/oscar/results.html:110
msgid "Search URL"
msgstr ""
#: searx/templates/courgette/results.html:16
#: searx/templates/default/results.html:17
#: searx/templates/oscar/results.html:115
msgid "Download results"
msgstr ""
#: searx/templates/courgette/results.html:34
#: searx/templates/default/results.html:35
msgid "Answers"
msgstr "Απαντήσεις"
#: searx/templates/courgette/results.html:42
#: searx/templates/default/results.html:43
#: searx/templates/oscar/results.html:90
msgid "Suggestions"
msgstr "Προτάσεις"
#: searx/templates/courgette/results.html:70
#: searx/templates/default/results.html:81
#: searx/templates/oscar/results.html:51 searx/templates/oscar/results.html:63
msgid "previous page"
msgstr "προηγούμενη σελίδα"
#: searx/templates/courgette/results.html:81
#: searx/templates/default/results.html:92
#: searx/templates/oscar/results.html:44 searx/templates/oscar/results.html:71
msgid "next page"
msgstr "επόμενη σελίδα"
#: searx/templates/courgette/search.html:3
#: searx/templates/default/search.html:3 searx/templates/oscar/search.html:4
#: searx/templates/oscar/search_full.html:9
#: searx/templates/pix-art/search.html:3
msgid "Search for..."
msgstr "Αναζήτηση για..."
#: searx/templates/courgette/stats.html:4 searx/templates/default/stats.html:4
#: searx/templates/oscar/stats.html:5 searx/templates/pix-art/stats.html:4
msgid "Engine stats"
msgstr ""
#: searx/templates/courgette/result_templates/images.html:4
#: searx/templates/default/result_templates/images.html:4
#: searx/templates/pix-art/result_templates/images.html:4
msgid "original context"
msgstr ""
#: searx/templates/courgette/result_templates/torrent.html:7
#: searx/templates/default/result_templates/torrent.html:11
#: searx/templates/oscar/result_templates/torrent.html:6
msgid "Seeder"
msgstr ""
#: searx/templates/courgette/result_templates/torrent.html:7
#: searx/templates/default/result_templates/torrent.html:11
#: searx/templates/oscar/result_templates/torrent.html:6
msgid "Leecher"
msgstr ""
#: searx/templates/courgette/result_templates/torrent.html:9
#: searx/templates/default/result_templates/torrent.html:9
#: searx/templates/oscar/macros.html:21
msgid "magnet link"
msgstr ""
#: searx/templates/courgette/result_templates/torrent.html:10
#: searx/templates/default/result_templates/torrent.html:10
#: searx/templates/oscar/macros.html:22
msgid "torrent file"
msgstr ""
#: searx/templates/default/categories.html:8
msgid "Click on the magnifier to perform search"
msgstr ""
#: searx/templates/default/result_templates/code.html:3
#: searx/templates/default/result_templates/default.html:3
#: searx/templates/default/result_templates/map.html:9
#: searx/templates/oscar/macros.html:20
msgid "cached"
msgstr ""
#: searx/templates/oscar/base.html:78
msgid "Powered by"
msgstr ""
#: searx/templates/oscar/base.html:78
msgid "a privacy-respecting, hackable metasearch engine"
msgstr ""
#: searx/templates/oscar/navbar.html:9 searx/templates/oscar/navbar.html:33
msgid "home"
msgstr ""
#: searx/templates/oscar/navbar.html:14 searx/templates/oscar/navbar.html:24
msgid "Toggle navigation"
msgstr ""
#: searx/templates/oscar/preferences.html:17
#: searx/templates/oscar/preferences.html:25
msgid "General"
msgstr ""
#: searx/templates/oscar/preferences.html:18
#: searx/templates/oscar/preferences.html:126
msgid "Engines"
msgstr ""
#: searx/templates/oscar/preferences.html:19
#: searx/templates/oscar/preferences.html:187
msgid "Plugins"
msgstr ""
#: searx/templates/oscar/preferences.html:20
#: searx/templates/oscar/preferences.html:210
msgid "Cookies"
msgstr ""
#: searx/templates/oscar/preferences.html:45
msgid "What language do you prefer for search?"
msgstr "Τι γλώσσα προτιμάτε για αναζήτηση;"
#: searx/templates/oscar/preferences.html:56
msgid "Change the language of the layout"
msgstr ""
#: searx/templates/oscar/preferences.html:66
msgid "Find stuff as you type"
msgstr ""
#: searx/templates/oscar/preferences.html:77
msgid "Proxying image results through searx"
msgstr ""
#: searx/templates/oscar/preferences.html:86
msgid ""
"Change how forms are submited, <a "
"href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\""
" rel=\"external\">learn more about request methods</a>"
msgstr ""
#: searx/templates/oscar/preferences.html:95
msgid "Filter content"
msgstr ""
#: searx/templates/oscar/preferences.html:105
msgid "Change searx layout"
msgstr ""
#: searx/templates/oscar/preferences.html:143
#: searx/templates/oscar/preferences.html:151
msgid "Shortcut"
msgstr ""
#: searx/templates/oscar/preferences.html:145
#: searx/templates/oscar/preferences.html:149
msgid "Avg. time"
msgstr ""
#: searx/templates/oscar/preferences.html:146
#: searx/templates/oscar/preferences.html:148
msgid "Max time"
msgstr ""
#: searx/templates/oscar/preferences.html:213
msgid ""
"This is the list of cookies and their values searx is storing on your "
"computer."
msgstr ""
#: searx/templates/oscar/preferences.html:214
msgid "With that list, you can assess searx transparency."
msgstr ""
#: searx/templates/oscar/preferences.html:219
msgid "Cookie name"
msgstr ""
#: searx/templates/oscar/preferences.html:220
msgid "Value"
msgstr ""
#: searx/templates/oscar/results.html:7
msgid "Search results"
msgstr "Αποτελέσματα αναζήτησης"
#: searx/templates/oscar/results.html:105
msgid "Links"
msgstr "Σύνδεσμοι"
#: searx/templates/oscar/search.html:6
#: searx/templates/oscar/search_full.html:11
msgid "Start search"
msgstr "Έναρξη αναζήτησης"
#: searx/templates/oscar/search_full.html:15
msgid "Show search filters"
msgstr "Προβολή φίλτρων αναζήτησης"
#: searx/templates/oscar/search_full.html:15
msgid "Hide search filters"
msgstr "Απόκρυψη φίλτρων αναζήτησης"
#: searx/templates/oscar/stats.html:2
msgid "stats"
msgstr "στατιστικά"
#: searx/templates/oscar/messages/first_time.html:4
#: searx/templates/oscar/messages/no_results.html:5
#: searx/templates/oscar/messages/save_settings_successfull.html:5
#: searx/templates/oscar/messages/unknow_error.html:5
msgid "Close"
msgstr ""
#: searx/templates/oscar/messages/first_time.html:6
#: searx/templates/oscar/messages/no_data_available.html:3
msgid "Heads up!"
msgstr ""
#: searx/templates/oscar/messages/first_time.html:7
msgid "It look like you are using searx first time."
msgstr ""
#: searx/templates/oscar/messages/js_disabled.html:2
msgid "Warning!"
msgstr "Προειδοποίηση!"
#: searx/templates/oscar/messages/js_disabled.html:3
msgid "Please enable JavaScript to use full functionality of this site."
msgstr ""
#: searx/templates/oscar/messages/no_cookies.html:3
msgid "Information!"
msgstr ""
#: searx/templates/oscar/messages/no_cookies.html:4
msgid "currently, there are no cookies defined."
msgstr ""
#: searx/templates/oscar/messages/no_data_available.html:4
msgid "There is currently no data available. "
msgstr ""
#: searx/templates/oscar/messages/no_results.html:7
msgid "Sorry!"
msgstr "Συγνώμη!"
#: searx/templates/oscar/messages/no_results.html:8
msgid ""
"we didn't find any results. Please use another query or search in more "
"categories."
msgstr ""
#: searx/templates/oscar/messages/save_settings_successfull.html:7
msgid "Well done!"
msgstr ""
#: searx/templates/oscar/messages/save_settings_successfull.html:8
msgid "Settings saved successfully."
msgstr ""
#: searx/templates/oscar/messages/unknow_error.html:7
msgid "Oh snap!"
msgstr ""
#: searx/templates/oscar/messages/unknow_error.html:8
msgid "Something went wrong."
msgstr ""
#: searx/templates/oscar/result_templates/default.html:7
msgid "show media"
msgstr ""
#: searx/templates/oscar/result_templates/default.html:7
msgid "hide media"
msgstr ""
#: searx/templates/oscar/result_templates/images.html:23
msgid "Get image"
msgstr ""
#: searx/templates/oscar/result_templates/images.html:24
msgid "View source"
msgstr ""
#: searx/templates/oscar/result_templates/map.html:7
msgid "show map"
msgstr "προβολή χάρτη"
#: searx/templates/oscar/result_templates/map.html:7
msgid "hide map"
msgstr "απόκρυψη χάρτη"
#: searx/templates/oscar/result_templates/map.html:11
msgid "show details"
msgstr "προβολή λεπτομερειών"
#: searx/templates/oscar/result_templates/map.html:11
msgid "hide details"
msgstr "απόκρυψη λεπτομερειών"
#: searx/templates/oscar/result_templates/torrent.html:7
msgid "Filesize"
msgstr "Μέγεθος αρχείου"
#: searx/templates/oscar/result_templates/torrent.html:9
msgid "Bytes"
msgstr ""
#: searx/templates/oscar/result_templates/torrent.html:10
msgid "kiB"
msgstr ""
#: searx/templates/oscar/result_templates/torrent.html:11
msgid "MiB"
msgstr ""
#: searx/templates/oscar/result_templates/torrent.html:12
msgid "GiB"
msgstr ""
#: searx/templates/oscar/result_templates/torrent.html:13
msgid "TiB"
msgstr ""
#: searx/templates/oscar/result_templates/torrent.html:15
msgid "Number of Files"
msgstr ""
#: searx/templates/oscar/result_templates/videos.html:7
msgid "show video"
msgstr ""
#: searx/templates/oscar/result_templates/videos.html:7
msgid "hide video"
msgstr ""
#: searx/templates/pix-art/results.html:28
msgid "Load more..."
msgstr ""

View File

@ -1,189 +1,232 @@
# English translations for PROJECT.
# Copyright (C) 2014 ORGANIZATION
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2015-02-13 18:27+0100\n"
"POT-Creation-Date: 2016-01-21 16:05+0100\n"
"PO-Revision-Date: 2014-01-30 15:22+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n"
"Language-Team: en <LL@li.org>\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"
"Generated-By: Babel 1.3\n"
"Generated-By: Babel 2.2.0\n"
#: searx/webapp.py:100
#: searx/webapp.py:114
msgid "files"
msgstr ""
#: searx/webapp.py:101
#: searx/webapp.py:115
msgid "general"
msgstr ""
#: searx/webapp.py:102
#: searx/webapp.py:116
msgid "music"
msgstr ""
#: searx/webapp.py:103
#: searx/webapp.py:117
msgid "social media"
msgstr ""
#: searx/webapp.py:104
#: searx/webapp.py:118
msgid "images"
msgstr ""
#: searx/webapp.py:105
#: searx/webapp.py:119
msgid "videos"
msgstr ""
#: searx/webapp.py:106
#: searx/webapp.py:120
msgid "it"
msgstr ""
#: searx/webapp.py:107
#: searx/webapp.py:121
msgid "news"
msgstr ""
#: searx/webapp.py:108
#: searx/webapp.py:122
msgid "map"
msgstr ""
#: searx/webapp.py:361
#: searx/webapp.py:123
msgid "science"
msgstr ""
#: searx/webapp.py:415
msgid "{minutes} minute(s) ago"
msgstr ""
#: searx/webapp.py:363
#: searx/webapp.py:417
msgid "{hours} hour(s), {minutes} minute(s) ago"
msgstr ""
#: searx/engines/__init__.py:182
#: searx/engines/__init__.py:185
msgid "Page loads (sec)"
msgstr ""
#: searx/engines/__init__.py:186
#: searx/engines/__init__.py:189
msgid "Number of results"
msgstr ""
#: searx/engines/__init__.py:190
#: searx/engines/__init__.py:193
msgid "Scores"
msgstr ""
#: searx/engines/__init__.py:194
#: searx/engines/__init__.py:197
msgid "Scores per result"
msgstr ""
#: searx/engines/__init__.py:198
#: searx/engines/__init__.py:201
msgid "Errors"
msgstr ""
#: searx/plugins/https_rewrite.py:29
msgid "Rewrite HTTP links to HTTPS if possible"
msgstr ""
#: searx/plugins/search_on_category_select.py:18
msgid "Search on category select"
msgstr ""
#: searx/plugins/search_on_category_select.py:19
msgid ""
"Perform search immediately if a category selected. Disable to select "
"multiple categories. (JavaScript required)"
msgstr ""
#: searx/plugins/self_info.py:20
msgid ""
"Displays your IP if the query is \"ip\" and your user agent if the query "
"contains \"user agent\"."
msgstr ""
#: searx/plugins/tracker_url_remover.py:26
msgid "Tracker URL remover"
msgstr ""
#: searx/plugins/tracker_url_remover.py:27
msgid "Remove trackers arguments from the returned URL"
msgstr ""
#: searx/templates/courgette/index.html:9
#: searx/templates/courgette/index.html:13
#: searx/templates/courgette/results.html:5
#: searx/templates/default/index.html:8 searx/templates/default/index.html:12
#: searx/templates/oscar/navbar.html:7 searx/templates/oscar/navbar.html:35
#: searx/templates/oscar/preferences.html:3
#: searx/templates/pix-art/index.html:8
msgid "preferences"
msgstr ""
#: searx/templates/courgette/index.html:11
#: searx/templates/default/index.html:10 searx/templates/oscar/about.html:3
#: searx/templates/oscar/navbar.html:8 searx/templates/oscar/navbar.html:34
#: searx/templates/pix-art/index.html:7
msgid "about"
msgstr ""
#: searx/templates/courgette/preferences.html:5
#: searx/templates/default/preferences.html:5
#: searx/templates/oscar/preferences.html:12
#: searx/templates/pix-art/preferences.html:5
msgid "Preferences"
msgstr ""
#: searx/templates/courgette/preferences.html:9
#: searx/templates/default/preferences.html:9
#: searx/templates/oscar/preferences.html:34
#: searx/templates/oscar/preferences.html:36
#: searx/templates/oscar/preferences.html:38
msgid "Default categories"
msgstr ""
#: searx/templates/courgette/preferences.html:13
#: searx/templates/default/preferences.html:14
#: searx/templates/oscar/preferences.html:42
#: searx/templates/oscar/preferences.html:44
#: searx/templates/pix-art/preferences.html:9
msgid "Search language"
msgstr ""
#: searx/templates/courgette/preferences.html:16
#: searx/templates/default/preferences.html:17
#: searx/templates/oscar/preferences.html:46
#: searx/templates/oscar/preferences.html:48
#: searx/templates/pix-art/preferences.html:12
msgid "Automatic"
msgstr ""
#: searx/templates/courgette/preferences.html:24
#: searx/templates/default/preferences.html:25
#: searx/templates/oscar/preferences.html:53
#: searx/templates/oscar/preferences.html:55
#: searx/templates/pix-art/preferences.html:20
msgid "Interface language"
msgstr ""
#: searx/templates/courgette/preferences.html:34
#: searx/templates/default/preferences.html:35
#: searx/templates/oscar/preferences.html:63
#: searx/templates/oscar/preferences.html:65
msgid "Autocomplete"
msgstr ""
#: searx/templates/courgette/preferences.html:45
#: searx/templates/default/preferences.html:46
#: searx/templates/oscar/preferences.html:74
#: searx/templates/oscar/preferences.html:76
msgid "Image proxy"
msgstr ""
#: searx/templates/courgette/preferences.html:48
#: searx/templates/default/preferences.html:49
#: searx/templates/oscar/preferences.html:78
#: searx/templates/oscar/preferences.html:80
msgid "Enabled"
msgstr ""
#: searx/templates/courgette/preferences.html:49
#: searx/templates/default/preferences.html:50
#: searx/templates/oscar/preferences.html:79
#: searx/templates/oscar/preferences.html:81
msgid "Disabled"
msgstr ""
#: searx/templates/courgette/preferences.html:54
#: searx/templates/default/preferences.html:55
#: searx/templates/oscar/preferences.html:83
#: searx/templates/oscar/preferences.html:85
#: searx/templates/pix-art/preferences.html:30
msgid "Method"
msgstr ""
#: searx/templates/courgette/preferences.html:63
#: searx/templates/default/preferences.html:64
#: searx/templates/oscar/preferences.html:92
#: searx/templates/oscar/preferences.html:94
#: searx/templates/oscar/preferences.html:144
#: searx/templates/oscar/preferences.html:150
msgid "SafeSearch"
msgstr ""
#: searx/templates/courgette/preferences.html:66
#: searx/templates/default/preferences.html:67
#: searx/templates/oscar/preferences.html:96
#: searx/templates/oscar/preferences.html:98
msgid "Strict"
msgstr ""
#: searx/templates/courgette/preferences.html:67
#: searx/templates/default/preferences.html:68
#: searx/templates/oscar/preferences.html:97
#: searx/templates/oscar/preferences.html:99
msgid "Moderate"
msgstr ""
#: searx/templates/courgette/preferences.html:68
#: searx/templates/default/preferences.html:69
#: searx/templates/oscar/preferences.html:98
#: searx/templates/oscar/preferences.html:100
msgid "None"
msgstr ""
#: searx/templates/courgette/preferences.html:73
#: searx/templates/default/preferences.html:74
#: searx/templates/oscar/preferences.html:102
#: searx/templates/oscar/preferences.html:104
#: searx/templates/pix-art/preferences.html:39
msgid "Themes"
msgstr ""
@ -217,11 +260,15 @@ msgstr ""
#: searx/templates/courgette/preferences.html:96
#: searx/templates/default/preferences.html:84
#: searx/templates/pix-art/preferences.html:49
msgid "Currently used search engines"
msgstr ""
#: searx/templates/courgette/preferences.html:100
#: searx/templates/default/preferences.html:88
#: searx/templates/oscar/preferences.html:142
#: searx/templates/oscar/preferences.html:152
#: searx/templates/pix-art/preferences.html:53
msgid "Engine name"
msgstr ""
@ -234,7 +281,11 @@ msgstr ""
#: searx/templates/courgette/preferences.html:113
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:101
#: searx/templates/oscar/preferences.html:145
#: searx/templates/oscar/macros.html:71
#: searx/templates/oscar/preferences.html:141
#: searx/templates/oscar/preferences.html:153
#: searx/templates/pix-art/preferences.html:54
#: searx/templates/pix-art/preferences.html:64
msgid "Allow"
msgstr ""
@ -242,13 +293,16 @@ msgstr ""
#: searx/templates/courgette/preferences.html:114
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:102
#: searx/templates/oscar/preferences.html:144
#: searx/templates/oscar/macros.html:70
#: searx/templates/pix-art/preferences.html:54
#: searx/templates/pix-art/preferences.html:65
msgid "Block"
msgstr ""
#: searx/templates/courgette/preferences.html:122
#: searx/templates/default/preferences.html:110
#: searx/templates/oscar/preferences.html:161
#: searx/templates/oscar/preferences.html:235
#: searx/templates/pix-art/preferences.html:73
msgid ""
"These settings are stored in your cookies, this allows us not to store "
"this data about you."
@ -256,7 +310,8 @@ msgstr ""
#: searx/templates/courgette/preferences.html:124
#: searx/templates/default/preferences.html:112
#: searx/templates/oscar/preferences.html:163
#: searx/templates/oscar/preferences.html:237
#: searx/templates/pix-art/preferences.html:75
msgid ""
"These cookies serve your sole convenience, we don't use these cookies to "
"track you."
@ -264,13 +319,21 @@ msgstr ""
#: searx/templates/courgette/preferences.html:127
#: searx/templates/default/preferences.html:115
#: searx/templates/oscar/preferences.html:166
#: searx/templates/oscar/preferences.html:240
#: searx/templates/pix-art/preferences.html:78
msgid "save"
msgstr ""
#: searx/templates/courgette/preferences.html:128
#: searx/templates/default/preferences.html:116
#: searx/templates/oscar/preferences.html:167
#: searx/templates/oscar/preferences.html:242
msgid "Reset defaults"
msgstr ""
#: searx/templates/courgette/preferences.html:129
#: searx/templates/default/preferences.html:117
#: searx/templates/oscar/preferences.html:241
#: searx/templates/pix-art/preferences.html:79
msgid "back"
msgstr ""
@ -312,16 +375,18 @@ msgstr ""
#: searx/templates/courgette/search.html:3
#: searx/templates/default/search.html:3 searx/templates/oscar/search.html:4
#: searx/templates/oscar/search_full.html:9
#: searx/templates/pix-art/search.html:3
msgid "Search for..."
msgstr ""
#: searx/templates/courgette/stats.html:4 searx/templates/default/stats.html:4
#: searx/templates/oscar/stats.html:5
#: searx/templates/oscar/stats.html:5 searx/templates/pix-art/stats.html:4
msgid "Engine stats"
msgstr ""
#: searx/templates/courgette/result_templates/images.html:4
#: searx/templates/default/result_templates/images.html:4
#: searx/templates/pix-art/result_templates/images.html:4
msgid "original context"
msgstr ""
@ -360,11 +425,11 @@ msgstr ""
msgid "cached"
msgstr ""
#: searx/templates/oscar/base.html:74
#: searx/templates/oscar/base.html:78
msgid "Powered by"
msgstr ""
#: searx/templates/oscar/base.html:74
#: searx/templates/oscar/base.html:78
msgid "a privacy-respecting, hackable metasearch engine"
msgstr ""
@ -377,46 +442,89 @@ msgid "Toggle navigation"
msgstr ""
#: searx/templates/oscar/preferences.html:17
#: searx/templates/oscar/preferences.html:23
#: searx/templates/oscar/preferences.html:25
msgid "General"
msgstr ""
#: searx/templates/oscar/preferences.html:18
#: searx/templates/oscar/preferences.html:124
#: searx/templates/oscar/preferences.html:126
msgid "Engines"
msgstr ""
#: searx/templates/oscar/preferences.html:43
#: searx/templates/oscar/preferences.html:19
#: searx/templates/oscar/preferences.html:187
msgid "Plugins"
msgstr ""
#: searx/templates/oscar/preferences.html:20
#: searx/templates/oscar/preferences.html:210
msgid "Cookies"
msgstr ""
#: searx/templates/oscar/preferences.html:45
msgid "What language do you prefer for search?"
msgstr ""
#: searx/templates/oscar/preferences.html:54
#: searx/templates/oscar/preferences.html:56
msgid "Change the language of the layout"
msgstr ""
#: searx/templates/oscar/preferences.html:64
#: searx/templates/oscar/preferences.html:66
msgid "Find stuff as you type"
msgstr ""
#: searx/templates/oscar/preferences.html:75
#: searx/templates/oscar/preferences.html:77
msgid "Proxying image results through searx"
msgstr ""
#: searx/templates/oscar/preferences.html:84
#: searx/templates/oscar/preferences.html:86
msgid ""
"Change how forms are submited, <a "
"href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\""
" rel=\"external\">learn more about request methods</a>"
msgstr ""
#: searx/templates/oscar/preferences.html:93
#: searx/templates/oscar/preferences.html:95
msgid "Filter content"
msgstr ""
#: searx/templates/oscar/preferences.html:103
#: searx/templates/oscar/preferences.html:105
msgid "Change searx layout"
msgstr ""
#: searx/templates/oscar/preferences.html:143
#: searx/templates/oscar/preferences.html:151
msgid "Shortcut"
msgstr ""
#: searx/templates/oscar/preferences.html:145
#: searx/templates/oscar/preferences.html:149
msgid "Avg. time"
msgstr ""
#: searx/templates/oscar/preferences.html:146
#: searx/templates/oscar/preferences.html:148
msgid "Max time"
msgstr ""
#: searx/templates/oscar/preferences.html:213
msgid ""
"This is the list of cookies and their values searx is storing on your "
"computer."
msgstr ""
#: searx/templates/oscar/preferences.html:214
msgid "With that list, you can assess searx transparency."
msgstr ""
#: searx/templates/oscar/preferences.html:219
msgid "Cookie name"
msgstr ""
#: searx/templates/oscar/preferences.html:220
msgid "Value"
msgstr ""
#: searx/templates/oscar/results.html:7
msgid "Search results"
msgstr ""
@ -466,6 +574,14 @@ msgstr ""
msgid "Please enable JavaScript to use full functionality of this site."
msgstr ""
#: searx/templates/oscar/messages/no_cookies.html:3
msgid "Information!"
msgstr ""
#: searx/templates/oscar/messages/no_cookies.html:4
msgid "currently, there are no cookies defined."
msgstr ""
#: searx/templates/oscar/messages/no_data_available.html:4
msgid "There is currently no data available. "
msgstr ""
@ -564,6 +680,10 @@ msgstr ""
msgid "hide video"
msgstr ""
#: searx/templates/pix-art/results.html:28
msgid "Load more..."
msgstr ""
#~ msgid "Localization"
#~ msgstr ""

Binary file not shown.

View File

@ -0,0 +1,686 @@
# Translations template for PROJECT.
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
# juanda097 <juanda097@openmailbox.org>, 2015
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-01-21 16:05+0100\n"
"PO-Revision-Date: 2016-01-21 15:06+0000\n"
"Last-Translator: Thomas Pointhuber\n"
"Language-Team: Esperanto (http://www.transifex.com/asciimoo/searx/language/eo/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.2.0\n"
"Language: eo\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: searx/webapp.py:114
msgid "files"
msgstr "dosieroj"
#: searx/webapp.py:115
msgid "general"
msgstr "ĝenerala"
#: searx/webapp.py:116
msgid "music"
msgstr "muziko"
#: searx/webapp.py:117
msgid "social media"
msgstr "sociaj retservoj"
#: searx/webapp.py:118
msgid "images"
msgstr "bildoj"
#: searx/webapp.py:119
msgid "videos"
msgstr "videoj"
#: searx/webapp.py:120
msgid "it"
msgstr ""
#: searx/webapp.py:121
msgid "news"
msgstr "novaĵoj"
#: searx/webapp.py:122
msgid "map"
msgstr "mapo"
#: searx/webapp.py:123
msgid "science"
msgstr ""
#: searx/webapp.py:415
msgid "{minutes} minute(s) ago"
msgstr ""
#: searx/webapp.py:417
msgid "{hours} hour(s), {minutes} minute(s) ago"
msgstr ""
#: searx/engines/__init__.py:185
msgid "Page loads (sec)"
msgstr ""
#: searx/engines/__init__.py:189
msgid "Number of results"
msgstr "Nombro de rezultoj"
#: searx/engines/__init__.py:193
msgid "Scores"
msgstr "Poentaroj"
#: searx/engines/__init__.py:197
msgid "Scores per result"
msgstr "Poentaroj por unu rezulto"
#: searx/engines/__init__.py:201
msgid "Errors"
msgstr "Eraroj"
#: searx/plugins/https_rewrite.py:29
msgid "Rewrite HTTP links to HTTPS if possible"
msgstr "Reverki HTTP ligiloj HTTP se eble"
#: searx/plugins/search_on_category_select.py:18
msgid "Search on category select"
msgstr ""
#: searx/plugins/search_on_category_select.py:19
msgid ""
"Perform search immediately if a category selected. Disable to select "
"multiple categories. (JavaScript required)"
msgstr ""
#: searx/plugins/self_info.py:20
msgid ""
"Displays your IP if the query is \"ip\" and your user agent if the query "
"contains \"user agent\"."
msgstr ""
#: searx/plugins/tracker_url_remover.py:26
msgid "Tracker URL remover"
msgstr ""
#: searx/plugins/tracker_url_remover.py:27
msgid "Remove trackers arguments from the returned URL"
msgstr ""
#: searx/templates/courgette/index.html:9
#: searx/templates/courgette/index.html:13
#: searx/templates/courgette/results.html:5
#: searx/templates/default/index.html:8 searx/templates/default/index.html:12
#: searx/templates/oscar/navbar.html:7 searx/templates/oscar/navbar.html:35
#: searx/templates/oscar/preferences.html:3
#: searx/templates/pix-art/index.html:8
msgid "preferences"
msgstr "preferoj"
#: searx/templates/courgette/index.html:11
#: searx/templates/default/index.html:10 searx/templates/oscar/about.html:3
#: searx/templates/oscar/navbar.html:8 searx/templates/oscar/navbar.html:34
#: searx/templates/pix-art/index.html:7
msgid "about"
msgstr ""
#: searx/templates/courgette/preferences.html:5
#: searx/templates/default/preferences.html:5
#: searx/templates/oscar/preferences.html:12
#: searx/templates/pix-art/preferences.html:5
msgid "Preferences"
msgstr "Preferoj"
#: searx/templates/courgette/preferences.html:9
#: searx/templates/default/preferences.html:9
#: searx/templates/oscar/preferences.html:36
#: searx/templates/oscar/preferences.html:38
msgid "Default categories"
msgstr "Nerepago kategorioj"
#: searx/templates/courgette/preferences.html:13
#: searx/templates/default/preferences.html:14
#: searx/templates/oscar/preferences.html:44
#: searx/templates/pix-art/preferences.html:9
msgid "Search language"
msgstr "Serĉo lingvo"
#: searx/templates/courgette/preferences.html:16
#: searx/templates/default/preferences.html:17
#: searx/templates/oscar/preferences.html:48
#: searx/templates/pix-art/preferences.html:12
msgid "Automatic"
msgstr "Aŭtomata"
#: searx/templates/courgette/preferences.html:24
#: searx/templates/default/preferences.html:25
#: searx/templates/oscar/preferences.html:55
#: searx/templates/pix-art/preferences.html:20
msgid "Interface language"
msgstr "Fasado lingvo"
#: searx/templates/courgette/preferences.html:34
#: searx/templates/default/preferences.html:35
#: searx/templates/oscar/preferences.html:65
msgid "Autocomplete"
msgstr ""
#: searx/templates/courgette/preferences.html:45
#: searx/templates/default/preferences.html:46
#: searx/templates/oscar/preferences.html:76
msgid "Image proxy"
msgstr ""
#: searx/templates/courgette/preferences.html:48
#: searx/templates/default/preferences.html:49
#: searx/templates/oscar/preferences.html:80
msgid "Enabled"
msgstr ""
#: searx/templates/courgette/preferences.html:49
#: searx/templates/default/preferences.html:50
#: searx/templates/oscar/preferences.html:81
msgid "Disabled"
msgstr ""
#: searx/templates/courgette/preferences.html:54
#: searx/templates/default/preferences.html:55
#: searx/templates/oscar/preferences.html:85
#: searx/templates/pix-art/preferences.html:30
msgid "Method"
msgstr ""
#: searx/templates/courgette/preferences.html:63
#: searx/templates/default/preferences.html:64
#: searx/templates/oscar/preferences.html:94
#: searx/templates/oscar/preferences.html:144
#: searx/templates/oscar/preferences.html:150
msgid "SafeSearch"
msgstr ""
#: searx/templates/courgette/preferences.html:66
#: searx/templates/default/preferences.html:67
#: searx/templates/oscar/preferences.html:98
msgid "Strict"
msgstr "Strikta"
#: searx/templates/courgette/preferences.html:67
#: searx/templates/default/preferences.html:68
#: searx/templates/oscar/preferences.html:99
msgid "Moderate"
msgstr "Modera"
#: searx/templates/courgette/preferences.html:68
#: searx/templates/default/preferences.html:69
#: searx/templates/oscar/preferences.html:100
msgid "None"
msgstr "Neniu"
#: searx/templates/courgette/preferences.html:73
#: searx/templates/default/preferences.html:74
#: searx/templates/oscar/preferences.html:104
#: searx/templates/pix-art/preferences.html:39
msgid "Themes"
msgstr "Temoj"
#: searx/templates/courgette/preferences.html:83
msgid "Color"
msgstr "Koloro"
#: searx/templates/courgette/preferences.html:86
msgid "Blue (default)"
msgstr "Blua (nerepago)"
#: searx/templates/courgette/preferences.html:87
msgid "Violet"
msgstr "Viola"
#: searx/templates/courgette/preferences.html:88
msgid "Green"
msgstr "Verda"
#: searx/templates/courgette/preferences.html:89
msgid "Cyan"
msgstr "Cejana"
#: searx/templates/courgette/preferences.html:90
msgid "Orange"
msgstr "Oranĝa"
#: searx/templates/courgette/preferences.html:91
msgid "Red"
msgstr "Ruĝa"
#: searx/templates/courgette/preferences.html:96
#: searx/templates/default/preferences.html:84
#: searx/templates/pix-art/preferences.html:49
msgid "Currently used search engines"
msgstr ""
#: searx/templates/courgette/preferences.html:100
#: searx/templates/default/preferences.html:88
#: searx/templates/oscar/preferences.html:142
#: searx/templates/oscar/preferences.html:152
#: searx/templates/pix-art/preferences.html:53
msgid "Engine name"
msgstr ""
#: searx/templates/courgette/preferences.html:101
#: searx/templates/default/preferences.html:89
msgid "Category"
msgstr "Kategorio"
#: searx/templates/courgette/preferences.html:102
#: searx/templates/courgette/preferences.html:113
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:101
#: searx/templates/oscar/macros.html:71
#: searx/templates/oscar/preferences.html:141
#: searx/templates/oscar/preferences.html:153
#: searx/templates/pix-art/preferences.html:54
#: searx/templates/pix-art/preferences.html:64
msgid "Allow"
msgstr "Permesi"
#: searx/templates/courgette/preferences.html:102
#: searx/templates/courgette/preferences.html:114
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:102
#: searx/templates/oscar/macros.html:70
#: searx/templates/pix-art/preferences.html:54
#: searx/templates/pix-art/preferences.html:65
msgid "Block"
msgstr "Bloko"
#: searx/templates/courgette/preferences.html:122
#: searx/templates/default/preferences.html:110
#: searx/templates/oscar/preferences.html:235
#: searx/templates/pix-art/preferences.html:73
msgid ""
"These settings are stored in your cookies, this allows us not to store this "
"data about you."
msgstr ""
#: searx/templates/courgette/preferences.html:124
#: searx/templates/default/preferences.html:112
#: searx/templates/oscar/preferences.html:237
#: searx/templates/pix-art/preferences.html:75
msgid ""
"These cookies serve your sole convenience, we don't use these cookies to "
"track you."
msgstr ""
#: searx/templates/courgette/preferences.html:127
#: searx/templates/default/preferences.html:115
#: searx/templates/oscar/preferences.html:240
#: searx/templates/pix-art/preferences.html:78
msgid "save"
msgstr ""
#: searx/templates/courgette/preferences.html:128
#: searx/templates/default/preferences.html:116
#: searx/templates/oscar/preferences.html:242
msgid "Reset defaults"
msgstr ""
#: searx/templates/courgette/preferences.html:129
#: searx/templates/default/preferences.html:117
#: searx/templates/oscar/preferences.html:241
#: searx/templates/pix-art/preferences.html:79
msgid "back"
msgstr ""
#: searx/templates/courgette/results.html:12
#: searx/templates/default/results.html:13
#: searx/templates/oscar/results.html:110
msgid "Search URL"
msgstr ""
#: searx/templates/courgette/results.html:16
#: searx/templates/default/results.html:17
#: searx/templates/oscar/results.html:115
msgid "Download results"
msgstr "Deŝuto rezultoj"
#: searx/templates/courgette/results.html:34
#: searx/templates/default/results.html:35
msgid "Answers"
msgstr "Respondoj"
#: searx/templates/courgette/results.html:42
#: searx/templates/default/results.html:43
#: searx/templates/oscar/results.html:90
msgid "Suggestions"
msgstr ""
#: searx/templates/courgette/results.html:70
#: searx/templates/default/results.html:81
#: searx/templates/oscar/results.html:51 searx/templates/oscar/results.html:63
msgid "previous page"
msgstr ""
#: searx/templates/courgette/results.html:81
#: searx/templates/default/results.html:92
#: searx/templates/oscar/results.html:44 searx/templates/oscar/results.html:71
msgid "next page"
msgstr ""
#: searx/templates/courgette/search.html:3
#: searx/templates/default/search.html:3 searx/templates/oscar/search.html:4
#: searx/templates/oscar/search_full.html:9
#: searx/templates/pix-art/search.html:3
msgid "Search for..."
msgstr ""
#: searx/templates/courgette/stats.html:4 searx/templates/default/stats.html:4
#: searx/templates/oscar/stats.html:5 searx/templates/pix-art/stats.html:4
msgid "Engine stats"
msgstr ""
#: searx/templates/courgette/result_templates/images.html:4
#: searx/templates/default/result_templates/images.html:4
#: searx/templates/pix-art/result_templates/images.html:4
msgid "original context"
msgstr ""
#: searx/templates/courgette/result_templates/torrent.html:7
#: searx/templates/default/result_templates/torrent.html:11
#: searx/templates/oscar/result_templates/torrent.html:6
msgid "Seeder"
msgstr ""
#: searx/templates/courgette/result_templates/torrent.html:7
#: searx/templates/default/result_templates/torrent.html:11
#: searx/templates/oscar/result_templates/torrent.html:6
msgid "Leecher"
msgstr ""
#: searx/templates/courgette/result_templates/torrent.html:9
#: searx/templates/default/result_templates/torrent.html:9
#: searx/templates/oscar/macros.html:21
msgid "magnet link"
msgstr ""
#: searx/templates/courgette/result_templates/torrent.html:10
#: searx/templates/default/result_templates/torrent.html:10
#: searx/templates/oscar/macros.html:22
msgid "torrent file"
msgstr ""
#: searx/templates/default/categories.html:8
msgid "Click on the magnifier to perform search"
msgstr ""
#: searx/templates/default/result_templates/code.html:3
#: searx/templates/default/result_templates/default.html:3
#: searx/templates/default/result_templates/map.html:9
#: searx/templates/oscar/macros.html:20
msgid "cached"
msgstr ""
#: searx/templates/oscar/base.html:78
msgid "Powered by"
msgstr ""
#: searx/templates/oscar/base.html:78
msgid "a privacy-respecting, hackable metasearch engine"
msgstr ""
#: searx/templates/oscar/navbar.html:9 searx/templates/oscar/navbar.html:33
msgid "home"
msgstr ""
#: searx/templates/oscar/navbar.html:14 searx/templates/oscar/navbar.html:24
msgid "Toggle navigation"
msgstr ""
#: searx/templates/oscar/preferences.html:17
#: searx/templates/oscar/preferences.html:25
msgid "General"
msgstr ""
#: searx/templates/oscar/preferences.html:18
#: searx/templates/oscar/preferences.html:126
msgid "Engines"
msgstr ""
#: searx/templates/oscar/preferences.html:19
#: searx/templates/oscar/preferences.html:187
msgid "Plugins"
msgstr ""
#: searx/templates/oscar/preferences.html:20
#: searx/templates/oscar/preferences.html:210
msgid "Cookies"
msgstr ""
#: searx/templates/oscar/preferences.html:45
msgid "What language do you prefer for search?"
msgstr ""
#: searx/templates/oscar/preferences.html:56
msgid "Change the language of the layout"
msgstr ""
#: searx/templates/oscar/preferences.html:66
msgid "Find stuff as you type"
msgstr ""
#: searx/templates/oscar/preferences.html:77
msgid "Proxying image results through searx"
msgstr ""
#: searx/templates/oscar/preferences.html:86
msgid ""
"Change how forms are submited, <a "
"href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\""
" rel=\"external\">learn more about request methods</a>"
msgstr " Ŝanĝ kiel formoj estas submetiĝita, < href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\" rel=\"external\"> Lerni pli pri peto metodoj</> "
#: searx/templates/oscar/preferences.html:95
msgid "Filter content"
msgstr ""
#: searx/templates/oscar/preferences.html:105
msgid "Change searx layout"
msgstr ""
#: searx/templates/oscar/preferences.html:143
#: searx/templates/oscar/preferences.html:151
msgid "Shortcut"
msgstr ""
#: searx/templates/oscar/preferences.html:145
#: searx/templates/oscar/preferences.html:149
msgid "Avg. time"
msgstr ""
#: searx/templates/oscar/preferences.html:146
#: searx/templates/oscar/preferences.html:148
msgid "Max time"
msgstr ""
#: searx/templates/oscar/preferences.html:213
msgid ""
"This is the list of cookies and their values searx is storing on your "
"computer."
msgstr ""
#: searx/templates/oscar/preferences.html:214
msgid "With that list, you can assess searx transparency."
msgstr ""
#: searx/templates/oscar/preferences.html:219
msgid "Cookie name"
msgstr ""
#: searx/templates/oscar/preferences.html:220
msgid "Value"
msgstr ""
#: searx/templates/oscar/results.html:7
msgid "Search results"
msgstr "Serĉrezultoj"
#: searx/templates/oscar/results.html:105
msgid "Links"
msgstr ""
#: searx/templates/oscar/search.html:6
#: searx/templates/oscar/search_full.html:11
msgid "Start search"
msgstr ""
#: searx/templates/oscar/search_full.html:15
msgid "Show search filters"
msgstr ""
#: searx/templates/oscar/search_full.html:15
msgid "Hide search filters"
msgstr ""
#: searx/templates/oscar/stats.html:2
msgid "stats"
msgstr "statistiko"
#: searx/templates/oscar/messages/first_time.html:4
#: searx/templates/oscar/messages/no_results.html:5
#: searx/templates/oscar/messages/save_settings_successfull.html:5
#: searx/templates/oscar/messages/unknow_error.html:5
msgid "Close"
msgstr "Ferm"
#: searx/templates/oscar/messages/first_time.html:6
#: searx/templates/oscar/messages/no_data_available.html:3
msgid "Heads up!"
msgstr ""
#: searx/templates/oscar/messages/first_time.html:7
msgid "It look like you are using searx first time."
msgstr ""
#: searx/templates/oscar/messages/js_disabled.html:2
msgid "Warning!"
msgstr "Averto!"
#: searx/templates/oscar/messages/js_disabled.html:3
msgid "Please enable JavaScript to use full functionality of this site."
msgstr "Bonvolu ebligi al Javaskripto uzi plenan funkcion de ĉi tiu ejo."
#: searx/templates/oscar/messages/no_cookies.html:3
msgid "Information!"
msgstr "Informoj!"
#: searx/templates/oscar/messages/no_cookies.html:4
msgid "currently, there are no cookies defined."
msgstr ""
#: searx/templates/oscar/messages/no_data_available.html:4
msgid "There is currently no data available. "
msgstr ""
#: searx/templates/oscar/messages/no_results.html:7
msgid "Sorry!"
msgstr "Mizera!"
#: searx/templates/oscar/messages/no_results.html:8
msgid ""
"we didn't find any results. Please use another query or search in more "
"categories."
msgstr ""
#: searx/templates/oscar/messages/save_settings_successfull.html:7
msgid "Well done!"
msgstr "Bone farite!"
#: searx/templates/oscar/messages/save_settings_successfull.html:8
msgid "Settings saved successfully."
msgstr "Fiksaĵoj savis sukcese."
#: searx/templates/oscar/messages/unknow_error.html:7
msgid "Oh snap!"
msgstr "Aj klak!"
#: searx/templates/oscar/messages/unknow_error.html:8
msgid "Something went wrong."
msgstr "Aĵo fuŝiĝis."
#: searx/templates/oscar/result_templates/default.html:7
msgid "show media"
msgstr "montr amaskomunikiloj"
#: searx/templates/oscar/result_templates/default.html:7
msgid "hide media"
msgstr "kaŝi amaskomunikilojn"
#: searx/templates/oscar/result_templates/images.html:23
msgid "Get image"
msgstr "Akiri bildon"
#: searx/templates/oscar/result_templates/images.html:24
msgid "View source"
msgstr "Vido fonto"
#: searx/templates/oscar/result_templates/map.html:7
msgid "show map"
msgstr "montr mapo"
#: searx/templates/oscar/result_templates/map.html:7
msgid "hide map"
msgstr "kaŝi mapon"
#: searx/templates/oscar/result_templates/map.html:11
msgid "show details"
msgstr "montr detaloj"
#: searx/templates/oscar/result_templates/map.html:11
msgid "hide details"
msgstr "kaŝi detalojn"
#: searx/templates/oscar/result_templates/torrent.html:7
msgid "Filesize"
msgstr "Filesize"
#: searx/templates/oscar/result_templates/torrent.html:9
msgid "Bytes"
msgstr ""
#: searx/templates/oscar/result_templates/torrent.html:10
msgid "kiB"
msgstr ""
#: searx/templates/oscar/result_templates/torrent.html:11
msgid "MiB"
msgstr ""
#: searx/templates/oscar/result_templates/torrent.html:12
msgid "GiB"
msgstr ""
#: searx/templates/oscar/result_templates/torrent.html:13
msgid "TiB"
msgstr ""
#: searx/templates/oscar/result_templates/torrent.html:15
msgid "Number of Files"
msgstr "Nombro de Dosieroj"
#: searx/templates/oscar/result_templates/videos.html:7
msgid "show video"
msgstr "montr video"
#: searx/templates/oscar/result_templates/videos.html:7
msgid "hide video"
msgstr "kaŝi videon"
#: searx/templates/pix-art/results.html:28
msgid "Load more..."
msgstr "Ŝarĝ pli..."

View File

@ -1,24 +1,25 @@
# Translations template for PROJECT.
# Copyright (C) 2015 ORGANIZATION
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
# Adam Tauber <asciimoo@gmail.com>, 2015
# Alejandro León Aznar, 2014
# Alejandro León Aznar, 2014-2015
# Oscar Carrero <holaoscar@protonmail.ch>, 2015
# juanda097 <juanda097@openmailbox.org>, 2016
# Oscar Carrero <ocf@openmailbox.org>, 2015
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2015-08-24 11:44+0200\n"
"PO-Revision-Date: 2015-09-05 20:46+0000\n"
"Last-Translator: Oscar Carrero <holaoscar@protonmail.ch>\n"
"POT-Creation-Date: 2016-01-21 16:05+0100\n"
"PO-Revision-Date: 2016-02-24 23:02+0000\n"
"Last-Translator: juanda097 <juanda097@openmailbox.org>\n"
"Language-Team: Spanish (http://www.transifex.com/asciimoo/searx/language/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"
"Generated-By: Babel 2.2.0\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@ -58,11 +59,15 @@ msgstr "noticias"
msgid "map"
msgstr "mapa"
#: searx/webapp.py:414
#: searx/webapp.py:123
msgid "science"
msgstr "ciencia"
#: searx/webapp.py:415
msgid "{minutes} minute(s) ago"
msgstr "hace {minutes} minuto(s)"
#: searx/webapp.py:416
#: searx/webapp.py:417
msgid "{hours} hour(s), {minutes} minute(s) ago"
msgstr "hace {hours} hora(s) y {minutes} minuto(s)"
@ -281,7 +286,7 @@ msgstr "Categoría"
#: searx/templates/courgette/preferences.html:113
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:101
#: searx/templates/oscar/macros.html:67
#: searx/templates/oscar/macros.html:71
#: searx/templates/oscar/preferences.html:141
#: searx/templates/oscar/preferences.html:153
#: searx/templates/pix-art/preferences.html:54
@ -293,7 +298,7 @@ msgstr "Permitir"
#: searx/templates/courgette/preferences.html:114
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:102
#: searx/templates/oscar/macros.html:66
#: searx/templates/oscar/macros.html:70
#: searx/templates/pix-art/preferences.html:54
#: searx/templates/pix-art/preferences.html:65
msgid "Block"
@ -475,7 +480,7 @@ msgstr "Buscar mientras escribes"
#: searx/templates/oscar/preferences.html:77
msgid "Proxying image results through searx"
msgstr "Filtrando resultados de imágenes en searx"
msgstr "Filtrado de resultados de imágenes en searx"
#: searx/templates/oscar/preferences.html:86
msgid ""

View File

@ -1,11 +1,11 @@
# Translations template for PROJECT.
# Copyright (C) 2015 ORGANIZATION
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
# Benjamin Sonntag <benjamin@sonntag.fr>, 2014
# Cqoicebordel <david.barouh@wanadoo.fr>, 2014
# Cqoicebordel <david.barouh@wanadoo.fr>, 2014-2015
# Cqoicebordel <david.barouh@wanadoo.fr>, 2014-2016
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014
# rike, 2014
# rike, 2014
@ -13,14 +13,14 @@ msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2015-08-24 11:44+0200\n"
"PO-Revision-Date: 2015-08-24 15:35+0000\n"
"POT-Creation-Date: 2016-01-21 16:05+0100\n"
"PO-Revision-Date: 2016-01-21 15:31+0000\n"
"Last-Translator: Cqoicebordel <david.barouh@wanadoo.fr>\n"
"Language-Team: French (http://www.transifex.com/asciimoo/searx/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"
"Generated-By: Babel 2.2.0\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
@ -60,11 +60,15 @@ msgstr "actus"
msgid "map"
msgstr "carte"
#: searx/webapp.py:414
#: searx/webapp.py:123
msgid "science"
msgstr "science"
#: searx/webapp.py:415
msgid "{minutes} minute(s) ago"
msgstr "il y a {minutes} minute(s)"
#: searx/webapp.py:416
#: searx/webapp.py:417
msgid "{hours} hour(s), {minutes} minute(s) ago"
msgstr "il y a {hours} heure(s), {minutes} minute(s)"
@ -283,7 +287,7 @@ msgstr "Catégorie"
#: searx/templates/courgette/preferences.html:113
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:101
#: searx/templates/oscar/macros.html:67
#: searx/templates/oscar/macros.html:71
#: searx/templates/oscar/preferences.html:141
#: searx/templates/oscar/preferences.html:153
#: searx/templates/pix-art/preferences.html:54
@ -295,7 +299,7 @@ msgstr "Autoriser"
#: searx/templates/courgette/preferences.html:114
#: searx/templates/default/preferences.html:90
#: searx/templates/default/preferences.html:102
#: searx/templates/oscar/macros.html:66
#: searx/templates/oscar/macros.html:70
#: searx/templates/pix-art/preferences.html:54
#: searx/templates/pix-art/preferences.html:65
msgid "Block"

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