Skip to content

How to Use iD's Localizer Module

Martin Raifer edited this page Mar 19, 2026 · 6 revisions

Here are some basic instructions for how to add a new translatable user interface text:

1. Create a new translatable string

Add an entry for each of your to-be-translated strings to the core.yaml file. Put it into an appropriate section matching the module you are working on. E.g. a new link label for the history panel would be best put here:

  info_panels:
    history:
      changeset_link: Changeset on osm.org

This string can now be referenced in iD via the stringId info_panels.history.changeset_link.

Optionally, you can now run the command npm run build:data to update the file dist/locales/en.min.json which is used by iD at runtime. This step is not necessary if you use npm start to test out your changes locally.

2. Using translatable strings in the user interface

Now you need to tell iD to use your newly created translatable strings. iD's localizer module offers some functions for that. If it is not included yet, you need to add the following line to import the module:

import { t } from '../../core/localizer';

Note that the number of ../ in this relative path changes depending on where exactly the module lives for which you would like to add translatable strings. Check the paths to make sure the localizer is imported correctly.

Now, how to get the translated strings into the iD frontend depends on where exactly you want to use the text:

Use t(stringId) for situations where you need the simple localized text

This method will simply return the translated string in the user's locale, or the English version from above if no translation is available. This is useful in certain situations where a raw text only is needed, for example when used in a title tooltip:

selection
    .append('button')
    .
    .attr('title', t('upload.button.tooltip'));

For regular text content, the following method is to be preferred:

Use t.addOrUpdate(stringId) for adding text with locale info

The method t.addOrUpdate adds text to the user interface as an HTML element with locale information. This meta information is important for accessibility reasons, as it is used by assistive technologies such as screen readers.

Here's how this method is typically used:

selection
    .append('a')
    .attr('href', '…')
    .call(t.addOrUpdate('info_panels.history.changeset_link'));

Don't use t.html(stringId) anymore!

Previously, instead of t.addOrUpdate, there existed a version called t.html which performed a similar task, but is now deprecated for security issues. Currently, this method is still used in a few places in the code, but will be replaced with t.addOrUpdate over time.

Using replacement variables

Some strings are templates that expect to get supplied with replacement variables. For example the string inspector.last_touched is defined as Last touched {timeago} by {user}, where {timeago} and {user} will be replaced by the respective time and user depending on which feature is selected. These can be supplied in the code as additional parameters after the string id in the t(), t.append(), or t.addOrUpdate() methods. Often these replacements are just numbers, or simple strings:

t.append('commit.outstanding_errors_message', {
    count: numberOfOutstandingErrors
});

In addition, t.append and t.addOrUpdate also supports to use a arbitrary dynamic callback functions for such a template replacements. This can be useful when another translated string should be used as one of the to be replaced templates:

t.append('operations._unavailable', {
    operation: t.append(`operations.${_operation.id}.title`))
});

Or when one wants to include extra HTML elements, e.g. to format a URL as a link. In this fully custom example, the callback function is called with a d3 selection and can append to it as needed, e.g.:

selection.call(t.append('stringId', {
    key1: 'replacementString',
    key2: sel => sel.append('a')
        .attr('href', 'https://example.com')
        .text();
})