|
1 import os |
|
2 import gettext as gettext_module |
|
3 |
1 from django import http |
4 from django import http |
2 from django.conf import settings |
5 from django.conf import settings |
3 from django.utils import importlib |
6 from django.utils import importlib |
4 from django.utils.translation import check_for_language, activate, to_locale, get_language |
7 from django.utils.translation import check_for_language, activate, to_locale, get_language |
5 from django.utils.text import javascript_quote |
8 from django.utils.text import javascript_quote |
6 import os |
9 from django.utils.encoding import smart_unicode |
7 import gettext as gettext_module |
10 from django.utils.formats import get_format_modules |
8 |
11 |
9 def set_language(request): |
12 def set_language(request): |
10 """ |
13 """ |
11 Redirect to a given url while setting the chosen language in the |
14 Redirect to a given url while setting the chosen language in the |
12 session or cookie. The url and the language code need to be |
15 session or cookie. The url and the language code need to be |
30 request.session['django_language'] = lang_code |
33 request.session['django_language'] = lang_code |
31 else: |
34 else: |
32 response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code) |
35 response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code) |
33 return response |
36 return response |
34 |
37 |
|
38 def get_formats(): |
|
39 """ |
|
40 Returns all formats strings required for i18n to work |
|
41 """ |
|
42 FORMAT_SETTINGS = ( |
|
43 'DATE_FORMAT', 'DATETIME_FORMAT', 'TIME_FORMAT', |
|
44 'YEAR_MONTH_FORMAT', 'MONTH_DAY_FORMAT', 'SHORT_DATE_FORMAT', |
|
45 'SHORT_DATETIME_FORMAT', 'FIRST_DAY_OF_WEEK', 'DECIMAL_SEPARATOR', |
|
46 'THOUSAND_SEPARATOR', 'NUMBER_GROUPING', |
|
47 'DATE_INPUT_FORMATS', 'TIME_INPUT_FORMATS', 'DATETIME_INPUT_FORMATS' |
|
48 ) |
|
49 result = {} |
|
50 for module in [settings] + get_format_modules(reverse=True): |
|
51 for attr in FORMAT_SETTINGS: |
|
52 try: |
|
53 result[attr] = getattr(module, attr) |
|
54 except AttributeError: |
|
55 pass |
|
56 src = [] |
|
57 for k, v in result.items(): |
|
58 if isinstance(v, (basestring, int)): |
|
59 src.append("formats['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(smart_unicode(v)))) |
|
60 elif isinstance(v, (tuple, list)): |
|
61 v = [javascript_quote(smart_unicode(value)) for value in v] |
|
62 src.append("formats['%s'] = ['%s'];\n" % (javascript_quote(k), "', '".join(v))) |
|
63 return ''.join(src) |
|
64 |
35 NullSource = """ |
65 NullSource = """ |
36 /* gettext identity library */ |
66 /* gettext identity library */ |
37 |
67 |
38 function gettext(msgid) { return msgid; } |
68 function gettext(msgid) { return msgid; } |
39 function ngettext(singular, plural, count) { return (count == 1) ? singular : plural; } |
69 function ngettext(singular, plural, count) { return (count == 1) ? singular : plural; } |
65 return value[pluralidx(count)]; |
95 return value[pluralidx(count)]; |
66 } |
96 } |
67 } |
97 } |
68 |
98 |
69 function gettext_noop(msgid) { return msgid; } |
99 function gettext_noop(msgid) { return msgid; } |
|
100 |
|
101 """ |
|
102 |
|
103 LibFormatHead = """ |
|
104 /* formatting library */ |
|
105 |
|
106 var formats = new Array(); |
|
107 |
|
108 """ |
|
109 |
|
110 LibFormatFoot = """ |
|
111 function get_format(format_type) { |
|
112 var value = formats[format_type]; |
|
113 if (typeof(value) == 'undefined') { |
|
114 return msgid; |
|
115 } else { |
|
116 return value; |
|
117 } |
|
118 } |
70 """ |
119 """ |
71 |
120 |
72 SimplePlural = """ |
121 SimplePlural = """ |
73 function pluralidx(count) { return (count == 1) ? 0 : 1; } |
122 function pluralidx(count) { return (count == 1) ? 0 : 1; } |
74 """ |
123 """ |
97 def null_javascript_catalog(request, domain=None, packages=None): |
146 def null_javascript_catalog(request, domain=None, packages=None): |
98 """ |
147 """ |
99 Returns "identity" versions of the JavaScript i18n functions -- i.e., |
148 Returns "identity" versions of the JavaScript i18n functions -- i.e., |
100 versions that don't actually do anything. |
149 versions that don't actually do anything. |
101 """ |
150 """ |
102 return http.HttpResponse(NullSource + InterPolate, 'text/javascript') |
151 src = [NullSource, InterPolate, LibFormatHead, get_formats(), LibFormatFoot] |
|
152 return http.HttpResponse(''.join(src), 'text/javascript') |
103 |
153 |
104 def javascript_catalog(request, domain='djangojs', packages=None): |
154 def javascript_catalog(request, domain='djangojs', packages=None): |
105 """ |
155 """ |
106 Returns the selected language catalog as a javascript library. |
156 Returns the selected language catalog as a javascript library. |
107 |
157 |
118 if 'language' in request.GET: |
168 if 'language' in request.GET: |
119 if check_for_language(request.GET['language']): |
169 if check_for_language(request.GET['language']): |
120 activate(request.GET['language']) |
170 activate(request.GET['language']) |
121 if packages is None: |
171 if packages is None: |
122 packages = ['django.conf'] |
172 packages = ['django.conf'] |
123 if type(packages) in (str, unicode): |
173 if isinstance(packages, basestring): |
124 packages = packages.split('+') |
174 packages = packages.split('+') |
125 packages = [p for p in packages if p == 'django.conf' or p in settings.INSTALLED_APPS] |
175 packages = [p for p in packages if p == 'django.conf' or p in settings.INSTALLED_APPS] |
126 default_locale = to_locale(settings.LANGUAGE_CODE) |
176 default_locale = to_locale(settings.LANGUAGE_CODE) |
127 locale = to_locale(get_language()) |
177 locale = to_locale(get_language()) |
128 t = {} |
178 t = {} |
129 paths = [] |
179 paths = [] |
|
180 en_catalog_missing = False |
130 # first load all english languages files for defaults |
181 # first load all english languages files for defaults |
131 for package in packages: |
182 for package in packages: |
132 p = importlib.import_module(package) |
183 p = importlib.import_module(package) |
133 path = os.path.join(os.path.dirname(p.__file__), 'locale') |
184 path = os.path.join(os.path.dirname(p.__file__), 'locale') |
134 paths.append(path) |
185 paths.append(path) |
135 try: |
186 try: |
136 catalog = gettext_module.translation(domain, path, ['en']) |
187 catalog = gettext_module.translation(domain, path, ['en']) |
137 t.update(catalog._catalog) |
188 t.update(catalog._catalog) |
138 except IOError: |
189 except IOError: |
139 # 'en' catalog was missing. This is harmless. |
190 # 'en' catalog was missing. |
|
191 if locale.startswith('en'): |
|
192 # If 'en' is the selected language this would cause issues |
|
193 # later on if default_locale is something other than 'en'. |
|
194 en_catalog_missing = True |
|
195 # Otherwise it is harmless. |
140 pass |
196 pass |
141 # next load the settings.LANGUAGE_CODE translations if it isn't english |
197 # next load the settings.LANGUAGE_CODE translations if it isn't english |
142 if default_locale != 'en': |
198 if default_locale != 'en': |
143 for path in paths: |
199 for path in paths: |
144 try: |
200 try: |
147 catalog = None |
203 catalog = None |
148 if catalog is not None: |
204 if catalog is not None: |
149 t.update(catalog._catalog) |
205 t.update(catalog._catalog) |
150 # last load the currently selected language, if it isn't identical to the default. |
206 # last load the currently selected language, if it isn't identical to the default. |
151 if locale != default_locale: |
207 if locale != default_locale: |
152 for path in paths: |
208 # If the flag en_catalog_missing has been set, the currently |
153 try: |
209 # selected language is English but it doesn't have a translation |
154 catalog = gettext_module.translation(domain, path, [locale]) |
210 # catalog (presumably due to being the language translated from). |
155 except IOError: |
211 # If that is the case, a wrong language catalog might have been |
156 catalog = None |
212 # loaded in the previous step. It needs to be discarded. |
157 if catalog is not None: |
213 if en_catalog_missing: |
158 t.update(catalog._catalog) |
214 t = {} |
|
215 else: |
|
216 for path in paths: |
|
217 try: |
|
218 catalog = gettext_module.translation(domain, path, [locale]) |
|
219 except IOError: |
|
220 catalog = None |
|
221 if catalog is not None: |
|
222 t = catalog._catalog |
159 src = [LibHead] |
223 src = [LibHead] |
160 plural = None |
224 plural = None |
161 if '' in t: |
225 if '' in t: |
162 for l in t[''].split('\n'): |
226 for l in t[''].split('\n'): |
163 if l.startswith('Plural-Forms:'): |
227 if l.startswith('Plural-Forms:'): |
172 csrc = [] |
236 csrc = [] |
173 pdict = {} |
237 pdict = {} |
174 for k, v in t.items(): |
238 for k, v in t.items(): |
175 if k == '': |
239 if k == '': |
176 continue |
240 continue |
177 if type(k) in (str, unicode): |
241 if isinstance(k, basestring): |
178 csrc.append("catalog['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(v))) |
242 csrc.append("catalog['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(v))) |
179 elif type(k) == tuple: |
243 elif isinstance(k, tuple): |
180 if k[0] not in pdict: |
244 if k[0] not in pdict: |
181 pdict[k[0]] = k[1] |
245 pdict[k[0]] = k[1] |
182 else: |
246 else: |
183 pdict[k[0]] = max(k[1], pdict[k[0]]) |
247 pdict[k[0]] = max(k[1], pdict[k[0]]) |
184 csrc.append("catalog['%s'][%d] = '%s';\n" % (javascript_quote(k[0]), k[1], javascript_quote(v))) |
248 csrc.append("catalog['%s'][%d] = '%s';\n" % (javascript_quote(k[0]), k[1], javascript_quote(v))) |
185 else: |
249 else: |
186 raise TypeError, k |
250 raise TypeError(k) |
187 csrc.sort() |
251 csrc.sort() |
188 for k,v in pdict.items(): |
252 for k, v in pdict.items(): |
189 src.append("catalog['%s'] = [%s];\n" % (javascript_quote(k), ','.join(["''"]*(v+1)))) |
253 src.append("catalog['%s'] = [%s];\n" % (javascript_quote(k), ','.join(["''"]*(v+1)))) |
190 src.extend(csrc) |
254 src.extend(csrc) |
191 src.append(LibFoot) |
255 src.append(LibFoot) |
192 src.append(InterPolate) |
256 src.append(InterPolate) |
|
257 src.append(LibFormatHead) |
|
258 src.append(get_formats()) |
|
259 src.append(LibFormatFoot) |
193 src = ''.join(src) |
260 src = ''.join(src) |
194 return http.HttpResponse(src, 'text/javascript') |
261 return http.HttpResponse(src, 'text/javascript') |
|
262 |