1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 from babel
import localedata
22 from babel
.support
import LazyProxy
24 from mediagoblin
import mg_globals
30 AVAILABLE_LOCALES
= None
31 TRANSLATIONS_PATH
= pkg_resources
.resource_filename(
32 'mediagoblin', 'i18n')
35 def set_available_locales():
36 """Set available locales for which we have translations"""
37 global AVAILABLE_LOCALES
38 locales
=['en', 'en_US'] # these are available without translations
39 for locale
in localedata
.list():
40 if gettext
.find('mediagoblin', TRANSLATIONS_PATH
, [locale
]):
41 locales
.append(locale
)
42 AVAILABLE_LOCALES
= locales
45 def locale_to_lower_upper(locale
):
47 Take a locale, regardless of style, and format it like "en_US"
50 lang
, country
= locale
.split('-', 1)
51 return '%s_%s' % (lang
.lower(), country
.upper())
53 lang
, country
= locale
.split('_', 1)
54 return '%s_%s' % (lang
.lower(), country
.upper())
59 def locale_to_lower_lower(locale
):
61 Take a locale, regardless of style, and format it like "en_us"
64 lang
, country
= locale
.split('_', 1)
65 return '%s-%s' % (lang
.lower(), country
.lower())
70 def get_locale_from_request(request
):
72 Return most appropriate language based on prefs/request request
74 request_args
= (request
.args
, request
.form
)[request
.method
=='POST']
76 if 'lang' in request_args
:
77 # User explicitely demanded a language, normalize lower_uppercase
78 target_lang
= locale_to_lower_upper(request_args
['lang'])
80 elif 'target_lang' in request
.session
:
81 # TODO: Uh, ohh, this is never ever set anywhere?
82 target_lang
= request
.session
['target_lang']
84 # Pull the most acceptable language based on browser preferences
85 # This returns one of AVAILABLE_LOCALES which is aready case-normalized.
86 # Note: in our tests request.accept_languages is None, so we need
87 # to explicitely fallback to en here.
88 target_lang
= request
.accept_languages
.best_match(AVAILABLE_LOCALES
) \
95 def get_gettext_translation(locale
):
97 Return the gettext instance based on this locale
99 # Later on when we have plugins we may want to enable the
100 # multi-translations system they have so we can handle plugin
103 # TODO: fallback nicely on translations from pt_PT to pt if not
105 if locale
in SETUP_GETTEXTS
:
106 this_gettext
= SETUP_GETTEXTS
[locale
]
108 this_gettext
= gettext
.translation(
109 'mediagoblin', TRANSLATIONS_PATH
, [locale
], fallback
=True)
110 if localedata
.exists(locale
):
111 SETUP_GETTEXTS
[locale
] = this_gettext
115 def pass_to_ugettext(*args
, **kwargs
):
117 Pass a translation on to the appropriate ugettext method.
119 The reason we can't have a global ugettext method is because
120 mg_globals gets swapped out by the application per-request.
122 return mg_globals
.thread_scope
.translations
.ugettext(
126 def lazy_pass_to_ugettext(*args
, **kwargs
):
128 Lazily pass to ugettext.
130 This is useful if you have to define a translation on a module
131 level but you need it to not translate until the time that it's
132 used as a string. For example, in:
133 def func(self, message=_('Hello boys and girls'))
135 you would want to use the lazy version for _.
137 return LazyProxy(pass_to_ugettext
, *args
, **kwargs
)
140 def pass_to_ngettext(*args
, **kwargs
):
142 Pass a translation on to the appropriate ngettext method.
144 The reason we can't have a global ngettext method is because
145 mg_globals gets swapped out by the application per-request.
147 return mg_globals
.thread_scope
.translations
.ngettext(
151 def lazy_pass_to_ngettext(*args
, **kwargs
):
153 Lazily pass to ngettext.
155 This is useful if you have to define a translation on a module
156 level but you need it to not translate until the time that it's
159 return LazyProxy(pass_to_ngettext
, *args
, **kwargs
)
162 def fake_ugettext_passthrough(string
):
164 Fake a ugettext call for extraction's sake ;)
166 In wtforms there's a separate way to define a method to translate
167 things... so we just need to mark up the text so that it can be
168 extracted, not so that it's actually run through gettext.