[Cubicweb] cube proposal for i18n content management

Florent Cayré florent.cayre at gmail.com
Mon Sep 12 15:38:18 CEST 2011

Hi list,

I am about to write a new cube for my own needs: easily write and 
maintain a web site with textual content translated in several languages.
I do not like CMS-like solutions where content translations only reside 
in the database, but would like to maintain them in mercurial too 
(providing the ability to easily rollback, see versino history, and so on).

Below is the small document I just wrote about it, with specifications 
and first implementation directions.
If you know a better/ more general way to do it or have any suggestion, 
please tell me through the list.

Thanks for your feedback,


Basic needs:

* translations should be manageable through VCS and the web interface

  - add a translation, edit the reference version of a text or its 

  - mark the reference version or one of its translations as 'on-line'

* must be totally non intrusive in the application schema: managed only 
by new
entity types

* translations can be defined at the field level, but still easy to 
should be able to define translations for each translatable field 
but all fields should be editable at once through the web interface (in 
a single

Tools translation managers and translators will need:

* easy way to know if translations are up-to-date compared to last default
revision (based on a date + a flag telling if an entity field edition
should lead to a translation into the other languages or not

* list missing/ deprecated translations

* rollback on-line versions to a given VCS revision


Use the vcsfile cube to maintain the translations:

* in the repository, one language corresponds to one branch, one folder 
to one entity,
one file to one field

* from the database point of view, the schema could look like:

  class Language(EntityType):
      """registered language for an application.

      See http://www.loc.gov/standards/iso639-2 for available codes.
      code = String(required=True, maxsize=2, unique=True,
                    description=_('ISO 639.2 Code'))
      name = String(required=True, internationalizable=True, maxsize=37,
                    description=_('ISO description'))

  class Translation(EntityType):
      __unique_together__ = ('fieldname', 'lang', 'translation_of')

      fieldname = String(required=True, maxsize=64)
      lang = SubjectRelation('Language', cardinality='1*', inlined=True,
      content = SubjectRelation('VersionContent', cardinality='1?', 

  class translation_of(RelationType):
      subject = 'Translation'
      cardinality = '1*'
      inlined = True

Ideally, using it with the `card` cube would only consist in defining
one RelationDefinition instance for each translatable entity type like:

  class translation_of(RelationDefinition):
        object = 'Card'

and an adapter inheriting a supplied base entity adapter 

  class TranslatableCardAdapter(TranslatableAdapter):
        translatable_fields = ('title', 'synopsis', 'content')

However, implementing translation display would probably imply monkey 
`Entity.printable_value` so that it calls the adapter.
If anyone has a better method, please tell me.

Another difficult point is regarding data migration: what if a 
translatable attribute
is dropped or renamed?

Hooks needed:

* translatable field creation/ edition in the web interface:
new `online` tagged revision of the corresponding file in the repository

* translatable entity deletion: removal of the corresponding files in the

* `content` relation synchronization with the online repository tag
(or tip if not present?)

More information about the Cubicweb mailing list