From 719769ee7c7f7794bf2dedcb7e09ebd533f767a4 Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Wed, 12 Oct 2022 11:12:46 +0100 Subject: [PATCH] I18n: Add Chinese (Simplified) (#56739) * Prevent _old.json files from being created * Add contrib docs for adding new locale * add chinese (simplified) --- contribute/internationalization.md | 12 ++++++++++++ .../SharedPreferences/SharedPreferences.tsx | 18 ++++++++++++++---- .../app/core/internationalization/constants.ts | 3 ++- public/app/core/internationalization/index.tsx | 11 ++++++++++- public/locales/en-US/grafana.json | 7 ++++--- public/locales/es-ES/grafana.json | 7 ++++--- public/locales/fr-FR/grafana.json | 7 ++++--- public/locales/i18next-parser.config.js | 4 +++- public/locales/pseudo-LOCALE/grafana.json | 9 +++++---- public/locales/zh-Hans/grafana.json | 7 ++++--- 10 files changed, 62 insertions(+), 23 deletions(-) diff --git a/contribute/internationalization.md b/contribute/internationalization.md index 726aca8a8c8..88ebb57b759 100644 --- a/contribute/internationalization.md +++ b/contribute/internationalization.md @@ -38,6 +38,18 @@ const ErrorMessage = ({ id, message }) => There was a 3. Before submitting your PR, run the `yarn i18n:extract` command to extract the messages you added into the `messages.po` file and make them available for translation. +## How to add a new language + +1. Add new locale in Crowdin and sync files to repo + 1. Grafana OSS Crowdin project -> "dot dot dot" menu in top right -> Target languages + 2. Grafana OSS Crowdin project -> Integrations -> Github -> Sync Now + 3. If Crowdin's locale code is different from our IETF language tag, add a custom mapping in Project Settings -> Language mapping +2. Update `public/app/core/internationalization/constants.ts` (add new constant, and add to `VALID_LOCALES`) +3. Update `public/app/core/internationalization/index.tsx` to add the message loader for the new locale +4. Update `public/app/core/components/SharedPreferences/SharedPreferences.tsx` to add the new locale to the options. +5. Update `public/locales/i18next-parser.config.js` to add the new locale to `locales` +6. Run `yarn i18n:extract` and commit the result + ## How translations work in Grafana Grafana uses the [LinguiJS](https://github.com/lingui/js-lingui) framework for managing translating phrases in the Grafana frontend. It: diff --git a/public/app/core/components/SharedPreferences/SharedPreferences.tsx b/public/app/core/components/SharedPreferences/SharedPreferences.tsx index ee7c1d94dd3..ddae355b197 100644 --- a/public/app/core/components/SharedPreferences/SharedPreferences.tsx +++ b/public/app/core/components/SharedPreferences/SharedPreferences.tsx @@ -19,7 +19,13 @@ import { } from '@grafana/ui'; import { DashboardPicker } from 'app/core/components/Select/DashboardPicker'; import { t, Trans } from 'app/core/internationalization'; -import { ENGLISH_US, FRENCH_FRANCE, PSEUDO_LOCALE, SPANISH_SPAIN } from 'app/core/internationalization/constants'; +import { + CHINESE_SIMPLIFIED, + ENGLISH_US, + FRENCH_FRANCE, + PSEUDO_LOCALE, + SPANISH_SPAIN, +} from 'app/core/internationalization/constants'; import { PreferencesService } from 'app/core/services/PreferencesService'; import { UserPreferencesDTO } from 'app/types'; @@ -43,15 +49,19 @@ const languages: Array> = [ }, { value: ENGLISH_US, - label: t('common.locale.en', 'English'), + label: t('common.locale.en-US', 'English'), }, { value: SPANISH_SPAIN, - label: t('common.locale.es', 'Spanish'), + label: t('common.locale.es-ES', 'Spanish'), }, { value: FRENCH_FRANCE, - label: t('common.locale.fr', 'French'), + label: t('common.locale.fr-FR', 'French'), + }, + { + value: CHINESE_SIMPLIFIED, + label: t('common.locale.zh-Hans', 'Chinese (Simplified)'), }, // TODO: dev only { diff --git a/public/app/core/internationalization/constants.ts b/public/app/core/internationalization/constants.ts index 9d44e6a1ab7..4dae89e789d 100644 --- a/public/app/core/internationalization/constants.ts +++ b/public/app/core/internationalization/constants.ts @@ -1,8 +1,9 @@ export const ENGLISH_US = 'en-US'; export const FRENCH_FRANCE = 'fr-FR'; export const SPANISH_SPAIN = 'es-ES'; +export const CHINESE_SIMPLIFIED = 'zh-Hans'; export const PSEUDO_LOCALE = 'pseudo-LOCALE'; export const DEFAULT_LOCALE = ENGLISH_US; -export const VALID_LOCALES: string[] = [ENGLISH_US, FRENCH_FRANCE, SPANISH_SPAIN, PSEUDO_LOCALE]; +export const VALID_LOCALES: string[] = [ENGLISH_US, FRENCH_FRANCE, SPANISH_SPAIN, CHINESE_SIMPLIFIED, PSEUDO_LOCALE]; diff --git a/public/app/core/internationalization/index.tsx b/public/app/core/internationalization/index.tsx index 3cdcc711cab..03319119c39 100644 --- a/public/app/core/internationalization/index.tsx +++ b/public/app/core/internationalization/index.tsx @@ -2,12 +2,21 @@ import i18n, { BackendModule, ResourceKey } from 'i18next'; import React from 'react'; import { Trans as I18NextTrans, initReactI18next } from 'react-i18next'; // eslint-disable-line no-restricted-imports -import { DEFAULT_LOCALE, ENGLISH_US, FRENCH_FRANCE, SPANISH_SPAIN, PSEUDO_LOCALE, VALID_LOCALES } from './constants'; +import { + DEFAULT_LOCALE, + ENGLISH_US, + FRENCH_FRANCE, + SPANISH_SPAIN, + PSEUDO_LOCALE, + VALID_LOCALES, + CHINESE_SIMPLIFIED, +} from './constants'; const messageLoaders: Record Promise> = { [ENGLISH_US]: () => import('../../../locales/en-US/grafana.json'), [FRENCH_FRANCE]: () => import('../../../locales/fr-FR/grafana.json'), [SPANISH_SPAIN]: () => import('../../../locales/es-ES/grafana.json'), + [CHINESE_SIMPLIFIED]: () => import('../../../locales/zh-Hans/grafana.json'), [PSEUDO_LOCALE]: () => import('../../../locales/pseudo-LOCALE/grafana.json'), }; diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 030881d10a1..51f95e36c18 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -2,9 +2,10 @@ "common": { "locale": { "default": "Default", - "en": "English", - "es": "Spanish", - "fr": "French" + "en-US": "English", + "es-ES": "Spanish", + "fr-FR": "French", + "zh-Hans": "Chinese (Simplified)" }, "save": "Save" }, diff --git a/public/locales/es-ES/grafana.json b/public/locales/es-ES/grafana.json index 2d241403404..992a5f22852 100644 --- a/public/locales/es-ES/grafana.json +++ b/public/locales/es-ES/grafana.json @@ -2,9 +2,10 @@ "common": { "locale": { "default": "", - "en": "", - "es": "", - "fr": "" + "en-US": "", + "es-ES": "", + "fr-FR": "", + "zh-Hans": "" }, "save": "" }, diff --git a/public/locales/fr-FR/grafana.json b/public/locales/fr-FR/grafana.json index 2d241403404..992a5f22852 100644 --- a/public/locales/fr-FR/grafana.json +++ b/public/locales/fr-FR/grafana.json @@ -2,9 +2,10 @@ "common": { "locale": { "default": "", - "en": "", - "es": "", - "fr": "" + "en-US": "", + "es-ES": "", + "fr-FR": "", + "zh-Hans": "" }, "save": "" }, diff --git a/public/locales/i18next-parser.config.js b/public/locales/i18next-parser.config.js index 799af12b8af..1b0d66cb782 100644 --- a/public/locales/i18next-parser.config.js +++ b/public/locales/i18next-parser.config.js @@ -2,7 +2,7 @@ module.exports = { // Default namespace used in your i18next config defaultNamespace: 'grafana', - locales: ['en-US', 'fr-FR', 'es-ES', 'pseudo-LOCALE'], + locales: ['en-US', 'fr-FR', 'es-ES', "zh-Hans", 'pseudo-LOCALE'], output: './public/locales/$LOCALE/$NAMESPACE.json', @@ -10,6 +10,8 @@ module.exports = { sort: true, + createOldCatalogs: false, + // Don't include default values for English, they'll remain in the source code skipDefaultValues: (locale) => locale !== 'en-US', }; diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json index ac62c6ec434..0c876f32d0e 100644 --- a/public/locales/pseudo-LOCALE/grafana.json +++ b/public/locales/pseudo-LOCALE/grafana.json @@ -2,9 +2,10 @@ "common": { "locale": { "default": "Đęƒäūľŧ", - "en": "Ēʼnģľįşĥ", - "es": "Ŝpäʼnįşĥ", - "fr": "Fřęʼnčĥ" + "en-US": "Ēʼnģľįşĥ", + "es-ES": "Ŝpäʼnįşĥ", + "fr-FR": "Fřęʼnčĥ", + "zh-Hans": "Cĥįʼnęşę (Ŝįmpľįƒįęđ)" }, "save": "Ŝävę" }, @@ -441,4 +442,4 @@ "user-sessions": { "loading": "Ŀőäđįʼnģ şęşşįőʼnş..." } -} +} \ No newline at end of file diff --git a/public/locales/zh-Hans/grafana.json b/public/locales/zh-Hans/grafana.json index 2d241403404..992a5f22852 100644 --- a/public/locales/zh-Hans/grafana.json +++ b/public/locales/zh-Hans/grafana.json @@ -2,9 +2,10 @@ "common": { "locale": { "default": "", - "en": "", - "es": "", - "fr": "" + "en-US": "", + "es-ES": "", + "fr-FR": "", + "zh-Hans": "" }, "save": "" },