--- a/goa/tools/i18n.py Mon Mar 23 13:07:26 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,282 +0,0 @@
-#!/usr/bin/env python
-"""This script is just a thin wrapper around ``msgcat`` and ``msgfmt``
-to generate ``.mo`` files
-"""
-
-import sys
-import os
-import os.path as osp
-import shutil
-from tempfile import mktemp
-from glob import glob
-from mx.DateTime import now
-
-from logilab.common.fileutils import ensure_fs_mode
-from logilab.common.shellutils import find, rm
-
-from yams import BASE_TYPES
-
-from cubicweb import CW_SOFTWARE_ROOT
-# from cubicweb.__pkginfo__ import version as cubicwebversion
-cubicwebversion = '2.48.2'
-
-DEFAULT_POT_HEAD = r'''# LAX application po file
-
-msgid ""
-msgstr ""
-"Project-Id-Version: cubicweb %s\n"
-"PO-Revision-Date: 2008-03-28 18:14+0100\n"
-"Last-Translator: Logilab Team <contact@logilab.fr>\n"
-"Language-Team: fr <contact@logilab.fr>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: cubicweb-devtools\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-''' % cubicwebversion
-
-
-STDLIB_ERTYPES = BASE_TYPES | set( ('EUser', 'EProperty', 'Card', 'identity', 'for_user') )
-
-def create_dir(directory):
- """create a directory if it doesn't exist yet"""
- try:
- os.makedirs(directory)
- print 'created directory', directory
- except OSError, ex:
- import errno
- if ex.errno != errno.EEXIST:
- raise
- print 'directory %s already exists' % directory
-
-def execute(cmd):
- """display the command, execute it and raise an Exception if returned
- status != 0
- """
- print cmd.replace(os.getcwd() + os.sep, '')
- status = os.system(cmd)
- if status != 0:
- raise Exception()
-
-def add_msg(w, msgid):
- """write an empty pot msgid definition"""
- if isinstance(msgid, unicode):
- msgid = msgid.encode('utf-8')
- msgid = msgid.replace('"', r'\"').splitlines()
- if len(msgid) > 1:
- w('msgid ""\n')
- for line in msgid:
- w('"%s"' % line.replace('"', r'\"'))
- else:
- w('msgid "%s"\n' % msgid[0])
- w('msgstr ""\n\n')
-
-
-def generate_schema_pot(w, vreg, tmpldir):
- """generate a pot file with schema specific i18n messages
-
- notice that relation definitions description and static vocabulary
- should be marked using '_' and extracted using xgettext
- """
- cube = tmpldir and osp.split(tmpldir)[-1]
- config = vreg.config
- vreg.register_objects(config.vregistry_path())
- w(DEFAULT_POT_HEAD)
- _generate_schema_pot(w, vreg, vreg.schema, libschema=None, # no libschema for now
- cube=cube)
-
-
-def _generate_schema_pot(w, vreg, schema, libschema=None, cube=None):
- w('# schema pot file, generated on %s\n' % now().strftime('%Y-%m-%d %H:%M:%S'))
- w('# \n')
- w('# singular and plural forms for each entity type\n')
- w('\n')
- # XXX hard-coded list of stdlib's entity schemas
- libschema = libschema or STDLIB_ERTYPES
- entities = [e for e in schema.entities() if not e in libschema]
- done = set()
- for eschema in sorted(entities):
- etype = eschema.type
- add_msg(w, etype)
- add_msg(w, '%s_plural' % etype)
- if not eschema.is_final():
- add_msg(w, 'This %s' % etype)
- add_msg(w, 'New %s' % etype)
- add_msg(w, 'add a %s' % etype)
- add_msg(w, 'remove this %s' % etype)
- if eschema.description and not eschema.description in done:
- done.add(eschema.description)
- add_msg(w, eschema.description)
- w('# subject and object forms for each relation type\n')
- w('# (no object form for final relation types)\n')
- w('\n')
- if libschema is not None:
- relations = [r for r in schema.relations() if not r in libschema]
- else:
- relations = schema.relations()
- for rschema in sorted(set(relations)):
- rtype = rschema.type
- add_msg(w, rtype)
- if not (schema.rschema(rtype).is_final() or rschema.symetric):
- add_msg(w, '%s_object' % rtype)
- if rschema.description and rschema.description not in done:
- done.add(rschema.description)
- add_msg(w, rschema.description)
- w('# add related box generated message\n')
- w('\n')
- for eschema in schema.entities():
- if eschema.is_final():
- continue
- entity = vreg.etype_class(eschema)(None, None)
- for x, rschemas in (('subject', eschema.subject_relations()),
- ('object', eschema.object_relations())):
- for rschema in rschemas:
- if rschema.is_final():
- continue
- for teschema in rschema.targets(eschema, x):
- if defined_in_library(libschema, eschema, rschema, teschema, x):
- continue
- if entity.relation_mode(rschema.type, teschema.type, x) == 'create':
- if x == 'subject':
- label = 'add %s %s %s %s' % (eschema, rschema, teschema, x)
- label2 = "creating %s (%s %%(linkto)s %s %s)" % (teschema, eschema, rschema, teschema)
- else:
- label = 'add %s %s %s %s' % (teschema, rschema, eschema, x)
- label2 = "creating %s (%s %s %s %%(linkto)s)" % (teschema, teschema, rschema, eschema)
- add_msg(w, label)
- add_msg(w, label2)
- cube = (cube or 'cubicweb') + '.'
- done = set()
- for reg, objdict in vreg.items():
- for objects in objdict.values():
- for obj in objects:
- objid = '%s_%s' % (reg, obj.id)
- if objid in done:
- continue
- if obj.__module__.startswith(cube) and obj.property_defs:
- add_msg(w, '%s_description' % objid)
- add_msg(w, objid)
- done.add(objid)
-
-def defined_in_library(libschema, etype, rtype, tetype, x):
- """return true if the given relation definition exists in cubicweb's library"""
- if libschema is None:
- return False
- if x == 'subject':
- subjtype, objtype = etype, tetype
- else:
- subjtype, objtype = tetype, etype
- try:
- return libschema.rschema(rtype).has_rdef(subjtype, objtype)
- except (KeyError, AttributeError):
- # if libschema is a simple list of entity types (lax specific)
- # or if the relation could not be found
- return False
-
-
-
-# XXX check if this is a pure duplication of the original
-# `cubicweb.common.i18n` function
-def compile_i18n_catalogs(sourcedirs, destdir, langs):
- """generate .mo files for a set of languages into the `destdir` i18n directory
- """
- print 'compiling %s catalogs...' % destdir
- errors = []
- for lang in langs:
- langdir = osp.join(destdir, lang, 'LC_MESSAGES')
- if not osp.exists(langdir):
- create_dir(langdir)
- pofiles = [osp.join(path, '%s.po' % lang) for path in sourcedirs]
- pofiles = [pof for pof in pofiles if osp.exists(pof)]
- mergedpo = osp.join(destdir, '%s_merged.po' % lang)
- try:
- # merge application messages' catalog with the stdlib's one
- execute('msgcat --use-first --sort-output --strict %s > %s'
- % (' '.join(pofiles), mergedpo))
- # make sure the .mo file is writeable and compile with *msgfmt*
- applmo = osp.join(destdir, lang, 'LC_MESSAGES', 'cubicweb.mo')
- try:
- ensure_fs_mode(applmo)
- except OSError:
- pass # suppose not osp.exists
- execute('msgfmt %s -o %s' % (mergedpo, applmo))
- except Exception, ex:
- errors.append('while handling language %s: %s' % (lang, ex))
- try:
- # clean everything
- os.unlink(mergedpo)
- except Exception:
- continue
- return errors
-
-
-def update_cubes_catalog(vreg, appdirectory, langs):
- toedit = []
- tmpl = osp.basename(osp.normpath(appdirectory))
- tempdir = mktemp()
- os.mkdir(tempdir)
- print '*' * 72
- print 'updating %s cube...' % tmpl
- os.chdir(appdirectory)
- potfiles = []
- if osp.exists(osp.join('i18n', 'entities.pot')):
- potfiles = potfiles.append( osp.join('i18n', 'entities.pot') )
- print '******** extract schema messages'
- schemapot = osp.join(tempdir, 'schema.pot')
- potfiles.append(schemapot)
- # XXX
- generate_schema_pot(open(schemapot, 'w').write, vreg, appdirectory)
- print '******** extract Javascript messages'
- jsfiles = find('.', '.js')
- if jsfiles:
- tmppotfile = osp.join(tempdir, 'js.pot')
- execute('xgettext --no-location --omit-header -k_ -L java --from-code=utf-8 -o %s %s'
- % (tmppotfile, ' '.join(jsfiles)))
- # no pot file created if there are no string to translate
- if osp.exists(tmppotfile):
- potfiles.append(tmppotfile)
- print '******** create cube specific catalog'
- tmppotfile = osp.join(tempdir, 'generated.pot')
- execute('xgettext --no-location --omit-header -k_ -o %s %s'
- % (tmppotfile, ' '.join(glob('*.py'))))
- if osp.exists(tmppotfile): # doesn't exists of no translation string found
- potfiles.append(tmppotfile)
- potfile = osp.join(tempdir, 'cube.pot')
- print '******** merging .pot files'
- execute('msgcat %s > %s' % (' '.join(potfiles), potfile))
- print '******** merging main pot file with existing translations'
- os.chdir('i18n')
- for lang in langs:
- print '****', lang
- tmplpo = '%s.po' % lang
- if not osp.exists(tmplpo):
- shutil.copy(potfile, tmplpo)
- else:
- execute('msgmerge -N -s %s %s > %snew' % (tmplpo, potfile, tmplpo))
- ensure_fs_mode(tmplpo)
- shutil.move('%snew' % tmplpo, tmplpo)
- toedit.append(osp.abspath(tmplpo))
- # cleanup
- rm(tempdir)
- # instructions pour la suite
- print '*' * 72
- print 'you can now edit the following files:'
- print '* ' + '\n* '.join(toedit)
-
-
-def getlangs(i18ndir):
- return [fname[:-3] for fname in os.listdir(i18ndir)
- if fname.endswith('.po')]
-
-
-def get_i18n_directory(appdirectory):
- if not osp.isdir(appdirectory):
- print '%s is not an application directory' % appdirectory
- sys.exit(2)
- i18ndir = osp.join(appdirectory, 'i18n')
- if not osp.isdir(i18ndir):
- print '%s is not an application directory ' \
- '(i18n subdirectory missing)' % appdirectory
- sys.exit(2)
- return i18ndir