general: switch i18n to django (#6735)

This commit is contained in:
Frédéric Péters 2017-07-13 20:24:05 +02:00
parent 079ccafc75
commit 0de5efb88a
8 changed files with 49 additions and 131 deletions

View File

@ -1,9 +1,7 @@
include ChangeLog
include MANIFEST.in
include VERSION
include wcs.cfg-sample
include po/Makefile
include po/*.po
include po/*.pot
recursive-include wcs/locale *.po *.mo
recursive-include extra/ *.py
recursive-include data/web/ *.html *.css *.png
recursive-include data/themes/default/ *.html *.css *.png *.gif *.jpg *.js *.ezt *.xml

View File

@ -1,38 +0,0 @@
POFILES=$(wildcard *.po)
MOFILES=$(POFILES:.po=.mo)
PYFILES=$(shell find ../wcs -name '*.py' | grep -v vendor)
all: $(MOFILES)
install: all
for file in $(MOFILES); do \
lang=`echo $$file | sed 's/\.mo//'`; \
install -d $(prefix)/usr/share/locale/$$lang/LC_MESSAGES/; \
install -m 0644 $$file $(prefix)/usr/share/locale/$$lang/LC_MESSAGES/wcs.mo; \
done
wcs.pot: $(PYFILES)
@echo "Rebuilding the pot file"
rm -f wcs.pot tmp.*.pot
cnt=0;
for file in $(PYFILES); do \
cnt=$$(expr $$cnt + 1); \
bn=$$cnt.`basename $$file`; \
xgettext --keyword=N_ --keyword=C_ -c -L Python -o tmp.$$bn.pot $$file; \
done
msgcat tmp.*.pot > wcs.pot
rm tmp.*.pot
%.mo: %.po
msgfmt -o $@ $<
%.po: wcs.pot
@echo -n "Merging wcs.pot and $@"
@msgmerge $@ wcs.pot -o $@.new
@if [ "`diff $@ $@.new | grep '[<>]' | wc -l`" -ne 2 ]; then \
mv -f $@.new $@; \
else \
rm -f $@.new; \
fi
@msgfmt --statistics $@

View File

@ -2,20 +2,24 @@
import os
import subprocess
import sys
from distutils.core import setup
from distutils import cmd
from distutils.command.install_data import install_data as _install_data
from distutils.cmd import Command
from distutils.command.build import build as _build
from distutils.command.sdist import sdist
from setuptools.command.install_lib import install_lib as _install_lib
from setuptools import setup
local_cfg = None
if os.path.exists('wcs/wcs_cfg.py'):
local_cfg = file('wcs/wcs_cfg.py').read()
os.unlink('wcs/wcs_cfg.py')
class build_trans(cmd.Command):
description = 'Compile .po files into .mo files'
class compile_translations(Command):
description = 'compile message catalogs to MO files via django compilemessages'
user_options = []
def initialize_options(self):
pass
@ -23,30 +27,27 @@ class build_trans(cmd.Command):
pass
def run(self):
po_dir = os.path.join(os.path.dirname(os.curdir), 'po')
for path, names, filenames in os.walk(po_dir):
for f in filenames:
if f.endswith('.po'):
lang = f[:-3]
src = os.path.join(path, f)
dest_path = os.path.join('build', 'locale', lang, 'LC_MESSAGES')
dest = os.path.join(dest_path, 'wcs.mo')
if not os.path.exists(dest_path):
os.makedirs(dest_path)
if not os.path.exists(dest):
print 'Compiling %s' % src
subprocess.call(['msgfmt', src, '--output-file', dest])
else:
src_mtime = os.stat(src)[8]
dest_mtime = os.stat(dest)[8]
if src_mtime > dest_mtime:
print 'Compiling %s' % src
subprocess.call(['msgfmt', src, '--output-file', dest])
try:
from django.core.management import call_command
for path, dirs, files in os.walk('wcs'):
if 'locale' not in dirs:
continue
curdir = os.getcwd()
os.chdir(os.path.realpath(path))
call_command('compilemessages')
os.chdir(curdir)
except ImportError:
sys.stderr.write('!!! Please install Django >= 1.4 to build translations\n')
class build(_build):
sub_commands = _build.sub_commands + [('build_trans', None)]
sub_commands = [('compile_translations', None)] + _build.sub_commands
class install_lib(_install_lib):
def run(self):
_build.run(self)
self.run_command('compile_translations')
_install_lib.run(self)
class eo_sdist(sdist):
@ -65,15 +66,6 @@ class eo_sdist(sdist):
os.remove('VERSION')
class install_data(_install_data):
def run(self):
for lang in os.listdir('build/locale/'):
lang_dir = os.path.join('share', 'locale', lang, 'LC_MESSAGES')
lang_file = os.path.join('build', 'locale', lang, 'LC_MESSAGES', 'wcs.mo')
self.data_files.append( (lang_dir, [lang_file]) )
_install_data.run(self)
def data_tree(destdir, sourcedir):
extensions = ['.css', '.png', '.jpeg', '.jpg', '.gif', '.xml', '.html',
'.js', '.ezt', '.dat', '.eot', '.svg', '.ttf', '.woff']
@ -103,8 +95,8 @@ def get_version():
cmdclass = {
'build': build,
'build_trans': build_trans,
'install_data': install_data,
'compile_translations': compile_translations,
'install_lib': install_lib,
'sdist': eo_sdist
}
@ -122,6 +114,7 @@ setup(
'wcs.qommon.vendor'],
cmdclass = cmdclass,
scripts = ['wcsctl.py'],
include_package_data=True,
data_files = data_tree('share/wcs/web/', 'data/web/') + \
data_tree('share/wcs/themes/', 'data/themes/') + \
data_tree('share/wcs/vendor/', 'data/vendor/') + \

View File

@ -130,11 +130,6 @@ def test_register_cronjobs():
def test_get_default_position():
assert pub.get_default_position() == '50.84;4.36'
def test_install_lang():
pub = create_temporary_pub()
pub.install_lang('xx')
assert pub.gettext.__self__.__class__.__name__ == 'NullTranslations'
def test_import_config_zip():
pub = create_temporary_pub()
pub.cfg['sp'] = {'what': 'ever'}

View File

@ -31,7 +31,6 @@ import traceback
import __builtin__
__builtin__.__dict__['N_'] = lambda x: x
import gettext
import linecache
from StringIO import StringIO
import xml.etree.ElementTree as ET
@ -41,6 +40,10 @@ try:
except ImportError:
raven = None
from django.conf import settings
from django.utils import translation
from django.utils.translation import gettext, ngettext
from quixote.publish import Publisher, get_request, get_response, get_publisher, redirect
from http_request import HTTPRequest
from http_response import HTTPResponse, AfterJob
@ -390,25 +393,13 @@ class QommonPublisher(Publisher, object):
def render_response(self, content):
return template.decorate(content, self.get_request().response)
def get_translation(self, lang):
'''Retrieve a translation object for the given language and
the current theme site.'''
current_theme = self.cfg.get('branding', {}).get('theme', 'default')
theme_directory = template.get_theme_directory(current_theme)
if theme_directory:
app_translation_path = os.path.join(theme_directory, '%s.mo' % lang)
if os.path.exists(app_translation_path):
trans = gettext.GNUTranslations(file(app_translation_path))
trans.add_fallback(self.translations[lang])
return trans
return self.translations[lang]
def install_lang(self, request):
lang = request.language
if lang is None or not lang in [x[0] for x in settings.LANGUAGES]:
lang = 'en'
translation.activate(lang)
request.LANGUAGE_CODE = lang
def install_lang(self, lang=None):
if lang is None or not self.translations.has_key(lang):
lang = (os.environ.get('LANG') or 'en')[:2]
if not self.translations.has_key(lang):
lang = 'en'
translation = self.get_translation(lang)
self.gettext = translation.gettext
self.ngettext = translation.ngettext
@ -635,7 +626,7 @@ class QommonPublisher(Publisher, object):
return redirect(request.get_path() + new_query_string)
request.language = self.get_site_language()
self.install_lang(request.language)
self.install_lang(request)
self.substitutions.feed(self)
self.substitutions.feed(request)
for extra_source in self.extra_sources:
@ -810,7 +801,6 @@ class QommonPublisher(Publisher, object):
return
cls._initialized = True
cls.load_extra_dirs()
cls.load_translations()
if cls.register_cron:
cls.register_cronjobs()
@ -867,30 +857,6 @@ class QommonPublisher(Publisher, object):
cls.translation_domains.append(name)
supported_languages = None
@classmethod
def load_translations(cls):
cls.translations = {
'C': gettext.NullTranslations(),
'en': gettext.NullTranslations(),
}
for lang in cls.supported_languages or []:
try:
cls.translations[lang] = gettext.translation(cls.APP_NAME, languages=[lang])
except IOError:
pass
if cls.translation_domains:
for domain in cls.translation_domains:
for lang in cls.supported_languages or []:
if not lang in cls.translations.keys():
continue
try:
trans = gettext.translation(domain, languages=[lang])
except IOError:
continue
cls.translations[lang]._catalog.update(trans._catalog)
cfg = None
def write_cfg(self):
s = cPickle.dumps(self.cfg)

View File

@ -34,19 +34,23 @@ TIME_ZONE = 'Europe/Brussels'
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'
LANGUAGES = (('en', 'English'), ('fr', 'French'))
SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = False
USE_I18N = True
# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = False
USE_L10N = True
# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True
LOCALE_PATHS = (os.path.join(PROJECT_PATH, 'wcs', 'locale'), )
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/var/www/example.com/media/"
MEDIA_ROOT = os.path.join(PROJECT_PATH, 'media')