Localization/Concepts/Non Text Resources: Difference between revisions

    From KDE TechBase
    (Initial revision.)
     
    m (Text replace - "<code text>" to "<syntaxhighlight lang="text">")
     
    (2 intermediate revisions by 2 users not shown)
    Line 3: Line 3:
    section=[[Localization#Concepts|Concepts]]|
    section=[[Localization#Concepts|Concepts]]|


    name=Localization of Non-Text Resources|
    name=Localizing Non-Text Resources|


    prereqs=[[Localization/Tools/Subversion|Subversion Ops]]|
    prereqs=[[Localization/Tools/Subversion|Subversion Ops]]|
    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/
             kdingus-splash.png
             kdingus-splash.png
    </code>
    </syntaxhighlight>
    Now, we have prepared the localized splash screen for language <tt>aa</tt>. Two things need to happen for the localized version to be shown to the user.
    Now, we have prepared the localized splash screen for language <tt>aa</tt>. Two things need to happen for the localized version to be shown to the user.


    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 37: Line 37:
                 aa/
                 aa/
                     kdingus-splash.png
                     kdingus-splash.png
    </code>
    </syntaxhighlight>
    Localized resources organized in this way are called ''localization bundles'', or ''lbundles'' for short.
    Localized resources organized in this way are called ''localization bundles'', or ''lbundles'' for short.


    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 66: Line 66:
                 CMakeLists.txt
                 CMakeLists.txt
                 kdingus-splash.png
                 kdingus-splash.png
    </code>
    </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 78: Line 78:
                     aa/
                     aa/
                         kdingus-splash.png
                         kdingus-splash.png
    </code>
    </syntaxhighlight>
    Observe that the structure of <tt>aa/data/kdeutils</tt> follows that of the <tt>kdeutils</tt> module itself, only ending with an <tt>l10n/aa</tt> lbundle subdirectory. This has advantages that will become apparent later.
    Observe that the structure of <tt>aa/data/kdeutils</tt> follows that of the <tt>kdeutils</tt> module itself, only ending with an <tt>l10n/aa</tt> lbundle subdirectory. This has advantages that will become apparent later.


    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)
    </code>
    </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)
    </code>
    </syntaxhighlight>
    The final <tt>CMakeLists.txt</tt> 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 [[#CMake Installation Instructions|below]]. Also, exactly which <tt>CMakeLists.txt</tt> is the final one (how deep in subdirectory structure), depends on exact installation instructions.
    The final <tt>CMakeLists.txt</tt> 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 [[#CMake Installation Instructions|below]]. Also, exactly which <tt>CMakeLists.txt</tt> is the final one (how deep in subdirectory structure), depends on exact installation instructions.


    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 105: Line 105:
                 CMakeLists.txt
                 CMakeLists.txt
                 kdingus-splash.png
                 kdingus-splash.png
    </code>
    </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 119: Line 119:
                     bb/
                     bb/
                         kdingus-splash.png
                         kdingus-splash.png
    </code>
    </syntaxhighlight>


    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 <tt>l10n/</tt> subdirectory itself.
    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 <tt>l10n/</tt> subdirectory itself.
    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/
             CMakeLists.txt
             CMakeLists.txt
             kdingus-splash.png
             kdingus-splash.png
    </code>
    </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)
    </code>
    </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)
    </code>
    </syntaxhighlight>


    === Complete Directories ===
    === Complete Directories ===


    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 160: Line 160:
             kdingus-bar.png
             kdingus-bar.png
             ...
             ...
    </code>
    </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
             PATTERN .svn EXCLUDE)
             PATTERN .svn EXCLUDE)
    </code>
    </syntaxhighlight>
    The corresponding <tt>CMakeLists.txt</tt> 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).
    The corresponding <tt>CMakeLists.txt</tt> 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).


    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 182: Line 182:
             hi48-app-kdingus.png
             hi48-app-kdingus.png
             ...
             ...
    </code>
    </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)
    </code>
    </syntaxhighlight>
    which selects true installation paths and modifies icon file names when installed.
    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:
    To properly install localized versions of such icons, the structure of the lbundle should be:
    <code text>
    <syntaxhighlight lang="text">
    ...
    ...
    l10n/
    l10n/
    Line 200: Line 200:
             hi48-app-kdingus.png
             hi48-app-kdingus.png
             ...
             ...
    </code>
    </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)
    </code>
    </syntaxhighlight>
    (the above-level <tt>CMakeLists.txt</tt> files just include their subdirectories for proper connection, as usual).
    (the above-level <tt>CMakeLists.txt</tt> files just include their subdirectories for proper connection, as usual).



    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.