From b7d969baf1c79360ae8becec6cfe7394f8a66e92 Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Wed, 12 Oct 2022 12:51:16 +0100 Subject: [PATCH] I18n: Improve tooling (#56731) * Delete en-US.json before extracting strings so it's always up to date * Add 'comment' to message jsons * Enable Pseudo-locale option only in dev mode * don't load english messages * fix package.json * fix --- package.json | 3 +- .../SharedPreferences/SharedPreferences.tsx | 61 +++++++++++-------- .../app/core/internationalization/index.tsx | 10 ++- public/locales/en-US/grafana.json | 1 + public/locales/es-ES/grafana.json | 1 + public/locales/fr-FR/grafana.json | 1 + public/locales/pseudo-LOCALE/grafana.json | 3 +- public/locales/zh-Hans/grafana.json | 1 + 8 files changed, 51 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 67b17f75cb4..1688c73cc11 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,8 @@ "watch": "yarn start -d watch,start core:start --watchTheme", "ci:test-frontend": "yarn run test:ci && yarn grafana-toolkit node-version-check", "postinstall": "husky install", - "i18n:extract": "yarn run i18next -c public/locales/i18next-parser.config.js 'public/**/*.{tsx,ts}' 'packages/grafana-ui/**/*.{tsx,ts}' && node ./public/locales/psuedo.js", + "i18n:clean": "rimraf public/locales/en-US/grafana.json", + "i18n:extract": "yarn i18n:clean && yarn run i18next -c public/locales/i18next-parser.config.js 'public/**/*.{tsx,ts}' 'packages/grafana-ui/**/*.{tsx,ts}' && node ./public/locales/psuedo.js", "i18n:compile": "echo 'no i18n compile yet, all good'", "betterer": "betterer", "betterer:merge": "betterer merge", diff --git a/public/app/core/components/SharedPreferences/SharedPreferences.tsx b/public/app/core/components/SharedPreferences/SharedPreferences.tsx index ddae355b197..b4a8f430845 100644 --- a/public/app/core/components/SharedPreferences/SharedPreferences.tsx +++ b/public/app/core/components/SharedPreferences/SharedPreferences.tsx @@ -42,33 +42,39 @@ const themes: SelectableValue[] = [ { value: 'light', label: t('shared-preferences.theme.light-label', 'Light') }, ]; -const languages: Array> = [ - { - value: '', - label: t('common.locale.default', 'Default'), - }, - { - value: ENGLISH_US, - label: t('common.locale.en-US', 'English'), - }, - { - value: SPANISH_SPAIN, - label: t('common.locale.es-ES', 'Spanish'), - }, - { - value: FRENCH_FRANCE, - label: t('common.locale.fr-FR', 'French'), - }, - { - value: CHINESE_SIMPLIFIED, - label: t('common.locale.zh-Hans', 'Chinese (Simplified)'), - }, - // TODO: dev only - { - value: PSEUDO_LOCALE, - label: 'Pseudo-locale', // no need to translate this key - }, -]; +function getLanguageOptions(): Array> { + const options = [ + { + value: '', + label: t('common.locale.default', 'Default'), + }, + { + value: ENGLISH_US, + label: t('common.locale.en-US', 'English'), + }, + { + value: SPANISH_SPAIN, + label: t('common.locale.es-ES', 'Spanish'), + }, + { + value: FRENCH_FRANCE, + label: t('common.locale.fr-FR', 'French'), + }, + { + value: CHINESE_SIMPLIFIED, + label: t('common.locale.zh-Hans', 'Chinese (Simplified)'), + }, + ]; + + if (process.env.NODE_ENV === 'development') { + options.push({ + value: PSEUDO_LOCALE, + label: 'Pseudo-locale', // no need to translate this key + }); + } + + return options; +} const i18nFlag = Boolean(config.featureToggles.internationalization); @@ -134,6 +140,7 @@ export class SharedPreferences extends PureComponent { const { theme, timezone, weekStart, homeDashboardUID, locale } = this.state; const { disabled } = this.props; const styles = getStyles(); + const languages = getLanguageOptions(); return (
diff --git a/public/app/core/internationalization/index.tsx b/public/app/core/internationalization/index.tsx index 03319119c39..a99fa2acfb4 100644 --- a/public/app/core/internationalization/index.tsx +++ b/public/app/core/internationalization/index.tsx @@ -13,7 +13,8 @@ import { } from './constants'; const messageLoaders: Record Promise> = { - [ENGLISH_US]: () => import('../../../locales/en-US/grafana.json'), + // English phrases are the default fallback string in the source, so we don't need to load the catalogue + [ENGLISH_US]: () => Promise.resolve({}), [FRENCH_FRANCE]: () => import('../../../locales/fr-FR/grafana.json'), [SPANISH_SPAIN]: () => import('../../../locales/es-ES/grafana.json'), [CHINESE_SIMPLIFIED]: () => import('../../../locales/zh-Hans/grafana.json'), @@ -50,6 +51,13 @@ export function initializeI18n(locale: string) { // If translations are empty strings (no translation), fall back to the default value in source code returnEmptyString: false, }); + + // This is a placeholder so we can put a 'comment' in the message json files. + // Starts with an underscore so it's sorted to the top of the file + t( + '_comment', + 'Do not manually edit this file, or update these source phrases in Crowdin. The source of truth for English strings are in the code source' + ); } export function changeLanguage(locale: string) { diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 51f95e36c18..ae8b5376533 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -1,4 +1,5 @@ { + "_comment": "Do not manually edit this file, or update these source phrases in Crowdin. The source of truth for English strings are in the code source", "common": { "locale": { "default": "Default", diff --git a/public/locales/es-ES/grafana.json b/public/locales/es-ES/grafana.json index 992a5f22852..903f86a76e9 100644 --- a/public/locales/es-ES/grafana.json +++ b/public/locales/es-ES/grafana.json @@ -1,4 +1,5 @@ { + "_comment": "Do not manually edit this file. Translations must be made in Crowdin which will sync them back into this file.", "common": { "locale": { "default": "", diff --git a/public/locales/fr-FR/grafana.json b/public/locales/fr-FR/grafana.json index 992a5f22852..903f86a76e9 100644 --- a/public/locales/fr-FR/grafana.json +++ b/public/locales/fr-FR/grafana.json @@ -1,4 +1,5 @@ { + "_comment": "Do not manually edit this file. Translations must be made in Crowdin which will sync them back into this file.", "common": { "locale": { "default": "", diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json index 0c876f32d0e..dc3153d6a14 100644 --- a/public/locales/pseudo-LOCALE/grafana.json +++ b/public/locales/pseudo-LOCALE/grafana.json @@ -1,4 +1,5 @@ { + "_comment": "Đő ʼnőŧ mäʼnūäľľy ęđįŧ ŧĥįş ƒįľę, őř ūpđäŧę ŧĥęşę şőūřčę pĥřäşęş įʼn Cřőŵđįʼn. Ŧĥę şőūřčę őƒ ŧřūŧĥ ƒőř Ēʼnģľįşĥ şŧřįʼnģş äřę įʼn ŧĥę čőđę şőūřčę", "common": { "locale": { "default": "Đęƒäūľŧ", @@ -442,4 +443,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 992a5f22852..903f86a76e9 100644 --- a/public/locales/zh-Hans/grafana.json +++ b/public/locales/zh-Hans/grafana.json @@ -1,4 +1,5 @@ { + "_comment": "Do not manually edit this file. Translations must be made in Crowdin which will sync them back into this file.", "common": { "locale": { "default": "",