Skip to main content

Translate your plugin

By default, plugins are available in English only and are not translated when you change your language settings in the Grafana UI.

If you want your plugin to be translatable to other languages you need to perform the changes described in this document. You can find the list of available languages in GitHub.

note

While this example is based on a panel plugin, the process is the same for data source and app plugins.

Before you begin​

info

Translation is available starting from Grafana 12.1.0 using the feature flag. If you're using Grafana 11.0.0 and later, the plugin will work but will only display in English (US). If you're using older versions of Grafana the plugin will not work.

The following is recommended:

  • Basic knowledge of Grafana plugin development
  • Basic understanding of the t function
  • Basic understanding of the Trans component

Overview of the files affected by translation​

If you create your plugin running the create-plugin scaffolding tool, enabling plugin translation involves updating the following files:

  • docker-compose.yaml
  • plugin.json
  • module.ts
  • webpack.config.ts
  • package.json

By the end of the translation process you'll have a file structure like this:

myorg-myplugin-plugintype/
├── src/
│ ├── locales
│ │ ├── en-US
│ │ │ └── myorg-myplugin-plugintype.json
│ │ └── pt-BR
│ │ └── myorg-myplugin-plugintype.json
│ ├── module.ts
│ └── plugin.json
├── tests/
├── docker-compose.yaml
└── package.json

Set up your plugin for translation​

Follow these steps to update your plugin and set it up for translation.

Enable translation in your Grafana instance​

To translate your plugin you need to enable the feature toggle localizationForPlugins in your Grafana instance.

To do so, update docker-compose.yaml in your plugin with the feature toggle localizationForPlugins:

docker-compose.yaml
services:
grafana:
extends:
file: .config/docker-compose-base.yaml
service: grafana
environment:
GF_FEATURE_TOGGLES_ENABLE: localizationForPlugins

Define the languages and Grafana dependencies​

Set up the translation languages for your plugin and the Grafana dependencies for translation.

To do so, add the relevant grafanaDependency and languages you want to translate to in the plugin.json file. For example, if you want to add US English and Brazilian Portuguese:

plugin.json
"dependencies": {
"grafanaDependency": ">=12.1.0", // @grafana/i18n works from version 11.0.0 and higher for en-US translations
"plugins": []
},
"languages": ["en-US", "pt-BR"] // the languages that the plugin supports

Update to the latest version of create-plugin​

Update your create-plugin configs to the latest version using the following command:

npx @grafana/create-plugin@latest update

Initialize translations in module.ts​

Add plugin translation to module.ts:

module.ts
import { initPluginTranslations } from '@grafana/i18n';
import pluginJson from 'plugin.json';

await initPluginTranslations(pluginJson.id);

Determine the text to translate​

After you've configured your plugin for translation you can proceed to mark up the language strings you want to translate. Each translatable string is assigned a unique key that ends up in each translation file under locales/<locale>/<plugin id>.json. Example using the t function:

export const plugin = new PanelPlugin<SimpleOptions>(SimplePanel).setPanelOption
return builder
.addTextInput({
path: 'text',
- name: 'Simple text option',
- description: 'Description of panel option',
- defaultValue: 'Default value of text input option',
+ name: t('panel.options.text.name', 'Simple text option'),
+ description: t('panel.options.text.description', 'Description of panel option'),
+ defaultValue: t('panel.options.text.defaultValue', 'Default value of text input option'),
})
.addBooleanSwitch({
path: 'showSeriesCount',
- name: 'Show series counter',
+ name: t('panel.options.showSeriesCount.name', 'Show series counter'),
defaultValue: false,
})
.addRadio({
path: 'seriesCountSize',
defaultValue: 'sm',
- name: 'Series counter size',
+ name: t('panel.options.seriesCountSize.name', 'Series counter size'),
settings: {
options: [
{
value: 'sm',
- label: 'Small',
+ label: t('panel.options.seriesCountSize.options.sm', 'Small'),
},
{
value: 'md',
- label: 'Medium',
+ label: t('panel.options.seriesCountSize.options.md', 'Medium'),
},
{
value: 'lg',
- label: 'Large',
+ label: t('panel.options.seriesCountSize.options.lg', 'Large'),
},
],
},

Example using the Trans component:​

 import { SimpleOptions } from 'types';
import { css, cx } from '@emotion/css';
import { useStyles2, useTheme2 } from '@grafana/ui';
import { PanelDataErrorView } from '@grafana/runtime';
+import { Trans } from '@grafana/i18n';

interface Props extends PanelProps<SimpleOptions> {}

@@ -60,9 +61,15 @@ export const SimplePanel: React.FC<Props> = ({ options, data, width, height, fie

<div className={styles.textBox}>
{options.showSeriesCount && (
- <div data-testid="simple-panel-series-counter">Number of series: {data.series.length}</div>
+ <div data-testid="simple-panel-series-counter">
+ <Trans i18nKey="components.simpePanel.options.showSeriesCount">
+ Number of series: {{ numberOfSeries: data.series.length }}
+ </Trans>
+ </div>
)}
- <div>Text option value: {options.text}</div>
+ <Trans i18nKey="components.simpePanel.options.textOptionValue">
+ Text option value: {{ optionValue: options.text }}
+ </Trans>
</div>
</div>
);

Obtain the translated text​

Use the i18next parser and i18n-extract to sweep all input files, extract tagged i18n keys, and save the translations.

Parse for translations​

Install the i18next parser:

npm install i18next-parser

Next, create a configuration file src/locales/i18next-parser.config.js and configure it so the parser sweeps your plugin and extracts the translations into the locales/[$LOCALE]/[your-plugin].json:

warning

The path locales/[$LOCALE]/[your-plugin-id].json is mandatory. If you modify it translations won't work.

i18next-parser.config.js
const pluginJson = require('../plugin.json');

module.exports = {
locales: ['en-US', 'pt-BR'], // An array of the locales your plugin supports
sort: true,
createOldCatalogs: false,
failOnWarnings: true,
verbose: false,
resetDefaultValueLocale: 'en-US', // Updates extracted values when they change in code
defaultNamespace: pluginJson.id,
input: ['../**/*.{tsx,ts}'],
output: 'src/locales/$LOCALE/$NAMESPACE.json',
};

Obtain your translation file​

Add the translation script i18n-extract to package.json:

package.json
  "scripts": {
"i18n-extract": "i18next --config src/locales/i18next-parser.config.js",
},

Run the script to translate the files:

npm run i18n-extract

The translation file will look similar to this:

{
"components": {
"simplePanel": {
"options": {
"showSeriesCount": "Number of series: {{numberOfSeries}}",
"textOptionValue": "Text option value: {{optionValue}}"
}
}
},
"panel": {
"options": {
"seriesCountSize": {
"name": "Series counter size",
"options": {
"lg": "Large",
"md": "Medium",
"sm": "Small"
}
},
"showSeriesCount": {
"name": "Show series counter"
},
"text": {
"defaultValue": "Default value of text input option",
"description": "Description of panel option",
"name": "Simple text option"
}
}
}
}

Test the translated plugin​

To test the plugin follow the steps in Set up your development environment to run your plugin locally.

You can then verify your plugin is displaying the appropriate text as you change the language.