For Developers‎ > ‎Design Documents‎ > ‎

UI Localization (aka Translations)

If you find an error in an existing translation, please file a bug using the translation template.  CC "".  Thank you!
Chromium uses GRIT for managing its translated strings in grd/grdp files.

    How to add a string

    1. Add the string to the grd file (generated_resources.grd, webkit_strings.grd, chromium_strings.grd or google_chrome_strings.grd).  
    2. **Very important info on writing message meanings and descriptions
    3. Surround the string with an appropriate <if> clause to ensure that it's only included it on platforms where it's actually used (e.g. Mac and Linux). Strings used on all platforms can omit the <if> clause.
    4. The next time you build the solution, this will automatically add the en-US string.
    5. In your code, include ui/base/l10n/l10n_util.h and chrome/grit/generated_resources.h.
    6. To get the string, use l10n_util::GetStringUTF16.  Alternately, you can use l10n_util::GetStringFUTF16 which will replace placeholders $1 through $4 with the extra arguments of GetStringFUTF16.  Note that we generally prefer to use UTF-16 encoded strings for user-visible text.
    7. Deal with message placeholder content
      1. Hey <ph name="USER">$1<ex>Joe</ex></ph>, you have <ph name="NUMBER"><ex>10</ex>$2</ph> messages.
    The base messages (en-US) will be translated to supported language locales by an internal Google Localization process, and the resulting translations are submitted to the chromium .xtb files after a few weeks (see the Workflow section below).

    How to add a screenshot
    1. Follow the steps at to add a screenshot to correspond with your strings.
    2. **Screenshots provide in-context information regarding how/where your string is used and provides an additional supplement to your strings meanings and descriptions.

    How to add an Android/Java string

    1. Add the string to the grd file in the Java folder (e.g. content/public/android/java/strings/android_content_strings.grd).  Strings should be named in all caps with the prefix IDS_.  For example: IDS_MY_STRING.
    2. **Very important info on writing good message meanings and descriptions.
    3. At build time, an Android-style strings.xml file will be generated in the out directory.
    4. You can reference these strings in Java code using the standard R.string.my_string syntax, or in Android layouts using @string/my_string.  Note: the name is lowercase and the IDS_ prefix is stripped.
    5. Deal with special characters,
    6. Deal with message placeholder content
      1. Hey <ph name="USER">%1$s<ex>Joe</ex></ph>, you have <ph name="NUMBER"><ex>10</ex>%2$d</ph> messages.
    The base messages (en-US) will be translated to supported language locales by an internal Google Localization process, and the resulting translations are submitted to the chromium .xtb files after a few weeks (see the Workflow section below).

    How to add a new grd(p) file

    • This should be rare. We want to be very careful about expanding the number of grd(p) files in our source tree.
    • New grdp files need to be referenced from a parent grd file.
    • New grd files need to be added to /src/tools/gritsettings/resource_ids, IF the resources will be referenced from C++ code (won't compile without - this doesn't impact translation process).
    • New grd files need to have a rule added to /src/chrome/chrome_resources.gyp, IF the resources will be referenced from C++ code (won't compile without - this doesn't impact translation process).
      • During 'gclient sync' these grit rules are run, and your grd's '.h' file will be generated.  This file should be included by any .cc file that references your strings.
    • New grd files need to be added to /src/tools/gritsettings/translation_expectations.pyl (or <message>s won't be translated).
    • If your new grd(p) will result in new XTB files after translation, you must commit placeholder .xtb files, or Chrome won't compile. The placeholders need to have a basic xml structure.
      •  Here's a handy way to create the xtbs: 
    > for lang in fr de en-GB etc; do echo '<?xml version="1.0" ?><!DOCTYPE translationbundle><translationbundle lang="'$lang'"></translationbundle>' > foo_strings_$lang.xtb; done
    • If your new grd will NOT be translated (set in translation_expectations.pyl and no XTB placeholder files required above), there is very minimal XML content required in your grd.  I wanted to document an example here:
    <?xml version="1.0" encoding="utf-8"?>
    This file contains all "about" strings.  It is set to NOT be translated, in translation_expectations.pyl.  en-US only.
    <grit base_dir="." latest_public_release="0" current_release="1"
          source_lang_id="en" enc_check="möl">
        <output filename="grit/about_strings.h" type="rc_header">
          <emit emit_type='prepend'></emit>
      <release seq="1" allow_pseudo="false">
        <messages fallback_to_english="true">
          <message name="IDS_NACL_DEBUG_MASK_CHOICE_DEBUG_ALL">
            Debug everything.

    Workflow for how strings get translated for Google Chrome

    1. Strings get added to a .grd(p) file in en-US.
    2. [BlackCloudOfMagic] Translators are provided with the new strings
    3. <internal link> Further internal detail about the translation process here.  </internal link>
    4. [BlackCloudOfMagic] Translations are created and stored in .xtb files
    5. Changes to .xtb files are submitted to the Chromium source tree


        Strings are included on all platforms by default and will needlessly increase the download size if not used.  It's important to judiciously surround strings with an appropriate <if> clauses  to ensure that they are only included on the platforms where they're actually used.

    Using message meanings to disambiguate strings

    By default, existing translations are reused when a new message matches an existing one. This can pose a problem when the contexts or restrictions (e.g. length, capitalization) for the two messages differ. To ensure that matching messages are translated separately, you may add a meaning attribute:
    <message name="IDS_TRANSLATE_BUBBLE_UNKNOWN_LANGUAGE"  meaning="Noun to use in place of a language name in part of a translate bubble message.">

    In this example, we'd like to apply the capitalization rules for language names (e.g. "Unknown" in English, "sconosciuto" in Italian), so we cannot reuse the existing translations of "Unknown". In general, the meaning attribute should specify:
    • The nature of the message (e.g. action / description / accessibility / ID) 
    • The nature of the word (e.g noun / adjective / verb). For example, "click" may be translated to "clic" or "clique" depending on context.
    • Any constraints (e.g. length) 
    • The homonymy disambiguation
    Messages with differing content or meaning attributes will always be translated separately. However, the meaning attribute should only be used to trigger separate translation; the general context for a message should be provided with the description attribute. 

    Writing good message descriptions

    Editor's note: See also the `meaning` attribute above. No matter how good a `description` you wrote, if your string matches an existing one, that existing translation will be re-used by default, and your `description` will be completely ignored.

    The message description added to the grd(p) file with your string is currently the only context our translators receive when translating UI strings.  We would all like to do our best to ensure that the user experience with Chromium is as natural as possible, no matter the language.  So let's try to give the translators as much clear context as possible.  The following includes what information is needed in a good description, placeholder information, max chars limit, as well as some examples of what these should look like.

    IE: (The translator would only see what is in bold)

    <message name="IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED" desc="In Title Case: Title of the bubble after bookmarking a page.">
        Bookmark Added!

    Why do we need message descriptions?

    The problem
    : Currently, the translators often have no context when they translate -- they see each string in isolation and in random order, so they don't even know which feature it could be associated with, where it might appear on a page, or what action it triggers. Without context, they can't know how to translate appropriately.

    The solution
    : Message descriptions can help provide context and other essential information, which in turn increases the speed, accuracy, and quality of translations, and, ultimately, improves user satisfaction.

    What information should I provide in the message description?

    • Where is the text located? (e.g., button, title, link, pull-down menu)
    • What triggers the message and/or what is the result? What page or text comes before and after?
    • What do the placeholders stand for? Will this message replace a placeholder in another message? Do they need to be arranged in a certain way?
    • Is this a verb or a noun? If an adjective, what does it refer to?
    • Who is the message intended for?
    • Are there any specific character limits that must not be exceeded? (e.g., for mobile products where UI space is restricted)
    How should line breaks be dealt with? Are there character limitations per line? Keep in mind that the translators will not know the product as well as you do, and they work on multiple products and projects. Also, they're not engineers. So make sure that the description will be understandable by a more general audience and doesn't contain too much technical detail. Imagine giving this description out of context to a person not on your project, say your Aunt. Would they still understand it?

    What does this look like in practice?

    Source Message: "US city or zip"
    Original Description: The message is shown in gray in the empty search box for a movie showtimes location. The content of the message should be localized by country to mean city or postal code (or simply city). Its purpose is to tell the user what kind of input will produce results.
    Comment: This is very informative description, that clearly explains the context and also gives specific instructions on how the message should be adapted for another (non-US) locale.

    Source Message: "Apply"
    Original Description: Button label for the apply button.
    Comment: Provides the context, but the translator will also need to know what is going to be applied.
    Better Description: Button label; clicking the button will apply the selected label names to the message thread.

    Source Message: "read Gmail attachment previews"
    Original Description: Displayed in the Settings panel which lists the various permissions that this app requires. Must start with a lowercase.
    Comment: Providing the translators with instructions is good, but they also need to know the reason. Why does this need to be lowercase? Different languages have different conventions around capitalization, so we need to know the reason behind the instruction. Also, what is the context? Will any text come before or after?
    Better Description: Displayed in the Settings panel which lists the various permissions that this app requires. Should start with a lowercase because it will be listed with other permissions, all separated by a comma.

    Source Message: "Zoom"
    Original Description: The "Zoom" menu command. It brings up help on how to zoom. Try to limit menu commands to 10 characters.
    Comment: Very nice description in Mobile Maps. Tells us what it does, what it triggers and what the character limit should be to keep consistency across similar messages.

    Source Message: "We could not send your message. A space alien ate it. Please try again in a few minutes."
    Comment: Should we translate the "space alien" part, or should it be changed to an appropriate equivalent for that locale? Should it be funny? By default, the translators will probably translate the message literally, so if they should get creative, the message description should let them know that.
    Better Description: An error message. This reason given is meant to be funny, so please use an appropriate silly reason for the error, and not necessarily a direct translation.

    Subpages (1): Mac Notes