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 | |
6ef75af5 SS |
19 | |
20 | ||
21 | from babel import localedata | |
ae3bc7fa AW |
22 | from babel.support import LazyProxy |
23 | ||
24 | from mediagoblin import mg_globals | |
25 | ||
26 | ################### | |
27 | # Translation tools | |
28 | ################### | |
29 | ||
826919c9 | 30 | AVAILABLE_LOCALES = None |
ae3bc7fa AW |
31 | TRANSLATIONS_PATH = pkg_resources.resource_filename( |
32 | 'mediagoblin', 'i18n') | |
33 | ||
34 | ||
826919c9 SS |
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 | |
6ef75af5 SS |
39 | for locale in localedata.list(): |
40 | if gettext.find('mediagoblin', TRANSLATIONS_PATH, [locale]): | |
41 | locales.append(locale) | |
826919c9 | 42 | AVAILABLE_LOCALES = locales |
6ef75af5 SS |
43 | |
44 | ||
ae3bc7fa AW |
45 | def locale_to_lower_upper(locale): |
46 | """ | |
7b9f9d1e | 47 | Take a locale, regardless of style, and format it like "en_US" |
ae3bc7fa AW |
48 | """ |
49 | if '-' in locale: | |
50 | lang, country = locale.split('-', 1) | |
51 | return '%s_%s' % (lang.lower(), country.upper()) | |
52 | elif '_' in locale: | |
53 | lang, country = locale.split('_', 1) | |
54 | return '%s_%s' % (lang.lower(), country.upper()) | |
55 | else: | |
56 | return locale.lower() | |
57 | ||
58 | ||
59 | def locale_to_lower_lower(locale): | |
60 | """ | |
9d3e56d5 | 61 | Take a locale, regardless of style, and format it like "en_us" |
ae3bc7fa AW |
62 | """ |
63 | if '_' in locale: | |
64 | lang, country = locale.split('_', 1) | |
65 | return '%s-%s' % (lang.lower(), country.lower()) | |
66 | else: | |
67 | return locale.lower() | |
68 | ||
69 | ||
70 | def get_locale_from_request(request): | |
71 | """ | |
72 | Figure out what target language is most appropriate based on the | |
73 | request | |
74 | """ | |
826919c9 | 75 | global AVAILABLE_LOCALES |
7b9f9d1e | 76 | request_form = request.args or request.form |
ae3bc7fa AW |
77 | |
78 | if request_form.has_key('lang'): | |
7b9f9d1e SS |
79 | # User explicitely demanded a language |
80 | target_lang = request_form['lang'] | |
ae3bc7fa | 81 | |
7b9f9d1e SS |
82 | elif 'target_lang' in request.session: |
83 | # TODO: Uh, ohh, this is never ever set anywhere? | |
ae3bc7fa | 84 | target_lang = request.session['target_lang'] |
ae3bc7fa | 85 | else: |
7b9f9d1e SS |
86 | # Pull the first acceptable language or English |
87 | # This picks your favorite browser lingo, falling back to 'en' | |
88 | ||
89 | # TODO: We need a list of available locales, and match with the list | |
90 | # of accepted locales, and serve the best available locale rather than | |
91 | # the most preferred, or fall back to 'en' immediately. | |
826919c9 | 92 | target_lang = request.accept_languages.best_match(AVAILABLE_LOCALES) |
e4e7fbee CAW |
93 | |
94 | return locale_to_lower_upper(target_lang) | |
ae3bc7fa AW |
95 | |
96 | SETUP_GETTEXTS = {} | |
97 | ||
6ef75af5 | 98 | def get_gettext_translation(locale): |
ae3bc7fa | 99 | """ |
6ef75af5 | 100 | Return the gettext instance based on this locale |
ae3bc7fa AW |
101 | """ |
102 | # Later on when we have plugins we may want to enable the | |
103 | # multi-translations system they have so we can handle plugin | |
104 | # translations too | |
105 | ||
106 | # TODO: fallback nicely on translations from pt_PT to pt if not | |
107 | # available, etc. | |
c80982c7 | 108 | if locale in SETUP_GETTEXTS: |
ae3bc7fa AW |
109 | this_gettext = SETUP_GETTEXTS[locale] |
110 | else: | |
111 | this_gettext = gettext.translation( | |
112 | 'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True) | |
6ef75af5 | 113 | if localedata.exists(locale): |
ae3bc7fa | 114 | SETUP_GETTEXTS[locale] = this_gettext |
6ef75af5 | 115 | return this_gettext |
ae3bc7fa AW |
116 | |
117 | ||
ae3bc7fa AW |
118 | def pass_to_ugettext(*args, **kwargs): |
119 | """ | |
120 | Pass a translation on to the appropriate ugettext method. | |
121 | ||
122 | The reason we can't have a global ugettext method is because | |
123 | mg_globals gets swapped out by the application per-request. | |
124 | """ | |
c80982c7 | 125 | return mg_globals.thread_scope.translations.ugettext( |
ae3bc7fa AW |
126 | *args, **kwargs) |
127 | ||
128 | ||
129 | def lazy_pass_to_ugettext(*args, **kwargs): | |
130 | """ | |
131 | Lazily pass to ugettext. | |
132 | ||
133 | This is useful if you have to define a translation on a module | |
134 | level but you need it to not translate until the time that it's | |
135 | used as a string. | |
136 | """ | |
137 | return LazyProxy(pass_to_ugettext, *args, **kwargs) | |
138 | ||
139 | ||
140 | def pass_to_ngettext(*args, **kwargs): | |
141 | """ | |
142 | Pass a translation on to the appropriate ngettext method. | |
143 | ||
144 | The reason we can't have a global ngettext method is because | |
145 | mg_globals gets swapped out by the application per-request. | |
146 | """ | |
c80982c7 | 147 | return mg_globals.thread_scope.translations.ngettext( |
ae3bc7fa AW |
148 | *args, **kwargs) |
149 | ||
150 | ||
151 | def lazy_pass_to_ngettext(*args, **kwargs): | |
152 | """ | |
153 | Lazily pass to ngettext. | |
154 | ||
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 | |
157 | used as a string. | |
158 | """ | |
159 | return LazyProxy(pass_to_ngettext, *args, **kwargs) | |
160 | ||
161 | ||
162 | def fake_ugettext_passthrough(string): | |
163 | """ | |
164 | Fake a ugettext call for extraction's sake ;) | |
165 | ||
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. | |
169 | """ | |
170 | return string |