update version 0.6

This commit is contained in:
Adrien Beudin 2015-01-13 16:40:30 +01:00
parent 684b966c57
commit c2d95ecba4
61 changed files with 1141 additions and 448 deletions

26
sources/CHANGELOG.rst Normal file
View File

@ -0,0 +1,26 @@
0.6.0
=====
- Changelog added
- New engines
- Flickr (api)
- Subtitleseeker
- photon
- 500px
- Searchcode
- Searchcode doc
- Kickass torrent
- Precise search request timeout handling
- Better favicon support
- Stricter config parsing
- Translation updates
- Multiple ui fixes
- Flickr (noapi) engine fix
- Pep8 fixes
News
~~~~
Health status of searx instances and engines: http://stats.searx.oe5tpo.com
(source: https://github.com/pointhi/searx_stats)

View File

@ -0,0 +1,57 @@
## 500px (Images)
#
# @website https://500px.com
# @provide-api yes (https://developers.500px.com/)
#
# @using-api no
# @results HTML
# @stable no (HTML can change)
# @parse url, title, thumbnail, img_src, content
#
# @todo rewrite to api
from urllib import urlencode
from urlparse import urljoin
from lxml import html
# engine dependent config
categories = ['images']
paging = True
# search-url
base_url = 'https://500px.com'
search_url = base_url+'/search?search?page={pageno}&type=photos&{query}'
# do search-request
def request(query, params):
params['url'] = search_url.format(pageno=params['pageno'],
query=urlencode({'q': query}))
return params
# get response from search-request
def response(resp):
results = []
dom = html.fromstring(resp.text)
# parse results
for result in dom.xpath('//div[@class="photo"]'):
link = result.xpath('.//a')[0]
url = urljoin(base_url, link.attrib.get('href'))
title = result.xpath('.//div[@class="title"]//text()')[0]
img_src = link.xpath('.//img')[0].attrib['src']
content = result.xpath('.//div[@class="info"]//text()')[0]
# append result
results.append({'url': url,
'title': title,
'img_src': img_src,
'content': content,
'template': 'images.html'})
# return results
return results

View File

@ -41,11 +41,8 @@ def load_module(filename):
module.name = modname
return module
if 'engines' not in settings or not settings['engines']:
print '[E] Error no engines found. Edit your settings.yml'
exit(2)
for engine_data in settings['engines']:
def load_engine(engine_data):
engine_name = engine_data['engine']
engine = load_module(engine_name + '.py')
@ -84,10 +81,10 @@ for engine_data in settings['engines']:
if engine_attr.startswith('_'):
continue
if getattr(engine, engine_attr) is None:
print '[E] Engine config error: Missing attribute "{0}.{1}"'.format(engine.name, engine_attr) # noqa
print('[E] Engine config error: Missing attribute "{0}.{1}"'\
.format(engine.name, engine_attr))
sys.exit(1)
engines[engine.name] = engine
engine.stats = {
'result_count': 0,
'search_count': 0,
@ -104,7 +101,12 @@ for engine_data in settings['engines']:
if engine.shortcut:
# TODO check duplications
if engine.shortcut in engine_shortcuts:
print('[E] Engine config error: ambigious shortcut: {0}'\
.format(engine.shortcut))
sys.exit(1)
engine_shortcuts[engine.shortcut] = engine.name
return engine
def get_engines_stats():
@ -194,3 +196,12 @@ def get_engines_stats():
sorted(errors, key=itemgetter('avg'), reverse=True)
),
]
if 'engines' not in settings or not settings['engines']:
print '[E] Error no engines found. Edit your settings.yml'
exit(2)
for engine_data in settings['engines']:
engine = load_engine(engine_data)
engines[engine.name] = engine

View File

@ -57,12 +57,16 @@ def response(resp):
link = result.xpath('.//div[@class="newstitle"]/a')[0]
url = link.attrib.get('href')
title = ' '.join(link.xpath('.//text()'))
contentXPath = result.xpath('.//div[@class="sn_txt"]/div//span[@class="sn_snip"]//text()')
contentXPath = result.xpath('.//div[@class="sn_txt"]/div'
'//span[@class="sn_snip"]//text()')
if contentXPath is not None:
content = escape(' '.join(contentXPath))
# parse publishedDate
publishedDateXPath = result.xpath('.//div[@class="sn_txt"]/div//span[contains(@class,"sn_ST")]//span[contains(@class,"sn_tm")]//text()')
publishedDateXPath = result.xpath('.//div[@class="sn_txt"]/div'
'//span[contains(@class,"sn_ST")]'
'//span[contains(@class,"sn_tm")]'
'//text()')
if publishedDateXPath is not None:
publishedDate = escape(' '.join(publishedDateXPath))
@ -74,7 +78,8 @@ def response(resp):
timeNumbers = re.findall(r'\d+', publishedDate)
publishedDate = datetime.now()\
- timedelta(hours=int(timeNumbers[0]))
elif re.match("^[0-9]+ hour(s|), [0-9]+ minute(s|) ago$", publishedDate):
elif re.match("^[0-9]+ hour(s|),"
" [0-9]+ minute(s|) ago$", publishedDate):
timeNumbers = re.findall(r'\d+', publishedDate)
publishedDate = datetime.now()\
- timedelta(hours=int(timeNumbers[0]))\

View File

@ -22,10 +22,17 @@ api_key = None
# search-url
url = 'http://www.faroo.com/'
search_url = url + 'api?{query}&start={offset}&length={number_of_results}&l={language}&src={categorie}&i=false&f=json&key={api_key}'
search_url = url + 'api?{query}'\
'&start={offset}'\
'&length={number_of_results}'\
'&l={language}'\
'&src={categorie}'\
'&i=false'\
'&f=json'\
'&key={api_key}' # noqa
search_category = {'general': 'web',
'news': 'news'}
'news': 'news'}
# do search-request
@ -80,8 +87,8 @@ def response(resp):
# parse results
for result in search_res['results']:
if result['news']:
# timestamp (how many milliseconds have passed between now and the beginning of 1970)
publishedDate = datetime.datetime.fromtimestamp(result['date']/1000.0)
# timestamp (milliseconds since 1970)
publishedDate = datetime.datetime.fromtimestamp(result['date']/1000.0) # noqa
# append news result
results.append({'url': result['url'],

View File

@ -0,0 +1,89 @@
#!/usr/bin/env python
# Flickr (Images)
#
# @website https://www.flickr.com
# @provide-api yes (https://secure.flickr.com/services/api/flickr.photos.search.html)
#
# @using-api no
# @results HTML
# @stable no
# @parse url, title, thumbnail, img_src
from urllib import urlencode
from json import loads
import re
categories = ['images']
url = 'https://secure.flickr.com/'
search_url = url+'search/?{query}&page={page}'
photo_url = 'https://www.flickr.com/photos/{userid}/{photoid}'
regex = re.compile(r"\"search-photos-models\",\"photos\":(.*}),\"totalItems\":", re.DOTALL)
image_sizes = ('o', 'k', 'h', 'b', 'c', 'z', 'n', 'm', 't', 'q', 's')
paging = True
def build_flickr_url(user_id, photo_id):
return photo_url.format(userid=user_id, photoid=photo_id)
def request(query, params):
params['url'] = search_url.format(query=urlencode({'text': query}),
page=params['pageno'])
return params
def response(resp):
results = []
matches = regex.search(resp.text)
if matches is None:
return results
match = matches.group(1)
search_results = loads(match)
if '_data' not in search_results:
return []
photos = search_results['_data']
for photo in photos:
# In paged configuration, the first pages' photos are represented by a None object
if photo is None:
continue
img_src = None
# From the biggest to the lowest format
for image_size in image_sizes:
if image_size in photo['sizes']:
img_src = photo['sizes'][image_size]['displayUrl']
break
if not img_src:
continue
if 'id' not in photo['owner']:
continue
url = build_flickr_url(photo['owner']['id'], photo['id'])
title = photo['title']
content = '<span class="photo-author">' + photo['owner']['username'] + '</span><br />'
if 'description' in photo:
content = content + '<span class="description">' + photo['description'] + '</span>'
# append result
results.append({'url': url,
'title': title,
'img_src': img_src,
'content': content,
'template': 'images.html'})
return results

View File

@ -1,54 +1,80 @@
#!/usr/bin/env python
## Flickr (Images)
#
# @website https://www.flickr.com
# @provide-api yes (https://secure.flickr.com/services/api/flickr.photos.search.html)
#
# @using-api yes
# @results JSON
# @stable yes
# @parse url, title, thumbnail, img_src
#More info on api-key : https://www.flickr.com/services/apps/create/
from urllib import urlencode
#from json import loads
from urlparse import urljoin
from lxml import html
from time import time
from json import loads
categories = ['images']
url = 'https://secure.flickr.com/'
search_url = url+'search/?{query}&page={page}'
results_xpath = '//div[@class="view display-item-tile"]/figure/div'
nb_per_page = 15
paging = True
api_key= None
url = 'https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key={api_key}&{text}&sort=relevance&extras=description%2C+owner_name%2C+url_o%2C+url_z&per_page={nb_per_page}&format=json&nojsoncallback=1&page={page}'
photo_url = 'https://www.flickr.com/photos/{userid}/{photoid}'
paging = True
def build_flickr_url(user_id, photo_id):
return photo_url.format(userid=user_id,photoid=photo_id)
def request(query, params):
params['url'] = search_url.format(query=urlencode({'text': query}),
page=params['pageno'])
time_string = str(int(time())-3)
params['cookies']['BX'] = '3oqjr6d9nmpgl&b=3&s=dh'
params['cookies']['xb'] = '421409'
params['cookies']['localization'] = 'en-us'
params['cookies']['flrbp'] = time_string +\
'-3a8cdb85a427a33efda421fbda347b2eaf765a54'
params['cookies']['flrbs'] = time_string +\
'-ed142ae8765ee62c9ec92a9513665e0ee1ba6776'
params['cookies']['flrb'] = '9'
params['url'] = url.format(text=urlencode({'text': query}),
api_key=api_key,
nb_per_page=nb_per_page,
page=params['pageno'])
return params
def response(resp):
results = []
dom = html.fromstring(resp.text)
for result in dom.xpath(results_xpath):
img = result.xpath('.//img')
search_results = loads(resp.text)
if not img:
# return empty array if there are no results
if not 'photos' in search_results:
return []
if not 'photo' in search_results['photos']:
return []
photos = search_results['photos']['photo']
# parse results
for photo in photos:
if 'url_o' in photo:
img_src = photo['url_o']
elif 'url_z' in photo:
img_src = photo['url_z']
else:
continue
img = img[0]
img_src = 'https:'+img.attrib.get('src')
url = build_flickr_url(photo['owner'], photo['id'])
if not img_src:
continue
href = urljoin(url, result.xpath('.//a')[0].attrib.get('href'))
title = img.attrib.get('alt', '')
results.append({'url': href,
title = photo['title']
content = '<span class="photo-author">'+ photo['ownername'] +'</span><br />'
content = content + '<span class="description">' + photo['description']['_content'] + '</span>'
# append result
results.append({'url': url,
'title': title,
'img_src': img_src,
'content': content,
'template': 'images.html'})
# return results
return results

View File

@ -9,7 +9,7 @@
# @stable yes (but deprecated)
# @parse url, title, img_src
from urllib import urlencode,unquote
from urllib import urlencode, unquote
from json import loads
# engine dependent config

View File

@ -0,0 +1,87 @@
## Kickass Torrent (Videos, Music, Files)
#
# @website https://kickass.so
# @provide-api no (nothing found)
#
# @using-api no
# @results HTML (using search portal)
# @stable yes (HTML can change)
# @parse url, title, content, seed, leech, magnetlink
from urlparse import urljoin
from cgi import escape
from urllib import quote
from lxml import html
from operator import itemgetter
# engine dependent config
categories = ['videos', 'music', 'files']
paging = True
# search-url
url = 'https://kickass.so/'
search_url = url + 'search/{search_term}/{pageno}/'
# specific xpath variables
magnet_xpath = './/a[@title="Torrent magnet link"]'
#content_xpath = './/font[@class="detDesc"]//text()'
# do search-request
def request(query, params):
params['url'] = search_url.format(search_term=quote(query),
pageno=params['pageno'])
# FIX: SSLError: hostname 'kickass.so'
# doesn't match either of '*.kickass.to', 'kickass.to'
params['verify'] = False
return params
# get response from search-request
def response(resp):
results = []
dom = html.fromstring(resp.text)
search_res = dom.xpath('//table[@class="data"]//tr')
# return empty array if nothing is found
if not search_res:
return []
# parse results
for result in search_res[1:]:
link = result.xpath('.//a[@class="cellMainLink"]')[0]
href = urljoin(url, link.attrib['href'])
title = ' '.join(link.xpath('.//text()'))
content = escape(html.tostring(result.xpath('.//span[@class="font11px lightgrey block"]')[0], method="text"))
seed = result.xpath('.//td[contains(@class, "green")]/text()')[0]
leech = result.xpath('.//td[contains(@class, "red")]/text()')[0]
# convert seed to int if possible
if seed.isdigit():
seed = int(seed)
else:
seed = 0
# convert leech to int if possible
if leech.isdigit():
leech = int(leech)
else:
leech = 0
magnetlink = result.xpath(magnet_xpath)[0].attrib['href']
# append result
results.append({'url': href,
'title': title,
'content': content,
'seed': seed,
'leech': leech,
'magnetlink': magnetlink,
'template': 'torrent.html'})
# return results sorted by seeder
return sorted(results, key=itemgetter('seed'), reverse=True)

View File

@ -28,15 +28,17 @@ search_url = base_url + 'w/api.php?action=query'\
'&srprop=timestamp'\
'&format=json'\
'&sroffset={offset}'\
'&srlimit={limit}'
'&srlimit={limit}' # noqa
# do search-request
def request(query, params):
offset = (params['pageno'] - 1) * number_of_results
string_args = dict(query=urlencode({'srsearch': query}),
offset=offset,
limit=number_of_results)
offset=offset,
limit=number_of_results)
format_strings = list(Formatter().parse(base_url))
if params['language'] == 'all':
@ -67,7 +69,8 @@ def response(resp):
# parse results
for result in search_results['query']['search']:
url = base_url.format(language=resp.search_params['language']) + 'wiki/' + quote(result['title'].replace(' ', '_').encode('utf-8'))
url = base_url.format(language=resp.search_params['language']) +\
'wiki/' + quote(result['title'].replace(' ', '_').encode('utf-8'))
# append result
results.append({'url': url,

View File

@ -9,20 +9,24 @@
# @parse url, title
from json import loads
from searx.utils import searx_useragent
# engine dependent config
categories = ['map']
paging = False
# search-url
url = 'https://nominatim.openstreetmap.org/search/{query}?format=json&polygon_geojson=1&addressdetails=1'
base_url = 'https://nominatim.openstreetmap.org/'
search_string = 'search/{query}?format=json&polygon_geojson=1&addressdetails=1'
result_base_url = 'https://openstreetmap.org/{osm_type}/{osm_id}'
# do search-request
def request(query, params):
params['url'] = url.format(query=query)
params['url'] = base_url + search_string.format(query=query)
# using searx User-Agent
params['headers']['User-Agent'] = searx_useragent()
return params
@ -68,8 +72,8 @@ def response(resp):
address.update({'house_number': address_raw.get('house_number'),
'road': address_raw.get('road'),
'locality': address_raw.get('city',
address_raw.get('town',
address_raw.get('village'))),
address_raw.get('town', # noqa
address_raw.get('village'))), # noqa
'postcode': address_raw.get('postcode'),
'country': address_raw.get('country'),
'country_code': address_raw.get('country_code')})

View File

@ -0,0 +1,132 @@
## Photon (Map)
#
# @website https://photon.komoot.de
# @provide-api yes (https://photon.komoot.de/)
#
# @using-api yes
# @results JSON
# @stable yes
# @parse url, title
from urllib import urlencode
from json import loads
from searx.utils import searx_useragent
# engine dependent config
categories = ['map']
paging = False
language_support = True
number_of_results = 10
# search-url
base_url = 'https://photon.komoot.de/'
search_string = 'api/?{query}&limit={limit}'
result_base_url = 'https://openstreetmap.org/{osm_type}/{osm_id}'
# list of supported languages
allowed_languages = ['de', 'en', 'fr', 'it']
# do search-request
def request(query, params):
params['url'] = base_url +\
search_string.format(query=urlencode({'q': query}),
limit=number_of_results)
if params['language'] != 'all':
language = params['language'].split('_')[0]
if language in allowed_languages:
params['url'] = params['url'] + "&lang=" + language
# using searx User-Agent
params['headers']['User-Agent'] = searx_useragent()
# FIX: SSLError: SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
params['verify'] = False
return params
# get response from search-request
def response(resp):
results = []
json = loads(resp.text)
# parse results
for r in json.get('features', {}):
properties = r.get('properties')
if not properties:
continue
# get title
title = properties['name']
# get osm-type
if properties.get('osm_type') == 'N':
osm_type = 'node'
elif properties.get('osm_type') == 'W':
osm_type = 'way'
elif properties.get('osm_type') == 'R':
osm_type = 'relation'
else:
# continue if invalide osm-type
continue
url = result_base_url.format(osm_type=osm_type,
osm_id=properties.get('osm_id'))
osm = {'type': osm_type,
'id': properties.get('osm_id')}
geojson = r.get('geometry')
if properties.get('extent'):
boundingbox = [properties.get('extent')[3],
properties.get('extent')[1],
properties.get('extent')[0],
properties.get('extent')[2]]
else:
# TODO: better boundingbox calculation
boundingbox = [geojson['coordinates'][1],
geojson['coordinates'][1],
geojson['coordinates'][0],
geojson['coordinates'][0]]
# address calculation
address = {}
# get name
if properties.get('osm_key') == 'amenity' or\
properties.get('osm_key') == 'shop' or\
properties.get('osm_key') == 'tourism' or\
properties.get('osm_key') == 'leisure':
address = {'name': properties.get('name')}
# add rest of adressdata, if something is already found
if address.get('name'):
address.update({'house_number': properties.get('housenumber'),
'road': properties.get('street'),
'locality': properties.get('city',
properties.get('town', # noqa
properties.get('village'))), # noqa
'postcode': properties.get('postcode'),
'country': properties.get('country')})
else:
address = None
# append result
results.append({'template': 'map.html',
'title': title,
'content': '',
'longitude': geojson['coordinates'][0],
'latitude': geojson['coordinates'][1],
'boundingbox': boundingbox,
'geojson': geojson,
'address': address,
'osm': osm,
'url': url})
# return results
return results

View File

@ -0,0 +1,65 @@
## Searchcode (It)
#
# @website https://searchcode.com/
# @provide-api yes (https://searchcode.com/api/)
#
# @using-api yes
# @results JSON
# @stable yes
# @parse url, title, content
from urllib import urlencode
from json import loads
import cgi
import re
# engine dependent config
categories = ['it']
paging = True
# search-url
url = 'https://searchcode.com/'
search_url = url+'api/codesearch_I/?{query}&p={pageno}'
# do search-request
def request(query, params):
params['url'] = search_url.format(query=urlencode({'q': query}),
pageno=params['pageno']-1)
return params
# get response from search-request
def response(resp):
results = []
search_results = loads(resp.text)
# parse results
for result in search_results['results']:
href = result['url']
title = "" + result['name'] + " - " + result['filename']
content = result['repo'] + "<br />"
lines = dict()
for line, code in result['lines'].items():
lines[int(line)] = code
content = content + '<pre class="code-formatter"><table class="code">'
for line, code in sorted(lines.items()):
content = content + '<tr><td class="line-number" style="padding-right:5px;">'
content = content + str(line) + '</td><td class="code-snippet">'
# Replace every two spaces with ' &nbps;' to keep formatting while allowing the browser to break the line if necessary
content = content + cgi.escape(code).replace('\t', ' ').replace(' ', '&nbsp; ').replace(' ', ' &nbsp;')
content = content + "</td></tr>"
content = content + "</table></pre>"
# append result
results.append({'url': href,
'title': title,
'content': content})
# return results
return results

View File

@ -0,0 +1,49 @@
## Searchcode (It)
#
# @website https://searchcode.com/
# @provide-api yes (https://searchcode.com/api/)
#
# @using-api yes
# @results JSON
# @stable yes
# @parse url, title, content
from urllib import urlencode
from json import loads
# engine dependent config
categories = ['it']
paging = True
# search-url
url = 'https://searchcode.com/'
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)
return params
# get response from search-request
def response(resp):
results = []
search_results = loads(resp.text)
# parse results
for result in search_results['results']:
href = result['url']
title = "[" + result['type'] + "] " + result['namespace'] + " " + result['name']
content = '<span class="highlight">[' + result['type'] + "] " + result['name'] + " " + result['synopsis'] + "</span><br />" + result['description']
# append result
results.append({'url': href,
'title': title,
'content': content})
# return results
return results

View File

@ -20,7 +20,12 @@ guest_client_id = 'b45b1aa10f1ac2941910a7f0d10f8e28'
# search-url
url = 'https://api.soundcloud.com/'
search_url = url + 'search?{query}&facet=model&limit=20&offset={offset}&linked_partitioning=1&client_id={client_id}'
search_url = url + 'search?{query}'\
'&facet=model'\
'&limit=20'\
'&offset={offset}'\
'&linked_partitioning=1'\
'&client_id={client_id}' # noqa
# do search-request

View File

@ -0,0 +1,74 @@
## Subtitleseeker (Video)
#
# @website http://www.subtitleseeker.com
# @provide-api no
#
# @using-api no
# @results HTML
# @stable no (HTML can change)
# @parse url, title, content
from cgi import escape
from urllib import quote_plus
from lxml import html
from searx.languages import language_codes
# engine dependent config
categories = ['videos']
paging = True
language = ""
# search-url
url = 'http://www.subtitleseeker.com/'
search_url = url+'search/TITLES/{query}&p={pageno}'
# specific xpath variables
results_xpath = '//div[@class="boxRows"]'
# do search-request
def request(query, params):
params['url'] = search_url.format(query=quote_plus(query),
pageno=params['pageno'])
return params
# get response from search-request
def response(resp):
results = []
dom = html.fromstring(resp.text)
search_lang = ""
if resp.search_params['language'] != 'all':
search_lang = [lc[1]
for lc in language_codes
if lc[0][:2] == resp.search_params['language']][0]
# parse results
for result in dom.xpath(results_xpath):
link = result.xpath(".//a")[0]
href = link.attrib.get('href')
if language is not "":
href = href + language + '/'
elif search_lang:
href = href + search_lang + '/'
title = escape(link.xpath(".//text()")[0])
content = result.xpath('.//div[contains(@class,"red")]//text()')[0]
content = content + " - "
content = content + html.tostring(result.xpath('.//div[contains(@class,"grey-web")]')[0], method='text')
if result.xpath(".//span") != []:
content = content + " - (" + result.xpath(".//span//text()")[0].strip() + ")"
# append result
results.append({'url': href,
'title': title,
'content': escape(content)})
# return results
return results

View File

@ -24,7 +24,11 @@ number_of_results = 5
# search-url
base_url = 'http://localhost:8090'
search_url = '/yacysearch.json?{query}&startRecord={offset}&maximumRecords={limit}&contentdom={search_type}&resource=global'
search_url = '/yacysearch.json?{query}'\
'&startRecord={offset}'\
'&maximumRecords={limit}'\
'&contentdom={search_type}'\
'&resource=global' # noqa
# yacy specific type-definitions
search_types = {'general': 'text',
@ -39,10 +43,11 @@ def request(query, params):
offset = (params['pageno'] - 1) * number_of_results
search_type = search_types.get(params['category'], '0')
params['url'] = base_url + search_url.format(query=urlencode({'query': query}),
offset=offset,
limit=number_of_results,
search_type=search_type)
params['url'] = base_url +\
search_url.format(query=urlencode({'query': query}),
offset=offset,
limit=number_of_results,
search_type=search_type)
# add language tag if specified
if params['language'] != 'all':
@ -70,19 +75,19 @@ def response(resp):
# append result
results.append({'url': result['link'],
'title': result['title'],
'content': result['description'],
'publishedDate': publishedDate})
'title': result['title'],
'content': result['description'],
'publishedDate': publishedDate})
elif resp.search_params['category'] == 'images':
# parse image results
for result in search_results:
# append result
results.append({'url': result['url'],
'title': result['title'],
'content': '',
'img_src': result['image'],
'template': 'images.html'})
'title': result['title'],
'content': '',
'img_src': result['image'],
'template': 'images.html'})
#TODO parse video, audio and file results

View File

@ -20,7 +20,8 @@ paging = True
language_support = True
# search-url
search_url = 'https://search.yahoo.com/search?{query}&b={offset}&fl=1&vl=lang_{lang}'
base_url = 'https://search.yahoo.com/'
search_url = 'search?{query}&b={offset}&fl=1&vl=lang_{lang}'
# specific xpath variables
results_xpath = '//div[@class="res"]'
@ -57,9 +58,9 @@ def request(query, params):
else:
language = params['language'].split('_')[0]
params['url'] = search_url.format(offset=offset,
query=urlencode({'p': query}),
lang=language)
params['url'] = base_url + search_url.format(offset=offset,
query=urlencode({'p': query}),
lang=language)
# TODO required?
params['cookies']['sB'] = 'fl=1&vl=lang_{lang}&sh=1&rw=new&v=1'\

View File

@ -16,6 +16,7 @@ along with searx. If not, see < http://www.gnu.org/licenses/ >.
'''
import re
from urlparse import urlparse
from lxml import etree
from os import listdir
from os.path import isfile, isdir, join
@ -86,15 +87,23 @@ def load_single_https_ruleset(filepath):
# TODO hack, which convert a javascript regex group
# into a valid python regex group
rule_from = ruleset.attrib.get('from').replace('$', '\\')
rule_to = ruleset.attrib.get('to').replace('$', '\\')
rule_from = ruleset.attrib['from'].replace('$', '\\')
if rule_from.endswith('\\'):
rule_from = rule_from[:-1]+'$'
rule_to = ruleset.attrib['to'].replace('$', '\\')
if rule_to.endswith('\\'):
rule_to = rule_to[:-1]+'$'
# TODO, not working yet because of the hack above,
# currently doing that in webapp.py
# rule_from_rgx = re.compile(rule_from, re.I)
# append rule
rules.append((rule_from, rule_to))
try:
rules.append((re.compile(rule_from, re.I | re.U), rule_to))
except:
# TODO log regex error
continue
# this child define an exclusion
elif ruleset.tag == 'exclusion':
@ -143,3 +152,56 @@ def load_https_rules(rules_path):
https_rules.append(ruleset)
print(' * {n} https-rules loaded'.format(n=len(https_rules)))
def https_url_rewrite(result):
skip_https_rewrite = False
# check if HTTPS rewrite is possible
for target, rules, exclusions in https_rules:
# check if target regex match with url
if target.match(result['parsed_url'].netloc):
# process exclusions
for exclusion in exclusions:
# check if exclusion match with url
if exclusion.match(result['url']):
skip_https_rewrite = True
break
# skip https rewrite if required
if skip_https_rewrite:
break
# process rules
for rule in rules:
try:
new_result_url = rule[0].sub(rule[1], result['url'])
except:
break
# parse new url
new_parsed_url = urlparse(new_result_url)
# continiue if nothing was rewritten
if result['url'] == new_result_url:
continue
# get domainname from result
# TODO, does only work correct with TLD's like
# asdf.com, not for asdf.com.de
# TODO, using publicsuffix instead of this rewrite rule
old_result_domainname = '.'.join(
result['parsed_url'].hostname.split('.')[-2:])
new_result_domainname = '.'.join(
new_parsed_url.hostname.split('.')[-2:])
# check if rewritten hostname is the same,
# to protect against wrong or malicious rewrite rules
if old_result_domainname == new_result_domainname:
# set new url
result['url'] = new_result_url
# target has matched, do not search over the other rules
break
return result

View File

@ -89,7 +89,7 @@
<rule from="^http://([aiw]\d|api|wis)\.sndcdn\.com/"
to="https://$1.sndcdn.com/" />
<rule from="^http://((?:api|backstage|blog|connect|developers|ec-media|eventlogger|help-assets|media|visuals|w|www)\.)?soundcloud\.com/"
<rule from="^http://((?:api|backstage|blog|connect|developers|ec-media|eventlogger|help-assets|media|visuals|w|www)\.|)soundcloud\.com/"
to="https://$1soundcloud.com/" />
<rule from="^https?://scbackstage\.wpengine\.netdna-cdn\.com/"

View File

@ -19,8 +19,9 @@ import requests as requests_lib
import threading
import re
from itertools import izip_longest, chain
from datetime import datetime
from operator import itemgetter
from Queue import Queue
from time import time
from urlparse import urlparse, unquote
from searx.engines import (
categories, engines
@ -33,82 +34,74 @@ from searx.query import Query
number_of_searches = 0
def search_request_wrapper(fn, url, engine_name, **kwargs):
try:
return fn(url, **kwargs)
except Exception, e:
# increase errors stats
engines[engine_name].stats['errors'] += 1
# print engine name and specific error message
print('[E] Error with engine "{0}":\n\t{1}'.format(
engine_name, str(e)))
return
def threaded_requests(requests):
for fn, url, request_args in requests:
timeout_limit = max(r[2]['timeout'] for r in requests)
search_start = time()
for fn, url, request_args, engine_name in requests:
request_args['timeout'] = timeout_limit
th = threading.Thread(
target=fn,
args=(url,),
target=search_request_wrapper,
args=(fn, url, engine_name),
kwargs=request_args,
name='search_request',
)
th._engine_name = engine_name
th.start()
for th in threading.enumerate():
if th.name == 'search_request':
th.join()
remaining_time = max(0.0, timeout_limit - (time() - search_start))
th.join(remaining_time)
if th.isAlive():
print('engine timeout: {0}'.format(th._engine_name))
# get default reqest parameter
def default_request_params():
return {
'method': 'GET', 'headers': {}, 'data': {}, 'url': '', 'cookies': {}}
'method': 'GET', 'headers': {}, 'data': {}, 'url': '', 'cookies': {}, 'verify': True}
# create a callback wrapper for the search engine results
def make_callback(engine_name,
results,
suggestions,
answers,
infoboxes,
callback,
params):
def make_callback(engine_name, results_queue, callback, params):
# creating a callback wrapper for the search engine results
def process_callback(response, **kwargs):
cb_res = []
response.search_params = params
# callback
try:
search_results = callback(response)
except Exception, e:
# increase errors stats
timeout_overhead = 0.2 # seconds
search_duration = time() - params['started']
timeout_limit = engines[engine_name].timeout + timeout_overhead
if search_duration > timeout_limit:
engines[engine_name].stats['page_load_time'] += timeout_limit
engines[engine_name].stats['errors'] += 1
results[engine_name] = cb_res
# print engine name and specific error message
print '[E] Error with engine "{0}":\n\t{1}'.format(
engine_name, str(e))
return
# callback
search_results = callback(response)
# add results
for result in search_results:
result['engine'] = engine_name
# if it is a suggestion, add it to list of suggestions
if 'suggestion' in result:
# TODO type checks
suggestions.add(result['suggestion'])
continue
# if it is an answer, add it to list of answers
if 'answer' in result:
answers.add(result['answer'])
continue
# if it is an infobox, add it to list of infoboxes
if 'infobox' in result:
infoboxes.append(result)
continue
# append result
cb_res.append(result)
results[engine_name] = cb_res
results_queue.put_nowait((engine_name, search_results))
# update stats with current page-load-time
engines[engine_name].stats['page_load_time'] += \
(datetime.now() - params['started']).total_seconds()
engines[engine_name].stats['page_load_time'] += search_duration
return process_callback
@ -420,6 +413,7 @@ class Search(object):
# init vars
requests = []
results_queue = Queue()
results = {}
suggestions = set()
answers = set()
@ -452,14 +446,13 @@ class Search(object):
request_params = default_request_params()
request_params['headers']['User-Agent'] = user_agent
request_params['category'] = selected_engine['category']
request_params['started'] = datetime.now()
request_params['started'] = time()
request_params['pageno'] = self.pageno
request_params['language'] = self.lang
# update request parameters dependent on
# search-engine (contained in engines folder)
request_params = engine.request(self.query.encode('utf-8'),
request_params)
engine.request(self.query.encode('utf-8'), request_params)
if request_params['url'] is None:
# TODO add support of offline engines
@ -468,13 +461,9 @@ class Search(object):
# create a callback wrapper for the search engine results
callback = make_callback(
selected_engine['name'],
results,
suggestions,
answers,
infoboxes,
results_queue,
engine.response,
request_params
)
request_params)
# create dictionary which contain all
# informations about the request
@ -482,7 +471,8 @@ class Search(object):
headers=request_params['headers'],
hooks=dict(response=callback),
cookies=request_params['cookies'],
timeout=engine.timeout
timeout=engine.timeout,
verify=request_params['verify']
)
# specific type of request (GET or POST)
@ -497,11 +487,34 @@ class Search(object):
continue
# append request to list
requests.append((req, request_params['url'], request_args))
requests.append((req, request_params['url'], request_args, selected_engine['name']))
if not requests:
return results, suggestions, answers, infoboxes
# send all search-request
threaded_requests(requests)
while not results_queue.empty():
engine_name, engine_results = results_queue.get_nowait()
# TODO type checks
[suggestions.add(x['suggestion'])
for x in list(engine_results)
if 'suggestion' in x
and engine_results.remove(x) is None]
[answers.add(x['answer'])
for x in list(engine_results)
if 'answer' in x
and engine_results.remove(x) is None]
infoboxes.extend(x for x in list(engine_results)
if 'infobox' in x
and engine_results.remove(x) is None)
results[engine_name] = engine_results
# update engine-specific stats
for engine_name, engine_results in results.items():
engines[engine_name].stats['search_count'] += 1

View File

@ -1,7 +1,7 @@
server:
port : 8888
secret_key : "ultrasecretkey" # change this!
debug : True # Debug mode, only for development
debug : False # Debug mode, only for development
request_timeout : 2.0 # seconds
base_url : False # Set custom base_url. Possible values: False or "https://your.custom.host/location/"
themes_path : "" # Custom ui themes path
@ -64,12 +64,20 @@ engines:
# engine : filecrop
# categories : files
# shortcut : fc
- name : 500px
engine : 500px
shortcut : px
- name : flickr
engine : flickr
categories : images
shortcut : fl
timeout: 3.0
# You can use the engine using the official stable API, but you need an API key
# See : https://www.flickr.com/services/apps/create/
# engine : flickr
# api_key: 'apikey' # required!
# Or you can use the html non-stable engine, activated by default
engine : flickr-noapi
- name : general-file
engine : generalfile
@ -95,10 +103,18 @@ engines:
engine : openstreetmap
shortcut : osm
- name : photon
engine : photon
shortcut : ph
# - name : piratebay
# engine : piratebay
# shortcut : tpb
- name : kickass
engine : kickass
shortcut : ka
- name : soundcloud
engine : soundcloud
shortcut : sc
@ -106,6 +122,21 @@ engines:
- name : stackoverflow
engine : stackoverflow
shortcut : st
- name : searchcode doc
engine : searchcode_doc
shortcut : scd
- name : searchcode code
engine : searchcode_code
shortcut : scc
- name : subtitleseeker
engine : subtitleseeker
shortcut : ss
# The language is an option. You can put any language written in english
# Examples : English, French, German, Hungarian, Chinese...
# language : English
- name : startpage
engine : startpage

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -1,2 +1,2 @@
/*! oscar/searx.min.js | 30-11-2014 | https://github.com/asciimoo/searx */
requirejs.config({baseUrl:"/static/oscar/js",paths:{app:"../app"}}),searx.autocompleter&&(searx.searchResults=new Bloodhound({datumTokenizer:Bloodhound.tokenizers.obj.whitespace("value"),queryTokenizer:Bloodhound.tokenizers.whitespace,remote:"/autocompleter?q=%QUERY"}),searx.searchResults.initialize()),$(document).ready(function(){searx.autocompleter&&$("#q").typeahead(null,{name:"search-results",displayKey:function(a){return a},source:searx.searchResults.ttAdapter()})}),$(document).ready(function(){$("#q.autofocus").focus(),$(".select-all-on-click").click(function(){$(this).select()}),$(".btn-collapse").click(function(){var a=$(this).data("btn-text-collapsed"),b=$(this).data("btn-text-not-collapsed");""!==a&&""!==b&&(new_html=$(this).hasClass("collapsed")?$(this).html().replace(a,b):$(this).html().replace(b,a),$(this).html(new_html))}),$(".btn-toggle .btn").click(function(){var a="btn-"+$(this).data("btn-class"),b=$(this).data("btn-label-default"),c=$(this).data("btn-label-toggled");""!==c&&(new_html=$(this).hasClass("btn-default")?$(this).html().replace(b,c):$(this).html().replace(c,b),$(this).html(new_html)),$(this).toggleClass(a),$(this).toggleClass("btn-default")})}),$(document).ready(function(){$(".searx_overpass_request").on("click",function(a){var b="https://overpass-api.de/api/interpreter?data=",c=b+"[out:json][timeout:25];(",d=");out meta;",e=$(this).data("osm-id"),f=$(this).data("osm-type"),g=$(this).data("result-table"),h="#"+$(this).data("result-table-loadicon"),i=["addr:city","addr:country","addr:housenumber","addr:postcode","addr:street"];if(e&&f&&g){g="#"+g;var j=null;switch(f){case"node":j=c+"node("+e+");"+d;break;case"way":j=c+"way("+e+");"+d;break;case"relation":j=c+"relation("+e+");"+d}if(j){$.ajax(j).done(function(a){if(a&&a.elements&&a.elements[0]){var b=a.elements[0],c=$(g).html();for(var d in b.tags)if(null===b.tags.name||-1==i.indexOf(d)){switch(c+="<tr><td>"+d+"</td><td>",d){case"phone":case"fax":c+='<a href="tel:'+b.tags[d].replace(/ /g,"")+'">'+b.tags[d]+"</a>";break;case"email":c+='<a href="mailto:'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"website":case"url":c+='<a href="'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikidata":c+='<a href="https://www.wikidata.org/wiki/'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikipedia":if(-1!=b.tags[d].indexOf(":")){c+='<a href="https://'+b.tags[d].substring(0,b.tags[d].indexOf(":"))+".wikipedia.org/wiki/"+b.tags[d].substring(b.tags[d].indexOf(":")+1)+'">'+b.tags[d]+"</a>";break}default:c+=b.tags[d]}c+="</td></tr>"}$(g).html(c),$(g).removeClass("hidden"),$(h).addClass("hidden")}}).fail(function(){$(h).html($(h).html()+'<p class="text-muted">could not load data!</p>')})}}$(this).off(a)}),$(".searx_init_map").on("click",function(a){var b=$(this).data("leaflet-target"),c=$(this).data("map-lon"),d=$(this).data("map-lat"),e=$(this).data("map-zoom"),f=$(this).data("map-boundingbox"),g=$(this).data("map-geojson");require(["leaflet-0.7.3.min"],function(){f&&(southWest=L.latLng(f[0],f[2]),northEast=L.latLng(f[1],f[3]),map_bounds=L.latLngBounds(southWest,northEast)),L.Icon.Default.imagePath="/static/oscar/img/map";{var a=L.map(b),h="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",i='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',j=new L.TileLayer(h,{minZoom:1,maxZoom:19,attribution:i}),k="http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg",l='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors | Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">',m=new L.TileLayer(k,{minZoom:1,maxZoom:18,subdomains:"1234",attribution:l}),n="http://otile{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg",o='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors | Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="https://developer.mapquest.com/content/osm/mq_logo.png"> | Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency';new L.TileLayer(n,{minZoom:1,maxZoom:11,subdomains:"1234",attribution:o})}map_bounds?setTimeout(function(){a.fitBounds(map_bounds,{maxZoom:17})},0):c&&d&&(e?a.setView(new L.LatLng(d,c),e):a.setView(new L.LatLng(d,c),8)),a.addLayer(m);var p={"OSM Mapnik":j,MapQuest:m};L.control.layers(p).addTo(a),g&&L.geoJson(g).addTo(a)}),$(this).off(a)})});
/*! oscar/searx.min.js | 19-12-2014 | https://github.com/asciimoo/searx */
requirejs.config({baseUrl:"./static/oscar/js",paths:{app:"../app"}}),searx.autocompleter&&(searx.searchResults=new Bloodhound({datumTokenizer:Bloodhound.tokenizers.obj.whitespace("value"),queryTokenizer:Bloodhound.tokenizers.whitespace,remote:"/autocompleter?q=%QUERY"}),searx.searchResults.initialize()),$(document).ready(function(){searx.autocompleter&&$("#q").typeahead(null,{name:"search-results",displayKey:function(a){return a},source:searx.searchResults.ttAdapter()})}),$(document).ready(function(){$("#q.autofocus").focus(),$(".select-all-on-click").click(function(){$(this).select()}),$(".btn-collapse").click(function(){var a=$(this).data("btn-text-collapsed"),b=$(this).data("btn-text-not-collapsed");""!==a&&""!==b&&(new_html=$(this).hasClass("collapsed")?$(this).html().replace(a,b):$(this).html().replace(b,a),$(this).html(new_html))}),$(".btn-toggle .btn").click(function(){var a="btn-"+$(this).data("btn-class"),b=$(this).data("btn-label-default"),c=$(this).data("btn-label-toggled");""!==c&&(new_html=$(this).hasClass("btn-default")?$(this).html().replace(b,c):$(this).html().replace(c,b),$(this).html(new_html)),$(this).toggleClass(a),$(this).toggleClass("btn-default")}),$(".btn-sm").dblclick(function(){var a="btn-"+$(this).data("btn-class");$(this).hasClass("btn-default")?($(".btn-sm > input").attr("checked","checked"),$(".btn-sm > input").prop("checked",!0),$(".btn-sm").addClass(a),$(".btn-sm").addClass("active"),$(".btn-sm").removeClass("btn-default")):($(".btn-sm > input").attr("checked",""),$(".btn-sm > input").removeAttr("checked"),$(".btn-sm > input").checked=!1,$(".btn-sm").removeClass(a),$(".btn-sm").removeClass("active"),$(".btn-sm").addClass("btn-default"))})}),$(document).ready(function(){$(".searx_overpass_request").on("click",function(a){var b="https://overpass-api.de/api/interpreter?data=",c=b+"[out:json][timeout:25];(",d=");out meta;",e=$(this).data("osm-id"),f=$(this).data("osm-type"),g=$(this).data("result-table"),h="#"+$(this).data("result-table-loadicon"),i=["addr:city","addr:country","addr:housenumber","addr:postcode","addr:street"];if(e&&f&&g){g="#"+g;var j=null;switch(f){case"node":j=c+"node("+e+");"+d;break;case"way":j=c+"way("+e+");"+d;break;case"relation":j=c+"relation("+e+");"+d}if(j){$.ajax(j).done(function(a){if(a&&a.elements&&a.elements[0]){var b=a.elements[0],c=$(g).html();for(var d in b.tags)if(null===b.tags.name||-1==i.indexOf(d)){switch(c+="<tr><td>"+d+"</td><td>",d){case"phone":case"fax":c+='<a href="tel:'+b.tags[d].replace(/ /g,"")+'">'+b.tags[d]+"</a>";break;case"email":c+='<a href="mailto:'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"website":case"url":c+='<a href="'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikidata":c+='<a href="https://www.wikidata.org/wiki/'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikipedia":if(-1!=b.tags[d].indexOf(":")){c+='<a href="https://'+b.tags[d].substring(0,b.tags[d].indexOf(":"))+".wikipedia.org/wiki/"+b.tags[d].substring(b.tags[d].indexOf(":")+1)+'">'+b.tags[d]+"</a>";break}default:c+=b.tags[d]}c+="</td></tr>"}$(g).html(c),$(g).removeClass("hidden"),$(h).addClass("hidden")}}).fail(function(){$(h).html($(h).html()+'<p class="text-muted">could not load data!</p>')})}}$(this).off(a)}),$(".searx_init_map").on("click",function(a){var b=$(this).data("leaflet-target"),c=$(this).data("map-lon"),d=$(this).data("map-lat"),e=$(this).data("map-zoom"),f=$(this).data("map-boundingbox"),g=$(this).data("map-geojson");require(["leaflet-0.7.3.min"],function(){f&&(southWest=L.latLng(f[0],f[2]),northEast=L.latLng(f[1],f[3]),map_bounds=L.latLngBounds(southWest,northEast)),L.Icon.Default.imagePath="./static/oscar/img/map";{var a=L.map(b),h="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",i='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',j=new L.TileLayer(h,{minZoom:1,maxZoom:19,attribution:i}),k="http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg",l='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors | Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">',m=new L.TileLayer(k,{minZoom:1,maxZoom:18,subdomains:"1234",attribution:l}),n="http://otile{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg",o='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors | Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="https://developer.mapquest.com/content/osm/mq_logo.png"> | Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency';new L.TileLayer(n,{minZoom:1,maxZoom:11,subdomains:"1234",attribution:o})}map_bounds?setTimeout(function(){a.fitBounds(map_bounds,{maxZoom:17})},0):c&&d&&(e?a.setView(new L.LatLng(d,c),e):a.setView(new L.LatLng(d,c),8)),a.addLayer(m);var p={"OSM Mapnik":j,MapQuest:m};L.control.layers(p).addTo(a),g&&L.geoJson(g).addTo(a)}),$(this).off(a)})});

View File

@ -16,7 +16,7 @@
*/
requirejs.config({
baseUrl: '/static/oscar/js',
baseUrl: './static/oscar/js',
paths: {
app: '../app'
}

View File

@ -63,4 +63,25 @@ $(document).ready(function(){
$(this).toggleClass(btnClass);
$(this).toggleClass('btn-default');
});
/**
* Select or deselect every categories on double clic
*/
$(".btn-sm").dblclick(function() {
var btnClass = 'btn-' + $(this).data('btn-class'); // primary
if($(this).hasClass('btn-default')) {
$(".btn-sm > input").attr('checked', 'checked');
$(".btn-sm > input").prop("checked", true);
$(".btn-sm").addClass(btnClass);
$(".btn-sm").addClass('active');
$(".btn-sm").removeClass('btn-default');
} else {
$(".btn-sm > input").attr('checked', '');
$(".btn-sm > input").removeAttr('checked');
$(".btn-sm > input").checked = false;
$(".btn-sm").removeClass(btnClass);
$(".btn-sm").removeClass('active');
$(".btn-sm").addClass('btn-default');
}
});
});

View File

@ -116,7 +116,7 @@ $(document).ready(function(){
// TODO hack
// change default imagePath
L.Icon.Default.imagePath = "/static/oscar/img/map";
L.Icon.Default.imagePath = "./static/oscar/img/map";
// init map
var map = L.map(leaflet_target);

View File

@ -1,7 +1,7 @@
<div class="result {{ result.class }}">
{% if result['favicon'] %}
<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result['favicon']}}.ico" />
{% if "icon_"~result.engine~".ico" in favicons %}
<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result.engine}}.ico" alt="{{result.engine}}" />
{% endif %}
<div>

View File

@ -1,6 +1,6 @@
<div class="image_result">
<p>
<a href="{{ result.img_src }}"><img src="{{ result.img_src }}" title={{ result.title }}/></a>
<a href="{{ result.img_src }}"><img src="{{ result.img_src }}" title="{{ result.title|striptags }}" alt="{{ result.title|striptags }}"/></a>
<span class="url"><a href="{{ result.url }}" class="small_font">original context</a></span>
</p>
</div>

View File

@ -1,7 +1,7 @@
<div class="result {{ result.class }}">
{% if result['favicon'] %}
<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result['favicon']}}.ico" />
{% if "icon_"~result.engine~".ico" in favicons %}
<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result.engine}}.ico" alt="{{result.engine}}" />
{% endif %}
<div>

View File

@ -1,12 +1,10 @@
<div class="result">
{% if result['favicon'] %}
<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result['favicon']}}.ico" />
{% if "icon_"~result.engine~".ico" in favicons %}
<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result.engine}}.ico" alt="{{result.engine}}" />
{% endif %}
<p>
<h3 class="result_title"><a href="{{ result.url }}">{{ result.title|safe }}</a></h3>
{% if result.publishedDate %}<p class="published_date">{{ result.publishedDate }}</p>{% endif %}
<a href="{{ result.url }}"><img width="400px" src="{{ result.thumbnail }}" title={{ result.title }} alt=" {{ result.title }}"/></a>
<a href="{{ result.url }}"><img width="400" src="{{ result.thumbnail }}" title="{{ result.title|striptags }}" alt="{{ result.title|striptags }}"/></a>
<p class="url">{{ result.url }}</p>
</p>
</div>

View File

@ -10,7 +10,7 @@
<div id="search_url">
{{ _('Search URL') }}:
<input type="text" value="{{ base_url }}?q={{ q|urlencode }}&pageno={{ pageno }}{% if selected_categories %}&category_{{ selected_categories|join("&category_") }}{% endif %}" readonly="" />
<input type="text" value="{{ base_url }}?q={{ q|urlencode }}&amp;pageno={{ pageno }}{% if selected_categories %}&amp;category_{{ selected_categories|join("&category_")|replace(' ','+') }}{% endif %}" readonly />
</div>
<div id="apis">
{{ _('Download results') }}
@ -43,9 +43,9 @@
{% for result in results %}
{% if result['template'] %}
{% include 'default/result_templates/'+result['template'] %}
{% include 'courgette/result_templates/'+result['template'] %}
{% else %}
{% include 'default/result_templates/default.html' %}
{% include 'courgette/result_templates/default.html' %}
{% endif %}
{% endfor %}

View File

@ -1,6 +1,6 @@
<div class="infobox">
<h2>{{ infobox.infobox }}</h2>
{% if infobox.img_src %}<img src="{{ infobox.img_src }}" />{% endif %}
{% if infobox.img_src %}<img src="{{ infobox.img_src }}" title="{{ infobox.infobox|striptags }}" alt="{{ infobox.infobox|striptags }}" />{% endif %}
<p>{{ infobox.entity }}</p>
<p>{{ infobox.content | safe }}</p>
{% if infobox.attributes %}

View File

@ -1,5 +1,5 @@
<div class="result {{ result.class }}">
<h3 class="result_title"> {% if result['favicon'] %}<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result['favicon']}}.ico" />{% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h3>
<h3 class="result_title">{% if "icon_"~result.engine~".ico" in favicons %}<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result.engine}}.ico" alt="{{result.engine}}" />{% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h3>
<p class="url">{{ result.pretty_url }} <a class="cache_link" href="https://web.archive.org/web/{{ result.url }}">cached</a></p>
{% if result.publishedDate %}<p class="published_date">{{ result.publishedDate }}</p>{% endif %}
<p class="content">{% if result.img_src %}<img src="{{ result.img_src }}" class="image" />{% endif %}{% if result.content %}{{ result.content|safe }}<br class="last"/>{% endif %}</p>

View File

@ -1,6 +1,6 @@
<div class="image_result">
<p>
<a href="{{ result.img_src }}"><img src="{{ result.img_src }}" title="{{ result.title }}"/></a>
<a href="{{ result.img_src }}"><img src="{{ result.img_src }}" title="{{ result.title|striptags }}" alt="{{ result.title|striptags }}" /></a>
<span class="url"><a href="{{ result.url }}" class="small_font">original context</a></span>
</p>
</div>

View File

@ -1,7 +1,7 @@
<div class="result {{ result.class }}">
{% if result['favicon'] %}
<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result['favicon']}}.ico" />
{% if "icon_"~result.engine~".ico" in favicons %}
<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result.engine}}.ico" alt="{{result.engine}}" />
{% endif %}
<div>

View File

@ -1,7 +1,6 @@
<div class="result torrent_result">
<h3 class="result_title"><a href="{{ result.url }}">{{ result.title|safe }}</a></h3>
{% if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif %}
<p class="stats">Seed: {{ result.seed }}, Leech: {{ result.leech }}</p>
<p><a href="{{ result.magnetlink }}" class="magnetlink">magnet link</a></p>
<p class="url">{{ result.pretty_url }}</p>
{% if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif %}
<p><a href="{{ result.magnetlink }}" class="magnetlink">magnet link</a> - <span class="stats">Seed: {{ result.seed }}, Leech: {{ result.leech }}</span></p>
</div>

View File

@ -1,8 +1,6 @@
<div class="result">
<p>
<h3 class="result_title"> {% if result['favicon'] %}<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result['favicon']}}.ico" />{% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h3>
<h3 class="result_title">{% if "icon_"~result.engine~".ico" in favicons %}<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result.engine}}.ico" alt="{{result.engine}}" />{% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h3>
{% if result.publishedDate %}<p class="published_date">{{ result.publishedDate }}</p>{% endif %}
<a href="{{ result.url }}"><img class="thumbnail" src="{{ result.thumbnail }}" title={{ result.title }} alt=" {{ result.title }}"/></a>
<a href="{{ result.url }}"><img class="thumbnail" src="{{ result.thumbnail }}" title="{{ result.title|striptags }}" alt="{{ result.title|striptags }}"/></a>
<p class="url">{{ result.url }}</p>
</p>
</div>

View File

@ -10,7 +10,7 @@
<div id="search_url">
{{ _('Search URL') }}:
<input type="text" value="{{ base_url }}?q={{ q|urlencode }}&pageno={{ pageno }}{% if selected_categories %}&category_{{ selected_categories|join("&category_") }}{% endif %}" readonly="" />
<input type="text" value="{{ base_url }}?q={{ q|urlencode }}&amp;pageno={{ pageno }}{% if selected_categories %}&amp;category_{{ selected_categories|join("&category_")|replace(' ','+') }}{% endif %}" readonly />
</div>
<div id="apis">
{{ _('Download results') }}

View File

@ -1,6 +1,6 @@
{% from 'oscar/macros.html' import icon %}
<h4 class="result_header">{% if result['favicon'] %}<img width="32" height="32" class="favicon" src="static/{{ theme }}/img/icons/{{ result['favicon'] }}.png" alt="{{ result['favicon'] }}" /> {% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h4>
<h4 class="result_header">{% if result.engine~".png" in favicons %}<img width="32" height="32" class="favicon" src="static/{{ theme }}/img/icons/{{ result.engine }}.png" alt="{{ result.engine }}" /> {% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h4>
{% if result.publishedDate %}<time class="text-muted" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time>{% endif %}
<small><a class="text-info" href="https://web.archive.org/web/{{ result.url }}">{{ icon('link') }} {{ _('cached') }}</a></small>

View File

@ -7,7 +7,7 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<h4 class="modal-title">{% if result['favicon'] %}<img width="32" height="32" class="favicon" src="static/{{ theme }}/img/icons/{{ result['favicon'] }}.png" alt="{{ result['favicon'] }}" /> {% endif %}{{ result.title|striptags }}</h4>
<h4 class="modal-title">{% if result.engine~".png" in favicons %}<img width="32" height="32" class="favicon" src="static/{{ theme }}/img/icons/{{ result.engine }}.png" alt="{{ result.engine }}" /> {% endif %}{{ result.title|striptags }}</h4>
</div>
<div class="modal-body">
<img class="img-responsive center-block" src="{{ result.img_src }}" alt="{{ result.title }}">

View File

@ -1,6 +1,6 @@
{% from 'oscar/macros.html' import icon %}
<h4 class="result_header">{% if result['favicon'] %}<img width="32" height="32" class="favicon" src="static/{{ theme }}/img/icons/{{ result['favicon'] }}.png" alt="{{ result['favicon'] }}" /> {% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h4>
<h4 class="result_header">{% if result.engine~".png" in favicons %}<img width="32" height="32" class="favicon" src="static/{{ theme }}/img/icons/{{ result.engine }}.png" alt="{{ result.engine }}" /> {% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h4>
{% if result.publishedDate %}<time class="text-muted" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time>{% endif %}

View File

@ -1,6 +1,6 @@
{% from 'oscar/macros.html' import icon %}
<h4 class="result_header">{% if result['favicon'] %}<img width="32" height="32" class="favicon" src="static/{{ theme }}/img/icons/{{ result['favicon'] }}.png" alt="{{ result['favicon'] }}" /> {% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h4>
<h4 class="result_header">{% if result.engine~".png" in favicons %}<img width="32" height="32" class="favicon" src="static/{{ theme }}/img/icons/{{ result.engine }}.png" alt="{{ result.engine }}" /> {% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h4>
{% if result.publishedDate %}<time class="text-muted" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time>{% endif %}
<small><a class="text-info" href="https://web.archive.org/web/{{ result.url }}">{{ icon('link') }} {{ _('cached') }}</a></small>

View File

@ -1,13 +1,13 @@
{% from 'oscar/macros.html' import icon %}
<h4 class="result_header">{% if result['favicon'] %}<img width="32" height="32" class="favicon" src="static/{{ theme }}/img/icons/{{ result['favicon'] }}.png" alt="{{ result['favicon'] }}" /> {% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h4>
<h4 class="result_header">{% if result.engine~".png" in favicons %}<img width="32" height="32" class="favicon" src="static/{{ theme }}/img/icons/{{ result.engine }}.png" alt="{{ result.engine }}" /> {% endif %}<a href="{{ result.url }}">{{ result.title|safe }}</a></h4>
{% if result.publishedDate %}<time class="text-muted" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time>{% endif %}
<small><a class="text-info" href="https://web.archive.org/web/{{ result.url }}">{{ icon('link') }} {{ _('cached') }}</a></small>
<div class="container-fluid">
<div class="row">
<img class="thumbnail col-xs-6 col-sm-4 col-md-4 result-content" src="{{ result.thumbnail|safe }}" alt="{{ result.title|urlencode }} {{ result['favicon'] }}" />
<a href="{{ result.url }}"><img class="thumbnail col-xs-6 col-sm-4 col-md-4 result-content" src="{{ result.thumbnail|safe }}" alt="{{ result.title|striptags }} {{ result.engine }}" /></a>
{% if result.content %}<p class="col-xs-12 col-sm-8 col-md-8 result-content">{{ result.content|safe }}</p>{% endif %}
</div>
</div>

View File

@ -49,7 +49,7 @@ class ViewsTestCase(SearxTestCase):
)
result = self.app.post('/', data={'q': 'test'})
self.assertIn(
'<h3 class="result_title"> <img width="14" height="14" class="favicon" src="static/default/img/icon_youtube.ico" /><a href="http://first.test.xyz">First <span class="highlight">Test</span></a></h3>', # noqa
'<h3 class="result_title"><img width="14" height="14" class="favicon" src="static/default/img/icon_youtube.ico" alt="youtube" /><a href="http://second.test.xyz">Second <span class="highlight">Test</span></a></h3>', # noqa
result.data
)
self.assertIn(

View File

@ -1,25 +1,28 @@
# English translations for .
# English translations for PROJECT.
# Copyright (C) 2014 ORGANIZATION
# This file is distributed under the same license as the project.
#
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
# pointhi, 2014
# pointhi, 2014
# rike, 2014
# stf <stefan.marsiske@gmail.com>, 2014
# stf <stefan.marsiske@gmail.com>, 2014
# rike, 2014
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2014-11-26 20:41+0100\n"
"PO-Revision-Date: 2014-03-15 18:40+0000\n"
"Last-Translator: pointhi\n"
"Language-Team: German "
"(http://www.transifex.com/projects/p/searx/language/de/)\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"PO-Revision-Date: 2014-12-25 10:01+0000\n"
"Last-Translator: Adam Tauber <asciimoo@gmail.com>\n"
"Language-Team: German (http://www.transifex.com/projects/p/searx/language/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: searx/webapp.py:308
msgid "{minutes} minute(s) ago"
@ -143,11 +146,9 @@ msgstr "Blockieren"
#: searx/templates/default/preferences.html:94
#: searx/templates/oscar/preferences.html:132
msgid ""
"These settings are stored in your cookies, this allows us not to store "
"this data about you."
msgstr ""
"Diese Informationen werden in Cookies auf Ihrem Rechner gespeichert, "
"damit wir keine Ihrer persönlichen Daten speichern müssen."
"These settings are stored in your cookies, this allows us not to store this "
"data about you."
msgstr "Diese Informationen werden in Cookies auf Ihrem Rechner gespeichert, damit wir keine Ihrer persönlichen Daten speichern müssen."
#: searx/templates/courgette/preferences.html:94
#: searx/templates/default/preferences.html:96
@ -155,9 +156,7 @@ msgstr ""
msgid ""
"These cookies serve your sole convenience, we don't use these cookies to "
"track you."
msgstr ""
"Diese Cookies dienen einzig Ihrem Komfort, wir verwenden sie nicht, um "
"Sie zu überwachen."
msgstr "Diese Cookies dienen einzig Ihrem Komfort, wir verwenden sie nicht, um Sie zu überwachen."
#: searx/templates/courgette/preferences.html:97
#: searx/templates/default/preferences.html:99
@ -214,35 +213,35 @@ msgstr "Suchmaschinenstatistik"
#: searx/templates/default/categories.html:8
msgid "Click on the magnifier to perform search"
msgstr ""
msgstr "klicke auf die Lupe, um die Suche zu starten"
#: searx/templates/default/preferences.html:72
msgid "Localization"
msgstr ""
msgstr "Übersetzung"
#: searx/templates/default/preferences.html:82
msgid "Yes"
msgstr ""
msgstr "Ja"
#: searx/templates/default/preferences.html:82
msgid "No"
msgstr ""
msgstr "Nein"
#: searx/templates/default/results.html:34
msgid "Answers"
msgstr ""
msgstr "Antworten"
#: searx/templates/oscar/base.html:69
msgid "Powered by"
msgstr ""
msgstr "Powered by"
#: searx/templates/oscar/base.html:69
msgid "a privacy-respecting, hackable metasearch engine"
msgstr "eine privatsphären respektierende, hackbare Metasuchmaschine"
msgstr "eine privatsphären-respektierende, hackbare Metasuchmaschine"
#: searx/templates/oscar/navbar.html:6
msgid "Toggle navigation"
msgstr ""
msgstr "Navigation umschalten"
#: searx/templates/oscar/navbar.html:15
msgid "home"
@ -260,25 +259,22 @@ msgstr "Suchmaschinen"
#: searx/templates/oscar/preferences.html:39
msgid "What language do you prefer for search?"
msgstr "Welche Sprache bevorzugst du für die Suche?"
msgstr "welche Sprache bevorzugst du für die Suche?"
#: searx/templates/oscar/preferences.html:50
msgid "Change the language of the layout"
msgstr "Ändere die Sprache des Layouts"
msgstr "ändere die Sprache des Layouts"
#: searx/templates/oscar/preferences.html:63
msgid "Find stuff as you type"
msgstr "finde Sachen während der Eingabe"
msgstr "zeige Vorschläge während der Eingabe an"
#: searx/templates/oscar/preferences.html:73
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 ""
"ändere wie Formulare übertragen werden, <a "
"href=\"https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP-"
"Anfragemethoden\" rel=\"external\">lerne mehr über Anfragemethoden</a>"
msgstr "ändere wie Formulare übertragen werden, <a href=\"https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP-Anfragemethoden\" rel=\"external\">lerne mehr über Anfragemethoden</a>"
#: searx/templates/oscar/preferences.html:84
msgid "Change searx layout"
@ -290,9 +286,10 @@ msgstr "Suchergebnisse"
#: searx/templates/oscar/results.html:73
msgid "Links"
msgstr ""
msgstr "Links"
#: searx/templates/oscar/search.html:6 searx/templates/oscar/search_full.html:7
#: searx/templates/oscar/search.html:6
#: searx/templates/oscar/search_full.html:7
msgid "Start search"
msgstr "Suche starten"
@ -302,7 +299,7 @@ msgstr "Suchfilter anzeigen"
#: searx/templates/oscar/search_full.html:11
msgid "Hide search filters"
msgstr "Suchfilter verstecke"
msgstr "Suchfilter verstecken"
#: searx/templates/oscar/stats.html:2
msgid "stats"
@ -318,11 +315,11 @@ msgstr "Schließen"
#: searx/templates/oscar/messages/first_time.html:6
#: searx/templates/oscar/messages/no_data_available.html:3
msgid "Heads up!"
msgstr "Information!"
msgstr "Achtung"
#: searx/templates/oscar/messages/first_time.html:7
msgid "It look like you are using searx first time."
msgstr ""
msgstr "Es sieht so aus als ob das dein erstes mal mit searx ist."
#: searx/templates/oscar/messages/js_disabled.html:2
msgid "Warning!"
@ -330,7 +327,7 @@ msgstr "Warnung!"
#: searx/templates/oscar/messages/js_disabled.html:3
msgid "Please enable JavaScript to use full functionality of this site."
msgstr "Bitte aktiviere JavaScript um alle möglichkeiten dieser Seite zu nutzen."
msgstr "Bitte aktiviere JavaScript, um alle funktionen dieser Seite zu nutzen. "
#: searx/templates/oscar/messages/no_data_available.html:4
msgid "There is currently no data available. "
@ -344,13 +341,11 @@ msgstr "Entschuldigung!"
msgid ""
"we didn't find any results. Please use another query or search in more "
"categories."
msgstr ""
"Es konnten keine Suchergebnisse gefunden werden. Bitte nutze einen "
"anderen Suchbegriff oder Suche das gewünschte in einer anderen Kategorie."
msgstr "Es konnten keine Suchergebnisse gefunden werden. Bitte nutze einen anderen Suchbegriff, oder Suche das gewünschte in einer anderen Kategorie. "
#: searx/templates/oscar/messages/save_settings_successfull.html:7
msgid "Well done!"
msgstr "Gut gemacht!"
msgstr "Gut gemacht"
#: searx/templates/oscar/messages/save_settings_successfull.html:8
msgid "Settings saved successfully."
@ -358,7 +353,7 @@ msgstr "Einstellungen wurden erfolgreich gespeichert."
#: searx/templates/oscar/messages/unknow_error.html:7
msgid "Oh snap!"
msgstr "Verdammt!"
msgstr "Oh nein'"
#: searx/templates/oscar/messages/unknow_error.html:8
msgid "Something went wrong."
@ -369,7 +364,7 @@ msgstr "Irgendetwas ist falsch gelaufen."
#: searx/templates/oscar/result_templates/torrent.html:6
#: searx/templates/oscar/result_templates/videos.html:6
msgid "cached"
msgstr "cached"
msgstr "zwischengelagert"
#: searx/templates/oscar/result_templates/images.html:21
msgid "Get image"
@ -393,15 +388,15 @@ msgstr "Details anzeigen"
#: searx/templates/oscar/result_templates/map.html:14
msgid "hide details"
msgstr "Details verstecke"
msgstr "Details verstecken"
#: searx/templates/oscar/result_templates/torrent.html:8
msgid "Seeder"
msgstr ""
msgstr "Samenverstreuer"
#: searx/templates/oscar/result_templates/torrent.html:8
msgid "Leecher"
msgstr ""
msgstr "Zecke"
# categories - manually added
# TODO - automatically add
@ -431,4 +426,3 @@ msgstr "Neuigkeiten"
msgid "map"
msgstr "Karte"

View File

@ -1,24 +1,27 @@
# French translations for SEARX
# Copyright (C) 2014 Benjamin Sonntag, rike, Adam Tauber
# This file is distributed under CC0 License
#
# English translations for PROJECT.
# Copyright (C) 2014 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
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014
# rike, 2014
# rike, 2014
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2014-11-26 20:41+0100\n"
"PO-Revision-Date: 2014-09-07 21:24+0000\n"
"Last-Translator: Adam Tauber <asciimoo@gmail.com>\n"
"Language-Team: French "
"(http://www.transifex.com/projects/p/searx/language/fr/)\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
"PO-Revision-Date: 2014-12-14 21:00+0000\n"
"Last-Translator: Cqoicebordel <david.barouh@wanadoo.fr>\n"
"Language-Team: French (http://www.transifex.com/projects/p/searx/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: searx/webapp.py:308
msgid "{minutes} minute(s) ago"
@ -142,11 +145,9 @@ msgstr "Bloquer"
#: searx/templates/default/preferences.html:94
#: searx/templates/oscar/preferences.html:132
msgid ""
"These settings are stored in your cookies, this allows us not to store "
"this data about you."
msgstr ""
"Ces paramètres sont stockés dans vos cookies ; ceci nous permet de ne pas"
" collecter vos données."
"These settings are stored in your cookies, this allows us not to store this "
"data about you."
msgstr "Ces paramètres sont stockés dans vos cookies ; ceci nous permet de ne pas collecter vos données."
#: searx/templates/courgette/preferences.html:94
#: searx/templates/default/preferences.html:96
@ -154,9 +155,7 @@ msgstr ""
msgid ""
"These cookies serve your sole convenience, we don't use these cookies to "
"track you."
msgstr ""
"Ces cookies existent pour votre confort d'utilisation, nous ne les "
"utilisons pas pour vous espionner."
msgstr "Ces cookies existent pour votre confort d'utilisation, nous ne les utilisons pas pour vous espionner."
#: searx/templates/courgette/preferences.html:97
#: searx/templates/default/preferences.html:99
@ -213,19 +212,19 @@ msgstr "Statistiques du moteur"
#: searx/templates/default/categories.html:8
msgid "Click on the magnifier to perform search"
msgstr ""
msgstr "Cliquez sur la loupe pour effectuer une recherche"
#: searx/templates/default/preferences.html:72
msgid "Localization"
msgstr ""
msgstr "Localisation"
#: searx/templates/default/preferences.html:82
msgid "Yes"
msgstr ""
msgstr "Oui"
#: searx/templates/default/preferences.html:82
msgid "No"
msgstr ""
msgstr "Non"
#: searx/templates/default/results.html:34
msgid "Answers"
@ -274,10 +273,7 @@ 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 ""
"Permet de choisir comment la recherche est envoyée, <a "
"href=\"https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol#M.C3.A9thodes\""
" rel=\"external\">en savoir plus sur les méthodes HTTP</a>"
msgstr "Permet de choisir comment la recherche est envoyée, <a href=\"https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol#M.C3.A9thodes\" rel=\"external\">en savoir plus sur les méthodes HTTP</a>"
#: searx/templates/oscar/preferences.html:84
msgid "Change searx layout"
@ -291,7 +287,8 @@ msgstr "Résultats de recherche"
msgid "Links"
msgstr "Liens"
#: searx/templates/oscar/search.html:6 searx/templates/oscar/search_full.html:7
#: searx/templates/oscar/search.html:6
#: searx/templates/oscar/search_full.html:7
msgid "Start search"
msgstr "Lancer une recherche"
@ -329,9 +326,7 @@ msgstr "Attention !"
#: searx/templates/oscar/messages/js_disabled.html:3
msgid "Please enable JavaScript to use full functionality of this site."
msgstr ""
"Merci d'activer JavaScript pour utiliser toutes les fonctionnalités de ce"
" site."
msgstr "Merci d'activer JavaScript pour utiliser toutes les fonctionnalités de ce site."
#: searx/templates/oscar/messages/no_data_available.html:4
msgid "There is currently no data available. "
@ -345,9 +340,7 @@ msgstr "Désolé !"
msgid ""
"we didn't find any results. Please use another query or search in more "
"categories."
msgstr ""
"nous n'avons trouvé aucun résultat. Effectuez une autre recherche ou "
"changez de catégorie."
msgstr "nous n'avons trouvé aucun résultat. Effectuez une autre recherche ou changez de catégorie."
#: searx/templates/oscar/messages/save_settings_successfull.html:7
msgid "Well done!"
@ -432,4 +425,3 @@ msgstr "actus"
msgid "map"
msgstr "carte"

View File

@ -1,24 +1,24 @@
# English translations for .
# English translations for PROJECT.
# Copyright (C) 2014 ORGANIZATION
# This file is distributed under the same license as the project.
#
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
# Adam Tauber <asciimoo@gmail.com>, 2014
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2014-11-26 20:41+0100\n"
"PO-Revision-Date: 2014-09-07 21:30+0000\n"
"PO-Revision-Date: 2014-12-22 16:11+0000\n"
"Last-Translator: Adam Tauber <asciimoo@gmail.com>\n"
"Language-Team: Hungarian "
"(http://www.transifex.com/projects/p/searx/language/hu/)\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"Language-Team: Hungarian (http://www.transifex.com/projects/p/searx/language/hu/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"
"Language: hu\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: searx/webapp.py:308
msgid "{minutes} minute(s) ago"
@ -93,19 +93,19 @@ msgstr "Felület nyelve"
#: searx/templates/default/preferences.html:36
#: searx/templates/oscar/preferences.html:53
msgid "Autocomplete"
msgstr ""
msgstr "Automatikus kiegészítés"
#: searx/templates/courgette/preferences.html:47
#: searx/templates/default/preferences.html:47
#: searx/templates/oscar/preferences.html:66
msgid "Method"
msgstr ""
msgstr "Method"
#: searx/templates/courgette/preferences.html:56
#: searx/templates/default/preferences.html:56
#: searx/templates/oscar/preferences.html:76
msgid "Themes"
msgstr ""
msgstr "Megjelenés"
#: searx/templates/courgette/preferences.html:66
#: searx/templates/default/preferences.html:66
@ -142,8 +142,8 @@ msgstr "Tiltás"
#: searx/templates/default/preferences.html:94
#: searx/templates/oscar/preferences.html:132
msgid ""
"These settings are stored in your cookies, this allows us not to store "
"this data about you."
"These settings are stored in your cookies, this allows us not to store this "
"data about you."
msgstr "Ezek a beállítások csak a böngésző cookie-jaiban tárolódnak."
#: searx/templates/courgette/preferences.html:94
@ -152,9 +152,7 @@ msgstr "Ezek a beállítások csak a böngésző cookie-jaiban tárolódnak."
msgid ""
"These cookies serve your sole convenience, we don't use these cookies to "
"track you."
msgstr ""
"Ezek a cookie-k csak kényelmi funkciókat látnak el, nem használjuk a "
"felhasználók követésére."
msgstr "Ezek a cookie-k csak kényelmi funkciókat látnak el, nem használjuk a felhasználók követésére."
#: searx/templates/courgette/preferences.html:97
#: searx/templates/default/preferences.html:99
@ -211,189 +209,190 @@ msgstr "Kereső statisztikák"
#: searx/templates/default/categories.html:8
msgid "Click on the magnifier to perform search"
msgstr ""
msgstr "A nagyítóra kattintva indítható a keresés"
#: searx/templates/default/preferences.html:72
msgid "Localization"
msgstr ""
msgstr "Nyelv"
#: searx/templates/default/preferences.html:82
msgid "Yes"
msgstr ""
msgstr "Igen"
#: searx/templates/default/preferences.html:82
msgid "No"
msgstr ""
msgstr "Nem"
#: searx/templates/default/results.html:34
msgid "Answers"
msgstr ""
msgstr "Válaszok"
#: searx/templates/oscar/base.html:69
msgid "Powered by"
msgstr ""
msgstr "Az oldalt kiszolgálja: "
#: searx/templates/oscar/base.html:69
msgid "a privacy-respecting, hackable metasearch engine"
msgstr ""
msgstr "egy privátszféra tisztelő, könnyen módosítható metakereső"
#: searx/templates/oscar/navbar.html:6
msgid "Toggle navigation"
msgstr ""
msgstr "Navigáció megjelenítés"
#: searx/templates/oscar/navbar.html:15
msgid "home"
msgstr ""
msgstr "főoldal"
#: searx/templates/oscar/preferences.html:11
#: searx/templates/oscar/preferences.html:17
msgid "General"
msgstr ""
msgstr "Általános"
#: searx/templates/oscar/preferences.html:12
#: searx/templates/oscar/preferences.html:99
msgid "Engines"
msgstr ""
msgstr "Kereső motorok"
#: searx/templates/oscar/preferences.html:39
msgid "What language do you prefer for search?"
msgstr ""
msgstr "Preferált keresési nyelv"
#: searx/templates/oscar/preferences.html:50
msgid "Change the language of the layout"
msgstr ""
msgstr "Felület nyelve"
#: searx/templates/oscar/preferences.html:63
msgid "Find stuff as you type"
msgstr ""
msgstr "Autómatikus kereső kifejezés kiegészítés"
#: searx/templates/oscar/preferences.html:73
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 ""
msgstr "Keresés metódusa (<a href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\" rel=\"external\">bővebben</a>)"
#: searx/templates/oscar/preferences.html:84
msgid "Change searx layout"
msgstr ""
msgstr "Megjelenés"
#: searx/templates/oscar/results.html:6
msgid "Search results"
msgstr ""
msgstr "Keresési eredmények"
#: searx/templates/oscar/results.html:73
msgid "Links"
msgstr ""
msgstr "Linkek"
#: searx/templates/oscar/search.html:6 searx/templates/oscar/search_full.html:7
#: searx/templates/oscar/search.html:6
#: searx/templates/oscar/search_full.html:7
msgid "Start search"
msgstr ""
msgstr "Keresés indítása"
#: searx/templates/oscar/search_full.html:11
msgid "Show search filters"
msgstr ""
msgstr "Keresési szűrők megjelenítése"
#: searx/templates/oscar/search_full.html:11
msgid "Hide search filters"
msgstr ""
msgstr "Keresési szűrők elrejtése"
#: searx/templates/oscar/stats.html:2
msgid "stats"
msgstr ""
msgstr "statisztikák"
#: 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 ""
msgstr "Bezár"
#: searx/templates/oscar/messages/first_time.html:6
#: searx/templates/oscar/messages/no_data_available.html:3
msgid "Heads up!"
msgstr ""
msgstr "Figyelem!"
#: searx/templates/oscar/messages/first_time.html:7
msgid "It look like you are using searx first time."
msgstr ""
msgstr "Úgy tűnik először használod a keresőt."
#: searx/templates/oscar/messages/js_disabled.html:2
msgid "Warning!"
msgstr ""
msgstr "Figyelem!"
#: searx/templates/oscar/messages/js_disabled.html:3
msgid "Please enable JavaScript to use full functionality of this site."
msgstr ""
msgstr "Engedélyezze a javascript-et a teljes funkcionalitás használathoz"
#: searx/templates/oscar/messages/no_data_available.html:4
msgid "There is currently no data available. "
msgstr ""
msgstr "Nincs megjeleníthető adat."
#: searx/templates/oscar/messages/no_results.html:7
msgid "Sorry!"
msgstr ""
msgstr "Elnézést!"
#: 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 ""
msgstr "Nincs megjeleníthető találat."
#: searx/templates/oscar/messages/save_settings_successfull.html:7
msgid "Well done!"
msgstr ""
msgstr "Siker!"
#: searx/templates/oscar/messages/save_settings_successfull.html:8
msgid "Settings saved successfully."
msgstr ""
msgstr "Beállítások mentve"
#: searx/templates/oscar/messages/unknow_error.html:7
msgid "Oh snap!"
msgstr ""
msgstr "Oh!"
#: searx/templates/oscar/messages/unknow_error.html:8
msgid "Something went wrong."
msgstr ""
msgstr "Hiba történt"
#: searx/templates/oscar/result_templates/default.html:6
#: searx/templates/oscar/result_templates/map.html:7
#: searx/templates/oscar/result_templates/torrent.html:6
#: searx/templates/oscar/result_templates/videos.html:6
msgid "cached"
msgstr ""
msgstr "tárolt"
#: searx/templates/oscar/result_templates/images.html:21
msgid "Get image"
msgstr ""
msgstr "Kép megjelenítése"
#: searx/templates/oscar/result_templates/images.html:22
msgid "View source"
msgstr ""
msgstr "Forrás megtekintése"
#: searx/templates/oscar/result_templates/map.html:10
msgid "show map"
msgstr ""
msgstr "Térkép"
#: searx/templates/oscar/result_templates/map.html:10
msgid "hide map"
msgstr ""
msgstr "Térkép elrejtése"
#: searx/templates/oscar/result_templates/map.html:14
msgid "show details"
msgstr ""
msgstr "Részletek"
#: searx/templates/oscar/result_templates/map.html:14
msgid "hide details"
msgstr ""
msgstr "Részletek elrejtése"
#: searx/templates/oscar/result_templates/torrent.html:8
msgid "Seeder"
msgstr ""
msgstr "Seeder"
#: searx/templates/oscar/result_templates/torrent.html:8
msgid "Leecher"
msgstr ""
msgstr "Leecher"
# categories - manually added
# TODO - automatically add
@ -423,4 +422,3 @@ msgstr "hírek"
msgid "map"
msgstr "térkép"

View File

@ -1,23 +1,23 @@
# English translations for .
# English translations for PROJECT.
# Copyright (C) 2014 ORGANIZATION
# This file is distributed under the same license as the project.
#
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
# André Koot <meneer@tken.net>, 2014
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2014-11-26 20:41+0100\n"
"PO-Revision-Date: 2014-09-09 15:33+0000\n"
"PO-Revision-Date: 2014-12-11 13:50+0000\n"
"Last-Translator: André Koot <meneer@tken.net>\n"
"Language-Team: Dutch "
"(http://www.transifex.com/projects/p/searx/language/nl/)\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"Language-Team: Dutch (http://www.transifex.com/projects/p/searx/language/nl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"
"Language: nl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: searx/webapp.py:308
msgid "{minutes} minute(s) ago"
@ -92,19 +92,19 @@ msgstr "Interfacetaal"
#: searx/templates/default/preferences.html:36
#: searx/templates/oscar/preferences.html:53
msgid "Autocomplete"
msgstr ""
msgstr "Auto-aanvullen"
#: searx/templates/courgette/preferences.html:47
#: searx/templates/default/preferences.html:47
#: searx/templates/oscar/preferences.html:66
msgid "Method"
msgstr ""
msgstr "Methode"
#: searx/templates/courgette/preferences.html:56
#: searx/templates/default/preferences.html:56
#: searx/templates/oscar/preferences.html:76
msgid "Themes"
msgstr ""
msgstr "Thema's"
#: searx/templates/courgette/preferences.html:66
#: searx/templates/default/preferences.html:66
@ -141,11 +141,9 @@ msgstr "Blokkeren"
#: searx/templates/default/preferences.html:94
#: searx/templates/oscar/preferences.html:132
msgid ""
"These settings are stored in your cookies, this allows us not to store "
"this data about you."
msgstr ""
"Deze instellingen worden bewaard in je cookies. Hierdoor hoeven wij niets"
" over jou te bewaren."
"These settings are stored in your cookies, this allows us not to store this "
"data about you."
msgstr "Deze instellingen worden bewaard in je cookies. Hierdoor hoeven wij niets over jou te bewaren."
#: searx/templates/courgette/preferences.html:94
#: searx/templates/default/preferences.html:96
@ -153,9 +151,7 @@ msgstr ""
msgid ""
"These cookies serve your sole convenience, we don't use these cookies to "
"track you."
msgstr ""
"Deze cookies zijn alleen voor je eigen gemak, we gebruiken deze cookies "
"niet om je te volgen."
msgstr "Deze cookies zijn alleen voor je eigen gemak, we gebruiken deze cookies niet om je te volgen."
#: searx/templates/courgette/preferences.html:97
#: searx/templates/default/preferences.html:99
@ -212,189 +208,190 @@ msgstr "Zoekmachinestatistieken"
#: searx/templates/default/categories.html:8
msgid "Click on the magnifier to perform search"
msgstr ""
msgstr "Klik op het vergrootglas om te zoeken"
#: searx/templates/default/preferences.html:72
msgid "Localization"
msgstr ""
msgstr "Vertaling"
#: searx/templates/default/preferences.html:82
msgid "Yes"
msgstr ""
msgstr "Ja"
#: searx/templates/default/preferences.html:82
msgid "No"
msgstr ""
msgstr "Nee"
#: searx/templates/default/results.html:34
msgid "Answers"
msgstr ""
msgstr "Antwoorden"
#: searx/templates/oscar/base.html:69
msgid "Powered by"
msgstr ""
msgstr "Powered by"
#: searx/templates/oscar/base.html:69
msgid "a privacy-respecting, hackable metasearch engine"
msgstr ""
msgstr "een privacy eerbiedigende, aanpasbare metazoekmachine"
#: searx/templates/oscar/navbar.html:6
msgid "Toggle navigation"
msgstr ""
msgstr "Omschakelen navigatie"
#: searx/templates/oscar/navbar.html:15
msgid "home"
msgstr ""
msgstr "thuis"
#: searx/templates/oscar/preferences.html:11
#: searx/templates/oscar/preferences.html:17
msgid "General"
msgstr ""
msgstr "Algemeen"
#: searx/templates/oscar/preferences.html:12
#: searx/templates/oscar/preferences.html:99
msgid "Engines"
msgstr ""
msgstr "Zoekmachines"
#: searx/templates/oscar/preferences.html:39
msgid "What language do you prefer for search?"
msgstr ""
msgstr "Welke taal wil je gebruiken voor het zoeken?"
#: searx/templates/oscar/preferences.html:50
msgid "Change the language of the layout"
msgstr ""
msgstr "Wijzig de taal van de layout"
#: searx/templates/oscar/preferences.html:63
msgid "Find stuff as you type"
msgstr ""
msgstr "Zoek tijdens het typen"
#: searx/templates/oscar/preferences.html:73
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 ""
msgstr "Bepaal hoe de formulieren worden ingestuurd, <a href=\"http://nl.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP-requests\" rel=\"external\">lees meer over request methodes</a>"
#: searx/templates/oscar/preferences.html:84
msgid "Change searx layout"
msgstr ""
msgstr "Wijzig searx layout"
#: searx/templates/oscar/results.html:6
msgid "Search results"
msgstr ""
msgstr "Zoekresultaten"
#: searx/templates/oscar/results.html:73
msgid "Links"
msgstr ""
msgstr "Links"
#: searx/templates/oscar/search.html:6 searx/templates/oscar/search_full.html:7
#: searx/templates/oscar/search.html:6
#: searx/templates/oscar/search_full.html:7
msgid "Start search"
msgstr ""
msgstr "Start zoeken"
#: searx/templates/oscar/search_full.html:11
msgid "Show search filters"
msgstr ""
msgstr "Toon zoekfilters"
#: searx/templates/oscar/search_full.html:11
msgid "Hide search filters"
msgstr ""
msgstr "Verberg zoekfilters"
#: searx/templates/oscar/stats.html:2
msgid "stats"
msgstr ""
msgstr "stats"
#: 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 ""
msgstr "Sluiten"
#: searx/templates/oscar/messages/first_time.html:6
#: searx/templates/oscar/messages/no_data_available.html:3
msgid "Heads up!"
msgstr ""
msgstr "Heads up!"
#: searx/templates/oscar/messages/first_time.html:7
msgid "It look like you are using searx first time."
msgstr ""
msgstr "Het lijkt erop dat je searx voor de eerste keer gebruikt."
#: searx/templates/oscar/messages/js_disabled.html:2
msgid "Warning!"
msgstr ""
msgstr "Waarschuwing!"
#: searx/templates/oscar/messages/js_disabled.html:3
msgid "Please enable JavaScript to use full functionality of this site."
msgstr ""
msgstr "Activeer JavaScript om alle functionaliteit van deze site te gebruiken."
#: searx/templates/oscar/messages/no_data_available.html:4
msgid "There is currently no data available. "
msgstr ""
msgstr "Er zijn momenteel geen gegevens beschikbaar."
#: searx/templates/oscar/messages/no_results.html:7
msgid "Sorry!"
msgstr ""
msgstr "Sorry!"
#: 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 ""
msgstr "we kregen geen resultaat. Probeer een andere opvraag of zoek in meer categorieën."
#: searx/templates/oscar/messages/save_settings_successfull.html:7
msgid "Well done!"
msgstr ""
msgstr "Goed gedaan!"
#: searx/templates/oscar/messages/save_settings_successfull.html:8
msgid "Settings saved successfully."
msgstr ""
msgstr "Instellingen succesvol opgeslagen."
#: searx/templates/oscar/messages/unknow_error.html:7
msgid "Oh snap!"
msgstr ""
msgstr "Verdraaid!"
#: searx/templates/oscar/messages/unknow_error.html:8
msgid "Something went wrong."
msgstr ""
msgstr "Er ging iets fout."
#: searx/templates/oscar/result_templates/default.html:6
#: searx/templates/oscar/result_templates/map.html:7
#: searx/templates/oscar/result_templates/torrent.html:6
#: searx/templates/oscar/result_templates/videos.html:6
msgid "cached"
msgstr ""
msgstr "gecached"
#: searx/templates/oscar/result_templates/images.html:21
msgid "Get image"
msgstr ""
msgstr "Toon afbeelding"
#: searx/templates/oscar/result_templates/images.html:22
msgid "View source"
msgstr ""
msgstr "Bekijk bron"
#: searx/templates/oscar/result_templates/map.html:10
msgid "show map"
msgstr ""
msgstr "toon kaart"
#: searx/templates/oscar/result_templates/map.html:10
msgid "hide map"
msgstr ""
msgstr "verberg kaart"
#: searx/templates/oscar/result_templates/map.html:14
msgid "show details"
msgstr ""
msgstr "toon details"
#: searx/templates/oscar/result_templates/map.html:14
msgid "hide details"
msgstr ""
msgstr "verberg details"
#: searx/templates/oscar/result_templates/torrent.html:8
msgid "Seeder"
msgstr ""
msgstr "Aanbieder"
#: searx/templates/oscar/result_templates/torrent.html:8
msgid "Leecher"
msgstr ""
msgstr "Ophaler"
# categories - manually added
# TODO - automatically add
@ -424,4 +421,3 @@ msgstr "nieuws"
msgid "map"
msgstr "kaart"

View File

@ -18,7 +18,7 @@ along with searx. If not, see < http://www.gnu.org/licenses/ >.
# version of searx
VERSION_MAJOR = 0
VERSION_MINOR = 5
VERSION_MINOR = 6
VERSION_BUILD = 0
VERSION_STRING = "{0}.{1}.{2}".format(VERSION_MAJOR,

View File

@ -41,15 +41,12 @@ from searx.utils import (
UnicodeWriter, highlight_content, html_to_text, get_themes
)
from searx.version import VERSION_STRING
from searx.https_rewrite import https_rules
from searx.languages import language_codes
from searx.https_rewrite import https_url_rewrite
from searx.search import Search
from searx.query import Query
from searx.autocomplete import backends as autocomplete_backends
from urlparse import urlparse
import re
static_path, templates_path, themes =\
get_themes(settings['themes_path']
@ -68,9 +65,12 @@ app.secret_key = settings['server']['secret_key']
babel = Babel(app)
#TODO configurable via settings.yml
favicons = ['wikipedia', 'youtube', 'vimeo', 'dailymotion', 'soundcloud',
'twitter', 'stackoverflow', 'github', 'deviantart']
global_favicons = []
for indice, theme in enumerate(themes):
global_favicons.append([])
theme_img_path = searx_dir+"/static/"+theme+"/img/"
for (dirpath, dirnames, filenames) in os.walk(theme_img_path):
global_favicons[indice].extend(filenames)
cookie_max_age = 60 * 60 * 24 * 365 * 23 # 23 years
@ -215,59 +215,7 @@ def index():
if settings['server']['https_rewrite']\
and result['parsed_url'].scheme == 'http':
skip_https_rewrite = False
# check if HTTPS rewrite is possible
for target, rules, exclusions in https_rules:
# check if target regex match with url
if target.match(result['url']):
# process exclusions
for exclusion in exclusions:
# check if exclusion match with url
if exclusion.match(result['url']):
skip_https_rewrite = True
break
# skip https rewrite if required
if skip_https_rewrite:
break
# process rules
for rule in rules:
try:
# TODO, precompile rule
p = re.compile(rule[0])
# rewrite url if possible
new_result_url = p.sub(rule[1], result['url'])
except:
break
# parse new url
new_parsed_url = urlparse(new_result_url)
# continiue if nothing was rewritten
if result['url'] == new_result_url:
continue
# get domainname from result
# TODO, does only work correct with TLD's like
# asdf.com, not for asdf.com.de
# TODO, using publicsuffix instead of this rewrite rule
old_result_domainname = '.'.join(
result['parsed_url'].hostname.split('.')[-2:])
new_result_domainname = '.'.join(
new_parsed_url.hostname.split('.')[-2:])
# check if rewritten hostname is the same,
# to protect against wrong or malicious rewrite rules
if old_result_domainname == new_result_domainname:
# set new url
result['url'] = new_result_url
# target has matched, do not search over the other rules
break
result = https_url_rewrite(result)
if search.request_data.get('format', 'html') == 'html':
if 'content' in result:
@ -288,10 +236,6 @@ def index():
else:
result['pretty_url'] = result['url']
for engine in result['engines']:
if engine in favicons:
result['favicon'] = engine
# TODO, check if timezone is calculated right
if 'publishedDate' in result:
result['pubdate'] = result['publishedDate'].strftime('%Y-%m-%d %H:%M:%S%z')
@ -344,7 +288,8 @@ def index():
suggestions=search.suggestions,
answers=search.answers,
infoboxes=search.infoboxes,
theme=get_current_theme_name()
theme=get_current_theme_name(),
favicons=global_favicons[themes.index(get_current_theme_name())]
)