Localization/Concepts/Non Text Resources: Difference between revisions

From KDE TechBase
m (Text replace - "</code>" to "</syntaxhighlight>")
m (Text replace - "<code text>" to "<syntaxhighlight lang="text">")
 
Line 22: Line 22:


Think of an installed KDE application. Its resources that one may want to localize will probably reside in <tt>share/</tt> directory of installation prefix. For example, the splash screen of KDingus may be installed like this:
Think of an installed KDE application. Its resources that one may want to localize will probably reside in <tt>share/</tt> directory of installation prefix. For example, the splash screen of KDingus may be installed like this:
<code text>
<syntaxhighlight lang="text">
/.../share/kdingus/
/.../share/kdingus/
     pics/
     pics/
Line 30: Line 30:


First, the localized splash must be installed in <tt>l10n/aa</tt> subdirectory of the directory where the original splash resides, and with the same name:
First, the localized splash must be installed in <tt>l10n/aa</tt> subdirectory of the directory where the original splash resides, and with the same name:
<code text>
<syntaxhighlight lang="text">
/.../share/kdingus/
/.../share/kdingus/
     pics/
     pics/
Line 59: Line 59:


Continuing with the KDingus example from above, assuming that it is an app within <tt>kdeutils</tt> module (i.e. one of the core modules, to which out-of-source lbundles apply). The location of its splash screen in the repository may be as follows:
Continuing with the KDingus example from above, assuming that it is an app within <tt>kdeutils</tt> module (i.e. one of the core modules, to which out-of-source lbundles apply). The location of its splash screen in the repository may be as follows:
<code text>
<syntaxhighlight lang="text">
/trunk/KDE/kdeutils/
/trunk/KDE/kdeutils/
     kdingus/
     kdingus/
Line 68: Line 68:
</syntaxhighlight>
</syntaxhighlight>
where <tt>CMakeLists.txt</tt> will contain the installation instructions for the splash image. Then, language <tt>aa</tt> could store the localized splash like this:
where <tt>CMakeLists.txt</tt> will contain the installation instructions for the splash image. Then, language <tt>aa</tt> could store the localized splash like this:
<code text>
<syntaxhighlight lang="text">
/trunk/l10n-kde4/aa/data/kdeutils/
/trunk/l10n-kde4/aa/data/kdeutils/
     CMakeLists.txt
     CMakeLists.txt
Line 82: Line 82:


The <tt>CMakeLists.txt</tt> files in language subdirectory, except the last one, are there only to include their subdirs, so that all levels are "connected":
The <tt>CMakeLists.txt</tt> files in language subdirectory, except the last one, are there only to include their subdirs, so that all levels are "connected":
<code text>
<syntaxhighlight lang="text">
# aa/data/kdeutils/CMakeLists.txt
# aa/data/kdeutils/CMakeLists.txt
add_subdirectory(kdingus)
add_subdirectory(kdingus)
</syntaxhighlight>
</syntaxhighlight>
and
and
<code text>
<syntaxhighlight lang="text">
# aa/data/kdeutils/kdingus/CMakeLists.txt
# aa/data/kdeutils/kdingus/CMakeLists.txt
add_subdirectory(pics)
add_subdirectory(pics)
Line 98: Line 98:


Assume now that KDingus is an extragear app, thus having this structure in the repository:
Assume now that KDingus is an extragear app, thus having this structure in the repository:
<code text>
<syntaxhighlight lang="text">
/trunk/extragear/utils/
/trunk/extragear/utils/
     kdingus/
     kdingus/
Line 107: Line 107:
</syntaxhighlight>
</syntaxhighlight>
If the languages <tt>aa</tt> and <tt>bb</tt> have prepared localized splashes, the lbundle will be stored within KDingus' data like this:
If the languages <tt>aa</tt> and <tt>bb</tt> have prepared localized splashes, the lbundle will be stored within KDingus' data like this:
<code text>
<syntaxhighlight lang="text">
/trunk/extragear/utils/
/trunk/extragear/utils/
     kdingus/
     kdingus/
Line 132: Line 132:


Our KDingus may install its splash screen by specifically instructing the image file to be installed. The installation instruction would then reside in the <tt>CMakeLists.txt</tt> on the same level as the image file:
Our KDingus may install its splash screen by specifically instructing the image file to be installed. The installation instruction would then reside in the <tt>CMakeLists.txt</tt> on the same level as the image file:
<code text>
<syntaxhighlight lang="text">
kdingus/
kdingus/
     pics/
     pics/
Line 139: Line 139:
</syntaxhighlight>
</syntaxhighlight>
and would contain something like:
and would contain something like:
<code text>
<syntaxhighlight lang="text">
install(FILES kdingus-splash.png
install(FILES kdingus-splash.png
         DESTINATION ${DATA_INSTALL_DIR}/kdingus/pics)
         DESTINATION ${DATA_INSTALL_DIR}/kdingus/pics)
</syntaxhighlight>
</syntaxhighlight>
In that case, the corresponding <tt>CMakeLists.txt</tt> for out-of-source lbundle (in <tt>aa</tt> language data directory), in the same relative position, would contain:
In that case, the corresponding <tt>CMakeLists.txt</tt> for out-of-source lbundle (in <tt>aa</tt> language data directory), in the same relative position, would contain:
<code text>
<syntaxhighlight lang="text">
install(FILES l10n/aa/kdingus-splash.png
install(FILES l10n/aa/kdingus-splash.png
         DESTINATION ${DATA_INSTALL_DIR}/kdingus/pics/l10n/aa)
         DESTINATION ${DATA_INSTALL_DIR}/kdingus/pics/l10n/aa)
Line 152: Line 152:


If there are more images, KDingus may very well install the whole <tt>pics/</tt> subdirectory using single install instruction in the <tt>CMakeLists.txt</tt> one level above:
If there are more images, KDingus may very well install the whole <tt>pics/</tt> subdirectory using single install instruction in the <tt>CMakeLists.txt</tt> one level above:
<code text>
<syntaxhighlight lang="text">
kdingus/
kdingus/
     CMakeLists.txt
     CMakeLists.txt
Line 162: Line 162:
</syntaxhighlight>
</syntaxhighlight>
which would look like:
which would look like:
<code text>
<syntaxhighlight lang="text">
install(DIRECTORY pics
install(DIRECTORY pics
         DESTINATION ${DATA_INSTALL_DIR}/kdingus
         DESTINATION ${DATA_INSTALL_DIR}/kdingus
Line 174: Line 174:


To install icons in full accordance with the specs is not exactly trivial, so KDE provides a custom CMake macro for application maintainers to use when installing icons. Such spec-conformant icons will look like:
To install icons in full accordance with the specs is not exactly trivial, so KDE provides a custom CMake macro for application maintainers to use when installing icons. Such spec-conformant icons will look like:
<code text>
<syntaxhighlight lang="text">
kdingus/
kdingus/
     icons/
     icons/
Line 184: Line 184:
</syntaxhighlight>
</syntaxhighlight>
and can be recognized by the initial prefix-size pattern. To install them, <tt>CMakeLists.txt</tt> will contain a terse instruction like this:
and can be recognized by the initial prefix-size pattern. To install them, <tt>CMakeLists.txt</tt> will contain a terse instruction like this:
<code text>
<syntaxhighlight lang="text">
kde4_install_icons(${DATA_INSTALL_DIR}/kdingus/icons)
kde4_install_icons(${DATA_INSTALL_DIR}/kdingus/icons)
</syntaxhighlight>
</syntaxhighlight>
Line 190: Line 190:


To properly install localized versions of such icons, the structure of the lbundle should be:
To properly install localized versions of such icons, the structure of the lbundle should be:
<code text>
<syntaxhighlight lang="text">
...
...
l10n/
l10n/
Line 202: Line 202:
</syntaxhighlight>
</syntaxhighlight>
regardless if out-of-source or in-source, and the final <tt>CMakeLists.txt</tt> should use the same instruction as for the original icons, but with language code as second argument:
regardless if out-of-source or in-source, and the final <tt>CMakeLists.txt</tt> should use the same instruction as for the original icons, but with language code as second argument:
<code text>
<syntaxhighlight lang="text">
kde4_install_icons(${DATA_INSTALL_DIR}/kdingus/icons aa)
kde4_install_icons(${DATA_INSTALL_DIR}/kdingus/icons aa)
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 21:12, 29 June 2011

Localizing Non-Text Resources
On Localization   Concepts
Prerequisites   Subversion Ops
Related Articles   Lbundle Checker
External Reading   CMake Documentation

Non-Text Resources To Localize?

In most introductory texts on localization, it will be noted that localization doesn't mean only translation of text, but that other resources too may need to be localized. Starting from KDE 4.1, any external content that a KDE application uses may be localized in a non-intrusive manner.

Typical candidate for localization is text embedded in images: on icons, splash screens, sidebars. Even when the image contains no text, it may be culturally geared towards English-speaking users, and a better locale analogy to achieve the same impact may exist.

Another example would be a set of sound files containing spoken English.

Localization Bundles

Think of an installed KDE application. Its resources that one may want to localize will probably reside in share/ directory of installation prefix. For example, the splash screen of KDingus may be installed like this:

/.../share/kdingus/
    pics/
        kdingus-splash.png

Now, we have prepared the localized splash screen for language aa. Two things need to happen for the localized version to be shown to the user.

First, the localized splash must be installed in l10n/aa subdirectory of the directory where the original splash resides, and with the same name:

/.../share/kdingus/
    pics/
        kdingus-splash.png
        l10n/
            aa/
                kdingus-splash.png

Localized resources organized in this way are called localization bundles, or lbundles for short.

Second, KDingus' code has to fetch the splash screen in one of several standard ways. For example, if KStandardDirs::locate() is used, then it will automatically return the localized resource if there. If the code assembles the path to the resource manually, then passing the finalized path through KLocale::localizedFilePath() will achieve the same effect. (You are reading this in order to be able to point the programmer in the right way, should you discover that the resource is not localizable as is.)

Let's now see how lbundles are supposed to be organized in the repository, so that they get installed correctly.

Inside The Repository

KDE traditionally has two distinct ways of distributing localized data. For the core KDE modules, the localized data is installed by the respective language packs themselves, rather than bundled with the code (which is the case, e.g. for Gnome modules). For non-core modules, e.g. the extragear, applications themselves distribute the localized data, that is bundled with the code.

This dichotomy, which the translations (PO files) follow, necessarily reflects itself on non-text resources as well. Therefore, there are two organizational types of lbundles:

out-of-source
lbundles for core modules, residing in respective language directories, and installed by the language pack
in-source
lbundles for non-core modules, kept within the application directories and installed by the application itself

Out-of-Source Lbundles

With the current structure of l10n sections of KDE repository, out-of-source boundles are stored within each language's data subdirectory. It is totally up to the language pack how it wants to install the contained lbundles to match the requested installation structure, but the recommendation would be as follows.

Continuing with the KDingus example from above, assuming that it is an app within kdeutils module (i.e. one of the core modules, to which out-of-source lbundles apply). The location of its splash screen in the repository may be as follows:

/trunk/KDE/kdeutils/
    kdingus/
        CMakeLists.txt
        pics/
            CMakeLists.txt
            kdingus-splash.png

where CMakeLists.txt will contain the installation instructions for the splash image. Then, language aa could store the localized splash like this:

/trunk/l10n-kde4/aa/data/kdeutils/
    CMakeLists.txt
    kdingus/
        CMakeLists.txt
        pics/
            CMakeLists.txt
            l10n/
                aa/
                    kdingus-splash.png

Observe that the structure of aa/data/kdeutils follows that of the kdeutils module itself, only ending with an l10n/aa lbundle subdirectory. This has advantages that will become apparent later.

The CMakeLists.txt files in language subdirectory, except the last one, are there only to include their subdirs, so that all levels are "connected":

# aa/data/kdeutils/CMakeLists.txt
add_subdirectory(kdingus)

and

# aa/data/kdeutils/kdingus/CMakeLists.txt
add_subdirectory(pics)

The final CMakeLists.txt is the one that should really install the lbundle. It should match the installation instructions of the original resource, and some typicall examples are given below. Also, exactly which CMakeLists.txt is the final one (how deep in subdirectory structure), depends on exact installation instructions.

In-Source Lbundles

Apps outside of core modules have to fetch the PO files from language folders, because they must distribute them bundled with the application package. So far this has shown not to be quite straightforward for application maintainers. This is why the lbundles intended for these apps are to be kept within the app itself, i.e. in-source: non-text resources that need localization should be infrequent, so maintainers shouldn't be burdened by yet another set of protocols to follow wrt. l10n.

Assume now that KDingus is an extragear app, thus having this structure in the repository:

/trunk/extragear/utils/
    kdingus/
        CMakeLists.txt
        pics/
            CMakeLists.txt
            kdingus-splash.png

If the languages aa and bb have prepared localized splashes, the lbundle will be stored within KDingus' data like this:

/trunk/extragear/utils/
    kdingus/
        CMakeLists.txt
        pics/
            CMakeLists.txt
            kdingus-splash.png
            l10n/
                aa/
                    kdingus-splash.png
                bb/
                    kdingus-splash.png

Before committing the localized data in this scenario, the language coordinator should inform the maintainer of KDingus. Especially when it is the first localized version of a particular original resource, i.e. there is a need to create the l10n/ subdirectory itself.

The installation instructions for the lbundle are now the responsibility of the app maintainer. But given that he knows his app's CMakeLists.txt files, it should be fairly straightforward for the maintainer to add additional instructions. Of course, a patch from a techy-minded translator will not hurt either.

CMake Installation Instructions

There are several characteristic ways in which KDE apps install their resources using CMake, the build system of KDE4. These are presented here, with the counterparts to install out-of-source or in-source lbundles.

Specific Files

Our KDingus may install its splash screen by specifically instructing the image file to be installed. The installation instruction would then reside in the CMakeLists.txt on the same level as the image file:

kdingus/
    pics/
        CMakeLists.txt
        kdingus-splash.png

and would contain something like:

install(FILES kdingus-splash.png
        DESTINATION ${DATA_INSTALL_DIR}/kdingus/pics)

In that case, the corresponding CMakeLists.txt for out-of-source lbundle (in aa language data directory), in the same relative position, would contain:

install(FILES l10n/aa/kdingus-splash.png
        DESTINATION ${DATA_INSTALL_DIR}/kdingus/pics/l10n/aa)

Complete Directories

If there are more images, KDingus may very well install the whole pics/ subdirectory using single install instruction in the CMakeLists.txt one level above:

kdingus/
    CMakeLists.txt
    pics/
        kdingus-splash.png
        kdingus-foo.png
        kdingus-bar.png
        ...

which would look like:

install(DIRECTORY pics
        DESTINATION ${DATA_INSTALL_DIR}/kdingus
        PATTERN .svn EXCLUDE)

The corresponding CMakeLists.txt in out-of-source lbundle, again in same relative position, would then contain exactly the same instruction (providing the tree structure is as in the example for out-of-source lbundles).

Furthermore, if the lbundles are in-source and the complete directory is installed like this, then the application maintainer needn't modify existing CMakeLists.txt at all to accomodate installation of lbundles.

Icons

To install icons in full accordance with the specs is not exactly trivial, so KDE provides a custom CMake macro for application maintainers to use when installing icons. Such spec-conformant icons will look like:

kdingus/
    icons/
        CMakeLists.txt
        hi16-app-kdingus.png
        hi32-app-kdingus.png
        hi48-app-kdingus.png
        ...

and can be recognized by the initial prefix-size pattern. To install them, CMakeLists.txt will contain a terse instruction like this:

kde4_install_icons(${DATA_INSTALL_DIR}/kdingus/icons)

which selects true installation paths and modifies icon file names when installed.

To properly install localized versions of such icons, the structure of the lbundle should be:

...
l10n/
    CMakeLists.txt
    aa/
        CMakeLists.txt
        hi16-app-kdingus.png
        hi32-app-kdingus.png
        hi48-app-kdingus.png
        ...

regardless if out-of-source or in-source, and the final CMakeLists.txt should use the same instruction as for the original icons, but with language code as second argument:

kde4_install_icons(${DATA_INSTALL_DIR}/kdingus/icons aa)

(the above-level CMakeLists.txt files just include their subdirectories for proper connection, as usual).

Keeping Localized Resources In Sync

To localize and prepare an lbundle for installation is the main part of the job, but same as with messages in PO files, at some point later the original resource may be modified, moved, or deleted. To be able to react accordingly, there is a special script on translator's disposal to track the state of lbundles against the original. Head to its article for further instructions.

Be sure to keep the "source" files for non-text resources in the repository too. For some resources, the source will be one of the files in the lbundle itself; e.g. for an icon, this is its scalable variant in SVG vector format (as opposed to different-sized bitmap PNGs), which is also installed. If this is not the case, keep the files needed to produce the final localized resource somewhere in the internal/ subdirectory of your language directory. This subdirectory is specifically excluded from packaging, so in it you can keep all internal files pertinent to localization effort of your team.