diff --git a/contribute/internationalization.md b/contribute/internationalization.md index d33e354a5a7..bc117459808 100644 --- a/contribute/internationalization.md +++ b/contribute/internationalization.md @@ -75,9 +75,8 @@ const ErrorMessage = ({ id, message }) => There Sometimes you may need to translate a string cannot be represented in JSX, such as `placeholder` props. Use the `t` macro for this. ```jsx -import { useTranslate } from "@grafana/i18n" +import { t } from "@grafana/i18n" -const { t } = useTranslate(); const placeholder = t('form.username-placeholder','Username'); return @@ -211,9 +210,8 @@ import { Trans } from '@grafana/i18n'; ``` ```js -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; -const { t } = useTranslate(); const translatedString = t('inbox.heading', 'You got {{count}} messages', { count: messages.length }); ``` diff --git a/packages/grafana-i18n/src/i18n.tsx b/packages/grafana-i18n/src/i18n.tsx index 343061a6c42..6a5f3f25c05 100644 --- a/packages/grafana-i18n/src/i18n.tsx +++ b/packages/grafana-i18n/src/i18n.tsx @@ -192,11 +192,6 @@ export const t: TFunction = (id: string, defaultMessage: string, values?: Record return tFunc(id, defaultMessage, values); }; -export function useTranslate() { - initDefaultI18nInstance(); - return { t }; -} - export function Trans(props: TransProps) { initDefaultI18nInstance(); const Component = transComponent ?? I18NextTrans; diff --git a/packages/grafana-i18n/src/index.ts b/packages/grafana-i18n/src/index.ts index 1aa6432ed39..a4ebd2b5289 100644 --- a/packages/grafana-i18n/src/index.ts +++ b/packages/grafana-i18n/src/index.ts @@ -22,6 +22,6 @@ export { PSEUDO_LOCALE, DEFAULT_LANGUAGE, } from './constants'; -export { initPluginTranslations, Trans, useTranslate } from './i18n'; +export { initPluginTranslations, t, Trans } from './i18n'; export type { ResourceLoader, Resources, TFunction, TransProps } from './types'; export { formatDate, formatDuration, formatDateRange } from './dates'; diff --git a/packages/grafana-i18n/src/internal/index.ts b/packages/grafana-i18n/src/internal/index.ts index c54d0ef93fb..7757d7b622d 100644 --- a/packages/grafana-i18n/src/internal/index.ts +++ b/packages/grafana-i18n/src/internal/index.ts @@ -17,5 +17,4 @@ export { getLanguage, getResolvedLanguage, initializeI18n, - t, } from '../i18n'; diff --git a/public/app/api/clients/provisioning/index.ts b/public/app/api/clients/provisioning/index.ts index c206d8611fa..99a5ca42f23 100644 --- a/public/app/api/clients/provisioning/index.ts +++ b/public/app/api/clients/provisioning/index.ts @@ -1,4 +1,4 @@ -import { t } from '@grafana/i18n/internal'; +import { t } from '@grafana/i18n'; import { isFetchError } from '@grafana/runtime'; import { notifyApp } from 'app/core/actions'; import { createSuccessNotification, createErrorNotification } from 'app/core/copy/appNotification'; diff --git a/public/app/core/components/AccessControl/AddPermission.tsx b/public/app/core/components/AccessControl/AddPermission.tsx index 3b2cde7838b..c7569ff09f6 100644 --- a/public/app/core/components/AccessControl/AddPermission.tsx +++ b/public/app/core/components/AccessControl/AddPermission.tsx @@ -1,7 +1,6 @@ import { useEffect, useMemo, useState } from 'react'; -import { Trans } from '@grafana/i18n'; -import { t } from '@grafana/i18n/internal'; +import { Trans, t } from '@grafana/i18n'; import { Button, Select, Stack } from '@grafana/ui'; import { CloseButton } from 'app/core/components/CloseButton/CloseButton'; import { ServiceAccountPicker } from 'app/core/components/Select/ServiceAccountPicker'; diff --git a/public/app/core/components/AccessControl/PermissionListItem.tsx b/public/app/core/components/AccessControl/PermissionListItem.tsx index 5a18bd566b6..cab4decff7b 100644 --- a/public/app/core/components/AccessControl/PermissionListItem.tsx +++ b/public/app/core/components/AccessControl/PermissionListItem.tsx @@ -1,7 +1,7 @@ import { css } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; -import { Trans, useTranslate } from '@grafana/i18n'; +import { Trans, t } from '@grafana/i18n'; import { Box, Button, Icon, Select, Tooltip, useStyles2 } from '@grafana/ui'; import { ResourcePermission } from './types'; @@ -16,7 +16,7 @@ interface Props { export const PermissionListItem = ({ item, permissionLevels, canSet, onRemove, onChange }: Props) => { const styles = useStyles2(getStyles); - const { t } = useTranslate(); + return ( {getAvatar(item)} diff --git a/public/app/core/components/AccessControl/Permissions.tsx b/public/app/core/components/AccessControl/Permissions.tsx index 36b32270160..6106de8d640 100644 --- a/public/app/core/components/AccessControl/Permissions.tsx +++ b/public/app/core/components/AccessControl/Permissions.tsx @@ -4,8 +4,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import * as React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { Trans } from '@grafana/i18n'; -import { t } from '@grafana/i18n/internal'; +import { Trans, t } from '@grafana/i18n'; import { Text, Box, Button, useStyles2, Space } from '@grafana/ui'; import { SlideDown } from 'app/core/components/Animations/SlideDown'; import { getBackendSrv } from 'app/core/services/backend_srv'; diff --git a/public/app/core/components/AppChrome/AppChromeService.tsx b/public/app/core/components/AppChrome/AppChromeService.tsx index 68a98eef634..8c91066066b 100644 --- a/public/app/core/components/AppChrome/AppChromeService.tsx +++ b/public/app/core/components/AppChrome/AppChromeService.tsx @@ -2,7 +2,7 @@ import { useObservable } from 'react-use'; import { BehaviorSubject } from 'rxjs'; import { AppEvents, NavModel, NavModelItem, PageLayoutType, UrlQueryValue } from '@grafana/data'; -import { t } from '@grafana/i18n/internal'; +import { t } from '@grafana/i18n'; import { config, locationService, reportInteraction } from '@grafana/runtime'; import appEvents from 'app/core/app_events'; import store from 'app/core/store'; diff --git a/public/app/core/components/AppChrome/ExtensionSidebar/ExtensionToolbarItemButton.test.tsx b/public/app/core/components/AppChrome/ExtensionSidebar/ExtensionToolbarItemButton.test.tsx index 3756924f507..32b0b644a64 100644 --- a/public/app/core/components/AppChrome/ExtensionSidebar/ExtensionToolbarItemButton.test.tsx +++ b/public/app/core/components/AppChrome/ExtensionSidebar/ExtensionToolbarItemButton.test.tsx @@ -1,26 +1,18 @@ import { render, screen, fireEvent } from '@testing-library/react'; -import { useTranslate } from '@grafana/i18n'; - import { ExtensionToolbarItemButton } from './ExtensionToolbarItemButton'; // Mock the useTranslate hook jest.mock('@grafana/i18n', () => ({ - useTranslate: jest.fn(), -})); - -describe('ExtensionToolbarItemButton', () => { - const mockTranslate = (_: string, fallback: string, values?: Record) => { + t: (_: string, fallback: string, values?: Record) => { if (values) { return fallback.replace('{{title}}', values.title); } return fallback; - }; - - beforeEach(() => { - (useTranslate as jest.Mock).mockReturnValue({ t: mockTranslate }); - }); + }, +})); +describe('ExtensionToolbarItemButton', () => { it('renders open button with default tooltip when no title is provided', () => { render(); diff --git a/public/app/core/components/AppChrome/ExtensionSidebar/ExtensionToolbarItemButton.tsx b/public/app/core/components/AppChrome/ExtensionSidebar/ExtensionToolbarItemButton.tsx index 070698d4190..da79fc15536 100644 --- a/public/app/core/components/AppChrome/ExtensionSidebar/ExtensionToolbarItemButton.tsx +++ b/public/app/core/components/AppChrome/ExtensionSidebar/ExtensionToolbarItemButton.tsx @@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css'; import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; import { ToolbarButton, useStyles2 } from '@grafana/ui'; interface ToolbarItemButtonProps { @@ -16,7 +16,6 @@ function ExtensionToolbarItemButtonComponent( ref: React.ForwardedRef ) { const styles = useStyles2(getStyles); - const { t } = useTranslate(); if (isOpen) { // render button to close the sidebar diff --git a/public/app/core/components/AppChrome/History/HistoryContainer.tsx b/public/app/core/components/AppChrome/History/HistoryContainer.tsx index d2e677f3b12..88cbde02856 100644 --- a/public/app/core/components/AppChrome/History/HistoryContainer.tsx +++ b/public/app/core/components/AppChrome/History/HistoryContainer.tsx @@ -3,7 +3,7 @@ import { useEffect } from 'react'; import { useToggle } from 'react-use'; import { GrafanaTheme2, store } from '@grafana/data'; -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; import { Drawer, ToolbarButton, useStyles2 } from '@grafana/ui'; import { appEvents } from 'app/core/app_events'; import { RecordHistoryEntryEvent } from 'app/types/events'; @@ -47,7 +47,6 @@ export function HistoryContainer() { }; }); }, []); - const { t } = useTranslate(); return ( <> diff --git a/public/app/core/components/AppChrome/History/HistoryWrapper.tsx b/public/app/core/components/AppChrome/History/HistoryWrapper.tsx index a0713e30055..f6120e81c8c 100644 --- a/public/app/core/components/AppChrome/History/HistoryWrapper.tsx +++ b/public/app/core/components/AppChrome/History/HistoryWrapper.tsx @@ -3,7 +3,7 @@ import moment from 'moment'; import { useState } from 'react'; import { FieldType, GrafanaTheme2, store } from '@grafana/data'; -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; import { Button, Card, IconButton, Space, Stack, Text, useStyles2, Box, Sparkline, useTheme2, Icon } from '@grafana/ui'; import { formatDate } from 'app/core/internationalization/dates'; @@ -13,7 +13,6 @@ import { HistoryEntry } from '../types'; import { logClickUnifiedHistoryEntryEvent, logUnifiedHistoryShowMoreEvent } from './eventsTracking'; export function HistoryWrapper({ onClose }: { onClose: () => void }) { - const { t } = useTranslate(); const history = store.getObject(HISTORY_LOCAL_STORAGE_KEY, []).filter((entry) => { return moment(entry.time).isAfter(moment().subtract(2, 'day').startOf('day')); }); @@ -89,7 +88,7 @@ function HistoryEntryAppView({ entry, isSelected, onClick }: ItemProps) { const styles = useStyles2(getStyles); const theme = useTheme2(); const [isExpanded, setIsExpanded] = useState(isSelected && entry.views.length > 0); - const { t } = useTranslate(); + const { breadcrumbs, views, time, url, sparklineData } = entry; const expandedLabel = isExpanded ? t('nav.history-wrapper.collapse', 'Collapse') diff --git a/public/app/core/components/AppChrome/MegaMenu/MegaMenu.tsx b/public/app/core/components/AppChrome/MegaMenu/MegaMenu.tsx index 4e68c1b8f18..9f85383b4d8 100644 --- a/public/app/core/components/AppChrome/MegaMenu/MegaMenu.tsx +++ b/public/app/core/components/AppChrome/MegaMenu/MegaMenu.tsx @@ -5,7 +5,7 @@ import { useLocation } from 'react-router-dom-v5-compat'; import { GrafanaTheme2, NavModelItem } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; import { config, reportInteraction } from '@grafana/runtime'; import { ScrollContainer, useStyles2 } from '@grafana/ui'; import { useGrafana } from 'app/core/context/GrafanaContext'; @@ -37,7 +37,7 @@ export const MegaMenu = memo( const state = chrome.useState(); const [patchPreferences] = usePatchUserPreferencesMutation(); const pinnedItems = usePinnedItems(); - const { t } = useTranslate(); + // Remove profile + help from tree const navItems = navTree .filter((item) => item.id !== 'profile' && item.id !== 'help') diff --git a/public/app/core/components/AppChrome/MegaMenu/MegaMenuHeader.tsx b/public/app/core/components/AppChrome/MegaMenu/MegaMenuHeader.tsx index b44c3e62745..7a5dc8d8d4f 100644 --- a/public/app/core/components/AppChrome/MegaMenu/MegaMenuHeader.tsx +++ b/public/app/core/components/AppChrome/MegaMenu/MegaMenuHeader.tsx @@ -1,7 +1,7 @@ import { css } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; import { IconButton, Stack, ToolbarButton, useTheme2 } from '@grafana/ui'; import { useGrafana } from 'app/core/context/GrafanaContext'; @@ -22,7 +22,7 @@ export function MegaMenuHeader({ handleMegaMenu, handleDockedMenu, onClose }: Pr const theme = useTheme2(); const { chrome } = useGrafana(); const state = chrome.useState(); - const { t } = useTranslate(); + const styles = getStyles(theme); return ( diff --git a/public/app/core/components/AppChrome/MegaMenu/MegaMenuItem.tsx b/public/app/core/components/AppChrome/MegaMenu/MegaMenuItem.tsx index fe99a1efad8..4c8afa5671f 100644 --- a/public/app/core/components/AppChrome/MegaMenu/MegaMenuItem.tsx +++ b/public/app/core/components/AppChrome/MegaMenu/MegaMenuItem.tsx @@ -5,7 +5,7 @@ import { useLocation } from 'react-router-dom-v5-compat'; import { useLocalStorage } from 'react-use'; import { FeatureState, GrafanaTheme2, NavModelItem, toIconName } from '@grafana/data'; -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; import { useStyles2, Text, IconButton, Icon, Stack, FeatureBadge } from '@grafana/ui'; import { useGrafana } from 'app/core/context/GrafanaContext'; @@ -58,7 +58,6 @@ export function MegaMenuItem({ link, activeItem, level = 0, onClick, onPin, isPi }); } }, [isActive]); - const { t } = useTranslate(); if (!link.url) { return null; diff --git a/public/app/core/components/AppChrome/MegaMenu/MegaMenuItemText.tsx b/public/app/core/components/AppChrome/MegaMenu/MegaMenuItemText.tsx index 1b9434aa313..b76e6006d78 100644 --- a/public/app/core/components/AppChrome/MegaMenu/MegaMenuItemText.tsx +++ b/public/app/core/components/AppChrome/MegaMenu/MegaMenuItemText.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; import { config } from '@grafana/runtime'; import { Icon, IconButton, Link, useTheme2 } from '@grafana/ui'; import { contextSrv } from 'app/core/services/context_srv'; @@ -20,7 +20,7 @@ export interface Props { export function MegaMenuItemText({ children, isActive, onClick, target, url, onPin, isPinned }: Props) { const theme = useTheme2(); - const { t } = useTranslate(); + const styles = getStyles(theme, isActive); const LinkComponent = !target && url.startsWith('/') ? Link : 'a'; diff --git a/public/app/core/components/AppChrome/MegaMenu/utils.ts b/public/app/core/components/AppChrome/MegaMenu/utils.ts index 55ec4af5389..9996db02879 100644 --- a/public/app/core/components/AppChrome/MegaMenu/utils.ts +++ b/public/app/core/components/AppChrome/MegaMenu/utils.ts @@ -1,7 +1,7 @@ import { useEffect } from 'react'; import { NavModelItem } from '@grafana/data'; -import { t } from '@grafana/i18n/internal'; +import { t } from '@grafana/i18n'; import { config, reportInteraction } from '@grafana/runtime'; import { MEGA_MENU_TOGGLE_ID } from 'app/core/constants'; import { HOME_NAV_ID } from 'app/core/reducers/navModel'; diff --git a/public/app/core/components/AppChrome/News/NewsDrawer.tsx b/public/app/core/components/AppChrome/News/NewsDrawer.tsx index d582a5267b4..f2122497204 100644 --- a/public/app/core/components/AppChrome/News/NewsDrawer.tsx +++ b/public/app/core/components/AppChrome/News/NewsDrawer.tsx @@ -2,7 +2,7 @@ import { css } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; import { IconButton, Drawer, useStyles2, Text } from '@grafana/ui'; import { DEFAULT_FEED_URL } from 'app/plugins/panel/news/constants'; import grotNewsSvg from 'img/grot-news.svg'; @@ -16,7 +16,7 @@ interface NewsContainerProps { export function NewsContainer({ onClose }: NewsContainerProps) { const styles = useStyles2(getStyles); - const { t } = useTranslate(); + return ( { getNews(); }, [getNews]); - const { t } = useTranslate(); if (state.error) { return
{state.error && state.error.message}
; diff --git a/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSelect.tsx b/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSelect.tsx index b75688a9c8c..2a33cf03123 100644 --- a/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSelect.tsx +++ b/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSelect.tsx @@ -2,7 +2,7 @@ import { css } from '@emotion/css'; import { useMemo, useState } from 'react'; import { SelectableValue, GrafanaTheme2 } from '@grafana/data'; -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; import { Icon, Select, useStyles2 } from '@grafana/ui'; import { contextSrv } from 'app/core/services/context_srv'; import { UserOrg } from 'app/types'; @@ -11,7 +11,7 @@ import { OrganizationBaseProps } from './types'; export function OrganizationSelect({ orgs, onSelectChange }: OrganizationBaseProps) { const styles = useStyles2(getStyles); - const { t } = useTranslate(); + const { orgId } = contextSrv.user; const options = useMemo( diff --git a/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx b/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx index 74b8749144a..a528a0c8341 100644 --- a/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx +++ b/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx @@ -1,6 +1,6 @@ import { useMemo, useState } from 'react'; -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; import { reportInteraction } from '@grafana/runtime'; import { Menu, Dropdown, ToolbarButton } from '@grafana/ui'; import { getExternalUserMngLinkUrl } from 'app/features/users/utils'; @@ -16,7 +16,7 @@ export interface Props {} export const QuickAdd = ({}: Props) => { const navBarTree = useSelector((state) => state.navBarTree); const [isOpen, setIsOpen] = useState(false); - const { t } = useTranslate(); + const createActions = useMemo(() => { const actions = findCreateActions(navBarTree); @@ -33,7 +33,7 @@ export const QuickAdd = ({}: Props) => { } return actions; - }, [navBarTree, t]); + }, [navBarTree]); const showQuickAdd = createActions.length > 0; if (!showQuickAdd) { diff --git a/public/app/core/components/AppChrome/ReturnToPrevious/DismissableButton.tsx b/public/app/core/components/AppChrome/ReturnToPrevious/DismissableButton.tsx index b618f69c291..ad417de2745 100644 --- a/public/app/core/components/AppChrome/ReturnToPrevious/DismissableButton.tsx +++ b/public/app/core/components/AppChrome/ReturnToPrevious/DismissableButton.tsx @@ -2,7 +2,7 @@ import { css } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { useTranslate } from '@grafana/i18n'; +import { t } from '@grafana/i18n'; import { Button, ButtonGroup, useStyles2 } from '@grafana/ui'; export interface DismissableButtonProps { @@ -13,7 +13,7 @@ export interface DismissableButtonProps { export const DismissableButton = ({ label, onClick, onDismiss }: DismissableButtonProps) => { const styles = useStyles2(getStyles); - const { t } = useTranslate(); + return (