Honor user's browser language (#558)
authorSebastian Spaeth <Sebastian@SSpaeth.de>
Sat, 1 Dec 2012 23:29:30 +0000 (00:29 +0100)
committerSebastian Spaeth <Sebastian@SSpaeth.de>
Sat, 1 Dec 2012 23:29:30 +0000 (00:29 +0100)
Previously we would attempt to satisfy the user's first language
preference, immediately falling back to english if that was not
possible. Now, we will get the best match of the user's preferred
languages.

This requires storing the available locales on app startup, so we
have mg_globals.available_locales ready to compare them against the
list of preferred user languages.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
mediagoblin/app.py
mediagoblin/init/__init__.py
mediagoblin/mg_globals.py
mediagoblin/tools/template.py
mediagoblin/tools/translate.py

index de421aca6241f2cb253b53ae9d69fffbf6af93af..876ded4ef2f35d3a3d5b028f3321923ce9cbc75c 100644 (file)
@@ -31,7 +31,7 @@ from mediagoblin.mg_globals import setup_globals
 from mediagoblin.init.celery import setup_celery_from_config
 from mediagoblin.init.plugins import setup_plugins
 from mediagoblin.init import (get_jinja_loader, get_staticdirector,
-    setup_global_and_app_config, setup_workbench, setup_database,
+    setup_global_and_app_config, setup_locales, setup_workbench, setup_database,
     setup_storage, setup_beaker_cache)
 from mediagoblin.tools.pluginapi import PluginManager
 
@@ -68,6 +68,9 @@ class MediaGoblinApp(object):
         # Setup other connections / useful objects
         ##########################################
 
+        # load all available locales
+        setup_locales()
+
         # Set up plugins -- need to do this early so that plugins can
         # affect startup.
         _log.info("Setting up plugins.")
index 9b0025c9fbd906cc6775127ebd2352185a71e47a..88af377e8b74b03f718c28d96d446dfe1c200888 100644 (file)
@@ -19,6 +19,7 @@ from beaker.util import parse_cache_config_options
 import jinja2
 
 from mediagoblin.tools import staticdirect
+from mediagoblin.tools.translate import get_available_locales
 from mediagoblin.init.config import (
     read_mediagoblin_config, generate_validation_report)
 from mediagoblin import mg_globals
@@ -37,6 +38,11 @@ class ImproperlyConfigured(Error):
     pass
 
 
+def setup_locales():
+    """Checks which language translations are available and sets them"""
+    setup_globals(available_locales=get_available_locales())
+
+
 def setup_global_and_app_config(config_path):
     global_config, validation_result = read_mediagoblin_config(config_path)
     app_config = global_config['mediagoblin']
index 356a944d981cfa86efa941207ec528d2cb0b7d1c..646fbdbd58af96210dfd076965575dc3d25c8ff9 100644 (file)
@@ -45,6 +45,8 @@ workbench_manager = None
 # A thread-local scope
 thread_scope = threading.local()
 
+# a list of translated locales
+available_locales = None
 # gettext (this will be populated on demand with gettext.Translations)
 thread_scope.translations = None
 
index 158d532111f452a96ac293b057521b865db9177a..6f603bab6ecf9ffbd66724bb7d439b0d6d878693 100644 (file)
@@ -20,7 +20,7 @@ from babel.localedata import exists
 from mediagoblin import mg_globals
 from mediagoblin import messages
 from mediagoblin.tools import common
-from mediagoblin.tools.translate import setup_gettext
+from mediagoblin.tools.translate import get_gettext_translation
 from mediagoblin.meddleware.csrf import render_csrf_form_token
 
 
@@ -34,7 +34,7 @@ def get_jinja_env(template_loader, locale):
     (In the future we may have another system for providing theming;
     for now this is good enough.)
     """
-    setup_gettext(locale)
+    mg_globals.thread_scope.translations = get_gettext_translation(locale)
 
     # If we have a jinja environment set up with this locale, just
     # return that one.
index ce6704514ad91d3b0b3af674775a0f9988e13a26..b6b7a5274da6debe865b06897863d6d3b5d3d614 100644 (file)
@@ -16,7 +16,9 @@
 
 import gettext
 import pkg_resources
-from babel.localedata import exists
+
+
+from babel import localedata
 from babel.support import LazyProxy
 
 from mediagoblin import mg_globals
@@ -30,6 +32,15 @@ TRANSLATIONS_PATH = pkg_resources.resource_filename(
     'mediagoblin', 'i18n')
 
 
+def get_available_locales():
+    """Return a list of locales for which we have translations"""
+    locales=[]
+    for locale in localedata.list():
+        if gettext.find('mediagoblin', TRANSLATIONS_PATH, [locale]):
+            locales.append(locale)
+    return locales
+
+
 def locale_to_lower_upper(locale):
     """
     Take a locale, regardless of style, and format it like "en_US"
@@ -76,15 +87,15 @@ def get_locale_from_request(request):
         # TODO: We need a list of available locales, and match with the list
         # of accepted locales, and serve the best available locale rather than
         # the most preferred, or fall back to 'en' immediately.
-        target_lang = request.accept_languages.best
-
-    return locale_to_lower_upper(target_lang)
+        target_lang = request.accept_languages.best_match(
+            mg_globals.available_locales)
+        return locale_to_lower_upper(target_lang)
 
 SETUP_GETTEXTS = {}
 
-def setup_gettext(locale):
+def get_gettext_translation(locale):
     """
-    Setup the gettext instance based on this locale
+    Return the gettext instance based on this locale
     """
     # Later on when we have plugins we may want to enable the
     # multi-translations system they have so we can handle plugin
@@ -97,10 +108,9 @@ def setup_gettext(locale):
     else:
         this_gettext = gettext.translation(
             'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
-        if exists(locale):
+        if localedata.exists(locale):
             SETUP_GETTEXTS[locale] = this_gettext
-
-    mg_globals.thread_scope.translations = this_gettext
+    return this_gettext
 
 
 def pass_to_ugettext(*args, **kwargs):