Internationalization: Translate page headers and Search dashboard actions (#60727)

* Fix: PageHeader & PageHeaderTabs & NavBarItem & DashboardActions & PanelMenu is displayed in default_language (#60719)

* I18N: update strings (#60719)

Co-authored-by: TaitChan <1441645821@qq.coom>
This commit is contained in:
TaitChan 2023-01-13 22:33:42 +08:00 committed by GitHub
parent ed88401a58
commit a1d33c63c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 156 additions and 37 deletions

View File

@ -13,6 +13,8 @@ export function getNavTitle(navId: string | undefined) {
switch (navId) { switch (navId) {
case 'home': case 'home':
return t('nav.home.title', 'Home'); return t('nav.home.title', 'Home');
case 'new':
return t('nav.new.title', 'New');
case 'create': case 'create':
return t('nav.create.title', 'Create'); return t('nav.create.title', 'Create');
case 'create-dashboard': case 'create-dashboard':
@ -43,6 +45,8 @@ export function getNavTitle(navId: string | undefined) {
return t('nav.new-dashboard.title', 'New dashboard'); return t('nav.new-dashboard.title', 'New dashboard');
case 'dashboards/folder/new': case 'dashboards/folder/new':
return t('nav.new-folder.title', 'New folder'); return t('nav.new-folder.title', 'New folder');
case 'dashboards/import':
return t('nav.create-import.title', 'Import');
case 'scenes': case 'scenes':
return t('nav.scenes.title', 'Scenes'); return t('nav.scenes.title', 'Scenes');
case 'explore': case 'explore':

View File

@ -3,6 +3,7 @@ import React, { FC } from 'react';
import { NavModelItem, NavModelBreadcrumb, GrafanaTheme2 } from '@grafana/data'; import { NavModelItem, NavModelBreadcrumb, GrafanaTheme2 } from '@grafana/data';
import { Tab, TabsBar, Icon, useStyles2, toIconName } from '@grafana/ui'; import { Tab, TabsBar, Icon, useStyles2, toIconName } from '@grafana/ui';
import { getNavTitle, getNavSubTitle } from 'app/core/components/NavBar/navBarItem-translations';
import { PanelHeaderMenuItem } from 'app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem'; import { PanelHeaderMenuItem } from 'app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem';
import { PageInfoItem } from '../Page/types'; import { PageInfoItem } from '../Page/types';
@ -71,7 +72,7 @@ const Navigation = ({ children }: { children: NavModelItem[] }) => {
return ( return (
!child.hideFromTabs && ( !child.hideFromTabs && (
<Tab <Tab
label={child.text} label={getNavTitle(child.id) ?? child.text}
active={child.active} active={child.active}
key={`${child.url}-${index}`} key={`${child.url}-${index}`}
icon={child.icon} icon={child.icon}
@ -96,19 +97,18 @@ export const PageHeader: FC<Props> = ({ navItem: model, renderTitle, actions, in
const renderHeader = (main: NavModelItem) => { const renderHeader = (main: NavModelItem) => {
const marginTop = main.icon === 'grafana' ? 12 : 14; const marginTop = main.icon === 'grafana' ? 12 : 14;
const icon = main.icon && toIconName(main.icon); const icon = main.icon && toIconName(main.icon);
const sub = subTitle ?? main.subTitle; const sub = subTitle ?? getNavSubTitle(main.id) ?? main.subTitle;
const text = getNavTitle(main.id) ?? main.text;
return ( return (
<div className="page-header__inner"> <div className="page-header__inner">
<span className="page-header__logo"> <span className="page-header__logo">
{icon && <Icon name={icon} size="xxxl" style={{ marginTop }} />} {icon && <Icon name={icon} size="xxxl" style={{ marginTop }} />}
{main.img && <img className="page-header__img" src={main.img} alt={`logo of ${main.text}`} />} {main.img && <img className="page-header__img" src={main.img} alt={`logo of ${text}`} />}
</span> </span>
<div className={cx('page-header__info-block', styles.headerText)}> <div className={cx('page-header__info-block', styles.headerText)}>
{renderTitle {renderTitle ? renderTitle(text) : renderHeaderTitle(text, main.breadcrumbs ?? [], main.highlightText)}
? renderTitle(main.text)
: renderHeaderTitle(main.text, main.breadcrumbs ?? [], main.highlightText)}
{info && <PageInfo info={info} />} {info && <PageInfo info={info} />}
{sub && <div className="page-header__sub-title">{sub}</div>} {sub && <div className="page-header__sub-title">{sub}</div>}
{actions && <div className={styles.actions}>{actions}</div>} {actions && <div className={styles.actions}>{actions}</div>}

View File

@ -109,9 +109,8 @@ export function getPanelMenu(
const menu: PanelMenuItem[] = []; const menu: PanelMenuItem[] = [];
if (!panel.isEditing) { if (!panel.isEditing) {
const viewTextTranslation = t('panel.header-menu.view', `View`);
menu.push({ menu.push({
text: viewTextTranslation, text: t('panel.header-menu.view', `View`),
iconClassName: 'eye', iconClassName: 'eye',
onClick: onViewPanel, onClick: onViewPanel,
shortcut: 'v', shortcut: 'v',
@ -120,7 +119,7 @@ export function getPanelMenu(
if (dashboard.canEditPanel(panel) && !panel.isEditing) { if (dashboard.canEditPanel(panel) && !panel.isEditing) {
menu.push({ menu.push({
text: 'Edit', text: t('panel.header-menu.edit', `Edit`),
iconClassName: 'edit', iconClassName: 'edit',
onClick: onEditPanel, onClick: onEditPanel,
shortcut: 'e', shortcut: 'e',
@ -138,10 +137,8 @@ export function getPanelMenu(
}); });
} }
const shareTextTranslation = t('panel.header-menu.share', `Share`);
menu.push({ menu.push({
text: shareTextTranslation, text: t('panel.header-menu.share', `Share`),
iconClassName: 'share-alt', iconClassName: 'share-alt',
onClick: onSharePanel, onClick: onSharePanel,
shortcut: 'p s', shortcut: 'p s',
@ -149,7 +146,7 @@ export function getPanelMenu(
if (contextSrv.hasAccessToExplore() && !(panel.plugin && panel.plugin.meta.skipDataQuery)) { if (contextSrv.hasAccessToExplore() && !(panel.plugin && panel.plugin.meta.skipDataQuery)) {
menu.push({ menu.push({
text: 'Explore', text: t('panel.header-menu.explore', `Explore`),
iconClassName: 'compass', iconClassName: 'compass',
onClick: onNavigateToExplore, onClick: onNavigateToExplore,
shortcut: 'x', shortcut: 'x',
@ -160,33 +157,27 @@ export function getPanelMenu(
// Only show these inspect actions for data plugins // Only show these inspect actions for data plugins
if (panel.plugin && !panel.plugin.meta.skipDataQuery) { if (panel.plugin && !panel.plugin.meta.skipDataQuery) {
const dataTextTranslation = t('panel.header-menu.inspect-data', `Data`);
inspectMenu.push({ inspectMenu.push({
text: dataTextTranslation, text: t('panel.header-menu.inspect-data', `Data`),
onClick: (e: React.MouseEvent<any>) => onInspectPanel(InspectTab.Data), onClick: (e: React.MouseEvent<any>) => onInspectPanel(InspectTab.Data),
}); });
if (dashboard.meta.canEdit) { if (dashboard.meta.canEdit) {
inspectMenu.push({ inspectMenu.push({
text: 'Query', text: t('panel.header-menu.query', `Query`),
onClick: (e: React.MouseEvent<any>) => onInspectPanel(InspectTab.Query), onClick: (e: React.MouseEvent<any>) => onInspectPanel(InspectTab.Query),
}); });
} }
} }
const jsonTextTranslation = t('panel.header-menu.inspect-json', `Panel JSON`);
inspectMenu.push({ inspectMenu.push({
text: jsonTextTranslation, text: t('panel.header-menu.inspect-json', `Panel JSON`),
onClick: (e: React.MouseEvent<any>) => onInspectPanel(InspectTab.JSON), onClick: (e: React.MouseEvent<any>) => onInspectPanel(InspectTab.JSON),
}); });
const inspectTextTranslation = t('panel.header-menu.inspect', `Inspect`);
menu.push({ menu.push({
type: 'submenu', type: 'submenu',
text: inspectTextTranslation, text: t('panel.header-menu.inspect', `Inspect`),
iconClassName: 'info-circle', iconClassName: 'info-circle',
onClick: (e: React.MouseEvent<any>) => onInspectPanel(), onClick: (e: React.MouseEvent<any>) => onInspectPanel(),
shortcut: 'i', shortcut: 'i',
@ -198,24 +189,24 @@ export function getPanelMenu(
if (canEdit && !(panel.isViewing || panel.isEditing)) { if (canEdit && !(panel.isViewing || panel.isEditing)) {
subMenu.push({ subMenu.push({
text: 'Duplicate', text: t('panel.header-menu.duplicate', `Duplicate`),
onClick: onDuplicatePanel, onClick: onDuplicatePanel,
shortcut: 'p d', shortcut: 'p d',
}); });
subMenu.push({ subMenu.push({
text: 'Copy', text: t('panel.header-menu.copy', `Copy`),
onClick: onCopyPanel, onClick: onCopyPanel,
}); });
if (isPanelModelLibraryPanel(panel)) { if (isPanelModelLibraryPanel(panel)) {
subMenu.push({ subMenu.push({
text: 'Unlink library panel', text: t('panel.header-menu.unlink-library-panel', `Unlink library panel`),
onClick: onUnlinkLibraryPanel, onClick: onUnlinkLibraryPanel,
}); });
} else { } else {
subMenu.push({ subMenu.push({
text: 'Create library panel', text: t('panel.header-menu.create-library-panel', `Create library panel`),
onClick: onAddLibraryPanel, onClick: onAddLibraryPanel,
}); });
} }
@ -261,16 +252,15 @@ export function getPanelMenu(
if (canEdit && panel.plugin && !panel.plugin.meta.skipDataQuery) { if (canEdit && panel.plugin && !panel.plugin.meta.skipDataQuery) {
subMenu.push({ subMenu.push({
text: 'Get help', text: t('panel.header-menu.get-help', 'Get help'),
onClick: (e: React.MouseEvent) => onInspectPanel(InspectTab.Help), onClick: (e: React.MouseEvent) => onInspectPanel(InspectTab.Help),
}); });
} }
if (subMenu.length) { if (subMenu.length) {
const moreTextTranslation = t('panel.header-menu.more', `More...`);
menu.push({ menu.push({
type: 'submenu', type: 'submenu',
text: moreTextTranslation, text: t('panel.header-menu.more', `More...`),
iconClassName: 'cube', iconClassName: 'cube',
subMenu, subMenu,
onClick: onMore, onClick: onMore,
@ -281,7 +271,7 @@ export function getPanelMenu(
menu.push({ type: 'divider', text: '' }); menu.push({ type: 'divider', text: '' });
menu.push({ menu.push({
text: 'Remove', text: t('panel.header-menu.remove', `Remove`),
iconClassName: 'trash-alt', iconClassName: 'trash-alt',
onClick: onRemovePanel, onClick: onRemovePanel,
shortcut: 'p r', shortcut: 'p r',

View File

@ -2,6 +2,7 @@ import React, { FC } from 'react';
import { config } from '@grafana/runtime'; import { config } from '@grafana/runtime';
import { Menu, Dropdown, Button, Icon } from '@grafana/ui'; import { Menu, Dropdown, Button, Icon } from '@grafana/ui';
import { t } from 'app/core/internationalization';
export interface Props { export interface Props {
folderUid?: string; folderUid?: string;
@ -28,11 +29,15 @@ export const DashboardActions: FC<Props> = ({ folderUid, canCreateFolders = fals
const MenuActions = () => { const MenuActions = () => {
return ( return (
<Menu> <Menu>
{canCreateDashboards && <Menu.Item url={actionUrl('new')} label="New Dashboard" />} {canCreateDashboards && (
{canCreateFolders && (config.featureToggles.nestedFolders || !folderUid) && ( <Menu.Item url={actionUrl('new')} label={t('search.dashboard-actions.new-dashboard', 'New Dashboard')} />
<Menu.Item url={actionUrl('new_folder')} label="New Folder" /> )}
{canCreateFolders && (config.featureToggles.nestedFolders || !folderUid) && (
<Menu.Item url={actionUrl('new_folder')} label={t('search.dashboard-actions.new-folder', 'New Folder')} />
)}
{canCreateDashboards && (
<Menu.Item url={actionUrl('import')} label={t('search.dashboard-actions.import', 'Import')} />
)} )}
{canCreateDashboards && <Menu.Item url={actionUrl('import')} label="Import" />}
</Menu> </Menu>
); );
}; };
@ -41,7 +46,7 @@ export const DashboardActions: FC<Props> = ({ folderUid, canCreateFolders = fals
<div> <div>
<Dropdown overlay={MenuActions} placement="bottom-start"> <Dropdown overlay={MenuActions} placement="bottom-start">
<Button variant="primary"> <Button variant="primary">
New {t('search.dashboard-actions.new', 'New')}
<Icon name="angle-down" /> <Icon name="angle-down" />
</Button> </Button>
</Dropdown> </Dropdown>

View File

@ -253,6 +253,9 @@
"subtitle": "Überwachungs- und Infrastruktur-Apps", "subtitle": "Überwachungs- und Infrastruktur-Apps",
"title": "Überwachung" "title": "Überwachung"
}, },
"new": {
"title": ""
},
"new-dashboard": { "new-dashboard": {
"title": "Neues Dashboard" "title": "Neues Dashboard"
}, },
@ -347,13 +350,22 @@
}, },
"panel": { "panel": {
"header-menu": { "header-menu": {
"copy": "",
"create-library-panel": "",
"duplicate": "",
"edit": "",
"explore": "",
"get-help": "",
"hide-legend": "Legende ausblenden", "hide-legend": "Legende ausblenden",
"inspect": "Überprüfen", "inspect": "Überprüfen",
"inspect-data": "Daten", "inspect-data": "Daten",
"inspect-json": "Panel-JSON", "inspect-json": "Panel-JSON",
"more": "Mehr …", "more": "Mehr …",
"query": "",
"remove": "",
"share": "Teilen", "share": "Teilen",
"show-legend": "Legende anzeigen", "show-legend": "Legende anzeigen",
"unlink-library-panel": "",
"view": "Anzeigen" "view": "Anzeigen"
} }
}, },
@ -374,6 +386,14 @@
"auto-refresh": "Automatisches Aktualisierungsintervall festlegen" "auto-refresh": "Automatisches Aktualisierungsintervall festlegen"
} }
}, },
"search": {
"dashboard-actions": {
"import": "",
"new": "",
"new-dashboard": "",
"new-folder": ""
}
},
"share-modal": { "share-modal": {
"dashboard": { "dashboard": {
"title": "Teilen" "title": "Teilen"

View File

@ -253,6 +253,9 @@
"subtitle": "Monitoring and infrastructure apps", "subtitle": "Monitoring and infrastructure apps",
"title": "Monitoring" "title": "Monitoring"
}, },
"new": {
"title": "New"
},
"new-dashboard": { "new-dashboard": {
"title": "New dashboard" "title": "New dashboard"
}, },
@ -347,13 +350,22 @@
}, },
"panel": { "panel": {
"header-menu": { "header-menu": {
"copy": "Copy",
"create-library-panel": "Create library panel",
"duplicate": "Duplicate",
"edit": "Edit",
"explore": "Explore",
"get-help": "Get help",
"hide-legend": "Hide legend", "hide-legend": "Hide legend",
"inspect": "Inspect", "inspect": "Inspect",
"inspect-data": "Data", "inspect-data": "Data",
"inspect-json": "Panel JSON", "inspect-json": "Panel JSON",
"more": "More...", "more": "More...",
"query": "Query",
"remove": "Remove",
"share": "Share", "share": "Share",
"show-legend": "Show legend", "show-legend": "Show legend",
"unlink-library-panel": "Unlink library panel",
"view": "View" "view": "View"
} }
}, },
@ -374,6 +386,14 @@
"auto-refresh": "Set auto refresh interval" "auto-refresh": "Set auto refresh interval"
} }
}, },
"search": {
"dashboard-actions": {
"import": "Import",
"new": "New",
"new-dashboard": "New Dashboard",
"new-folder": "New Folder"
}
},
"share-modal": { "share-modal": {
"dashboard": { "dashboard": {
"title": "Share" "title": "Share"

View File

@ -253,6 +253,9 @@
"subtitle": "Aplicaciones de supervisión e infraestructura", "subtitle": "Aplicaciones de supervisión e infraestructura",
"title": "Seguimiento" "title": "Seguimiento"
}, },
"new": {
"title": ""
},
"new-dashboard": { "new-dashboard": {
"title": "Nuevo panel de control" "title": "Nuevo panel de control"
}, },
@ -347,13 +350,22 @@
}, },
"panel": { "panel": {
"header-menu": { "header-menu": {
"copy": "",
"create-library-panel": "",
"duplicate": "",
"edit": "",
"explore": "",
"get-help": "",
"hide-legend": "Ocultar leyenda", "hide-legend": "Ocultar leyenda",
"inspect": "Inspeccionar", "inspect": "Inspeccionar",
"inspect-data": "Datos", "inspect-data": "Datos",
"inspect-json": "JSON de panel", "inspect-json": "JSON de panel",
"more": "Más...", "more": "Más...",
"query": "",
"remove": "",
"share": "Compartir", "share": "Compartir",
"show-legend": "Mostrar leyenda", "show-legend": "Mostrar leyenda",
"unlink-library-panel": "",
"view": "Vista" "view": "Vista"
} }
}, },
@ -374,6 +386,14 @@
"auto-refresh": "Establecer intervalo de actualización automática" "auto-refresh": "Establecer intervalo de actualización automática"
} }
}, },
"search": {
"dashboard-actions": {
"import": "",
"new": "",
"new-dashboard": "",
"new-folder": ""
}
},
"share-modal": { "share-modal": {
"dashboard": { "dashboard": {
"title": "Compartir" "title": "Compartir"

View File

@ -253,6 +253,9 @@
"subtitle": "Applications de suivi et d'infrastructure", "subtitle": "Applications de suivi et d'infrastructure",
"title": "Suivi" "title": "Suivi"
}, },
"new": {
"title": ""
},
"new-dashboard": { "new-dashboard": {
"title": "Nouveau tableau de bord" "title": "Nouveau tableau de bord"
}, },
@ -347,13 +350,22 @@
}, },
"panel": { "panel": {
"header-menu": { "header-menu": {
"copy": "",
"create-library-panel": "",
"duplicate": "",
"edit": "",
"explore": "",
"get-help": "",
"hide-legend": "Masquer la légende", "hide-legend": "Masquer la légende",
"inspect": "Inspecter", "inspect": "Inspecter",
"inspect-data": "Données", "inspect-data": "Données",
"inspect-json": "Panneau JSON", "inspect-json": "Panneau JSON",
"more": "Plus...", "more": "Plus...",
"query": "",
"remove": "",
"share": "Partager", "share": "Partager",
"show-legend": "Afficher la légende", "show-legend": "Afficher la légende",
"unlink-library-panel": "",
"view": "Afficher" "view": "Afficher"
} }
}, },
@ -374,6 +386,14 @@
"auto-refresh": "Définir l'intervalle d'actualisation automatique" "auto-refresh": "Définir l'intervalle d'actualisation automatique"
} }
}, },
"search": {
"dashboard-actions": {
"import": "",
"new": "",
"new-dashboard": "",
"new-folder": ""
}
},
"share-modal": { "share-modal": {
"dashboard": { "dashboard": {
"title": "Partager" "title": "Partager"

View File

@ -253,6 +253,9 @@
"subtitle": "Mőʼnįŧőřįʼnģ äʼnđ įʼnƒřäşŧřūčŧūřę äppş", "subtitle": "Mőʼnįŧőřįʼnģ äʼnđ įʼnƒřäşŧřūčŧūřę äppş",
"title": "Mőʼnįŧőřįʼnģ" "title": "Mőʼnįŧőřįʼnģ"
}, },
"new": {
"title": "Ńęŵ"
},
"new-dashboard": { "new-dashboard": {
"title": "Ńęŵ đäşĥþőäřđ" "title": "Ńęŵ đäşĥþőäřđ"
}, },
@ -347,13 +350,22 @@
}, },
"panel": { "panel": {
"header-menu": { "header-menu": {
"copy": "Cőpy",
"create-library-panel": "Cřęäŧę ľįþřäřy päʼnęľ",
"duplicate": "Đūpľįčäŧę",
"edit": "Ēđįŧ",
"explore": "Ēχpľőřę",
"get-help": "Ğęŧ ĥęľp",
"hide-legend": "Ħįđę ľęģęʼnđ", "hide-legend": "Ħįđę ľęģęʼnđ",
"inspect": "Ĩʼnşpęčŧ", "inspect": "Ĩʼnşpęčŧ",
"inspect-data": "Đäŧä", "inspect-data": "Đäŧä",
"inspect-json": "Päʼnęľ ĴŜØŃ", "inspect-json": "Päʼnęľ ĴŜØŃ",
"more": "Mőřę...", "more": "Mőřę...",
"query": "Qūęřy",
"remove": "Ŗęmővę",
"share": "Ŝĥäřę", "share": "Ŝĥäřę",
"show-legend": "Ŝĥőŵ ľęģęʼnđ", "show-legend": "Ŝĥőŵ ľęģęʼnđ",
"unlink-library-panel": "Ůʼnľįʼnĸ ľįþřäřy päʼnęľ",
"view": "Vįęŵ" "view": "Vįęŵ"
} }
}, },
@ -374,6 +386,14 @@
"auto-refresh": "Ŝęŧ äūŧő řęƒřęşĥ įʼnŧęřväľ" "auto-refresh": "Ŝęŧ äūŧő řęƒřęşĥ įʼnŧęřväľ"
} }
}, },
"search": {
"dashboard-actions": {
"import": "Ĩmpőřŧ",
"new": "Ńęŵ",
"new-dashboard": "Ńęŵ Đäşĥþőäřđ",
"new-folder": "Ńęŵ Főľđęř"
}
},
"share-modal": { "share-modal": {
"dashboard": { "dashboard": {
"title": "Ŝĥäřę" "title": "Ŝĥäřę"

View File

@ -253,6 +253,9 @@
"subtitle": "监控和基础设施应用", "subtitle": "监控和基础设施应用",
"title": "正在监控" "title": "正在监控"
}, },
"new": {
"title": ""
},
"new-dashboard": { "new-dashboard": {
"title": "新建仪表板" "title": "新建仪表板"
}, },
@ -347,13 +350,22 @@
}, },
"panel": { "panel": {
"header-menu": { "header-menu": {
"copy": "",
"create-library-panel": "",
"duplicate": "",
"edit": "",
"explore": "",
"get-help": "",
"hide-legend": "", "hide-legend": "",
"inspect": "检查", "inspect": "检查",
"inspect-data": "数据", "inspect-data": "数据",
"inspect-json": "面板 JSON", "inspect-json": "面板 JSON",
"more": "更多...", "more": "更多...",
"query": "",
"remove": "",
"share": "分享", "share": "分享",
"show-legend": "", "show-legend": "",
"unlink-library-panel": "",
"view": "查看" "view": "查看"
} }
}, },
@ -374,6 +386,14 @@
"auto-refresh": "" "auto-refresh": ""
} }
}, },
"search": {
"dashboard-actions": {
"import": "",
"new": "",
"new-dashboard": "",
"new-folder": ""
}
},
"share-modal": { "share-modal": {
"dashboard": { "dashboard": {
"title": "分享" "title": "分享"