added infrastructure code for later javascript translating (currently not active)
git-svn-id: http://code.djangoproject.com/svn/django/trunk@1529 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
946bd1e370
commit
5917fdcf2d
|
@ -7,6 +7,8 @@ import getopt
|
|||
|
||||
from django.utils.translation import templateize
|
||||
|
||||
pythonize_re = re.compile(r'\n\s*//')
|
||||
|
||||
localedir = None
|
||||
|
||||
if os.path.isdir(os.path.join('conf', 'locale')):
|
||||
|
@ -39,6 +41,9 @@ for o, v in opts:
|
|||
elif o == '-a':
|
||||
all = True
|
||||
|
||||
if domain not in ('django', 'djangojs'):
|
||||
print "currently make-messages.py only supports domains 'django' and 'djangojs'"
|
||||
sys.exit(1)
|
||||
if (lang is None and not all) or domain is None:
|
||||
print "usage: make-messages.py -l <language>"
|
||||
print " or: make-messages.py -a"
|
||||
|
@ -66,7 +71,28 @@ for lang in languages:
|
|||
|
||||
for (dirpath, dirnames, filenames) in os.walk("."):
|
||||
for file in filenames:
|
||||
if file.endswith('.py') or file.endswith('.html'):
|
||||
if domain == 'djangojs' and file.endswith('.js'):
|
||||
if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
|
||||
src = open(os.path.join(dirpath, file), "rb").read()
|
||||
src = pythonize_re.sub('\n#', src)
|
||||
open(os.path.join(dirpath, '%s.py' % file), "wb").write(src)
|
||||
thefile = '%s.py' % file
|
||||
cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy -o - "%s"' % (
|
||||
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
|
||||
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
|
||||
msgs = stdout.read()
|
||||
errors = stderr.read()
|
||||
if errors:
|
||||
print "errors happened while running xgettext on %s" % file
|
||||
print errors
|
||||
sys.exit(8)
|
||||
old = '#: '+os.path.join(dirpath, thefile)[2:]
|
||||
new = '#: '+os.path.join(dirpath, file)[2:]
|
||||
msgs = msgs.replace(old, new)
|
||||
if msgs:
|
||||
open(potfile, 'ab').write(msgs)
|
||||
os.unlink(os.path.join(dirpath, thefile))
|
||||
elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')):
|
||||
thefile = file
|
||||
if file.endswith('.html'):
|
||||
src = open(os.path.join(dirpath, file), "rb").read()
|
||||
|
@ -91,6 +117,7 @@ for lang in languages:
|
|||
if thefile != file:
|
||||
os.unlink(os.path.join(dirpath, thefile))
|
||||
|
||||
if os.path.exists(potfile):
|
||||
(stdin, stdout, stderr) = os.popen3('msguniq %s' % potfile, 'b')
|
||||
msgs = stdout.read()
|
||||
errors = stderr.read()
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import re
|
||||
|
||||
from django.conf.settings import DEFAULT_CHARSET
|
||||
|
||||
# Capitalizes the first letter of a string.
|
||||
capfirst = lambda x: x and x[0].upper() + x[1:]
|
||||
|
||||
|
@ -90,3 +92,20 @@ def compress_string(s):
|
|||
zfile.write(s)
|
||||
zfile.close()
|
||||
return zbuf.getvalue()
|
||||
|
||||
ustring_re = re.compile(u"([\u0080-\uffff])")
|
||||
def javascript_quote(s):
|
||||
|
||||
def fix(match):
|
||||
return r"\u%04x" % ord(match.group(1))
|
||||
|
||||
if type(s) == str:
|
||||
s = s.decode(DEFAULT_ENCODING)
|
||||
elif type(s) != unicode:
|
||||
raise TypeError, s
|
||||
s = s.replace('\\', '\\\\')
|
||||
s = s.replace('\n', '\\n')
|
||||
s = s.replace('\t', '\\t')
|
||||
s = s.replace("'", "\\'")
|
||||
return str(ustring_re.sub(fix, s))
|
||||
|
||||
|
|
|
@ -212,6 +212,21 @@ def get_language():
|
|||
from django.conf.settings import LANGUAGE_CODE
|
||||
return LANGUAGE_CODE
|
||||
|
||||
def catalog():
|
||||
"""
|
||||
This function returns the current active catalog for further processing.
|
||||
This can be used if you need to modify the catalog or want to access the
|
||||
whole message catalog instead of just translating one string.
|
||||
"""
|
||||
global _default, _active
|
||||
t = _active.get(currentThread(), None)
|
||||
if t is not None:
|
||||
return t
|
||||
if _default is None:
|
||||
from django.conf import settings
|
||||
_default = translation(settings.LANGUAGE_CODE)
|
||||
return _default
|
||||
|
||||
def gettext(message):
|
||||
"""
|
||||
This function will be patched into the builtins module to provide the _
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
import re
|
||||
import os
|
||||
|
||||
import gettext as gettext_module
|
||||
|
||||
from django.utils import httpwrappers
|
||||
from django.utils.translation import check_for_language
|
||||
from django.utils.translation import check_for_language, activate, to_locale, get_language
|
||||
from django.utils.text import javascript_quote
|
||||
from django.conf import settings
|
||||
|
||||
def set_language(request):
|
||||
"""
|
||||
|
@ -20,3 +27,163 @@ def set_language(request):
|
|||
else:
|
||||
response.set_cookie('django_language', lang_code)
|
||||
return response
|
||||
|
||||
NullSource = """
|
||||
/* gettext identity library */
|
||||
|
||||
function gettext(msgid) {
|
||||
return msgid;
|
||||
}
|
||||
|
||||
function ngettext(singular, plural, count) {
|
||||
if (count == 1) {
|
||||
return singular;
|
||||
} else {
|
||||
return plural;
|
||||
}
|
||||
}
|
||||
|
||||
function gettext_noop(msgid) {
|
||||
return msgid;
|
||||
}
|
||||
"""
|
||||
|
||||
LibHead = """
|
||||
/* gettext library */
|
||||
|
||||
var catalog = new Array();
|
||||
"""
|
||||
|
||||
LibFoot = """
|
||||
|
||||
function gettext(msgid) {
|
||||
var value = catalog[msgid];
|
||||
if (typeof(value) == 'undefined') {
|
||||
return msgid;
|
||||
} else {
|
||||
if (typeof(value) == 'string') {
|
||||
return value;
|
||||
} else {
|
||||
return value[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ngettext(singular, plural, count) {
|
||||
value = catalog[singular];
|
||||
if (typeof(value) == 'undefined') {
|
||||
if (count == 1) {
|
||||
return singular;
|
||||
} else {
|
||||
return plural;
|
||||
}
|
||||
} else {
|
||||
return value[pluralidx(count)];
|
||||
}
|
||||
}
|
||||
|
||||
function gettext_noop(msgid) {
|
||||
return msgid;
|
||||
}
|
||||
"""
|
||||
|
||||
SimplePlural = """
|
||||
function pluralidx(count) {
|
||||
if (count == 1) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
InterPolate = r"""
|
||||
function interpolate(fmt, obj, named) {
|
||||
if (named) {
|
||||
return fmt.replace(/%\(\w+\)s/, function(match){return String(obj[match.slice(2,-2)])});
|
||||
} else {
|
||||
return fmt.replace(/%s/, function(match){return String(obj.shift())});
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
def javascript_catalog(request, domain='djangojs', packages=None):
|
||||
"""
|
||||
Returns the selected language catalog as a javascript library.
|
||||
|
||||
Receives the list of packages to check for translations in the
|
||||
packages parameter either from an infodict or as a +-delimited
|
||||
string from the request. Default is 'django.conf'.
|
||||
|
||||
Additionally you can override the gettext domain for this view,
|
||||
but usually you don't want to do that, as JavaScript messages
|
||||
go to the djangojs domain. But this might be needed if you
|
||||
deliver your JavaScript source from Django templates.
|
||||
"""
|
||||
if request.GET:
|
||||
if request.GET.has_key('language'):
|
||||
if check_for_language(request.GET['language']):
|
||||
activate(request.GET['language'])
|
||||
if packages is None:
|
||||
packages = ['django.conf']
|
||||
if type(packages) in (str, unicode):
|
||||
packages = packages.split('+')
|
||||
default_locale = to_locale(settings.LANGUAGE_CODE)
|
||||
locale = to_locale(get_language())
|
||||
t = {}
|
||||
paths = []
|
||||
for package in packages:
|
||||
p = __import__(package, {}, {}, [''])
|
||||
path = os.path.join(os.path.dirname(p.__file__), 'locale')
|
||||
paths.append(path)
|
||||
#!!! add loading of catalogs from settings.LANGUAGE_CODE and request.LANGUAGE_CODE!
|
||||
try:
|
||||
catalog = gettext_module.translation(domain, path, [default_locale])
|
||||
except IOError, e:
|
||||
catalog = None
|
||||
if catalog is not None:
|
||||
t.update(catalog._catalog)
|
||||
if locale != default_locale:
|
||||
for path in paths:
|
||||
try:
|
||||
catalog = gettext_module.translation(domain, path, [locale])
|
||||
except IOError, e:
|
||||
catalog = None
|
||||
if catalog is not None:
|
||||
t.update(catalog._catalog)
|
||||
src = [LibHead]
|
||||
plural = None
|
||||
for l in t[''].split('\n'):
|
||||
if l.startswith('Plural-Forms:'):
|
||||
plural = l.split(':',1)[1].strip()
|
||||
if plural is not None:
|
||||
# this should actually be a compiled function of a typical plural-form:
|
||||
# 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;
|
||||
plural = [el.strip() for el in plural.split(';') if el.strip().startswith('plural=')][0].split('=',1)[1]
|
||||
src.append('function pluralidx(n) {\n return %s;\n}\n' % plural)
|
||||
else:
|
||||
src.append(SimplePlural)
|
||||
csrc = []
|
||||
pdict = {}
|
||||
for k, v in t.items():
|
||||
if k == '':
|
||||
continue
|
||||
if type(k) in (str, unicode):
|
||||
csrc.append("catalog['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(v)))
|
||||
elif type(k) == tuple:
|
||||
if not pdict.has_key(k[0]):
|
||||
pdict[k[0]] = k[1]
|
||||
else:
|
||||
pdict[k[0]] = max(k[1], pdict[k[0]])
|
||||
csrc.append("catalog['%s'][%d] = '%s';\n" % (javascript_quote(k[0]), k[1], javascript_quote(v)))
|
||||
else:
|
||||
raise TypeError, k
|
||||
csrc.sort()
|
||||
for k,v in pdict.items():
|
||||
src.append("catalog['%s'] = [%s];\n" % (javascript_quote(k), ','.join(["''"]*(v+1))))
|
||||
src.extend(csrc)
|
||||
src.append(LibFoot)
|
||||
src.append(InterPolate)
|
||||
src = ''.join(src)
|
||||
return httpwrappers.HttpResponse(src, 'text/javascript')
|
||||
|
||||
|
|
Loading…
Reference in New Issue