Changeset 1529
- Timestamp:
- 12/04/05 06:06:16 (3 years ago)
- Files:
-
- django/trunk/django/bin/make-messages.py (modified) (4 diffs)
- django/trunk/django/utils/text.py (modified) (2 diffs)
- django/trunk/django/utils/translation.py (modified) (1 diff)
- django/trunk/django/views/i18n.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/bin/make-messages.py
r1528 r1529 7 7 8 8 from django.utils.translation import templateize 9 10 pythonize_re = re.compile(r'\n\s*//') 9 11 10 12 localedir = None … … 40 42 all = True 41 43 44 if domain not in ('django', 'djangojs'): 45 print "currently make-messages.py only supports domains 'django' and 'djangojs'" 46 sys.exit(1) 42 47 if (lang is None and not all) or domain is None: 43 48 print "usage: make-messages.py -l <language>" … … 67 72 for (dirpath, dirnames, filenames) in os.walk("."): 68 73 for file in filenames: 69 if file.endswith('.py') or file.endswith('.html'): 74 if domain == 'djangojs' and file.endswith('.js'): 75 if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath)) 76 src = open(os.path.join(dirpath, file), "rb").read() 77 src = pythonize_re.sub('\n#', src) 78 open(os.path.join(dirpath, '%s.py' % file), "wb").write(src) 79 thefile = '%s.py' % file 80 cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy -o - "%s"' % ( 81 os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile)) 82 (stdin, stdout, stderr) = os.popen3(cmd, 'b') 83 msgs = stdout.read() 84 errors = stderr.read() 85 if errors: 86 print "errors happened while running xgettext on %s" % file 87 print errors 88 sys.exit(8) 89 old = '#: '+os.path.join(dirpath, thefile)[2:] 90 new = '#: '+os.path.join(dirpath, file)[2:] 91 msgs = msgs.replace(old, new) 92 if msgs: 93 open(potfile, 'ab').write(msgs) 94 os.unlink(os.path.join(dirpath, thefile)) 95 elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')): 70 96 thefile = file 71 97 if file.endswith('.html'): … … 92 118 os.unlink(os.path.join(dirpath, thefile)) 93 119 94 (stdin, stdout, stderr) = os.popen3('msguniq %s' % potfile, 'b') 95 msgs = stdout.read() 96 errors = stderr.read() 97 if errors: 98 print "errors happened while running msguniq" 99 print errors 100 sys.exit(8) 101 open(potfile, 'w').write(msgs) 102 if os.path.exists(pofile): 103 (stdin, stdout, stderr) = os.popen3('msgmerge -q %s %s' % (pofile, potfile), 'b') 120 if os.path.exists(potfile): 121 (stdin, stdout, stderr) = os.popen3('msguniq %s' % potfile, 'b') 104 122 msgs = stdout.read() 105 123 errors = stderr.read() 106 124 if errors: 107 print "errors happened while running msg merge"125 print "errors happened while running msguniq" 108 126 print errors 109 127 sys.exit(8) 110 open(pofile, 'wb').write(msgs) 111 os.unlink(potfile) 128 open(potfile, 'w').write(msgs) 129 if os.path.exists(pofile): 130 (stdin, stdout, stderr) = os.popen3('msgmerge -q %s %s' % (pofile, potfile), 'b') 131 msgs = stdout.read() 132 errors = stderr.read() 133 if errors: 134 print "errors happened while running msgmerge" 135 print errors 136 sys.exit(8) 137 open(pofile, 'wb').write(msgs) 138 os.unlink(potfile) 112 139 django/trunk/django/utils/text.py
r1068 r1529 1 1 import re 2 3 from django.conf.settings import DEFAULT_CHARSET 2 4 3 5 # Capitalizes the first letter of a string. … … 91 93 zfile.close() 92 94 return zbuf.getvalue() 95 96 ustring_re = re.compile(u"([\u0080-\uffff])") 97 def javascript_quote(s): 98 99 def fix(match): 100 return r"\u%04x" % ord(match.group(1)) 101 102 if type(s) == str: 103 s = s.decode(DEFAULT_ENCODING) 104 elif type(s) != unicode: 105 raise TypeError, s 106 s = s.replace('\\', '\\\\') 107 s = s.replace('\n', '\\n') 108 s = s.replace('\t', '\\t') 109 s = s.replace("'", "\\'") 110 return str(ustring_re.sub(fix, s)) 111 django/trunk/django/utils/translation.py
r1388 r1529 212 212 from django.conf.settings import LANGUAGE_CODE 213 213 return LANGUAGE_CODE 214 215 def catalog(): 216 """ 217 This function returns the current active catalog for further processing. 218 This can be used if you need to modify the catalog or want to access the 219 whole message catalog instead of just translating one string. 220 """ 221 global _default, _active 222 t = _active.get(currentThread(), None) 223 if t is not None: 224 return t 225 if _default is None: 226 from django.conf import settings 227 _default = translation(settings.LANGUAGE_CODE) 228 return _default 214 229 215 230 def gettext(message): django/trunk/django/views/i18n.py
r1068 r1529 1 import re 2 import os 3 4 import gettext as gettext_module 5 1 6 from django.utils import httpwrappers 2 from django.utils.translation import check_for_language 7 from django.utils.translation import check_for_language, activate, to_locale, get_language 8 from django.utils.text import javascript_quote 9 from django.conf import settings 3 10 4 11 def set_language(request): … … 21 28 response.set_cookie('django_language', lang_code) 22 29 return response 30 31 NullSource = """ 32 /* gettext identity library */ 33 34 function gettext(msgid) { 35 return msgid; 36 } 37 38 function ngettext(singular, plural, count) { 39 if (count == 1) { 40 return singular; 41 } else { 42 return plural; 43 } 44 } 45 46 function gettext_noop(msgid) { 47 return msgid; 48 } 49 """ 50 51 LibHead = """ 52 /* gettext library */ 53 54 var catalog = new Array(); 55 """ 56 57 LibFoot = """ 58 59 function gettext(msgid) { 60 var value = catalog[msgid]; 61 if (typeof(value) == 'undefined') { 62 return msgid; 63 } else { 64 if (typeof(value) == 'string') { 65 return value; 66 } else { 67 return value[0]; 68 } 69 } 70 } 71 72 function ngettext(singular, plural, count) { 73 value = catalog[singular]; 74 if (typeof(value) == 'undefined') { 75 if (count == 1) { 76 return singular; 77 } else { 78 return plural; 79 } 80 } else { 81 return value[pluralidx(count)]; 82 } 83 } 84 85 function gettext_noop(msgid) { 86 return msgid; 87 } 88 """ 89 90 SimplePlural = """ 91 function pluralidx(count) { 92 if (count == 1) { 93 return 0; 94 } else { 95 return 1; 96 } 97 } 98 """ 99 100 InterPolate = r""" 101 function interpolate(fmt, obj, named) { 102 if (named) { 103 return fmt.replace(/%\(\w+\)s/, function(match){return String(obj[match.slice(2,-2)])}); 104 } else { 105 return fmt.replace(/%s/, function(match){return String(obj.shift())}); 106 } 107 } 108 """ 109 110 def javascript_catalog(request, domain='djangojs', packages=None): 111 """ 112 Returns the selected language catalog as a javascript library. 113 114 Receives the list of packages to check for translations in the 115 packages parameter either from an infodict or as a +-delimited 116 string from the request. Default is 'django.conf'. 117 118 Additionally you can override the gettext domain for this view, 119 but usually you don't want to do that, as JavaScript messages 120 go to the djangojs domain. But this might be needed if you 121 deliver your JavaScript source from Django templates. 122 """ 123 if request.GET: 124 if request.GET.has_key('language'): 125 if check_for_language(request.GET['language']): 126 activate(request.GET['language']) 127 if packages is None: 128 packages = ['django.conf'] 129 if type(packages) in (str, unicode): 130 packages = packages.split('+') 131 default_locale = to_locale(settings.LANGUAGE_CODE) 132 locale = to_locale(get_language()) 133 t = {} 134 paths = [] 135 for package in packages: 136 p = __import__(package, {}, {}, ['']) 137 path = os.path.join(os.path.dirname(p.__file__), 'locale') 138 paths.append(path) 139 #!!! add loading of catalogs from settings.LANGUAGE_CODE and request.LANGUAGE_CODE! 140 try: 141 catalog = gettext_module.translation(domain, path, [default_locale]) 142 except IOError, e: 143 catalog = None 144 if catalog is not None: 145 t.update(catalog._catalog) 146 if locale != default_locale: 147 for path in paths: 148 try: 149 catalog = gettext_module.translation(domain, path, [locale]) 150 except IOError, e: 151 catalog = None 152 if catalog is not None: 153 t.update(catalog._catalog) 154 src = [LibHead] 155 plural = None 156 for l in t[''].split('\n'): 157 if l.startswith('Plural-Forms:'): 158 plural = l.split(':',1)[1].strip() 159 if plural is not None: 160 # this should actually be a compiled function of a typical plural-form: 161 # Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; 162 plural = [el.strip() for el in plural.split(';') if el.strip().startswith('plural=')][0].split('=',1)[1] 163 src.append('function pluralidx(n) {\n return %s;\n}\n' % plural) 164 else: 165 src.append(SimplePlural) 166 csrc = [] 167 pdict = {} 168 for k, v in t.items(): 169 if k == '': 170 continue 171 if type(k) in (str, unicode): 172 csrc.append("catalog['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(v))) 173 elif type(k) == tuple: 174 if not pdict.has_key(k[0]): 175 pdict[k[0]] = k[1] 176 else: 177 pdict[k[0]] = max(k[1], pdict[k[0]]) 178 csrc.append("catalog['%s'][%d] = '%s';\n" % (javascript_quote(k[0]), k[1], javascript_quote(v))) 179 else: 180 raise TypeError, k 181 csrc.sort() 182 for k,v in pdict.items(): 183 src.append("catalog['%s'] = [%s];\n" % (javascript_quote(k), ','.join(["''"]*(v+1)))) 184 src.extend(csrc) 185 src.append(LibFoot) 186 src.append(InterPolate) 187 src = ''.join(src) 188 return httpwrappers.HttpResponse(src, 'text/javascript') 189
