Commits

Christoph Zwerschke committed 5508bd9

Sanitize language codes from browser (fixes #2406 and #2512).

Comments (0)

Files changed (2)

tests/test_i18n.py

+# -*- coding: utf-8 -*-
+
+from tg import i18n
+
+
+def test_sanitize_language_code():
+    """Check that slightly malformed language codes can be corrected."""
+    for lang in 'pt', 'PT':
+        assert i18n.sanitize_language_code(lang) == 'pt'
+    for lang in 'pt-br', 'pt_br', 'pt_BR':
+        assert i18n.sanitize_language_code(lang) == 'pt_BR'
+    for lang in 'foo', 'bar', 'foo-bar':
+        assert i18n.sanitize_language_code(lang) == lang
 import logging
 
+from gettext import translation
+
+from babel import parse_locale
+
 import formencode
+
 import pylons
 import pylons.i18n
 from pylons.i18n import add_fallback, LanguageError, get_lang
 from pylons.configuration import config
 from pylons import session
-from gettext import translation
+
 
 log = logging.getLogger(__name__)
 
+
+def sanitize_language_code(lang):
+    """Sanitize the language code if the spelling is slightly wrong.
+
+    For instance, 'pt-br' and 'pt_br' should be interpreted as 'pt_BR'.
+
+    """
+    try:
+        lang = '_'.join(filter(None, parse_locale(lang)[:2]))
+    except ValueError:
+        if '-' in lang:
+            try:
+                lang = '_'.join(filter(None, parse_locale(lang, sep='-')[:2]))
+            except ValueError:
+                pass
+    return lang
+
+
 def setup_i18n():
     """Set languages from the request header and the session.
 
 
     Automatically called by tg controllers to setup i18n.
     Should only be manually called if you override controllers function.
+
     """
     if pylons.session:
         # If session is available, we try to see if there are languages set
             languages = []
     else:
         languages = []
-    languages.extend(pylons.request.accept_language.best_matches())
+    languages.extend(map(sanitize_language_code,
+        pylons.request.accept_language.best_matches()))
     set_temporary_lang(languages)
 
 
 
     languages should be a string or a list of strings.
     First lang will be used as main lang, others as fallbacks.
+
     """
     # the logging to the screen was removed because
     # the printing to the screen for every problem causes serious slow down.
-    
+
     try:
         pylons.i18n.set_lang(languages)
     except LanguageError:
 
     languages should be a string or a list of strings.
     First lang will be used as main lang, others as fallbacks.
+
     """
     set_temporary_lang(languages)
 
         session[config.get('lang_session_key', 'tg_lang')] = languages
         session.save()
 
+
 _localdir = formencode.api.get_localedir()
 
 def set_formencode_translation(languages):
     """Set request specific translation of FormEncode."""
     try:
-        formencode_translation = translation('FormEncode',languages=languages, localedir=_localdir)
+        formencode_translation = translation(
+            'FormEncode',languages=languages, localedir=_localdir)
     except IOError, error:
         raise LanguageError('IOError: %s' % error)
     pylons.tmpl_context.formencode_translation = formencode_translation
 
 
-
 __all__ = [
     "setup_i18n", "set_lang", "get_lang", "add_fallback", "set_temporary_lang"
 ]