Internationalisation

Differences between revisions 32 and 33
Revision 32 as of 2009-11-06 06:56:19
Size: 20424
Editor: www
Comment:
Revision 33 as of 2009-11-06 19:29:58
Size: 20614
Editor: 212
Comment: Added upstream bugs
Deletions are marked like this. Additions are marked like this.
Line 81: Line 81:
 * [[https://bugzilla.gnome.org/show_bug.cgi?id=568845|Upstream glib bug]]
Line 83: Line 84:

TODO

Additional information:

 * [[https://bugzilla.gnome.org/show_bug.cgi?id=569829|Upstream gconf bug]]

Translations in Ubuntu (from a developer perspective)

This document tries to outline:

  • How Ubuntu deals with translations (and i18n in general) from a developer's perspective
  • Which tools are interesting for developers to make sure that translations and i18n work fine

General information

Translations/info.png

Make sure to read the TranslationLifecycle in the translations wiki pages for a general overview of how translations work in Ubuntu

Packaging

Language Packs

General

Packages in main and restricted don't contain translations (*.mo) files themselves, they are stripped during the build on the Launchpad buildds and put into language-pack-* packages instead. This is done in an attempt to bundle the translations you're interested in and cut down the occupied space.

Translations/info.png

Once a package is promoted to main, it only needs to be rebuilt the first time after promotion so that pkgbinarymangler can strip the translations. After this, import to Launchpad Translations and export in language packs "will just happen"

Translation templates

For pkgstriptranslations (in the pkgbinarymangler package) to do the job right and translations to be imported into Launchpad, please make sure that your package in main or restricted generates a POT translation template during the build. It does not necessarily need to be shipped in the source or in the binary package. Generating it during the build is good enough.

Translations/warning.png

If your package does not generate a POT template on build, its translations will remain as Blocked in the Launchpad Translations import queue and will not be imported

This can be achieved by running the following in debian/rules:

  • For packages using CDBS and automake:
    • You just need to include /usr/share/cdbs/1/rules/langpack.mk in debian/rules

    • If the package is a GNOME one, and you are using the gnome.mk CDBS class already, you should be good to go, since it already includes langpack.mk

    • KDE packages: TODO
    • If for some reason the POT template cannot be generated during the build, see the sections below.
  • Other packages, using intltool usually require:

    • A call to intltool-update -p in debian/rules, or

    • a call to an already existing Makefile target to build the POT (this does exist quite often in fact).
  • Packages which don't use intltool:

    • Need to get fixed individually
    • Usually by adding a call to xgettext and po/POTFILES.in, or

    • Finding an already existing Makefile target. e.g. Use $(MAKE) -C po update-po instead of (cd po; make update-po; cd ..).

  • Packages which use python-distutils-extra:

    • Template creation should happen automagically Smile :)

    • TODO: explanation of the command and auto modules

Other translation files

Desktop Entries

Translations of desktop entries (.desktop files) are also stripped out and included in language packs.

Contrary to what other distros do (except currently OpenSUSE), the translations are not expected to be in the .desktop files themselves (static translations), but rather in the same .mo file of the application, from which they are then loaded at runtime. We do this in order to be able to translate them in Launchpad and to ship them in language packs, so that they can be edited and updated by Ubuntu translators.

The runtime loading is done by patches to patch glib and kdelibs, which recognises the the X-Ubuntu-Gettext-Domain additional key we add to all Ubuntu .desktop files and adds gettext support when loading them. Note that if the .desktop file already contains translations, these static translations will be preferred.

Adding the X-Ubuntu-Gettext-Domain= key is done during build time in the packaging either automatically with the package build system or (increasingly rarely) with patches.

Packaging Method

Method for adding key

KDE CDBS

kde.mk includes /usr/lib/kubuntu-desktop-i18n/kubuntu.mk which adds the key using the package name (or an environment variable specified in debian/rule)

KDE old CDBS

Older packages may will use /usr/share/cdbs/1/class/kde4.mk, which add the key, this is deprecated in favour of /usr/share/pkg-kde-tools/makefiles/1/cdbs/kde.mk

KDE Debhelper 7

/usr/share/pkg-kde-tools/makefiles/1/debhelper/kde.mk includes /usr/lib/kubuntu-desktop-i18n/debhelper/kubuntu.mk which adds the key based on the package name (or an environment variable)

GNOME CDBS

gnome.mk includes langpack.mk, the catalogue name comes from po/Makefile

GNOME Debhelper 7

TODO

GNOME Old

The .desktop files are patched directly e.g. transmission

For KDE the translations themselves are downloaded as part of the packaging process of the upstream kde-l10n-xx language packs.

The patch to glib is being submitted upstream (using the key X-GNOME-Gettext-Domain) but has not yet been accepted. The Ubuntu glib version supports both keys, it first checks for X-GNOME- and then X-Ubuntu-.

In summary, for packages in main we strip the translations out of the .desktop files, and glib/kdelibs carry a distro patch to load translations from the .mo file. They use the X-Ubuntu-Gettext-Domain key to figure out where to get the translation from.

Additional information:

Schema files

TODO

Additional information:

Policy files

$ for i in `ls /usr/share/polkit-1/actions/`; do dpkg -S $i; done

Interactive upgrade hooks

After certain upgrades (most notably upgrades between Ubuntu releases), there are follow-up actions which should be taken by the user. These are not logically part of the upgrade, but should be dealt with at some point after the upgrade is complete.

They take the form of helper scripts that can be called by the package's postinst script, and can be internationalized through language packs.

Here's an example showing how these can be internationalized:

_Name: The great UTF-8 Migration
Priority: Medium
Command: bc
Terminal: True
GettextDomain: hwdb-clinet
DisplayIf: shell-command
Title: Change the default title here
DontShowAfterReboot: False
_Description: 
 This command will convert your stuff into UTF-8.
 Use this command if you want a working gnome desktop and you
 feel the world should be a better place.

This is a notification description file as it should be put into a source package. NB the '_' prefix for fields that should be translated. For getting these strings into the package's PO template, you should add a stanza like this to po/POTFILES.in:

[type: gettext/rfc822deb] debian/utf8-migration.installnote

The file should be shipped in /usr/share/packagename and the package's postinst script should install it if the notification should be displayed. At that time it needs to remove the '_' prefixes:

install -d /var/lib/update-notifier/user.d/
sed 's/^_//' /usr/share/utf8-migration-tool/utf8-migration.installnote > /var/lib/update-notifier/user.d/utf8-migration

Verifying translation uploads

This information is intended to help package maintainers to optimize their packages, so that translation related files get automatically imported into Launchpad.

Testing the package locally

To test if your package conforms to the requirements of the import script in Launchpad, please do the following:

  1. Install the pkgbinarymangler package

  2. In /etc/pkgbinarymangler/striptranslations.conf set enable: to true

  3. Optionally, install any build dependencies: sudo apt-get build-dep $PKGNAME

  4. Build the package with debuild -uc -us -b

  5. You will find a <pkgname>-translations.tar.gz tarball along with the .deb package(s)

  6. Untar that tarball into a temporary directory
  7. Compare if the directory structure and the .pot and .po files conform to the requirements listed below

Guidelines

If the application uses gettext, like most GTK and GNU applications do:

  • Template name and domain: the filename of the template (.pot file) should be the same as what the expected translation domain is.

  • Translation filenames: the actual translations (.po files) must have a filename of the format $LANGUAGECODE.po or $LOCALECODE.po (e.g. de.po, pt_BR.po, zh_TW.po)

  • Template and translations location: all translation-related files (the .pot template and its corresponding .po templates) must end up in the same (sub-)directory if possible.

  • Multiple domains: if the application has multiple translation domains (i.e. multiple .pot files), each .pot file and their corresponding .po files should end up in a separate subdirectory (e.g. po/nautilus/nautilus.pot and po/libnautilus/libnautilus.pot)

  • Recommended translations layout: it is recommended that templates and translations for the main application or library are located in the po/ directory.

  • Recommended help layout: it is recommended that templates and translations for help files are located in the help/po/ directory. Note: they will be ignored by Launchpad, since we currently have no infrastructure to deal with them properly.

  • Recommended documentation layout: it is recommended that templates and translations for documentation files are located in the doc/po/ directory. Note: they will also be ignored by Launchpad for the same reason as the help translations.

  • Obsolete translations: if there are .po files present in the package but no associated .pot template, please remove them, since they cannot be used without a .pot template. There might be a bug in the package or in the source code whereby the .pot file doesn't get generated, so make sure to double-check that as well.

  • Valid POT template: please check if the .pot file has any meaningful content. Empty .pot files should be removed and the package build rules be fixed.

  • Templates generated by patches: if your package contains patches and those patches result into extra templates, like patches.pot, please merge those changes into the main template, as we have no use for patch .pot files. Such .pot files should not exist in the final tarball.

  • Multiple templates merged into one: if the package generates multiple .pot files and later merges them into one, only the final .pot file should be present in the final tarball.

  • Architecture-dependent templates: if the package creates the same .pot file in architecture-dependent subdirectories, please consider to merge them, as we can only deal with one single .pot per translation domain.

  • Test templates: test routines and test files should not generate any .pot template or ship any .po file. If such files are present, please remove them.

  • Use UTF-8 encoding: if you have multiple .po files for a language, each in a different encoding, please consider renaming the ones encoded in UTF-8 to be the main .po file for that language and discard the other ones. They might be interesting for Windows users, but not for Linux ones, since translations get converted with iconv into the encoding the user is runnning anyway. And nowadays UTF-8 is the default encoding on Linux. E.g.: if you have zh_TW.po (Big5 encoding), zh_TW.UTF-8.po and zh_TW.cp960.po, please remove zh_TW.po and zh_TW.cp960.po and rename zh_TW.UTF-8.po to zh_TW.po.

  • Obsolete no locale: the no locale is obsolete. If you find no.po files, please look into it and find out if it's Norwegian Bokmål or Nynorsk. Usually it's Bokmål. Please rename the file to the proper language code: nb.po for Bokmål, nn.po for Nynorsk. If nb.po and nn.po are already present, remove no.po.

  • English US translations: If you have an en_US.po file, please investigate if it really contains translations (i.e. if the source code uses en_GB or another language) and if not, you can safely discard it.

Documentation

TODO:

  • Converting xml to PO with xml2po

  • Launchpad import

Packages not using the Gettext format

Mozilla

OpenOffice.org

Coding

STILL IN DRAFT STATUS

Individual programming languages

General
  • Mention po and help/po

  • Mention where .desktop.in and other internationalizable files, etc. are recommended to go

If you are using multiple graphical toolkits
  • Mention gtk and qt

C application, using automake and intltool

Changes in configure.ac

GETTEXT_PACKAGE=your-application-domain-name
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [gettext package name])
AM_GLIB_GNU_GETTEXT

# AM_GNOME_GETTEXT above substs $DATADIRNAME
# this is the directory where the *.{mo,gmo} files are installed
localedir='${prefix}/${DATADIRNAME}/locale'
AC_SUBST(localedir)

IT_PROG_INTLTOOL([0.40.0])

AC_OUTPUT([
po/Makefile.in
])

Changes in Makefile.am

General

SUBDIRS = po

If you are using Freedesktop.org desktop entries

desktopdir = $(datadir)/applications
desktop_in_files = yourappname.desktop.in
desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
@INTLTOOL_DESKTOP_RULE@

EXTRA_DIST = \
        $(desktop_in_files)      \

DISTCLEANFILES = \
        $(desktop_DATA) \

If you are using Gconf schema files

schema_in_files = yourappname.schemas.in
schemadir = @GCONF_SCHEMA_FILE_DIR@
schema_DATA = $(schema_in_files:.schemas.in=.schemas)
@INTLTOOL_SCHEMAS_RULE@

EXTRA_DIST = \
        $(schema_in_files)      \

DISTCLEANFILES = \
        $(schema_DATA) \
  • Marking the files for internationalisation:

If you are using Policykit policy files

policydir = $(YOURAPPS_POLICY_DIR)
policy_in_files = yourappname.policy.in
policy_DATA = $(policy_in_files:.policy.in=.policy)

@INTLTOOL_POLICY_RULE@

EXTRA_DIST = \
        $(policy_in_files) \

DISTCLEANFILES = \
        $(policy_DATA)
  • Marking them for internationalisation: TODO: prepare a separate section on policy files, including the snippet below

  <action id="org.freedesktop.systemtoolsbackends.set">
    <_description>Manage system configuration</_description>
    <_message>System policy prevents modifying the configuration</_message>
    <defaults>
      <allow_inactive>no</allow_inactive>
      <allow_active>auth_admin</allow_active>
    </defaults>
  </action>

Other required files
  • po/LINGUAS
  • po/POTFILES.in
  • [optional] po/POTFILES.skip

Code changes

Enabling gettext

Marking strings for translation
  • Mention gettext _()
  • Mention ngettext

Python application, using automake and intltool

Python application, using pyton-distutils-extra

Translator comments

Translator credits

GTK

KDE

Launchpad

Launchpad integration library

Ubuntu applications use the Launchpad integration library to provide shortcuts to Launchpad to obtain help, report bugs and submit translations. You can see it in action in any Ubuntu application's Help menu:

LPI.png

Here's an example in C of how support for this library was added to Empathy:

=== modified file 'configure.ac'
--- configure.ac        2009-10-13 03:20:58 +0000
+++ configure.ac        2009-10-13 03:26:58 +0000
@@ -131,6 +131,7 @@
    gstreamer-0.10
    unique-1.0
    gnome-keyring-1 >= $KEYRING_REQUIRED
+   launchpad-integration
 ])
 
 PKG_CHECK_MODULES(LIBNOTIFY, libnotify >= $LIBNOTIFY_REQUIRED)

=== modified file 'src/empathy-main-window.c'
--- src/empathy-main-window.c   2009-10-13 03:20:58 +0000
+++ src/empathy-main-window.c   2009-10-13 18:15:41 +0000
@@ -27,6 +27,9 @@
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 
+/* Add launchpad hooks */
+#include <launchpad-integration.h>
+
 #include <libempathy/empathy-contact.h>
 #include <libempathy/empathy-utils.h>
 #include <libempathy/empathy-account-manager.h>
@@ -1424,6 +1427,9 @@
 
        main_window_update_status (window, window->account_manager);
 
+       /* Add launchpad hooks */
+       launchpad_integration_add_ui (window->ui_manager, "/menubar/help/LaunchpadItems");
+
        return window->window;
 }
 

=== modified file 'src/empathy-main-window.ui'
--- src/empathy-main-window.ui  2009-10-13 03:19:42 +0000
+++ src/empathy-main-window.ui  2009-10-13 18:17:20 +0000
@@ -243,6 +243,7 @@
         <menu action="help">
           <menuitem action="help_contents"/>
           <menuitem action="help_debug"/>
+          <placeholder name="LaunchpadItems"/>
           <menuitem action="help_about"/>
         </menu>
       </menubar>

Additional documentation

Translation process

TODO

  • String freeze
  • Translation
  • Translation deadline
  • Language pack updates

Launchpad

The import queue

All translation templates (.pot files) and translations (.po) end up in the Launchpad Translations import queue before being imported into Launchpad.

Some of the Ubuntu import queues:

Templates generally get approved automatically, but sometimes there is some manual work involved in approving them. The Ubuntu Translations Coordinators Team manages the import queue. We've got a mailing list where issues can be discussed and we welcome the help of any community members experienced with translations.

If your project is hosted in Launchpad

General Advice

If you want to make sure that your packages translations are set up correctly, try running:

  • For GNOME packages:

cd po; intltool-update -m

and be sure to either fix the issues or report them upstream.

Note: this is only worth trying if the package uses intltool for i18n (i.e. look for intltool.m4 in the top-level source directory)

  • For GNU packages:
  • For KDE packages:

Sometimes empty .po files caused packages to build from source.

Kubuntu-specific notes


CategoryUbuntuDevelopment CategoryTranslations

UbuntuDevelopment/Internationalisation (last edited 2010-08-18 14:21:17 by 140)