mirror of
https://github.com/grafana/grafana.git
synced 2025-07-30 10:42:20 +08:00

* i18n: adds grafana/i18n * Trigger build * chore: fix frontend lint * chore: refactor * chore: refactor * chore: expose getI18nInstance in shared deps * chore: refactors away second init * Trigger build * chore: updates after PR feedback * chore: sync with enterprise * chore: adds shouldUnescape * Trigger build * chore: makes functions internal * Trigger build * chore: fix for Pseudo locale * chore: bumps package version * chore: fix the version of i18n package
144 lines
5.1 KiB
TypeScript
144 lines
5.1 KiB
TypeScript
import { i18n } from 'i18next';
|
|
|
|
import * as i18nModule from '@grafana/i18n/internal';
|
|
|
|
import { server } from './loader/pluginLoader.mock';
|
|
import { SystemJS } from './loader/systemjs';
|
|
import { SystemJSWithLoaderHooks } from './loader/types';
|
|
import { addTranslationsToI18n } from './plugin_loader';
|
|
|
|
describe('plugin_loader', () => {
|
|
describe('addTranslationsToI18n', () => {
|
|
const systemJSPrototype: SystemJSWithLoaderHooks = SystemJS.constructor.prototype;
|
|
const originalFetch = systemJSPrototype.fetch;
|
|
const originalResolve = systemJSPrototype.resolve;
|
|
let addResourceBundleSpy: jest.SpyInstance;
|
|
|
|
beforeAll(() => {
|
|
server.listen();
|
|
systemJSPrototype.resolve = (moduleId: string) => moduleId;
|
|
systemJSPrototype.shouldFetch = () => true;
|
|
// because server.listen() patches fetch, we need to reassign this to the systemJSPrototype
|
|
// this is identical to what happens in the original code: https://github.com/systemjs/systemjs/blob/main/src/features/fetch-load.js#L12
|
|
systemJSPrototype.fetch = window.fetch;
|
|
});
|
|
|
|
beforeEach(() => {
|
|
addResourceBundleSpy = jest
|
|
.spyOn(i18nModule, 'addResourceBundle')
|
|
.mockImplementation(() => ({}) as unknown as i18n);
|
|
});
|
|
|
|
afterEach(() => {
|
|
server.resetHandlers();
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
afterAll(() => {
|
|
SystemJS.constructor.prototype.resolve = originalResolve;
|
|
SystemJS.constructor.prototype.fetch = originalFetch;
|
|
server.close();
|
|
});
|
|
|
|
it('should add translations that match the resolved language first', async () => {
|
|
const translations = {
|
|
'en-US': '/public/plugins/test-panel/locales/en-US/test-panel.json',
|
|
'pt-BR': '/public/plugins/test-panel/locales/pt-BR/test-panel.json',
|
|
};
|
|
|
|
await addTranslationsToI18n({
|
|
resolvedLanguage: 'pt-BR',
|
|
fallbackLanguage: 'en-US',
|
|
pluginId: 'test-panel',
|
|
translations,
|
|
});
|
|
|
|
expect(addResourceBundleSpy).toHaveBeenCalledTimes(1);
|
|
expect(addResourceBundleSpy).toHaveBeenNthCalledWith(1, 'pt-BR', 'test-panel', { testKey: 'valorDeTeste' });
|
|
});
|
|
|
|
it('should add translations that match the fallback language if the resolved language is not in the translations', async () => {
|
|
const translations = {
|
|
'en-US': '/public/plugins/test-panel/locales/en-US/test-panel.json',
|
|
'pt-BR': '/public/plugins/test-panel/locales/pt-BR/test-panel.json',
|
|
};
|
|
|
|
await addTranslationsToI18n({
|
|
resolvedLanguage: 'sv-SE',
|
|
fallbackLanguage: 'en-US',
|
|
pluginId: 'test-panel',
|
|
translations,
|
|
});
|
|
|
|
expect(addResourceBundleSpy).toHaveBeenCalledTimes(1);
|
|
expect(addResourceBundleSpy).toHaveBeenNthCalledWith(1, 'en-US', 'test-panel', { testKey: 'testValue' });
|
|
});
|
|
|
|
it('should warn if no translations are found', async () => {
|
|
const translations = {
|
|
'en-US': '/public/plugins/test-panel/locales/en-US/test-panel.json',
|
|
'pt-BR': '/public/plugins/test-panel/locales/pt-BR/test-panel.json',
|
|
};
|
|
|
|
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
|
|
await addTranslationsToI18n({
|
|
resolvedLanguage: 'sv-SE',
|
|
fallbackLanguage: 'sv-SE',
|
|
pluginId: 'test-panel',
|
|
translations,
|
|
});
|
|
|
|
expect(consoleSpy).toHaveBeenCalledWith('Could not find any translation for plugin test-panel', {
|
|
resolvedLanguage: 'sv-SE',
|
|
fallbackLanguage: 'sv-SE',
|
|
});
|
|
});
|
|
|
|
it('should warn if no exported default is found', async () => {
|
|
const translations = {
|
|
'en-US': '/public/plugins/test-panel/locales/en-US/no-default-export.json',
|
|
'pt-BR': '/public/plugins/test-panel/locales/pt-BR/no-default-export.json',
|
|
};
|
|
|
|
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
|
|
await addTranslationsToI18n({
|
|
resolvedLanguage: 'en-US',
|
|
fallbackLanguage: 'en-US',
|
|
pluginId: 'test-panel',
|
|
translations,
|
|
});
|
|
|
|
expect(consoleSpy).toHaveBeenCalledWith('Could not find default export for plugin test-panel', {
|
|
resolvedLanguage: 'en-US',
|
|
fallbackLanguage: 'en-US',
|
|
path: '/public/plugins/test-panel/locales/en-US/no-default-export.json',
|
|
});
|
|
});
|
|
|
|
it('should warn if translations cannot be loaded', async () => {
|
|
const translations = {
|
|
'en-US': '/public/plugins/test-panel/locales/en-US/unknown.json',
|
|
'pt-BR': '/public/plugins/test-panel/locales/pt-BR/unknown.json',
|
|
};
|
|
|
|
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
|
|
await addTranslationsToI18n({
|
|
resolvedLanguage: 'en-US',
|
|
fallbackLanguage: 'pt-BR',
|
|
pluginId: 'test-panel',
|
|
translations,
|
|
});
|
|
|
|
expect(consoleSpy).toHaveBeenCalledWith('Could not load translation for plugin test-panel', {
|
|
resolvedLanguage: 'en-US',
|
|
fallbackLanguage: 'pt-BR',
|
|
error: new TypeError('Failed to fetch'),
|
|
path: '/public/plugins/test-panel/locales/en-US/unknown.json',
|
|
});
|
|
});
|
|
});
|
|
});
|