aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/tools/translate.py
diff options
context:
space:
mode:
Diffstat (limited to 'mediagoblin/tools/translate.py')
-rw-r--r--mediagoblin/tools/translate.py102
1 files changed, 78 insertions, 24 deletions
diff --git a/mediagoblin/tools/translate.py b/mediagoblin/tools/translate.py
index 01cabe6a..b20e57d1 100644
--- a/mediagoblin/tools/translate.py
+++ b/mediagoblin/tools/translate.py
@@ -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
@@ -25,14 +27,40 @@ from mediagoblin import mg_globals
# Translation tools
###################
-
+AVAILABLE_LOCALES = None
TRANSLATIONS_PATH = pkg_resources.resource_filename(
'mediagoblin', 'i18n')
+def set_available_locales():
+ """Set available locales for which we have translations"""
+ global AVAILABLE_LOCALES
+ locales=['en', 'en_US'] # these are available without translations
+ for locale in localedata.list():
+ if gettext.find('mediagoblin', TRANSLATIONS_PATH, [locale]):
+ locales.append(locale)
+ AVAILABLE_LOCALES = locales
+
+
+class ReallyLazyProxy(LazyProxy):
+ """
+ Like LazyProxy, except that it doesn't cache the value ;)
+ """
+ @property
+ def value(self):
+ return self._func(*self._args, **self._kwargs)
+
+ def __repr__(self):
+ return "<%s for %s(%r, %r)>" % (
+ self.__class__.__name__,
+ self._func,
+ self._args,
+ self._kwargs)
+
+
def locale_to_lower_upper(locale):
"""
- Take a locale, regardless of style, and format it like "en-US"
+ Take a locale, regardless of style, and format it like "en_US"
"""
if '-' in locale:
lang, country = locale.split('-', 1)
@@ -57,28 +85,32 @@ def locale_to_lower_lower(locale):
def get_locale_from_request(request):
"""
- Figure out what target language is most appropriate based on the
- request
+ Return most appropriate language based on prefs/request request
"""
- request_form = request.GET or request.form
+ request_args = (request.args, request.form)[request.method=='POST']
- if request_form.has_key('lang'):
- return locale_to_lower_upper(request_form['lang'])
+ if 'lang' in request_args:
+ # User explicitely demanded a language, normalize lower_uppercase
+ target_lang = locale_to_lower_upper(request_args['lang'])
- if 'target_lang' in request.session:
+ elif 'target_lang' in request.session:
+ # TODO: Uh, ohh, this is never ever set anywhere?
target_lang = request.session['target_lang']
- # Pull the first acceptable language or English
else:
- # TODO: Internationalization broken
- target_lang = 'en'
+ # Pull the most acceptable language based on browser preferences
+ # This returns one of AVAILABLE_LOCALES which is aready case-normalized.
+ # Note: in our tests request.accept_languages is None, so we need
+ # to explicitely fallback to en here.
+ target_lang = request.accept_languages.best_match(AVAILABLE_LOCALES) \
+ or "en_US"
- return locale_to_lower_upper(target_lang)
+ return 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
@@ -91,15 +123,14 @@ 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
-# Force en to be setup before anything else so that
-# mg_globals.translations is never None
-setup_gettext('en')
+def set_thread_locale(locale):
+ """Set the current translation for this thread"""
+ mg_globals.thread_scope.translations = get_gettext_translation(locale)
def pass_to_ugettext(*args, **kwargs):
@@ -112,6 +143,16 @@ def pass_to_ugettext(*args, **kwargs):
return mg_globals.thread_scope.translations.ugettext(
*args, **kwargs)
+def pass_to_ungettext(*args, **kwargs):
+ """
+ Pass a translation on to the appropriate ungettext method.
+
+ The reason we can't have a global ugettext method is because
+ mg_globals gets swapped out by the application per-request.
+ """
+ return mg_globals.thread_scope.translations.ungettext(
+ *args, **kwargs)
+
def lazy_pass_to_ugettext(*args, **kwargs):
"""
@@ -119,9 +160,12 @@ def lazy_pass_to_ugettext(*args, **kwargs):
This is useful if you have to define a translation on a module
level but you need it to not translate until the time that it's
- used as a string.
+ used as a string. For example, in:
+ def func(self, message=_('Hello boys and girls'))
+
+ you would want to use the lazy version for _.
"""
- return LazyProxy(pass_to_ugettext, *args, **kwargs)
+ return ReallyLazyProxy(pass_to_ugettext, *args, **kwargs)
def pass_to_ngettext(*args, **kwargs):
@@ -143,7 +187,17 @@ def lazy_pass_to_ngettext(*args, **kwargs):
level but you need it to not translate until the time that it's
used as a string.
"""
- return LazyProxy(pass_to_ngettext, *args, **kwargs)
+ return ReallyLazyProxy(pass_to_ngettext, *args, **kwargs)
+
+def lazy_pass_to_ungettext(*args, **kwargs):
+ """
+ Lazily pass to ungettext.
+
+ This is useful if you have to define a translation on a module
+ level but you need it to not translate until the time that it's
+ used as a string.
+ """
+ return ReallyLazyProxy(pass_to_ungettext, *args, **kwargs)
def fake_ugettext_passthrough(string):