the Chromium logo

The Chromium Projects

GRIT User's Guide

Getting Started

Your chromium checkout contains GRIT. Run //tools/grit/grit.py for help. GRIT integrates easily with GYP, see examples.

It's a good idea to run GRIT's unit tests to check that your installation is OK. Run grit unit, which should print the result of the tests, ending with OK.

Creating a Blank .grd File

You can run grit newgrd to create a new .grd file with no content but a skeleton to start you off with. Alternatively, copy a pre-existing .grd file as a starting point.

If you're looking to convert an existing .rc file to the .grd format, see the section Converting Your RC File to GRIT Format below.

For GRIT to recognize the new .grd file in Chromium, there needs to be a new entry for it in //tools/gritsettings/resource_ids.spec. See the header in that file and also //tools/gritsettings/README.md for details.

Adding Resources

Includes (e.g. GIF, BMP, ICO etc.)

Here are the steps to add an included resource, e.g. a GIF or BMP. Note that this does not include HTML templates, those are considered "structures" (see section below).

  1. Open your project's .grd file.
  2. Find the latest <release> element (the one with the highest number in the 'seq' attribute). These elements group together resources that are part of the same public release. Note that some projects always use just a single <release> element.
  3. Under that <release> element, find an <includes> element.
  4. Add an <include> element to the end of that <includes> element. The <include> element has the following attributes, and no body:
    • type: This goes into the RC file verbatim, so it is the resource type string you want to use for this include, e.g. 'GIF'
    • name: This is the textual ID of this resource. GRIT will generate a #define in the resource header file for this textual ID, so you can use it in your code as long as you include the resource header file.
    • file: This is the path to the file to include, relative to the .grd file

i18n Messages

Note: readers are here advised to also read UI Localization (aka Translations).

Similarly for includes (above), find the latest <release> element, then find a <messages> node under that. Add an i18n <message> node under it. i18n <message> nodes have the following attributes:

The body of the <message> element is the text of the message. Inline in the text, you should use <ph> elements to indicate non-translatable sections (human or automatic translators will leave the <ph> element content alone - they will not try to translate it).

The <ph> element has a single attribute, 'name', which you use to give the placeholder a name (which must be uppercase and should usually be descriptive, e.g. USER_NAME or TIME_REMAINING). Apart from the non-translatable text, the <ph> element can contain a single <ex> element containing an example of what the placeholder could be replaced with. This is shown to the translators, and could be e.g. "Jói" for a placeholder with a name of USER_NAME.

For example:

<message name="ID_OF_MESSAGE">
  Hello <ph name="USER_NAME">%s<ex>Joi</ex></ph>, how are you today?
</message>

GRIT allows you to use messages that begin or end with whitespace. You need to put ''' (that's three single quotes, like Python's triple quotes) before leading whitespace and after trailing whitespace, because the default is to strip leading and trailing whitespace from messages.

Example

Given a message that looked like the following in the RC file:

IDS_EMAIL_ESTIMATE "%d of about %d emails - "

This should be represented as the following in the .grd file:

<message name="IDS_EMAIL_ESTIMATE"
internal_comment="TODO make the placeholders reorderable so the translators can rearrange things"
desc="Shown at top of results page">
  <ph name="ITEM">%d<ex>1</ex></ph> of about <ph name="ESTIMATED_TOTAL">%d<ex>130</ex></ph> emails - '''
</message>

Let's walk through what's going on here:

Structures (menus, dialogs, HTML templates, etc.)

Any resource that is not a simple message and contains one or more translateable parts needs to be defined as a <structure> element. Similar to includes and messages (see above), you find the latest <release> element, find a <structures> node under that, and add a<structure> node to it. <structure> nodes have the following attributes:

Note that GRIT only has support for symbolic resource IDs (IDs that are preprocessor defines that are given a numeric value) and not for string literal resource IDs. The latter are suboptimal, since they increase the size of the resources. If the .rc file you point to uses string literal resource IDs, you will have to #define those string literals manually to use those resources. The recommended approach is to only use symbolic resource IDs.

Splitting Resources into Multiple Files

It is possible to have 'sub' grd files, the ones with .grdp extension.

They can be include in .grd files using the <part> element. See this example.

Outputs and Translations

By calling grit build you make GRIT build RC files and resource header files from a .grd file. This section details how to specify which files to output, how to specify the translation files to use, and how to use conditional output of resources.

Specifying Output Files and Translation Files

The way you specify which files grit build should output is using an <outputs> section in the .grd file. NOTE: The <outputs> section should be put at the top of the .grd file, as this can speed up GRIT when used with build systems that scan the .grd file for dependencies.

To specify the translation files to use, you use a <translations> section that points to each of the .xtb (translation bundle) files containing the translations.

The top of your .grd file, including the <outputs> and <translations> sections might look like this:

<?xml version="1.0" encoding="UTF-8"?>
<grit latest_public_release="0" source_lang_id="en" current_release="1"
base_dir="../.." enc_check="möl">
<outputs>
  <output filename="resource.h" type="rc_header" />
  <output filename="en/generated_resources_en.rc" type="rc_all" lang="en" />
  <output filename="fr/generated_resources_fr.rc" type="rc_all" lang="fr" />
  <output filename="ja/generated_resources_ja.rc" type="rc_all" lang="ja" />
</outputs>
<translations>
  <file path="$TRANSLATIONS_FOLDER/fr.xtb" lang="fr" />
  <file path="$TRANSLATIONS_FOLDER/ja.xtb" lang="ja" />
</translations>
<!-- Remainder of .grd file -->
</grit>

Something to note here: The language code is included in the filename of each of the generated .rc files, even though it is already a component of the files' paths. This is recommended to ensure that the .res intermediary files which are generated by the RC compiler from the .rc files and then linked into the executable do not share the same filename (as they may all be built into one directory even if the GRIT output files are in separate directories).

Conditional Output of Resources

In an .rc file, it's common to use C preprocessor commands to control which parts of the file get output given the existence or values of C preprocessor defines. GRIT has this same capability, in addition to allowing output of resources to be conditional on which language is being output.

To use conditional output of resources, simply enclose some of your <message>, <structure> or <include> elements in an <if> element. The 'if' element has a single attribute 'expr', the contents of which are evaluated as a Python expression, and the resources within the 'if' element are only output if the result of that expression is true. Your Python expression has access to the following objects and functions:

Note that conditional output of resources only affects those output files of GRIT that determine which resources get linked into your executable, i.e. currently only the .rc files output. It has no effect on resource header files, or translation interchange files like .xmb files. This is desirable for several reasons, e.g. resource IDs stay the same regardless of conditional output, all messages always go to translation, etc.

Avoid unnecessary header includes

GRIT by default includes some header files (for example: atlres.h). In order to avoid these includes you can use the <emit> tag as a child of <output>. Doing this would replace all the includes with your customized includes. Including an empty <emit> tag makes GRIT include no header files in the generated resource file.

<output filename="resource.grh" type="rc_header">
<emit>#include "foo/bar.h"</emit>
</output>

GRIT Cookbook

This section documents some common "recipes" for getting things done using GRIT.

Getting Ready for Release

When you are about to release, you will probably want to make sure none of your messages get automatically pseudotranslated, i.e. you want to have 'grit build' fail if there are some missing translations. To achieve this goal, you simply add a allow_pseudo="false" attribute to your <release> node (this attribute is true by default), e.g.:

<release seq="1" allow_pseudo="false">
<!--
If GRIT finds a missing translation for any message or any part
of any structure within this element, it will fail rather than
create an automatic pseudotranslation.
-->
<messages>
  ...
</messages>
<structures>
  ...
</structures>
</release>

When you start working on your next release, leave everything inside that <release> element alone (or at least don't modify or add to it - OK to remove from it). Instead, create a new <release> element and put the resources you add to your new release inside that element. If you need to modify one of the existing resources, move it from the old release to the new release, and modify it within the new release.

Language-Specific Graphics (or Other Included Resources)

There is often a need to localize graphics, e.g. logos that have text on them. It's easy to tell GRIT to use different logos for different languages:

<!-- Other parts of .grd file snipped -->
<includes first_id="2048">
  <if expr="lang in \['de', 'en', 'es', 'fr', 'it'\]">
    <include type="GIF" name="IDR_LOGO" file="logo.gif" />
  </if>
  <if expr="lang == 'ja'">
    <include type="GIF" name="IDR_LOGO" file="ja_logo.gif" />
  </if>
  <if expr="lang == 'zh_cn'">
    <include type="GIF" name="IDR_LOGO" file="zh_cn_logo.gif" />
  </if>
</includes>
<!-- Other parts of .grd file snipped -->

Here we use the same logo for English and FIGS languages, and different logos for Japanese and Simplified Chinese.

Language-Specific Layout of Dialog Boxes

It's common for dialog boxes to require a different layout for languages other than English, as most languages are much more verbose than English (30-40% on average). Of course the best way to handle this is to make the dialog boxes for English roomy enough to account for all languages, but this is not always possible due to aesthetics or project constraints. Likewise, other structured resources, such as HTML templates, sometimes need to have locale-specific versions.

Although you could use a few <if> nodes to achieve something close to what you want, this would mean each of your different structured resource variants would need to be in English. It would be much more convenient to be able to have your variants in the target language (so that you can easily size e.g. the dialog correctly) yet pick up the source messages from the original structured resource. This is what the <skeleton> node is for.

Here's how you would use it:

<!-- Other parts of .grd file snipped -->
<structures first_id="4096">
  <!-- The file specified in the <structure> node is used except when one of the
  expressions in <skeleton> nodes is true. -->
  <structure type="dialog" name="IDD_DIALOG" file="structured_resources.rc">
    <!-- The variant_of_revision attribute is mandatory and intended to specify
    which source control revision number this skeleton variant is a variant of.
    Useful so that GRIT can automatically detect if you may need to update your
    skeleton (not implemented yet). -->
    <skeleton expr="lang == 'ja'" file="ja\\IDD_DIALOG\\IDD_DIALOG.rc" variant_of_revision="3" />
  </structure>
</structures>
<!-- Other parts of .grd file snipped -->

To help you work with variant skeletons, there is a tool grit resize that will output a Microsoft Visual Studio project file and an .rc file containing the dialogs you request in the language you request. See grit help resize for more details.

NOTE: The <skeleton> node currently only works for structures with type="dialog". Support for it can be added to other structure types but usually what you want for e.g. HTML structures can usually be accomplished more easily by using separate files and selecting between them with <if> nodes (see the above section).

Language-Specific Messages

Occasionally, there is a need for a message to have a different meaning in one language than it does in another. An example of this is that a Terms of Use document might have to have different clauses for the U.S. than it does for Germany. It's easy to give GRIT different variants of the same message to use for different languages:

<!-- Other parts of .grd file snipped -->
<messages first_id="10240">
  <if expr="lang != 'de'">
    <message name="IDM_TERMS_OF_USE" desc="Do not translate this message into German">
      Use this product at your own risk.
    </message>
  </if>
  <if expr="lang == 'de'">
    <message name="IDM_TERMS_OF_USE" desc="This message only needs to be translated into German">
      Use this product at your own risk, except as limited by German law.
    </message>
  </if>
</messages>
<!-- Other parts of .grd file snipped -->

There are a couple of things to note here:

Getting Translations of Strings in Images

You may have a bunch of images that contain some text, and wouldn't it be nice to be able to get that text translated along with everything else? You can do this by following this recipe:

<!-- ... -->
<includes first_id="1024">
  <!-- ... -->
  <include type="GIF" name="IDR_SUBMIT_BUTTON" file="submit_btn.gif" />
</includes>
<!-- ... -->
<messages>
  <!-- ... -->
  <if expr="False">
    <message name="IDM_MESSAGE_FOR_PICTURE_IDR_SUBMIT_BUTTON">
      Submit
    </message>
  </if>
</messages>
<!-- ... -->

The trick here is to match the message with the include by using a simple naming convention (the message node's 'name' is the include node's 'name' with IDM_MESSAGE_FOR_PICTURE* prefixed), and to prevent the message from getting included in your executable by putting it into an <if expr="False"> block (keep in mind that <if> blocks only affect output of resources to .rc files, and not to .xmb files or other translation interchange formats GRIT may support in the future).*

After the translators have finished their job, you'll be able to find your image's translated text in the .xtb file for the language(s) in question.

Translate by Example

In some cases, we have resources that difficult for a non-programmer to translate. An example is a date picture string, which might look like M'/'d YYYY. A useful thing to do here is to get the translator to translate an example of what the result of applying that format string might look like. Then as a programmer you can take the translated example and translate it back into a picture string. The recipe for this would be:

<!-- ... -->
<messages first_id="1024">
  <!-- ... -->
  <if expr="False">
    <message name="IDM_DATE_FORMAT_EXAMPLE_TO_TRANSLATE">
      6/6 2005
    </message>
  </if>
  <message translateable="false" name="IDM_DATE_FORMAT">
    M'/'d YYYY
  </message>
</messages>
<!-- ... -->

Here we add a message IDM_DATE_FORMAT_EXAMPLE_TO_TRANSLATE that gets sent for translation, but not added to your executable (because it's enclosed in an if-false block). The real resource is marked non-translatable, so it doesn't get sent for translation. Once the translators are done, you look for the message in the .xtb file, interpret the examples back into picture strings, and add them to your .grd file using conditional output to control which one gets used for which language:

<!-- ... -->
<messages first_id="1024">
  <!-- ... -->
  <if expr="False">
    <message name="IDM_DATE_FORMAT_EXAMPLE_TO_TRANSLATE">
      9/23 2005
    </message>
  </if>
  <if expr="lang == 'en'">
    <message translateable="false" name="IDM_DATE_FORMAT">
      M'/'d YYYY
    </message>
  </if>
  <if expr="lang == 'fr'">
    <message translateable="false" name="IDM_DATE_FORMAT"
    internal_comment="Translation of example was '23/09 2005'">
      dd'/'MM YYYY
    </message>
  </if>
</messages>
<!-- ... -->

Miscellaneous GRIT extensions and tips

GRIT has several other features you can use to help with localization.

In html files, it is common that the ref link needs to point to the localized page, for example,

http://www.example.com/support/myproduct?lang={language}

In order for the link to point to the correct language, when GRIT is generating the localized html files from the html template, we set the langparameter to an expandable GRIT variable GRITLANGCODE, so that it will be expanded to the correct langauge code.

In a struct node, enable the HTML template to use expandable variable by setting expand_variables attribute to "true". Here is an example.

<structure name="AFINTRO.HTML" encoding="utf-8" file="afintro.html"
type="tr_html" generateid="false" expand_variables="true"/>

In the html template, set the lang parameter of the link to GRITLANGCODE. Here is an example.

<a href="http://www.example.com/support/myproduct?lang=\[GRITLANGCODE\]"
target="_blank">Go to site</a>

Using expandable variable to generate HTML files for RTL languages

To enable GRIT to generate right-to-left (RTL) layout HTML files for RTL languages, we can use the special expandable variable GRITDIR.

In struct node, enable the HTML template to use expandable variables by setting the expand_variables attribute to "true".

<structure name="AFINTRO.HTML" encoding="utf-8" file="afintro.html"
type="tr_html" generateid="false" expand_variables="true"/>

In the HTML template, embed GRITDIR variable in the <html> tag. Here is an example.

<html style="width:29em; height:24em"
XMLNS:t="urn:schemas-microsoft-com:time" \[GRITDIR\]>

Using expandable variable to set the language attribute in product version information correctly in VS_VERSION_INFO of rc file

In order to have Language attribute of product version information show the correct language information for client application, the VS_VERSION_INFO section has to set the attributes using correct LCID and charset code. Again, we can use grit expandable variables to make life easier. Here is an example.

VS_VERSION_INFO VERSIONINFO
...
BEGIN
  BLOCK "StringFileInfo"
  BEGIN
    BLOCK "\[GRITVERLANGCHARSETHEX\]"
    BEGIN
      ...
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", \[GRITVERLANGID\], \[GRITVERCHARSETID\]
  END
END

Running processing after translation of structures

Sometimes, it may be necessary to run additional processing of a translated file <structure> after translation has occurred. To do this, use the run_command attribute on the structure element. To add the filename to the command, use %(filename)s. For instance, to run type on a file after it's been processed by grit, do:

<structure name="AFINTRO.HTML" encoding="utf-8" file="afintro.html"
type="tr_html" run_command="type %(filename)s"/>

Migrating Your Project

Converting Your RC File to GRIT Format

The grit rc2grd tool takes an existing RC file, which should be the RC file for the source language, and converts it into a .grd file.

Because of the way grit rc2grd works, a bit of preparation of the original RC file is required.

When you open up the .grd file, you will notice that some of your stringtable messages have been changed so that HTML code and printf orFormatMessage format specifiers have been replaced with placeholders (<ph> nodes). For all placeholders that were put in place of printf and FormatMessage format specifiers, the placeholder name starts as TODO_XXXX and the example is set to TODO. This allows you to go through the generated .grd file and replace the TODO_XXXX placeholder names with sensible names (ones that will help the translators) and the example text with an actual example of what might be put in place of this placeholder (for instance if the placeholder name is NUMBER then the example might just be "5").

The .grd file that gets generated will refer to your original .rc file for any menus, dialogs and version information resources. You can continue using e.g. the Visual Studio resource editor to edit these resources in the original .rc file. However, once you've started building your project using the .rc file generated from the .grd file by grit build, you should delete stringtables and "includes" from your original .rc file as these should now be in the .grd file and you don't want people to get confused and edit them in the old location.

Note that the grit rc2grd tool only supports symbolic resource IDs and will not transfer resources that are identified by string literals over to the .grd file. It is recommended not to use string literals as resource IDs.