Localizing Your Chrome Extension: An Easy Tutorial

Localization and Internationalization is a great way to get more users for your extension. Here is a simple tutorial that will help you do that.

This tutorial assumes you already know how to create a chrome extension. If not, you can head to my other tutorial to learn how to do that.


Step 1: Changing Manifest.json

When localizing your extension, you need to pick a default locale. This needs to be defined in the manifest.json file:

{
	...
    "default_locale": "en",
    ...
}

You need to add a new key default_locale and the value should be the locale that your extension will default to. In the example above we chose en for English.

You can check the list of supported locales here. If you pick a locale that's not supported, Chrome will ignore it.

Step 2: Translation Strings

Next thing you need to do is start creating the JSON files that will hold the localizable strings in your extension.

You will need to first create the directory locales in the root of your extension. Then inside that directory, you will be creating a folder for each locale that will hold the JSON file with the string translations for each locale. For example, to add the string translations for the English locale en, you will need to create the directory en inside _locales , then create messages.json inside it.

You don't have to create the messages.json file for every language, and you don't have to translate all the strings for every language. The only thing that is required is to have the default locale's strings. Then for any other language, if a message isn't translated for that locale, it will just default to the string in the default locale.

So, based on the previous example, we need to create the file _locales/en/messages.json and place the strings that we will need to translate throughout the extension.

The format for messages.json file is as follows:

{
	"KEY": {
    	"message": "VALUE"
    },
    ...
}

For each string you want to translate, you need to specify the KEY and then the value for it will be an object with key message and the value of it will be the string in this locale.

For example, If I want to add the string "Hello":

{
	"greeting": {
    	"message": "Hello"
    }
}

Here, I am defining the key greeting and that its value in the English locale will be "Hello".

You can also add an optional key description. This is only helpful if you want others to translate your string and you can give them some context on when this message is used or how it should be translated.

What if we want to pass a parameter to the translation string that shouldn't be translated? Let's say I want to greet the user by their name. For example, "Hello, John".

To add parameters to the string, the string object should look like this:

{
	"greeting": {
    	"message": "Hello, $USERNAME$",
        "placeholder": {
        	"username": {
            	"content": "$1"
            }
        }
    }
}

Here's what we did:

  1. We used $USERNAME for the name of the parameter in message
  2. We added a new key in the greeting object which is placeholder. placeholder is an object that has objects in it with the key being the name of the parameter present in message, and the value of each one has the key content which defines the value of the parameter.
  3. Using $1 in content means it will be the first parameter passed to the translation function (we will talk about this soon). The value can be something like $2 (second parameter), $3 (third parameter), or just a string like "John". If no value is passed in the translation function, $USERNAME will just be replaced by an empty string.

Each object in placeholder can also have an optional key example as to what the parameter value can be. For example:

{
	...
    "username": {
    	"content": "$1",
        "example": "John"
    }
    ...
}

This is, like the description key explained above, can be helpful for anyone translating this extension to understand what the parameter passed to the message could be.

Let's say we want to add now the translation for the Spanish language. We need to create the file locales/es/messages.json. Note that we created a new folder es in _locales.

Then inside the messages.json file we will have the following:

{
	"greeting": {
    	"message": "Hola"
    }
}

We need to use the same key we used in the default locale which is greeting, as we will later use it to fetch the string based on the locale. Then for message we use the translation for the Spanish language.

Note that if you use a parameter you also need to place it here. For example:

{
	"greeting": {
    	"message": "Hola, $USERNAME",
        "placeholder": {
        	"username": {	
            	"content": "$1"
            }
        }
    }
}

Step 3: Use The Localized Strings

In JS files:

To get the localized string in JS files, you need to use the function chrome.i18n.getMessage. For example:

chrome.i18n.getMessage('greeting');

The value will be the translation of the key greeting in the current locale. If the translation is not present, the value in the default locale will be used.

If you want to pass a parameter, you can pass it as the second parameter:

chrome.i18n.getMessage('greeting', 'John');

Note that if you want to pass multiple parameters you should use an array.

In manifest.json and CSS files

To use a localized string in manifest.json and CSS files, you need to precede the name of the string with __MSG_ and then follow it with __. For example :

{
...
"name": "__MSG_greeting__"
...
}

__MSG_greeting__ will place the translation for the key greeting.

Localization in HTML files

In order to translate a string in HTML files, you need to do it manually using javascript.

Here’s how you can do it with vanilla Javascript:

You can also do it with jQuery:

Step 4 (optional): Changing the CSS Direction Based on The Locale

When you are localizing your extension, you might need to change the styling based on the language. Most importantly, making your extension compatible with RTL and LTR languages.

Chrome’s Internationalization system provides some messages or variables that are helpful throughout localizing your extension. The ones that will be especially helpful in CSS are:

  1. @@bidi_dir: The direction based on the current locale (value will be either rtl or ltr)
  2. @@bidi_reversed_dir: The reverse of the current direction. So if the value of @@bidi_dir is rtl, the value of @@bidi_reversed_dir will be ltr, and vise versa.
  3. @@bidi_start_edge: If the value of @@bidi_dir is rtl, the value will be right; else, it will be left.
  4. @@bidi_end_edge: If the value of @@bidi_dir is rtl, the value will be left; else, it will be left. It's basically the opposite of @@bidi_start_edge.

These messages are helpful in your CSS as you can use them when styling your extension. For example:

extension. For example:

html {
	direction: __MSG_@@bidi_dir__; //The direction will change based on the current locale
}

Make sure to precede every message in CSS with __MSG_ and follow it with __

There are additional provided messages:

  1. @@extension_id: The id of your extension. You can’t use it in manifest.json
  2. @@ui_locale: The current locale.

Conclusion

After following the steps above, your chrome extension will be localized and ready for users of different languages!