I18n: Import Scenes translations (#106852)
* wip * use initScenesTranslations * comment * use just plain resource loaded from scenes lib * update to the published scenes version * rename loadPluginResources to loadNamespacedResources
This commit is contained in:
+2
-2
@@ -287,8 +287,8 @@
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/prometheus": "workspace:*",
|
||||
"@grafana/runtime": "workspace:*",
|
||||
"@grafana/scenes": "^6.20.1",
|
||||
"@grafana/scenes-react": "^6.20.1",
|
||||
"@grafana/scenes": "^6.21.0",
|
||||
"@grafana/scenes-react": "^6.21.0",
|
||||
"@grafana/schema": "workspace:*",
|
||||
"@grafana/sql": "workspace:*",
|
||||
"@grafana/ui": "workspace:*",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { initReactI18next, setDefaults, setI18n } from 'react-i18next';
|
||||
|
||||
import { DEFAULT_LANGUAGE } from './constants';
|
||||
import {
|
||||
loadPluginResources,
|
||||
loadNamespacedResources,
|
||||
initDefaultI18nInstance,
|
||||
initDefaultReactI18nInstance,
|
||||
initPluginTranslations,
|
||||
@@ -22,7 +22,7 @@ describe('i18n', () => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('loadPluginResources', () => {
|
||||
describe('loadNamespacedResources', () => {
|
||||
it('should load all resources for a plugin', async () => {
|
||||
const loaders: ResourceLoader[] = [
|
||||
() => Promise.resolve({ hello: 'Hi' }),
|
||||
@@ -30,7 +30,7 @@ describe('i18n', () => {
|
||||
];
|
||||
const addResourceBundleSpy = jest.spyOn(i18n, 'addResourceBundle');
|
||||
|
||||
await loadPluginResources('test', 'en-US', loaders);
|
||||
await loadNamespacedResources('test', 'en-US', loaders);
|
||||
|
||||
expect(addResourceBundleSpy).toHaveBeenCalledTimes(2);
|
||||
expect(addResourceBundleSpy).toHaveBeenNthCalledWith(1, 'en-US', 'test', { hello: 'Hi' }, true, false);
|
||||
@@ -45,7 +45,7 @@ describe('i18n', () => {
|
||||
jest.spyOn(console, 'error').mockImplementation();
|
||||
const addResourceBundleSpy = jest.spyOn(i18n, 'addResourceBundle');
|
||||
|
||||
await loadPluginResources('test', 'en-US', loaders);
|
||||
await loadNamespacedResources('test', 'en-US', loaders);
|
||||
|
||||
expect(addResourceBundleSpy).toHaveBeenCalledTimes(1);
|
||||
expect(addResourceBundleSpy).toHaveBeenCalledWith('en-US', 'test', { i18n: 'i18n' }, true, false);
|
||||
@@ -55,7 +55,7 @@ describe('i18n', () => {
|
||||
const loaders: ResourceLoader[] = [];
|
||||
const addResourceBundleSpy = jest.spyOn(i18n, 'addResourceBundle');
|
||||
|
||||
await loadPluginResources('test', 'en-US', loaders);
|
||||
await loadNamespacedResources('test', 'en-US', loaders);
|
||||
|
||||
expect(addResourceBundleSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
@@ -30,8 +30,7 @@ function initTFuncAndTransComponent({ id, ns }: { id?: string; ns?: string[] } =
|
||||
transComponent = (props: TransProps) => <I18NextTrans shouldUnescape ns={ns} {...props} />;
|
||||
}
|
||||
|
||||
// exported for testing
|
||||
export async function loadPluginResources(id: string, language: string, loaders?: ResourceLoader[]) {
|
||||
export async function loadNamespacedResources(namespace: string, language: string, loaders?: ResourceLoader[]) {
|
||||
if (!loaders?.length) {
|
||||
return;
|
||||
}
|
||||
@@ -42,9 +41,9 @@ export async function loadPluginResources(id: string, language: string, loaders?
|
||||
loaders.map(async (loader) => {
|
||||
try {
|
||||
const resources = await loader(resolvedLanguage);
|
||||
addResourceBundle(resolvedLanguage, id, resources);
|
||||
addResourceBundle(resolvedLanguage, namespace, resources);
|
||||
} catch (error) {
|
||||
console.error(`Error loading resources for plugin ${id} and language: ${resolvedLanguage}`, error);
|
||||
console.error(`Error loading resources for namespace ${namespace} and language: ${resolvedLanguage}`, error);
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -85,7 +84,7 @@ export async function initPluginTranslations(id: string, loaders?: ResourceLoade
|
||||
const language = getResolvedLanguage();
|
||||
initTFuncAndTransComponent({ id });
|
||||
|
||||
await loadPluginResources(id, language, loaders);
|
||||
await loadNamespacedResources(id, language, loaders);
|
||||
|
||||
return { language };
|
||||
}
|
||||
|
||||
@@ -17,4 +17,5 @@ export {
|
||||
getLanguage,
|
||||
getResolvedLanguage,
|
||||
initializeI18n,
|
||||
loadNamespacedResources,
|
||||
} from '../i18n';
|
||||
|
||||
+10
-3
@@ -19,7 +19,8 @@ import {
|
||||
standardFieldConfigEditorRegistry,
|
||||
standardTransformersRegistry,
|
||||
} from '@grafana/data';
|
||||
import { initializeI18n } from '@grafana/i18n/internal';
|
||||
import { DEFAULT_LANGUAGE } from '@grafana/i18n';
|
||||
import { initializeI18n, loadNamespacedResources } from '@grafana/i18n/internal';
|
||||
import {
|
||||
locationService,
|
||||
registerEchoBackend,
|
||||
@@ -49,6 +50,7 @@ import {
|
||||
setPanelRenderer,
|
||||
setPluginPage,
|
||||
} from '@grafana/runtime/internal';
|
||||
import { loadResources as loadScenesResources } from '@grafana/scenes';
|
||||
import config, { updateConfig } from 'app/core/config';
|
||||
import { getStandardTransformers } from 'app/features/transformers/standardTransformers';
|
||||
|
||||
@@ -63,7 +65,7 @@ import { getAllOptionEditors, getAllStandardFieldConfigs } from './core/componen
|
||||
import { PluginPage } from './core/components/Page/PluginPage';
|
||||
import { GrafanaContextType, useReturnToPreviousInternal } from './core/context/GrafanaContext';
|
||||
import { initializeCrashDetection } from './core/crash';
|
||||
import { NAMESPACES } from './core/internationalization/constants';
|
||||
import { NAMESPACES, GRAFANA_NAMESPACE } from './core/internationalization/constants';
|
||||
import { loadTranslations } from './core/internationalization/loadTranslations';
|
||||
import { postInitTasks, preInitTasks } from './core/lifecycle-hooks';
|
||||
import { setMonacoEnv } from './core/monacoEnv';
|
||||
@@ -142,7 +144,12 @@ export class GrafanaApp {
|
||||
// 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. Even though it is in a comment the following line is still extracted
|
||||
// t('_comment', 'The code is the source of truth for English phrases. They should be updated in the components directly, and additional plurals specified in this file.');
|
||||
initI18nPromise.then(({ language }) => updateConfig({ language }));
|
||||
initI18nPromise.then(async ({ language }) => {
|
||||
updateConfig({ language });
|
||||
|
||||
// Initialise scenes translations into the Grafana namespace. Must finish before any scenes UI is rendered.
|
||||
return loadNamespacedResources(GRAFANA_NAMESPACE, language ?? DEFAULT_LANGUAGE, [loadScenesResources]);
|
||||
});
|
||||
|
||||
setBackendSrv(backendSrv);
|
||||
await initEchoSrv();
|
||||
|
||||
@@ -5,6 +5,8 @@ import { DEFAULT_LANGUAGE, PSEUDO_LOCALE, LANGUAGES as SUPPORTED_LANGUAGES } fro
|
||||
|
||||
export type LocaleFileLoader = () => Promise<ResourceKey>;
|
||||
|
||||
export const GRAFANA_NAMESPACE = 'grafana' as const;
|
||||
|
||||
type BaseLanguageDefinition = (typeof SUPPORTED_LANGUAGES)[number];
|
||||
export interface LanguageDefinition<Namespace extends string = string> extends BaseLanguageDefinition {
|
||||
/** Function to load translations */
|
||||
@@ -16,7 +18,7 @@ export const LANGUAGES: LanguageDefinition[] = SUPPORTED_LANGUAGES.map((def) =>
|
||||
const locale = def.code === PSEUDO_LOCALE ? DEFAULT_LANGUAGE : def.code;
|
||||
return {
|
||||
...def,
|
||||
loader: { grafana: () => import(`../../../locales/${locale}/grafana.json`) },
|
||||
loader: { [GRAFANA_NAMESPACE]: () => import(`../../../locales/${locale}/grafana.json`) },
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -3497,11 +3497,11 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@grafana/scenes-react@npm:^6.20.1":
|
||||
version: 6.20.2
|
||||
resolution: "@grafana/scenes-react@npm:6.20.2"
|
||||
"@grafana/scenes-react@npm:^6.21.0":
|
||||
version: 6.21.1
|
||||
resolution: "@grafana/scenes-react@npm:6.21.1"
|
||||
dependencies:
|
||||
"@grafana/scenes": "npm:6.20.2"
|
||||
"@grafana/scenes": "npm:6.21.1"
|
||||
lru-cache: "npm:^10.2.2"
|
||||
react-use: "npm:^17.4.0"
|
||||
peerDependencies:
|
||||
@@ -3513,17 +3513,18 @@ __metadata:
|
||||
react: ^18.0.0
|
||||
react-dom: ^18.0.0
|
||||
react-router-dom: ^6.28.0
|
||||
checksum: 10/43bd83d0f265c1e8ac867d0d26d1e970bf9b7d87ff78abd263c51cb2c4af73d536642cbf50d75aa9e1c1af16e9802f1684cc50dfe9f43a8129687ed4831e0706
|
||||
checksum: 10/2012aae4ce275f428afdadbeabb48eea4faf3045286e68f1e6cc9a02d9118cf2f4094e3f6fce770fc1935f7ac3021362aed9b8a803eefb48e767e38abf0b8679
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@grafana/scenes@npm:6.20.2, @grafana/scenes@npm:^6.20.1":
|
||||
version: 6.20.2
|
||||
resolution: "@grafana/scenes@npm:6.20.2"
|
||||
"@grafana/scenes@npm:6.21.1, @grafana/scenes@npm:^6.21.0":
|
||||
version: 6.21.1
|
||||
resolution: "@grafana/scenes@npm:6.21.1"
|
||||
dependencies:
|
||||
"@floating-ui/react": "npm:^0.26.16"
|
||||
"@leeoniya/ufuzzy": "npm:^1.0.16"
|
||||
"@tanstack/react-virtual": "npm:^3.9.0"
|
||||
i18next-parser: "npm:9.3.0"
|
||||
react-grid-layout: "npm:1.3.4"
|
||||
react-use: "npm:17.5.0"
|
||||
react-virtualized-auto-sizer: "npm:1.0.24"
|
||||
@@ -3531,13 +3532,14 @@ __metadata:
|
||||
peerDependencies:
|
||||
"@grafana/data": ">=10.4"
|
||||
"@grafana/e2e-selectors": ">=10.4"
|
||||
"@grafana/i18n": "*"
|
||||
"@grafana/runtime": ">=10.4"
|
||||
"@grafana/schema": ">=10.4"
|
||||
"@grafana/ui": ">=10.4"
|
||||
react: ^18.0.0
|
||||
react-dom: ^18.0.0
|
||||
react-router-dom: ^6.28.0
|
||||
checksum: 10/b71416a84773dbe684e348bdb71c8daa507b6e3d84225bc632d191389e8fbd6c7524b1098750bc07d886596786ec47107259966ef9303d603de04012a0ef4d37
|
||||
checksum: 10/e22f11389a66624d4e5e8addd813902d5c268e4dbe7ee32588c5049b11a540e86d938d52de57ad19a778a211db8f12210138db4ebf09e5ec6e2154522d4ba2da
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -18138,8 +18140,8 @@ __metadata:
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/prometheus": "workspace:*"
|
||||
"@grafana/runtime": "workspace:*"
|
||||
"@grafana/scenes": "npm:^6.20.1"
|
||||
"@grafana/scenes-react": "npm:^6.20.1"
|
||||
"@grafana/scenes": "npm:^6.21.0"
|
||||
"@grafana/scenes-react": "npm:^6.21.0"
|
||||
"@grafana/schema": "workspace:*"
|
||||
"@grafana/sql": "workspace:*"
|
||||
"@grafana/test-utils": "workspace:*"
|
||||
|
||||
Reference in New Issue
Block a user