def test_admin_licence_list_view(self): """ The admin list view of licences should display the name of the licence. """ user = UserFactory(is_staff=True, is_superuser=True) self.client.login(username=user.username, password="******") # Create a licence with English fields and French translations licence = LicenceFactory(name="some licence name") with switch_language(licence, "fr"): licence.name = "quelque nom de licence" licence.save() # Get the admin list view in English url = reverse("admin:courses_licence_changelist") response = self.client.get(url, follow=True) # Check that the page includes the name in English with switch_language(licence, "en"): self.assertContains(response, licence.name, status_code=200) # Get the admin change view in French with translation.override("fr"): url = reverse("admin:courses_licence_changelist") response = self.client.get(url) # Check that the page includes the name in French with switch_language(licence, "fr"): self.assertContains(response, licence.name)
def test_opening_is_reverted_if_fk_object_was_deleted(self): opening = self.create_default_job_opening(translated=True) self.assertEqual(len(get_for_object(opening)), 0) # revision 1: en 1, de 0 category_1 = self.default_category new_values_en_1 = self.make_new_values(self.opening_values_raw['en'], 1) with switch_language(opening, 'en'): self.create_revision(opening, **new_values_en_1) # revision 2: en 1, de 1 new_values_de_1 = self.make_new_values(self.opening_values_raw['de'], 1) # update category category_2 = JobCategory.objects.create( app_config=self.app_config, **self.make_new_values(self.category_values_raw['en'], 2)) new_values_de_1['category'] = category_2 with switch_language(opening, 'de'): self.create_revision(opening, **new_values_de_1) # delete category_1 with transaction.atomic(): category_1.delete() self.assertEqual(JobCategory.objects.all().count(), 1) # revert to 1 self.revert_to(opening, 1) opening = JobOpening.objects.get(pk=opening.pk) self.assertNotEqual(opening.category, category_2) self.assertEqual(JobCategory.objects.all().count(), 2)
def test_models_course_run_copy_translations_one_language(self): """ The "copy_translations" method called for a specific language should only port parler's translations for this language from one course run to the other. """ course_run = CourseRunFactory(title="my title") CourseRunTranslation.objects.create(master=course_run, language_code="fr", title="mon titre") old_course_run = CourseRun.objects.get(pk=course_run.pk) self.assertEqual(CourseRunTranslation.objects.count(), 2) with switch_language(old_course_run, "fr"): self.assertEqual(old_course_run.title, "mon titre") course_run.pk = None course_run.save() self.assertEqual(CourseRunTranslation.objects.count(), 2) course_run.copy_translations(old_course_run, language="fr") self.assertEqual(CourseRun.objects.count(), 2) self.assertEqual(CourseRunTranslation.objects.count(), 3) self.assertEqual( CourseRunTranslation.objects.filter(master=course_run).count(), 1) course_run.refresh_from_db() self.assertEqual(course_run.title, "mon titre") # Fallback to french with switch_language(course_run, "fr"): self.assertEqual(course_run.title, "mon titre")
def test_authsource_translation(settings): PARLER_LANGUAGES = { None: ( { 'code': 'fi', }, { 'code': 'sv', }, ), 'default': { 'fallbacks': ['fi'], } } settings.PARLER_LANGUAGES = PARLER_LANGUAGES settings.LANGUAGE_CODE = 'fi' data = { 'auth_id': 'testSource', 'icon_url': 'https://foo.fi/image.png', 'title': 'test title', } obj = AuthenticationSource.objects.create(**data) swedish_title = 'titel' obj.set_current_language('sv') obj.title = swedish_title obj.save() with switch_language(obj, 'fi'): assert obj.title == data['title'] with switch_language(obj, 'sv'): assert obj.title == swedish_title
def test_models_course_run_copy_translations_all_languages(self): """ The "copy_translations" method should port parler's translations for all languages from one course run to the other. """ course_run = CourseRunFactory(title="my title") CourseRunTranslation.objects.create(master=course_run, language_code="fr", title="mon titre") old_course_run = CourseRun.objects.get(pk=course_run.pk) self.assertEqual(CourseRunTranslation.objects.count(), 2) with switch_language(old_course_run, "fr"): self.assertEqual(old_course_run.title, "mon titre") course_run.pk = None course_run.save() self.assertEqual(CourseRunTranslation.objects.count(), 2) course_run.copy_translations(old_course_run) self.assertEqual(CourseRun.objects.count(), 2) self.assertEqual(CourseRunTranslation.objects.count(), 4) self.assertEqual( CourseRunTranslation.objects.filter(master=course_run).count(), 2) course_run.refresh_from_db() self.assertEqual(course_run.title, "my title") with switch_language(course_run, "fr"): self.assertEqual(course_run.title, "mon titre")
def test_admin_licence_change_view_get(self): """ The admin change view should include the name and content fields for the given language. """ user = UserFactory(is_staff=True, is_superuser=True) self.client.login(username=user.username, password="******") # Create a licence with English fields and French translations licence = LicenceFactory(name="some licence name", content="some licence text content") with switch_language(licence, "fr"): licence.name = "quelque nom de licence" licence.content = "quelque contenu textuel de licence" licence.save() # Get the admin change view in English url = reverse("admin:courses_licence_change", args=[licence.id]) response = self.client.get(url) # Check that the page includes the name and content in English with switch_language(licence, "en"): self.assertContains(response, licence.name) self.assertContains(response, licence.content) # Get the admin change view in French url = reverse("admin:courses_licence_change", args=[licence.id]) response = self.client.get("{}?language=fr".format(url)) # Check that the page includes the name and content in French with switch_language(licence, "fr"): self.assertContains(response, licence.name) self.assertContains(response, licence.content)
def test_post_detail_view(self): page1, page2 = self.get_pages() post1, post2 = self.get_posts() with switch_language(post1, 'en'): request = self.get_page_request(page1, AnonymousUser(), r'/en/blog/', edit=False) view_obj = PostDetailView() view_obj.request = request with self.assertRaises(Http404): view_obj.kwargs = {'slug': 'not-existing'} post_obj = view_obj.get_object() view_obj.kwargs = {'slug': post1.slug} post_obj = view_obj.get_object() self.assertEqual(post_obj, post1) self.assertEqual(post_obj.language_code, 'en') with switch_language(post1, 'it'): request = self.get_page_request(page1, AnonymousUser(), r'/it/blog/', lang_code='it', edit=False) view_obj.request = request view_obj.kwargs = {'slug': post1.slug} post_obj = view_obj.get_object() self.assertEqual(post_obj, post1) self.assertEqual(post_obj.language_code, 'it') view_obj.object = post_obj context = view_obj.get_context_data() self.assertEqual(context['post'], post1) self.assertEqual(context['post'].language_code, 'it') self.assertTrue(context['meta'])
def test_revert_revision(self): values_raw = { 'title': 'Title revision {0}', 'slug': 'revision-{0}-slug', 'start_date': tz_datetime(2014, 9, 10), 'publish_at': tz_datetime(2014, 9, 10), } content1 = 'Revision 1 content' content2 = 'Revision 2 content, brand new one!' event = self.create_default_event() # revision 1 revision_1_values = self.make_new_values(values_raw, 1) event.set_current_language('en') self.create_event_revision(event, content=content1, **revision_1_values) # revision 2 revision_2_values = self.make_new_values(values_raw, 2) event = Event.objects.get(pk=event.pk) event.set_current_language('en') self.create_event_revision(event, content=content2, **revision_2_values) # check that latest revision values are used with switch_language(event, 'en'): url_revision_2 = event.get_absolute_url() response = self.client.get(url_revision_2) self.assertContains(response, revision_2_values['title']) self.assertContains(response, content2) # test that there is no default values self.assertNotContains(response, self.default_content['en']) self.assertNotContains(response, self.default_en['title']) # test that there is no previous version content (placeholder) self.assertNotContains(response, content1) # test revert for event self.revert_to(event, 1) # test urls, since slug was changed they shouldn't be the same. event = Event.objects.get(pk=event.pk) with switch_language(event, 'en'): url_revision_1 = event.get_absolute_url() self.assertNotEqual(url_revision_2, url_revision_1) response = self.client.get(url_revision_1) self.assertContains(response, revision_1_values['title']) self.assertContains(response, content1) # test that there is no default content self.assertNotContains(response, self.default_content['en']) self.assertNotContains(response, self.default_en['title']) # test that there is no revision 2 content self.assertNotContains(response, revision_2_values['title']) # test that there is no revision 2 content (placeholder) self.assertNotContains(response, content2)
def test_cast_multilanguage(self): cast = self.windtalkers.cast nicolas = cast.all()[0] with switch_language(nicolas, 'pl'): self.assertEqual(nicolas.role, u'Sierżant Joe Enders') with switch_language(nicolas, 'en'): self.assertEqual(nicolas.role, u'Sergeant Joe Enders')
def test_add_translations(self): values = [ # language code, name, slug ('en', "Cheese Omelette", "cheese-omelette"), ('de', "Käseomelett", "kaseomelett"), ('fr', "Omelette au Fromage", "omelette-au-fromage"), ] node = None # Create the translations for lang, name, slug in values: if node: with switch_language(node, lang): node.name = name node.save() else: with translation.override(lang): node = Category.add_root(name=name) node.save() # Now test that they exist (and didn't obliterate one another) for lang, name, slug in values: with switch_language(node, lang): self.assertEqual(node.name, name) self.assertEqual(node.slug, slug) # Now test that we gracefully handle languages where there is no # translation. with switch_language(node, 'it'): try: node.name except Exception: self.fail("Translating to an unavailable language should not " "result in an exception.")
def test_add_translations(self): values = [ # language code, name, slug ('en', "Cheese Omelette", "cheese-omelette"), ('de', "Käseomelett", "kaseomelett"), ('fr', "Omelette au Fromage", "omelette-au-fromage"), ] node = None # Create the translations for lang, name, slug in values: if node: with switch_language(node, lang): node.name = name node.save() else: with translation.override(lang): node = Category.add_root(name=name) node.save() # Now test that they exist (and didn't obliterate one another) for lang, name, slug in values: with switch_language(node, lang): self.assertEqual(node.name, name) self.assertEqual(node.slug, slug) # Now test that we gracefully handle languages where there is no # translation. with switch_language(node, 'it'): try: node.name except: self.fail("Translating to an unavailable language should not " "result in an exception.")
def test_article_detail_not_translated_fallback(self): """ If the fallback is configured, article is available in any (configured) language """ author = self.create_person() code = "{0}-".format(self.language) article = Article.objects.create(title=rand_str(), slug=rand_str(prefix=code), app_config=self.app_config, author=author, owner=author.user, publishing_date=datetime.now()) article.save() article.categories.add(self.category1) # current language - it still exists article = Article.objects.get(pk=article.pk) language = settings.LANGUAGES[0][0] with switch_language(self.category1, language): url = reverse('aldryn_newsblog:article-detail', kwargs={'slug': article.slug}) response = self.client.get(url) self.assertContains(response, article.title) # non existing language - it still exists language = settings.LANGUAGES[1][0] with switch_language(self.category1, language): url = reverse('aldryn_newsblog:article-detail', kwargs={'slug': article.slug}) response = self.client.get(url) self.assertContains(response, article.title)
def test_dashboard_detail_not_translated_no_fallback(self): """ If the fallback is disabled, dashboard is available only in the language in which is translated """ author = self.create_person() code = "{0}-".format(self.language) dashboard = Dashboard.objects.create( title=self.rand_str(), slug=self.rand_str(prefix=code), app_config=self.app_config, author=author, owner=author.user, publishing_date=now(), is_published=True, ) dashboard.save() dashboard.categories.add(self.category1) PARLER_LANGUAGES = { 1: ( { 'code': 'de' }, { 'code': 'fr' }, { 'code': 'en' }, ), 'default': { 'hide_untranslated': True, } } LANGUAGES = add_default_language_settings(PARLER_LANGUAGES) with override_parler_settings(PARLER_LANGUAGES=LANGUAGES): # current language - it still exists dashboard = Dashboard.objects.get(pk=dashboard.pk) language = settings.LANGUAGES[0][0] with switch_language(self.category1, language): url = reverse('dashboards_app:dashboard-detail', kwargs={'slug': dashboard.slug}) response = self.client.get(url) self.assertContains(response, dashboard.title) # non existing language - it does NOT exists language = settings.LANGUAGES[1][0] with switch_language(self.category1, language): url = reverse('dashboards_app:dashboard-detail', kwargs={'slug': dashboard.slug}) response = self.client.get(url) self.assertEqual(response.status_code, 404)
def _create_timeseries(self, station, var_en, var_fr): variable = models.Variable() with switch_language(variable, "en"): variable.descr = var_en with switch_language(variable, "fr"): variable.descr = var_fr variable.save() mommy.make( models.Timeseries, timeseries_group__gentity=station, timeseries_group__variable=variable, )
def test_article_detail_not_translated_fallback(self): """ If the fallback is configured, article is available in any (configured) language """ author = self.create_person() code = "{0}-".format(self.language) with override(settings.LANGUAGES[0][0]): article = Article.objects.create( title=self.rand_str(), slug=self.rand_str(prefix=code), app_config=self.app_config, author=author, owner=author.user, publishing_date=now(), is_published=True, ) article.save() article.categories.add(self.category1) url_one = reverse( 'aldryn_newsblog:article-detail', kwargs={'slug': article.slug} ) # Parler settings should be same as cms settings and vice versa # ensure that if hide_untranslated = True we don't have a fallback # redirect. LANGUAGES = add_default_language_settings(PARLER_LANGUAGES_HIDE) with override_parler_settings(PARLER_LANGUAGES=LANGUAGES): language = settings.LANGUAGES[1][0] with switch_language(article, language): slug = article.safe_translation_getter('slug', None, language_code=language, any_language=True) url = reverse( 'aldryn_newsblog:article-detail', kwargs={'slug': slug} ) self.assertNotEquals(url, url_one) response = self.client.get(url) self.assertEquals(response.status_code, 404) # Test again with redirect_on_fallback = False with self.settings(CMS_LANGUAGES=self.NO_REDIRECT_CMS_SETTINGS): language = settings.LANGUAGES[1][0] with switch_language(article, language): slug = article.safe_translation_getter('slug', None) url = reverse( 'aldryn_newsblog:article-detail', kwargs={'slug': slug, } ) self.assertNotEquals(url, url_one) response = self.client.get(url) self.assertEquals(response.status_code, 404)
def test_get(user_api_client, endpoint, scope_included, service): foo_scope = ApiScopeFactory(api=ApiFactory(domain=ApiDomainFactory(identifier='https://foo.com'))) with switch_language(foo_scope, 'en'): foo_scope.name = 'name' foo_scope.description = 'description' foo_scope.save() with switch_language(foo_scope, 'fi'): foo_scope.name = 'nimi' foo_scope.description = 'kuvaus' foo_scope.save() user_consent = UserConsentFactory( user=user_api_client.user, client=service.client, scope=['email', foo_scope.identifier] ) url = LIST_URL if endpoint == 'list' else get_detail_url(user_consent) if scope_included: url += '?include=scope' response = user_api_client.get(url) assert response.status_code == 200 if endpoint == 'list': assert len(response.data['results']) == 1 user_consent_data = response.data['results'][0] else: user_consent_data = response.data assert set(user_consent_data.keys()) == {'id', 'date_given', 'expires_at', 'service', 'scopes'} assert parse_datetime(user_consent_data['date_given']) == user_consent.date_given assert parse_datetime(user_consent_data['expires_at']) == user_consent.expires_at assert user_consent_data['service'] == user_consent.client.service.id if scope_included: scope_data = user_consent_data['scopes'] assert len(scope_data) == 2 oidc_scope = scope_data[0] api_scope = scope_data[1] assert oidc_scope.keys() == {'id', 'name', 'description'} assert oidc_scope['id'] == 'email' assert oidc_scope['name'] == {'fi': 'Sähköposti', 'sv': 'E-postadress', 'en': 'Email'} assert 'en' in oidc_scope['description'] assert api_scope.keys() == {'id', 'name', 'description'} assert api_scope['id'] == foo_scope.identifier assert api_scope['name'] == {'fi': 'nimi', 'en': 'name'} assert api_scope['description'] == {'fi': 'kuvaus', 'en': 'description'} else: assert user_consent_data['scopes'] == user_consent.scope
def test_two_active_hook_pages_same_category_and_opening_names(self): # regression for issue with two job configs (different namespace) # which have same categories names/slugs and same openings title/slugs new_config = JobsConfig.objects.create( namespace='another_apphook_to_test') new_apphook_page = self.create_page( title='new apphook', slug='new-apphook', namespace=new_config.namespace) default_opening = self.create_default_job_opening(translated=True) same_name_category = self.create_default_job_category( translated=True, config=new_config) same_name_opening = self.create_default_job_opening( translated=True, category=same_name_category) lead_in_text_raw = '{0} lead in for other config' for language in ('de', 'en'): # get urls default_opening_url = default_opening.get_absolute_url(language) same_name_opening_url = same_name_opening.get_absolute_url(language) with override(language): default_app_url = self.page.get_absolute_url() other_app_url = new_apphook_page.get_absolute_url() with switch_language(same_name_opening, language): # change lead in to be different for other opening same_name_opening.lead_in = lead_in_text_raw.format( language) same_name_opening.save() # urls should be different because namespace is different self.assertNotEqual(default_app_url, other_app_url) response_default = self.client.get(default_app_url) self.assertEqual(response_default.status_code, 200) self.assertContains(response_default, default_opening_url) response_other = self.client.get(other_app_url) self.assertEqual(response_other.status_code, 200) self.assertContains(response_other, same_name_opening_url) # test translated content, unfortunately we need to explicitly # switch language with switch_language(default_opening, language): self.assertContains(response_default, default_opening.title) with switch_language(same_name_opening, language): self.assertContains(response_other, same_name_opening.title)
def test_article_detail_not_translated_fallback(self): """ If the fallback is configured, article is available in any (configured) language """ author = self.create_person() code = "{0}-".format(self.language) with override(settings.LANGUAGES[0][0]): article = Article.objects.create( title=self.rand_str(), slug=self.rand_str(prefix=code), app_config=self.app_config, author=author, owner=author.user, publishing_date=now()) article.save() article.categories.add(self.category1) url_one = reverse( 'aldryn_newsblog:article-detail', kwargs={'slug': article.slug} ) LANGUAGES = add_default_language_settings(PARLER_LANGUAGES_SHOW) with override_parler_settings(PARLER_LANGUAGES=LANGUAGES): # Non-existing language - an article will be returned, even though # it is the wrong language. language = settings.LANGUAGES[1][0] with switch_language(article, language): url = reverse( 'aldryn_newsblog:article-detail', kwargs={'slug': article.slug, } ) self.assertNotEquals(url, url_one) response = self.client.get(url) # This is a redirect to the new language self.assertEquals(response.status_code, 302) # Test again with redirect_on_fallback = False with self.settings(CMS_LANGUAGES=self.NO_REDIRECT_CMS_SETTINGS): language = settings.LANGUAGES[1][0] with switch_language(article, language): url = reverse( 'aldryn_newsblog:article-detail', kwargs={'slug': article.slug, } ) self.assertNotEquals(url, url_one) response = self.client.get(url) # This is a redirect to the new language self.assertEquals(response.status_code, 200)
def get_value(self, obj): try: if not obj.get_parent(): return '' for lang_short, lang_long in settings.LANGUAGES: with switch_language(obj, lang_short): with switch_language(obj.get_parent(), lang_short): parent_slug = obj.get_parent().slug # return slug in language which is set FIRST in settings.LANGUAGES return parent_slug except (ValueError, ObjectDoesNotExist): return None
def create_default_event(self, translated=False): event = Event.objects.create(**self.default_en) with switch_language(event, 'en'): api.add_plugin(event.description, 'TextPlugin', 'en', body=self.default_content['en']) # check if we need a translated event if translated: event.create_translation('de', **self.default_de) with switch_language(event, 'de'): api.add_plugin(event.description, 'TextPlugin', 'de', body=self.default_content['de']) return Event.objects.language('en').get(pk=event.pk)
def test_edit_plugin_directly(self): job_opening = self.create_default_job_opening() # revision 1 content_en_1 = self.plugin_values_raw['en'].format(1) self.create_revision(job_opening, content=content_en_1) self.assertEqual(len(get_for_object(job_opening)), 1) # revision 2 content_en_2 = self.plugin_values_raw['en'].format(2) with transaction.atomic(): language = job_opening.get_current_language() plugins = job_opening.content.get_plugins().filter( language=language) plugin = plugins[0].get_plugin_instance()[0] plugin.body = content_en_2 plugin.save() aldryn_create_revision(job_opening) self.assertEqual(len(get_for_object(job_opening)), 2) with switch_language(job_opening, 'en'): url = job_opening.get_absolute_url() response = self.client.get(url) self.assertContains(response, content_en_2) self.assertNotContains(response, content_en_1) self.revert_to(job_opening, 1) job_opening = JobOpening.objects.get(pk=job_opening.pk) response = self.client.get(job_opening.get_absolute_url()) self.assertContains(response, content_en_1) self.assertNotContains(response, content_en_2)
def test_opening_reverted_revision_serves_appropriate_content(self): job_opening = self.create_default_job_opening() # revision 1 new_values_en_1 = self.make_new_values(self.opening_values_raw['en'], 1) content_en_1 = self.plugin_values_raw['en'].format(1) self.create_revision( job_opening, content=content_en_1, **new_values_en_1) # revision 2 new_values_en_2 = self.make_new_values(self.opening_values_raw['en'], 2) content_en_2 = self.plugin_values_raw['en'].format(2) self.create_revision( job_opening, content=content_en_2, **new_values_en_2) # revert to 1 job_opening = JobOpening.objects.get(pk=job_opening.pk) self.revert_to(job_opening, 1) job_opening = JobOpening.objects.get(pk=job_opening.pk) with switch_language(job_opening, 'en'): url = job_opening.get_absolute_url() response = self.client.get(url) self.assertContains(response, new_values_en_1['title']) self.assertContains(response, content_en_1) self.assertNotContains(response, new_values_en_2['title']) self.assertNotContains(response, content_en_2)
def notification_template(): notification_type = "event_created" notifications.register(notification_type, "Event created") template = NotificationTemplate.objects.language("en").create( type=notification_type, subject="test subject, variable value: {{ subject_var }}!", body_html="<b>test body HTML</b>, variable value: {{ body_html_var }}!", body_text="test body text, variable value: {{ body_text_var }}!", ) with switch_language(template, "fi"): template.subject = "testiotsikko, muuttujan arvo: {{ subject_var }}!" template.body_html = ( "<b>testihötömölöruumis</b>, muuttujan arvo: {{ body_html_var }}!") template.body_text = "testitekstiruumis, muuttujan arvo: {{ body_text_var }}!" template.save() dummy_context = DummyContext() dummy_context.update({ COMMON_CONTEXT: {}, notification_type: { "subject_var": "subject", "body_html_var": "body_html_var", "body_text_var": "body_text_var", }, }) return template
def test_menu_nodes(self): """ Tests if all categories are present in the menu """ for lang in ('en', 'it'): request = self.get_page_request(None, self.user, r'/%s/blog/' % lang, edit=False) activate(lang) nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu') nodes_copy = copy.deepcopy(nodes) for cat in self.cats: if not cat.has_translation(lang): continue with switch_language(cat, lang): # find in node list found = None for node in nodes_copy: if node.url == cat.get_absolute_url(): found = node break self.assertIsNotNone(found) nodes_copy.remove(found) self.assertEqual(node.id, cat.id) self.assertEqual(node.title, cat.name) # check that all categories were found in menu self.assertEqual(len(nodes_copy), 0)
def get_value(self, obj): if self.attribute is None: return None tmp = self.attribute.split('_') attr_name = "_".join(tmp[:-1]) attr_language = tmp[-1] value = obj with switch_language(value, attr_language): translation.activate(attr_language) try: value = getattr(value, attr_name, None) except (ValueError, ObjectDoesNotExist): # needs to have a primary key value before a many-to-many # relationship can be used. return None if value is None: return None # RelatedManager and ManyRelatedManager classes are callable in # Django >= 1.7 but we don't want to call them if callable(value) and not isinstance(value, Manager): value = value() return value
def test_models_course_run_mark_dirty_parler(self): """ Updating the value of a field translatable via parler should mark the related course page dirty (waiting to be published) only in the impacted language. """ course = CourseFactory(page_languages=["en", "fr"]) course_run = CourseRunFactory(direct_course=course) CourseRunTranslation.objects.create(master=course_run, language_code="fr", title="mon titre") self.assertTrue(course_run.direct_course.extended_object.publish("en")) self.assertTrue(course_run.direct_course.extended_object.publish("fr")) course_run.refresh_from_db() self.assertIsNotNone(course_run.public_course_run) title_query = course_run.direct_course.extended_object.title_set title_obj_en = title_query.get(language="en") title_obj_fr = title_query.get(language="fr") self.assertEqual(title_query.count(), 2) with switch_language(course_run, "fr"): course_run.title = "nouveau titre" course_run.save() self.assertEqual(title_obj_en.publisher_state, PUBLISHER_STATE_DEFAULT) self.assertEqual(title_obj_fr.publisher_state, PUBLISHER_STATE_DEFAULT) course_run.mark_course_dirty() title_obj_en.refresh_from_db() title_obj_fr.refresh_from_db() self.assertEqual(title_obj_en.publisher_state, PUBLISHER_STATE_DEFAULT) self.assertEqual(title_obj_fr.publisher_state, PUBLISHER_STATE_DIRTY)
def test_index_multilingual(self): self.index = ArticleIndex() content0 = self.rand_str(prefix='content0_') self.setup_categories() article_1 = self.create_article(content=content0, lead_in=u'lead in text', title=u'a title') article_2 = self.create_article(content=content0, lead_in=u'lead in text', title=u'second title') for article in (article_1, article_2): for category in (self.category1, self.category2): article.categories.add(category) with switch_language(article_2, 'de'): article_2.title = u'de title' article_2.lead_in = u'de lead in' article_2.save() LANGUAGES = add_default_language_settings(PARLER_LANGUAGES_HIDE) with override_parler_settings(PARLER_LANGUAGES=LANGUAGES): with smart_override('de'): language = get_current_language() # english-only article is excluded qs = self.index.index_queryset(language) self.assertEqual(qs.count(), 1) self.assertEqual( qs.translated(language, title__icontains='title').count(), 1) # the language is correctly setup for article_de in qs: self.assertEqual(self.index.get_title(article_de), 'de title') self.assertEqual(self.index.get_description(article_de), 'de lead in')
def load_sms_templates(offset): logger.info("Writing SMS templates") sms_notifications = { PaymentNotificationType.SMS_INVOICE_NOTICE: "invoice_notice_{lang}.txt", PaymentNotificationType.SMS_BERTH_SWITCH_NOTICE: "berth_switch_notice_{lang}.txt", } for notification_index, (notification_type, template_path) in enumerate( sms_notifications.items()): template = NotificationTemplate.objects.create( id=notification_index + offset, type=notification_type.value, ) for (lang, _name) in languages: with override(lang), switch_language(template, lang): template.subject = notification_type.label full_path = os.path.join(PROJECT_ROOT, "templates", "sms", template_path).format(lang=lang) # Check that the path for the specified language exists if os.path.isfile(full_path): with open(full_path, "r") as template_file: body = str(template_file.read()) # The HTML body works just to test the rendered message, it won't be used template.body_html = body template.body_text = body template.save() logger.info(f"Written template: {template}")
def test_modifier(self): """ Tests if correct category is selected in the menu according to context (view object) """ post1, post2 = self.get_posts() tests = ( # view class, view kwarg, view object, category (PostDetailView, 'slug', post1, post1.categories.first()), (CategoryEntriesView, 'category', self.cats[2], self.cats[2]) ) for view_cls, kwarg, obj, cat in tests: request = self.get_page_request(None, self.user, r'/en/blog/', edit=False) activate('en') with switch_language(obj, 'en'): view_obj = view_cls() view_obj.request = request view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) # check if selected menu node points to cat nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu') found = False for node in nodes: if node.selected: self.assertEqual(node.url, cat.get_absolute_url()) found = True break self.assertTrue(found)
def handle(self, *args, **options): languages = options.get('languages') if languages is None: languages = [language[0] for language in settings.LANGUAGES] # ArticleTranslation translation_model = Article._parler_meta.root_model for article in Article.objects.published(): translations = article.translations.filter( language_code__in=languages ) # build internal parler cache parler_cache = dict( (trans.language_code, trans) for trans in translations) # set internal parler cache # to avoid parler hitting db for every language article._translations_cache[translation_model] = parler_cache for translation in translations: language = translation.language_code with switch_language(article, language_code=language): translation.search_data = article.get_search_data() # make sure to only update the search_data field translation.save(update_fields=["search_data"])
def setup_categories(self): """ Sets-up i18n categories (self.category_root, self.category1 and self.category2) for use in tests """ self.language = settings.LANGUAGES[0][0] categories = [] # Set the default language, create the objects with override(self.language): code = "{0}-".format(self.language) self.category_root = Category.add_root( name=self.rand_str(prefix=code, length=8)) categories.append(self.category_root) self.category1 = self.category_root.add_child( name=self.rand_str(prefix=code, length=8)) categories.append(self.category1) self.category2 = self.category_root.add_child( name=self.rand_str(prefix=code, length=8)) categories.append(self.category2) # We should reload category_root, since we modified its children. self.category_root = self.reload(self.category_root) # Setup the other language(s) translations for the categories for language, _ in settings.LANGUAGES[1:]: for category in categories: with switch_language(category, language): code = "{0}-".format(language) category.name = self.rand_str(prefix=code, length=8) category.save()
def test_category_multiple_choice_field(self): root = Category.add_root(name="root") root.save() child1 = root.add_child(name="child1") child2 = root.add_child(name="child2") grandchild1 = child1.add_child(name="grandchild1") root = self.reload(root) child1 = self.reload(child1) field = CategoryMultipleChoiceField(None) self.assertEqual( field.label_from_instance(child2), " child2", ) self.assertEqual( field.label_from_instance(grandchild1), " grandchild1", ) # Tests that the field correctly throws an ImproperlyConfigured # exception if the given object is not a Category (or something that # acts like one) with self.assertRaises(ImproperlyConfigured): field.label_from_instance(object) # Check that using an untranslated language does not raise exceptions with switch_language(child1, 'it'): try: field.label_from_instance(child1) except ImproperlyConfigured: self.fail("Translating to an unavailable language should not " "result in an exception.")
def test_dashboard_update_organisation(client, organisation): url = reverse('dashboard-organisation-edit', kwargs={ 'organisation_slug': organisation.slug, }) initiator = organisation.initiators.first() client.login(username=initiator.email, password='******') response = client.get(url) form = response.context_data['form'] assert form.prefiled_languages() == ['en'] assert len(form.untranslated()) == 8 assert len(form.translated()) == 7 assert form.translated()[0][0] == 'en' assert len(form.translated()[0][1]) == 4 response = client.post(url, { 'twitter_handle': 'a thandle', 'place': 'Berlin', 'country': 'DE', 'de': 'de', 'de__title': 'title.de', 'de__description': 'desc.de', 'de__description_why': 'desc why.de', 'de__description_how': 'desc how.de', }) response.status_code == 200 organisation.refresh_from_db() assert organisation.place == 'Berlin' assert organisation.twitter_handle == 'a thandle' with switch_language(organisation, 'de'): assert organisation.description == 'desc.de'
def get_absolute_url(self, lang=None): if not lang or lang not in self.get_available_languages(): lang = get_language() if not lang or lang not in self.get_available_languages(): lang = self.get_current_language() with switch_language(self, lang): category = self.categories.first() kwargs = {} if self.date_published: current_date = self.date_published else: current_date = self.date_created urlconf = get_setting('PERMALINK_URLS')[self.app_config.url_patterns] if '<year>' in urlconf: kwargs['year'] = current_date.year if '<month>' in urlconf: kwargs['month'] = '%02d' % current_date.month if '<day>' in urlconf: kwargs['day'] = '%02d' % current_date.day if '<slug>' in urlconf: kwargs['slug'] = self.safe_translation_getter( 'slug', language_code=lang, any_language=True ) # NOQA if '<category>' in urlconf: kwargs['category'] = category.safe_translation_getter( 'slug', language_code=lang, any_language=True) # NOQA return reverse('%s:post-detail' % self.app_config.namespace, kwargs=kwargs)
def render_notification_template(notification_type, context, language_code=DEFAULT_LANGUAGE): """ Render a notification template with given context in given language Returns a namedtuple containing all content fields (subject, html_body, text_body) of the template. """ template = NotificationTemplate.objects.get(type=notification_type) env = SandboxedEnvironment(trim_blocks=True, lstrip_blocks=True, undefined=StrictUndefined) with switch_language(template, language_code): try: subject = env.from_string(template.subject).render(context) html_body = env.from_string(template.html_body).render(context) if template.text_body: text_body = env.from_string(template.text_body).render(context) else: text_body = strip_tags(html_body) return RenderedTemplate(subject, html_body, text_body) except TemplateError as e: raise NotificationTemplateException(e) from e
def dispatch(self, request, *args, **kwargs): try: return super(TranslatableSlugMixin, self).dispatch(request, *args, **kwargs) except FallbackLanguageResolved as e: # Handle the fallback language redirect for get_object() with switch_language(e.object, e.correct_language): return HttpResponsePermanentRedirect(e.object.get_absolute_url())
def get_search_data(self, post, language, request): with switch_language(post, language): description = post.get_description() abstract = strip_tags(post.safe_translation_getter('abstract', default='')) keywords = post.get_keywords() text_bits = [] if abstract: text_bits.append(abstract) if description: text_bits.append(description) if keywords: text_bits.append(' '.join(keywords)) self.prepared_data['keywords'] = ','.join(keywords) for category in post.categories.all(): text_bits.append( force_text(category.safe_translation_getter('name'))) for tag in post.tags.all(): text_bits.append(force_text(tag.name)) if get_setting('USE_PLACEHOLDER'): plugins = post.content.cmsplugin_set.filter(language=language) content_bits = [] for base_plugin in plugins: content = get_plugin_index_data(base_plugin, request) content_bits.append(' '.join(content)) post_text = ' '.join(content_bits) else: post_text = post.safe_translation_getter('post_text') if post_text: post_text = strip_tags(post_text) self.prepared_data['post_text'] = post_text text_bits.append(post_text) return ' '.join(text_bits)
def get_absolute_url(self, lang=None): if not lang or lang not in self.get_available_languages(): lang = get_language() if not lang or lang not in self.get_available_languages(): lang = self.get_current_language() with switch_language(self, lang): category = self.categories.first() kwargs = {} if self.date_published: current_date = self.date_published else: current_date = self.date_created urlconf = get_setting('PERMALINK_URLS')[ self.app_config.url_patterns] if '<year>' in urlconf: kwargs['year'] = current_date.year if '<month>' in urlconf: kwargs['month'] = '%02d' % current_date.month if '<day>' in urlconf: kwargs['day'] = '%02d' % current_date.day if '<slug>' in urlconf: kwargs['slug'] = self.safe_translation_getter( 'slug', language_code=lang, any_language=True) # NOQA if '<category>' in urlconf: kwargs['category'] = category.safe_translation_getter( 'slug', language_code=lang, any_language=True) # NOQA return reverse('%s:post-detail' % self.app_config.namespace, kwargs=kwargs)
def handle(self, *args, **options): languages = options.get('languages') if languages is None: languages = [language[0] for language in settings.LANGUAGES] # ArticleTranslation translation_model = Article._parler_meta.root_model for article in Article.objects.published(): translations = article.translations.filter( language_code__in=languages) # build internal parler cache parler_cache = dict( (trans.language_code, trans) for trans in translations) # set internal parler cache # to avoid parler hitting db for every language article._translations_cache[translation_model] = parler_cache for translation in translations: language = translation.language_code with switch_language(article, language_code=language): translation.search_data = article.get_search_data() # make sure to only update the search_data field translation.save(update_fields=["search_data"])
def test_modifier(self): """ Tests if correct category is selected in the menu according to context (view object) """ posts = self.get_posts() pages = self.get_pages() tests = ( # view class, view kwarg, view object, category (PostDetailView, "slug", posts[0], posts[0].categories.first()), (CategoryEntriesView, "category", self.cats[2], self.cats[2]), ) for view_cls, kwarg, obj, cat in tests: request = self.get_page_request(pages[1], self.user, path=obj.get_absolute_url()) with smart_override("en"): with switch_language(obj, "en"): view_obj = view_cls() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.app_config = self.app_config_1 view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) # check if selected menu node points to cat nodes = menu_pool.get_nodes(request, namespace="BlogCategoryMenu") found = False for node in nodes: if node.selected: self.assertEqual(node.url, obj.get_absolute_url()) found = True break self.assertTrue(found)
def create_timeseries(self): self.htimeseries = HTimeseries() self.htimeseries.data = pd.DataFrame( index=[dt.datetime(2017, 11, 23, 17, 23), dt.datetime(2018, 11, 25, 1, 0)], data={"value": [1.0, 2.0], "flags": ["", ""]}, columns=["value", "flags"], ) self.station = mommy.make( models.Station, name="Komboti", geom=Point(x=21.00000, y=39.00000, srid=4326), original_srid=4326, ) self.time_zone = mommy.make(models.TimeZone, code="EET", utc_offset=120) self.variable = models.Variable() with switch_language(self.variable, "en"): self.variable.descr = "Beauty" self.variable.save() self.timeseries_group = mommy.make( models.TimeseriesGroup, gentity=self.station, time_zone=self.time_zone, precision=2, variable=self.variable, ) self.timeseries = mommy.make( models.Timeseries, type=models.Timeseries.RAW, timeseries_group=self.timeseries_group, ) self.timeseries.set_data(self.htimeseries.data)
def render(self, context, language_code=DEFAULT_LANG): """ Render this notification template with given context and language Returns a dict containing all content fields of the template. Example: {'short_message': 'foo', 'subject': 'bar', 'body': 'baz', 'html_body': '<b>foobar</b>'} """ env = SandboxedEnvironment(trim_blocks=True, lstrip_blocks=True, undefined=StrictUndefined) env.filters['reservation_time'] = reservation_time env.filters['format_datetime'] = format_datetime env.filters['format_datetime_tz'] = format_datetime_tz logger.debug('Rendering template for notification %s' % self.type) with switch_language(self, language_code): try: rendered_notification = { attr: env.from_string(getattr(self, attr)).render(context) for attr in ('short_message', 'subject', 'html_body') } if self.body: rendered_notification['body'] = env.from_string( self.body).render(context) else: # if text body is empty use html body without tags as text body rendered_notification['body'] = strip_tags( rendered_notification['html_body']) return rendered_notification except TemplateError as e: raise NotificationTemplateException(e) from e
def render(self, context, language_code=DEFAULT_LANG): """ Render this notification template with given context and language Returns a dict containing all content fields of the template. Example: {'short_message': 'foo', 'subject': 'bar', 'body': 'baz', 'html_body': '<b>foobar</b>'} """ env = SandboxedEnvironment(trim_blocks=True, lstrip_blocks=True, undefined=StrictUndefined) env.filters['reservation_time'] = reservation_time env.filters['format_datetime'] = format_datetime env.filters['format_datetime_tz'] = format_datetime_tz logger.debug('Rendering template for notification %s' % self.type) with switch_language(self, language_code): try: rendered_notification = { attr: env.from_string(getattr(self, attr)).render(context) for attr in ('short_message', 'subject', 'html_body') } if self.body: rendered_notification['body'] = env.from_string(self.body).render(context) else: # if text body is empty use html body without tags as text body rendered_notification['body'] = strip_tags(rendered_notification['html_body']) return rendered_notification except TemplateError as e: raise NotificationTemplateException(e) from e
def get_absolute_url(self, lang=None): lang = _get_language(self, lang) with switch_language(self, lang): category = self.categories.first() kwargs = {} if self.date_published: current_date = self.date_published else: current_date = self.date_created urlconf = get_setting("PERMALINK_URLS")[ self.app_config.url_patterns] if "<year>" in urlconf: kwargs["year"] = current_date.year if "<month>" in urlconf: kwargs["month"] = "%02d" % current_date.month if "<day>" in urlconf: kwargs["day"] = "%02d" % current_date.day if "<slug>" in urlconf: kwargs["slug"] = self.safe_translation_getter( "slug", language_code=lang, any_language=True) # NOQA if "<category>" in urlconf: kwargs["category"] = category.safe_translation_getter( "slug", language_code=lang, any_language=True) # NOQA return reverse("%s:post-detail" % self.app_config.namespace, kwargs=kwargs)
def render_notification_template(notification_type, context, language_code=DEFAULT_LANG): """ Render a notification template with given context Returns a dict containing all content fields of the template. Example: {'short_message': 'foo', 'subject': 'bar', 'body': 'baz'} """ try: template = NotificationTemplate.objects.get(type=notification_type) except NotificationTemplate.DoesNotExist as e: raise NotificationTemplateException(e) from e env = SandboxedEnvironment(trim_blocks=True, lstrip_blocks=True, undefined=StrictUndefined) env.filters['reservation_time'] = reservation_time env.filters['format_datetime'] = format_datetime env.filters['format_datetime_tz'] = format_datetime_tz logger.info('Rendering template for notification %s' % notification_type) with switch_language(template, language_code): try: return { attr: env.from_string(getattr(template, attr)).render(context) for attr in ('short_message', 'subject', 'body') } except TemplateError as e: raise NotificationTemplateException(e) from e
def test_instant_articles(self): self.user.first_name = 'Admin' self.user.last_name = 'User' self.user.save() posts = self.get_posts() pages = self.get_pages() posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') posts[0].categories.add(self.category_1) posts[0].author = self.user posts[0].save() add_plugin( posts[0].content, 'TextPlugin', language='en', body='<h3>Ciao</h3><p></p><p>Ciao</p>' ) with smart_override('en'): with switch_language(posts[0], 'en'): request = self.get_page_request( pages[1], self.user, path=posts[0].get_absolute_url() ) feed = FBInstantArticles() feed.namespace, feed.config = get_app_instance(request) self.assertEqual(list(feed.items()), [posts[0]]) xml = feed(request) self.assertContains(xml, '<guid>{0}</guid>'.format(posts[0].guid)) self.assertContains(xml, 'content:encoded') self.assertContains(xml, 'class="op-modified" datetime="{0}"'.format( posts[0].date_modified.strftime(FBInstantFeed.date_format) )) self.assertContains(xml, '<link rel="canonical" href="{0}"/>'.format( posts[0].get_full_url() )) # Assert text transformation self.assertContains(xml, '<h2>Ciao</h2><p>Ciao</p>') self.assertContains(xml, '<a>Admin User</a>')
def handle(self, *args, **options): if args: raise CommandError("Command doesn't accept any arguments") site = options['site'] host = options['host'] from_lang = options['from'] to_lang = options['to'] if not from_lang: raise CommandError("Provide a --from=.. language to redirect for") if not host: host = Site.objects.get_current().domain if '://' not in host: host = "http://{0}".format(host) from_name = get_language_info(from_lang)['name'] to_name = get_language_info(to_lang)['name'] with translation.override(from_lang): qs = (UrlNode.objects .parent_site(site) .non_polymorphic() .translated(to_lang) .order_by('translations___cached_url')) if not qs: raise CommandError("No URLs found for site {0} in {1}".format(site, from_name)) self.stdout.write('# Redirecting all translated {0} URLs to the {1} site\n'.format(from_name, to_name)) self.stdout.write("# Generated using {0}".format(" ".join(sys.argv))) for page in qs: from_url = page.default_url with switch_language(page, to_lang): to_url = page.get_absolute_url() if from_url == to_url: continue if from_url.endswith('/'): from_regexp = from_url.rstrip('/') from_rule = "~ ^{0}(/|$)".format(from_regexp) else: from_regexp = from_url from_rule = "= {0}".format(from_regexp) if page.plugin.urls: self.stdout.write("location {0} {{ rewrite ^{1}(.*)$ {2}{3}$1; }}\n".format( from_rule, from_regexp, host, to_url.rstrip('/') )) else: self.stdout.write("location {0} {{ return 301 {1}{2}; }}\n".format( from_rule, host, to_url )) # Final redirect for all identical URLs self.stdout.write("\n# Redirect all remaining and identical URls:\n") self.stdout.write("location / {{ rewrite ^/(.*)$ {0}/$1 permanent; }}\n".format(host))
def test_article_detail_not_translated_no_fallback(self): """ If the fallback is disabled, article is available only in the language in which is translated """ author = self.create_person() code = "{0}-".format(self.language) article = Article.objects.create( title=self.rand_str(), slug=self.rand_str(prefix=code), app_config=self.app_config, author=author, owner=author.user, publishing_date=now(), is_published=True, ) article.save() article.categories.add(self.category1) PARLER_LANGUAGES = { 1: ( {'code': 'de'}, {'code': 'fr'}, {'code': 'en'}, ), 'default': { 'hide_untranslated': True, } } LANGUAGES = add_default_language_settings(PARLER_LANGUAGES) with override_parler_settings(PARLER_LANGUAGES=LANGUAGES): # current language - it still exists article = Article.objects.get(pk=article.pk) language = settings.LANGUAGES[0][0] with switch_language(self.category1, language): url = reverse('aldryn_newsblog:article-detail', kwargs={'slug': article.slug}) response = self.client.get(url) self.assertContains(response, article.title) # non existing language - it does NOT exists language = settings.LANGUAGES[1][0] with switch_language(self.category1, language): url = reverse('aldryn_newsblog:article-detail', kwargs={'slug': article.slug}) response = self.client.get(url) self.assertEqual(response.status_code, 404)
def get_i18n_urls_for_job(self, job_opening): job_urls = [] for language, _ in settings.LANGUAGES: with switch_language(job_opening, language): job_url = job_opening.get_absolute_url() self.assertNotIn(job_url, job_urls) job_urls.append(job_url) return job_urls
def test_articles_by_category(self): """ Tests that we can find articles by their categories, in ANY of the languages they are translated to. """ LANGUAGES = add_default_language_settings(PARLER_LANGUAGES_HIDE) with override_parler_settings(PARLER_LANGUAGES=LANGUAGES): author = self.create_person() for category in (self.category1, self.category2): articles = [] code = "{0}-".format(self.language) for _ in range(11): article = Article.objects.create( title=self.rand_str(), slug=self.rand_str(prefix=code), app_config=self.app_config, author=author, owner=author.user, publishing_date=now(), is_published=True, ) # Make sure there are translations in place for the # articles. for language, _ in settings.LANGUAGES[1:]: with switch_language(article, language): code = "{0}-".format(language) article.title = self.rand_str(prefix=code) article.save() article.categories.add(category) articles.append(article) for language, _ in settings.LANGUAGES: with switch_language(category, language): url = reverse( 'aldryn_newsblog:article-list-by-category', kwargs={'category': category.slug}) response = self.client.get(url) for article in articles: if language in article.get_available_languages(): article.set_current_language(language) self.assertContains(response, article.title) else: article.set_current_language(language) self.assertNotContains(response, article.title)
def test_detail_view_same_category_and_opening_names(self): # regression for issue with two job configs (different namespace) # which have same categories names/slugs and same openings title/slugs new_config = self.create_config(namespace='another_apphook_to_test') self.create_page( title='new apphook', slug='new-apphook', namespace=new_config.namespace) default_opening = self.create_default_job_opening(translated=True) same_name_category = self.create_default_job_category( translated=True, config=new_config) same_name_opening = self.create_default_job_opening( translated=True, category=same_name_category) lead_in_text_raw = '{0} lead in for other config' for language in ('de', 'en'): # get urls default_opening_url = default_opening.get_absolute_url(language) same_name_opening_url = same_name_opening.get_absolute_url(language) with switch_language(same_name_opening, language): # change lead in to be different for other opening same_name_opening.lead_in = lead_in_text_raw.format( language) same_name_opening.save() # urls should be different because namespace is different self.assertNotEqual(default_opening_url, same_name_opening_url) # default one response_default = self.client.get(default_opening_url) self.assertEqual(response_default.status_code, 200) # same named response_other = self.client.get(same_name_opening_url) self.assertEqual(response_other.status_code, 200) # test translatable content with switch_language(default_opening, language): self.assertContains(response_default, default_opening.title) self.assertContains(response_default, default_opening.lead_in) with switch_language(same_name_opening, language): self.assertContains(response_other, same_name_opening.title) self.assertContains(response_other, same_name_opening.lead_in)
def get_absolute_urls(self): """ Return all available URLs to this page. """ result = {} for code, cached_url in self.translations.values_list('language_code', '_cached_url'): with switch_language(self, code): root = reverse('fluent-page').rstrip('/') result[code] = root + cached_url return result