Fix day filter
[cds-indico.git] / indico / util / i18n_test.py
blobcd53cb5df11e0d70961880886070f0ffccd0c97c
1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 import os
18 import pytest
19 from babel.messages import Catalog
20 from babel.messages.mofile import write_mo
21 from babel.support import Translations
22 from flask import session, request, has_request_context
23 from flask_babelex import get_domain
24 from speaklater import _LazyString
25 from werkzeug.http import LanguageAccept
27 from indico.util.i18n import _, ngettext, ungettext, gettext_context, session_language, babel, make_bound_gettext
28 from indico.core.plugins import IndicoPlugin, plugin_engine
31 DICTIONARIES = {
32 'fr_FR': {
33 'This is not a string': u"Ceci n'est pas une cha\u00cene"
36 'fr_MP': {
37 'Fetch the cow': u'Fetchez la vache',
38 'The wheels': u'Les wheels',
39 ('{} cow', 0): u'{} vache',
40 ('{} cow', 1): u'{} vaches',
43 'en_PI': {
44 'I need a drink.': u"I be needin' a bottle of rhum!"
49 class MockTranslations(Translations):
50 """
51 Mock `Translations` class - returns a mock dictionary
52 based on the selected locale
53 """
55 def __init__(self):
56 super(MockTranslations, self).__init__()
57 self._catalog = DICTIONARIES[babel.locale_selector_func()]
60 class MockPlugin(IndicoPlugin):
61 def init(self):
62 pass
65 @pytest.fixture
66 def mock_translations(monkeypatch, request_context):
67 domain = get_domain()
68 locales = {'fr_FR': 'French',
69 'en_GB': 'English'}
70 monkeypatch.setattr('indico.util.i18n.get_all_locales', lambda: locales)
71 monkeypatch.setattr(domain, 'get_translations', MockTranslations)
74 @pytest.mark.usefixtures('mock_translations')
75 def test_straight_translation():
76 session.lang = 'fr_MP' # 'Monty Python' French
78 a = _(u'Fetch the cow')
79 b = _(u'The wheels')
81 assert isinstance(a, unicode)
82 assert isinstance(b, unicode)
85 @pytest.mark.usefixtures('mock_translations')
86 def test_lazy_translation():
87 a = _(u'Fetch the cow')
88 b = _(u'The wheels')
90 assert isinstance(a, _LazyString)
91 assert isinstance(b, _LazyString)
93 session.lang = 'fr_MP'
95 assert unicode(a) == u'Fetchez la vache'
96 assert unicode(b) == u'Les wheels'
99 @pytest.mark.usefixtures('mock_translations')
100 def test_ngettext():
101 session.lang = 'fr_MP'
103 assert ngettext(u'{} cow', u'{} cows', 1).format(1) == u'1 vache'
104 assert ungettext(u'{} cow', u'{} cows', 42).format(42) == u'42 vaches'
107 @pytest.mark.usefixtures('mock_translations')
108 def test_translate_bytes():
109 session.lang = 'fr_MP'
111 assert _(u'Fetch the cow') == u'Fetchez la vache'
112 assert _('The wheels') == 'Les wheels'
115 @pytest.mark.usefixtures('mock_translations')
116 def test_context_manager():
117 session.lang = 'fr_MP'
118 with session_language('en_PI'):
119 assert session.lang == 'en_PI'
120 assert _(u'I need a drink.') == u"I be needin' a bottle of rhum!"
122 assert session.lang == 'fr_MP'
125 def test_set_best_lang_no_request():
126 assert not has_request_context()
127 assert babel.locale_selector_func() == 'en_GB'
130 @pytest.mark.usefixtures('mock_translations')
131 def test_set_best_lang_request():
132 with session_language('en_PI'):
133 assert babel.locale_selector_func() == 'en_PI'
136 @pytest.mark.usefixtures('mock_translations')
137 def test_set_best_lang_no_session_lang():
138 request.accept_languages = LanguageAccept([('en-PI', 1), ('fr_FR', 0.7)])
139 assert babel.locale_selector_func() == 'fr_FR'
141 request.accept_languages = LanguageAccept([('fr-FR', 1)])
142 assert babel.locale_selector_func() == 'fr_FR'
145 @pytest.mark.usefixtures('mock_translations')
146 def test_translation_plugins(app, tmpdir):
147 session.lang = 'fr_FR'
148 plugin = MockPlugin(plugin_engine, app)
149 app.extensions['pluginengine'].plugins['dummy'] = plugin
150 plugin.root_path = tmpdir.strpath
151 french_core_str = DICTIONARIES['fr_FR']['This is not a string']
152 french_plugin_str = "This is not le french string"
154 trans_dir = os.path.join(plugin.root_path, 'translations', 'fr_FR', 'LC_MESSAGES')
155 os.makedirs(trans_dir)
157 # Create proper *.mo file for plugin translation
158 with open(os.path.join(trans_dir, 'messages.mo'), 'wb') as f:
159 catalog = Catalog(locale='fr_FR', domain='plugin')
160 catalog.add("This is not a string", "This is not le french string")
161 write_mo(f, catalog)
163 gettext_plugin = make_bound_gettext('dummy')
165 assert _(u'This is not a string') == french_core_str
166 assert gettext_context(u"This is not a string") == french_core_str
167 assert gettext_plugin(u"This is not a string") == french_plugin_str
169 with plugin.plugin_context():
170 assert _(u'This is not a string') == french_core_str
171 assert gettext_context(u"This is not a string") == french_plugin_str
172 assert gettext_plugin(u"This is not a string") == french_plugin_str