i18n Semantics Cheat Sheet

For quite some time when applying formatting in GUI development one either needs to apply directly visual HTML markup or some sort of odd plain text formatting. Thankfully the internationalization system supports more sensible ways of doing this, in particular semantic markup rather than visual markup.

Let me illustrate the difference quickly. Say you have a title in HTML and you want the title to have a special format. The visual way to go about this woud be:

<b><em>This is a Supreme Title</em></b>

the semantic way however looks like:

<h1>This is a Supreme Title</h1>

In a semantics markup you are not defining how something looks, but what it is, the visual appearance of this thing is defined somewhere else. Just like in the example above, if you use the h1 tag you can easily format all primary headers in a unified fashion using CSS, if you use the visual tags and want to change something you will have to manually walk through all your HTML code and change it.

Now, the very same problem applies to strings you might want to use in your code. For instance you might have something like that in your code:

i18n("I deleted <qt><b><em>%1</em></b></qt> muhahaha!", a);

Should you not have a lot to do with i18n or l10n, a translator would get this string in most editors exactly like that (i.e. including your markup). There are multiple reasons why this is bad. For one, the translator could accidentally break the markup (since he needs to copy it into the translated string), for another, the translators do not know the context of this message and will have a hard time translating it properly. Additionally of course the same problem applies as with HTML and changing the appearance.

The awesome i18n/l10n crew hence came up with a very nice system to solve this using semantics markup.

Applying semantics markup the above string could look like this to provide both context for the translators and useful default formatting for the file name that will be inserted at %1:

i18nc("@info", "I deleted <filename>%1</filename> muhahaha!", a);

If you are developing software using the KDE platform then please checkout the detailed semantics page and use semantics to make our translators’ life easier and your formatting more coherent with the rest of the system.

We at Kubuntu certainly endorse i18n semantics and apply it whenever possible in our software, due to that we created a cheat sheet  that helps with remembering the various markups tags .

[Also available as SVG]

5 thoughts on “i18n Semantics Cheat Sheet

  1. That looks very interesting, the more context translators get, the better quality translations we can deliver. Good work KDE i18n team!

    I’ve got some questions the answer of which could not find on the wiki page, or I might have overlooked.

    In short, what do the messages with these markup in the code look like for translators (i.e. in the .pot template)?

    I could imagine that something like i18nc(“@action:button”, “Move”); will end up with “@action:button” put in a msgctxt field, but I cannot picture where or whether the will appear in something like i18nc(“@info”, “%1 does not exist”, fname);


  2. i18nc(“@action:button”, “Move”);
    translates to:
    msgctxt “@action:button”
    msgid “Move”

    i18nc(“@info”, “%1 does not exist”, fname);
    msgctxt “@info”
    msgid “%1 does not exist”

    i18nc(“@info”, “%1 does not exist”, fname);
    msgctxt “@info”
    msgid “%1 does not exist”

    So the tags really just replace the formatting tags, you would apply otherwise, with semantic tags to convey context for the translators *and* produce unified formatting (e.g. maybe expands to at runtime).

    • Thanks for the reply, that clarifies things. However, it seems that WordPress got rid of the markup on my comment.

      What I meant is, what would i18nc(“@info”, “%1 does not exist”, fname); look like to translators?

      (I hope the extra whitespace helps with WP not eating the markup)

  3. Silly wordpress -.- Maybe it does not eat proper encoded input…

    i18nc(“@info”, “<filename>%1</filename> does not exist”, fname);


    msgctxt “@info”
    msgid “<filename>%1</filename> does not exist”
    msgstr “”

    In words: the context becomes msgctxt and the string verbatim becomes msgid, resolution from filename tag to actual formatting occurs at runtime

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s