This page describes how to set up Mercurial to be smart about merging your gettext catalogs using the GNU gettext tools.

The setup assumes you have .po files somewhere in your repository that you keep updated by rescanning your code with xgettext. The usual process is something like:

xgettext -L <your programming language of choice> -o strings_list.pot
msgmerge current_catalog.po strings_list.pot > new_catalog.po
mv new_catalog.po current_catalog.po

This way all your code is rescanned and existing translations are reused, including fuzzy matching for minor changes in the original strings. The problem is .po files contain a number of references that are extracted from code (such as file paths, line numbers and many other things) and will change frequently, making .po catalogs impossible to merge by hand using standard 3-way tools.

In order to have mercurial merge .po files for you, you can use the following script:

 #!/bin/bash
LOCAL=$1
OTHER=$2
OUTPUT=$3

POTLOCAL=`mktemp /tmp/potfile.XXXXXXXXX`
POTOTHER=`mktemp /tmp/potfile.XXXXXXXXX`
POTNEW=`mktemp /tmp/potfile.XXXXXXXXX`


cat $LOCAL | msgfilter --keep-header sed -e d 2>/dev/null | sed -e '/^# /d' > $POTLOCAL
cat $OTHER | msgfilter --keep-header sed -e d 2>/dev/null | sed -e '/^# /d' > $POTOTHER

msgcat $POTLOCAL $POTOTHER > $POTNEW
msgmerge $LOCAL --compendium $OTHER $POTNEW > $OUTPUT

Keep in mind this will always give priority to translations in the local branch over the incoming changes. This makes sense for most use cases. In order to change this behaviour just swap $LOCAL and $OTHER in the msgmerge call. True 3-way merging would be cool but would involve either fancy preprocessing and postprocessing to use a standard 3-way merge tool, or making a merge-tool specifically for this purpose (ouch).

In order to have Mercurial use this, add the following lines to .hgrc:

pomerge.priority = 60
pomerge.premerge = False
pomerge.args = $local $other $output
pomerge.executable = <path to the script above>

[merge-patterns]
**.po = pomerge