For most of our cross-platform code our Gettext-based KF::I18n Framework takes care of translating user-readable texts on Android as well. It doesn’t cover Android-specific files and/or Android-native code though. Fortunately it’s not hard to integrate that with KDE’s translation infrastructure as well.

Marking strings for translation

For Android’s translation system all messages needing localization have to be put into the res/values/strings.xml file and are assigned translation ids there.

<?xml version='1.0' encoding='utf-8'?>
    <string name="application_name_full">KDE Itinerary</string>
    <string name="application_name_short">Itinerary</string>
    <string name="shortcut_label_current_ticket_short">Current Ticket</string>

Messages can then be referenced by their translation id, both in Java code and the various XML files including the Android manifest. The latter is probably the more commonly needed case for KDE’s apps, which have typically fairly little code written in Java directly.

In XML files those strings can then referenced using the @string/<translation_id> notation:

    <activity android:name="org.kde.itinerary.Activity"

In Java code, those messages are accessible via the getString method in android.content.Context and using the translation id constants R.string.<translation_id>.

Translation infrastructure integration

For KDE’s translation infrastructure to pick this up, a file named is needed in the project root directory. It’s used by the nightly translation run to extract and merge translations that are stored in their own format rather than the usual Gettext catalogs.

Using the following template only two paths need to be adjusted to the respective project:

#!/usr/bin/env bash

# the name of catalog we create (without the.pot extension)
# relative path to the Android resource folder

function export_pot_file
    mkdir outdir
    ANSI_COLORS_DISABLED=1 a2po export --android $ANDROID_RES_DIR --gettext outdir
    mv outdir/template.pot $1
    rm -rf outdir
    rm -f rc.cpp

function import_po_files
    find "$podir" -type f -name "*@*.po" -delete
    find "$podir" -name '*.po' -exec msgattrib --no-obsolete -o {} {} \;
    ANSI_COLORS_DISABLED=1 a2po import --ignore-fuzzy --android $ANDROID_RES_DIR --gettext $podir

See e.g. KDE Itinerary’s for a full example.

After adding that file you should see translated strings.xml variants starting to appear within a few days.