Grafana uses the i18next framework for managing translating phrases in the Grafana frontend.
Note: We don't currently accept contributions for translations. Please don't submit pull requests translating grafana.json
files - they will be rejected. We do accept contributions to mark up phrases for translation.
<Trans i18nKey="search-results.panel-link">Go to {{ pageTitle }}</Trans>
in code to add a translatable phrase.public/locales/{locale}/grafana.json
.make i18n-extract
.en-US
(fallback language) is in grafana/grafana
, and the single source of truth for any translated language is Crowdin.{locale}/grafana.json
<Trans />
component from @grafana/i18n
with the i18nKey
, ensuring it conforms to the following guidelines, with the default English translation. For example:import { Trans } from '@grafana/i18n';
const SearchTitle = ({ term }) => <Trans i18nKey="search-page.results-title">Results for {{ term }}</Trans>;
Prefer using <Trans />
for JSX children, and t()
for props and other JavaScript usage.
There may be cases where you need to interpolate variables inside other components in the translation.
If the nested component is displaying the variable only (e.g. to add emphasis or color), the best solution is to create a new wrapping component:
import { Trans } from '@grafana/i18n';
import { Text } from '@grafana/ui';
const SearchTerm = ({ term }) => <Text color="success">{term}</Text>;
const SearchTitle = ({ term }) => (
<Trans i18nKey="search-page.results-title">
Results for <SearchTerm term={term} />
</Trans>
);
However there are also cases where the nested component might be displaying additional text which also needs to be translated. In this case, you can use the values
prop to explicitly pass variables to the translation, and reference them as templated strings in the markup. For example:
import { Trans } from '@grafana/i18n';
import { Text } from '@grafana/ui';
const SearchTitle = ({ term }) => (
<Trans i18nKey="search-page.results-title" values={{ myVariable: term }}>
Results for <Text color="success">{'{{ myVariable }}'} and this translated text is also in green</Text>
</Trans>
);
When translating in grafana-ui
, use a relative path to import <Trans />
and t()
from src/utils/i18n
.
Note that our tooling must be able to statically analyze the code to extract the phrase, so the i18nKey
can't be dynamic. For example: the following will not work:
const ErrorMessage = ({ id, message }) => <Trans i18nKey={`errors.${id}`}>There was an error: {{ message }}</Trans>;
Upon reload, the default English phrase appears on the page.
Before submitting your PR, run the make i18n-extract
command to extract the messages you added into the public/locales/en-US/grafana.json
file and make them available for translation.
Note: All other languages receive their translations when they are ready to be downloaded from Crowdin.
Sometimes you may need to translate a string cannot be represented in JSX, such as placeholder
props. Use the t
macro for this.
import { useTranslate } from "@grafana/i18n"
const { t } = useTranslate();
const placeholder = t('form.username-placeholder','Username');
return <input type="value" placeholder={placeholder}>
Interpolating phrases is a bit more verbose. Make sure the placeholders in the string match the values passed in the object - there's no type safety here!
const placeholder = t('page.greeting', 'Hello {{ username }}', { username });
While the t
function can technically be used outside of React functions (for example, in actions or reducers), aim to keep all UI phrases within the React UI functions.
public/app/core/internationalization/constants.ts
.
LOCALES
array.src/public/locales/localeExtensions.ts
.Grafana uses the i18next framework for managing translating phrases in the Grafana frontend. It:
Grafana loads the message catalog JSON before the initial render.
We set explicit IDs for phrases to make it easier to identify phrases out of context, and to track where they're used.
IDs follow a naming scheme that includes where the phrase is used. The exception is the rare case of a single reoccurring word like "Cancel", but the default is to use a feature-specific phrase.
Message IDs are made of up to three segments in the format feature.area.phrase
. For example:
dashboard.header.refresh-label
explore.toolbar.share-tooltip
For components used all over the site, use just two segments:
footer.update
navigation.home
We rely on a global i18next singleton (that lives inside the i18next) for storing the i18next configuration.
Refer to the i18next and react-i18next documentation for more details.
For fixed phrases:
import { Trans } from '@grafana/i18n';
<Trans i18nKey="page.greeting">Hello user!</Trans>;
To interpolate a variable, include it as an object child. It's a weird syntax, but Trans
will do its magic to make it work:
import { Trans } from '@grafana/i18n';
<Trans i18nKey="page.greeting">Hello {{ name: user.name }}!</Trans>;
const userName = user.name;
<Trans i18nKey="page.greeting">Hello {{ userName }}!</Trans>;
Variables must be strings (or, must support calling .toString()
, which we almost never want). For example:
import { Trans } from '@grafana/i18n';
// This will not work
const userName = <strong>user.name</strong>;
<Trans i18nKey="page.greeting">Hello {{ userName }}!</Trans>;
// Instead, put the JSX inside the phrase directly
const userName = user.name;
<Trans i18nKey="page.greeting">
Hello <strong>{{ userName }}</strong>!
</Trans>;
Both HTML tags and React components can be included in a phase. The Trans
function handles interpolating for its children.
import { Trans } from "@grafana/i18n"
<Trans i18nKey="page.explainer">
Click <button>here</button> to <a href="https://grafana.com">learn more.</a>
</Trans>
// ↓ is in the grafana.json file like ↓
{
"page": {
"explainer": "Click <0>here</0> to <1>learn more</1>"
}
}
Plurals require special handling to make sure they can be translated according to the rules of each locale (which may be more complex than you think). Use either the <Trans />
component or the t
function, with the count
prop to provide a singular form. For example:
import { Trans } from '@grafana/i18n';
<Trans i18nKey="inbox.heading" count={messages.length}>
You got {{ count: messages.length }} messages
</Trans>;
import { useTranslate } from '@grafana/i18n';
const { t } = useTranslate();
const translatedString = t('inbox.heading', 'You got {{count}} messages', { count: messages.length });
Once extracted with make i18n-extract
you need to manually edit the English grafana.json
message catalog to correct the plural forms. Refer to the react-i18next docs for more details.
{
"inbox": {
"heading_one": "You got {{count}} message",
"heading_other": "You got {{count}} messages"
}
}
Note: This is only for proofreaders with permissions to the Grafana OSS project on Crowdin.
To provide feedback on translations, sign into Crowdin and follow these steps:
grafana/main > public > locales > 'language denomination' > grafana.json
grafana.json
file.@Translated
to be sure the team of linguists gets notified.Grafana's documentation is not yet open for translation and should be authored in American English only.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )