[You can also view the single-page version of this document.]

Localization (l10n)

Translation has been divided into two domains. First, there is the translation of server messages sent to connecting clients. This issue has been punted for now. Second there is the translation of the client and its libraries.

Localization overview

The gettext package provides services for translating messages. It uses the xgettext tool to extract strings from the sources for translation. This works by extracting the arguments of the _(), N_() and Q_() macros. _() is used in context where function calls are allowed (typically anything except static initializers). N_() is used whenever _() isn't. Strings marked with N_() need to be passed to gettext translation routines whenever referenced in the code. For an example, look at how the header and footer are handled in subversion/svn/help-cmd.c. Q_() is used for messages which have singular and plural version.

Beside _(), N_() and Q_() macros also U_() is used to mark strings which will not be translated because it's in general not useful to translate internal error messages. This should affect only obscure error messages most users should never ever see (caused by bugs in Subversion or very special repository corruptions). The reason for using U_() is to explicitly note that a gettext call was not just forgotten.

When using direct calls to gettext routines (*gettext or *dgettext), keep in mind that most of Subversion code is library code. Therefore the default domain is not necessarily Subversion's own domain. In library code you should use the dgettext versions of the gettext functions. The domain name is defined in the PACKAGE_NAME define.

All required setup for localization is controlled by the ENABLE_NLS conditional in svn_private_config.h (for *nix) and svn_private_config.hw (for Windows). Be sure to put

   #include "svn_private_config.h"

as the last include in any file which requires localization.

Also note that return values of _(), Q_() and *gettext() calls are UTF-8 encoded; this means that they should be translated to the current locale being written as any form of program output.

The GNU gettext manual (https://www.gnu.org/software/gettext/manual/html_node/gettext_toc.html) provides additional information on writing translatable programs in its section "Preparing Program Sources". Its hints mainly apply to string composition.

Currently available translations can be found in the po section of the repository. Please contact dev@subversion.apache.org when you want to start a translation not available yet. Translation discussion takes place on that list.

Software version requirements

The Makefile build targets locale-gnu-* (used to maintain po files) require GNU gettext 0.13 or newer. Note that this is not a requirement for those wanting to compile the *.po files into *.mo's.

Starting a new translation

Before starting a new translation please contact the subversion development mailing list to make sure you are not duplicating efforts. Also please note that the project has a strong preference for translations which are maintained by more than one person: mailing the lists with your intentions might help you find supporters.

After that, you should perform the following steps:

Unix (GNU gettext)

  1. check out Subversion (see INSTALL for more information)
  2. run ./autogen.sh
  3. run ./configure
  4. run make locale-gnu-pot
    This step is currently only supported for GNU gettext Makefile based systems
  5. run msginit --locale LOCALE -o LOCALE.po in the subversion/po directory of your working copy. LOCALE is the ll[_LL] language and country code used to identify your locale.

Steps (2) and (3) generate a Makefile; step (4) generates subversion/po/subversion.pot

The Subversion project has a policy not to put names in its files, so please apply the two changes described below.

The header in the newly generated .po file looks like this:

  # SOME DESCRIPTIVE TITLE.
  # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
  # This file is distributed under the same license as the PACKAGE package.
  # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.

Please replace that block with the following text:

  # <Your language> translation for subversion package
  #    Licensed to the Apache Software Foundation (ASF) under one
  #    or more contributor license agreements.  See the NOTICE file
  #    distributed with this work for additional information
  #    regarding copyright ownership.  The ASF licenses this file
  #    to you under the Apache License, Version 2.0 (the
  #    "License"); you may not use this file except in compliance
  #    with the License.  You may obtain a copy of the License at
  #
  #      http://www.apache.org/licenses/LICENSE-2.0
  #
  #    Unless required by applicable law or agreed to in writing,
  #    software distributed under the License is distributed on an
  #    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  #    KIND, either express or implied.  See the License for the
  #    specific language governing permissions and limitations
  #    under the License.

The first translation block in the .po file contains two lines like these:

  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
  "Language-Team: LANGUAGE <LL@li.org>\n"

Please replace those with these two lines:

  "Last-Translator: Subversion Developers <dev@subversion.apache.org>\n"
  "Language-Team: YOUR LANGUAGE <dev@subversion.apache.org>\n"

Unix (non-GNU gettext)

To be documented

Windows

See issue #1977.

Verifying your po file

Before submitting to the mailing list or committing to the repository, please make sure your po file 'compiles'. You can do this with these steps (on Makefile based systems):

  1. run ./autogen.sh
  2. run ./configure (with the appropriate arguments)
  3. run make locale

The autogen.sh step is important, since it adds new po files as dependencies of the 'locale' build target. Note however that steps 1 and 2 are only needed once after you have added a new translation.

Submitting your po file

Please don't mail large po files to the mailing lists. There are many subscribers on dev@subversion.apache.org who are on slow links and do not want to receive a large file by email. Instead, place the po file somewhere on the Internet for download, and just post the URL. If you do not have a site available, please ask on dev@ and someone will help you find a location.

Of course, if you have commit access to the Subversion repository, you can just commit the po file there, assuming all other requirements have been satisfied.

Updating existing po files

The Makefile based part of the build system contains a make target to facilitate maintenance of existing po files. To update po files on systems with GNU gettext run

    make locale-gnu-po-update

To only update a particular language, you may use

    make locale-gnu-po-update PO=ll

where ll is the name of the po file without the extension (i.e. PO=sv).

It is recommended that the .po update is done by using two commits; one after the "make locale-gnu-po-update", and one after the translation is done. This has two advantages:

  • gettext(1) produces lots of line number changes which makes the resulting diff hard to review by the other translators. By committing twice, all the line number changes are stored in the first commit, and the second commit contains all the actual translations with no extra garbage.
  • If there are several translators for a specific language (which is highly preferred by the project) you don't risk working for hours just to find that some other translator already has done the job when you're finished. You will immediately notice that someone else is working on the .po file when you try to perform the first commit, because svn will tell you that the file is outdated.

Maintenance on branches

Editing po files in trunk is pretty straightforward, but gets a bit more complicated when those changes are going to be transferred to a release branch. Project policy is to make no direct changes on release branches, everything that is committed to the branch should be merged from trunk. This also applies to po files. Using svn merge to do the job can lead to conflicts and fuzzy messages due to the changes in line numbers and string formatting done by gettext.

The scheme below eliminates any complexity which exists when using svn merge to do branch updates. The following rules apply:
  • Translation updates go to trunk
  • Messages required on the branch which ever existed on trunk get merged from trunk
  • There are 2 mass operations allowed on po files on branches:
    • make locale-gnu-po-update
    • merging messages from trunk (see below)
  • The remaining few messages which never existed on trunk in any revision are translated on the branch
  • Message options (such as fuzzy) can be tweaked

The above list is a complete enumeration of all operations allowed on po files on branches.

Merging messages from trunk revision X of YY.po to your branch working copy can be done with this command:

  svn cat -r X ^/subversion/trunk/subversion/po/YY.po | \
    po-merge.py YY.po

Requirements for po and mo files

On some gettext implementations we have to ensure that the mo files — whether obtained through the project or created locally — are encoded using UTF-8. This requirement stems from the fact that Subversion uses UTF-8 internally, some implementations translate to the active locale and the fact that bind_textdomain_codeset() is not portable across implementations.

To satisfy this requirement po files are required to be UTF-8 encoded. If the gettext implementation on the target system doesn't support bind_textdomain_codeset(), the build system will ensure that the mo file is in UTF-8 by removing the Content-Type header from the po file header. Note that some msgfmt utilities dislike the absence of the charset designator and will generate warnings along the lines of "Won't be able to do character set conversion" because of it. You can safely ignore these warnings.

Conventions for the empty string msgid section

Some gettext implementations use a section with a msgid "" (empty string) to keep administrative data. One of the headers suggested is the 'Last-Translator:' field. Because the Subversion project has a policy not to name contributors in specific files, but give credit in the repository log messages, you are required not to put your name in this field.

Since some tools require this field to consider the po file valid (i.e. Emacs PO Mode), you can put "dev@subversion.apache.org" into this field.

Translation teams

The Translation Project attempts to organise translation attempts and get translators for various packages. Some teams have guidelines to stimulate consistency across packages.

Single versus double quotes

The project has standardised the use of quotes. Some translation teams have done the same. If there is no translation team for your locale or they did not standardise quoting, please follow the project guidelines elsewhere in this guide. If they did: follow them :-)

Error message conventions

Since translators will generally see all error messages in the code, it's important to know that there is a special section in this document about this category of strings. Here the same applies as does for the quotes: Adhere to them on all points for which there is no explicit policy set out by the translation team for your language.