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/>.
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
33 'This is not a string': u
"Ceci n'est pas une cha\u00cene"
37 'Fetch the cow': u
'Fetchez la vache',
38 'The wheels': u
'Les wheels',
39 ('{} cow', 0): u
'{} vache',
40 ('{} cow', 1): u
'{} vaches',
44 'I need a drink.': u
"I be needin' a bottle of rhum!"
49 class MockTranslations(Translations
):
51 Mock `Translations` class - returns a mock dictionary
52 based on the selected locale
56 super(MockTranslations
, self
).__init
__()
57 self
._catalog
= DICTIONARIES
[babel
.locale_selector_func()]
60 class MockPlugin(IndicoPlugin
):
66 def mock_translations(monkeypatch
, request_context
):
68 locales
= {'fr_FR': 'French',
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')
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')
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')
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")
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