From 3d1da2178808145a484dff7ffd90e1ca00f95fcb Mon Sep 17 00:00:00 2001 From: waynelwz <100347187+waynelwz@users.noreply.github.com> Date: Thu, 6 Apr 2023 19:07:12 +0800 Subject: [PATCH] feat(console): i18n support for zh (#2056) * ui: i18n & font * update: use baseui LocaleProvider * update: add language selector * update: use useTranslation temporarily in packages * update: visitor selector ui * fix: lint error --- .../src/form/WidgetFormModal.tsx | 6 +- .../starwhale-core/src/form/schemas/fields.ts | 9 +- .../src/widget/WidgetRenderTree.tsx | 9 +- .../src/DynamicSelector/Selector.tsx | 4 +- .../src/IconFont/fonts/iconfont.css | 10 +- .../src/IconFont/fonts/iconfont.js | 2 +- .../src/IconFont/fonts/iconfont.json | 7 + .../src/IconFont/fonts/iconfont.ttf | 4 +- .../src/IconFont/fonts/iconfont.woff | 4 +- .../src/IconFont/fonts/iconfont.woff2 | 4 +- .../starwhale-ui/src/IconFont/index.tsx | 1 + .../starwhale-ui/src/Modal/confirm.tsx | 6 +- .../starwhale-ui/src/Search/Search.tsx | 4 +- .../starwhale-ui/src/Select/Select.tsx | 5 + .../starwhale-ui/src/Transfer/Transfer.tsx | 10 +- .../base/data-table/cells/cell-placement.tsx | 2 +- .../src/base/data-table/column-boolean.tsx | 2 +- .../data-table/column-categorical-tags.tsx | 6 +- .../base/data-table/column-categorical.tsx | 2 +- .../src/base/data-table/column-datetime.tsx | 2 +- .../src/base/data-table/column-numerical.tsx | 2 +- .../base/data-table/config-manage-columns.tsx | 8 +- .../src/base/data-table/config-views-edit.tsx | 17 +- .../src/base/data-table/config-views.tsx | 9 +- .../src/base/data-table/data-custom-table.tsx | 4 +- .../src/base/data-table/filter-menu.tsx | 2 +- .../base/data-table/filter-operate-menu.tsx | 6 +- .../src/base/data-table/filter-shell.tsx | 2 +- .../base/data-table/headers/header-cell.tsx | 6 +- .../src/base/data-table/headers/headers.tsx | 2 +- .../src/base/data-table/locales/en_US.ts | 10 - .../src/base/data-table/locales/index.tsx | 16 - .../src/base/data-table/locales/types.ts | 5 - .../base/data-table/stateful-data-table.tsx | 2 +- .../packages/starwhale-ui/src/i18n/index.ts | 3 + console/packages/starwhale-ui/src/i18n/zh.ts | 44 ++ .../packages/starwhale-ui/src/theme/index.ts | 2 +- .../src/DNDListWidget/index.tsx | 6 +- .../src/SectionWidget/GridWidget.tsx | 6 +- .../component/ChartConfigPopover.tsx | 16 +- .../component/SectionAccordionPanel.tsx | 4 +- .../SectionWidget/component/SectionForm.tsx | 2 +- .../component/SectionPopover.tsx | 23 +- .../src/SectionWidget/index.tsx | 15 +- console/src/App.tsx | 27 +- console/src/assets/bg-1920x1080.jpg | 3 + console/src/assets/bg-2560x1440.jpg | 3 + console/src/assets/bg-3840x2160.jpg | 3 + console/src/assets/fonts/iconfont.css | 42 +- console/src/assets/fonts/iconfont.js | 2 +- console/src/assets/fonts/iconfont.json | 63 +++ console/src/assets/fonts/iconfont.ttf | 4 +- console/src/assets/fonts/iconfont.woff | 4 +- console/src/assets/fonts/iconfont.woff2 | 4 +- .../components/Header/LanguageSelector.tsx | 64 +++ console/src/components/Header/index.tsx | 17 +- console/src/consts/index.ts | 10 + .../components/DatasetTreeSelector.tsx | 7 + console/src/domain/job/components/JobForm.tsx | 2 +- .../src/domain/job/components/JobStatus.tsx | 2 +- .../project/components/RoleSelector.tsx | 32 +- .../project/components/VisitSelector.tsx | 13 +- .../components/RuntimeTreeSelector.tsx | 7 + console/src/i18n/index.ts | 10 +- console/src/i18n/locales.ts | 466 +++++++++++++++++- console/src/pages/BaseLayout.tsx | 5 +- .../pages/Evaluation/EvaluationListCard.tsx | 2 +- .../Evaluation/EvaluationWidgetResults.tsx | 20 +- console/src/pages/Home/LoginLayout.tsx | 3 +- console/src/pages/Project/ProjectListCard.tsx | 14 +- console/src/pages/Project/ProjectMembers.tsx | 72 ++- console/src/styles/_global.scss | 15 +- 72 files changed, 1065 insertions(+), 162 deletions(-) delete mode 100644 console/packages/starwhale-ui/src/base/data-table/locales/en_US.ts delete mode 100644 console/packages/starwhale-ui/src/base/data-table/locales/index.tsx delete mode 100644 console/packages/starwhale-ui/src/base/data-table/locales/types.ts create mode 100644 console/packages/starwhale-ui/src/i18n/index.ts create mode 100644 console/packages/starwhale-ui/src/i18n/zh.ts create mode 100644 console/src/assets/bg-1920x1080.jpg create mode 100644 console/src/assets/bg-2560x1440.jpg create mode 100644 console/src/assets/bg-3840x2160.jpg create mode 100644 console/src/components/Header/LanguageSelector.tsx diff --git a/console/packages/starwhale-core/src/form/WidgetFormModal.tsx b/console/packages/starwhale-core/src/form/WidgetFormModal.tsx index 447314fa27..6e6ea97419 100644 --- a/console/packages/starwhale-core/src/form/WidgetFormModal.tsx +++ b/console/packages/starwhale-core/src/form/WidgetFormModal.tsx @@ -9,6 +9,7 @@ import { StoreType, useEditorContext } from '../context/EditorContextProvider' import { useDatastoreTablesByPrefix } from '../datastore/hooks/useDatastoreTables' import WidgetFormModel from './WidgetFormModel' import WidgetModel from '../widget/WidgetModel' +import useTranslation from '@/hooks/useTranslation' const PAGE_TABLE_SIZE = 100 @@ -27,6 +28,7 @@ export default function WidgetFormModal({ handleFormSubmit: (args: any) => void id?: string }) { + const [t] = useTranslation() // @FIXME use event bus handle global state const { dynamicVars } = useEditorContext() const { prefix } = dynamicVars @@ -84,7 +86,7 @@ export default function WidgetFormModal({ }, }} > - Add Chart + {t('panel.chart.add')}
- {!type && 'Select a metric to visalize in this chart'} + {!type && t('panel.add.placeholder')} {type && (
{ return { chartType: { type: 'string', - title: 'Chart Type', + title: i18n.t('panel.chart.type'), oneOf: WidgetFactory.getPanels().map((v) => ({ const: v.type, @@ -33,7 +34,7 @@ export const tableNameField = (tables: any, schema?: RJSFSchema): RJSFSchema | u return { tableName: { type: 'array', - title: 'Table Name', + title: i18n.t('panel.chart.table.name'), uniqueItems: true, items: { type: 'string', @@ -49,7 +50,7 @@ export const tableNameField = (tables: any, schema?: RJSFSchema): RJSFSchema | u return { tableName: { type: 'string', - title: 'Table Name', + title: i18n.t('panel.chart.table.name'), oneOf: tables.map((v: any) => ({ const: v.name, @@ -61,7 +62,7 @@ export const tableNameField = (tables: any, schema?: RJSFSchema): RJSFSchema | u export const chartTitleField = (): RJSFSchema | undefined => ({ chartTitle: { - title: 'Chart Title', + title: i18n.t('panel.chart.title'), type: 'string', }, }) diff --git a/console/packages/starwhale-core/src/widget/WidgetRenderTree.tsx b/console/packages/starwhale-core/src/widget/WidgetRenderTree.tsx index 3ff04e2ca8..6dfd59ed23 100644 --- a/console/packages/starwhale-core/src/widget/WidgetRenderTree.tsx +++ b/console/packages/starwhale-core/src/widget/WidgetRenderTree.tsx @@ -13,6 +13,7 @@ import WidgetFormModal from '../form/WidgetFormModal' import WidgetPreviewModal from '../form/WidgetPreviewModal' import useRestoreState from './hooks/useRestoreState' import shallow from 'zustand/shallow' +import useTranslation from '@/hooks/useTranslation' export const WrapedWidgetNode = withWidgetDynamicProps(function WidgetNode(props: WidgetProps) { const { childWidgets, path = [] } = props @@ -51,7 +52,13 @@ export function WidgetRenderTree({ initialState, onStateChange }: any) { const [isPanelModalOpen, setIsPanelModalOpen] = React.useState(false) const [viewWidget, setViewWidget] = useState() const [isPanelPreviewModalOpen, setIsPanelPreviewModalOpen] = React.useState(false) - const form = useRef(new WidgetFormModel().initPanelSchema()) + const form = useRef(new WidgetFormModel()) + + // @FIXME useTranslation + const [t] = useTranslation() + useEffect(() => { + form.current.initPanelSchema() + }, [t]) const { toSave } = useRestoreState(store, initialState, dynamicVars) diff --git a/console/packages/starwhale-ui/src/DynamicSelector/Selector.tsx b/console/packages/starwhale-ui/src/DynamicSelector/Selector.tsx index 847f7e411a..35627ef7de 100644 --- a/console/packages/starwhale-ui/src/DynamicSelector/Selector.tsx +++ b/console/packages/starwhale-ui/src/DynamicSelector/Selector.tsx @@ -13,6 +13,7 @@ import { } from './StyledComponent' import Tree from '../Tree/Tree' import { KEY_STRINGS } from 'baseui/menu' +import useTranslation from '@/hooks/useTranslation' // @ts-ignore const containsNode = (parent, child) => { @@ -37,10 +38,11 @@ export function DynamicSelector({ onChange, startEnhancer, endEnhancer = defaultEndEnhancer(), - placeholder = 'Select Item', options = [], ...rest }: DynamicSelectorPropsT) { + const [t] = useTranslation() + const placeholder = rest.placeholder ?? t('selector.placeholder') const ref = useRef(null) const [isEditing, setIsEditing] = useState(false) const [values, setValues] = useState(rest.value ?? []) diff --git a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.css b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.css index 82caf55ae3..9ae277875d 100644 --- a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.css +++ b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 3410006 */ - src: url('iconfont.woff2?t=1680087448712') format('woff2'), - url('iconfont.woff?t=1680087448712') format('woff'), - url('iconfont.ttf?t=1680087448712') format('truetype'); + src: url('iconfont.woff2?t=1680769284437') format('woff2'), + url('iconfont.woff?t=1680769284437') format('woff'), + url('iconfont.ttf?t=1680769284437') format('truetype'); } .iconfont { @@ -13,6 +13,10 @@ -moz-osx-font-smoothing: grayscale; } +.icon-global:before { + content: "\e65f"; +} + .icon-library:before { content: "\e65e"; } diff --git a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.js b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.js index 7b73bad185..419a787fbc 100644 --- a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.js +++ b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_3410006='',function(h){var l=(l=document.getElementsByTagName("script"))[l.length-1],c=l.getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var o,i,v,m,t,s=function(l,c){c.parentNode.insertBefore(l,c)};if(c&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}o=function(){var l,c=document.createElement("div");c.innerHTML=h._iconfont_svg_string_3410006,(c=c.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",c=c,(l=document.body).firstChild?s(c,l.firstChild):l.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),o()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(v=o,m=h.document,t=!1,z(),m.onreadystatechange=function(){"complete"==m.readyState&&(m.onreadystatechange=null,a())})}function a(){t||(t=!0,v())}function z(){try{m.documentElement.doScroll("left")}catch(l){return void setTimeout(z,50)}a()}}(window); \ No newline at end of file +window._iconfont_svg_string_3410006='',function(h){var l=(l=document.getElementsByTagName("script"))[l.length-1],c=l.getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var o,i,v,m,t,s=function(l,c){c.parentNode.insertBefore(l,c)};if(c&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}o=function(){var l,c=document.createElement("div");c.innerHTML=h._iconfont_svg_string_3410006,(c=c.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",c=c,(l=document.body).firstChild?s(c,l.firstChild):l.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),o()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(v=o,m=h.document,t=!1,z(),m.onreadystatechange=function(){"complete"==m.readyState&&(m.onreadystatechange=null,a())})}function a(){t||(t=!0,v())}function z(){try{m.documentElement.doScroll("left")}catch(l){return void setTimeout(z,50)}a()}}(window); \ No newline at end of file diff --git a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.json b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.json index 0d1e898739..d26294b08e 100644 --- a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.json +++ b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.json @@ -5,6 +5,13 @@ "css_prefix_text": "icon-", "description": "", "glyphs": [ + { + "icon_id": "34901738", + "name": "global", + "font_class": "global", + "unicode": "e65f", + "unicode_decimal": 58975 + }, { "icon_id": "34824376", "name": "library", diff --git a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.ttf b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.ttf index a9ae07d275..c3ca6299e4 100644 --- a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.ttf +++ b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.ttf @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30f0371eb6ad148d03c5fa1918ea51b4969c13c76ce8351084dd64cbb6aa728e -size 16928 +oid sha256:5afe89e07d24d707c3b24eec2565191358a44da65586c2ee09e3fb35b1443e60 +size 17168 diff --git a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.woff b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.woff index 0520ebdc31..ee7ff3720a 100644 --- a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.woff +++ b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.woff @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:163f5b5194546fc5e43c2fb18747d02b352cb83ca13db6adc07083a21a62c5a1 -size 9836 +oid sha256:b635875ed44c5366bd7a84d4835db1f312dcf3509df760e0f28323bab731c9e9 +size 9980 diff --git a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.woff2 b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.woff2 index 267bc9a123..e03d233e9a 100644 --- a/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.woff2 +++ b/console/packages/starwhale-ui/src/IconFont/fonts/iconfont.woff2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5571eb0b40e8618fcc3121d3d0ff569193bd0b20274aac622f398d240b993adc -size 8220 +oid sha256:5f8f087e468fdfdf5f110a1f8f508df16984fb364f28b8aaaab75ebb01b8e2cb +size 8332 diff --git a/console/packages/starwhale-ui/src/IconFont/index.tsx b/console/packages/starwhale-ui/src/IconFont/index.tsx index 18582d3710..cca76cf94a 100644 --- a/console/packages/starwhale-ui/src/IconFont/index.tsx +++ b/console/packages/starwhale-ui/src/IconFont/index.tsx @@ -91,6 +91,7 @@ export type IconTypesT = | 'invalidFile' | 'group' | 'library' + | 'global' interface IIconFontProps { style?: React.CSSProperties diff --git a/console/packages/starwhale-ui/src/Modal/confirm.tsx b/console/packages/starwhale-ui/src/Modal/confirm.tsx index a739388f33..0adb46e5a4 100644 --- a/console/packages/starwhale-ui/src/Modal/confirm.tsx +++ b/console/packages/starwhale-ui/src/Modal/confirm.tsx @@ -4,6 +4,7 @@ import { Button, IButtonProps } from '../Button' import IconFont from '../IconFont' import { expandMargin, expandPadding } from '../utils' import { LabelMedium } from 'baseui/typography' +import useTranslation from '@/hooks/useTranslation' export interface IConfirmCtxProviderProps { children?: React.ReactNode @@ -25,6 +26,7 @@ const ConfirmCtx = React.createContext({ }) const ConfirmCtxProvider = ({ children }: IConfirmCtxProviderProps) => { + const [t] = useTranslation() const [showModal, setShowModal] = useState(false) const [showProps, setShowProps] = useState({}) const resolver: React.MutableRefObject<(ok: boolean) => void> = useRef(() => {}) @@ -107,7 +109,7 @@ const ConfirmCtxProvider = ({ children }: IConfirmCtxProviderProps) => { setShowModal(false) }} > - No + {t('remove.no')}
diff --git a/console/packages/starwhale-ui/src/Search/Search.tsx b/console/packages/starwhale-ui/src/Search/Search.tsx index ccfe2f5501..e7c52d730d 100644 --- a/console/packages/starwhale-ui/src/Search/Search.tsx +++ b/console/packages/starwhale-ui/src/Search/Search.tsx @@ -7,6 +7,7 @@ import FilterRenderer from './FilterRenderer' import { ValueT } from './types' import IconFont from '../IconFont' import { LabelSmall } from 'baseui/typography' +import useTranslation from '@/hooks/useTranslation' export const useStyles = createUseStyles({ searchBar: { @@ -69,6 +70,7 @@ export interface ISearchProps { export default function Search({ value = [], onChange, ...props }: ISearchProps) { const styles = useStyles() + const [t] = useTranslation() const ref = useRef(null) const [isEditing, setIsEditing] = useState(false) const [items, setItems] = useState(value) @@ -174,7 +176,7 @@ export default function Search({ value = [], onChange, ...props }: ISearchProps)
{!isEditing && items.length === 0 && ( - Search and Filter + {t('table.search.placeholder')} )}
diff --git a/console/packages/starwhale-ui/src/Select/Select.tsx b/console/packages/starwhale-ui/src/Select/Select.tsx index ec2a740775..37cda51a14 100644 --- a/console/packages/starwhale-ui/src/Select/Select.tsx +++ b/console/packages/starwhale-ui/src/Select/Select.tsx @@ -2,6 +2,7 @@ import { Select as BaseSelect, SelectProps, SIZE } from 'baseui/select' import React from 'react' import IconFont from '../IconFont' import { mergeOverrides } from '../utils' +import useTranslation from '@/hooks/useTranslation' export { SIZE } from 'baseui/select' @@ -11,6 +12,7 @@ export interface ISelectProps extends SelectProps { } export function Select({ size = 'compact', ...props }: ISelectProps) { + const [t] = useTranslation() const overrides = mergeOverrides( { ControlContainer: { @@ -47,6 +49,9 @@ export function Select({ size = 'compact', ...props }: ISelectProps) { props.overrides ) + // eslint-disable-next-line no-param-reassign + props.placeholder ??= t('selector.placeholder') + // eslint-disable-next-line react/jsx-props-no-spreading return } diff --git a/console/packages/starwhale-ui/src/Transfer/Transfer.tsx b/console/packages/starwhale-ui/src/Transfer/Transfer.tsx index 46f4a23f5f..3646dd4c08 100644 --- a/console/packages/starwhale-ui/src/Transfer/Transfer.tsx +++ b/console/packages/starwhale-ui/src/Transfer/Transfer.tsx @@ -8,6 +8,7 @@ import Input from '../Input' import TransferList from './TransferList' import useUnSortedSelection from '../utils/useUnsortedSelection' import { BusyPlaceholder } from '../BusyLoaderWrapper' +import useTranslation from '@/hooks/useTranslation' const useStyles = createUseStyles({ transfer: { @@ -110,6 +111,7 @@ export default function Transfer({ value = defaultValue, onChange = () => {}, }: TransferPropsT) { + const [t] = useTranslation() const styles = useStyles() const [css, theme] = useStyletron() const [query, setQuery] = React.useState('') @@ -202,7 +204,11 @@ export default function Transfer({
)}
- +
} columns={$rightFilteredColumns} isDragable={isDragable} diff --git a/console/packages/starwhale-ui/src/base/data-table/cells/cell-placement.tsx b/console/packages/starwhale-ui/src/base/data-table/cells/cell-placement.tsx index 70c4929e09..04d3a253cd 100644 --- a/console/packages/starwhale-ui/src/base/data-table/cells/cell-placement.tsx +++ b/console/packages/starwhale-ui/src/base/data-table/cells/cell-placement.tsx @@ -64,7 +64,7 @@ function CellPlacement({ columnIndex, rowIndex, data, style }: any) { rowIndex === data.rowHighlightIndex ? 'table-row--hovering' : undefined, css({ - ...theme.borders.border200, + // ...theme.borders.border200, borderTop: 'none', borderBottom: 'none', borderRight: 'none', diff --git a/console/packages/starwhale-ui/src/base/data-table/column-boolean.tsx b/console/packages/starwhale-ui/src/base/data-table/column-boolean.tsx index bee3d4be4e..65243694f1 100644 --- a/console/packages/starwhale-ui/src/base/data-table/column-boolean.tsx +++ b/console/packages/starwhale-ui/src/base/data-table/column-boolean.tsx @@ -8,7 +8,7 @@ import { CategoricalFilter } from './column-categorical' import Column from './column' import { COLUMNS } from './constants' import { ColumnT, FilterTypes, SharedColumnOptionsT } from './types' -import { LocaleContext } from './locales' +import { LocaleContext } from 'baseui/locale' type OptionsT = SharedColumnOptionsT diff --git a/console/packages/starwhale-ui/src/base/data-table/column-categorical-tags.tsx b/console/packages/starwhale-ui/src/base/data-table/column-categorical-tags.tsx index 0e10f1c459..7e524d5925 100644 --- a/console/packages/starwhale-ui/src/base/data-table/column-categorical-tags.tsx +++ b/console/packages/starwhale-ui/src/base/data-table/column-categorical-tags.tsx @@ -13,12 +13,13 @@ import { LabelSmall } from 'baseui/typography' import Column from './column' import { COLUMNS } from './constants' import type { ColumnT, SharedColumnOptionsT } from './types' -import { LocaleContext } from './locales' +import { LocaleContext } from 'baseui/locale' import FilterShell from './filter-shell' import { matchesQuery, splitByQuery } from './text-search' import { Tag, KIND as TAG_KIND, VARIANT as TAG_VARIANT } from 'baseui/tag' import { Popover, PLACEMENT } from 'baseui/popover' import IconFont from '../../IconFont' +import { DataTableLocaleT } from './locale' type OptionsT = SharedColumnOptionsT @@ -261,7 +262,8 @@ type CategoricalEditPopoverProps = { export function CategoricalEditPopover(props: CategoricalEditPopoverProps) { const [css, theme] = useStyletron() - const locale = React.useContext(LocaleContext) + //@ts-ignore + const locale: { datatable: DataTableLocaleT } = React.useContext(LocaleContext) const inputRef = React.useRef(null) React.useEffect(() => { if (inputRef.current) { diff --git a/console/packages/starwhale-ui/src/base/data-table/column-categorical.tsx b/console/packages/starwhale-ui/src/base/data-table/column-categorical.tsx index a2225196a8..8d09862351 100644 --- a/console/packages/starwhale-ui/src/base/data-table/column-categorical.tsx +++ b/console/packages/starwhale-ui/src/base/data-table/column-categorical.tsx @@ -13,7 +13,7 @@ import { LabelSmall } from 'baseui/typography' import Column from './column' import { COLUMNS } from './constants' import type { ColumnT, SharedColumnOptionsT } from './types' -import { LocaleContext } from './locales' +import { LocaleContext } from 'baseui/locale' import FilterShell from './filter-shell' import { matchesQuery, splitByQuery, HighlightCellText } from './text-search' diff --git a/console/packages/starwhale-ui/src/base/data-table/column-datetime.tsx b/console/packages/starwhale-ui/src/base/data-table/column-datetime.tsx index 5808b101f5..e2000571bc 100644 --- a/console/packages/starwhale-ui/src/base/data-table/column-datetime.tsx +++ b/console/packages/starwhale-ui/src/base/data-table/column-datetime.tsx @@ -35,7 +35,7 @@ import Column from './column' import { COLUMNS, DATETIME_OPERATIONS } from './constants' import FilterShell from './filter-shell' import type { ColumnT, SharedColumnOptionsT } from './types' -import { LocaleContext } from './locales' +import { LocaleContext } from 'baseui/locale' type OptionsT = { formatString?: string diff --git a/console/packages/starwhale-ui/src/base/data-table/column-numerical.tsx b/console/packages/starwhale-ui/src/base/data-table/column-numerical.tsx index 9e746e009d..f551b1202b 100644 --- a/console/packages/starwhale-ui/src/base/data-table/column-numerical.tsx +++ b/console/packages/starwhale-ui/src/base/data-table/column-numerical.tsx @@ -11,7 +11,7 @@ import Column from './column' import { COLUMNS, NUMERICAL_FORMATS, MAX_BIN_COUNT, HISTOGRAM_SIZE } from './constants' import FilterShell, { type ExcludeKind } from './filter-shell' import { ColumnT, FilterTypes, SharedColumnOptionsT } from './types' -import { LocaleContext } from './locales' +import { LocaleContext } from 'baseui/locale' // @ts-ignore import { bin, max as maxFunc, extent, scaleLinear, median, bisector } from 'd3' import { Slider } from 'baseui/slider' diff --git a/console/packages/starwhale-ui/src/base/data-table/config-manage-columns.tsx b/console/packages/starwhale-ui/src/base/data-table/config-manage-columns.tsx index c89dc40001..2ffdc53969 100644 --- a/console/packages/starwhale-ui/src/base/data-table/config-manage-columns.tsx +++ b/console/packages/starwhale-ui/src/base/data-table/config-manage-columns.tsx @@ -9,6 +9,7 @@ import { createUseStyles } from 'react-jss' import cn from 'classnames' import { Transfer } from '@starwhale/ui/Transfer' import Button from '@starwhale/ui/Button' +import useTranslation from '@/hooks/useTranslation' const useStyles = createUseStyles({ transferWrapper: { @@ -63,6 +64,7 @@ type T = string const ConfigManageColumns = React.forwardRef<{ getConfig: () => any }, PropsT>((props, configRef) => { const styles = useStyles() const [, theme] = useStyletron() + const [t] = useTranslation() const [isOpen, setIsOpen] = React.useState(false) const { expandedWidth, expanded, setExpanded } = useDrawer() @@ -159,11 +161,13 @@ const ConfigManageColumns = React.forwardRef<{ getConfig: () => any }, PropsT>(( }, }} > - Manage Columns + {t('table.column.manage')} )} -
Manage Columns
+
+ {t('table.column.manage')} +
) { const [css] = useStyletron() - // const [t] = useTranslation() + const [t] = useTranslation() const [name, setName] = React.useState(props.view?.name ?? '') const [sortBy, setSortBy] = React.useState(props.view?.sortBy ?? '') const [queries, setQueries] = React.useState(props.view?.queries ?? []) @@ -61,9 +62,9 @@ function ViewEdit(props: ViewListPropsT, ref: React.Ref) { flexDirection: 'column', })} > - View Name * + {t('table.view.name')} * ) { flexDirection: 'column', })} > - Add Filter + {t('table.filter.add')}
@@ -106,7 +107,7 @@ function ViewEdit(props: ViewListPropsT, ref: React.Ref) { flexDirection: 'column', })} > - Sort + {t('table.sort.by')}
) { diff --git a/console/packages/starwhale-widgets/src/SectionWidget/component/SectionPopover.tsx b/console/packages/starwhale-widgets/src/SectionWidget/component/SectionPopover.tsx index 9861d527b1..198472454d 100644 --- a/console/packages/starwhale-widgets/src/SectionWidget/component/SectionPopover.tsx +++ b/console/packages/starwhale-widgets/src/SectionWidget/component/SectionPopover.tsx @@ -4,23 +4,28 @@ import { StatefulMenu } from 'baseui/menu' import IconFont from '@starwhale/ui/IconFont' import { expandMargin, expandPadding } from '@starwhale/ui/utils' import { ConfirmButton } from '@starwhale/ui/Modal' - -const COLUMN_OPTIONS = [ - { label: 'Rename', type: 'rename' }, - { label: 'Add above', type: 'addAbove' }, - { label: 'Add belove', type: 'addBelow' }, - { label: 'Delete', type: 'delete' }, -] +import useTranslation from '@/hooks/useTranslation' // @ts-ignore export default function SectionPopover({ onOptionSelect }) { + const [t] = useTranslation() + + const $options = React.useMemo(() => { + return [ + { label: t('panel.rename'), type: 'rename' }, + { label: t('panel.add.above'), type: 'addAbove' }, + { label: t('panel.add.below'), type: 'addBelow' }, + { label: t('panel.delete'), type: 'delete' }, + ] + }, [t]) + return ( ( { if (item.type === 'delete') { close() @@ -30,7 +35,7 @@ export default function SectionPopover({ onOptionSelect }) { close() }} overrides={{ - List: { style: { height: '160px', width: '150px' } }, + List: { style: { minHeight: '160px', minWidth: '150px' } }, Option: { props: { getItemLabel: (item: { label: string; type: string }) => { diff --git a/console/packages/starwhale-widgets/src/SectionWidget/index.tsx b/console/packages/starwhale-widgets/src/SectionWidget/index.tsx index 030e1ce4b7..158b98057f 100644 --- a/console/packages/starwhale-widgets/src/SectionWidget/index.tsx +++ b/console/packages/starwhale-widgets/src/SectionWidget/index.tsx @@ -21,6 +21,7 @@ import { DragEndEvent, DragStartEvent } from '@starwhale/core/events/common' import SectionAccordionPanel from './component/SectionAccordionPanel' import SectionForm from './component/SectionForm' import ChartConfigGroup from './component/ChartConfigGroup' +import useTranslation from '@/hooks/useTranslation' const useStyles = createUseStyles({ panelWrapper: { @@ -58,7 +59,7 @@ export const CONFIG: WidgetConfig = { group: WidgetGroupType.LIST, description: 'ui layout for dynamic grid view', optionConfig: { - title: 'Panel', + title: '', isExpaned: true, layoutConfig: { padding: 20, @@ -78,17 +79,20 @@ type Option = typeof CONFIG['optionConfig'] // @ts-ignore function SectionWidget(props: WidgetRendererProps) { + const [t] = useTranslation() const styles = useStyles() const { optionConfig, children, eventBus, type } = props // @ts-ignore - const { title = '', isExpaned = false, layoutConfig, layout } = optionConfig as Option + const { isExpaned = false, layoutConfig, layout } = optionConfig as Option const [isDragging, setIsDragging] = useState(false) const len = children ? React.Children.count(children) : 0 const { boxWidth, boxHeight, padding } = layoutConfig const { width, height } = layout + const title = optionConfig?.title || t('panel.name') + const [isModelOpen, setIsModelOpen] = useState(false) const handleSectionForm = ({ name }: { name: string }) => { @@ -280,7 +284,7 @@ function SectionWidget(props: WidgetRendererProps) {
setIsModelOpen(false)} closeable animate autoFocus> - Panel + {t('panel.name')} @@ -290,11 +294,12 @@ function SectionWidget(props: WidgetRendererProps) { } const EmptyPlaceholder = () => { + const [t] = useTranslation() + return ( - {/* eslint-disable-next-line react/no-unescaped-entities */} - Click "Add Chart" to add visualizations + {t('panel.list.placeholder')} ) } diff --git a/console/src/App.tsx b/console/src/App.tsx index d07a6295bd..131b81d2b2 100644 --- a/console/src/App.tsx +++ b/console/src/App.tsx @@ -2,7 +2,7 @@ import React from 'react' import { Client as Styletron } from 'styletron-engine-atomic' import { Provider as StyletronProvider } from 'styletron-react' -import { BaseProvider } from 'baseui' +import { BaseProvider, LocaleProvider } from 'baseui' import { SidebarContext } from '@/contexts/SidebarContext' import { useSidebar } from '@/hooks/useSidebar' import { QueryClient, QueryClientProvider } from 'react-query' @@ -12,6 +12,8 @@ import { ToasterContainer } from 'baseui/toast' import { ConfirmCtxProvider } from '@starwhale/ui/Modal' import Routes from './routes' import { AuthProvider } from './api/Auth' +import i18n from './i18n' +import locales from '@starwhale/ui/i18n' apiInit() @@ -21,18 +23,25 @@ export default function App(): any { // eslint-disable-next-line react-hooks/exhaustive-deps const sidebarData = useSidebar() + const overrideLanguage = React.useMemo(() => { + // @ts-ignore + return locales?.[i18n.language] ?? {} + }, []) + return ( - - - - - - - - + + + + + + + + + + diff --git a/console/src/assets/bg-1920x1080.jpg b/console/src/assets/bg-1920x1080.jpg new file mode 100644 index 0000000000..e0dc0dfbe6 --- /dev/null +++ b/console/src/assets/bg-1920x1080.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13b265adcaf433d412b9b3177b7767451186987eb288772be61ac75229f2261c +size 181293 diff --git a/console/src/assets/bg-2560x1440.jpg b/console/src/assets/bg-2560x1440.jpg new file mode 100644 index 0000000000..3c0205ca96 --- /dev/null +++ b/console/src/assets/bg-2560x1440.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa80a56a26153b7328b5e2d521fbd485253807b460492e73f955019988a3997a +size 275440 diff --git a/console/src/assets/bg-3840x2160.jpg b/console/src/assets/bg-3840x2160.jpg new file mode 100644 index 0000000000..1d524883ca --- /dev/null +++ b/console/src/assets/bg-3840x2160.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:581be547f354ddffefde67ad8930227151869b4ac368480420d2a6ec27697d5d +size 504210 diff --git a/console/src/assets/fonts/iconfont.css b/console/src/assets/fonts/iconfont.css index 7c03213d10..9ae277875d 100644 --- a/console/src/assets/fonts/iconfont.css +++ b/console/src/assets/fonts/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 3410006 */ - src: url('iconfont.woff2?t=1667979623500') format('woff2'), - url('iconfont.woff?t=1667979623500') format('woff'), - url('iconfont.ttf?t=1667979623500') format('truetype'); + src: url('iconfont.woff2?t=1680769284437') format('woff2'), + url('iconfont.woff?t=1680769284437') format('woff'), + url('iconfont.ttf?t=1680769284437') format('truetype'); } .iconfont { @@ -13,6 +13,42 @@ -moz-osx-font-smoothing: grayscale; } +.icon-global:before { + content: "\e65f"; +} + +.icon-library:before { + content: "\e65e"; +} + +.icon-group:before { + content: "\e65d"; +} + +.icon-loading:before { + content: "\e65c"; +} + +.icon-experiment:before { + content: "\e65b"; +} + +.icon-download:before { + content: "\e659"; +} + +.icon-upload:before { + content: "\e65a"; +} + +.icon-calendar:before { + content: "\e658"; +} + +.icon-file2:before { + content: "\e657"; +} + .icon-a-Addabove:before { content: "\e654"; } diff --git a/console/src/assets/fonts/iconfont.js b/console/src/assets/fonts/iconfont.js index 9d90aa1529..419a787fbc 100644 --- a/console/src/assets/fonts/iconfont.js +++ b/console/src/assets/fonts/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_3410006='',function(h){var l=(l=document.getElementsByTagName("script"))[l.length-1],c=l.getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var o,i,v,t,m,s=function(l,c){c.parentNode.insertBefore(l,c)};if(c&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}o=function(){var l,c=document.createElement("div");c.innerHTML=h._iconfont_svg_string_3410006,(c=c.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",c=c,(l=document.body).firstChild?s(c,l.firstChild):l.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),o()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(v=o,t=h.document,m=!1,z(),t.onreadystatechange=function(){"complete"==t.readyState&&(t.onreadystatechange=null,a())})}function a(){m||(m=!0,v())}function z(){try{t.documentElement.doScroll("left")}catch(l){return void setTimeout(z,50)}a()}}(window); \ No newline at end of file +window._iconfont_svg_string_3410006='',function(h){var l=(l=document.getElementsByTagName("script"))[l.length-1],c=l.getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var o,i,v,m,t,s=function(l,c){c.parentNode.insertBefore(l,c)};if(c&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}o=function(){var l,c=document.createElement("div");c.innerHTML=h._iconfont_svg_string_3410006,(c=c.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",c=c,(l=document.body).firstChild?s(c,l.firstChild):l.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),o()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(v=o,m=h.document,t=!1,z(),m.onreadystatechange=function(){"complete"==m.readyState&&(m.onreadystatechange=null,a())})}function a(){t||(t=!0,v())}function z(){try{m.documentElement.doScroll("left")}catch(l){return void setTimeout(z,50)}a()}}(window); \ No newline at end of file diff --git a/console/src/assets/fonts/iconfont.json b/console/src/assets/fonts/iconfont.json index daba0c192e..d26294b08e 100644 --- a/console/src/assets/fonts/iconfont.json +++ b/console/src/assets/fonts/iconfont.json @@ -5,6 +5,69 @@ "css_prefix_text": "icon-", "description": "", "glyphs": [ + { + "icon_id": "34901738", + "name": "global", + "font_class": "global", + "unicode": "e65f", + "unicode_decimal": 58975 + }, + { + "icon_id": "34824376", + "name": "library", + "font_class": "library", + "unicode": "e65e", + "unicode_decimal": 58974 + }, + { + "icon_id": "34341578", + "name": "group", + "font_class": "group", + "unicode": "e65d", + "unicode_decimal": 58973 + }, + { + "icon_id": "34125367", + "name": "loading", + "font_class": "loading", + "unicode": "e65c", + "unicode_decimal": 58972 + }, + { + "icon_id": "33793517", + "name": "experiment", + "font_class": "experiment", + "unicode": "e65b", + "unicode_decimal": 58971 + }, + { + "icon_id": "33548920", + "name": "download", + "font_class": "download", + "unicode": "e659", + "unicode_decimal": 58969 + }, + { + "icon_id": "33548921", + "name": "upload", + "font_class": "upload", + "unicode": "e65a", + "unicode_decimal": 58970 + }, + { + "icon_id": "33442844", + "name": "calendar", + "font_class": "calendar", + "unicode": "e658", + "unicode_decimal": 58968 + }, + { + "icon_id": "33295022", + "name": "file2", + "font_class": "file2", + "unicode": "e657", + "unicode_decimal": 58967 + }, { "icon_id": "32592454", "name": "Add above", diff --git a/console/src/assets/fonts/iconfont.ttf b/console/src/assets/fonts/iconfont.ttf index 8e9153b5c8..c3ca6299e4 100644 --- a/console/src/assets/fonts/iconfont.ttf +++ b/console/src/assets/fonts/iconfont.ttf @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c3648b029aece01627a21aa3c3a787fe8c55e0c1b69e80c110bdac0ce1532f6 -size 15788 +oid sha256:5afe89e07d24d707c3b24eec2565191358a44da65586c2ee09e3fb35b1443e60 +size 17168 diff --git a/console/src/assets/fonts/iconfont.woff b/console/src/assets/fonts/iconfont.woff index 7c52503441..ee7ff3720a 100644 --- a/console/src/assets/fonts/iconfont.woff +++ b/console/src/assets/fonts/iconfont.woff @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d80880a332edf889dc7d03c7c381c314972540000aed04fe3e637ac67dca3ef8 -size 9196 +oid sha256:b635875ed44c5366bd7a84d4835db1f312dcf3509df760e0f28323bab731c9e9 +size 9980 diff --git a/console/src/assets/fonts/iconfont.woff2 b/console/src/assets/fonts/iconfont.woff2 index e3f746fc02..e03d233e9a 100644 --- a/console/src/assets/fonts/iconfont.woff2 +++ b/console/src/assets/fonts/iconfont.woff2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2dc87487ec59ea7d03a904f87b4501cca9edc5fd238ffdd309cd04c45e5dc2a3 -size 7688 +oid sha256:5f8f087e468fdfdf5f110a1f8f508df16984fb364f28b8aaaab75ebb01b8e2cb +size 8332 diff --git a/console/src/components/Header/LanguageSelector.tsx b/console/src/components/Header/LanguageSelector.tsx new file mode 100644 index 0000000000..03aac420a4 --- /dev/null +++ b/console/src/components/Header/LanguageSelector.tsx @@ -0,0 +1,64 @@ +import React from 'react' +import Select from '@starwhale/ui/Select' +import IconFont from '@starwhale/ui/IconFont' +import { languages } from '@/consts' +import i18n from '@/i18n' +import { expandBorder } from '@starwhale/ui/utils' + +export interface IRoleSelectorProps { + value?: string + onChange?: (newValue: string) => void +} + +export default function LanguageSelector() { + const languageValue = React.useMemo(() => { + const lan = i18n.language + const lanPrefix = lan.split('-')[0] + return ( + languages.find((option) => option.id === lan) || + languages.find((option) => option.id === lanPrefix) || + languages.find((option) => option.id.split('-')[0] === lanPrefix) || + languages[0] + ) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [i18n.language, languages]) + + return ( +