├── .editorconfig ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── MANIFEST ├── MANIFEST.in ├── README.rst ├── Vagrantfile ├── multilingual ├── __init__.py ├── elasticsearch_backend.py └── utils.py ├── setup.cfg ├── setup.py ├── tests ├── __init__.py ├── functional_tests │ ├── __init__.py │ ├── test_hooks.py │ ├── test_index_creation.py │ └── test_query.py ├── manage.py ├── requirements.txt ├── testproject │ ├── __init__.py │ ├── admin.py │ ├── fixtures │ │ ├── documents.json │ │ ├── parler_small.json │ │ └── small.json │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ ├── __init__.py │ │ │ └── import_sgm.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20150907_1648.py │ │ └── __init__.py │ ├── models.py │ ├── search_indexes.py │ ├── settings.py │ ├── signals.py │ ├── templates │ │ ├── base.html │ │ ├── search │ │ │ ├── indexes │ │ │ │ └── testproject │ │ │ │ │ ├── document_text.txt │ │ │ │ │ └── parlerdocument_text.txt │ │ │ └── search.html │ │ └── testproject │ │ │ ├── document_list.html │ │ │ └── parlerdocument_list.html │ ├── tests.py │ ├── translation.py │ ├── urls.py │ ├── views.py │ └── wsgi.py ├── tox.ini └── unittests │ ├── __init__.py │ ├── mocks.py │ ├── test_hooks.py │ ├── test_index_creation.py │ └── test_query.py └── vagrant_data ├── bashrc ├── common_requirements.txt ├── etc-bash.bashrc └── vagrant.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | end_of_line = lf 6 | insert_final_newline = true 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | indent_style = space 10 | indent_size = 4 11 | max_line_length = 100 12 | quote_type = single 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # IDEs 9 | .idea 10 | .DS_Store 11 | 12 | 13 | # Distribution / packaging 14 | .Python 15 | env/ 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | .vagrant/ 30 | venv/ 31 | 32 | # PyInstaller 33 | # Usually these files are written by a python script from a template 34 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 35 | *.manifest 36 | *.spec 37 | 38 | # Installer logs 39 | pip-log.txt 40 | pip-delete-this-directory.txt 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .coverage 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | *.sqlite 57 | 58 | # Sphinx documentation 59 | docs/_build/ 60 | 61 | # PyBuilder 62 | target/ 63 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | sudo: false 3 | python: 4 | - "2.7" 5 | - "3.4" 6 | services: 7 | - elasticsearch 8 | before_script: 9 | - sleep 10 10 | env: 11 | - DJANGO_REQUIREMENT="Django>=1.6,<1.7" 12 | - DJANGO_REQUIREMENT="Django>=1.9,<1.10" 13 | 14 | # command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors 15 | install: 16 | - pip install -q $DJANGO_REQUIREMENT "elasticsearch==1.7.0" "django-haystack==2.4.1" django-modeltranslation django-parler flake8 17 | - python setup.py -q install 18 | # command to run tests, e.g. python setup.py test 19 | script: 20 | - flake8 21 | - cd tests 22 | - ./manage.py test tests 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | Feel free to contribute to the project. It is hosted on 5 | [Github](https://github.com/sbaechler/django-multilingual-search). 6 | Clone the repository and open a pull request. 7 | 8 | # Setup 9 | There is a Vagrant box included in this repo to help development of the plugin. 10 | 11 | The box contains Django, Postgres and Elasticsearch. 12 | 13 | To work with the box simply run: 14 | 15 | vagrant up 16 | vagrant ssh 17 | 18 | create a virtualenv and install the requirements in `tests/testproject/requirements.txt`. 19 | 20 | You can access a WebGUI for elasticsearch here: http://localhost:9200/_plugin/head/ 21 | 22 | 23 | # Testing 24 | The plugin uses Tox for testing under different Python versions. 25 | 26 | To manually run the tests, activate a virtual env, go to the directory /vagrant/tests 27 | and run ``./testproject/manage.py test``. 28 | 29 | 30 | # Test Data 31 | The app uses the Europarl ACL WMT 2013 test set. 32 | 33 | http://matrix.statmt.org/test_sets/list 34 | 35 | http://matrix.statmt.org/test_sets/newstest2013.tgz?1367361979 36 | 37 | There is a Django management command that can import the reference SGML data and create Django models from it. 38 | 39 | vagrant@precise64:/vagrant/tests/testproject$ ./manage.py import_sgm --delete ../../test 40 | 41 | The option ``--delete`` causes the import to delete any existing data. 42 | The only argument is the path to the ``test`` directory containing the SGML files. 43 | 44 | The ACL WMT 2013 test set is included as Django-fixture. 45 | 46 | 47 | # Coding style 48 | PEP-8 with a line length of 100. 49 | 50 | If you have the [Editorconfig Plugin](http://editorconfig.org/) installed, your IDE is 51 | automatically going to enforce the correct style. 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Feinheit GmbH, Simon Bächler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | # file GENERATED by distutils, do NOT edit 2 | LICENSE 3 | README.rst 4 | setup.cfg 5 | setup.py 6 | multilingual/__init__.py 7 | multilingual/elasticsearch_backend.py 8 | multilingual/utils.py 9 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include README.rst 3 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Django Multilingual Search 2 | ========================== 3 | 4 | A multilingual Haystack plugin for Django and Elasticsearch. 5 | The module is a drop-in replacement for the Haystack ``ElasticsearchSearchEngine``. 6 | 7 | Instead of a single index it creates an index for each language specified in ``settings.LANGUAGES``. 8 | 9 | A query is routed to the index of the currently active language. 10 | 11 | .. image:: https://travis-ci.org/sbaechler/django-multilingual-search.svg?branch=master 12 | :target: https://travis-ci.org/sbaechler/django-multilingual-search 13 | 14 | Currently, support for Django 1.10 is not guaranteed. 15 | 16 | Installation 17 | ------------ 18 | 19 | Install with pip:: 20 | 21 | pip install django-multilingual-search 22 | 23 | The major and minor versions of this project correspond to the Haystack version the package was 24 | tested against. This version is for Haystack 2.4. 25 | 26 | 27 | Configuration 28 | ------------- 29 | 30 | The app provides a drop-in replacement for the ElasticsearchEngine of Haystack. 31 | To use it, specify this engine in ``settings.py``:: 32 | 33 | HAYSTACK_CONNECTIONS = { 34 | 'default': { 35 | 'ENGINE': 'multilingual.elasticsearch_backend.ElasticsearchMultilingualSearchEngine', 36 | 'URL': 'http://127.0.0.1:9200/', 37 | 'INDEX_NAME': 'myproject', 38 | }, 39 | } 40 | 41 | For automatic indexing of new entries the Haystack 42 | `signal processors `_ 43 | can be used without modification. It is recommended that a custom SignalProcessor be used 44 | instead of the ``RealtimeSignalProcessor`` because of server timeout issues with the latter. 45 | 46 | 47 | Contributing 48 | ------------ 49 | Please read the `Contributing <./CONTRIBUTING.md>`_ guide. Any help is greatly appreciated. 50 | 51 | My current company is not using Python, so I won't be able to maintain and keep this library updated. 52 | 53 | 54 | Release History 55 | --------------- 56 | 57 | - 2.4.2: Support Haystack 2.4.1 58 | - 2.4.1: Add compatibility with Django-parler. 59 | - 2.4.0: Update code for compatibility with Haystack 2.4 60 | - 2.3.0: First release 61 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | VAGRANTFILE_API_VERSION = "2" 5 | 6 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 7 | config.vm.box = "precise64" 8 | config.vm.box_url = "http://files.vagrantup.com/precise64.box" 9 | config.vm.synced_folder "./vagrant_data", "/vagrant_data" 10 | config.vm.provision :shell, :path => "vagrant_data/vagrant.sh" 11 | config.vm.network :forwarded_port, guest: 9200, host: 9200 12 | config.vm.network :forwarded_port, guest: 8000, host: 8000 13 | end 14 | -------------------------------------------------------------------------------- /multilingual/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbaechler/django-multilingual-search/485c690d865da3267b19e073e28d3e2290f36611/multilingual/__init__.py -------------------------------------------------------------------------------- /multilingual/elasticsearch_backend.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | from django.conf import settings as django_settings 4 | from django.utils import translation 5 | import elasticsearch 6 | from elasticsearch import NotFoundError, ImproperlyConfigured 7 | import haystack 8 | from haystack.backends import BaseEngine 9 | from haystack.backends.elasticsearch_backend import ( 10 | ElasticsearchSearchBackend, ElasticsearchSearchQuery, FIELD_MAPPINGS, DEFAULT_FIELD_MAPPING) 11 | from haystack.constants import DJANGO_CT, DJANGO_ID 12 | from haystack.utils import get_identifier 13 | from .utils import get_analyzer_for 14 | 15 | 16 | class ElasticsearchMultilingualSearchBackend(ElasticsearchSearchBackend): 17 | """ 18 | Subclasses the Haystack backend. 19 | """ 20 | def __init__(self, connection_alias, **connection_options): 21 | """ 22 | :param connection_alias: The connection name. Usually 'default' 23 | :param connection_options: The connection settings. 24 | """ 25 | super(ElasticsearchMultilingualSearchBackend, self).__init__( 26 | connection_alias, **connection_options) 27 | 28 | # self.index_name will be modified for each translation. 29 | self.index_base_name = self.index_name 30 | if not hasattr(django_settings, 'LANGUAGES'): 31 | raise ImproperlyConfigured("You must specify 'LANGUAGES' in your Django settings.") 32 | self.languages = [l[0] for l in django_settings.LANGUAGES] 33 | self._reset_existing_mapping() 34 | self.content_field_name = '' 35 | 36 | def _index_name_for_language(self, language): 37 | return '{0}-{1}'.format(self.index_base_name, language) 38 | 39 | def _reset_existing_mapping(self): 40 | self.existing_mapping = dict((l, {}) for l, v in django_settings.LANGUAGES) 41 | 42 | def setup(self): 43 | """ 44 | Defers loading until needed. 45 | Compares the existing mapping for each language with the current codebase. 46 | If they differ, it automatically updates the index. 47 | """ 48 | # Get the existing mapping & cache it. We'll compare it 49 | # during the ``update`` & if it doesn't match, we'll put the new 50 | # mapping. 51 | for language in self.languages: 52 | self.index_name = self._index_name_for_language(language) 53 | try: 54 | self.existing_mapping[language] = self.conn.indices.get_mapping( 55 | index=self.index_name) 56 | except NotFoundError: 57 | pass 58 | except Exception: 59 | if not self.silently_fail: 60 | raise 61 | 62 | unified_index = haystack.connections[self.connection_alias].get_unified_index() 63 | 64 | self.content_field_name, field_mapping = self.build_schema( 65 | unified_index.all_searchfields(), language) 66 | 67 | current_mapping = { 68 | 'modelresult': { 69 | 'properties': field_mapping, 70 | '_boost': { 71 | 'name': 'boost', 72 | 'null_value': 1.0 73 | } 74 | } 75 | } 76 | 77 | if current_mapping != self.existing_mapping[language]: 78 | try: 79 | # Make sure the index is there first. 80 | self.conn.indices.create( 81 | index=self.index_name, 82 | body=self.DEFAULT_SETTINGS, 83 | ignore=400) 84 | self.conn.indices.put_mapping( 85 | index=self.index_name, 86 | doc_type='modelresult', 87 | body=current_mapping 88 | ) 89 | self.existing_mapping[language] = current_mapping 90 | except Exception: 91 | if not self.silently_fail: 92 | raise 93 | 94 | self.setup_complete = True 95 | 96 | def clear(self, models=None, commit=True): 97 | """ 98 | Clears all indexes for the current project. 99 | :param models: if specified, only deletes the entries for the given models. 100 | :param commit: This is ignored by Haystack (maybe a bug?) 101 | """ 102 | for language in self.languages: 103 | self.log.debug('clearing index for {0}'.format(language)) 104 | self.index_name = self._index_name_for_language(language) 105 | super(ElasticsearchMultilingualSearchBackend, self).clear(models, commit) 106 | self._reset_existing_mapping() 107 | 108 | def update(self, index, iterable, commit=True): 109 | """ 110 | Updates the index with current data. 111 | :param index: The search_indexes.Index object 112 | :param iterable: The queryset 113 | :param commit: commit to the backend. 114 | """ 115 | parler = False 116 | # setup here because self.existing_mappings are overridden. 117 | if not self.setup_complete: 118 | try: 119 | self.setup() 120 | except elasticsearch.TransportError as e: 121 | if not self.silently_fail: 122 | raise 123 | 124 | self.log.error("Failed to add documents to Elasticsearch: %s", e) 125 | return 126 | 127 | if hasattr(iterable, 'language') and hasattr(iterable.language, '__call__'): 128 | parler = True # Django-parler 129 | 130 | for language in self.languages: 131 | self.index_name = self._index_name_for_language(language) 132 | # self.log.debug('updating index for {0}'.format(language)) 133 | if parler: 134 | # workaround for django-parler 135 | for item in iterable: 136 | item.set_current_language(language) 137 | super(ElasticsearchMultilingualSearchBackend, self).update( 138 | index, iterable, commit) 139 | else: 140 | with translation.override(language): 141 | super(ElasticsearchMultilingualSearchBackend, self).update( 142 | index, iterable, commit) 143 | 144 | def build_schema(self, fields, language): 145 | """ 146 | Build the index schema for the given field. New argument language. 147 | :param fields: 148 | :param language: the language code 149 | :return: a dictionary wit the field name (string) and the 150 | mapping configuration (dictionary) 151 | """ 152 | content_field_name = '' 153 | mapping = { 154 | DJANGO_CT: {'type': 'string', 'index': 'not_analyzed', 'include_in_all': False}, 155 | DJANGO_ID: {'type': 'string', 'index': 'not_analyzed', 'include_in_all': False}, 156 | } 157 | 158 | for field_name, field_class in fields.items(): 159 | field_mapping = FIELD_MAPPINGS.get( 160 | field_class.field_type, DEFAULT_FIELD_MAPPING).copy() 161 | if field_class.boost != 1.0: 162 | field_mapping['boost'] = field_class.boost 163 | 164 | if field_class.document is True: 165 | content_field_name = field_class.index_fieldname 166 | 167 | # Do this last to override `text` fields. 168 | if field_mapping['type'] == 'string': 169 | # Use the language analyzer for text fields. 170 | if field_mapping['analyzer'] == DEFAULT_FIELD_MAPPING['analyzer']: 171 | field_mapping['analyzer'] = get_analyzer_for(language) 172 | if field_class.indexed is False or hasattr(field_class, 'facet_for'): 173 | field_mapping['index'] = 'not_analyzed' 174 | del field_mapping['analyzer'] 175 | 176 | mapping[field_class.index_fieldname] = field_mapping 177 | 178 | return content_field_name, mapping 179 | 180 | def search(self, query_string, **kwargs): 181 | """ 182 | The main search method 183 | :param query_string: The string to pass to Elasticsearch. e.g. '*:*' 184 | :param kwargs: start_offset, end_offset, result_class 185 | :return: result_class instance 186 | """ 187 | self.index_name = self._index_name_for_language(translation.get_language()) 188 | # self.log.debug('search method called (%s): %s' % 189 | # (translation.get_language(), query_string)) 190 | return super(ElasticsearchMultilingualSearchBackend, self).search(query_string, **kwargs) 191 | 192 | def remove(self, obj_or_string, commit=True): 193 | """ 194 | Removes an object from the index. 195 | :param obj_or_string: 196 | :param commit: 197 | """ 198 | if not self.setup_complete: 199 | try: 200 | self.setup() 201 | except elasticsearch.TransportError as e: 202 | if not self.silently_fail: 203 | raise 204 | doc_id = get_identifier(obj_or_string) 205 | self.log.error("Failed to remove document '%s' from Elasticsearch: %s", doc_id, e) 206 | return 207 | 208 | for language in self.languages: 209 | # self.log.debug('removing {0} from index {1}'.format(obj_or_string, language)) 210 | self.index_name = self._index_name_for_language(language) 211 | with translation.override(language): 212 | super(ElasticsearchMultilingualSearchBackend, self).remove(obj_or_string, 213 | commit=commit) 214 | 215 | 216 | class ElasticsearchMultilingualSearchQuery(ElasticsearchSearchQuery): 217 | """ The original class is good enough for now. """ 218 | 219 | 220 | class ElasticsearchMultilingualSearchEngine(BaseEngine): 221 | backend = ElasticsearchMultilingualSearchBackend 222 | query = ElasticsearchMultilingualSearchQuery 223 | -------------------------------------------------------------------------------- /multilingual/utils.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | 4 | 5 | def get_analyzer_for(language_code, default='snowball'): 6 | """ 7 | Get the available language analyzer for the given language code or else the default. 8 | :param language_code: Django language code 9 | :param default: The analyzer to return if no language analyzer has been found. 10 | Defaults to 'snowball'. 11 | :return: The Haystack language name. E.g. 'german' or the default analyzer 12 | """ 13 | languages = { 14 | 'ar': 'arabic', 15 | # '': 'armenian', 16 | 'eu': 'basque', 17 | 'pt-br': 'brazilian', 18 | 'bg': 'bulgarian', 19 | 'ca': 'catalan', 20 | 'zh-hans': 'chinese', 21 | 'zh-hant': 'chinese', 22 | # 'cjk', 23 | 'cs': 'czech', 24 | 'da': 'danish', 25 | 'nl': 'dutch', 26 | 'en': 'english', 27 | 'fi': 'finnish', 28 | 'fr': 'french', 29 | 'gl': 'galician', 30 | 'de': 'german', 31 | 'el': 'greek', 32 | 'hi': 'hindi', 33 | 'hu': 'hungarian', 34 | 'id': 'indonesian', 35 | 'ga': 'irish', 36 | 'it': 'italian', 37 | 'lv': 'latvian', 38 | 'no': 'norwegian', 39 | 'fa': 'persian', 40 | 'pt': 'portuguese', 41 | 'ro': 'romanian', 42 | 'ru': 'russian', 43 | # 'sorani', 44 | 'es': 'spanish', 45 | 'sv': 'swedish', 46 | 'tr': 'turkish', 47 | 'th': 'thai' 48 | } 49 | if language_code in languages: 50 | return languages[language_code] 51 | elif language_code[:2] in languages: 52 | return languages[language_code[:2]] 53 | return default 54 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | exclude=docs,migrations,venv,.tox 3 | max-line-length = 100 4 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from distutils.core import setup 3 | import os 4 | 5 | 6 | def read(fname): 7 | return open(os.path.join(os.path.dirname(__file__), fname)).read() 8 | 9 | 10 | # Hard linking doesn't work inside VirtualBox shared folders. This means that 11 | # you can't use tox in a directory that is being shared with Vagrant, 12 | # since tox relies on `python setup.py sdist` which uses hard links. As a 13 | # workaround, disable hard-linking if setup.py is a descendant of /vagrant. 14 | # See 15 | # https://stackoverflow.com/questions/7719380/python-setup-py-sdist-error-operation-not-permitted 16 | # for more details. 17 | if os.path.abspath(__file__).split(os.path.sep)[1] == 'vagrant': 18 | del os.link 19 | 20 | setup( 21 | name='django-multilingual-search', 22 | version='2.4.1', 23 | packages=['multilingual'], 24 | url='https://github.com/sbaechler/django-multilingual-search', 25 | license='BSD', 26 | author='Simon Bächler', 27 | author_email='b@chler.com', 28 | description='A drop-in replacement for the Haystack Elasticsearch backend which allows ' 29 | 'multilingual indexes for Django.', 30 | long_description=read('README.rst'), 31 | platforms=['OS Independent'], 32 | install_requires=[ 33 | 'Django>=1.5', 34 | 'django-haystack==2.4.1', 35 | 'elasticsearch>=1.6.0,<1.8' 36 | ], 37 | classifiers=[ 38 | 'Development Status :: 5 - Production/Stable', 39 | 'License :: OSI Approved :: BSD License', 40 | 'Framework :: Django', 41 | 'Intended Audience :: Developers', 42 | 'Topic :: Internet :: WWW/HTTP :: Indexing/Search', 43 | 'Programming Language :: Python', 44 | 'Programming Language :: Python :: 2', 45 | 'Programming Language :: Python :: 2.7', 46 | 'Programming Language :: Python :: 3', 47 | 'Programming Language :: Python :: 3.2', 48 | 'Programming Language :: Python :: 3.3', 49 | 'Programming Language :: Python :: 3.4', 50 | ] 51 | ) 52 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbaechler/django-multilingual-search/485c690d865da3267b19e073e28d3e2290f36611/tests/__init__.py -------------------------------------------------------------------------------- /tests/functional_tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbaechler/django-multilingual-search/485c690d865da3267b19e073e28d3e2290f36611/tests/functional_tests/__init__.py -------------------------------------------------------------------------------- /tests/functional_tests/test_hooks.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals, print_function 3 | from django.test import TestCase 4 | from django.utils import translation 5 | from django.utils.html import escape 6 | from django.db.models import signals 7 | import haystack 8 | import time 9 | from multilingual.elasticsearch_backend import ElasticsearchMultilingualSearchEngine 10 | from testproject.models import Document 11 | from testproject.signals import DocumentOnlySignalProcessor 12 | from unittests.mocks import create_documents, Data 13 | 14 | try: 15 | from unittest import mock # python >= 3.3 16 | except ImportError: 17 | import mock # python 2 18 | 19 | 20 | class HookTest(TestCase): 21 | 22 | def setUp(self): 23 | # Haystack stores the connection in a global variable. This has to be reset 24 | # because otherwise the mock is still refrenced (Django < 1.8). 25 | haystack.connections.reload('default') 26 | 27 | self.sp = DocumentOnlySignalProcessor(haystack.connections, 28 | haystack.connection_router) 29 | 30 | def tearDown(self): 31 | engine = ElasticsearchMultilingualSearchEngine() 32 | es = engine.backend('default', **Data.connection_options) 33 | es.clear(models=None, commit=True) 34 | self.sp.teardown() 35 | time.sleep(1) 36 | 37 | def test_hook_called(self): 38 | documents = create_documents() 39 | engine = ElasticsearchMultilingualSearchEngine() 40 | es = engine.backend('default', **Data.connection_options) 41 | es.clear(models=None, commit=True) 42 | self.assertTrue(signals.post_save.has_listeners(sender=Document)) 43 | 44 | unified_index = engine.get_unified_index() 45 | index = unified_index.get_index(Document) 46 | iterable = Document.objects.all() 47 | es.update(index, iterable) 48 | time.sleep(1) 49 | 50 | self.assertTrue(es.conn.indices.exists('testproject-en')) 51 | count = es.conn.count(index='testproject-en') 52 | self.assertEqual(0, count['count']) 53 | 54 | # write a new entry in the database 55 | documents[0].save() 56 | reference = documents[0].object 57 | self.assertIsNotNone(reference.id) 58 | id = 'testproject.document.1' 59 | time.sleep(0.5) 60 | 61 | self.assertFalse(isinstance(es.conn, mock.Mock)) 62 | 63 | for language in es.languages: 64 | index_name = es._index_name_for_language(language) 65 | self.assertTrue(es.conn.indices.exists(index_name)) 66 | count = es.conn.count(index=index_name) 67 | print(count) 68 | 69 | self.assertEqual(1, count['count'], 'Index %s contains the document' % index_name) 70 | self.assertTrue(es.conn.exists(index=index_name, doc_type='_all', id=id)) 71 | doc = es.conn.get(index=index_name, id=id) 72 | self.assertTrue(doc['found']) 73 | self.assertEqual(doc['_type'], 'modelresult') 74 | self.assertEqual(doc['_source']['docid'], reference.docid) 75 | with translation.override(language): 76 | self.assertIn(escape(reference.text), doc['_source']['text']) 77 | 78 | # delete the object. The object needs to be removed from the index. 79 | reference.delete() 80 | for language in es.languages: 81 | index_name = es._index_name_for_language(language) 82 | self.assertTrue(es.conn.indices.exists(index_name)) 83 | count = es.conn.count(index=index_name) 84 | self.assertEqual(0, count['count']) 85 | -------------------------------------------------------------------------------- /tests/functional_tests/test_index_creation.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | from django.conf import settings 4 | from django.test import TestCase 5 | from django.utils import translation 6 | import time 7 | from django.utils.html import escape 8 | from testproject.models import Document, ParlerDocument 9 | from unittests.mocks import Data 10 | from multilingual.elasticsearch_backend import ElasticsearchMultilingualSearchBackend, \ 11 | ElasticsearchMultilingualSearchEngine 12 | 13 | 14 | class IndexTest(TestCase): 15 | """ 16 | Tests the index creation functions against a real Elasitcsearch server. 17 | """ 18 | fixtures = ['documents', 'parler_small'] 19 | index_exists = False 20 | 21 | def setUp(self): 22 | self.count = 52 23 | 24 | def tearDown(self): 25 | if self.index_exists: 26 | engine = ElasticsearchMultilingualSearchEngine() 27 | es = engine.backend('default', **Data.connection_options) 28 | es.clear(models=None, commit=True) 29 | time.sleep(1) 30 | 31 | def test_fixture_and_elasticsearch_up(self): 32 | documents = Document.objects.all() 33 | self.assertEqual(len(documents), self.count) 34 | languages = [l[0] for l in settings.LANGUAGES] 35 | es = ElasticsearchMultilingualSearchBackend('default', **Data.connection_options) 36 | self.assertEqual(languages, es.languages) 37 | 38 | self.assertTrue(es.conn.ping()) 39 | info = es.conn.info() 40 | self.assertEqual('elasticsearch', info['cluster_name']) 41 | self.assertEqual(200, info['status']) 42 | 43 | def test_multilingual_modeltranslations_update(self): 44 | """ 45 | Test the update method on the multilingual backend. 46 | """ 47 | engine = ElasticsearchMultilingualSearchEngine() 48 | es = engine.backend('default', **Data.connection_options) 49 | # the indexes don't exist yet. 50 | for language in es.languages: 51 | index_name = es._index_name_for_language(language) 52 | self.assertFalse(es.conn.indices.exists(index_name)) 53 | 54 | es.setup() 55 | self.index_exists = True 56 | unified_index = engine.get_unified_index() 57 | index = unified_index.get_index(Document) 58 | iterable = Document.objects.all() 59 | es.update(index, iterable) 60 | time.sleep(1) 61 | id = 'testproject.document.10' 62 | i = 0 63 | # use this document as a reference. 64 | reference = Document.objects.get(id=10) 65 | 66 | for language in es.languages: 67 | # check all language indexes 68 | index_name = es._index_name_for_language(language) 69 | self.assertTrue(es.conn.indices.exists(index_name)) 70 | count = es.conn.count(index=index_name) 71 | self.assertEqual(self.count, count['count']) 72 | 73 | # make sure the index has been created 74 | while not es.conn.exists(index=index_name, doc_type='_all', id=id) and i < 5: 75 | time.sleep(0.5) 76 | i += 1 77 | self.assertTrue(es.conn.exists(index=index_name, doc_type='_all', id=id)) 78 | # get the document with the above id from the correct index 79 | doc = es.conn.get(index=index_name, id=id) 80 | self.assertTrue(doc['found']) 81 | self.assertEqual(doc['_type'], 'modelresult') 82 | self.assertEqual(doc['_source']['docid'], reference.docid) 83 | with translation.override(language): 84 | self.assertIn(escape(reference.text), doc['_source']['text']) 85 | 86 | def test_parler_modeltranslations_update(self): 87 | """ 88 | Test the update method on the multiligual backend for parler models. 89 | """ 90 | engine = ElasticsearchMultilingualSearchEngine() 91 | es = engine.backend('default', **Data.connection_options) 92 | # the indexes don't exist yet. 93 | for language in es.languages: 94 | index_name = es._index_name_for_language(language) 95 | self.assertFalse(es.conn.indices.exists(index_name)) 96 | 97 | es.setup() 98 | self.index_exists = True 99 | unified_index = engine.get_unified_index() 100 | index = unified_index.get_index(Document) 101 | iterable = ParlerDocument.objects.prefetch_related('translations').all() 102 | es.update(index, iterable) 103 | time.sleep(1) 104 | id = 'testproject.parlerdocument.1' 105 | i = 0 106 | # use this document as a reference. 107 | reference = ParlerDocument.objects.get(id=1) 108 | 109 | for language in es.languages: 110 | # check all language indexes 111 | index_name = es._index_name_for_language(language) 112 | reference.set_current_language(language) 113 | self.assertTrue(es.conn.indices.exists(index_name)) 114 | count = es.conn.count(index=index_name) 115 | self.assertEqual(3, count['count']) 116 | 117 | # make sure the index has been created 118 | while not es.conn.exists(index=index_name, doc_type='_all', id=id) and i < 5: 119 | time.sleep(0.5) 120 | i += 1 121 | self.assertTrue(es.conn.exists(index=index_name, doc_type='_all', id=id)) 122 | # get the document with the above id from the correct index 123 | doc = es.conn.get(index=index_name, id=id) 124 | self.assertTrue(doc['found']) 125 | self.assertEqual(doc['_type'], 'modelresult') 126 | self.assertEqual(doc['_source']['docid'], reference.docid) 127 | with translation.override(language): 128 | self.assertIn(escape(reference.text), doc['_source']['text']) 129 | -------------------------------------------------------------------------------- /tests/functional_tests/test_query.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | from django.test import TestCase 4 | from django.utils import translation 5 | from django.utils.html import escape 6 | import haystack 7 | from haystack.query import SearchQuerySet 8 | import time 9 | 10 | from testproject.models import Document, ParlerDocument 11 | from unittests.mocks import Data 12 | 13 | try: 14 | from unittest import mock # python >= 3.3 15 | except ImportError: 16 | import mock # python 2 17 | 18 | from multilingual.elasticsearch_backend import ElasticsearchMultilingualSearchQuery, \ 19 | ElasticsearchMultilingualSearchEngine 20 | 21 | 22 | class BackendTest(TestCase): 23 | fixtures = ['small', 'parler_small'] 24 | maxDiff = None 25 | index_exists = False 26 | 27 | def setUp(self): 28 | self.count = 3 29 | haystack.connections.reload('default') 30 | 31 | def tearDown(self): 32 | if self.index_exists: 33 | engine = ElasticsearchMultilingualSearchEngine() 34 | es = engine.backend('default', **Data.connection_options) 35 | es.clear(models=None, commit=True) 36 | time.sleep(1) 37 | 38 | def test_live_query(self): 39 | engine = ElasticsearchMultilingualSearchEngine() 40 | es = engine.backend('default', **Data.connection_options) 41 | es.setup() 42 | sqs = SearchQuerySet() 43 | self.assertFalse(sqs.query.has_run()) 44 | self.assertIsInstance(sqs.query, ElasticsearchMultilingualSearchQuery) 45 | all_results = sqs.all() 46 | self.assertEqual(list(all_results), []) # execute a query 47 | self.assertTrue(isinstance(all_results, SearchQuerySet)) 48 | 49 | def test_query_method_modeltranslations(self): 50 | engine = ElasticsearchMultilingualSearchEngine() 51 | es = engine.backend('default', **Data.connection_options) 52 | es.setup() 53 | # fill up the index 54 | self.index_exists = True 55 | unified_index = engine.get_unified_index() 56 | index = unified_index.get_index(Document) 57 | iterable = Document.objects.all() 58 | es.update(index, iterable) 59 | time.sleep(1) 60 | id = 'testproject.document.2' 61 | i = 0 62 | # use this document as a reference. 63 | reference = Document.objects.get(id=2) 64 | 65 | for language in es.languages: 66 | # check all language indexes 67 | index_name = es._index_name_for_language(language) 68 | self.assertTrue(es.conn.indices.exists(index_name)) 69 | count = es.conn.count(index=index_name) 70 | self.assertEqual(self.count, count['count']) 71 | 72 | # make sure the index has been created 73 | while not es.conn.exists(index=index_name, doc_type='_all', id=id) and i < 5: 74 | time.sleep(0.5) 75 | i += 1 76 | self.assertTrue(es.conn.exists(index=index_name, doc_type='_all', id=id)) 77 | # get the document with the above id from the correct index 78 | doc = es.conn.get(index=index_name, id=id) 79 | self.assertTrue(doc['found']) 80 | self.assertEqual(doc['_type'], 'modelresult') 81 | self.assertEqual(doc['_source']['docid'], reference.docid) 82 | with translation.override(language): 83 | self.assertIn(escape(reference.text), doc['_source']['text']) 84 | 85 | with translation.override('en'): 86 | # test the search queryset 87 | sqs = SearchQuerySet() 88 | # Django 1.5 doesn't clean up patches 89 | self.assertFalse(isinstance(sqs.query.backend.conn, mock.Mock)) 90 | result = sqs.filter(content='United States') 91 | # result might be empty the first time this is called. (Django < 1.8) 92 | if len(result) == 0: 93 | result = sqs.filter(content='United States') 94 | self.assertEqual(2, len(result)) 95 | self.assertEqual('cyberpresse/2012/12/01/1564248', result[0].docid) 96 | self.assertEqual('cyberpresse/2012/12/01/1564741', result[1].docid) 97 | self.assertIn(escape(reference.text), result[1].text) 98 | 99 | with translation.override('de'): 100 | # test the search queryset 101 | sqs = SearchQuerySet() 102 | result = sqs.filter(content='Früherkennungstest') 103 | self.assertEqual(1, len(result)) 104 | self.assertEqual('cyberpresse/2012/12/01/1564741', result[0].docid) 105 | self.assertIn(escape(reference.text), result[0].text) 106 | 107 | def test_query_method_parler(self): 108 | engine = ElasticsearchMultilingualSearchEngine() 109 | es = engine.backend('default', **Data.connection_options) 110 | es.setup() 111 | # fill up the index 112 | self.index_exists = True 113 | unified_index = engine.get_unified_index() 114 | index = unified_index.get_index(Document) 115 | iterable = ParlerDocument.objects.prefetch_related('translations').all() 116 | es.update(index, iterable) 117 | time.sleep(1) 118 | id = 'testproject.parlerdocument.2' 119 | i = 0 120 | # use this document as a reference. 121 | reference = ParlerDocument.objects.get(id=2) 122 | 123 | for language in es.languages: 124 | # check all language indexes 125 | index_name = es._index_name_for_language(language) 126 | reference.set_current_language(language) 127 | 128 | self.assertTrue(es.conn.indices.exists(index_name)) 129 | count = es.conn.count(index=index_name) 130 | self.assertEqual(self.count, count['count']) 131 | 132 | # make sure the index has been created 133 | while not es.conn.exists(index=index_name, doc_type='_all', id=id) and i < 5: 134 | time.sleep(0.5) 135 | i += 1 136 | self.assertTrue(es.conn.exists(index=index_name, doc_type='_all', id=id)) 137 | # get the document with the above id from the correct index 138 | doc = es.conn.get(index=index_name, id=id) 139 | self.assertTrue(doc['found']) 140 | self.assertEqual(doc['_type'], 'modelresult') 141 | self.assertEqual(doc['_source']['docid'], reference.docid) 142 | with translation.override(language): 143 | self.assertIn(escape(reference.text), doc['_source']['text']) 144 | 145 | with translation.override('en'): 146 | # test the search queryset 147 | sqs = SearchQuerySet() 148 | reference.set_current_language('en') 149 | # Django 1.5 doesn't clean up patches 150 | self.assertFalse(isinstance(sqs.query.backend.conn, mock.Mock)) 151 | result = sqs.filter(content='United States') 152 | # result might be empty the first time this is called. (Django < 1.8) 153 | if len(result) == 0: 154 | result = sqs.filter(content='United States') 155 | self.assertEqual(2, len(result)) 156 | self.assertEqual('cyberpresse/2012/12/01/1564248', result[0].docid) 157 | self.assertEqual('cyberpresse/2012/12/01/1564741', result[1].docid) 158 | self.assertIn(escape(reference.text), result[1].text) 159 | 160 | with translation.override('de'): 161 | # test the search queryset 162 | sqs = SearchQuerySet() 163 | reference.set_current_language('de') 164 | result = sqs.filter(content='Früherkennungstest') 165 | self.assertEqual(1, len(result)) 166 | self.assertEqual('cyberpresse/2012/12/01/1564741', result[0].docid) 167 | self.assertIn(escape(reference.text), result[0].text) 168 | -------------------------------------------------------------------------------- /tests/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testproject.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /tests/requirements.txt: -------------------------------------------------------------------------------- 1 | Django>=1.5,<1.10 2 | elasticsearch==1.7.0 3 | urllib3>=1.10.4 4 | psycopg2 5 | ipdb 6 | django-haystack>=2.4.1, <2.5 7 | django-modeltranslation==0.9.1 8 | django-parler==1.5 9 | -------------------------------------------------------------------------------- /tests/testproject/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbaechler/django-multilingual-search/485c690d865da3267b19e073e28d3e2290f36611/tests/testproject/__init__.py -------------------------------------------------------------------------------- /tests/testproject/admin.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | from django.contrib import admin 4 | from .models import Document, ParlerDocument 5 | 6 | admin.site.register(Document) 7 | admin.site.register(ParlerDocument) 8 | -------------------------------------------------------------------------------- /tests/testproject/fixtures/parler_small.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fields": { 4 | "genre": "news", 5 | "origlang": "fr", 6 | "docid": "cyberpresse/2012/12/01/1564248" 7 | }, 8 | "model": "testproject.parlerdocument", 9 | "pk": 1 10 | }, 11 | { 12 | "fields": { 13 | "genre": "news", 14 | "origlang": "fr", 15 | "docid": "cyberpresse/2012/12/01/1564741" 16 | }, 17 | "model": "testproject.parlerdocument", 18 | "pk": 2 19 | }, 20 | { 21 | "fields": { 22 | "genre": "news", 23 | "origlang": "fr", 24 | "docid": "cyberpresse/2012/12/01/1566244" 25 | }, 26 | "model": "testproject.parlerdocument", 27 | "pk": 3 28 | }, 29 | { 30 | "model": "testproject.parlerdocumenttranslation", 31 | "fields": { 32 | "master": 1, 33 | "text": "Republik\u00e1n\u0161t\u00ed l\u00edd\u0159i od\u016fvodnili svou politiku nezbytnost\u00ed boje proti volebn\u00edm podvod\u016fm.\nBrennanovo st\u0159edisko v\u0161ak takov\u00fd podvod ozna\u010duje za m\u00fdtus s t\u00edm, \u017ee volebn\u00ed podvod je v USA m\u00e9n\u011b \u010dast\u00fd ne\u017e po\u010det osob, kter\u00e9 zem\u0159ou po z\u00e1sahu bleskem.\nRepublik\u00e1n\u0161t\u00ed advok\u00e1ti ostatn\u011b za posledn\u00edch deset let zaznamenali pouze 300 p\u0159\u00edpad\u016f volebn\u00edch podvod\u016f v USA.\n\nJedno je jist\u00e9: tato nov\u00e1 ustanoven\u00ed budou m\u00edt negativn\u00ed dopad na volebn\u00ed \u00fa\u010dast.\nV tomto smyslu tato opat\u0159en\u00ed \u010d\u00e1ste\u010dn\u011b podkopou americk\u00fd demokratick\u00fd syst\u00e9m.\n\nNa rozd\u00edl od Kanady maj\u00ed v USA odpov\u011bdnost za organizaci feder\u00e1ln\u00edch voleb jednotliv\u00e9 st\u00e1ty.\nA v tomto duchu v\u011bt\u0161ina americk\u00fdch vl\u00e1d od roku 2009 vyhla\u0161uje nov\u00e9 z\u00e1kony, kter\u00e9 zt\u011b\u017euj\u00ed proces volby nebo z\u00e1pisu do volebn\u00edho seznamu.\nTento jev zaznamenal rozmach po volb\u00e1ch v listopadu 2010, b\u011bhem nich\u017e p\u0159ibylo 675 nov\u00fdch republik\u00e1nsk\u00fdch z\u00e1stupc\u016f ve 26 st\u00e1tech.\nN\u00e1sledkem toho bylo jen za rok 2011 p\u0159edlo\u017eeno 180 n\u00e1vrh\u016f z\u00e1kona omezuj\u00edc\u00edch volebn\u00ed pr\u00e1vo ve 41 st\u00e1tech.\n\nNov\u00e9 volebn\u00ed z\u00e1kony vy\u017eaduj\u00ed, aby voli\u010di p\u0159edkl\u00e1dali pr\u016fkaz toto\u017enosti s fotografi\u00ed a doklad o americk\u00e9m st\u00e1tn\u00edm ob\u010danstv\u00ed.\nTyto z\u00e1kony nav\u00edc omezuj\u00ed obdob\u00ed pro volby v p\u0159edstihu, zneplat\u0148uj\u00ed pr\u00e1vo zapsat se na seznam voli\u010d\u016f v den kon\u00e1n\u00ed voleb a odn\u00edmaj\u00ed volebn\u00ed pr\u00e1vo ob\u010dan\u016fm se z\u00e1pisem v trestn\u00edm rejst\u0159\u00edku.\n\nP\u0159ed volbami v roce 2006 nevy\u017eadoval na voli\u010d\u00edch p\u0159edlo\u017een\u00ed p\u016fkazu toto\u017enosti s fotografi\u00ed \u017e\u00e1dn\u00fd americk\u00fd st\u00e1t.\nPrvn\u00edm st\u00e1tem, kter\u00fd tento po\u017eadavek zavedl, byla Indiana.\n\u00dastavnost indiansk\u00e9ho z\u00e1kona potvrdil v roce 2008 Nejvy\u0161\u0161\u00ed soud USA.\nRepublik\u00e1nsk\u00e9 \u00fa\u0159ady sp\u011bchaly s roz\u0161\u00ed\u0159en\u00edm tohoto postupu i do ostatn\u00edch st\u00e1t\u016f.\nZa posledn\u00ed dva roky podpo\u0159ily n\u00e1vrhy takov\u00fdch z\u00e1kon\u016f ve 34 st\u00e1tech s c\u00edlem p\u0159inutit voli\u010de, aby p\u0159edkl\u00e1dali pr\u016fkazy toto\u017enosti s fotografi\u00ed.\n\nJe t\u0159eba poznamenat, \u017ee na rozd\u00edl od Quebeku nemaj\u00ed ameri\u010dt\u00ed ob\u010dan\u00e9 univerz\u00e1ln\u00ed pr\u016fkaz\n\n", 34 | "language_code": "cs", 35 | "title": "Strategie republik\u00e1nsk\u00e9 strany proti Obamovu znovuzvolen\u00ed" 36 | }, 37 | "pk": 1 38 | }, 39 | { 40 | "model": "testproject.parlerdocumenttranslation", 41 | "fields": { 42 | "master": 2, 43 | "text": "Test PSA p\u0159in\u00e1\u0161el leckdy chybn\u00e9 v\u00fdsledky, kter\u00e9 byly nespr\u00e1vn\u011b negativn\u00ed \u010di dokonce nespr\u00e1vn\u011b pozitivn\u00ed, co\u017e vedlo ke zbyte\u010dn\u00fdm l\u00e9ka\u0159sk\u00fdm z\u00e1krok\u016fm.\nTo v\u0161e je\u0161t\u011b zv\u00fd\u0161ilo v\u00e1havost mu\u017e\u016f, kte\u0159\u00ed se ji\u017e tak zdr\u00e1hali na vy\u0161et\u0159en\u00ed v\u016fbec j\u00edt.\nNechat se vy\u0161et\u0159it nebo ne?\nPo\u017e\u00e1dali jsme o n\u00e1zor dva odborn\u00edky.\n\nVe studi\u00edch prov\u00e1d\u011bn\u00fdch v USA se projevila vysok\u00e1 m\u00edra kontaminace mezi jednotliv\u00fdmi testovan\u00fdmi skupinami, je tedy obt\u00ed\u017en\u00e9 interpretovat tyto v\u00fdsledky a p\u0159in\u00e9st hodnotn\u00e1 doporu\u010den\u00ed.\nDal\u0161\u00ed studie, tentokr\u00e1t evropsk\u00e1, konstatovala rozd\u00edlnou \u00famrtnost mezi pacienty, kte\u0159\u00ed podstoupili vy\u0161et\u0159en\u00ed, a t\u011bmi, kte\u0159\u00ed na n\u011b ne\u0161li.\n\nTato studie tak\u00e9 prok\u00e1zala po 12let\u00e9m odstupu, \u017ee ti, kdo na vy\u0161et\u0159en\u00ed nejdou, maj\u00ed o 30 a\u017e 40% vy\u0161\u0161\u00ed riziko v\u00fdskytu metast\u00e1z.\nDoporu\u010duji tedy vy\u0161et\u0159en\u00ed od 50 let v\u011bku nebo od 40 let, pokud v\u00e1\u0161 p\u0159\u00edm\u00fd p\u0159\u00edbuzn\u00fd m\u011bl rakovinu prostaty.\nOhro\u017een\u011bj\u0161\u00ed skupinou jsou rovn\u011b\u017e mu\u017ei afroamerick\u00e9ho p\u016fvodu.\n\nKl\u00ed\u010dem je p\u0159ijmout spr\u00e1vn\u00e9 rozhodnut\u00ed, jakmile je rakovina odhalena.\nExistuj\u00ed agresivn\u00ed druhy rakoviny a takov\u00e9 druhy, kter\u00e9 jsou nete\u010dn\u00e9.\nJe tedy nezbytn\u00e9 spr\u00e1vn\u011b vysv\u011btlit pacientovi m\u00edru nebezpe\u010dnosti jeho druhu rakoviny, nab\u00eddnout mu mo\u017en\u00e9 alternativy, nel\u00e9\u010dit nutn\u011b rakovinu prostaty, kter\u00e1 nem\u00e1 v dlouhodob\u00e9m horizontu dopad na \u017eivot, a zam\u011b\u0159it se v t\u011bchto p\u0159\u00edpadech sp\u00ed\u0161e na aktivn\u00ed dohled nad nemoc\u00ed.\n\nDnes se \u0159ada mu\u017e\u016f, u nich\u017e byla rakovina diagnostikov\u00e1na, nel\u00e9\u010d\u00ed, jeliko\u017e jejich druh rakoviny nen\u00ed agresivn\u00ed a neohro\u017euje je na \u017eivot\u011b.\nNavrhneme jim sp\u00ed\u0161e prov\u00e1d\u011bn\u00ed aktivn\u00edho dohledu a v p\u0159\u00edpad\u011b progrese nemoci jim nab\u00eddneme l\u00e9\u010dbu.\n\nSt\u00e1le \u010dast\u011bji a s v\u011bt\u0161\u00ed p\u0159esnost\u00ed stanovujeme krit\u00e9ria, je\u017e pom\u00e1haj\u00ed p\u0159i rozhodov\u00e1n\u00ed, kter\u00fd druh l\u00e9\u010dit a kter\u00fd ne.\nP\u0159esto tedy doporu\u010duji vy\u0161et\u0159en\u00ed absolvovat.\nD\u016fle\u017eit\u00e9 je ale absolvovat pohovor s l\u00e9ka\u0159em a stanovit, zda je vhodn\u00e9 vy\u0161et\u0159en\u00ed podstoupit nebo ne.\n\nVe spolupr\u00e1ci s Mezin\u00e1rodn\u00ed urologickou spole\u010dnost\u00ed vytvo\u0159ilo hnut\u00ed Movember n\u00e1stroj, kter\u00fd umo\u017e\u0148uje hodnotit pro a proti v souvislosti s vy\u0161et\u0159en\u00edm PSA.\nTento dokument si m\u016f\u017eete st\u00e1hnout (moment\u00e1ln\u011b v angli\u010dtin\u011b, p\u0159eklad bude k dispozici pozd\u011bji) na t\u00e9to adrese: http://ca.movember.com/fr/mens-health/prostate-cancer-screening\n\nPrevence onemocn\u011bn\u00ed\n\nBohu\u017eel neexistuje \u017e\u00e1dn\u00fd z\u00e1zra\u010dn\u00fd postup pro prevenci rakoviny.\nNavzdory pokrok\u016fm ve v\u00fdzkumu se zd\u00e1 nejlep\u0161\u00edm prost\u0159edkem pro omezen\u00ed rizik onemocn\u011bn\u00ed p\u0159ijet\u00ed z\u00e1sad zdrav\u00e9ho \u017eivotn\u00edho stylu.\n\nOdhaduje se, \u017ee kdyby v\u0161ichni zdrav\u011b jedli a dostate\u010dn\u011b se h\u00fdbali, dalo by se p\u0159edej\u00edt a\u017e 30% p\u0159\u00edpad\u016f rakoviny.\n\n", 44 | "language_code": "cs", 45 | "title": "Odhalov\u00e1n\u00ed rakoviny prostaty: absolvovat vy\u0161et\u0159en\u00ed nebo ne?" 46 | }, 47 | "pk": 2 48 | }, 49 | { 50 | "model": "testproject.parlerdocumenttranslation", 51 | "fields": { 52 | "master": 3, 53 | "text": "Ozn\u00e1men\u00ed o pravd\u011bpodobn\u00e9m objevu Higgsova bosonu vyvolal vloni v l\u00e9t\u011b opr\u00e1vn\u011bn\u00fd rozruch.\nExistuje n\u00e1zor, \u017ee tento boson se pod\u00edl\u00ed na mechanismu, kter\u00fd je odpov\u011bdn\u00fd za ve\u0161kerou hmotu ve vesm\u00edru.\nA d\u00e1le jde o posledn\u00ed \u010d\u00e1stici, jej\u00ed\u017e existenci p\u0159edpov\u00edd\u00e1 standardn\u00ed model - na\u0161e nejlep\u0161\u00ed nebo \"nejm\u00e9n\u011b \u0161patn\u00e9\" vysv\u011btlen\u00ed povahy a chov\u00e1n\u00ed hmoty - kter\u00fd v\u0161ak dosud nebyl empiricky pozorov\u00e1n.\n\nMezi fyziky v\u0161ak dosud nepanuje stoprocentn\u00ed jistota, \u017ee jde o Higgs\u016fv boson.\nNepochybuje se o tom, \u017ee m\u00e1me k dispozici zcela novou \u010d\u00e1stici, kter\u00e1 se velmi podob\u00e1 Higgsovu bosonu, jak je p\u0159edpov\u011bzen standardn\u00edm modelem.\nNov\u00e1 data zve\u0159ejn\u011bn\u00e1 tento t\u00fdden b\u011bhem velk\u00e9ho fyzik\u00e1ln\u00edho kongresu v Kj\u00f3tu jej sp\u00ed\u0161e potvrzuj\u00ed, chyb\u011bj\u00ed v\u0161ak je\u0161t\u011b ve\u0161ker\u00e9 \u00fadaje, abychom mohli m\u00edt absolutn\u00ed jistotu.\n\nNicm\u00e9n\u011b p\u0159edpokl\u00e1dejme, \u017ee jde o Higgs\u016fv boson, jeliko\u017e rizika omylu se jev\u00ed jako mal\u00e1, a pod\u00edvejme se na to, o\u010d vlastn\u011b jde.\n\nV tomto sv\u011bt\u011b plat\u00ed zcela nezpochybniteln\u00fd z\u00e1kon, podle n\u011bho\u017e se dv\u011b v\u011bci nemohou vyskytovat ve stejn\u00fd okam\u017eik na stejn\u00e9m m\u00edst\u011b.\nToto pravidlo nelze obej\u00edt - a nepokou\u0161ejte se o to p\u0159\u00edli\u0161 usilovn\u011b, jinak si ubl\u00ed\u017e\u00edte.\n\nI kdy\u017e je \u010d\u00e1sticov\u00e1 fyzika velmi podivn\u00fd sv\u011bt, ukazuje se, \u017ee i u n\u00ed plat\u00ed obdobn\u00fd z\u00e1kon: Pauliho vylu\u010dovac\u00ed princip, podle kter\u00e9ho nemohou dv\u011b \u010d\u00e1stice zab\u00edrat stejn\u00fd prostor ve stejn\u00e9m okam\u017eiku, pokud jsou ve stejn\u00e9m \"kvantov\u00e9m stavu\" - tento \"stav\" zhruba \u0159e\u010deno vytv\u00e1\u0159\u00ed n\u011bkter\u00e9 z jejich vlastnost\u00ed.\nD\u00e1le d\u011bl\u00ed fyzikov\u00e9 \u010d\u00e1stice na dv\u011b kategorie.\nNa jedn\u00e9 stran\u011b najdeme spo\u0159\u00e1dan\u00e9 ob\u010dany, neboli fermiony, kter\u00e9 poslu\u0161n\u011b dodr\u017euj\u00ed Pauliho princip.\nA na druh\u00e9m konci se pohybuj\u00ed bosony, podl\u00ed anarchist\u00e9, kte\u0159\u00ed si nev\u00e1\u017e\u00ed v\u016fbec ni\u010deho - rozhodn\u011b tedy ne tohoto principu, co\u017e znamen\u00e1, \u017ee mohou klidn\u011b b\u00fdt na stejn\u00e9m m\u00edst\u011b ve stejnou dobu.\n\nTyto bosony se d\u00e1le d\u011bl\u00ed na dv\u011b skupiny podle za\u0159\u00edzen\u00ed (mimochodem naprosto \u00fa\u017easn\u00e9ho), j\u00edm\u017e je The Particle Adventure, v laborato\u0159\u00edch Berkeley: mesony, kter\u00e9 zde nech\u00e1me bez pov\u0161imnut\u00ed, a \"silov\u00e9 \u010d\u00e1stice\", jimi\u017e se \u0161\u00ed\u0159\u00ed velk\u00e9 p\u0159\u00edrodn\u00ed s\u00edly a s nimi\u017e je Higgs\u016fv boson nejsp\u00ed\u0161 n\u011bjak\u00fdm zp\u016fsobem sp\u0159\u00edzn\u011bn.\n\nNutno v\u0161ak \u0159\u00edct, \u017ee tyto bosony nejsou tak exotick\u00e1 zv\u00ed\u0159\u00e1tka, jak by bylo mo\u017eno se domn\u00edvat.\nPokud tento \u010dl\u00e1nek p\u0159e\u010dtete, je to d\u00edky bosonu s neobvyklou banalitou: fotonu, neboli \"\u010d\u00e1stici sv\u011btla\", kter\u00fd je \"nositelem\" elektromagnetick\u00e9 s\u00edly.\nKdy\u017e toti\u017e \u010d\u00e1stice s elektrick\u00fdm n\u00e1bojem zrychl\u00ed nebo zm\u011bn\u00ed sv\u016fj sm\u011br, \"vyru\u0161\u00ed\" t\u00edm elektromagnetick\u00e9 pole v tomto konkr\u00e9tn\u00edm m\u00edst\u011b, podobn\u011b jako obl\u00e1zek hozen\u00fd do rybn\u00edka.\nZ tohoto \"vyru\u0161en\u00ed\" vznikne elektromagnetick\u00e1 vlna (sv\u011btlo, infra\u010derven\u00e9 nebo ultrafialov\u00e9 z\u00e1\u0159en\u00ed atd.)\n\n", 54 | "language_code": "cs", 55 | "title": "Higgs\u016fv boson prozkoum\u00e1n" 56 | }, 57 | "pk": 3 58 | }, 59 | { 60 | "model": "testproject.parlerdocumenttranslation", 61 | "fields": { 62 | "master": 1, 63 | "text": "Die F\u00fchrungskr\u00e4fte der Republikaner rechtfertigen ihre Politik mit der Notwendigkeit, den Wahlbetrug zu bek\u00e4mpfen.\nAllerdings h\u00e4lt das Brennan Center letzteres f\u00fcr einen Mythos, indem es bekr\u00e4ftigt, dass der Wahlbetrug in den USA seltener ist als die Anzahl der vom Blitzschlag get\u00f6teten Menschen.\nDie Rechtsanw\u00e4lte der Republikaner haben in 10 Jahren in den USA \u00fcbrigens nur 300 F\u00e4lle von Wahlbetrug verzeichnet.\n\nEins ist sicher: diese neuen Bestimmungen werden sich negativ auf die Wahlbeteiligung auswirken.\nIn diesem Sinne untergraben diese Ma\u00dfnahmen teilweise das demokratische System der USA.\n\nIm Gegensatz zu Kanada sind die US-Bundesstaaten f\u00fcr die Durchf\u00fchrung der Wahlen in den einzelnen Staaten verantwortlich.\nIn diesem Sinne hat die Mehrheit der amerikanischen Regierungen seit 2009 neue Gesetze verk\u00fcndet, die das Verfahren f\u00fcr die Registrierung oder den Urnengang erschweren.\nDieses Ph\u00e4nomen hat nach den Wahlen vom November 2010 an Bedeutung gewonnen, bei denen 675 neue republikanische Vertreter in 26 Staaten verzeichnet werden konnten.\nInfolgedessen wurden 180 Gesetzesentw\u00fcrfe allein im Jahr 2011 eingef\u00fchrt, die die Aus\u00fcbung des Wahlrechts in 41 Staaten einschr\u00e4nken.\n\nDie neuen Wahlgesetze verlangen, dass die W\u00e4hler einen Lichtbildausweis und einen Nachweis der US-Staatsb\u00fcrgerschaft vorlegen.\nDar\u00fcber hinaus werden durch diese Gesetze ebenfalls die Zeitr\u00e4ume f\u00fcr die vorzeitige Stimmabgabe verk\u00fcrzt, das Recht f\u00fcr ung\u00fcltig erkl\u00e4rt, sich am Wahltag als W\u00e4hler zu registrieren, und Staatsb\u00fcrgern das Wahlrecht abgesprochen, f\u00fcr die eine Gerichtsakte vorliegt.\n\nVor den Wahlen von 2006 hat kein US-Staat von den W\u00e4hlern verlangt, einen Lichtbildausweis vorzuzeigen.\nIndiana war der erste Bundesstaat, der eine derartige Forderung erhoben hat.\nDer Oberste Gerichtshof der Vereinigten Staaten best\u00e4tigte im Jahr 2008 die Verfassungsm\u00e4\u00dfigkeit des Gesetzes von Indiana.\nDie republikanischen Beh\u00f6rden beeilten sich, diese Praxis auf andere Staaten auszudehnen.\n\n", 64 | "language_code": "de", 65 | "title": "Eine republikanische Strategie, um der Wiederwahl von Obama entgegenzutreten" 66 | }, 67 | "pk": 53 68 | }, 69 | { 70 | "model": "testproject.parlerdocumenttranslation", 71 | "fields": { 72 | "master": 2, 73 | "text": "Der PSA-Test weise in der Tat manchmal fehlerhafte Ergebnisse auf, mit falschen negativen oder aber auch falschen positiven Ergebnissen, die zu unn\u00f6tigen medizinischen Eingriffen f\u00fchren.\nDies f\u00fchrt zu st\u00e4rkerem Z\u00f6gern der bereits unentschlossenen M\u00e4nner f\u00fcr die Durchf\u00fchrung von Fr\u00fcherkennungstests.\nSollte der Test gemacht werden oder nicht?\nWir haben die Meinung von zwei Fach\u00e4rzten eingeholt.\n\nBei den in den USA durchgef\u00fchrten Studien bestanden zahlreiche St\u00f6rfaktoren zwischen den Kontrollgruppen, sodass es schwierig ist, diese Daten zu interpretieren und eindeutige Empfehlungen zu geben.\nEine weitere Studie, dieses Mal aus Europa, kam zu der Schlussfolgerung, dass ein Unterschied bei der Sterblichkeit von Patienten mit und ohne Fr\u00fcherkennung besteht.\n\nDiese Studie hat ebenfalls gezeigt, dass bei einer Nachbeobachtung nach 12 Jahren die Wahrscheinlichkeit der Bildung von Metastasen um 30 bis 40% h\u00f6her ist, wenn keine Fr\u00fcherkennung durchgef\u00fchrt wurde.\nDeshalb empfehle ich den Test ab einem Alter von 50 Jahren bzw. 40 Jahren, wenn man einen direkten Verwandten hat, der bereits an Prostatakrebs erkrankt war.\nBei M\u00e4nnern afro-amerikanischer Herkunft besteht ebenfalls ein h\u00f6heres Risiko.\n\nDas Wichtigste ist, die richtige Entscheidung zu treffen, sobald eine Krebserkrankung erkannt wurde.\nEs gibt Krebsarten, die aggressiv und andere, die indolent sind.\nDem Patienten muss das Ausma\u00df des Risikos seiner Krebserkrankung wirklich verst\u00e4ndlich gemacht werden, indem ihm die m\u00f6glichen Optionen aufgezeigt werden, bei denen Prostatakrebse unbehandelt bleiben kann, wenn er die Lebensqualit\u00e4t auf lange Sicht nicht beeintr\u00e4chtigt, und man sich in diesen F\u00e4llen eher f\u00fcr eine aktive \u00dcberwachung der Krankheit entscheidet.\n\nHeute findet bei vielen M\u00e4nnern, bei denen man Krebs erkannt hat, keine Behandlung statt, da ihr Krebs nicht aggressiv ist und keine Bedrohung f\u00fcr ihr Leben darstellt.\n\n", 74 | "language_code": "de", 75 | "title": "Prostatakrebsfr\u00fcherkennung: sollte der Test gemacht werden oder nicht?" 76 | }, 77 | "pk": 54 78 | }, 79 | { 80 | "model": "testproject.parlerdocumenttranslation", 81 | "fields": { 82 | "master": 3, 83 | "text": "Die Ank\u00fcndigung der wahrscheinlichen Entdeckung des Higgs-Bosons hat im letzten Sommer ein gewisses Aufsehen erregt, und dies aus gutem Grund.\nMan glaubt in der Tat, dass dieses Boson an nichts weniger als am Mechanismus beteiligt ist, der f\u00fcr die Masse aller Objekte im Universum verantwortlich ist.\nUnd schlie\u00dflich handelt es sich um das letzte Teilchen, dessen Existenz vom Standardmodell - unserer besten oder \"am wenigsten falschen\" Erkl\u00e4rung der Natur und dem Verhalten der Materie - vorausgesagt, aber empirisch noch nicht beobachtet wurde.\n\nAber f\u00fcr die Physiker ist es noch nicht vollst\u00e4ndig sicher, dass es sich wirklich um das Higgs handelt.\nWir wissen ohne den Schatten eines Zweifels, dass wir ein echtes neues Teilchen haben, und dass es dem vom Standardmodell vorausgesagten Higgs-Boson stark \u00e4hnelt.\nDar\u00fcber hinaus scheint dies durch neue Daten best\u00e4tigt zu werden, die in dieser Woche auf einem gro\u00dfen Physik-Kongress in Kyoto vorgestellt wurden, aber es fehlen noch Daten, um dar\u00fcber vollkommen sicher zu sein.\n\nGehen wir trotzdem davon aus, dass es sich tats\u00e4chlich um das Higgs handelt, da scheinbar nur ein geringes Risiko besteht, sich zu t\u00e4uschen, und schauen wir uns an, um was es geht.\n\nEs gibt in dieser Welt ein zwangsl\u00e4ufig unumg\u00e4ngliches Gesetz, das bewirkt, dass zwei Objekte nicht gleichzeitig am selben Ort vorhanden sein k\u00f6nnen.\nEs ist nicht m\u00f6glich, gegen diese Regel zu versto\u00dfen - und versuchen Sie es nicht zu stark, da Sie sich wehtun werden.\n\n", 84 | "language_code": "de", 85 | "title": "Das Higgs-Boson analysiert" 86 | }, 87 | "pk": 55 88 | }, 89 | { 90 | "model": "testproject.parlerdocumenttranslation", 91 | "fields": { 92 | "master": 1, 93 | "text": "Republican leaders justified their policy by the need to combat electoral fraud.\nHowever, the Brennan Centre considers this a myth, stating that electoral fraud is rarer in the United States than the number of people killed by lightning.\nIndeed, Republican lawyers identified only 300 cases of electoral fraud in the United States in a decade.\n\nOne thing is certain: these new provisions will have a negative impact on voter turn-out.\nIn this sense, the measures will partially undermine the American democratic system.\n\nUnlike in Canada, the American States are responsible for the organisation of federal elections in the United States.\nIt is in this spirit that a majority of American governments have passed new laws since 2009 making the registration or voting process more difficult.\nThis phenomenon gained momentum following the November 2010 elections, which saw 675 new Republican representatives added in 26 States.\nAs a result, 180 bills restricting the exercise of the right to vote in 41 States were introduced in 2011 alone.\n\nThe new election laws require voters to show a photo ID card and proof of US citizenship.\nFurthermore, these laws also reduce early voting periods, invalidate the right to register as a voter on election day and withdraw the right to vote of citizens with a criminal record.\n\nBefore the 2006 elections, no US State required voters to show a photo ID card.\nIndiana was the first State to impose such a requirement.\nIn 2008, the Supreme Court of the United States upheld the constitutionality of the Indiana law.\nThe Republican authorities were quick to extend this practice to other States.\nOver the past two years, they sponsored bills in 34 States to force voters to show a photo ID card.\n\nIt is important to note that, unlike Quebec, American citizens do not have a universal ID card such as the health insurance card.\nIn fact, 11% of American citizens, i.e. 21 million people of voting age, do not possess a photo ID card issued by a government agency of their State.\nIn addition, five million new voters in 2012 do not have such identification.\n", 94 | "language_code": "en", 95 | "title": "A Republican strategy to counter the re-election of Obama " 96 | }, 97 | "pk": 105 98 | }, 99 | { 100 | "model": "testproject.parlerdocumenttranslation", 101 | "fields": { 102 | "master": 2, 103 | "text": "Indeed, the PSA test sometimes shows erroneous results with false negative or even false positive results, which involve unnecessary medical interventions.\nEnough to make already reluctant men hesitate to take screening tests.\nTake the test or not?\nWe asked two specialists for their opinion.\n\nIn studies conducted in the United States, there was a lot of contamination between control groups, so it is difficult to interpret the data and make firm recommendations.\nAnother study, this time a European one, concluded that there was a difference in mortality between patients who were screened and those who were not.\n\nThis study also showed, with a follow-up after 12 years, that it is between 30 and 40% more likely for metastases to occur in the absence of screening.\nI therefore recommend the test from age 50, or 40 if you have a direct relative who previously had prostate cancer.\nAfrican-American men are also more at risk.\n\nThe key is to make the right decision once cancer has been detected.\nThere are aggressive cancers and others that are indolent.\nThe patient really needs to be made to understand the degree of risk of his cancer, by offering him the options available, not necessarily treating prostate cancers that are not long-term life threatening, and opting instead, in such cases, for active monitoring of the disease.\n\n", 104 | "language_code": "en", 105 | "title": "Prostate cancer screening: take the test or not?" 106 | }, 107 | "pk": 106 108 | }, 109 | { 110 | "model": "testproject.parlerdocumenttranslation", 111 | "fields": { 112 | "master": 3, 113 | "text": "The announcement of the probable discovery of the Higgs boson created quite a stir last summer, and with good reason.\nIndeed, it is believed that this boson is part of the mechanism responsible for the mass of everything in the Universe, no less.\nAlso it is the last particle whose existence is predicted by the Standard Model - our best or \"less worse\" explanation of the nature and behaviour of matter - but which has not yet been observed empirically.\n\nBut for physicists, it is still not completely sure that it really is the Higgs.\nWe know without a shadow of a doubt that it is a new authentic particle, and greatly resembles the Higgs boson predicted by the Standard Model.\nIn addition, new data unveiled this week at a large physics Congress in Kyoto seem to confirm this, but there are still insufficient data to be perfectly sure.\n\nBut let's suppose that it really is the Higgs, since the chances of being mistaken seem slim, and see what it is.\n\nIn our world, there is a fatally unavoidable law which states that two things cannot meet at the same place at the same time.\nThere's no way to break this rule - and don't try too hard, you'll go mad.\n\nHowever, even though particle physics is a very strange world, it turns out that it also has a law of the same kind: the Pauli exclusion principle, which states that two particles cannot occupy the same space at the same time if they are in the same \"quantum state\" - this \"state\" consisting roughly of certain of their characteristics.\nBased on this, physicists classify particles into two categories.\nIn one corner we have good citizens called fermions, who wisely obey the Pauli principle.\nWhile lurking in the other are the bosons, a nasty band of anarchists who respect nothing - at all events, not this principle, which means that they can indeed be found in the same place at the same time.\n\nThese bosons are then divided into two groups, according to the Berkeley Labs Particle Adventure site (absolutely extraordinary, by the way): mesons, which we will not discuss here, and \"force particles\" by which the great forces of nature are propagated and to which the Higgs boson may be somehow related.\n\nThese bosons, it must be stressed here, are not all such exotic bugs as you might think.\nIn fact, if you can read this article, it is thanks to an extraordinarily banal boson: the photon, or the \"light particle\" which is the \"messenger\"\n\n", 114 | "language_code": "en", 115 | "title": "The Higgs boson revealed" 116 | }, 117 | "pk": 107 118 | }, 119 | { 120 | "model": "testproject.parlerdocumenttranslation", 121 | "fields": { 122 | "master": 1, 123 | "text": "Los dirigentes republicanos justificaron su pol\u00edtica por la necesidad de luchar contra el fraude electoral.\nAhora bien, el Centro Brennan considera esto \u00faltimo un mito y afirma que el fraude electoral es menos frecuente en los Estados Unidos que el n\u00famero de personas que mueren a causa de la ca\u00edda de un rayo.\nDe hecho, los abogados republicanos no han encontrado m\u00e1s que 300 casos de fraude electoral en los Estados Unidos en diez a\u00f1os.\n\nUna cosa es cierta: esas nuevas disposiciones afectar\u00e1n negativamente a la tasa de participaci\u00f3n.\nEn ese sentido, estas medidas minar\u00e1n en parte el sistema democr\u00e1tico americano.\n\nAl contrario de lo que ocurre en Canad\u00e1, los estados americanos son responsables de la organizaci\u00f3n de las elecciones federales en los Estados Unidos.\nY en esa misma l\u00ednea una mayor\u00eda de los gobiernos americanos promulgaron, a partir de 2009, nuevas leyes que dificultaban el proceso de inscripci\u00f3n o de votaci\u00f3n.\nEste fen\u00f3meno se ha extendido tras las elecciones de noviembre de 2010, que vieron el aumento de 675 nuevos representantes republicanos en 26 estados.\nEn consecuencia, durante el a\u00f1o 2011 se introdujeron 180 proyectos de ley que restring\u00edan el ejercicio del derecho de voto en 41 estados.\n\nLas nuevas leyes electorales exigen que los electores presenten un documento de identidad con una fotograf\u00eda, adem\u00e1s de una prueba de ciudadan\u00eda americana.\nPor otra parte, esas leyes reducen los per\u00edodos de voto anticipado, invalidan el derecho a inscribirse como elector en el d\u00eda del escrutinio y retiran su derecho al voto a los ciudadanos con antecedentes penales.\n\nAntes de las elecciones de 2006, ning\u00fan estado americano exig\u00eda que los electores presentaran un documento de identidad con fotograf\u00eda.\nEl Estado de Indiana fue el primero en exigirlo.\nEl Tribunal Supremo de los Estados Unidos confirm\u00f3 en 2008 la constitucionalidad de la ley de Indiana.\nPor ello, las autoridades republicanas se apresuraron a extender esa pr\u00e1ctica a otros estados.\n\n", 124 | "language_code": "es", 125 | "title": "Una estrategia republicana para obstaculizar la reelecci\u00f3n de Obama" 126 | }, 127 | "pk": 157 128 | }, 129 | { 130 | "model": "testproject.parlerdocumenttranslation", 131 | "fields": { 132 | "master": 2, 133 | "text": "En efecto, el test de PSA presenta, en ocasiones, resultados err\u00f3neos, con falsos resultados negativos o incluso falsos resultados positivos, tras los que se decide realizar intervenciones m\u00e9dicas in\u00fatiles.\nEs un motivo m\u00e1s que suficiente para hacer dudar a los hombres, ya reticentes de por s\u00ed, sobre si deber\u00edan hacerse o no los tests de detecci\u00f3n.\n\u00bfHacerse el test o no?\nHemos pedido consejo a dos especialistas.\n\nEn los estudios realizados en los Estados Unidos se detect\u00f3 un gran \u00edndice de contagios entre los grupos de muestra, por lo que es dif\u00edcil interpretar esos datos y hacer recomendaciones firmes.\nPor su parte, el estudio europeo mostr\u00f3 cierta diferencia de mortalidad entre los pacientes que se hab\u00edan realizado la detecci\u00f3n y los que no.\n\nEl estudio, con un seguimiento a los 12 a\u00f1os, demostr\u00f3 adem\u00e1s que existe entre el 30 y el 40% de posibilidades de padecer met\u00e1stasis si no se ha realizado el test de detecci\u00f3n.\nRecomiendo, por tanto, el test a partir de los 50 a\u00f1os, o a partir de los 40 a\u00f1os si tu padre ha sufrido c\u00e1ncer de pr\u00f3stata.\nLos hombres de origen afroamericano tienen un \u00edndice de riesgo m\u00e1s elevado.\n\nLa clave es tomar una buena decisi\u00f3n una vez detectado el c\u00e1ncer.\nHay c\u00e1nceres agresivos y otros c\u00e1nceres que son indolentes.\nEs verdaderamente necesario lograr que el paciente comprenda el grado de riesgo de su c\u00e1ncer. Se le deben ofrecer todas las opciones posibles y no necesariamente tratar los c\u00e1nceres de pr\u00f3stata que no atenten contra la vida a largo plazo, en cuyo caso se debe optar m\u00e1s bien por una vigilancia activa de la enfermedad.\n\nHoy en d\u00eda muchos hombres a los que se les ha detectado un c\u00e1ncer no son tratados, puesto que dicho c\u00e1ncer no es agresivo ni entra\u00f1a un riesgo para su vida.\nEn su lugar, les sugerimos una vigilancia activa de la enfermedad y, si \u00e9sta progresa, les ofrecemos un tratamiento.\n\n", 134 | "language_code": "es", 135 | "title": "Detecci\u00f3n del c\u00e1ncer de pr\u00f3stata: \u00bfHacerse el test o no hac\u00e9rselo?" 136 | }, 137 | "pk": 158 138 | }, 139 | { 140 | "model": "testproject.parlerdocumenttranslation", 141 | "fields": { 142 | "master": 3, 143 | "text": "El anuncio del probable descubrimiento del bos\u00f3n de Higgs gener\u00f3 una gran conmoci\u00f3n el verano pasado, y con raz\u00f3n.\nSe cree, en efecto, que este bos\u00f3n es part\u00edcipe del mecanismo responsable de la masa de todo lo que existe en el universo, nada m\u00e1s y nada menos. \nY lo que es m\u00e1s, se trata de la part\u00edcula cuya existencia predijo el modelo est\u00e1ndar: nuestra mejor o \"menos mala\" explicaci\u00f3n de la naturaleza y del comportamiento de la materia, que a\u00fan no ha sido observado emp\u00edricamente.\n\nPero para los f\u00edsicos no est\u00e1 totalmente claro que se trate de Higgs.\nSabemos sin lugar a dudas que existe una nueva part\u00edcula y que se parece mucho al bos\u00f3n de Higgs predicho por el modelo est\u00e1ndar.\nAdem\u00e1s, nuevos datos desvelados esta semana en un importante congreso de f\u00edsica celebrado en Kioto parecen confirmar que s\u00ed lo es, aunque a\u00fan faltan m\u00e1s datos para estar completamente seguros.\n\nDe todas maneras, suponemos que se trata de Higgs, ya que las posibilidades de equivocarse parecen pocas. Veremos de qu\u00e9 se trata.\n\nHay, en este gran mundo, una ley generalizada y ineludible que implica que dos cosas no pueden encontrarse en el mismo lugar al mismo tiempo.\nNo hay manera de infringir esa norma y no lo intente demasiado, porque terminar\u00e1 haci\u00e9ndose da\u00f1o.\n\nAunque la f\u00edsica de las part\u00edculas sea un mundo muy complejo, se ha demostrado que tambi\u00e9n en ella existe una ley de estas caracter\u00edsticas: el principio de exclusi\u00f3n de Pauli, que estipula que dos part\u00edculas no pueden ocupar el mismo espacio al mismo tiempo si est\u00e1n en el mismo \"estado cu\u00e1ntico\"; un \"estado\" que consta, grosso modo, de algunas de sus caracter\u00edsticas.\nLos f\u00edsicos clasifican las part\u00edculas en dos categor\u00edas.\nPor una parte nos encontramos con los buenos ciudadanos llamados fermiones, que obedecen sabiamente al principio de Pauli.\nY por otra est\u00e1n los bosones, una sucia panda de anarquistas que no tiene respeto por nada, o al menos no por este principio, lo que significa que pueden encontrarse en el mismo lugar y al mismo tiempo.\n\nSeg\u00fan la p\u00e1gina web The Particle Adventure de los Laboratorios Berkeley que, por cierto, es extraordinaria, los bosones se dividen en dos grupos: los mesones, de los que no hablaremos aqu\u00ed, y las \"part\u00edculas de fuerza\", por las que las grandes fuerzas de la naturaleza se propagan y con las cuales el bos\u00f3n de Higgs estar\u00eda de alguna forma emparentado.\n\nEstos bosones, cabr\u00eda subrayar aqu\u00ed, no son los bichos ex\u00f3ticos que podr\u00edamos creer.\n\n", 144 | "language_code": "es", 145 | "title": "El bos\u00f3n de Higgs en detalle" 146 | }, 147 | "pk": 159 148 | }, 149 | { 150 | "model": "testproject.parlerdocumenttranslation", 151 | "fields": { 152 | "master": 1, 153 | "text": "Les dirigeants r\u00e9publicains justifi\u00e8rent leur politique par la n\u00e9cessit\u00e9 de lutter contre la fraude \u00e9lectorale.\nOr, le Centre Brennan consid\u00e8re cette derni\u00e8re comme un mythe, affirmant que la fraude \u00e9lectorale est plus rare aux \u00c9tats-Unis que le nombre de personnes tu\u00e9es par la foudre.\nD'ailleurs, les avocats r\u00e9publicains n'ont recens\u00e9 que 300 cas de fraude \u00e9lectorale aux \u00c9tats-Unis en dix ans.\n\nUne chose est certaine: ces nouvelles dispositions influenceront n\u00e9gativement le taux de participation.\nEn ce sens, ces mesures mineront en partie le syst\u00e8me d\u00e9mocratique am\u00e9ricain.\n\nContrairement au Canada, les \u00c9tats am\u00e9ricains sont responsables de l'organisation des \u00e9lections f\u00e9d\u00e9rales aux \u00c9tats-Unis.\nC'est dans cet esprit qu'une majorit\u00e9 de gouvernements am\u00e9ricains promulgu\u00e8rent \u00e0 partir de 2009 de nouvelles lois rendant plus difficile le processus d'inscription ou de vote.\nCe ph\u00e9nom\u00e8ne a pris de l'ampleur apr\u00e8s les \u00e9lections de novembre 2010 qui virent s'ajouter 675 nouveaux repr\u00e9sentants r\u00e9publicains dans 26 \u00c9tats.\nEn cons\u00e9quence, 180 projets de lois restreignant l'exercice du droit de vote dans 41 \u00c9tats furent introduits durant la seule ann\u00e9e de 2011.\n\nLes nouvelles lois \u00e9lectorales exigent que les \u00e9lecteurs pr\u00e9sentent une carte d'identit\u00e9 avec photo et une preuve de citoyennet\u00e9 am\u00e9ricaine.\nPar ailleurs, ces lois r\u00e9duisent aussi les p\u00e9riodes de vote par anticipation, invalident le droit de s'inscrire comme \u00e9lecteur le jour du scrutin et retirent aux citoyens ayant un dossier judiciaire leur droit de vote.\n\nAvant les \u00e9lections de 2006, aucun \u00c9tat am\u00e9ricain n'exigeait des \u00e9lecteurs de pr\u00e9senter une carte d'identit\u00e9 avec photo.\nL'Indiana fut le premier \u00c9tat \u00e0 poser une telle exigence.\nLa Cour Supr\u00eame des \u00c9tats-Unis confirma en 2008 la constitutionnalit\u00e9 de la loi de l'Indiana.\nLes autorit\u00e9s r\u00e9publicaines s'empress\u00e8rent d'\u00e9tendre cette pratique \u00e0 d'autres \u00c9tats.\nAu cours des deux derni\u00e8res ann\u00e9es, elles parrainaient des projets de loi dans 34 \u00c9tats pour forcer les \u00e9lecteurs \u00e0 pr\u00e9senter une carte d'identit\u00e9 avec photo.\n\nIl est important de noter que, contrairement au Qu\u00e9bec, les citoyens am\u00e9ricains ne disposent pas de carte d'identit\u00e9 universelle comme la carte de l'assurance maladie.\nDe fait, 11% des citoyens am\u00e9ricains, soit 21 millions de personnes en \u00e2ge de voter, ne poss\u00e8dent pas de cartes d'identit\u00e9 avec photo \u00e9mises par une agence gouvernementale de leur \u00c9tat.\n\n", 154 | "language_code": "fr", 155 | "title": "Une strat\u00e9gie r\u00e9publicaine pour contrer la r\u00e9\u00e9lection d'Obama" 156 | }, 157 | "pk": 209 158 | }, 159 | { 160 | "model": "testproject.parlerdocumenttranslation", 161 | "fields": { 162 | "master": 2, 163 | "text": "En effet, le test d'APS pr\u00e9senterait parfois des r\u00e9sultats erron\u00e9s, avec de faux r\u00e9sultats n\u00e9gatifs ou encore de faux positifs, lesquels entra\u00eenent des interventions m\u00e9dicales inutiles.\nDe quoi faire h\u00e9siter encore plus les hommes d\u00e9j\u00e0 r\u00e9ticents \u00e0 passer des tests de d\u00e9pistage.\nPasser le test ou non?\nNous avons demand\u00e9 l'avis de deux sp\u00e9cialistes.\n\nDans les \u00e9tudes men\u00e9es aux \u00c9tats-Unis, il y avait beaucoup de contamination entre les groupes t\u00e9moins, il est donc difficile d'interpr\u00e9ter ces donn\u00e9es et d'avoir des recommandations fermes.\nUne autre \u00e9tude, celle-l\u00e0 europ\u00e9enne, a conclu \u00e0 une diff\u00e9rence de mortalit\u00e9 entre les patients qui ont eu un d\u00e9pistage et ceux qui n'en ont pas eu.\n\nCette \u00e9tude a aussi d\u00e9montr\u00e9, avec un suivi apr\u00e8s 12 ans, qu'on a entre 30 et 40% de plus de chances d'avoir des m\u00e9tastases si on n'est pas d\u00e9pist\u00e9.\nJe recommande donc le test \u00e0 partir de 50 ans, ou \u00e0 partir de 40 ans si on a un parent direct qui a d\u00e9j\u00e0 eu un cancer de la prostate.\nLes hommes d'origine afro-am\u00e9ricaine sont \u00e9galement plus \u00e0 risque.\n\nLa cl\u00e9 est de prendre la bonne d\u00e9cision une fois qu'on a d\u00e9tect\u00e9 un cancer.\nIl y a des cancers agressifs et d'autres qui sont indolents.\nIl faut vraiment faire comprendre au patient le degr\u00e9 de risque de son cancer, en lui offrant les options possibles, en ne traitant pas n\u00e9cessairement les cancers de la prostate qui ne portent pas atteinte \u00e0 la vie \u00e0 long terme, et en optant plut\u00f4t, dans ces cas-l\u00e0, pour une surveillance active de la maladie.\n\nAujourd'hui, beaucoup d'hommes chez qui on d\u00e9tecte un cancer ne seront pas trait\u00e9s, car leur cancer n'est pas agressif et ne menace pas leur vie.\nOn va leur sugg\u00e9rer de faire de la surveillance active et si la maladie progresse, on va leur offrir un traitement.\n\nDe plus en plus, on d\u00e9termine avec pr\u00e9cision des crit\u00e8res pour d\u00e9cider qui devrait ou ne devrait pas \u00eatre trait\u00e9.\nJe recommande donc quand m\u00eame de passer le test.\n\n", 164 | "language_code": "fr", 165 | "title": "D\u00e9pistage du cancer de la prostate: passer le test ou non?" 166 | }, 167 | "pk": 210 168 | }, 169 | { 170 | "model": "testproject.parlerdocumenttranslation", 171 | "fields": { 172 | "master": 3, 173 | "text": "L'annonce de la d\u00e9couverte probable du boson de Higgs a cr\u00e9\u00e9 tout un \u00e9moi, l'\u00e9t\u00e9 dernier, et pour cause.\nOn croit en effet que ce boson participe au m\u00e9canisme responsable de la masse de toute chose dans l'Univers, rien que \u00e7a.\nEt puis, il s'agit de la derni\u00e8re particule dont l'existence est pr\u00e9dite par le Mod\u00e8le standard - notre meilleure, ou \"moins pire\" explication de la nature et du comportement de la mati\u00e8re - mais qui n'a pas encore \u00e9t\u00e9 observ\u00e9e empiriquement.\n\nMais pour les physiciens, il n'est pas encore compl\u00e8tement s\u00fbr qu'il s'agisse bien du Higgs.\nOn sait sans l'ombre d'un doute que l'on tient une authentique nouvelle particule, et qu'elle ressemble beaucoup au boson de Higgs pr\u00e9dit par le Mod\u00e8le standard.\nEn outre, de nouvelles donn\u00e9es d\u00e9voil\u00e9es cette semaine lors d'un grand congr\u00e8s de physique, \u00e0 Kyoto, semblent le confirmer, mais il manque encore des donn\u00e9es pour en \u00eatre parfaitement certain.\n\nSupposons tout de m\u00eame qu'il s'agisse bien du Higgs, puisque les chances de se tromper semblent minces, et voyons de quoi il s'agit.\n\nIl y a, en ce bas monde, une loi fatalement incontournable voulant que deux choses ne peuvent pas se retrouver au m\u00eame endroit en m\u00eame temps.\nPas moyen d'enfreindre cette r\u00e8gle - et n'essayez pas trop fort, vous allez vous faire mal.\n\nOr m\u00eame si la physique des particules est un monde bien \u00e9trange, il s'av\u00e8re qu'elle a, elle aussi, une loi de ce genre: le principe d'exclusion de Pauli, qui stipule que deux particules ne peuvent pas occuper le m\u00eame espace au m\u00eame moment si elles sont dans le m\u00eame \"\u00e9tat quantique\" - cet \"\u00e9tat\" consistant grosso modo en certaines de leurs caract\u00e9ristiques.\nDe l\u00e0, les physiciens classent les particules en deux cat\u00e9gories.\nDans un coin, on trouve de bons citoyens nomm\u00e9s fermions, qui ob\u00e9issent sagement au principe de Pauli.\nEt dans l'autre s'agitent les bosons, une sale bande d'anarchistes qui n'ont de respect pour rien - en tout cas, pas pour ce principe, ce qui signifie qu'ils peuvent bel et bien se trouver au m\u00eame endroit, en m\u00eame temps.\n\nCes bosons se divisent ensuite en deux groupes, selon le site (absolument extraordinaire, d'ailleurs) The Particle Adventure, des Laboratoires Berkeley: les m\u00e9sons, que nous n'aborderons pas ici, et les \"particules de force\", par lesquelles les grandes forces de la nature se propagent et auxquelles le boson de Higgs serait en quelque sorte apparent\u00e9.\n\nCes bosons-l\u00e0, il faut le souligner ici, ne sont pas tous des bestioles aussi exotiques qu'on pourrait le croire.\nEn fait, si vous parvenez \u00e0 lire cette chronique, c'est gr\u00e2ce \u00e0 un boson d'une extraordinaire banalit\u00e9: le photon, ou la \"particule de lumi\u00e8re\" qui est le \"messager\"\n\n", 174 | "language_code": "fr", 175 | "title": "Le boson de Higgs d\u00e9cortiqu\u00e9" 176 | }, 177 | "pk": 211 178 | }, 179 | { 180 | "model": "testproject.parlerdocumenttranslation", 181 | "fields": { 182 | "master": 1, 183 | "text": "\u041b\u0438\u0434\u0435\u0440\u044b \u0440\u0435\u0441\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u043d\u0446\u0435\u0432 \u043e\u043f\u0440\u0430\u0432\u0434\u044b\u0432\u0430\u043b\u0438 \u0441\u0432\u043e\u044e \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u0431\u043e\u0440\u044c\u0431\u044b \u0441 \u0444\u0430\u043b\u044c\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f\u043c\u0438 \u043d\u0430 \u0432\u044b\u0431\u043e\u0440\u0430\u0445.\n\u041e\u0434\u043d\u0430\u043a\u043e \u0432 \u0426\u0435\u043d\u0442\u0440\u0435 \u0411\u0440\u0435\u043d\u043d\u0430\u043d\u0430 \u0441\u0447\u0438\u0442\u0430\u044e\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u043c\u0438\u0444\u043e\u043c, \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u044f, \u0447\u0442\u043e \u0441\u043b\u0443\u0447\u0430\u0438 \u0444\u0430\u043b\u044c\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439 \u043d\u0430 \u0432\u044b\u0431\u043e\u0440\u0430\u0445 \u0432 \u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u043d\u044b\u0445 \u0428\u0442\u0430\u0442\u0430\u0445 \u0431\u043e\u043b\u0435\u0435 \u0440\u0435\u0434\u043a\u0438, \u0447\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0438 \u0441\u043c\u0435\u0440\u0442\u0438 \u043e\u0442 \u0443\u0434\u0430\u0440\u0430 \u043c\u043e\u043b\u043d\u0438\u0438.\n\u041a \u0442\u043e\u043c\u0443 \u0436\u0435 \u044e\u0440\u0438\u0441\u0442\u044b \u0440\u0435\u0441\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u043d\u0446\u0435\u0432 \u043d\u0430\u0441\u0447\u0438\u0442\u0430\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e 300 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u044d\u043b\u0435\u043a\u0442\u043e\u0440\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0430\u043b\u044c\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439 \u0432 \u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u043d\u044b\u0445 \u0428\u0442\u0430\u0442\u0430\u0445 \u0437\u0430 \u0434\u0435\u0441\u044f\u0442\u044c \u043b\u0435\u0442.\n\n\u041e\u0434\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0441 \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e: \u044d\u0442\u0438 \u043d\u043e\u0432\u044b\u0435 \u0442\u0435\u043d\u0434\u0435\u043d\u0446\u0438\u0438 \u043e\u043a\u0430\u0436\u0443\u0442 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u0432\u043b\u0438\u044f\u043d\u0438\u0435 \u043d\u0430 \u044f\u0432\u043a\u0443 \u0438\u0437\u0431\u0438\u0440\u0430\u0442\u0435\u043b\u0435\u0439.\n\u0412 \u044d\u0442\u043e\u043c \u0441\u043c\u044b\u0441\u043b\u0435 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u0434\u0438\u0441\u043a\u0440\u0435\u0434\u0438\u0442\u0438\u0440\u0443\u044e\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0430\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u043e\u0439 \u0434\u0435\u043c\u043e\u043a\u0440\u0430\u0442\u0438\u0438.\n\n\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u041a\u0430\u043d\u0430\u0434\u044b \u0430\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u0438\u0435 \u0448\u0442\u0430\u0442\u044b \u043d\u0435\u0441\u0443\u0442 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0437\u0430 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044e \u0444\u0435\u0434\u0435\u0440\u0430\u043b\u044c\u043d\u044b\u0445 \u0432\u044b\u0431\u043e\u0440\u043e\u0432 \u0432 \u0421\u0428\u0410.\n\u0418\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c\u0441\u0442\u0432 \u0448\u0442\u0430\u0442\u043e\u0432 \u0441 2009 \n\n", 184 | "language_code": "ru", 185 | "title": "\u0420\u0435\u0441\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u043d\u0441\u043a\u0430\u044f \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f \u0441\u043e\u043f\u0440\u043e\u0442\u0438\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c\u0443 \u0438\u0437\u0431\u0440\u0430\u043d\u0438\u044e \u041e\u0431\u0430\u043c\u044b" 186 | }, 187 | "pk": 261 188 | }, 189 | { 190 | "model": "testproject.parlerdocumenttranslation", 191 | "fields": { 192 | "master": 2, 193 | "text": "\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0442\u0435\u0441\u0442 \u043d\u0430 \u041f\u0421\u0410 \u0434\u0430\u0435\u0442 \u0438\u043d\u043e\u0433\u0434\u0430 \u043e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b, \u043b\u0436\u0435\u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0435, \u0430 \u0438\u043d\u043e\u0433\u0434\u0430 \u0438 \u043b\u0436\u0435\u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043a \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u043e\u043c\u0443 \u043c\u0435\u0434\u0438\u0446\u0438\u043d\u0441\u043a\u043e\u043c\u0443 \u0432\u043c\u0435\u0448\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0443.\n\u041c\u0443\u0436\u0447\u0438\u043d\u0430\u043c, \u0438 \u0442\u0430\u043a \u043d\u0435\u043e\u0445\u043e\u0442\u043d\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0449\u0438\u043c \u0434\u0438\u0441\u043f\u0430\u043d\u0441\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044e, \u0435\u0441\u0442\u044c \u043e\u0442 \u0447\u0435\u0433\u043e \u0437\u0430\u0441\u043e\u043c\u043d\u0435\u0432\u0430\u0442\u044c\u0441\u044f \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435.\n\u041f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u0435\u0441\u0442 \u0438\u043b\u0438 \u043d\u0435\u0442?\n\u041c\u044b \u0441\u043f\u0440\u043e\u0441\u0438\u043b\u0438 \u043c\u043d\u0435\u043d\u0438\u0435 \u0434\u0432\u0443\u0445 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u043e\u0432.\n\n\u0412 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f\u0445, \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0445 \u0432 \u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u043d\u044b\u0445 \u0428\u0442\u0430\u0442\u0430\u0445, \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u043b\u0438\u0441\u044c \u043c\u043d\u043e\u0433\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u043b\u0443\u0447\u0430\u0438 \u0437\u0430\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u0440\u0435\u0434\u0438 \u0433\u0440\u0443\u043f\u043f \u0438\u0441\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u044b\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u0440\u0443\u0434\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0442\u0440\u0443\u0434\u043d\u043e \u0432\u044b\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u0447\u0435\u0442\u043a\u0438\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438.\n\u0414\u0440\u0443\u0433\u043e\u0435 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u043d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u0435\u0432\u0440\u043e\u043f\u0435\u0439\u0441\u043a\u043e\u0435, \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b\u043e \u0440\u0430\u0437\u043d\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0441\u043c\u0435\u0440\u0442\u043d\u043e\u0441\u0442\u0438 \u0443 \u0442\u0435\u0445 \u043f\u0430\u0446\u0438\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0448\u043b\u0438 \u0441\u043a\u0440\u0438\u043d\u0438\u043d\u0433, \u0438 \u0442\u0435\u0445, \u043a\u0442\u043e \u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043b.\n\n\u042d\u0442\u043e \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e, \u043f\u043e\u0441\u043b\u0435 12-\u043b\u0435\u0442\u043d\u0435\u0433\u043e \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u044f, \u0447\u0442\u043e \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u0430\u0441\u0442\u0430\u0437 \u043d\u0430 30-40% \u0432\u044b\u0448\u0435 \u0443 \u0442\u0435\u0445, \u043a\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0448\u0435\u043b \u0441\u043a\u0440\u0438\u043d\u0438\u043d\u0433.\n\u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u044f \u0431\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043b \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u0435\u0441\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 50\n\n", 194 | "language_code": "ru", 195 | "title": "\u0421\u043a\u0440\u0438\u043d\u0438\u043d\u0433 \u0440\u0430\u043a\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0436\u0435\u043b\u0435\u0437\u044b: \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u0435\u0441\u0442 \u0438\u043b\u0438 \u043d\u0435\u0442?" 196 | }, 197 | "pk": 262 198 | }, 199 | { 200 | "model": "testproject.parlerdocumenttranslation", 201 | "fields": { 202 | "master": 3, 203 | "text": "\u041c\u0438\u043d\u0443\u0432\u0448\u0438\u043c \u043b\u0435\u0442\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0443\u0447\u0435\u043d\u044b\u043c, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c \u0431\u043e\u0437\u043e\u043d \u0425\u0438\u0433\u0433\u0441\u0430, \u0432\u044b\u0437\u0432\u0430\u043b\u043e \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0430\u0436\u0438\u043e\u0442\u0430\u0436 - \u0438 \u043d\u0435 \u0431\u0435\u0437 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0439.\n\u0421\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0431\u043e\u0437\u043e\u043d \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0435\u0442 \u043c\u0430\u0441\u0441\u0443 \u0432\u0441\u0435\u0445 \u0447\u0430\u0441\u0442\u0438\u0446 \u0432\u043e \u0412\u0441\u0435\u043b\u0435\u043d\u043d\u043e\u0439, \u043d\u0438 \u043c\u043d\u043e\u0433\u043e \u043d\u0438 \u043c\u0430\u043b\u043e.\n\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u044d\u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0447\u0430\u0441\u0442\u0438\u0446\u0430, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 - \u043d\u0430\u0448\u0435\u0433\u043e \u043b\u0443\u0447\u0448\u0435\u0433\u043e, \u0438\u043b\u0438, \u0432\u043e \u0432\u0441\u044f\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \"\u043d\u0430\u0438\u043c\u0435\u043d\u0435\u0435 \u043d\u0435\u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e\u0433\u043e\" \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u0440\u043e\u0434\u044b \u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043c\u0430\u0442\u0435\u0440\u0438\u0438, - \u043d\u043e \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0440\u0430\u043d\u044c\u0448\u0435 \u043d\u0435 \u0443\u0434\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c \u043e\u043f\u044b\u0442\u043d\u044b\u043c \u043f\u0443\u0442\u0435\u043c.\n\n\u041d\u043e \u0444\u0438\u0437\u0438\u043a\u0438 \u0435\u0449\u0435 \u043d\u0435 \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0440\u0435\u0447\u044c \u0438\u0434\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u043e \u0431\u043e\u0437\u043e\u043d\u0435 \u0425\u0438\u0433\u0433\u0441\u0430.\n\u041c\u044b \u0437\u043d\u0430\u0435\u043c, \u0431\u0435\u0437 \u0442\u0435\u043d\u0438 \u0441\u043e\u043c\u043d\u0435\u043d\u0438\u044f, \u0447\u0442\u043e \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0434\u0435\u043b\u043e \u0441 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u043e\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438\u0446\u0435\u0439 \u0438 \u0447\u0442\u043e \u043e\u043d\u0430 \u0441\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u0431\u043e\u0437\u043e\u043d \u0425\u0438\u0433\u0433\u0441\u0430, \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e.\n\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043d\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u043d\u0430 \u044d\u0442\u043e\u0439 \u043d\u0435\u0434\u0435\u043b\u0435 \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u043a\u0440\u0443\u043f\u043d\u043e\u043c \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u043a\u043e\u043d\u0433\u0440\u0435\u0441\u0441\u0435 \u0432 \u041a\u0438\u043e\u0442\u043e, \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u044d\u0442\u043e \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u044e\u0442, \u0445\u043e\u0442\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0439 \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0435\u0449\u0435 \u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0435\u0442.\n\n\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0432\u0441\u0435 \u0436\u0435, \u0447\u0442\u043e \u0440\u0435\u0447\u044c \u0438\u0434\u0435\u0442 \u043e \u0431\u043e\u0437\u043e\u043d\u0435 \u0425\u0438\u0433\u0433\u0441\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u0448\u0430\u043d\u0441\u044b \u043e\u0448\u0438\u0431\u0438\u0442\u044c\u0441\u044f \u043a\u0430\u0436\u0443\u0442\u0441\u044f \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438, \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0436\u0435 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442.\n\n\u0415\u0441\u0442\u044c, \u0432 \u044d\u0442\u043e\u043c \u043c\u0438\u0440\u0435 \u043e\u0434\u0438\u043d \u0437\u0430\u043a\u043e\u043d \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u0435\u0438\u0437\u0431\u0435\u0436\u043d\u044b\u0439, \u0433\u043b\u0430\u0441\u044f\u0449\u0438\u0439, \u0447\u0442\u043e \u0434\u0432\u0435 \u0432\u0435\u0449\u0438 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u0438 \u0442\u043e\u043c\n\n", 204 | "language_code": "ru", 205 | "title": "\u0411\u043e\u0437\u043e\u043d \u0425\u0438\u0433\u0433\u0441\u0430 \u0432 \u0434\u0435\u0442\u0430\u043b\u044f\u0445" 206 | }, 207 | "pk": 263 208 | } 209 | ] 210 | -------------------------------------------------------------------------------- /tests/testproject/fixtures/small.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "model": "testproject.document", 4 | "fields": { 5 | "text_es": "Los dirigentes republicanos justificaron su pol\u00edtica por la necesidad de luchar contra el fraude electoral.\nAhora bien, el Centro Brennan considera esto \u00faltimo un mito y afirma que el fraude electoral es menos frecuente en los Estados Unidos que el n\u00famero de personas que mueren a causa de la ca\u00edda de un rayo.\nDe hecho, los abogados republicanos no han encontrado m\u00e1s que 300 casos de fraude electoral en los Estados Unidos en diez a\u00f1os.\n\nUna cosa es cierta: esas nuevas disposiciones afectar\u00e1n negativamente a la tasa de participaci\u00f3n.\nEn ese sentido, estas medidas minar\u00e1n en parte el sistema democr\u00e1tico americano.\n\nAl contrario de lo que ocurre en Canad\u00e1, los estados americanos son responsables de la organizaci\u00f3n de las elecciones federales en los Estados Unidos.\nY en esa misma l\u00ednea una mayor\u00eda de los gobiernos americanos promulgaron, a partir de 2009, nuevas leyes que dificultaban el proceso de inscripci\u00f3n o de votaci\u00f3n.\nEste fen\u00f3meno se ha extendido tras las elecciones de noviembre de 2010, que vieron el aumento de 675 nuevos representantes republicanos en 26 estados.\nEn consecuencia, durante el a\u00f1o 2011 se introdujeron 180 proyectos de ley que restring\u00edan el ejercicio del derecho de voto en 41 estados.\n\nLas nuevas leyes electorales exigen que los electores presenten un documento de identidad con una fotograf\u00eda, adem\u00e1s de una prueba de ciudadan\u00eda americana.\nPor otra parte, esas leyes reducen los per\u00edodos de voto anticipado, invalidan el derecho a inscribirse como elector en el d\u00eda del escrutinio y retiran su derecho al voto a los ciudadanos con antecedentes penales.\n\nAntes de las elecciones de 2006, ning\u00fan estado americano exig\u00eda que los electores presentaran un documento de identidad con fotograf\u00eda.\nEl Estado de Indiana fue el primero en exigirlo.\nEl Tribunal Supremo de los Estados Unidos confirm\u00f3 en 2008 la constitucionalidad de la ley de Indiana.\nPor ello, las autoridades republicanas se apresuraron a extender esa pr\u00e1ctica a otros estados.\n\n", 6 | "title_es": "Una estrategia republicana para obstaculizar la reelecci\u00f3n de Obama", 7 | "title_fr": "Une strat\u00e9gie r\u00e9publicaine pour contrer la r\u00e9\u00e9lection d'Obama", 8 | "genre": "news", 9 | "text": "Republican leaders justified their policy by the need to combat electoral fraud.\nHowever, the Brennan Centre considers this a myth, stating that electoral fraud is rarer in the United States than the number of people killed by lightning.\nIndeed, Republican lawyers identified only 300 cases of electoral fraud in the United States in a decade.\n\nOne thing is certain: these new provisions will have a negative impact on voter turn-out.\nIn this sense, the measures will partially undermine the American democratic system.\n\nUnlike in Canada, the American States are responsible for the organisation of federal elections in the United States.\nIt is in this spirit that a majority of American governments have passed new laws since 2009 making the registration or voting process more difficult.\nThis phenomenon gained momentum following the November 2010 elections, which saw 675 new Republican representatives added in 26 States.\nAs a result, 180 bills restricting the exercise of the right to vote in 41 States were introduced in 2011 alone.\n\nThe new election laws require voters to show a photo ID card and proof of US citizenship.\nFurthermore, these laws also reduce early voting periods, invalidate the right to register as a voter on election day and withdraw the right to vote of citizens with a criminal record.\n\nBefore the 2006 elections, no US State required voters to show a photo ID card.\nIndiana was the first State to impose such a requirement.\nIn 2008, the Supreme Court of the United States upheld the constitutionality of the Indiana law.\nThe Republican authorities were quick to extend this practice to other States.\nOver the past two years, they sponsored bills in 34 States to force voters to show a photo ID card.\n\nIt is important to note that, unlike Quebec, American citizens do not have a universal ID card such as the health insurance card.\nIn fact, 11% of American citizens, i.e. 21 million people of voting age, do not possess a photo ID card issued by a government agency of their State.\nIn addition, five million new voters in 2012 do not have such identification.\n", 10 | "title_en": "A Republican strategy to counter the re-election of Obama ", 11 | "title_ru": "\u0420\u0435\u0441\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u043d\u0441\u043a\u0430\u044f \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f \u0441\u043e\u043f\u0440\u043e\u0442\u0438\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c\u0443 \u0438\u0437\u0431\u0440\u0430\u043d\u0438\u044e \u041e\u0431\u0430\u043c\u044b", 12 | "text_cs": "Republik\u00e1n\u0161t\u00ed l\u00edd\u0159i od\u016fvodnili svou politiku nezbytnost\u00ed boje proti volebn\u00edm podvod\u016fm.\nBrennanovo st\u0159edisko v\u0161ak takov\u00fd podvod ozna\u010duje za m\u00fdtus s t\u00edm, \u017ee volebn\u00ed podvod je v USA m\u00e9n\u011b \u010dast\u00fd ne\u017e po\u010det osob, kter\u00e9 zem\u0159ou po z\u00e1sahu bleskem.\nRepublik\u00e1n\u0161t\u00ed advok\u00e1ti ostatn\u011b za posledn\u00edch deset let zaznamenali pouze 300 p\u0159\u00edpad\u016f volebn\u00edch podvod\u016f v USA.\n\nJedno je jist\u00e9: tato nov\u00e1 ustanoven\u00ed budou m\u00edt negativn\u00ed dopad na volebn\u00ed \u00fa\u010dast.\nV tomto smyslu tato opat\u0159en\u00ed \u010d\u00e1ste\u010dn\u011b podkopou americk\u00fd demokratick\u00fd syst\u00e9m.\n\nNa rozd\u00edl od Kanady maj\u00ed v USA odpov\u011bdnost za organizaci feder\u00e1ln\u00edch voleb jednotliv\u00e9 st\u00e1ty.\nA v tomto duchu v\u011bt\u0161ina americk\u00fdch vl\u00e1d od roku 2009 vyhla\u0161uje nov\u00e9 z\u00e1kony, kter\u00e9 zt\u011b\u017euj\u00ed proces volby nebo z\u00e1pisu do volebn\u00edho seznamu.\nTento jev zaznamenal rozmach po volb\u00e1ch v listopadu 2010, b\u011bhem nich\u017e p\u0159ibylo 675 nov\u00fdch republik\u00e1nsk\u00fdch z\u00e1stupc\u016f ve 26 st\u00e1tech.\nN\u00e1sledkem toho bylo jen za rok 2011 p\u0159edlo\u017eeno 180 n\u00e1vrh\u016f z\u00e1kona omezuj\u00edc\u00edch volebn\u00ed pr\u00e1vo ve 41 st\u00e1tech.\n\nNov\u00e9 volebn\u00ed z\u00e1kony vy\u017eaduj\u00ed, aby voli\u010di p\u0159edkl\u00e1dali pr\u016fkaz toto\u017enosti s fotografi\u00ed a doklad o americk\u00e9m st\u00e1tn\u00edm ob\u010danstv\u00ed.\nTyto z\u00e1kony nav\u00edc omezuj\u00ed obdob\u00ed pro volby v p\u0159edstihu, zneplat\u0148uj\u00ed pr\u00e1vo zapsat se na seznam voli\u010d\u016f v den kon\u00e1n\u00ed voleb a odn\u00edmaj\u00ed volebn\u00ed pr\u00e1vo ob\u010dan\u016fm se z\u00e1pisem v trestn\u00edm rejst\u0159\u00edku.\n\nP\u0159ed volbami v roce 2006 nevy\u017eadoval na voli\u010d\u00edch p\u0159edlo\u017een\u00ed p\u016fkazu toto\u017enosti s fotografi\u00ed \u017e\u00e1dn\u00fd americk\u00fd st\u00e1t.\nPrvn\u00edm st\u00e1tem, kter\u00fd tento po\u017eadavek zavedl, byla Indiana.\n\u00dastavnost indiansk\u00e9ho z\u00e1kona potvrdil v roce 2008 Nejvy\u0161\u0161\u00ed soud USA.\nRepublik\u00e1nsk\u00e9 \u00fa\u0159ady sp\u011bchaly s roz\u0161\u00ed\u0159en\u00edm tohoto postupu i do ostatn\u00edch st\u00e1t\u016f.\nZa posledn\u00ed dva roky podpo\u0159ily n\u00e1vrhy takov\u00fdch z\u00e1kon\u016f ve 34 st\u00e1tech s c\u00edlem p\u0159inutit voli\u010de, aby p\u0159edkl\u00e1dali pr\u016fkazy toto\u017enosti s fotografi\u00ed.\n\nJe t\u0159eba poznamenat, \u017ee na rozd\u00edl od Quebeku nemaj\u00ed ameri\u010dt\u00ed ob\u010dan\u00e9 univerz\u00e1ln\u00ed pr\u016fkaz\n\n", 13 | "title_cs": "Strategie republik\u00e1nsk\u00e9 strany proti Obamovu znovuzvolen\u00ed", 14 | "docid": "cyberpresse/2012/12/01/1564248", 15 | "text_de": "Die F\u00fchrungskr\u00e4fte der Republikaner rechtfertigen ihre Politik mit der Notwendigkeit, den Wahlbetrug zu bek\u00e4mpfen.\nAllerdings h\u00e4lt das Brennan Center letzteres f\u00fcr einen Mythos, indem es bekr\u00e4ftigt, dass der Wahlbetrug in den USA seltener ist als die Anzahl der vom Blitzschlag get\u00f6teten Menschen.\nDie Rechtsanw\u00e4lte der Republikaner haben in 10 Jahren in den USA \u00fcbrigens nur 300 F\u00e4lle von Wahlbetrug verzeichnet.\n\nEins ist sicher: diese neuen Bestimmungen werden sich negativ auf die Wahlbeteiligung auswirken.\nIn diesem Sinne untergraben diese Ma\u00dfnahmen teilweise das demokratische System der USA.\n\nIm Gegensatz zu Kanada sind die US-Bundesstaaten f\u00fcr die Durchf\u00fchrung der Wahlen in den einzelnen Staaten verantwortlich.\nIn diesem Sinne hat die Mehrheit der amerikanischen Regierungen seit 2009 neue Gesetze verk\u00fcndet, die das Verfahren f\u00fcr die Registrierung oder den Urnengang erschweren.\nDieses Ph\u00e4nomen hat nach den Wahlen vom November 2010 an Bedeutung gewonnen, bei denen 675 neue republikanische Vertreter in 26 Staaten verzeichnet werden konnten.\nInfolgedessen wurden 180 Gesetzesentw\u00fcrfe allein im Jahr 2011 eingef\u00fchrt, die die Aus\u00fcbung des Wahlrechts in 41 Staaten einschr\u00e4nken.\n\nDie neuen Wahlgesetze verlangen, dass die W\u00e4hler einen Lichtbildausweis und einen Nachweis der US-Staatsb\u00fcrgerschaft vorlegen.\nDar\u00fcber hinaus werden durch diese Gesetze ebenfalls die Zeitr\u00e4ume f\u00fcr die vorzeitige Stimmabgabe verk\u00fcrzt, das Recht f\u00fcr ung\u00fcltig erkl\u00e4rt, sich am Wahltag als W\u00e4hler zu registrieren, und Staatsb\u00fcrgern das Wahlrecht abgesprochen, f\u00fcr die eine Gerichtsakte vorliegt.\n\nVor den Wahlen von 2006 hat kein US-Staat von den W\u00e4hlern verlangt, einen Lichtbildausweis vorzuzeigen.\nIndiana war der erste Bundesstaat, der eine derartige Forderung erhoben hat.\nDer Oberste Gerichtshof der Vereinigten Staaten best\u00e4tigte im Jahr 2008 die Verfassungsm\u00e4\u00dfigkeit des Gesetzes von Indiana.\nDie republikanischen Beh\u00f6rden beeilten sich, diese Praxis auf andere Staaten auszudehnen.\n\n", 16 | "text_en": "Republican leaders justified their policy by the need to combat electoral fraud.\nHowever, the Brennan Centre considers this a myth, stating that electoral fraud is rarer in the United States than the number of people killed by lightning.\nIndeed, Republican lawyers identified only 300 cases of electoral fraud in the United States in a decade.\n\nOne thing is certain: these new provisions will have a negative impact on voter turn-out.\nIn this sense, the measures will partially undermine the American democratic system.\n\nUnlike in Canada, the American States are responsible for the organisation of federal elections in the United States.\nIt is in this spirit that a majority of American governments have passed new laws since 2009 making the registration or voting process more difficult.\nThis phenomenon gained momentum following the November 2010 elections, which saw 675 new Republican representatives added in 26 States.\nAs a result, 180 bills restricting the exercise of the right to vote in 41 States were introduced in 2011 alone.\n\nThe new election laws require voters to show a photo ID card and proof of US citizenship.\nFurthermore, these laws also reduce early voting periods, invalidate the right to register as a voter on election day and withdraw the right to vote of citizens with a criminal record.\n\nBefore the 2006 elections, no US State required voters to show a photo ID card.\nIndiana was the first State to impose such a requirement.\nIn 2008, the Supreme Court of the United States upheld the constitutionality of the Indiana law.\n\n", 17 | "origlang": "fr", 18 | "title_de": "Eine republikanische Strategie, um der Wiederwahl von Obama entgegenzutreten", 19 | "text_ru": "\u041b\u0438\u0434\u0435\u0440\u044b \u0440\u0435\u0441\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u043d\u0446\u0435\u0432 \u043e\u043f\u0440\u0430\u0432\u0434\u044b\u0432\u0430\u043b\u0438 \u0441\u0432\u043e\u044e \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u0431\u043e\u0440\u044c\u0431\u044b \u0441 \u0444\u0430\u043b\u044c\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f\u043c\u0438 \u043d\u0430 \u0432\u044b\u0431\u043e\u0440\u0430\u0445.\n\u041e\u0434\u043d\u0430\u043a\u043e \u0432 \u0426\u0435\u043d\u0442\u0440\u0435 \u0411\u0440\u0435\u043d\u043d\u0430\u043d\u0430 \u0441\u0447\u0438\u0442\u0430\u044e\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u043c\u0438\u0444\u043e\u043c, \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u044f, \u0447\u0442\u043e \u0441\u043b\u0443\u0447\u0430\u0438 \u0444\u0430\u043b\u044c\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439 \u043d\u0430 \u0432\u044b\u0431\u043e\u0440\u0430\u0445 \u0432 \u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u043d\u044b\u0445 \u0428\u0442\u0430\u0442\u0430\u0445 \u0431\u043e\u043b\u0435\u0435 \u0440\u0435\u0434\u043a\u0438, \u0447\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0438 \u0441\u043c\u0435\u0440\u0442\u0438 \u043e\u0442 \u0443\u0434\u0430\u0440\u0430 \u043c\u043e\u043b\u043d\u0438\u0438.\n\u041a \u0442\u043e\u043c\u0443 \u0436\u0435 \u044e\u0440\u0438\u0441\u0442\u044b \u0440\u0435\u0441\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u043d\u0446\u0435\u0432 \u043d\u0430\u0441\u0447\u0438\u0442\u0430\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e 300 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u044d\u043b\u0435\u043a\u0442\u043e\u0440\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0430\u043b\u044c\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439 \u0432 \u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u043d\u044b\u0445 \u0428\u0442\u0430\u0442\u0430\u0445 \u0437\u0430 \u0434\u0435\u0441\u044f\u0442\u044c \u043b\u0435\u0442.\n\n\u041e\u0434\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0441 \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e: \u044d\u0442\u0438 \u043d\u043e\u0432\u044b\u0435 \u0442\u0435\u043d\u0434\u0435\u043d\u0446\u0438\u0438 \u043e\u043a\u0430\u0436\u0443\u0442 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u0432\u043b\u0438\u044f\u043d\u0438\u0435 \u043d\u0430 \u044f\u0432\u043a\u0443 \u0438\u0437\u0431\u0438\u0440\u0430\u0442\u0435\u043b\u0435\u0439.\n\u0412 \u044d\u0442\u043e\u043c \u0441\u043c\u044b\u0441\u043b\u0435 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u0434\u0438\u0441\u043a\u0440\u0435\u0434\u0438\u0442\u0438\u0440\u0443\u044e\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0430\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u043e\u0439 \u0434\u0435\u043c\u043e\u043a\u0440\u0430\u0442\u0438\u0438.\n\n\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u041a\u0430\u043d\u0430\u0434\u044b \u0430\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u0438\u0435 \u0448\u0442\u0430\u0442\u044b \u043d\u0435\u0441\u0443\u0442 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0437\u0430 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044e \u0444\u0435\u0434\u0435\u0440\u0430\u043b\u044c\u043d\u044b\u0445 \u0432\u044b\u0431\u043e\u0440\u043e\u0432 \u0432 \u0421\u0428\u0410.\n\u0418\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c\u0441\u0442\u0432 \u0448\u0442\u0430\u0442\u043e\u0432 \u0441 2009 \n\n", 20 | "title": "A Republican strategy to counter the re-election of Obama ", 21 | "text_fr": "Les dirigeants r\u00e9publicains justifi\u00e8rent leur politique par la n\u00e9cessit\u00e9 de lutter contre la fraude \u00e9lectorale.\nOr, le Centre Brennan consid\u00e8re cette derni\u00e8re comme un mythe, affirmant que la fraude \u00e9lectorale est plus rare aux \u00c9tats-Unis que le nombre de personnes tu\u00e9es par la foudre.\nD'ailleurs, les avocats r\u00e9publicains n'ont recens\u00e9 que 300 cas de fraude \u00e9lectorale aux \u00c9tats-Unis en dix ans.\n\nUne chose est certaine: ces nouvelles dispositions influenceront n\u00e9gativement le taux de participation.\nEn ce sens, ces mesures mineront en partie le syst\u00e8me d\u00e9mocratique am\u00e9ricain.\n\nContrairement au Canada, les \u00c9tats am\u00e9ricains sont responsables de l'organisation des \u00e9lections f\u00e9d\u00e9rales aux \u00c9tats-Unis.\nC'est dans cet esprit qu'une majorit\u00e9 de gouvernements am\u00e9ricains promulgu\u00e8rent \u00e0 partir de 2009 de nouvelles lois rendant plus difficile le processus d'inscription ou de vote.\nCe ph\u00e9nom\u00e8ne a pris de l'ampleur apr\u00e8s les \u00e9lections de novembre 2010 qui virent s'ajouter 675 nouveaux repr\u00e9sentants r\u00e9publicains dans 26 \u00c9tats.\nEn cons\u00e9quence, 180 projets de lois restreignant l'exercice du droit de vote dans 41 \u00c9tats furent introduits durant la seule ann\u00e9e de 2011.\n\nLes nouvelles lois \u00e9lectorales exigent que les \u00e9lecteurs pr\u00e9sentent une carte d'identit\u00e9 avec photo et une preuve de citoyennet\u00e9 am\u00e9ricaine.\nPar ailleurs, ces lois r\u00e9duisent aussi les p\u00e9riodes de vote par anticipation, invalident le droit de s'inscrire comme \u00e9lecteur le jour du scrutin et retirent aux citoyens ayant un dossier judiciaire leur droit de vote.\n\nAvant les \u00e9lections de 2006, aucun \u00c9tat am\u00e9ricain n'exigeait des \u00e9lecteurs de pr\u00e9senter une carte d'identit\u00e9 avec photo.\nL'Indiana fut le premier \u00c9tat \u00e0 poser une telle exigence.\nLa Cour Supr\u00eame des \u00c9tats-Unis confirma en 2008 la constitutionnalit\u00e9 de la loi de l'Indiana.\nLes autorit\u00e9s r\u00e9publicaines s'empress\u00e8rent d'\u00e9tendre cette pratique \u00e0 d'autres \u00c9tats.\nAu cours des deux derni\u00e8res ann\u00e9es, elles parrainaient des projets de loi dans 34 \u00c9tats pour forcer les \u00e9lecteurs \u00e0 pr\u00e9senter une carte d'identit\u00e9 avec photo.\n\nIl est important de noter que, contrairement au Qu\u00e9bec, les citoyens am\u00e9ricains ne disposent pas de carte d'identit\u00e9 universelle comme la carte de l'assurance maladie.\nDe fait, 11% des citoyens am\u00e9ricains, soit 21 millions de personnes en \u00e2ge de voter, ne poss\u00e8dent pas de cartes d'identit\u00e9 avec photo \u00e9mises par une agence gouvernementale de leur \u00c9tat.\n\n" 22 | }, 23 | "pk": 1 24 | }, 25 | { 26 | "model": "testproject.document", 27 | "fields": { 28 | "text_es": "En efecto, el test de PSA presenta, en ocasiones, resultados err\u00f3neos, con falsos resultados negativos o incluso falsos resultados positivos, tras los que se decide realizar intervenciones m\u00e9dicas in\u00fatiles.\nEs un motivo m\u00e1s que suficiente para hacer dudar a los hombres, ya reticentes de por s\u00ed, sobre si deber\u00edan hacerse o no los tests de detecci\u00f3n.\n\u00bfHacerse el test o no?\nHemos pedido consejo a dos especialistas.\n\nEn los estudios realizados en los Estados Unidos se detect\u00f3 un gran \u00edndice de contagios entre los grupos de muestra, por lo que es dif\u00edcil interpretar esos datos y hacer recomendaciones firmes.\nPor su parte, el estudio europeo mostr\u00f3 cierta diferencia de mortalidad entre los pacientes que se hab\u00edan realizado la detecci\u00f3n y los que no.\n\nEl estudio, con un seguimiento a los 12 a\u00f1os, demostr\u00f3 adem\u00e1s que existe entre el 30 y el 40% de posibilidades de padecer met\u00e1stasis si no se ha realizado el test de detecci\u00f3n.\nRecomiendo, por tanto, el test a partir de los 50 a\u00f1os, o a partir de los 40 a\u00f1os si tu padre ha sufrido c\u00e1ncer de pr\u00f3stata.\nLos hombres de origen afroamericano tienen un \u00edndice de riesgo m\u00e1s elevado.\n\nLa clave es tomar una buena decisi\u00f3n una vez detectado el c\u00e1ncer.\nHay c\u00e1nceres agresivos y otros c\u00e1nceres que son indolentes.\nEs verdaderamente necesario lograr que el paciente comprenda el grado de riesgo de su c\u00e1ncer. Se le deben ofrecer todas las opciones posibles y no necesariamente tratar los c\u00e1nceres de pr\u00f3stata que no atenten contra la vida a largo plazo, en cuyo caso se debe optar m\u00e1s bien por una vigilancia activa de la enfermedad.\n\nHoy en d\u00eda muchos hombres a los que se les ha detectado un c\u00e1ncer no son tratados, puesto que dicho c\u00e1ncer no es agresivo ni entra\u00f1a un riesgo para su vida.\nEn su lugar, les sugerimos una vigilancia activa de la enfermedad y, si \u00e9sta progresa, les ofrecemos un tratamiento.\n\n", 29 | "title_es": "Detecci\u00f3n del c\u00e1ncer de pr\u00f3stata: \u00bfHacerse el test o no hac\u00e9rselo?", 30 | "title_fr": "D\u00e9pistage du cancer de la prostate: passer le test ou non?", 31 | "genre": "news", 32 | "text": "Indeed, the PSA test sometimes shows erroneous results with false negative or even false positive results, which involve unnecessary medical interventions.\nEnough to make already reluctant men hesitate to take screening tests.\nTake the test or not?\nWe asked two specialists for their opinion.\n\nIn studies conducted in the United States, there was a lot of contamination between control groups, so it is difficult to interpret the data and make firm recommendations.\nAnother study, this time a European one, concluded that there was a difference in mortality between patients who were screened and those who were not.\n\nThis study also showed, with a follow-up after 12 years, that it is between 30 and 40% more likely for metastases to occur in the absence of screening.\nI therefore recommend the test from age 50, or 40 if you have a direct relative who previously had prostate cancer.\nAfrican-American men are also more at risk.\n\nThe key is to make the right decision once cancer has been detected.\nThere are aggressive cancers and others that are indolent.\nThe patient really needs to be made to understand the degree of risk of his cancer, by offering him the options available, not necessarily treating prostate cancers that are not long-term life threatening, and opting instead, in such cases, for active monitoring of the disease.\n\n", 33 | "title_en": "Prostate cancer screening: take the test or not?", 34 | "title_ru": "\u0421\u043a\u0440\u0438\u043d\u0438\u043d\u0433 \u0440\u0430\u043a\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0436\u0435\u043b\u0435\u0437\u044b: \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u0435\u0441\u0442 \u0438\u043b\u0438 \u043d\u0435\u0442?", 35 | "text_cs": "Test PSA p\u0159in\u00e1\u0161el leckdy chybn\u00e9 v\u00fdsledky, kter\u00e9 byly nespr\u00e1vn\u011b negativn\u00ed \u010di dokonce nespr\u00e1vn\u011b pozitivn\u00ed, co\u017e vedlo ke zbyte\u010dn\u00fdm l\u00e9ka\u0159sk\u00fdm z\u00e1krok\u016fm.\nTo v\u0161e je\u0161t\u011b zv\u00fd\u0161ilo v\u00e1havost mu\u017e\u016f, kte\u0159\u00ed se ji\u017e tak zdr\u00e1hali na vy\u0161et\u0159en\u00ed v\u016fbec j\u00edt.\nNechat se vy\u0161et\u0159it nebo ne?\nPo\u017e\u00e1dali jsme o n\u00e1zor dva odborn\u00edky.\n\nVe studi\u00edch prov\u00e1d\u011bn\u00fdch v USA se projevila vysok\u00e1 m\u00edra kontaminace mezi jednotliv\u00fdmi testovan\u00fdmi skupinami, je tedy obt\u00ed\u017en\u00e9 interpretovat tyto v\u00fdsledky a p\u0159in\u00e9st hodnotn\u00e1 doporu\u010den\u00ed.\nDal\u0161\u00ed studie, tentokr\u00e1t evropsk\u00e1, konstatovala rozd\u00edlnou \u00famrtnost mezi pacienty, kte\u0159\u00ed podstoupili vy\u0161et\u0159en\u00ed, a t\u011bmi, kte\u0159\u00ed na n\u011b ne\u0161li.\n\nTato studie tak\u00e9 prok\u00e1zala po 12let\u00e9m odstupu, \u017ee ti, kdo na vy\u0161et\u0159en\u00ed nejdou, maj\u00ed o 30 a\u017e 40% vy\u0161\u0161\u00ed riziko v\u00fdskytu metast\u00e1z.\nDoporu\u010duji tedy vy\u0161et\u0159en\u00ed od 50 let v\u011bku nebo od 40 let, pokud v\u00e1\u0161 p\u0159\u00edm\u00fd p\u0159\u00edbuzn\u00fd m\u011bl rakovinu prostaty.\nOhro\u017een\u011bj\u0161\u00ed skupinou jsou rovn\u011b\u017e mu\u017ei afroamerick\u00e9ho p\u016fvodu.\n\n", 36 | "title_cs": "Odhalov\u00e1n\u00ed rakoviny prostaty: absolvovat vy\u0161et\u0159en\u00ed nebo ne?", 37 | "docid": "cyberpresse/2012/12/01/1564741", 38 | "text_de": "Der PSA-Test weise in der Tat manchmal fehlerhafte Ergebnisse auf, mit falschen negativen oder aber auch falschen positiven Ergebnissen, die zu unn\u00f6tigen medizinischen Eingriffen f\u00fchren.\nDies f\u00fchrt zu st\u00e4rkerem Z\u00f6gern der bereits unentschlossenen M\u00e4nner f\u00fcr die Durchf\u00fchrung von Fr\u00fcherkennungstests.\nSollte der Test gemacht werden oder nicht?\nWir haben die Meinung von zwei Fach\u00e4rzten eingeholt.\n\nBei den in den USA durchgef\u00fchrten Studien bestanden zahlreiche St\u00f6rfaktoren zwischen den Kontrollgruppen, sodass es schwierig ist, diese Daten zu interpretieren und eindeutige Empfehlungen zu geben.\nEine weitere Studie, dieses Mal aus Europa, kam zu der Schlussfolgerung, dass ein Unterschied bei der Sterblichkeit von Patienten mit und ohne Fr\u00fcherkennung besteht.\n\nDiese Studie hat ebenfalls gezeigt, dass bei einer Nachbeobachtung nach 12 Jahren die Wahrscheinlichkeit der Bildung von Metastasen um 30 bis 40% h\u00f6her ist, wenn keine Fr\u00fcherkennung durchgef\u00fchrt wurde.\nDeshalb empfehle ich den Test ab einem Alter von 50 Jahren bzw. 40 Jahren, wenn man einen direkten Verwandten hat, der bereits an Prostatakrebs erkrankt war.\nBei M\u00e4nnern afro-amerikanischer Herkunft besteht ebenfalls ein h\u00f6heres Risiko.\n\nDas Wichtigste ist, die richtige Entscheidung zu treffen, sobald eine Krebserkrankung erkannt wurde.\nEs gibt Krebsarten, die aggressiv und andere, die indolent sind.\nDem Patienten muss das Ausma\u00df des Risikos seiner Krebserkrankung wirklich verst\u00e4ndlich gemacht werden, indem ihm die m\u00f6glichen Optionen aufgezeigt werden, bei denen Prostatakrebse unbehandelt bleiben kann, wenn er die Lebensqualit\u00e4t auf lange Sicht nicht beeintr\u00e4chtigt, und man sich in diesen F\u00e4llen eher f\u00fcr eine aktive \u00dcberwachung der Krankheit entscheidet.\n\nHeute findet bei vielen M\u00e4nnern, bei denen man Krebs erkannt hat, keine Behandlung statt, da ihr Krebs nicht aggressiv ist und keine Bedrohung f\u00fcr ihr Leben darstellt.\n\n", 39 | "text_en": "Indeed, the PSA test sometimes shows erroneous results with false negative or even false positive results, which involve unnecessary medical interventions.\nEnough to make already reluctant men hesitate to take screening tests.\nTake the test or not?\nWe asked two specialists for their opinion.\n\nIn studies conducted in the United States, there was a lot of contamination between control groups, so it is difficult to interpret the data and make firm recommendations.\nAnother study, this time a European one, concluded that there was a difference in mortality between patients who were screened and those who were not.\n\nThis study also showed, with a follow-up after 12 years, that it is between 30 and 40% more likely for metastases to occur in the absence of screening.\nI therefore recommend the test from age 50, or 40 if you have a direct relative who previously had prostate cancer.\nAfrican-American men are also more at risk.\n\nThe key is to make the right decision once cancer has been detected.\nThere are aggressive cancers and others that are indolent.\nThe patient really needs to be made to understand the degree of risk of his cancer, by offering him the options available, not necessarily treating prostate cancers that are not long-term life threatening, and opting instead, in such cases, for active monitoring of the disease.\n\nToday, many men in whom cancer has been detected will not be treated because their cancer is not aggressive and is not life threatening.\nActive monitoring will be suggested, and if the disease progresses, they will be offered treatment.\n\n", 40 | "origlang": "fr", 41 | "title_de": "Prostatakrebsfr\u00fcherkennung: sollte der Test gemacht werden oder nicht?", 42 | "text_ru": "\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0442\u0435\u0441\u0442 \u043d\u0430 \u041f\u0421\u0410 \u0434\u0430\u0435\u0442 \u0438\u043d\u043e\u0433\u0434\u0430 \u043e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b, \u043b\u0436\u0435\u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0435, \u0430 \u0438\u043d\u043e\u0433\u0434\u0430 \u0438 \u043b\u0436\u0435\u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043a \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u043e\u043c\u0443 \u043c\u0435\u0434\u0438\u0446\u0438\u043d\u0441\u043a\u043e\u043c\u0443 \u0432\u043c\u0435\u0448\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0443.\n\u041c\u0443\u0436\u0447\u0438\u043d\u0430\u043c, \u0438 \u0442\u0430\u043a \u043d\u0435\u043e\u0445\u043e\u0442\u043d\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0449\u0438\u043c \u0434\u0438\u0441\u043f\u0430\u043d\u0441\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044e, \u0435\u0441\u0442\u044c \u043e\u0442 \u0447\u0435\u0433\u043e \u0437\u0430\u0441\u043e\u043c\u043d\u0435\u0432\u0430\u0442\u044c\u0441\u044f \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435.\n\u041f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u0435\u0441\u0442 \u0438\u043b\u0438 \u043d\u0435\u0442?\n\u041c\u044b \u0441\u043f\u0440\u043e\u0441\u0438\u043b\u0438 \u043c\u043d\u0435\u043d\u0438\u0435 \u0434\u0432\u0443\u0445 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u043e\u0432.\n\n\u0412 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f\u0445, \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0445 \u0432 \u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u043d\u044b\u0445 \u0428\u0442\u0430\u0442\u0430\u0445, \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u043b\u0438\u0441\u044c \u043c\u043d\u043e\u0433\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u043b\u0443\u0447\u0430\u0438 \u0437\u0430\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u0440\u0435\u0434\u0438 \u0433\u0440\u0443\u043f\u043f \u0438\u0441\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u044b\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u0440\u0443\u0434\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0442\u0440\u0443\u0434\u043d\u043e \u0432\u044b\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u0447\u0435\u0442\u043a\u0438\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438.\n\n", 43 | "title": "Prostate cancer screening: take the test or not?", 44 | "text_fr": "En effet, le test d'APS pr\u00e9senterait parfois des r\u00e9sultats erron\u00e9s, avec de faux r\u00e9sultats n\u00e9gatifs ou encore de faux positifs, lesquels entra\u00eenent des interventions m\u00e9dicales inutiles.\nDe quoi faire h\u00e9siter encore plus les hommes d\u00e9j\u00e0 r\u00e9ticents \u00e0 passer des tests de d\u00e9pistage.\nPasser le test ou non?\nNous avons demand\u00e9 l'avis de deux sp\u00e9cialistes.\n\nDans les \u00e9tudes men\u00e9es aux \u00c9tats-Unis, il y avait beaucoup de contamination entre les groupes t\u00e9moins, il est donc difficile d'interpr\u00e9ter ces donn\u00e9es et d'avoir des recommandations fermes.\nUne autre \u00e9tude, celle-l\u00e0 europ\u00e9enne, a conclu \u00e0 une diff\u00e9rence de mortalit\u00e9 entre les patients qui ont eu un d\u00e9pistage et ceux qui n'en ont pas eu.\n\nCette \u00e9tude a aussi d\u00e9montr\u00e9, avec un suivi apr\u00e8s 12 ans, qu'on a entre 30 et 40% de plus de chances d'avoir des m\u00e9tastases si on n'est pas d\u00e9pist\u00e9.\nJe recommande donc le test \u00e0 partir de 50 ans, ou \u00e0 partir de 40 ans si on a un parent direct qui a d\u00e9j\u00e0 eu un cancer de la prostate.\nLes hommes d'origine afro-am\u00e9ricaine sont \u00e9galement plus \u00e0 risque.\n\nLa cl\u00e9 est de prendre la bonne d\u00e9cision une fois qu'on a d\u00e9tect\u00e9 un cancer.\nIl y a des cancers agressifs et d'autres qui sont indolents.\n\n" 45 | }, 46 | "pk": 2 47 | }, 48 | { 49 | "model": "testproject.document", 50 | "fields": { 51 | "text_es": "El anuncio del probable descubrimiento del bos\u00f3n de Higgs gener\u00f3 una gran conmoci\u00f3n el verano pasado, y con raz\u00f3n.\nSe cree, en efecto, que este bos\u00f3n es part\u00edcipe del mecanismo responsable de la masa de todo lo que existe en el universo, nada m\u00e1s y nada menos. \nY lo que es m\u00e1s, se trata de la part\u00edcula cuya existencia predijo el modelo est\u00e1ndar: nuestra mejor o \"menos mala\" explicaci\u00f3n de la naturaleza y del comportamiento de la materia, que a\u00fan no ha sido observado emp\u00edricamente.\n\nPero para los f\u00edsicos no est\u00e1 totalmente claro que se trate de Higgs.\nSabemos sin lugar a dudas que existe una nueva part\u00edcula y que se parece mucho al bos\u00f3n de Higgs predicho por el modelo est\u00e1ndar.\nAdem\u00e1s, nuevos datos desvelados esta semana en un importante congreso de f\u00edsica celebrado en Kioto parecen confirmar que s\u00ed lo es, aunque a\u00fan faltan m\u00e1s datos para estar completamente seguros.\n\nDe todas maneras, suponemos que se trata de Higgs, ya que las posibilidades de equivocarse parecen pocas. Veremos de qu\u00e9 se trata.\n\nHay, en este gran mundo, una ley generalizada y ineludible que implica que dos cosas no pueden encontrarse en el mismo lugar al mismo tiempo.\nNo hay manera de infringir esa norma y no lo intente demasiado, porque terminar\u00e1 haci\u00e9ndose da\u00f1o.\n\nAunque la f\u00edsica de las part\u00edculas sea un mundo muy complejo, se ha demostrado que tambi\u00e9n en ella existe una ley de estas caracter\u00edsticas: el principio de exclusi\u00f3n de Pauli, que estipula que dos part\u00edculas no pueden ocupar el mismo espacio al mismo tiempo si est\u00e1n en el mismo \"estado cu\u00e1ntico\"; un \"estado\" que consta, grosso modo, de algunas de sus caracter\u00edsticas.\nLos f\u00edsicos clasifican las part\u00edculas en dos categor\u00edas.\nPor una parte nos encontramos con los buenos ciudadanos llamados fermiones, que obedecen sabiamente al principio de Pauli.\n\n", 52 | "title_es": "El bos\u00f3n de Higgs en detalle", 53 | "title_fr": "Le boson de Higgs d\u00e9cortiqu\u00e9", 54 | "genre": "news", 55 | "text": "The announcement of the probable discovery of the Higgs boson created quite a stir last summer, and with good reason.\nIndeed, it is believed that this boson is part of the mechanism responsible for the mass of everything in the Universe, no less.\nAlso it is the last particle whose existence is predicted by the Standard Model - our best or \"less worse\" explanation of the nature and behaviour of matter - but which has not yet been observed empirically.\n\nBut for physicists, it is still not completely sure that it really is the Higgs.\nWe know without a shadow of a doubt that it is a new authentic particle, and greatly resembles the Higgs boson predicted by the Standard Model.\nIn addition, new data unveiled this week at a large physics Congress in Kyoto seem to confirm this, but there are still insufficient data to be perfectly sure.\n\nBut let's suppose that it really is the Higgs, since the chances of being mistaken seem slim, and see what it is.\n\nIn our world, there is a fatally unavoidable law which states that two things cannot meet at the same place at the same time.\nThere's no way to break this rule - and don't try too hard, you'll go mad.\n\nHowever, even though particle physics is a very strange world, it turns out that it also has a law of the same kind: the Pauli exclusion principle, which states that two particles cannot occupy the same space at the same time if they are in the same \"quantum state\" - this \"state\" consisting roughly of certain of their characteristics.\nBased on this, physicists classify particles into two categories.\n\n", 56 | "title_en": "The Higgs boson revealed", 57 | "title_ru": "\u0411\u043e\u0437\u043e\u043d \u0425\u0438\u0433\u0433\u0441\u0430 \u0432 \u0434\u0435\u0442\u0430\u043b\u044f\u0445", 58 | "text_cs": "Ozn\u00e1men\u00ed o pravd\u011bpodobn\u00e9m objevu Higgsova bosonu vyvolal vloni v l\u00e9t\u011b opr\u00e1vn\u011bn\u00fd rozruch.\nExistuje n\u00e1zor, \u017ee tento boson se pod\u00edl\u00ed na mechanismu, kter\u00fd je odpov\u011bdn\u00fd za ve\u0161kerou hmotu ve vesm\u00edru.\nA d\u00e1le jde o posledn\u00ed \u010d\u00e1stici, jej\u00ed\u017e existenci p\u0159edpov\u00edd\u00e1 standardn\u00ed model - na\u0161e nejlep\u0161\u00ed nebo \"nejm\u00e9n\u011b \u0161patn\u00e9\" vysv\u011btlen\u00ed povahy a chov\u00e1n\u00ed hmoty - kter\u00fd v\u0161ak dosud nebyl empiricky pozorov\u00e1n.\n\nMezi fyziky v\u0161ak dosud nepanuje stoprocentn\u00ed jistota, \u017ee jde o Higgs\u016fv boson.\nNepochybuje se o tom, \u017ee m\u00e1me k dispozici zcela novou \u010d\u00e1stici, kter\u00e1 se velmi podob\u00e1 Higgsovu bosonu, jak je p\u0159edpov\u011bzen standardn\u00edm modelem.\nNov\u00e1 data zve\u0159ejn\u011bn\u00e1 tento t\u00fdden b\u011bhem velk\u00e9ho fyzik\u00e1ln\u00edho kongresu v Kj\u00f3tu jej sp\u00ed\u0161e potvrzuj\u00ed, chyb\u011bj\u00ed v\u0161ak je\u0161t\u011b ve\u0161ker\u00e9 \u00fadaje, abychom mohli m\u00edt absolutn\u00ed jistotu.\n\nNicm\u00e9n\u011b p\u0159edpokl\u00e1dejme, \u017ee jde o Higgs\u016fv boson, jeliko\u017e rizika omylu se jev\u00ed jako mal\u00e1, a pod\u00edvejme se na to, o\u010d vlastn\u011b jde.\n\nV tomto sv\u011bt\u011b plat\u00ed zcela nezpochybniteln\u00fd z\u00e1kon, podle n\u011bho\u017e se dv\u011b v\u011bci nemohou vyskytovat ve stejn\u00fd okam\u017eik na stejn\u00e9m m\u00edst\u011b.\nToto pravidlo nelze obej\u00edt - a nepokou\u0161ejte se o to p\u0159\u00edli\u0161 usilovn\u011b, jinak si ubl\u00ed\u017e\u00edte.\n\nI kdy\u017e je \u010d\u00e1sticov\u00e1 fyzika velmi podivn\u00fd sv\u011bt, ukazuje se, \u017ee i u n\u00ed plat\u00ed obdobn\u00fd z\u00e1kon: Pauliho vylu\u010dovac\u00ed princip, podle kter\u00e9ho nemohou dv\u011b \u010d\u00e1stice zab\u00edrat stejn\u00fd prostor ve stejn\u00e9m okam\u017eiku, pokud jsou ve stejn\u00e9m \"kvantov\u00e9m stavu\" - tento \"stav\" zhruba \u0159e\u010deno vytv\u00e1\u0159\u00ed n\u011bkter\u00e9 z jejich vlastnost\u00ed.\n\n", 59 | "title_cs": "Higgs\u016fv boson prozkoum\u00e1n", 60 | "docid": "cyberpresse/2012/12/01/1566244", 61 | "text_de": "Die Ank\u00fcndigung der wahrscheinlichen Entdeckung des Higgs-Bosons hat im letzten Sommer ein gewisses Aufsehen erregt, und dies aus gutem Grund.\nMan glaubt in der Tat, dass dieses Boson an nichts weniger als am Mechanismus beteiligt ist, der f\u00fcr die Masse aller Objekte im Universum verantwortlich ist.\nUnd schlie\u00dflich handelt es sich um das letzte Teilchen, dessen Existenz vom Standardmodell - unserer besten oder \"am wenigsten falschen\" Erkl\u00e4rung der Natur und dem Verhalten der Materie - vorausgesagt, aber empirisch noch nicht beobachtet wurde.\n\nAber f\u00fcr die Physiker ist es noch nicht vollst\u00e4ndig sicher, dass es sich wirklich um das Higgs handelt.\nWir wissen ohne den Schatten eines Zweifels, dass wir ein echtes neues Teilchen haben, und dass es dem vom Standardmodell vorausgesagten Higgs-Boson stark \u00e4hnelt.\nDar\u00fcber hinaus scheint dies durch neue Daten best\u00e4tigt zu werden, die in dieser Woche auf einem gro\u00dfen Physik-Kongress in Kyoto vorgestellt wurden, aber es fehlen noch Daten, um dar\u00fcber vollkommen sicher zu sein.\n\nGehen wir trotzdem davon aus, dass es sich tats\u00e4chlich um das Higgs handelt, da scheinbar nur ein geringes Risiko besteht, sich zu t\u00e4uschen, und schauen wir uns an, um was es geht.\n\nEs gibt in dieser Welt ein zwangsl\u00e4ufig unumg\u00e4ngliches Gesetz, das bewirkt, dass zwei Objekte nicht gleichzeitig am selben Ort vorhanden sein k\u00f6nnen.\nEs ist nicht m\u00f6glich, gegen diese Regel zu versto\u00dfen - und versuchen Sie es nicht zu stark, da Sie sich wehtun werden.\n\nDenn selbst wenn die Teilchenphysik eine wirklich seltsame Welt ist, stellt sich heraus, dass f\u00fcr sie ebenfalls ein derartiges Gesetz gilt: das Pauli'sche Ausschlussprinzip, das besagt, dass zwei Teilchen nicht den selben Raum zur selben Zeit besetzen k\u00f6nnen, wenn sie sich im selben \"Quantenzustand\" befinden, wobei dieser \"Zustand\" im Gro\u00dfen und Ganzen aus einigen ihrer Eigenschaften besteht.\n\n", 62 | "text_en": "The announcement of the probable discovery of the Higgs boson created quite a stir last summer, and with good reason.\nIndeed, it is believed that this boson is part of the mechanism responsible for the mass of everything in the Universe, no less.\nAlso it is the last particle whose existence is predicted by the Standard Model - our best or \"less worse\" explanation of the nature and behaviour of matter - but which has not yet been observed empirically.\n\nBut for physicists, it is still not completely sure that it really is the Higgs.\nWe know without a shadow of a doubt that it is a new authentic particle, and greatly resembles the Higgs boson predicted by the Standard Model.\nIn addition, new data unveiled this week at a large physics Congress in Kyoto seem to confirm this, but there are still insufficient data to be perfectly sure.\n\nBut let's suppose that it really is the Higgs, since the chances of being mistaken seem slim, and see what it is.\n\nIn our world, there is a fatally unavoidable law which states that two things cannot meet at the same place at the same time.\nThere's no way to break this rule - and don't try too hard, you'll go mad.\n\nHowever, even though particle physics is a very strange world, it turns out that it also has a law of the same kind: the Pauli exclusion principle, which states that two particles cannot occupy the same space at the same time if they are in the same \"quantum state\" - this \"state\" consisting roughly of certain of their characteristics.\nBased on this, physicists classify particles into two categories.\nIn one corner we have good citizens called fermions, who wisely obey the Pauli principle.\n\n", 63 | "origlang": "fr", 64 | "title_de": "Das Higgs-Boson analysiert", 65 | "text_ru": "\u041c\u0438\u043d\u0443\u0432\u0448\u0438\u043c \u043b\u0435\u0442\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0443\u0447\u0435\u043d\u044b\u043c, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c \u0431\u043e\u0437\u043e\u043d \u0425\u0438\u0433\u0433\u0441\u0430, \u0432\u044b\u0437\u0432\u0430\u043b\u043e \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0430\u0436\u0438\u043e\u0442\u0430\u0436 - \u0438 \u043d\u0435 \u0431\u0435\u0437 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0439.\n\u0421\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0431\u043e\u0437\u043e\u043d \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0435\u0442 \u043c\u0430\u0441\u0441\u0443 \u0432\u0441\u0435\u0445 \u0447\u0430\u0441\u0442\u0438\u0446 \u0432\u043e \u0412\u0441\u0435\u043b\u0435\u043d\u043d\u043e\u0439, \u043d\u0438 \u043c\u043d\u043e\u0433\u043e \u043d\u0438 \u043c\u0430\u043b\u043e.\n\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u044d\u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0447\u0430\u0441\u0442\u0438\u0446\u0430, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 - \u043d\u0430\u0448\u0435\u0433\u043e \u043b\u0443\u0447\u0448\u0435\u0433\u043e, \u0438\u043b\u0438, \u0432\u043e \u0432\u0441\u044f\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \"\u043d\u0430\u0438\u043c\u0435\u043d\u0435\u0435 \u043d\u0435\u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e\u0433\u043e\" \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u0440\u043e\u0434\u044b \u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043c\u0430\u0442\u0435\u0440\u0438\u0438, - \u043d\u043e \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0440\u0430\u043d\u044c\u0448\u0435 \u043d\u0435 \u0443\u0434\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c \u043e\u043f\u044b\u0442\u043d\u044b\u043c \u043f\u0443\u0442\u0435\u043c.\n\n", 66 | "title": "The Higgs boson revealed", 67 | "text_fr": "L'annonce de la d\u00e9couverte probable du boson de Higgs a cr\u00e9\u00e9 tout un \u00e9moi, l'\u00e9t\u00e9 dernier, et pour cause.\nOn croit en effet que ce boson participe au m\u00e9canisme responsable de la masse de toute chose dans l'Univers, rien que \u00e7a.\nEt puis, il s'agit de la derni\u00e8re particule dont l'existence est pr\u00e9dite par le Mod\u00e8le standard - notre meilleure, ou \"moins pire\" explication de la nature et du comportement de la mati\u00e8re - mais qui n'a pas encore \u00e9t\u00e9 observ\u00e9e empiriquement.\n\nMais pour les physiciens, il n'est pas encore compl\u00e8tement s\u00fbr qu'il s'agisse bien du Higgs.\nOn sait sans l'ombre d'un doute que l'on tient une authentique nouvelle particule, et qu'elle ressemble beaucoup au boson de Higgs pr\u00e9dit par le Mod\u00e8le standard.\nEn outre, de nouvelles donn\u00e9es d\u00e9voil\u00e9es cette semaine lors d'un grand congr\u00e8s de physique, \u00e0 Kyoto, semblent le confirmer, mais il manque encore des donn\u00e9es pour en \u00eatre parfaitement certain.\n\nSupposons tout de m\u00eame qu'il s'agisse bien du Higgs, puisque les chances de se tromper semblent minces, et voyons de quoi il s'agit.\n\nIl y a, en ce bas monde, une loi fatalement incontournable voulant que deux choses ne peuvent pas se retrouver au m\u00eame endroit en m\u00eame temps.\nPas moyen d'enfreindre cette r\u00e8gle - et n'essayez pas trop fort, vous allez vous faire mal.\n\nOr m\u00eame si la physique des particules est un monde bien \u00e9trange, il s'av\u00e8re qu'elle a, elle aussi, une loi de ce genre: le principe d'exclusion de Pauli, qui stipule que deux particules ne peuvent pas occuper le m\u00eame espace au m\u00eame moment si elles sont dans le m\u00eame \"\u00e9tat quantique\" - cet \"\u00e9tat\" consistant grosso modo en certaines de leurs caract\u00e9ristiques.\nDe l\u00e0, les physiciens classent les particules en deux cat\u00e9gories.\nDans un coin, on trouve de bons citoyens nomm\u00e9s fermions, qui ob\u00e9issent sagement au principe de Pauli.\nEt dans l'autre s'agitent les bosons, une sale bande d'anarchistes qui n'ont de respect pour rien - en tout cas, pas pour ce principe, ce qui signifie qu'ils peuvent bel et bien se trouver au m\u00eame endroit, en m\u00eame temps.\n\nCes bosons se divisent ensuite en deux groupes, selon le site (absolument extraordinaire, d'ailleurs) The Particle Adventure, des Laboratoires Berkeley: les m\u00e9sons, que nous n'aborderons pas ici, et les \"particules de force\", par lesquelles les grandes forces de la nature se propagent et auxquelles le boson de Higgs serait en quelque sorte apparent\u00e9.\n\n" 68 | }, 69 | "pk": 3 70 | } 71 | ] 72 | -------------------------------------------------------------------------------- /tests/testproject/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbaechler/django-multilingual-search/485c690d865da3267b19e073e28d3e2290f36611/tests/testproject/management/__init__.py -------------------------------------------------------------------------------- /tests/testproject/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbaechler/django-multilingual-search/485c690d865da3267b19e073e28d3e2290f36611/tests/testproject/management/commands/__init__.py -------------------------------------------------------------------------------- /tests/testproject/management/commands/import_sgm.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | import codecs 4 | from django.core.management import BaseCommand 5 | from django.utils import translation 6 | import os 7 | from glob import glob 8 | from ...models import ParlerDocument, Document 9 | 10 | try: 11 | from HTMLParser import HTMLParser # Python 2 12 | except ImportError: 13 | from html.parser import HTMLParser # Python 3 14 | 15 | 16 | class SGMLParser(HTMLParser): 17 | """ Parses the SGML file and create database entries. """ 18 | 19 | def __init__(self, model, language): 20 | """ 21 | Creates the objects from the given model. 22 | :param model: A Django model class. 23 | """ 24 | super(SGMLParser, self).__init__() 25 | self.model_class = model 26 | self.model = None 27 | self.text = '' 28 | self.is_title = False 29 | self.language = language 30 | 31 | def parse(self, data): 32 | self._lines = [] 33 | self.reset() 34 | self.feed(data) 35 | 36 | # called on an opening tag 37 | def handle_starttag(self, tag, attrs): 38 | if tag == 'doc': 39 | self.start_new_model(attrs) 40 | elif tag == 'h1': 41 | self.is_title = True 42 | 43 | # called on a closing tag 44 | def handle_endtag(self, tag): 45 | if tag == 'doc': 46 | self.end_new_model() 47 | elif tag == 'h1': 48 | self.is_title = False 49 | elif tag == 'p': 50 | self.text += '\n' 51 | 52 | def handle_data(self, data): 53 | if data != '\n': 54 | if self.is_title: 55 | self.model.title = data 56 | else: 57 | self.text += (data + '\n') 58 | 59 | # create a new object instance 60 | def start_new_model(self, attrs): 61 | attributes = dict(attrs) 62 | self.model, created = self.model_class.objects.get_or_create(docid=attributes['docid']) 63 | for attr, value in attrs: 64 | if hasattr(self.model, attr): 65 | setattr(self.model, attr, value) 66 | 67 | # save the object instance 68 | def end_new_model(self): 69 | self.model.text = self.text 70 | self.text = '' 71 | self.model.save() 72 | self.model = None 73 | 74 | 75 | class Command(BaseCommand): 76 | help = 'Import test data from a SGML source. The filename must end in -ref..sgm' 77 | 78 | def add_arguments(self, parser): 79 | parser.add_argument('path', type=str) 80 | parser.add_argument('--delete', 81 | action='store_true', 82 | dest='delete', 83 | default=False, 84 | help='Delete all models before import.') 85 | 86 | def handle(self, *args, **options): 87 | if options['delete']: 88 | Document.objects.all().delete() 89 | 90 | path = options['path'] 91 | if not os.path.isdir(path): 92 | raise AttributeError('Path "{0}" is not a directory'.format(path)) 93 | files = glob(os.path.join(path, '*ref.*.sgm')) 94 | for file in files: 95 | language = file.split('.')[-2] 96 | translation.activate(language) 97 | self.stdout.write('{0}: {1}'.format(file, language)) 98 | with codecs.open(file, 'r', 'utf-8') as f: 99 | modeltranslation_parser = SGMLParser(Document, language) 100 | parler_parser = SGMLParser(ParlerDocument, language) 101 | data = f.read() 102 | modeltranslation_parser.parse(data) 103 | parler_parser.parse(data) 104 | 105 | self.stdout.write('Done.') 106 | -------------------------------------------------------------------------------- /tests/testproject/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name='Document', 15 | fields=[ 16 | ('id', models.AutoField(primary_key=True, serialize=False, auto_created=True, verbose_name='ID')), 17 | ('docid', models.CharField(max_length=100)), 18 | ('genre', models.CharField(max_length=20)), 19 | ('origlang', models.CharField(max_length=10)), 20 | ('text', models.TextField()), 21 | ('text_en', models.TextField(null=True)), 22 | ('text_de', models.TextField(null=True)), 23 | ('text_es', models.TextField(null=True)), 24 | ('text_fr', models.TextField(null=True)), 25 | ('text_cs', models.TextField(null=True)), 26 | ('text_ru', models.TextField(null=True)), 27 | ('title', models.TextField(blank=True)), 28 | ('title_en', models.TextField(blank=True, null=True)), 29 | ('title_de', models.TextField(blank=True, null=True)), 30 | ('title_es', models.TextField(blank=True, null=True)), 31 | ('title_fr', models.TextField(blank=True, null=True)), 32 | ('title_cs', models.TextField(blank=True, null=True)), 33 | ('title_ru', models.TextField(blank=True, null=True)), 34 | ], 35 | options={ 36 | 'ordering': ['docid'], 37 | 'verbose_name': 'Document', 38 | }, 39 | ), 40 | ] 41 | -------------------------------------------------------------------------------- /tests/testproject/migrations/0002_auto_20150907_1648.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('testproject', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='ParlerDocument', 16 | fields=[ 17 | ('id', models.AutoField(primary_key=True, auto_created=True, serialize=False, verbose_name='ID')), 18 | ('docid', models.CharField(max_length=100)), 19 | ('genre', models.CharField(max_length=20)), 20 | ('origlang', models.CharField(max_length=10)), 21 | ], 22 | options={ 23 | 'ordering': ['docid'], 24 | 'verbose_name': 'Parler Document', 25 | }, 26 | ), 27 | migrations.CreateModel( 28 | name='ParlerDocumentTranslation', 29 | fields=[ 30 | ('id', models.AutoField(primary_key=True, auto_created=True, serialize=False, verbose_name='ID')), 31 | ('language_code', models.CharField(db_index=True, max_length=15, verbose_name='Language')), 32 | ('text', models.TextField()), 33 | ('title', models.TextField(blank=True)), 34 | ('master', models.ForeignKey(related_name='translations', editable=False, null=True, to='testproject.ParlerDocument')), 35 | ], 36 | options={ 37 | 'default_permissions': (), 38 | 'verbose_name': 'Parler Document Translation', 39 | 'db_tablespace': '', 40 | 'db_table': 'testproject_parlerdocument_translation', 41 | 'managed': True, 42 | }, 43 | ), 44 | migrations.AlterModelOptions( 45 | name='document', 46 | options={'ordering': ['docid'], 'verbose_name': 'Modeltranslations Document'}, 47 | ), 48 | migrations.AlterUniqueTogether( 49 | name='parlerdocumenttranslation', 50 | unique_together=set([('language_code', 'master')]), 51 | ), 52 | ] 53 | -------------------------------------------------------------------------------- /tests/testproject/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbaechler/django-multilingual-search/485c690d865da3267b19e073e28d3e2290f36611/tests/testproject/migrations/__init__.py -------------------------------------------------------------------------------- /tests/testproject/models.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | from django.db import models 4 | from parler.models import TranslatableModel, TranslatedFields 5 | 6 | 7 | class Document(models.Model): 8 | """ The document model class to test the library with 9 | django-modeltranslations. 10 | """ 11 | docid = models.CharField(max_length=100) 12 | genre = models.CharField(max_length=20) 13 | origlang = models.CharField(max_length=10) 14 | text = models.TextField() 15 | title = models.TextField(blank=True) 16 | 17 | class Meta: 18 | verbose_name = 'Modeltranslations Document' 19 | ordering = ['docid'] 20 | 21 | def __unicode__(self): 22 | return '{0} ({1})'.format(self.title, self.docid) 23 | 24 | def __str__(self): 25 | return '{0} ({1})'.format(self.title, self.docid) 26 | 27 | 28 | class ParlerDocument(TranslatableModel): 29 | """ The document model class to test the library with 30 | django-parler 31 | """ 32 | docid = models.CharField(max_length=100) 33 | genre = models.CharField(max_length=20) 34 | origlang = models.CharField(max_length=10) 35 | 36 | translations = TranslatedFields( 37 | text=models.TextField(), 38 | title=models.TextField(blank=True), 39 | ) 40 | 41 | class Meta: 42 | verbose_name = 'Parler Document' 43 | ordering = ['docid'] 44 | 45 | def __unicode__(self): 46 | return '{0} ({1})'.format(self.title, self.docid) 47 | 48 | def __str__(self): 49 | return '{0} ({1})'.format(self.title, self.docid) 50 | -------------------------------------------------------------------------------- /tests/testproject/search_indexes.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | 4 | from haystack import indexes 5 | from .models import Document, ParlerDocument 6 | 7 | 8 | class DocumentIndex(indexes.SearchIndex, indexes.Indexable): 9 | text = indexes.CharField(document=True, use_template=True) 10 | docid = indexes.CharField(model_attr='docid') 11 | 12 | def get_model(self): 13 | return Document 14 | 15 | 16 | class ParlerIndex(indexes.SearchIndex, indexes.Indexable): 17 | text = indexes.CharField(document=True, use_template=True) 18 | docid = indexes.CharField(model_attr='docid') 19 | 20 | def get_model(self): 21 | return ParlerDocument 22 | -------------------------------------------------------------------------------- /tests/testproject/settings.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | """ 3 | Django settings for testproject project. 4 | 5 | For more information on this file, see 6 | https://docs.djangoproject.com/en/1.7/topics/settings/ 7 | 8 | For the full list of settings and their values, see 9 | https://docs.djangoproject.com/en/1.7/ref/settings/ 10 | """ 11 | 12 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 13 | import os 14 | import sys 15 | 16 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 17 | 18 | sys.path.insert(0, os.path.dirname(BASE_DIR)) 19 | 20 | # SECURITY WARNING: keep the secret key used in production secret! 21 | SECRET_KEY = 'b2k427m)td!v8h-0@=qd-9pvvu@gd_zl-0^i@6j589uhp=egsx' 22 | 23 | # SECURITY WARNING: don't run with debug turned on in production! 24 | DEBUG = True 25 | 26 | TEMPLATE_DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = ( 34 | 'modeltranslation', 35 | 'django.contrib.admin', 36 | 'django.contrib.auth', 37 | 'django.contrib.contenttypes', 38 | 'django.contrib.sessions', 39 | 'django.contrib.messages', 40 | 'django.contrib.staticfiles', 41 | 'testproject', 42 | 'haystack', 43 | 'parler', 44 | ) 45 | 46 | MIDDLEWARE_CLASSES = ( 47 | 'django.contrib.sessions.middleware.SessionMiddleware', 48 | 'django.middleware.common.CommonMiddleware', 49 | 'django.middleware.csrf.CsrfViewMiddleware', 50 | 'django.middleware.locale.LocaleMiddleware', 51 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 52 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 53 | 'django.contrib.messages.middleware.MessageMiddleware', 54 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 55 | ) 56 | 57 | ROOT_URLCONF = 'testproject.urls' 58 | 59 | WSGI_APPLICATION = 'testproject.wsgi.application' 60 | 61 | 62 | # Database 63 | # https://docs.djangoproject.com/en/1.7/ref/settings/#databases 64 | 65 | DATABASES = { 66 | 'default': { 67 | 'ENGINE': 'django.db.backends.sqlite3', 68 | 'NAME': 'myapp.sqlite', 69 | } 70 | } 71 | 72 | # Internationalization 73 | # https://docs.djangoproject.com/en/1.7/topics/i18n/ 74 | 75 | LANGUAGE_CODE = 'en' 76 | LANGUAGES = (('en', 'English'), 77 | ('de', 'Deutsch'), 78 | ('es', 'Spanisch'), 79 | ('fr', 'Französisch'), 80 | ('cs', 'Tschechisch'), 81 | ('ru', 'Russisch'), 82 | ) 83 | 84 | 85 | TIME_ZONE = 'UTC' 86 | 87 | USE_I18N = True 88 | 89 | USE_L10N = True 90 | 91 | USE_TZ = True 92 | 93 | 94 | # Static files (CSS, JavaScript, Images) 95 | # https://docs.djangoproject.com/en/1.7/howto/static-files/ 96 | 97 | STATIC_URL = '/static/' 98 | 99 | HAYSTACK_CONNECTIONS = { 100 | 'default': { 101 | 'ENGINE': 'multilingual.elasticsearch_backend.ElasticsearchMultilingualSearchEngine', 102 | 'URL': 'http://127.0.0.1:9200/', 103 | 'INDEX_NAME': 'testproject', 104 | 'SILENTLY_FAIL': False, 105 | 'TIMEOUT': 30, 106 | }, 107 | } 108 | 109 | HAYSTACK_LOGGING = True 110 | 111 | LOGGING = { 112 | 'version': 1, 113 | 'disable_existing_loggers': False, 114 | 'handlers': { 115 | 'console': { 116 | 'class': 'logging.StreamHandler', 117 | }, 118 | }, 119 | 'loggers': { 120 | 'django': { 121 | 'handlers': ['console'], 122 | 'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'), 123 | }, 124 | 'haystack': { 125 | 'handlers': ['console'], 126 | 'level': 'DEBUG' 127 | } 128 | }, 129 | } 130 | 131 | TEMPLATES = [ 132 | { 133 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 134 | 'APP_DIRS': True, 135 | }, 136 | ] 137 | -------------------------------------------------------------------------------- /tests/testproject/signals.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | from django.db import models 4 | from haystack import signals 5 | from .models import Document 6 | 7 | 8 | class DocumentOnlySignalProcessor(signals.BaseSignalProcessor): 9 | def setup(self): 10 | # Listen only to the ``Document`` model. 11 | models.signals.post_save.connect(self.handle_save, sender=Document) 12 | models.signals.post_delete.connect(self.handle_delete, sender=Document) 13 | 14 | def teardown(self): 15 | # Disconnect only for the ``Document`` model. 16 | models.signals.post_save.disconnect(self.handle_save, sender=Document) 17 | models.signals.post_delete.disconnect(self.handle_delete, sender=Document) 18 | -------------------------------------------------------------------------------- /tests/testproject/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | {% load i18n %} 3 | 4 | 5 | 6 | 7 | 8 | 9 | Django Multilingual search 10 | 11 | 12 |
13 | 46 |
47 | 48 | 49 | 50 |
51 | {% block content %}{% endblock %} 52 |
53 | 54 | 55 | {% block js %}{% endblock %} 56 | 57 | -------------------------------------------------------------------------------- /tests/testproject/templates/search/indexes/testproject/document_text.txt: -------------------------------------------------------------------------------- 1 | {{ object.title }} 2 | {{ object.text }} -------------------------------------------------------------------------------- /tests/testproject/templates/search/indexes/testproject/parlerdocument_text.txt: -------------------------------------------------------------------------------- 1 | {{ object.title }} 2 | {{ object.text }} -------------------------------------------------------------------------------- /tests/testproject/templates/search/search.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load highlight %} 3 | 4 | {% block content %} 5 |

All elements

6 |
7 | {% if query %} 8 | {% for result in page.object_list %} 9 |
10 | 17 |
18 |
19 |

{% highlight result.object.text with query html_tag "mark" %}

20 |

{{ result.object.text }}

21 |
22 |
23 |
24 | {% empty %} 25 |

No results found.

26 | {% endfor %} 27 | {% if page.has_previous or page.has_next %} 28 |
29 | {% if page.has_previous %}{% endif %}« Previous{% if page.has_previous %}{% endif %} 30 | | 31 | {% if page.has_next %}{% endif %}Next »{% if page.has_next %}{% endif %} 32 |
33 | {% endif %} 34 | {% endif %} 35 |
36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /tests/testproject/templates/testproject/document_list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |

All elements

5 |
6 | {% for document in object_list %} 7 |
8 | 15 |
16 |
17 | {{ document.text }} 18 |
19 |
20 |
21 | {% endfor %} 22 |
23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /tests/testproject/templates/testproject/parlerdocument_list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |

All Parler elements

5 |
6 | {% for document in object_list %} 7 |
8 | 15 |
16 |
17 | {{ document.text }} 18 |
19 |
20 |
21 | {% endfor %} 22 |
23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /tests/testproject/tests.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | # import all test modules for the old test runner 4 | from tests.unittests.test_index_creation import BackendTest as BT1 # noqa 5 | from tests.unittests.test_query import BackendTest as BT2 # noqa 6 | from tests.unittests.test_hooks import BackendTest as BT4 # noqa 7 | from tests.functional_tests.test_query import BackendTest as BT3 # noqa 8 | from tests.functional_tests.test_index_creation import IndexTest # noqa 9 | from tests.functional_tests.test_hooks import HookTest # noqa 10 | -------------------------------------------------------------------------------- /tests/testproject/translation.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | 4 | from modeltranslation.translator import translator, TranslationOptions 5 | 6 | from .models import Document 7 | 8 | 9 | class DocumentTranslationOptions(TranslationOptions): 10 | fields = ('title', 'text') 11 | 12 | 13 | translator.register(Document, DocumentTranslationOptions) 14 | -------------------------------------------------------------------------------- /tests/testproject/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import include, url, patterns 2 | from django.conf.urls.i18n import i18n_patterns 3 | from django.contrib import admin 4 | from haystack.views import search_view_factory 5 | from .views import DocumentView, Search, LanguageRedirectView, ParlerView 6 | 7 | search_view = search_view_factory(Search) 8 | 9 | urlpatterns = patterns( 10 | url(r'^admin/', include(admin.site.urls)), 11 | url(r'^search/', search_view, name='search'), 12 | (r'^$', LanguageRedirectView.as_view()), 13 | (r'^i18n/', include('django.conf.urls.i18n')), 14 | ) 15 | 16 | urlpatterns += i18n_patterns( 17 | url(r'^$', DocumentView.as_view(), name='home'), 18 | url(r'^parler/$', ParlerView.as_view(), name='parler_home'), 19 | ) 20 | -------------------------------------------------------------------------------- /tests/testproject/views.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | from django.core.urlresolvers import reverse 4 | from django.views.generic import ListView, RedirectView 5 | from haystack.forms import HighlightedSearchForm 6 | from haystack.views import SearchView 7 | from .models import Document, ParlerDocument 8 | 9 | 10 | class SearchForm(HighlightedSearchForm): 11 | pass 12 | 13 | 14 | class DocumentView(ListView): 15 | model = Document 16 | paginate_by = 20 17 | 18 | 19 | class ParlerView(ListView): 20 | paginate_by = 20 21 | 22 | def get_queryset(self): 23 | return ParlerDocument.objects.prefetch_related('translations') 24 | 25 | 26 | class Search(SearchView): 27 | form = SearchForm 28 | model = Document 29 | paginate_by = 20 30 | 31 | 32 | class LanguageRedirectView(RedirectView): 33 | def get_redirect_url(self): 34 | return reverse('home') 35 | -------------------------------------------------------------------------------- /tests/testproject/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for testproject project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testproject.settings") 12 | 13 | from django.core.wsgi import get_wsgi_application # noqa 14 | application = get_wsgi_application() 15 | -------------------------------------------------------------------------------- /tests/tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | setupdir = .. 3 | 4 | envlist = 5 | py27-1.5.X, 6 | py27-1.6.X, 7 | py27-1.7.X, 8 | py27-1.8.X, 9 | py34-1.8.X 10 | 11 | [testenv] 12 | commands = 13 | {envpython} manage.py test tests 14 | setenv = 15 | PYTHONPATH = .:{toxworkdir}/../.. 16 | 17 | [testenv:py27-1.5.X] 18 | commands = 19 | {envpython} manage.py test testproject --settings=testproject.settings 20 | basepython = python2.7 21 | deps = 22 | Django>=1.5,<1.6 23 | elasticsearch==1.7.0 24 | urllib3==1.10.4 25 | django-haystack==2.4.1 26 | django-modeltranslation==0.9.1 27 | django-parler==1.5 28 | mock 29 | 30 | [testenv:py27-1.6.X] 31 | basepython = python2.7 32 | deps = 33 | Django>=1.6,<1.7 34 | elasticsearch==1.7.0 35 | urllib3==1.10.4 36 | django-haystack==2.4.1 37 | django-modeltranslation==0.9.1 38 | django-parler==1.5 39 | mock 40 | 41 | [testenv:py27-1.7.X] 42 | basepython = python2.7 43 | deps = 44 | Django>=1.7,<1.8 45 | elasticsearch==1.7.0 46 | urllib3==1.10.4 47 | django-haystack==2.4.1 48 | django-modeltranslation==0.9.1 49 | django-parler==1.5 50 | mock 51 | 52 | [testenv:py27-1.8.X] 53 | basepython = python2.7 54 | deps = 55 | Django>=1.8,<1.9 56 | elasticsearch==1.7.0 57 | urllib3==1.10.4 58 | django-haystack==2.4.1 59 | django-modeltranslation==0.12 60 | django-parler==1.6.5 61 | mock 62 | 63 | [testenv:py34-1.8.X] 64 | basepython = python3.4 65 | deps = 66 | Django>=1.8,<1.9 67 | elasticsearch==1.7.0 68 | urllib3==1.10.4 69 | django-haystack==2.4.1 70 | django-modeltranslation==0.12 71 | django-parler==1.6.5 72 | -------------------------------------------------------------------------------- /tests/unittests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbaechler/django-multilingual-search/485c690d865da3267b19e073e28d3e2290f36611/tests/unittests/__init__.py -------------------------------------------------------------------------------- /tests/unittests/mocks.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | from django.conf import settings 4 | from django.core import serializers 5 | import os 6 | 7 | try: 8 | from unittest import mock # python >= 3.3 9 | except ImportError: 10 | import mock # python 2 11 | 12 | 13 | class Data: 14 | connection_options = settings.HAYSTACK_CONNECTIONS['default'] 15 | existing_mapping = {'modelresult': {'_boost': {'null_value': 1.0, 'name': 'boost'}, 16 | 'properties': {'django_id': {'index': 'not_analyzed', 17 | 'include_in_all': False, 18 | 'type': 'string'}, 19 | 'docid': {'analyzer': 'snowball', 20 | 'type': 'string'}, 21 | 'django_ct': {'index': 'not_analyzed', 22 | 'include_in_all': False, 23 | 'type': 'string'}, 24 | 'text': {'analyzer': 'snowball', 25 | 'type': 'string'}}}} 26 | 27 | # same as modelresult.properties 28 | field_mapping = {'text': {'type': 'string', 'analyzer': 'snowball'}, 29 | 'django_ct': {'type': 'string', 'index': 'not_analyzed', 30 | 'include_in_all': False}, 31 | 'docid': {'type': 'string', 'analyzer': 'snowball'}, 32 | 'django_id': {'type': 'string', 'index': 'not_analyzed', 33 | 'include_in_all': False}} 34 | 35 | index_keys = ['django_ct', 'id', 'text', 'docid', 'django_id', '_id'] 36 | 37 | search_kwargs = {'_source': True, 'doc_type': 'modelresult', 'index': 'testproject', 38 | 'body': {'query': {'filtered': {'query': {'match_all': {}}, 39 | 'filter': {'terms': {'django_ct': 40 | ['testproject.parlerdocument', 41 | 'testproject.document']}}}}, 42 | 'from': 0, 'size': 1}} 43 | 44 | raw_results = {'timed_out': False, 45 | '_shards': {'failed': 0, 'total': 5, 'successful': 5}, 46 | 'hits': {'total': 0, 'max_score': None, 'hits': []}, 'took': 7} 47 | 48 | 49 | def mock_indices(): 50 | mymock = mock.Mock() 51 | attrs = {'get_mapping.return_value': Data.existing_mapping} 52 | 53 | mymock.configure_mock(**attrs) 54 | return mymock 55 | 56 | 57 | def mock_backend(): 58 | mymock = mock.Mock() 59 | attrs = {'search.return_value': {}} 60 | mymock.configure_mock(**attrs) 61 | return mymock 62 | 63 | 64 | def create_documents(): 65 | """ 66 | Deserializes objects from the 'small' fixture 67 | :return: A list of DeserializedObject 68 | https://docs.djangoproject.com/en/1.8/topics/serialization/#serialization-formats-json 69 | """ 70 | path = os.path.join(settings.BASE_DIR, 'testproject', 'fixtures', 'small.json') 71 | with open(path, 'r') as f: 72 | documents = list(serializers.deserialize('json', f)) 73 | 74 | return documents 75 | -------------------------------------------------------------------------------- /tests/unittests/test_hooks.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | 4 | from django.test import TestCase 5 | from django.conf import settings 6 | import haystack 7 | from haystack.signals import RealtimeSignalProcessor 8 | 9 | from testproject.models import Document 10 | from .mocks import create_documents 11 | 12 | try: 13 | from unittest import mock # python >= 3.3 14 | except ImportError: 15 | import mock # python 2 16 | 17 | 18 | class BackendTest(TestCase): 19 | maxDiff = None 20 | 21 | @mock.patch('elasticsearch.Elasticsearch') 22 | def test_post_save_and_delete_hook(self, es_obj): 23 | # index uses a global loader for the backend. 24 | documents = create_documents() 25 | doc = documents[0] 26 | doc.save() 27 | # send the post_save signal 28 | index = haystack.connections['default'].get_unified_index().get_index(Document) 29 | backend = index._get_backend('default') # Multilingual Backend 30 | # test if the command has been sent to ES 31 | if not isinstance(backend.conn, mock.Mock): 32 | backend.conn = mock.MagicMock() 33 | es = backend.conn 34 | index.update_object(doc.object, 'default') 35 | 36 | self.assertFalse(es.delete.called) 37 | self.assertTrue(es.bulk.called) 38 | call_args = es.bulk.call_args_list 39 | self.assertEqual(len(call_args), len(settings.LANGUAGES)) 40 | self.assertEqual(call_args[0][0][0][0], {'index': {'_id': 'testproject.document.1'}}) 41 | index_list = [a[1] for a in call_args] 42 | self.assertIn({'doc_type': 'modelresult', 'index': 'testproject-en'}, index_list) 43 | self.assertIn({'doc_type': 'modelresult', 'index': 'testproject-de'}, index_list) 44 | self.assertIn({'doc_type': 'modelresult', 'index': 'testproject-es'}, index_list) 45 | self.assertIn(doc.object.text_en, call_args[0][0][0][1]['text']) 46 | # test delete 47 | index.remove_object(doc.object, 'default') 48 | 49 | self.assertTrue(es.delete.called) 50 | call_args = es.delete.call_args_list 51 | self.assertEqual(len(call_args), len(settings.LANGUAGES)) 52 | self.assertEqual(call_args[0][1], 53 | {'index': 'testproject-en', 'ignore': 404, 54 | 'doc_type': 'modelresult', 'id': 'testproject.document.1'}) 55 | self.assertEqual(call_args[1][1], 56 | {'id': 'testproject.document.1', 'doc_type': 'modelresult', 57 | 'ignore': 404, 'index': 'testproject-de'}) 58 | 59 | @mock.patch('elasticsearch.Elasticsearch') 60 | @mock.patch.object(RealtimeSignalProcessor, 'handle_save', autospec=True) 61 | @mock.patch.object(RealtimeSignalProcessor, 'handle_delete', autospec=True) 62 | def test_hook_called(self, mock_delete, mock_save, mock_es): 63 | # check if the signals are triggered 64 | rsp = RealtimeSignalProcessor(haystack.connections, haystack.connection_router) # noqa 65 | self.assertFalse(mock_delete.called) 66 | self.assertFalse(mock_save.called) 67 | documents = create_documents() 68 | doc = documents[0] 69 | doc.save() 70 | self.assertTrue(mock_save.called) 71 | doc.object.delete() 72 | self.assertTrue(mock_delete.called) 73 | -------------------------------------------------------------------------------- /tests/unittests/test_index_creation.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | from django.test import TestCase 4 | from django.conf import settings 5 | from django.utils import translation 6 | from django.utils.html import escape 7 | from haystack.backends.elasticsearch_backend import ElasticsearchSearchBackend, \ 8 | ElasticsearchSearchEngine 9 | from haystack.management.commands.update_index import do_update 10 | from multilingual.elasticsearch_backend import ElasticsearchMultilingualSearchBackend, \ 11 | ElasticsearchMultilingualSearchEngine 12 | from .mocks import mock_indices, Data 13 | from testproject.models import Document 14 | from multilingual.utils import get_analyzer_for 15 | 16 | try: 17 | from unittest import mock # python >= 3.3 18 | except ImportError: 19 | import mock # python 2 20 | 21 | 22 | class BackendTest(TestCase): 23 | maxDiff = None 24 | 25 | @mock.patch('elasticsearch.Elasticsearch') 26 | def test_mocking_works(self, mock_obj): 27 | # create a backend instance 28 | es = ElasticsearchMultilingualSearchBackend('default', **Data.connection_options) 29 | for language in settings.LANGUAGES: 30 | self.assertIn(language[0], es.existing_mapping.keys()) 31 | # in the constructor, an Elasticsearche instance is created as 'conn' property. 32 | self.assertTrue(isinstance(es.conn, mock.Mock)) 33 | self.assertIsNot(es.conn, mock_obj) # a new mock is created. 34 | self.assertFalse(es.silently_fail) 35 | indices = mock_indices() # use the indices mock from the mocks module. 36 | es.conn.attach_mock(indices, 'indices') 37 | self.assertEqual(es.conn.indices.get_mapping(), Data.existing_mapping) 38 | es.setup() 39 | # Data.connection_options.INDEX_NAME 40 | indices.get_mapping.assert_any_call(index='testproject-en') 41 | indices.get_mapping.assert_any_call(index='testproject-de') 42 | indices.get_mapping.assert_any_call(index='testproject-ru') 43 | 44 | @mock.patch('elasticsearch.Elasticsearch') 45 | def test_do_update(self, mock_obj): 46 | """ 47 | Tests the update_index.do_update function 48 | """ 49 | engine = ElasticsearchMultilingualSearchEngine() 50 | backend = mock.Mock() 51 | engine._backend = backend 52 | index = engine.get_unified_index() 53 | qs = Document.objects.all() 54 | start = 0 55 | end = len(qs) 56 | total = end - start 57 | do_update(backend, index, qs, start, end, total, verbosity=1, commit=False) 58 | # The update method has been called 59 | self.assertTrue(backend.update.called) 60 | call_args_list = backend.update.call_args_list 61 | # args, the queryset cannot be testet for equality. 62 | self.assertEqual(call_args_list[0][0][0], index) 63 | # kwargs 64 | self.assertEqual(call_args_list[0][1], {'commit': False}) 65 | 66 | @mock.patch('elasticsearch.Elasticsearch') 67 | def test_setup_on_haystack_backend(self, mock_obj): 68 | """ 69 | Tests the Setup method on the elasticsearch backend. 70 | """ 71 | es = ElasticsearchSearchBackend('default', **Data.connection_options) 72 | self.assertFalse(es.setup_complete) 73 | es.setup() 74 | self.assertTrue(es.setup_complete) 75 | self.assertEqual(es.existing_mapping, Data.existing_mapping) 76 | es.conn.indices.create.assert_called_with(index='testproject', 77 | ignore=400, body=es.DEFAULT_SETTINGS) 78 | es.conn.indices.put_mapping.assert_called_with(index='testproject', 79 | doc_type='modelresult', 80 | body=Data.existing_mapping) 81 | 82 | @mock.patch('elasticsearch.Elasticsearch') 83 | def test_setup_on_multilingual_backend(self, mock_obj): 84 | """ 85 | Tests the Setup method on the elasticsearch backend. 86 | """ 87 | es = ElasticsearchMultilingualSearchBackend('default', **Data.connection_options) 88 | self.assertFalse(es.setup_complete) 89 | es.setup() 90 | self.assertTrue(es.setup_complete) 91 | self.assertNotEqual(es.existing_mapping['de'], Data.existing_mapping) 92 | self.assertEqual(es.existing_mapping['de']['modelresult']['properties']['text']['analyzer'], 93 | get_analyzer_for('de')) 94 | es.conn.indices.create.assert_any_call(index='testproject-de', 95 | ignore=400, body=es.DEFAULT_SETTINGS) 96 | es.conn.indices.put_mapping.assert_any_call(index='testproject-de', 97 | doc_type='modelresult', 98 | body=es.existing_mapping['de']) 99 | 100 | self.assertNotEqual(es.existing_mapping['en'], Data.existing_mapping) 101 | self.assertEqual(es.existing_mapping['en']['modelresult']['properties']['text']['analyzer'], 102 | get_analyzer_for('en')) 103 | es.conn.indices.create.assert_any_call(index='testproject-en', 104 | ignore=400, body=es.DEFAULT_SETTINGS) 105 | es.conn.indices.put_mapping.assert_any_call(index='testproject-en', 106 | doc_type='modelresult', 107 | body=es.existing_mapping['en']) 108 | 109 | self.assertNotEqual(es.existing_mapping['fr'], Data.existing_mapping) 110 | self.assertEqual(es.existing_mapping['fr']['modelresult']['properties']['text']['analyzer'], 111 | get_analyzer_for('fr')) 112 | es.conn.indices.create.assert_any_call(index='testproject-fr', 113 | ignore=400, body=es.DEFAULT_SETTINGS) 114 | es.conn.indices.put_mapping.assert_any_call(index='testproject-fr', 115 | doc_type='modelresult', 116 | body=es.existing_mapping['fr']) 117 | 118 | @mock.patch('elasticsearch.Elasticsearch') 119 | def test_haystack_clear(self, mock_obj): 120 | es = ElasticsearchSearchBackend('default', **Data.connection_options) 121 | es.setup() 122 | es.clear(models=None, commit=True) # commit is ignored anyway 123 | es.conn.indices.delete.assert_called_with(index='testproject', ignore=404) 124 | 125 | @mock.patch('elasticsearch.Elasticsearch') 126 | def test_multilingual_clear(self, mock_obj): 127 | es = ElasticsearchMultilingualSearchBackend('default', **Data.connection_options) 128 | es.setup() 129 | es.clear(models=None, commit=False) 130 | es.conn.indices.delete.assert_any_call(index='testproject-en', ignore=404) 131 | es.conn.indices.delete.assert_any_call(index='testproject-fr', ignore=404) 132 | es.conn.indices.delete.assert_any_call(index='testproject-de', ignore=404) 133 | es.conn.indices.delete.assert_any_call(index='testproject-ru', ignore=404) 134 | 135 | 136 | class IndexTest(TestCase): 137 | fixtures = ['small'] 138 | maxDiff = None 139 | 140 | def test_fixture(self): 141 | qs = Document.objects.all() 142 | self.assertEqual(3, len(qs)) 143 | 144 | @mock.patch('elasticsearch.Elasticsearch') 145 | def test_haystack_update(self, mock_obj): 146 | """ 147 | Test the update method on the Haystack backend 148 | """ 149 | engine = ElasticsearchSearchEngine() 150 | es = ElasticsearchSearchBackend('default', **Data.connection_options) 151 | engine._backend = es 152 | es.setup() 153 | unified_index = engine.get_unified_index() 154 | index = unified_index.get_index(Document) 155 | iterable = Document.objects.all() 156 | es.update(index, iterable) 157 | es.conn.indices.refresh.assert_called_with(index='testproject') 158 | self.assertTrue(es.conn.bulk.called) 159 | call_args = es.conn.bulk.call_args[0][0] 160 | self.assertEqual(6, len(call_args)) 161 | self.assertEqual({'index': {'_id': 'testproject.document.1'}}, call_args[0]) 162 | self.assertEqual({'index': {'_id': 'testproject.document.2'}}, call_args[2]) 163 | self.assertEqual({'index': {'_id': 'testproject.document.3'}}, call_args[4]) 164 | self.assertIn('Republican leaders justified their policy', call_args[1]['text']) 165 | doc1 = Document.objects.get(pk=1) 166 | self.assertIn(doc1.text, call_args[1]['text']) 167 | self.assertIn('the PSA test sometimes shows erroneous results', call_args[3]['text']) 168 | self.assertIn('The announcement of the probable discovery of the Higgs boson', 169 | call_args[5]['text']) 170 | 171 | @mock.patch('elasticsearch.Elasticsearch') 172 | def test_multilingual_update(self, mock_obj): 173 | """ 174 | Test the update method on the multilingual backend. 175 | """ 176 | engine = ElasticsearchMultilingualSearchEngine() 177 | es = engine.backend('default', **Data.connection_options) 178 | es.setup() 179 | unified_index = engine.get_unified_index() 180 | index = unified_index.get_index(Document) 181 | iterable = Document.objects.all() 182 | es.update(index, iterable) 183 | es.conn.indices.refresh.assert_any_call(index='testproject-en') 184 | es.conn.indices.refresh.assert_any_call(index='testproject-de') 185 | es.conn.indices.refresh.assert_any_call(index='testproject-fr') 186 | self.assertTrue(es.conn.bulk.called) 187 | self.assertEqual(len(es.conn.bulk.call_args_list), len(settings.LANGUAGES)) 188 | for call_args in es.conn.bulk.call_args_list: 189 | language = call_args[1]['index'][-2:] 190 | content = call_args[0][0][1] 191 | document = Document.objects.get(id=content['django_id']) 192 | self.assertEqual(document.docid, content['docid']) 193 | with translation.override(language): 194 | self.assertIn(escape(document.text), content['text']) 195 | -------------------------------------------------------------------------------- /tests/unittests/test_query.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import absolute_import, unicode_literals 3 | from django.test import SimpleTestCase 4 | from django.utils import translation 5 | 6 | from haystack.backends.elasticsearch_backend import ElasticsearchSearchBackend 7 | from haystack.query import SearchQuerySet 8 | from multilingual.elasticsearch_backend import ElasticsearchMultilingualSearchQuery, \ 9 | ElasticsearchMultilingualSearchBackend 10 | from .mocks import Data, mock_backend 11 | 12 | try: 13 | from unittest import mock # python >= 3.3 14 | except ImportError: 15 | import mock # python 2 16 | 17 | 18 | class BackendTest(SimpleTestCase): 19 | maxDiff = None 20 | 21 | # django_ct list has a random order. 22 | def assert_called_with_search_kwargs(self, search): 23 | try: 24 | search.assert_called_with(**Data.search_kwargs) 25 | except AssertionError: 26 | Data.search_kwargs['body']['query']['filtered']['filter']['terms']['django_ct'].reverse() # noqa 27 | search.assert_called_with(**Data.search_kwargs) 28 | 29 | @mock.patch('elasticsearch.Elasticsearch') 30 | def test_query(self, mock_es): 31 | sqs = SearchQuerySet() 32 | self.assertFalse(sqs.query.has_run()) 33 | self.assertIsInstance(sqs.query, ElasticsearchMultilingualSearchQuery) 34 | all_results = sqs.all() 35 | all_results.query.backend = mock_backend() 36 | list(all_results) 37 | self.assertTrue(all_results.query.backend.search.called) 38 | self.assertEqual('*:*', all_results.query.backend.search.call_args[0][0]) 39 | 40 | @mock.patch('elasticsearch.Elasticsearch') 41 | def test_haystack_search(self, mock_es): 42 | es = ElasticsearchSearchBackend('default', **Data.connection_options) 43 | self.assertFalse(es.setup_complete) 44 | es.setup() 45 | es.search('*:*', end_offset=1) 46 | # es.conn.search.assert_called_with(**Data.search_kwargs) 47 | self.assert_called_with_search_kwargs(es.conn.search) 48 | 49 | @mock.patch('elasticsearch.Elasticsearch') 50 | def test_multilingual_search(self, mock_es): 51 | es = ElasticsearchMultilingualSearchBackend('default', **Data.connection_options) 52 | es.setup() 53 | kwargs = Data.search_kwargs.copy() 54 | for language in ['de', 'en', 'ru']: 55 | with translation.override(language): 56 | es.search('*:*', end_offset=1) 57 | kwargs['index'] = es._index_name_for_language(language) 58 | es.conn.search.assert_called_with(**kwargs) 59 | 60 | @mock.patch('elasticsearch.Elasticsearch') 61 | def test_haystack_process_results(self, mock_es): 62 | es = ElasticsearchSearchBackend('default', **Data.connection_options) 63 | es.setup() 64 | results = es._process_results(Data.raw_results) 65 | expected = {'hits': 0, 'spelling_suggestion': None, 'results': [], 'facets': {}} 66 | self.assertEqual(expected, results) 67 | 68 | @mock.patch('elasticsearch.Elasticsearch') 69 | def test_multiligual_process_results(self, mock_es): 70 | es = ElasticsearchMultilingualSearchBackend('default', **Data.connection_options) 71 | es.setup() 72 | results = es._process_results(Data.raw_results) 73 | expected = {'hits': 0, 'spelling_suggestion': None, 'results': [], 'facets': {}} 74 | self.assertEqual(expected, results) 75 | -------------------------------------------------------------------------------- /vagrant_data/bashrc: -------------------------------------------------------------------------------- 1 | # ~/.bashrc: executed by bash(1) for non-login shells. 2 | # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) 3 | # for examples 4 | 5 | # If not running interactively, don't do anything 6 | [ -z "$PS1" ] && return 7 | 8 | # don't put duplicate lines in the history. See bash(1) for more options 9 | # ... or force ignoredups and ignorespace 10 | HISTCONTROL=ignoredups:ignorespace 11 | 12 | # append to the history file, don't overwrite it 13 | shopt -s histappend 14 | 15 | # for setting history length see HISTSIZE and HISTFILESIZE in bash(1) 16 | HISTSIZE=1000 17 | HISTFILESIZE=2000 18 | 19 | # check the window size after each command and, if necessary, 20 | # update the values of LINES and COLUMNS. 21 | shopt -s checkwinsize 22 | 23 | # make less more friendly for non-text input files, see lesspipe(1) 24 | [ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" 25 | 26 | # set variable identifying the chroot you work in (used in the prompt below) 27 | if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then 28 | debian_chroot=$(cat /etc/debian_chroot) 29 | fi 30 | 31 | # set a fancy prompt (non-color, unless we know we "want" color) 32 | case "$TERM" in 33 | xterm-color) color_prompt=yes;; 34 | esac 35 | 36 | # uncomment for a colored prompt, if the terminal has the capability; turned 37 | # off by default to not distract the user: the focus in a terminal window 38 | # should be on the output of commands, not on the prompt 39 | force_color_prompt=yes 40 | 41 | if [ -n "$force_color_prompt" ]; then 42 | if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then 43 | # We have color support; assume it's compliant with Ecma-48 44 | # (ISO/IEC-6429). (Lack of such support is extremely rare, and such 45 | # a case would tend to support setf rather than setaf.) 46 | color_prompt=yes 47 | else 48 | color_prompt= 49 | fi 50 | fi 51 | 52 | if [ "$color_prompt" = yes ]; then 53 | PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' 54 | else 55 | PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' 56 | fi 57 | unset color_prompt force_color_prompt 58 | 59 | # If this is an xterm set the title to user@host:dir 60 | case "$TERM" in 61 | xterm*|rxvt*) 62 | PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" 63 | ;; 64 | *) 65 | ;; 66 | esac 67 | 68 | # enable color support of ls and also add handy aliases 69 | if [ -x /usr/bin/dircolors ]; then 70 | test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" 71 | alias ls='ls --color=auto' 72 | #alias dir='dir --color=auto' 73 | #alias vdir='vdir --color=auto' 74 | 75 | alias grep='grep --color=auto' 76 | alias fgrep='fgrep --color=auto' 77 | alias egrep='egrep --color=auto' 78 | fi 79 | 80 | # some more ls aliases 81 | alias ll='ls -alF' 82 | alias la='ls -A' 83 | alias l='ls -CF' 84 | 85 | # Alias definitions. 86 | # You may want to put all your additions into a separate file like 87 | # ~/.bash_aliases, instead of adding them here directly. 88 | # See /usr/share/doc/bash-doc/examples in the bash-doc package. 89 | 90 | if [ -f ~/.bash_aliases ]; then 91 | . ~/.bash_aliases 92 | fi 93 | 94 | # enable programmable completion features (you don't need to enable 95 | # this, if it's already enabled in /etc/bash.bashrc and /etc/profile 96 | # sources /etc/bash.bashrc). 97 | if [ -f /etc/bash_completion ] && ! shopt -oq posix; then 98 | . /etc/bash_completion 99 | fi 100 | 101 | export WORKON_HOME=$HOME/.virtualenvs 102 | export PIP_DOWNLOAD_CACHE=$HOME/.pip_download_cache 103 | source /usr/local/bin/virtualenvwrapper.sh 104 | -------------------------------------------------------------------------------- /vagrant_data/common_requirements.txt: -------------------------------------------------------------------------------- 1 | Django==1.7.2 2 | django-devserver==0.8.0 3 | Pillow==2.7.0 4 | gunicorn==19.1.1 5 | fabric==1.10.0 6 | -------------------------------------------------------------------------------- /vagrant_data/etc-bash.bashrc: -------------------------------------------------------------------------------- 1 | # System-wide .bashrc file for interactive bash(1) shells. 2 | 3 | # To enable the settings / commands in this file for login shells as well, 4 | # this file has to be sourced in /etc/profile. 5 | 6 | # If not running interactively, don't do anything 7 | [ -z "$PS1" ] && return 8 | 9 | # check the window size after each command and, if necessary, 10 | # update the values of LINES and COLUMNS. 11 | shopt -s checkwinsize 12 | 13 | # set variable identifying the chroot you work in (used in the prompt below) 14 | if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then 15 | debian_chroot=$(cat /etc/debian_chroot) 16 | fi 17 | 18 | # set a fancy prompt (non-color, overwrite the one in /etc/profile) 19 | PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' 20 | 21 | # Commented out, don't overwrite xterm -T "title" -n "icontitle" by default. 22 | # If this is an xterm set the title to user@host:dir 23 | #case "$TERM" in 24 | #xterm*|rxvt*) 25 | # PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"' 26 | # ;; 27 | #*) 28 | # ;; 29 | #esac 30 | 31 | # enable bash completion in interactive shells 32 | #if [ -f /etc/bash_completion ] && ! shopt -oq posix; then 33 | # . /etc/bash_completion 34 | #fi 35 | 36 | # sudo hint 37 | if [ ! -e "$HOME/.sudo_as_admin_successful" ] && [ ! -e "$HOME/.hushlogin" ] ; then 38 | case " $(groups) " in *\ admin\ *) 39 | if [ -x /usr/bin/sudo ]; then 40 | cat <<-EOF 41 | To run a command as administrator (user "root"), use "sudo ". 42 | See "man sudo_root" for details. 43 | 44 | EOF 45 | fi 46 | esac 47 | fi 48 | 49 | # if the command-not-found package is installed, use it 50 | if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then 51 | function command_not_found_handle { 52 | # check because c-n-f could've been removed in the meantime 53 | if [ -x /usr/lib/command-not-found ]; then 54 | /usr/bin/python /usr/lib/command-not-found -- "$1" 55 | return $? 56 | elif [ -x /usr/share/command-not-found/command-not-found ]; then 57 | /usr/bin/python /usr/share/command-not-found/command-not-found -- "$1" 58 | return $? 59 | else 60 | printf "%s: command not found\n" "$1" >&2 61 | return 127 62 | fi 63 | } 64 | fi 65 | 66 | export LANGUAGE=en_GB.UTF-8 67 | export LANG=en_GB.UTF-8 68 | export LC_ALL=en_GB.UTF-8 69 | -------------------------------------------------------------------------------- /vagrant_data/vagrant.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script to set up dependencies for Django on Vagrant. 4 | 5 | PG_VERSION=9.4 6 | # Edit the following to change the name of the database user that will be created: 7 | APP_DB_USER=myapp 8 | APP_DB_PASS=dbpass 9 | 10 | # Edit the following to change the name of the database that is created (defaults to the user name) 11 | APP_DB_NAME=$APP_DB_USER 12 | 13 | 14 | print_db_usage () { 15 | echo "Your PostgreSQL database has been setup and can be accessed on your local machine on the forwarded port (default: 15432)" 16 | echo " Host: localhost" 17 | echo " Port: 15432" 18 | echo " Database: $APP_DB_NAME" 19 | echo " Username: $APP_DB_USER" 20 | echo " Password: $APP_DB_PASS" 21 | echo "" 22 | echo "Admin access to postgres user via VM:" 23 | echo " vagrant ssh" 24 | echo " sudo su - postgres" 25 | echo "" 26 | echo "psql access to app database user via VM:" 27 | echo " vagrant ssh" 28 | echo " sudo su - postgres" 29 | echo " PGUSER=$APP_DB_USER PGPASSWORD=$APP_DB_PASS psql -h localhost $APP_DB_NAME" 30 | echo "" 31 | echo "Env variable for application development:" 32 | echo " DATABASE_URL=postgresql://$APP_DB_USER:$APP_DB_PASS@localhost:15432/$APP_DB_NAME" 33 | echo "" 34 | echo "Local command to access the database via psql:" 35 | echo " PGUSER=$APP_DB_USER PGPASSWORD=$APP_DB_PASS psql -h localhost -p 15432 $APP_DB_NAME" 36 | } 37 | 38 | PROVISIONED_ON=/etc/vm_provision_on_timestamp 39 | if [ -f "$PROVISIONED_ON" ] 40 | then 41 | echo "VM was already provisioned at: $(cat $PROVISIONED_ON)" 42 | echo "To run system updates manually login via 'vagrant ssh' and run 'apt-get update && apt-get upgrade'" 43 | echo "" 44 | print_db_usage 45 | exit 46 | fi 47 | 48 | export DEBIAN_FRONTEND=noninteractive 49 | 50 | # Need to fix locale so that Postgres creates databases in UTF-8 51 | cp -p /vagrant_data/etc-bash.bashrc /etc/bash.bashrc 52 | locale-gen en_GB.UTF-8 53 | dpkg-reconfigure locales 54 | 55 | export LANGUAGE=en_GB.UTF-8 56 | export LANG=en_GB.UTF-8 57 | export LC_ALL=en_GB.UTF-8 58 | 59 | 60 | PG_REPO_APT_SOURCE=/etc/apt/sources.list.d/pgdg.list 61 | if [ ! -f "$PG_REPO_APT_SOURCE" ] 62 | then 63 | # Add PG apt repo: 64 | echo "deb http://apt.postgresql.org/pub/repos/apt/ precise-pgdg main" > "$PG_REPO_APT_SOURCE" 65 | 66 | # Add PGDG repo key: 67 | wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | apt-key add - 68 | fi 69 | 70 | 71 | 72 | # Install essential packages from Apt 73 | ./vagrant_data/apt.postgresql.org.sh 74 | apt-get update -y 75 | apt-get -y upgrade 76 | 77 | # Python dev packages 78 | apt-get install -y build-essential python-software-properties python-pip 79 | # Dependencies for image processing with Pillow (drop-in replacement for PIL) 80 | # supporting: jpeg, tiff, png, freetype, littlecms 81 | apt-get install -y libjpeg-dev libtiff-dev zlib1g-dev libfreetype6-dev liblcms2-dev 82 | # Git (we'd rather avoid people keeping credentials for git commits in the repo, but sometimes we need it for pip requirements that aren't in PyPI) 83 | apt-get install -y git elasticsearch 84 | 85 | # install all versions of Python for testing. 86 | add-apt-repository -y ppa:fkrull/deadsnakes 87 | apt-get install -qq python2.7 python2.7-dev python3.4 python3.4-dev 88 | 89 | # Postgresql 90 | 91 | # 92 | #apt-get -y install "postgresql-$PG_VERSION" "postgresql-contrib-$PG_VERSION" libpq-dev 93 | # 94 | #PG_CONF="/etc/postgresql/$PG_VERSION/main/postgresql.conf" 95 | #PG_HBA="/etc/postgresql/$PG_VERSION/main/pg_hba.conf" 96 | #PG_DIR="/var/lib/postgresql/$PG_VERSION/main" 97 | # 98 | ## Edit postgresql.conf to change listen address to '*': 99 | #sed -i "s/#listen_addresses = 'localhost'/listen_addresses = '*'/" "$PG_CONF" 100 | # 101 | ## Append to pg_hba.conf to add password auth: 102 | #echo "host all all all md5" >> "$PG_HBA" 103 | # 104 | ## Explicitly set default client_encoding 105 | #echo "client_encoding = utf8" >> "$PG_CONF" 106 | # 107 | ## Restart so that all new config is loaded: 108 | #service postgresql restart 109 | # 110 | #cat << EOF | su - postgres -c psql 111 | #-- Create the database user: 112 | #CREATE USER $APP_DB_USER WITH PASSWORD '$APP_DB_PASS'; 113 | # 114 | #-- Create the database: 115 | #CREATE DATABASE $APP_DB_NAME WITH OWNER=$APP_DB_USER 116 | # LC_COLLATE='en_US.utf8' 117 | # LC_CTYPE='en_US.utf8' 118 | # ENCODING='UTF8' 119 | # TEMPLATE=template0; 120 | #EOF 121 | 122 | # Tag the provision time: 123 | date > "$PROVISIONED_ON" 124 | 125 | 126 | # install java 127 | sudo apt-get install openjdk-7-jre-headless -y 128 | 129 | 130 | # install elasticsearch 131 | wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.4.2.deb 132 | sudo dpkg -i elasticsearch-1.4.2.deb 133 | 134 | # Configure Elasticsearch to automatically start during bootup : 135 | update-rc.d elasticsearch defaults 95 10 136 | sudo service elasticsearch start 137 | 138 | 139 | # install head 140 | sudo /usr/share/elasticsearch/bin/plugin -install mobz/elasticsearch-head 141 | 142 | 143 | # virtualenv global setup 144 | if ! command -v pip; then 145 | easy_install -U pip 146 | fi 147 | if [[ ! -f /usr/local/bin/virtualenv ]]; then 148 | easy_install virtualenv 149 | fi 150 | 151 | pip install tox 152 | 153 | # bash environment global setup 154 | cp -p /vagrant_data/bashrc /home/vagrant/.bashrc 155 | 156 | 157 | # Cleanup 158 | apt-get clean 159 | 160 | 161 | --------------------------------------------------------------------------------