Commit | Line | Data |
---|---|---|
ae3bc7fa | 1 | # GNU MediaGoblin -- federated, autonomous media hosting |
cf29e8a8 | 2 | # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. |
ae3bc7fa AW |
3 | # |
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. | |
8 | # | |
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. | |
13 | # | |
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/>. | |
16 | ||
17 | import gettext | |
18 | import pkg_resources | |
19 | from babel.localedata import exists | |
20 | from babel.support import LazyProxy | |
21 | ||
22 | from mediagoblin import mg_globals | |
23 | ||
24 | ################### | |
25 | # Translation tools | |
26 | ################### | |
27 | ||
28 | ||
29 | TRANSLATIONS_PATH = pkg_resources.resource_filename( | |
30 | 'mediagoblin', 'i18n') | |
31 | ||
32 | ||
33 | def locale_to_lower_upper(locale): | |
34 | """ | |
35 | Take a locale, regardless of style, and format it like "en-us" | |
36 | """ | |
37 | if '-' in locale: | |
38 | lang, country = locale.split('-', 1) | |
39 | return '%s_%s' % (lang.lower(), country.upper()) | |
40 | elif '_' in locale: | |
41 | lang, country = locale.split('_', 1) | |
42 | return '%s_%s' % (lang.lower(), country.upper()) | |
43 | else: | |
44 | return locale.lower() | |
45 | ||
46 | ||
47 | def locale_to_lower_lower(locale): | |
48 | """ | |
49 | Take a locale, regardless of style, and format it like "en_US" | |
50 | """ | |
51 | if '_' in locale: | |
52 | lang, country = locale.split('_', 1) | |
53 | return '%s-%s' % (lang.lower(), country.lower()) | |
54 | else: | |
55 | return locale.lower() | |
56 | ||
57 | ||
58 | def get_locale_from_request(request): | |
59 | """ | |
60 | Figure out what target language is most appropriate based on the | |
61 | request | |
62 | """ | |
63 | request_form = request.GET or request.POST | |
64 | ||
65 | if request_form.has_key('lang'): | |
66 | return locale_to_lower_upper(request_form['lang']) | |
67 | ||
ae3bc7fa AW |
68 | # Your routing can explicitly specify a target language |
69 | matchdict = request.matchdict or {} | |
70 | ||
71 | if matchdict.has_key('locale'): | |
72 | target_lang = matchdict['locale'] | |
73 | elif request.session.has_key('target_lang'): | |
74 | target_lang = request.session['target_lang'] | |
ed594264 | 75 | # Pull the first acceptable language or English |
ae3bc7fa | 76 | else: |
47150919 CAW |
77 | # WebOb recently changed how it handles determining best language. |
78 | # Here's a compromise commit that handles either/or... | |
79 | if hasattr(request.accept_language, "best_matches"): | |
80 | accept_lang_matches = request.accept_language.best_matches() | |
81 | if accept_lang_matches: | |
82 | target_lang = accept_lang_matches[0] | |
83 | else: | |
84 | target_lang = 'en' | |
85 | else: | |
86 | target_lang = request.accept.best_match( | |
87 | request.accept_language, 'en') | |
ae3bc7fa AW |
88 | |
89 | return locale_to_lower_upper(target_lang) | |
90 | ||
91 | SETUP_GETTEXTS = {} | |
92 | ||
93 | def setup_gettext(locale): | |
94 | """ | |
95 | Setup the gettext instance based on this locale | |
96 | """ | |
97 | # Later on when we have plugins we may want to enable the | |
98 | # multi-translations system they have so we can handle plugin | |
99 | # translations too | |
100 | ||
101 | # TODO: fallback nicely on translations from pt_PT to pt if not | |
102 | # available, etc. | |
103 | if SETUP_GETTEXTS.has_key(locale): | |
104 | this_gettext = SETUP_GETTEXTS[locale] | |
105 | else: | |
106 | this_gettext = gettext.translation( | |
107 | 'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True) | |
108 | if exists(locale): | |
109 | SETUP_GETTEXTS[locale] = this_gettext | |
110 | ||
111 | mg_globals.setup_globals( | |
112 | translations=this_gettext) | |
113 | ||
114 | ||
115 | # Force en to be setup before anything else so that | |
116 | # mg_globals.translations is never None | |
117 | setup_gettext('en') | |
118 | ||
119 | ||
120 | def pass_to_ugettext(*args, **kwargs): | |
121 | """ | |
122 | Pass a translation on to the appropriate ugettext method. | |
123 | ||
124 | The reason we can't have a global ugettext method is because | |
125 | mg_globals gets swapped out by the application per-request. | |
126 | """ | |
127 | return mg_globals.translations.ugettext( | |
128 | *args, **kwargs) | |
129 | ||
130 | ||
131 | def lazy_pass_to_ugettext(*args, **kwargs): | |
132 | """ | |
133 | Lazily pass to ugettext. | |
134 | ||
135 | This is useful if you have to define a translation on a module | |
136 | level but you need it to not translate until the time that it's | |
137 | used as a string. | |
138 | """ | |
139 | return LazyProxy(pass_to_ugettext, *args, **kwargs) | |
140 | ||
141 | ||
142 | def pass_to_ngettext(*args, **kwargs): | |
143 | """ | |
144 | Pass a translation on to the appropriate ngettext method. | |
145 | ||
146 | The reason we can't have a global ngettext method is because | |
147 | mg_globals gets swapped out by the application per-request. | |
148 | """ | |
149 | return mg_globals.translations.ngettext( | |
150 | *args, **kwargs) | |
151 | ||
152 | ||
153 | def lazy_pass_to_ngettext(*args, **kwargs): | |
154 | """ | |
155 | Lazily pass to ngettext. | |
156 | ||
157 | This is useful if you have to define a translation on a module | |
158 | level but you need it to not translate until the time that it's | |
159 | used as a string. | |
160 | """ | |
161 | return LazyProxy(pass_to_ngettext, *args, **kwargs) | |
162 | ||
163 | ||
164 | def fake_ugettext_passthrough(string): | |
165 | """ | |
166 | Fake a ugettext call for extraction's sake ;) | |
167 | ||
168 | In wtforms there's a separate way to define a method to translate | |
169 | things... so we just need to mark up the text so that it can be | |
170 | extracted, not so that it's actually run through gettext. | |
171 | """ | |
172 | return string |