From 31323859c7caa03b1ccac282ffb35f4e6823c004 Mon Sep 17 00:00:00 2001 From: Brad Pokorny Date: Mon, 26 Aug 2013 18:07:25 +0000 Subject: [PATCH] Use system locale when Accept-Language header is not provided Remove en_US as the default language when no header is provided, and use None instead. Upon translation None will be defaulted to system as it was before the translation changes. Fixes bug 1214476 Change-Id: Ia18ae76f9dc3c93c7d14203af6f65b916500927e --- ceilometer/api/middleware.py | 19 +++++++++++++++---- tests/api/v2/test_app.py | 31 +++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/ceilometer/api/middleware.py b/ceilometer/api/middleware.py index 202f6c7c9..ad35b1e82 100644 --- a/ceilometer/api/middleware.py +++ b/ceilometer/api/middleware.py @@ -40,6 +40,20 @@ LOG = log.getLogger(__name__) class ParsableErrorMiddleware(object): """Replace error body with something the client can parse. """ + + @staticmethod + def best_match_language(accept_language): + """Determines best available locale from the Accept-Language + header. + + :returns: the best language match or None if the 'Accept-Language' + header was not available in the request. + """ + if not accept_language: + return None + all_languages = gettextutils.get_available_languages('ceilometer') + return accept_language.best_match(all_languages) + def __init__(self, app): self.app = app @@ -82,10 +96,7 @@ class ParsableErrorMiddleware(object): if isinstance(hook, hooks.TranslationHook): error = hook.local_error.translatable_error break - user_locale = req.accept_language.best_match( - gettextutils.get_available_languages('ceilometer'), - default_match='en_US') - + user_locale = self.best_match_language(req.accept_language) if (req.accept.best_match(['application/json', 'application/xml']) == 'application/xml'): try: diff --git a/tests/api/v2/test_app.py b/tests/api/v2/test_app.py index ae1031b0f..d829d4775 100644 --- a/tests/api/v2/test_app.py +++ b/tests/api/v2/test_app.py @@ -70,10 +70,14 @@ class TestApiMiddleware(FunctionalTest): # This doesn't really matter database_connection = tests_db.MongoDBFakeConnectionUrl() - translated_error = 'Translated error' + no_lang_translated_error = 'No lang translated error' + en_US_translated_error = 'en-US translated error' def _fake_get_localized_message(self, message, user_locale): - return self.translated_error + if user_locale is None: + return self.no_lang_translated_error + else: + return self.en_US_translated_error def test_json_parsable_error_middleware_404(self): response = self.get_json('/invalid_path', @@ -129,7 +133,7 @@ class TestApiMiddleware(FunctionalTest): self.assertEqual(response.content_type, "application/json") self.assertTrue(response.json['error_message']) fault = json.loads(response.json['error_message']) - self.assertEqual(fault['faultstring'], self.translated_error) + self.assertEqual(fault['faultstring'], self.no_lang_translated_error) def test_xml_parsable_error_middleware_404(self): response = self.get_json('/invalid_path', @@ -165,4 +169,23 @@ class TestApiMiddleware(FunctionalTest): self.assertEqual(response.xml.tag, 'error_message') fault = response.xml.findall('./error/faultstring') for fault_string in fault: - self.assertEqual(fault_string.text, self.translated_error) + self.assertEqual(fault_string.text, self.no_lang_translated_error) + + def test_best_match_language(self): + # Ensure that we are actually invoking language negotiation + self.stubs.Set(gettextutils, 'get_localized_message', + self._fake_get_localized_message) + + response = self.get_json('/alarms/-', + expect_errors=True, + headers={"Accept": + "application/xml,*/*", + "Accept-Language": + "en-US"} + ) + self.assertEqual(response.status_int, 400) + self.assertEqual(response.content_type, "application/xml") + self.assertEqual(response.xml.tag, 'error_message') + fault = response.xml.findall('./error/faultstring') + for fault_string in fault: + self.assertEqual(fault_string.text, self.en_US_translated_error)