Edgewall Software

Version 1 (modified by Christian Boos, 10 years ago) ( diff )

Start a tutorial about pulling and pushing from Transifex, for our translator coordinators

Transifex and Trac

This page is still a work-in-progress. When I'm confident the content is 100% accurate, I'll post an companion mail on trac-dev ("Trac and Transifex").

For now, the content is enough to explain the changes I made today on Transifex (in particular see the #Releases section below), in case someone noticed and wondered.

Once you're familiar with Transifex (they have some very good documentation on their site), you can apply for membership to one translation team for a language, or create a new team if your language of choice isn't yet represented there (be aware that undertaking a new translation for Trac represents a lot of work).

Updating translations there is only one part of the story, since you need to get your changes integrated into the source code. For that, you need to inform the translator coordinator for your language (see tickets for translation coordination). She will pull the changes from Transifex using the procedure described below, verify them, and commit them. If the translator coordinator doesn't react in due time or is not active anymore, an member of the Trac team will likely notice the activity on the ticket and he could do the same but without the language verification step, obviously.

It's even a better idea to contact and discuss with the translator coordinator before updating the catalogs on Transifex, as some might not be up to date, and you will risk to duplicate work and make integration harder.

Pulling changes from Transifex

You want to update the Trac source code with the latest changes from Transifex, for one or more languages. Typically you'd do this for approving and committing these changes if you're a translation coordinator, or because you want to prepare a patch for submitting those changes for review on a ticket.


You first need to install the Transifex client.

Well, it's usually nothing more than:

easy_install transifex-client

(or one variation of the above)

Of course, you also need to have a checkout of the source, of the branch where you want to work. branches//0.12-stable will be maintained for the foreseeable future, so you may want to start contributing there, but branches//1.0-stable is now the official stable release branch, so don't neglect it. trunk is where the new interesting stuff happen (TracDev/Proposals/ConfigEnumTranslation?).

Now let's go through a complete example. I made one update to the resource corresponding to the messages catalog on 0.12 for the French translation (more specifically, on that page: Transifex:resource/0_12-stable-messages-pot/l/fr/).

Checking the status

First thing to do is to check if everything is correctly configured:

cboos@linux:~/trac/0.12-stable$ tx status
No authentication data found.
trac -> 0_12-stable-messages-js-pot (1 of 2)
Translation Files:
 - en: trac/locale/messages-js.pot (source)
 - ca: trac/locale/ca/LC_MESSAGES/messages-js.po
 - de: trac/locale/de/LC_MESSAGES/messages-js.po
 - en_GB: trac/locale/en_GB/LC_MESSAGES/messages-js.po
 - en_US: trac/locale/en_US/LC_MESSAGES/messages-js.po
 - eo: trac/locale/eo/LC_MESSAGES/messages-js.po

If you get the No authentication data found. line, you first need to authenticate yourself:

cboos@linux:~/trac/0.12-stable$ mkdir tmp
cboos@linux:~/trac/0.12-stable$ cd tmp/
cboos@linux:~/trac/0.12-stable/tmp$ tx init
Creating .tx folder...
Transifex instance [https://www.transifex.com]: 
Creating skeleton...
Creating config file...
No entry found for host https://www.transifex.com. Creating...
Please enter your transifex username: cboos
Updating /home/cboos/.transifexrc file...
cboos@linux:~/trac/0.12-stable/tmp$ cd ..
cboos@linux:~/trac/0.12-stable$ rm -fr tmp

Alternatively, you can directly edit your ~/.transifexrc file, and add:

hostname = https://www.transifex.com
password = <your actual password>
token = 
username = <your account name>

token can be left empty, but must be present.

Then try again:

cboos@linux:~/trac/0.12-stable$ tx status | grep fr
 - fr: trac/locale/fr/LC_MESSAGES/messages-js.po
 - fr: trac/locale/fr/LC_MESSAGES/messages.po

Now, before pulling changes from Transifex, make sure you have no local modifications to the catalogs you're about to update. Otherwise, those local modifications will be lost (well, on Windows at least; seems that on Linux it manages to make better checks with the timestamps between the local file and the file on the server).

Pulling the French catalogs from Transifex

You made sure you have no pending local modifications, you may now pull:

cboos@linux:~/trac/0.12-stable$ tx pull -l fr
Pulling new translations for resource trac.0_12-stable-messages-js-pot (source: trac/locale/messages-js.pot)
 -> fr: trac/locale/fr/LC_MESSAGES/messages-js.po
Pulling new translations for resource trac.0_12-stable-messages-pot (source: trac/locale/messages.pot)
 -> fr: trac/locale/fr/LC_MESSAGES/messages.po

If you see 'Skipping…' messages, the Transifex client thinks it should better avoid updating your local copy. If you're sure you know better, you can pass the -f flag so that it updates it nevertheless.

Examining the changes

If at this point you want to check the difference … good luck! Transifex introduces a bunch of unrelated formatting changes in the translations, folding multiple lines into one, etc.

You can get rid of these spurious changes by doing an update with Babel:

cboos@linux:~/trac/0.12-stable$ make update-fr
python setup.py update_catalog -l fr update_catalog_js -l fr
running update_catalog
updating catalog 'trac/locale/fr/LC_MESSAGES/messages.po' based on 'trac/locale/messages.pot'
running update_catalog_js
updating catalog 'trac/locale/fr/LC_MESSAGES/messages-js.po' based on 'trac/locale/messages-js.pot'

Now the changes are hopefully much more significant:

  • trac/locale/fr/LC_MESSAGES/messages.po

    diff --git a/trac/locale/fr/LC_MESSAGES/messages.po b/trac/locale/fr/LC_MESSAGES/messages.po
    index 00f3c3c..a33bf50 100644
    a b  
    11# French translations for Trac.
    2 # Copyright (C) 2007-2008 Edgewall Software
     2# Copyright (C) 2012 Edgewall Software
    33# This file is distributed under the same license as the Trac project.
     5# Translators:
     6# Christian Boos <cboos@edgewall.org>, 2008,2012.
     7# Christian Boos <cboos@neuf.fr>, 2008.
    58# Emmanuel Blot <emmanuel.blot@free.fr>, 2007.
    6 # Christian Boos <cboos@edgewall.org>, 2008.
    79# Michel Briand <michelbriand@free.fr>, 2008.
    8 # Stéphane Raimbault <stephane.raimbault@gmail.com>, 2009
     10# Stéphane Raimbault <stephane.raimbault@gmail.com>, 2009.
    911msgid ""
    1012msgstr ""
    11 "Project-Id-Version: Trac 0.12\n"
    12 "Report-Msgid-Bugs-To: trac-dev@googlegroups.com\n"
     13"Project-Id-Version:  Trac\n"
     14"Report-Msgid-Bugs-To: http://trac.edgewall.org/\n"
    1315"POT-Creation-Date: 2012-01-29 14:04+0100\n"
    14 "PO-Revision-Date: 2011-01-25 20:28+0100\n"
     16"PO-Revision-Date: 2012-10-27 13:13+0000\n"
    1517"Last-Translator: Christian Boos <cboos@edgewall.org>\n"
    16 "Language-Team: fr_FR <trac-dev@googlegroups.com>\n"
     18"Language-Team: French <trac-dev@googlegroups.com>\n"
    1719"Plural-Forms: nplurals=2; plural=(n > 1)\n"
    1820"MIME-Version: 1.0\n"
    1921"Content-Type: text/plain; charset=utf-8\n"
    msgstr "à %(owner)s"  
    26542655#: trac/ticket/default_workflow.py:251 trac/ticket/default_workflow.py:271
    26552656#, python-format
    26562657msgid "The owner will be changed from %(current_owner)s"
    2657 msgstr "Le propriétaire changera de %(current_owner)s"
     2658msgstr "Le propriétaire ne sera plus %(current_owner)s"
    26592660#: trac/ticket/default_workflow.py:259
    26602661#, python-format

It's a good idea to get rid of the changes in the first hunk. With git, it's easy:

cboos@linux:~/trac/0.12-stable> git checkout -p
diff --git a/trac/locale/fr/LC_MESSAGES/messages.po b/trac/locale/fr/LC_MESSAGES/messages.po
index 00f3c3c..a33bf50 100644
--- a/trac/locale/fr/LC_MESSAGES/messages.po
+++ b/trac/locale/fr/LC_MESSAGES/messages.po
@@ -1,19 +1,21 @@
 # French translations for Trac.
-# Copyright (C) 2007-2008 Edgewall Software
+# Copyright (C) 2012 Edgewall Software
 # This file is distributed under the same license as the Trac project.
+# Translators:
+# Christian Boos <cboos@edgewall.org>, 2008,2012.
+# Christian Boos <cboos@neuf.fr>, 2008.
 # Emmanuel Blot <emmanuel.blot@free.fr>, 2007.
-# Christian Boos <cboos@edgewall.org>, 2008.
 # Michel Briand <michelbriand@free.fr>, 2008.
-# Stéphane Raimbault <stephane.raimbault@gmail.com>, 2009
+# Stéphane Raimbault <stephane.raimbault@gmail.com>, 2009.
 msgid ""
 msgstr ""
-"Project-Id-Version: Trac 0.12\n"
-"Report-Msgid-Bugs-To: trac-dev@googlegroups.com\n"
+"Project-Id-Version:  Trac\n"
+"Report-Msgid-Bugs-To: http://trac.edgewall.org/\n"
 "POT-Creation-Date: 2012-01-29 14:04+0100\n"
-"PO-Revision-Date: 2011-01-25 20:28+0100\n"
+"PO-Revision-Date: 2012-10-27 13:13+0000\n"
 "Last-Translator: Christian Boos <cboos@edgewall.org>\n"
-"Language-Team: fr_FR <trac-dev@googlegroups.com>\n"
+"Language-Team: French <trac-dev@googlegroups.com>\n"
 "Plural-Forms: nplurals=2; plural=(n > 1)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
Discard this hunk from worktree [y,n,q,a,d,/,j,J,g,s,e,?]? y
@@ -2654,7 +2655,7 @@ msgstr "à %(owner)s"
 #: trac/ticket/default_workflow.py:251 trac/ticket/default_workflow.py:271
 #, python-format
 msgid "The owner will be changed from %(current_owner)s"
-msgstr "Le propriétaire changera de %(current_owner)s"
+msgstr "Le propriétaire ne sera plus %(current_owner)s"
 #: trac/ticket/default_workflow.py:259
 #, python-format
Discard this hunk from worktree [y,n,q,a,d,/,K,j,J,g,e,?]? q

Note that you can also do make diff for a more up-to-the-point output. FIXME based on svn diff only

Do something with those changes…

… do whatever you wish, for example commit the changes to the source with an appropriate log message, but, please!, before that:

  • remember to check your catalog with make check (here, make check-fr)
  • remember to check your catalog by compiling it (here make compile-fr)

Pushing local modifications of the French catalogs to Transifex

After the commit, if you did any local adaptations like the removal of the spurious metadata changes, you can also push those changes back to Transifex the same way, as Transifex won't pick up the changes made to the translated catalogs from the repository (it will do that for the catalog templates though, so the latter are always up-to-date).

cboos@linux:~/trac/0.12-stable$ tx push -t -l fr
Pushing translations for resource trac.0_12-stable-messages-js-pot:
Pushing 'fr' translations (file: trac/locale/fr/LC_MESSAGES/messages-js.po)
Pushing translations for resource trac.0_12-stable-messages-pot:
Pushing 'fr' translations (file: trac/locale/fr/LC_MESSAGES/messages.po)

Notes about the Transifex "Releases"

Transifex is not exactly clear if a release should be a line of development (branch) or a given released version. It supports both and let you choose to organize you the way wish.

I opted to make the "releases" match our maintenance branches, and not individual releases (well, we still have a few of these, as apparently you can't delete a release).

The downside is that string freeze periods and release dates will need to be adjusted constantly on the same release. The alternative, creating a new "release" for each actual version we release bears as much overhead (more even, are there's no copy operation) and doesn't bring any benefit besides keeping a record of the versions we made, record that we obviously maintain here anyway in the roadmap.

OTOH, the big benefit is that all the links from t.e.o to Tx won't need to be updated after each minor release. The only updates needed will be at the occasion of introducing a new major release (i.e. for 1.2).

Note: See TracWiki for help on using the wiki.