I18n: Add useT hook for plugin translation API (#102033)
* Create placeholder useT function * expose useT() in @grafana/runtime * fix setting useT correctly * example usage of useT * rename hook to useTranslate * fix rename * remove comment
This commit is contained in:
+5
-1
@@ -887,7 +887,8 @@ exports[`better eslint`] = {
|
||||
"public/app/app.ts:5381": [
|
||||
[0, 0, 0, "\'@grafana/runtime/src/components/PanelDataErrorView\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
|
||||
[0, 0, 0, "\'@grafana/runtime/src/components/PanelRenderer\' import is restricted from being used by a pattern. Import from the public export instead.", "1"],
|
||||
[0, 0, 0, "\'@grafana/runtime/src/components/PluginPage\' import is restricted from being used by a pattern. Import from the public export instead.", "2"]
|
||||
[0, 0, 0, "\'@grafana/runtime/src/components/PluginPage\' import is restricted from being used by a pattern. Import from the public export instead.", "2"],
|
||||
[0, 0, 0, "\'@grafana/runtime/src/unstable\' import is restricted from being used by a pattern. Import from the public export instead.", "3"]
|
||||
],
|
||||
"public/app/core/TableModel.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
@@ -2883,6 +2884,9 @@ exports[`better eslint`] = {
|
||||
"public/app/features/auth-config/utils/data.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
],
|
||||
"public/app/features/bookmarks/BookmarksPage.tsx:5381": [
|
||||
[0, 0, 0, "\'@grafana/runtime/src/unstable\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
|
||||
],
|
||||
"public/app/features/browse-dashboards/api/browseDashboardsAPI.ts:5381": [
|
||||
[0, 0, 0, "Do not re-export imported variable (\`@reduxjs/toolkit/query/react\`)", "0"]
|
||||
],
|
||||
|
||||
@@ -9,5 +9,4 @@
|
||||
* and be subject to the standard policies
|
||||
*/
|
||||
|
||||
// Dummy export to make it a valid module. Remove when we have real exports.
|
||||
export const unstable = {};
|
||||
export { useTranslate as useT, setUseTranslateHook } from './utils/i18n';
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
type UseTranslateHook = () => (id: string, defaultMessage: string, values?: Record<string, unknown>) => string;
|
||||
|
||||
/**
|
||||
* Provides a i18next-compatible translation function.
|
||||
*/
|
||||
export let useTranslate: UseTranslateHook = () => {
|
||||
// Fallback implementation that should be overridden by setUseT
|
||||
const errorMessage = 'useT is not set. useT must not be called before Grafana is initialized.';
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
console.error(errorMessage);
|
||||
return (id: string, defaultMessage: string) => {
|
||||
return defaultMessage;
|
||||
};
|
||||
};
|
||||
|
||||
export function setUseTranslateHook(useTParam: UseTranslateHook) {
|
||||
useTranslate = useTParam;
|
||||
}
|
||||
+3
-1
@@ -45,6 +45,7 @@ import {
|
||||
import { setPanelDataErrorView } from '@grafana/runtime/src/components/PanelDataErrorView';
|
||||
import { setPanelRenderer } from '@grafana/runtime/src/components/PanelRenderer';
|
||||
import { setPluginPage } from '@grafana/runtime/src/components/PluginPage';
|
||||
import { setUseTranslateHook } from '@grafana/runtime/src/unstable';
|
||||
import config, { updateConfig } from 'app/core/config';
|
||||
import { getStandardTransformers } from 'app/features/transformers/standardTransformers';
|
||||
|
||||
@@ -58,7 +59,7 @@ import { getAllOptionEditors, getAllStandardFieldConfigs } from './core/componen
|
||||
import { PluginPage } from './core/components/Page/PluginPage';
|
||||
import { GrafanaContextType, useChromeHeaderHeight, useReturnToPreviousInternal } from './core/context/GrafanaContext';
|
||||
import { initializeCrashDetection } from './core/crash';
|
||||
import { initializeI18n } from './core/internationalization';
|
||||
import { initializeI18n, useTranslateInternal } from './core/internationalization';
|
||||
import { setMonacoEnv } from './core/monacoEnv';
|
||||
import { interceptLinkClicks } from './core/navigation/patch/interceptLinkClicks';
|
||||
import { CorrelationsService } from './core/services/CorrelationsService';
|
||||
@@ -253,6 +254,7 @@ export class GrafanaApp {
|
||||
|
||||
setReturnToPreviousHook(useReturnToPreviousInternal);
|
||||
setChromeHeaderHeightHook(useChromeHeaderHeight);
|
||||
setUseTranslateHook(useTranslateInternal);
|
||||
|
||||
if (config.featureToggles.crashDetection) {
|
||||
initializeCrashDetection();
|
||||
|
||||
@@ -72,6 +72,8 @@ export const Trans = (props: TransProps): ReactElement => {
|
||||
* This is a simple wrapper over i18n.t() to provide default namespaces and enforce a consistent API.
|
||||
* Note: Don't use this in the top level module scope. This wrapper needs initialization, which is done during Grafana
|
||||
* startup, and it will throw if used before.
|
||||
*
|
||||
* This will soon be deprecated in favor of useT()
|
||||
* @param id ID of the translation string
|
||||
* @param defaultMessage Default message to use if the translation is missing
|
||||
* @param values Values to be interpolated into the string
|
||||
@@ -111,3 +113,11 @@ export function getI18next() {
|
||||
|
||||
return i18nInstance || i18n;
|
||||
}
|
||||
|
||||
// We want to move to a react-only API for translations.
|
||||
// This hook doesn't do much now, but we want it to define the API for plugins.
|
||||
// Perhaps in the future this will use useTranslation from react-i18next or something else
|
||||
// from context
|
||||
export function useTranslateInternal() {
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import { GrafanaTheme2, NavModelItem } from '@grafana/data';
|
||||
import { useT } from '@grafana/runtime/src/unstable';
|
||||
import { EmptyState, useStyles2 } from '@grafana/ui';
|
||||
import { usePinnedItems } from 'app/core/components/AppChrome/MegaMenu/hooks';
|
||||
import { findByUrl } from 'app/core/components/AppChrome/MegaMenu/utils';
|
||||
import { NavLandingPageCard } from 'app/core/components/NavLandingPage/NavLandingPageCard';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
import { t, Trans } from 'app/core/internationalization';
|
||||
import { Trans } from 'app/core/internationalization';
|
||||
import { useSelector } from 'app/types';
|
||||
|
||||
export function BookmarksPage() {
|
||||
const t = useT();
|
||||
const styles = useStyles2(getStyles);
|
||||
const pinnedItems = usePinnedItems();
|
||||
const navTree = useSelector((state) => state.navBarTree);
|
||||
|
||||
Reference in New Issue
Block a user