From 3aca6b914ac9c53a1d82bae5e19773498c779cd8 Mon Sep 17 00:00:00 2001 From: nowgnuesLee <192685612+nowgnuesLee@users.noreply.github.com> Date: Thu, 25 Sep 2025 09:01:06 +0000 Subject: [PATCH] feat(FR-1409): implementing import and delete for revision (#4230) resolves #4190 (FR-1409) # Reservoir UI Enhancements This PR enhances the Reservoir UI with improved artifact management capabilities: - Adds artifact cleanup functionality to remove versions that are no longer needed - Improves the artifact detail page with better version management - Adds cancel functionality for in-progress artifact pulls - Refactors components for better reusability and maintainability - Adds comprehensive i18n support for all new UI elements ## Key Components Added: - `BAIDeleteArtifactModal` for removing artifact versions - `BAIArtifactDescriptions` for consistent artifact metadata display - `BAIArtifactTypeTag` and `BAIArtifactStatusTag` for consistent status visualization - `BAIArtifactRevisionDownloadButton` and `BAIArtifactRevisionDeleteButton` for version management - `BAISelect`, `BAIBucketSelect`, and `BAIObjectStorageSelect` for improved selection interfaces ## Schema Changes: - Removed duplicate type definitions - Added new mutation `cleanupArtifactRevisions` to replace `deleteArtifactRevisions` - Added `ReservoirRegistry` types and related mutations - Simplified storage handling in artifact operations **Checklist:** - [x] Documentation - [ ] Minium required manager version - [ ] Specific setting for review - [ ] Minimum requirements to check during review - [ ] Test case(s) to demonstrate the difference of before/after --- packages/backend.ai-ui/package.json | 4 +- .../components/BAIGraphQLPropertyFilter.tsx | 21 +- .../BAIImportFromHuggingFaceModal.tsx | 150 ++++++ .../src/components/BAISelect.tsx | 180 ++++++++ .../src/components/TotalFooter.tsx | 33 ++ .../fragments/BAIArtifactDescriptions.tsx | 71 +++ .../BAIArtifactRevisionDeleteButton.tsx | 48 ++ .../BAIArtifactRevisionDownloadButton.tsx | 39 ++ .../fragments/BAIArtifactRevisionTable.tsx | 62 ++- .../fragments/BAIArtifactStatusTag.tsx | 24 + .../components/fragments/BAIArtifactTable.tsx | 87 ++-- .../fragments/BAIArtifactTypeTag.tsx | 47 ++ .../components/fragments/BAIBucketSelect.tsx | 144 ++++++ .../fragments/BAIDeleteArtifactModal.tsx | 205 +++++++++ .../fragments/BAIImportArtifactModal.tsx | 223 +++++---- .../fragments/BAIObjectStorageSelect.tsx | 120 +++++ .../BAIPullingArtifactRevisionAlert.tsx | 110 ++++- .../src/components/fragments/index.ts | 21 +- .../backend.ai-ui/src/components/index.ts | 4 + .../src/hooks/useEventNotStable.ts | 21 + .../src/hooks/usePaginatedQuery.ts | 87 ++++ .../src/icons/BAIHuggingFaceIcon.tsx | 12 + .../backend.ai-ui/src/icons/HuggingFace.svg | 8 + packages/backend.ai-ui/src/icons/index.ts | 1 + packages/backend.ai-ui/src/locale/de.json | 57 ++- packages/backend.ai-ui/src/locale/el.json | 57 ++- packages/backend.ai-ui/src/locale/en.json | 60 ++- packages/backend.ai-ui/src/locale/es.json | 57 ++- packages/backend.ai-ui/src/locale/fi.json | 57 ++- packages/backend.ai-ui/src/locale/fr.json | 57 ++- packages/backend.ai-ui/src/locale/id.json | 57 ++- packages/backend.ai-ui/src/locale/it.json | 57 ++- packages/backend.ai-ui/src/locale/ja.json | 57 ++- packages/backend.ai-ui/src/locale/ko.json | 58 ++- packages/backend.ai-ui/src/locale/mn.json | 57 ++- packages/backend.ai-ui/src/locale/ms.json | 58 ++- packages/backend.ai-ui/src/locale/pl.json | 58 ++- packages/backend.ai-ui/src/locale/pt-BR.json | 45 +- packages/backend.ai-ui/src/locale/pt.json | 58 ++- packages/backend.ai-ui/src/locale/ru.json | 58 ++- packages/backend.ai-ui/src/locale/th.json | 58 ++- packages/backend.ai-ui/src/locale/tr.json | 58 ++- packages/backend.ai-ui/src/locale/vi.json | 57 ++- packages/backend.ai-ui/src/locale/zh-CN.json | 58 ++- packages/backend.ai-ui/src/locale/zh-TW.json | 57 ++- pnpm-lock.yaml | 9 +- react/src/App.tsx | 26 +- .../src/components/MainLayout/WebUISider.tsx | 5 +- .../src/components/ReservoirArtifactList.tsx | 429 ------------------ react/src/helper/graphql-transformer.ts | 2 +- .../src/pages/ReservoirArtifactDetailPage.tsx | 132 ++++-- react/src/pages/ReservoirPage.tsx | 217 +++------ react/src/utils/reservoir.tsx | 59 --- resources/i18n/de.json | 8 + resources/i18n/el.json | 8 + resources/i18n/en.json | 8 + resources/i18n/es.json | 8 + resources/i18n/fi.json | 8 + resources/i18n/fr.json | 8 + resources/i18n/id.json | 8 + resources/i18n/it.json | 8 + resources/i18n/ja.json | 8 + resources/i18n/ko.json | 8 + resources/i18n/mn.json | 8 + resources/i18n/ms.json | 8 + resources/i18n/pl.json | 8 + resources/i18n/pt-BR.json | 8 + resources/i18n/pt.json | 8 + resources/i18n/ru.json | 8 + resources/i18n/th.json | 8 + resources/i18n/tr.json | 8 + resources/i18n/vi.json | 8 + resources/i18n/zh-CN.json | 8 + resources/i18n/zh-TW.json | 8 + src/lib/backend.ai-client-esm.ts | 3 + 75 files changed, 2961 insertions(+), 1007 deletions(-) create mode 100644 packages/backend.ai-ui/src/components/BAIImportFromHuggingFaceModal.tsx create mode 100644 packages/backend.ai-ui/src/components/BAISelect.tsx create mode 100644 packages/backend.ai-ui/src/components/TotalFooter.tsx create mode 100644 packages/backend.ai-ui/src/components/fragments/BAIArtifactDescriptions.tsx create mode 100644 packages/backend.ai-ui/src/components/fragments/BAIArtifactRevisionDeleteButton.tsx create mode 100644 packages/backend.ai-ui/src/components/fragments/BAIArtifactRevisionDownloadButton.tsx create mode 100644 packages/backend.ai-ui/src/components/fragments/BAIArtifactStatusTag.tsx create mode 100644 packages/backend.ai-ui/src/components/fragments/BAIArtifactTypeTag.tsx create mode 100644 packages/backend.ai-ui/src/components/fragments/BAIBucketSelect.tsx create mode 100644 packages/backend.ai-ui/src/components/fragments/BAIDeleteArtifactModal.tsx create mode 100644 packages/backend.ai-ui/src/components/fragments/BAIObjectStorageSelect.tsx create mode 100644 packages/backend.ai-ui/src/hooks/useEventNotStable.ts create mode 100644 packages/backend.ai-ui/src/hooks/usePaginatedQuery.ts create mode 100644 packages/backend.ai-ui/src/icons/BAIHuggingFaceIcon.tsx create mode 100644 packages/backend.ai-ui/src/icons/HuggingFace.svg delete mode 100644 react/src/components/ReservoirArtifactList.tsx delete mode 100644 react/src/utils/reservoir.tsx diff --git a/packages/backend.ai-ui/package.json b/packages/backend.ai-ui/package.json index 55da303801..cf5efeeff8 100644 --- a/packages/backend.ai-ui/package.json +++ b/packages/backend.ai-ui/package.json @@ -105,18 +105,16 @@ "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^19.0.3", "@types/react-relay": "^18.2.1", + "@types/relay-runtime": "^19.0.2", "@types/react-resizable": "^3.0.8", "@types/relay-test-utils": "^19.0.0", "@vitejs/plugin-react": "^4.5.0", - "ahooks": "^3.8.4", - "dayjs": "^1.11.13", "eslint": "^8.57.1", "eslint-config-react-app": "^7.0.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-react": "^7.37.4", "eslint-plugin-storybook": "^9.1.1", "fast-glob": "^3.3.3", - "graphql": "^16.10.0", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "storybook": "^9.1.1", diff --git a/packages/backend.ai-ui/src/components/BAIGraphQLPropertyFilter.tsx b/packages/backend.ai-ui/src/components/BAIGraphQLPropertyFilter.tsx index 7a8917f877..8e5d262f23 100644 --- a/packages/backend.ai-ui/src/components/BAIGraphQLPropertyFilter.tsx +++ b/packages/backend.ai-ui/src/components/BAIGraphQLPropertyFilter.tsx @@ -136,8 +136,25 @@ interface FilterCondition { } const OPERATORS_BY_TYPE: Record = { - string: ['equals', 'notEquals', 'contains', 'startsWith', 'endsWith', 'in', 'notIn'], - number: ['equals', 'notEquals', 'greaterThan', 'greaterOrEqual', 'lessThan', 'lessOrEqual', 'in', 'notIn'], + string: [ + 'equals', + 'notEquals', + 'contains', + 'startsWith', + 'endsWith', + 'in', + 'notIn', + ], + number: [ + 'equals', + 'notEquals', + 'greaterThan', + 'greaterOrEqual', + 'lessThan', + 'lessOrEqual', + 'in', + 'notIn', + ], boolean: ['equals'], enum: ['equals', 'notEquals', 'in', 'notIn'], }; diff --git a/packages/backend.ai-ui/src/components/BAIImportFromHuggingFaceModal.tsx b/packages/backend.ai-ui/src/components/BAIImportFromHuggingFaceModal.tsx new file mode 100644 index 0000000000..9447f3c61e --- /dev/null +++ b/packages/backend.ai-ui/src/components/BAIImportFromHuggingFaceModal.tsx @@ -0,0 +1,150 @@ +import { BAIImportFromHuggingFaceModalScanArtifactModelsMutation } from '../__generated__/BAIImportFromHuggingFaceModalScanArtifactModelsMutation.graphql'; +import BAIFlex from './BAIFlex'; +import BAIText from './BAIText'; +import BAIUnmountAfterClose from './BAIUnmountAfterClose'; +import { App, Form, Input, Modal, ModalProps } from 'antd'; +import { useTranslation } from 'react-i18next'; +import { graphql, useMutation } from 'react-relay'; + +export interface BAIImportFromHuggingFaceModalProps + extends Omit { + onOk: (e: React.MouseEvent, artifactId: string) => void; +} + +const BAIImportFromHuggingFaceModal = ({ + onOk, + onCancel, + ...modalProps +}: BAIImportFromHuggingFaceModalProps) => { + const { t } = useTranslation(); + const [form] = Form.useForm(); + const { message } = App.useApp(); + + const [scanArtifactModels, isInflightScanArtifactModels] = + useMutation( + graphql` + mutation BAIImportFromHuggingFaceModalScanArtifactModelsMutation( + $input: ScanArtifactModelsInput! + ) { + scanArtifactModels(input: $input) { + artifactRevision { + count + edges { + node { + artifact { + id + } + } + } + } + } + } + `, + ); + return ( + + { + form + .validateFields() + .then((values) => { + scanArtifactModels({ + variables: { + input: { + models: [ + { + modelId: values.modelId, + revision: values.revision ?? null, + }, + ], + }, + }, + onCompleted: (res, errors) => { + if (errors && errors.length > 0) { + errors.forEach((err) => + message.error( + err.message ?? + t( + 'comp:BAIImportFromHuggingFaceModal.Failed to import model from hugging face', + ), + ), + ); + return; + } + message.success( + t( + 'comp:BAIImportFromHuggingFaceModal.SuccessfullyImportedModelFromHuggingFace', + ), + ); + onOk( + e, + res.scanArtifactModels.artifactRevision.edges[0].node + .artifact.id, + ); + }, + onError: (error) => { + message.error( + error.message ?? + t( + 'comp:BAIImportFromHuggingFaceModal.Failed to import model from hugging face', + ), + ); + }, + }); + }) + .catch(() => {}); + }} + onCancel={(e) => { + onCancel?.(e); + }} + afterClose={() => { + form.resetFields(); + }} + > +
+ + + {t('comp:BAIImportFromHuggingFaceModal.ModalDescription')} + + + + + + + + +
+
+
+ ); +}; + +export default BAIImportFromHuggingFaceModal; diff --git a/packages/backend.ai-ui/src/components/BAISelect.tsx b/packages/backend.ai-ui/src/components/BAISelect.tsx new file mode 100644 index 0000000000..3aa23f50e9 --- /dev/null +++ b/packages/backend.ai-ui/src/components/BAISelect.tsx @@ -0,0 +1,180 @@ +import BAIFlex from './BAIFlex'; +import { Divider, Select, SelectProps, theme, Tooltip, Typography } from 'antd'; +import { createStyles } from 'antd-style'; +import { BaseOptionType, DefaultOptionType } from 'antd/es/select'; +import { GetRef } from 'antd/lib'; +import classNames from 'classnames'; +import _ from 'lodash'; +import React, { useLayoutEffect, useRef } from 'react'; + +const useStyles = createStyles(({ css, token }) => ({ + ghostSelect: css` + &.ant-select { + .ant-select-selector { + background-color: transparent; + border-color: ${token.colorBgBase} !important; + /* box-shadow: none; */ + color: ${token.colorBgBase}; + /* transition: color 0.3s, border-color 0.3s; */ + } + + &:hover .ant-select-selector { + background-color: rgb(255 255 255 / 10%); + } + + &:active .ant-select-selector { + background-color: rgb(255 255 255 / 10%); + } + + .ant-select-arrow { + color: ${token.colorBgBase}; + } + + &:hover .ant-select-arrow { + color: ${token.colorBgBase}; + } + + &:active .ant-select-arrow { + color: ${token.colorBgBase}; + } + } + `, +})); + +export interface BAISelectProps< + ValueType = any, + OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType, +> extends SelectProps { + ref?: React.RefObject> | null>; + ghost?: boolean; + autoSelectOption?: + | boolean + | ((options: SelectProps['options']) => ValueType); + tooltip?: string; + atBottomThreshold?: number; + atBottomStateChange?: (atBottom: boolean) => void; + bottomLoading?: boolean; + footer?: React.ReactNode; + endReached?: () => void; // New prop for endReached +} + +function BAISelect< + ValueType = any, + OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType, +>({ + ref, + autoSelectOption, + ghost, + tooltip = '', + atBottomThreshold = 30, + atBottomStateChange, + bottomLoading, + footer, + endReached, // Destructure the new prop + ...selectProps +}: BAISelectProps): React.ReactElement { + const { value, options, onChange } = selectProps; + const { styles } = useStyles(); + // const dropdownRef = useRef(null); + const lastScrollTop = useRef(0); + const isAtBottom = useRef(false); + const { token } = theme.useToken(); + + useLayoutEffect(() => { + if (autoSelectOption && _.isEmpty(value) && options?.[0]) { + if (_.isBoolean(autoSelectOption)) { + onChange?.(options?.[0].value || options?.[0], options?.[0]); + } else if (_.isFunction(autoSelectOption)) { + onChange?.(autoSelectOption(options), options?.[0]); + } + } + }, [value, options, onChange, autoSelectOption]); + + // Function to check if the scroll has reached the bottom + const handlePopupScroll = (e: React.UIEvent) => { + if (!atBottomStateChange && !endReached) return; // Check for endReached + + const target = e.target as HTMLElement; + const scrollTop = target.scrollTop; + // const scrollDirection = scrollTop > lastScrollTop.current ? 'down' : 'up'; + lastScrollTop.current = scrollTop; + + const isAtBottomNow = + target.scrollHeight - scrollTop - target.clientHeight <= + atBottomThreshold; + + // Only notify when the state changes + // ~~or when scrolling down at the bottom~~ + if ( + isAtBottomNow !== isAtBottom.current + // || + // (isAtBottomNow && scrollDirection === 'down') + ) { + isAtBottom.current = isAtBottomNow; + atBottomStateChange?.(isAtBottomNow); + + if (isAtBottomNow) { + endReached?.(); // Call endReached when at the bottom + } + } + }; + + return ( + + + {...selectProps} + ref={ref} + className={ + ghost + ? classNames(styles.ghostSelect, selectProps.className) + : selectProps.className + } + onPopupScroll={(e) => { + if (atBottomStateChange || endReached) handlePopupScroll(e); + selectProps.onPopupScroll?.(e); + }} + dropdownRender={ + footer + ? (menu) => { + // Process with custom dropdownRender if provided + // const renderedMenu = selectProps.dropdownRender + // ? selectProps.dropdownRender(menu) + // : menu; + + return ( + + {menu} + + + {_.isString(footer) ? ( + + {footer} + + ) : ( + footer + )} + + + ); + } + : undefined + } + /> + + ); +} + +export default BAISelect; diff --git a/packages/backend.ai-ui/src/components/TotalFooter.tsx b/packages/backend.ai-ui/src/components/TotalFooter.tsx new file mode 100644 index 0000000000..1df9ee3ea9 --- /dev/null +++ b/packages/backend.ai-ui/src/components/TotalFooter.tsx @@ -0,0 +1,33 @@ +import BAIFlex from './BAIFlex'; +import { LoadingOutlined } from '@ant-design/icons'; +import { theme, Typography } from 'antd'; +import { useTranslation } from 'react-i18next'; + +const TotalFooter: React.FC<{ + loading?: boolean; + total?: number; +}> = ({ loading, total }) => { + const { token } = theme.useToken(); + const { t } = useTranslation(); + return ( + + {loading ? ( + + ) : ( +
+ )} + + {t('general.TotalItems', { + total: total, + })} + + + ); +}; + +export default TotalFooter; diff --git a/packages/backend.ai-ui/src/components/fragments/BAIArtifactDescriptions.tsx b/packages/backend.ai-ui/src/components/fragments/BAIArtifactDescriptions.tsx new file mode 100644 index 0000000000..e5617128dd --- /dev/null +++ b/packages/backend.ai-ui/src/components/fragments/BAIArtifactDescriptions.tsx @@ -0,0 +1,71 @@ +import { BAIArtifactDescriptionsFragment$key } from '../../__generated__/BAIArtifactDescriptionsFragment.graphql'; +import BAILink from '../BAILink'; +import BAIArtifactTypeTag from './BAIArtifactTypeTag'; +import { Descriptions, DescriptionsProps, Typography } from 'antd'; +import dayjs from 'dayjs'; +import relativeTime from 'dayjs/plugin/relativeTime'; +import { useTranslation } from 'react-i18next'; +import { graphql, useFragment } from 'react-relay'; + +export interface BAIArtifactDescriptionsProps { + artifactFrgmt: BAIArtifactDescriptionsFragment$key; +} + +dayjs.extend(relativeTime); + +const BAIArtifactDescriptions = ({ + artifactFrgmt, +}: BAIArtifactDescriptionsProps) => { + const { t } = useTranslation(); + const artifact = useFragment( + graphql` + fragment BAIArtifactDescriptionsFragment on Artifact { + name + description + source { + name + url + } + ...BAIArtifactTypeTagFragment + } + `, + artifactFrgmt, + ); + + const items: DescriptionsProps['items'] = [ + { + key: 'name', + label: t('comp:BAIArtifactDescriptions.Name'), + children: artifact.name, + span: 2, + }, + { + key: 'type', + label: t('comp:BAIArtifactDescriptions.Type'), + children: , + }, + { + key: 'source', + label: t('comp:BAIArtifactDescriptions.Source'), + children: ( + + {artifact.source.name} + + ), + }, + { + key: 'description', + label: t('comp:BAIArtifactDescriptions.Description'), + children: artifact.description ? ( + {artifact.description} + ) : ( + 'N/A' + ), + span: 2, + }, + ]; + + return ; +}; + +export default BAIArtifactDescriptions; diff --git a/packages/backend.ai-ui/src/components/fragments/BAIArtifactRevisionDeleteButton.tsx b/packages/backend.ai-ui/src/components/fragments/BAIArtifactRevisionDeleteButton.tsx new file mode 100644 index 0000000000..2a4992a7f8 --- /dev/null +++ b/packages/backend.ai-ui/src/components/fragments/BAIArtifactRevisionDeleteButton.tsx @@ -0,0 +1,48 @@ +import { BAIArtifactRevisionDeleteButtonFragment$key } from '../../__generated__/BAIArtifactRevisionDeleteButtonFragment.graphql'; +import { BAITrashBinIcon } from '../../icons'; +import { Button, ButtonProps, theme } from 'antd'; +import _ from 'lodash'; +import { graphql, useFragment } from 'react-relay'; + +export interface BAIArtifactRevisionDeleteButtonProps + extends Omit { + revisionsFrgmt: BAIArtifactRevisionDeleteButtonFragment$key; + loading?: boolean; +} + +const BAIArtifactRevisionDeleteButton = ({ + revisionsFrgmt, + ...buttonProps +}: BAIArtifactRevisionDeleteButtonProps) => { + const { token } = theme.useToken(); + const revisions = useFragment( + graphql` + fragment BAIArtifactRevisionDeleteButtonFragment on ArtifactRevision + @relay(plural: true) { + status + } + `, + revisionsFrgmt, + ); + const isDeletable = revisions.some( + (revision) => + revision.status !== 'SCANNED' && revision.status !== 'PULLING', + ); + + return ( + + }} + /> + { + onClickDelete(record.id); + }} + /> + ); }, }, @@ -141,11 +152,14 @@ const BAIArtifactRevisionTable = ({ dataIndex: 'updatedAt', key: 'updatedAt', width: '15%', - render: (updated_at: string) => ( - - {dayjs(updated_at).fromNow()} - - ), + render: (updated_at: string) => + updated_at ? ( + + {dayjs(updated_at).fromNow()} + + ) : ( + 'N/A' + ), }, ]; diff --git a/packages/backend.ai-ui/src/components/fragments/BAIArtifactStatusTag.tsx b/packages/backend.ai-ui/src/components/fragments/BAIArtifactStatusTag.tsx new file mode 100644 index 0000000000..c3aba69a2f --- /dev/null +++ b/packages/backend.ai-ui/src/components/fragments/BAIArtifactStatusTag.tsx @@ -0,0 +1,24 @@ +import { BAIArtifactStatusTagFragment$key } from '../../__generated__/BAIArtifactStatusTagFragment.graphql'; +import BAITag from '../BAITag'; +import { graphql, useFragment } from 'react-relay'; + +export interface BAIArtifactStatusTagProps { + artifactRevisionFrgmt: BAIArtifactStatusTagFragment$key; +} + +const BAIArtifactStatusTag = ({ + artifactRevisionFrgmt, +}: BAIArtifactStatusTagProps) => { + const revision = useFragment( + graphql` + fragment BAIArtifactStatusTagFragment on ArtifactRevision { + status + } + `, + artifactRevisionFrgmt, + ); + + return {revision.status}; +}; + +export default BAIArtifactStatusTag; diff --git a/packages/backend.ai-ui/src/components/fragments/BAIArtifactTable.tsx b/packages/backend.ai-ui/src/components/fragments/BAIArtifactTable.tsx index 8c9fae0488..125bad7a5c 100644 --- a/packages/backend.ai-ui/src/components/fragments/BAIArtifactTable.tsx +++ b/packages/backend.ai-ui/src/components/fragments/BAIArtifactTable.tsx @@ -10,22 +10,17 @@ import { } from '../../helper'; import BAIFlex from '../BAIFlex'; import BAILink from '../BAILink'; -import BAITag from '../BAITag'; import BAIText from '../BAIText'; import { BAITable, BAITableProps } from '../Table'; +import BAIArtifactRevisionDownloadButton from './BAIArtifactRevisionDownloadButton'; +import BAIArtifactStatusTag from './BAIArtifactStatusTag'; +import BAIArtifactTypeTag from './BAIArtifactTypeTag'; import { SyncOutlined } from '@ant-design/icons'; -import { - Button, - TableColumnsType, - Tag, - theme, - Tooltip, - Typography, -} from 'antd'; +import { TableColumnsType, theme, Typography } from 'antd'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; import _ from 'lodash'; -import { Package, Container, Brain, Download } from 'lucide-react'; +import { Package, Container, Brain } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { graphql, useFragment } from 'react-relay'; @@ -56,19 +51,6 @@ export const getStatusIcon = (status: string) => { } }; -export const getTypeColor = (type: string) => { - switch (type) { - case 'model': - return 'blue'; - case 'package': - return 'green'; - case 'image': - return 'orange'; - default: - return 'default'; - } -}; - export const getTypeIcon = (type: string, size: number = 16) => { const colorMap = { model: '#1677ff', @@ -88,9 +70,8 @@ export const getTypeIcon = (type: string, size: number = 16) => { } }; -export type Artifact = NonNullable< - NonNullable[number] ->; +export type Artifact = + NonNullable[number]; export interface BAIArtifactTableProps extends Omit, 'dataSource' | 'columns' | 'rowKey'> { @@ -98,7 +79,7 @@ export interface BAIArtifactTableProps onClickPull: (artifactId: string, revisionId: string) => void; } -const BAIArtifactRevisionTable = ({ +const BAIArtifactTable = ({ artifactFragment, onClickPull, ...tableProps @@ -115,7 +96,8 @@ const BAIArtifactRevisionTable = ({ name description updatedAt - type + scannedAt + ...BAIArtifactTypeTagFragment latestVersion: revisions( first: 1 orderBy: { field: VERSION, direction: DESC } @@ -126,6 +108,8 @@ const BAIArtifactRevisionTable = ({ version size status + ...BAIArtifactStatusTagFragment + ...BAIArtifactRevisionDownloadButtonFragment } } } @@ -146,10 +130,7 @@ const BAIArtifactRevisionTable = ({ {name} - - {getTypeIcon(record.type, 14)}  - {record.type.toUpperCase()} - + {record.description && ( ); }, - width: '45%', + width: '30%', }, { title: t('comp:BAIArtifactRevisionTable.LatestVersion'), @@ -177,20 +158,14 @@ const BAIArtifactRevisionTable = ({ {latestVersion.version} - {latestVersion.status.toUpperCase()} + {latestVersion.status === 'SCANNED' ? ( - - } + message={t('comp:BAIPullingArtifactRevisionAlert.VersionIsPullingNow', { + version: pullingArtifactRevision.version, + })} + action={ + + } /> ); }; diff --git a/packages/backend.ai-ui/src/components/fragments/index.ts b/packages/backend.ai-ui/src/components/fragments/index.ts index 02df2211c6..1c3b240f6e 100644 --- a/packages/backend.ai-ui/src/components/fragments/index.ts +++ b/packages/backend.ai-ui/src/components/fragments/index.ts @@ -11,6 +11,25 @@ export type { BAIImportArtifactModalArtifactFragmentKey, BAIImportArtifactModalArtifactRevisionFragmentKey, } from './BAIImportArtifactModal'; - +export { default as BAIObjectStorageSelect } from './BAIObjectStorageSelect'; +export type { BAIObjectStorageSelectProps } from './BAIObjectStorageSelect'; +export { default as BAIBucketSelect } from './BAIBucketSelect'; +export type { BAIBucketSelectProps } from './BAIBucketSelect'; export { default as BAIPullingArtifactRevisionAlert } from './BAIPullingArtifactRevisionAlert'; export type { BAIPullingArtifactRevisionAlertProps } from './BAIPullingArtifactRevisionAlert'; +export { default as BAIDeleteArtifactModal } from './BAIDeleteArtifactModal'; +export type { + BAIDeleteArtifactModalProps, + BAIDeleteArtifactModalArtifactFragmentKey, + BAIDeleteArtifactModalArtifactRevisionFragmentKey, +} from './BAIDeleteArtifactModal'; +export { default as BAIArtifactTypeTag } from './BAIArtifactTypeTag'; +export type { BAIArtifactTypeTagProps } from './BAIArtifactTypeTag'; +export { default as BAIArtifactStatusTag } from './BAIArtifactStatusTag'; +export type { BAIArtifactStatusTagProps } from './BAIArtifactStatusTag'; +export { default as BAIArtifactDescriptions } from './BAIArtifactDescriptions'; +export type { BAIArtifactDescriptionsProps } from './BAIArtifactDescriptions'; +export { default as BAIArtifactRevisionDownloadButton } from './BAIArtifactRevisionDownloadButton'; +export type { BAIArtifactRevisionDownloadButtonProps } from './BAIArtifactRevisionDownloadButton'; +export { default as BAIArtifactRevisionDeleteButton } from './BAIArtifactRevisionDeleteButton'; +export type { BAIArtifactRevisionDeleteButtonProps } from './BAIArtifactRevisionDeleteButton'; diff --git a/packages/backend.ai-ui/src/components/index.ts b/packages/backend.ai-ui/src/components/index.ts index 61c194ce03..f063d48425 100644 --- a/packages/backend.ai-ui/src/components/index.ts +++ b/packages/backend.ai-ui/src/components/index.ts @@ -39,6 +39,10 @@ export { default as BAIBackButton } from './BAIBackButton'; export type { BAIBackButtonProps } from './BAIBackButton'; export { default as BAIText } from './BAIText'; export type { BAITextProps } from './BAIText'; +export { default as BAISelect } from './BAISelect'; +export type { BAISelectProps } from './BAISelect'; +export { default as BAIImportFromHuggingFaceModal } from './BAIImportFromHuggingFaceModal'; +export type { BAIImportFromHuggingFaceModalProps } from './BAIImportFromHuggingFaceModal'; export * from './Table'; export * from './fragments'; export * from './provider'; diff --git a/packages/backend.ai-ui/src/hooks/useEventNotStable.ts b/packages/backend.ai-ui/src/hooks/useEventNotStable.ts new file mode 100644 index 0000000000..dbc424c38d --- /dev/null +++ b/packages/backend.ai-ui/src/hooks/useEventNotStable.ts @@ -0,0 +1,21 @@ +import { useCallback, useLayoutEffect, useRef } from 'react'; + +export function useEventNotStable( + handler: (...args: Args) => Return, +) { + // eslint-disable-next-line + const handlerRef = useRef(undefined); + + // In a real implementation, this would run before layout effects + useLayoutEffect(() => { + handlerRef.current = handler; + }); + + // eslint-disable-next-line + // @ts-ignore + return useCallback((...args: Args) => { + // In a real implementation, this would throw if called during render + const fn = handlerRef.current; + return fn ? fn(...args) : undefined; + }, []); +} diff --git a/packages/backend.ai-ui/src/hooks/usePaginatedQuery.ts b/packages/backend.ai-ui/src/hooks/usePaginatedQuery.ts new file mode 100644 index 0000000000..2883ea2b63 --- /dev/null +++ b/packages/backend.ai-ui/src/hooks/usePaginatedQuery.ts @@ -0,0 +1,87 @@ +import { useEventNotStable } from './useEventNotStable'; +import _ from 'lodash'; +import { useState, useTransition, useMemo, useRef, useEffect } from 'react'; +import { GraphQLTaggedNode, useLazyLoadQuery } from 'react-relay'; +import { OperationType } from 'relay-runtime'; + +type extraOptions = { + getItem: (result: Result) => any; + getTotal: (result: Result) => number | undefined; + getId: (item: ItemType) => string | undefined | null; +}; +export function useLazyPaginatedQuery< + T extends OperationType & { + variables: { limit: number; offset: number }; + }, + ItemType, +>( + query: GraphQLTaggedNode, + initialPaginationVariables: Pick, + otherVariables: Omit, 'limit' | 'offset'>, + options: Parameters>[2], + { getItem, getId, getTotal }: extraOptions, +) { + const previousResult = useRef([]); + const [isLoadingNext, startLoadingNextTransition] = useTransition(); + + // limit doesn't change after the first render + const [limit] = useState(initialPaginationVariables.limit); + const [offset, setOffset] = useState(0); + + const previousOtherVariablesRef = useRef(otherVariables); + + const isNewOtherVariables = !_.isEqual( + previousOtherVariablesRef.current, + otherVariables, + ); + + // Fetch the initial data using useLazyLoadQuery + const result = useLazyLoadQuery( + query, + { + limit: isNewOtherVariables ? initialPaginationVariables.limit : limit, + offset: isNewOtherVariables ? 0 : offset, + ...otherVariables, + }, + options, + ); + + const data = useMemo(() => { + const items = getItem(result); + if (isNewOtherVariables) { + previousResult.current = []; + } + return items + ? _.uniqBy([...previousResult.current, ...items], getId) + : undefined; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [result]); + + const hasNext = offset + limit < (getTotal(result) as number); + + const loadNext = useEventNotStable(() => { + if (isLoadingNext || !hasNext) return; + previousResult.current = data || []; + startLoadingNextTransition(() => { + const nextOffset = offset + limit; + setOffset(nextOffset); + }); + }); + + useEffect(() => { + // Reset the offset and limit when otherVariables change after success rendering + if (isNewOtherVariables) { + previousOtherVariablesRef.current = otherVariables; + setOffset(0); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isNewOtherVariables]); + + return { + paginationData: data, + result, + loadNext, + hasNext, + isLoadingNext, + }; +} diff --git a/packages/backend.ai-ui/src/icons/BAIHuggingFaceIcon.tsx b/packages/backend.ai-ui/src/icons/BAIHuggingFaceIcon.tsx new file mode 100644 index 0000000000..641fbcbc88 --- /dev/null +++ b/packages/backend.ai-ui/src/icons/BAIHuggingFaceIcon.tsx @@ -0,0 +1,12 @@ +import { default as logo } from './HuggingFace.svg?react'; +import Icon from '@ant-design/icons'; +import { CustomIconComponentProps } from '@ant-design/icons/lib/components/Icon'; + +interface BAIHuggingFaceIconProps + extends Omit {} + +const BAIHuggingFaceIcon: React.FC = (props) => { + return ; +}; + +export default BAIHuggingFaceIcon; diff --git a/packages/backend.ai-ui/src/icons/HuggingFace.svg b/packages/backend.ai-ui/src/icons/HuggingFace.svg new file mode 100644 index 0000000000..56e2605be6 --- /dev/null +++ b/packages/backend.ai-ui/src/icons/HuggingFace.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/backend.ai-ui/src/icons/index.ts b/packages/backend.ai-ui/src/icons/index.ts index 2d894dcc55..acc050477e 100644 --- a/packages/backend.ai-ui/src/icons/index.ts +++ b/packages/backend.ai-ui/src/icons/index.ts @@ -38,3 +38,4 @@ export { default as BAIUploadIcon } from './BAIUploadIcon'; export { default as BAIURLStartIcon } from './BAIURLStartIcon'; export { default as BAIUserOutlinedIcon } from './BAIUserOutlinedIcon'; export { default as BAIUserUnionIcon } from './BAIUserUnionIcon'; +export { default as BAIHuggingFaceIcon } from './BAIHuggingFaceIcon'; diff --git a/packages/backend.ai-ui/src/locale/de.json b/packages/backend.ai-ui/src/locale/de.json index 681976a0cd..d09c4829ad 100644 --- a/packages/backend.ai-ui/src/locale/de.json +++ b/packages/backend.ai-ui/src/locale/de.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Beschreibung", + "Name": "Name", + "Source": "Quelle", + "Type": "Typ" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Aktion", + "Control": "Kontrolle", "LatestVersion": "Neueste Version", "Name": "Name", + "PullThisVersion": "Ziehen Sie diese Version", + "RemoveThisVersion": "Entfernen Sie diese Version", "Size": "Größe", "Status": "Status", "Updated": "Aktualisiert", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Aktion", "PullLatestVersion": "Die neueste Version ziehen", + "Scanned": "Gescannt", "Size": "Größe", "Updated": "Aktualisiert", "Version": "Version" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} Versionen sind ausgeschlossen.", + "FailedToRemoveVersions": "Versionen nicht entfernen.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Es können nur Versionen entfernt werden, die nicht im Ziehen oder beim Durchsuchen sind.", + "RemoveVersions": "Versionen entfernen", + "Size": "Größe", + "SuccessFullyRemoved": "Erfolgreich entfernt {{count}} Versionen.", + "Version": "Version" + }, "comp:BAIImportArtifactModal": { - "Description": "Beschreibung", - "Name": "Name", + "ExcludedVersions": "{{count}} Versionen sind ausgeschlossen.", + "FailedToPullVersions": "Versäumte, Versionen zu ziehen.", + "OnlySCANNEDVersionsCanBePulled": "Es können nur gescannte Versionen gezogen werden.", "Pull": "Ziehen", - "PullArtifact": "Artefakt ziehen", - "PulledVersionsAreExcluded": "Ziehversionen sind ausgeschlossen.", - "Source": "Quelle", - "Type": "Typ" + "PullVersion": "Pull -Version", + "Size": "Größe", + "SuccessFullyPulled": "Erfolgreich angeforderte Pull für {{count}} -Versionen.", + "Version": "Version" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Geben Sie eine Modell -ID ein. (z. B. OpenAI/GPT-OSS-20B)", + "EnterAVersion": "Geben Sie eine Version ein. (Standard: Haupt)", + "Failed to import model from hugging face": "Versäumte das Importieren von Modellen aus dem Umarmen des Gesichts", + "Import": "Import", + "ModalDescription": "Importieren Sie ein Modell aus dem Umarmen, indem Sie die Modell -ID und Version angeben.", + "ModalTitle": "Importieren vom umarmen Gesicht", + "ModelID": "Modell ID", + "SuccessfullyImportedModelFromHuggingFace": "Erfolgreich angeforderte Import von Modell aus dem Umarmen Gesicht", + "Version": "Version" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Suche", "ResetFilter": "Filter zurücksetzen" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Zivil ziehen", + "CancelingWillRestartThePulling": "Das Abbrechen startet das Ziehen neu", + "FailedToCancelThePulling": "Das Ziehen versäumte es, das Ziehen abzubrechen.", + "VersionIsPullingNow": "{{version}} Version zieht jetzt.", + "VersionPullCanceledSuccessfully": "Pull of {{version}} Version erfolgreich abgebrochen.", + "WARNING": "WARNUNG", + "YouAreAboutToCancelThisVersion": "Sie sind kurz davor, diese Version abzusagen" + }, "comp:BAISessionAgentIds": { "Agent": "Agent" }, @@ -82,10 +121,14 @@ }, "general": { "NSelected": "{{count}} ausgewählt", + "TotalItems": "Total {{total}} Elemente", "button": { + "Cancel": "Stornieren", + "Close": "Schließen", "CopyAll": "Alle kopieren", "Create": "Erstellen", "Delete": "Löschen", + "Remove": "Entfernen", "Upload": "Hochladen" } } diff --git a/packages/backend.ai-ui/src/locale/el.json b/packages/backend.ai-ui/src/locale/el.json index 03a62ca717..b75957ef2e 100644 --- a/packages/backend.ai-ui/src/locale/el.json +++ b/packages/backend.ai-ui/src/locale/el.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Περιγραφή", + "Name": "Ονομα", + "Source": "Πηγή", + "Type": "Τύπος" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Δράση", + "Control": "Ελεγχος", "LatestVersion": "Τελευταία έκδοση", "Name": "Ονομα", + "PullThisVersion": "Τραβήξτε αυτήν την έκδοση", + "RemoveThisVersion": "Καταργήστε αυτήν την έκδοση", "Size": "Μέγεθος", "Status": "Κατάσταση", "Updated": "Ενημερωμένος", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Δράση", "PullLatestVersion": "Τραβήξτε την τελευταία έκδοση", + "Scanned": "Σαρωμένος", "Size": "Μέγεθος", "Updated": "Ενημερωμένος", "Version": "Εκδοχή" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} Οι εκδόσεις εξαιρούνται.", + "FailedToRemoveVersions": "Αποτυχία κατάργησης των εκδόσεων.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Μόνο εκδόσεις που δεν είναι σε τράβηγμα ή σαρωμένη μπορούν να αφαιρεθούν.", + "RemoveVersions": "Καταργήστε τις εκδόσεις", + "Size": "Μέγεθος", + "SuccessFullyRemoved": "Κατάργηση επιτυχώς {{count}} εκδόσεις.", + "Version": "Εκδοχή" + }, "comp:BAIImportArtifactModal": { - "Description": "Περιγραφή", - "Name": "Ονομα", + "ExcludedVersions": "{{count}} Οι εκδόσεις εξαιρούνται.", + "FailedToPullVersions": "Απέτυχε να τραβήξει εκδόσεις.", + "OnlySCANNEDVersionsCanBePulled": "Μπορούν να τραβηχτούν μόνο οι σαρωμένες εκδόσεις.", "Pull": "Τραβήξτε", - "PullArtifact": "Τραβήξτε το τεχνούργημα", - "PulledVersionsAreExcluded": "Οι εκδόσεις που τραβήχτηκαν εξαιρούνται.", - "Source": "Πηγή", - "Type": "Τύπος" + "PullVersion": "Εκδοχή έλξης", + "Size": "Μέγεθος", + "SuccessFullyPulled": "Ζήτησε με επιτυχία την έλξη {{count}}}.", + "Version": "Εκδοχή" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Εισαγάγετε ένα αναγνωριστικό μοντέλου. (π.χ. OpenAI/GPT-OSS-20B)", + "EnterAVersion": "Εισαγάγετε μια έκδοση. (προεπιλογή: κύρια)", + "Failed to import model from hugging face": "Αποτυχία εισαγωγής μοντέλου από το πρόσωπο αγκάλιασμα", + "Import": "Εισαγωγή", + "ModalDescription": "Εισαγάγετε ένα μοντέλο από το αγκάλιασμα προσδιορίζοντας το αναγνωριστικό μοντέλου και την έκδοση.", + "ModalTitle": "Εισαγωγή από αγκαλιά πρόσωπο", + "ModelID": "Μοντέλο ταυτότητας", + "SuccessfullyImportedModelFromHuggingFace": "Ζήτησε επιτυχώς εισαγωγή μοντέλου από το αγκάλιασμα πρόσωπο", + "Version": "Εκδοχή" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Αναζήτηση", "ResetFilter": "Επαναφορά φίλτρων" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Ακυρώσω", + "CancelingWillRestartThePulling": "Η ακύρωση θα επανεκκινήσει το τράβηγμα", + "FailedToCancelThePulling": "Απέτυχε να ακυρώσει το τράβηγμα.", + "VersionIsPullingNow": "{{version}} Έκδοση τραβά τώρα.", + "VersionPullCanceledSuccessfully": "Τραβήξτε το {{version}} έκδοση ακυρώθηκε με επιτυχία.", + "WARNING": "ΠΡΟΕΙΔΟΠΟΙΗΣΗ", + "YouAreAboutToCancelThisVersion": "Πρόκειται να ακυρώσετε αυτήν την έκδοση" + }, "comp:BAISessionAgentIds": { "Agent": "Μέσο" }, @@ -82,10 +121,14 @@ }, "general": { "NSelected": "{{count}} Επιλεγμένη", + "TotalItems": "Σύνολο {{total}} στοιχεία", "button": { + "Cancel": "Ματαίωση", + "Close": "Κοντά", "CopyAll": "Αντιγράψτε όλα", "Create": "Δημιουργώ", "Delete": "Διαγράφω", + "Remove": "Αφαιρώ", "Upload": "Μεταφορτώσω" } } diff --git a/packages/backend.ai-ui/src/locale/en.json b/packages/backend.ai-ui/src/locale/en.json index 502a08d5c5..93f4197913 100644 --- a/packages/backend.ai-ui/src/locale/en.json +++ b/packages/backend.ai-ui/src/locale/en.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Description", + "Name": "Name", + "Source": "Source", + "Type": "Type" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Action", + "Control": "Control", "LatestVersion": "Latest Version", "Name": "Name", + "PullThisVersion": "Pull this version", + "RemoveThisVersion": "Remove this version", "Size": "Size", "Status": "Status", "Updated": "Updated", @@ -12,23 +20,57 @@ "comp:BAIArtifactTable": { "Action": "Action", "PullLatestVersion": "Pull latest version", + "Scanned": "Scanned", "Size": "Size", "Updated": "Updated", "Version": "Version" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} versions are excluded.", + "FailedToRemoveVersions": "Failed to remove versions.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Only versions that are not in PULLING or SCANNED can be removed.", + "RemoveVersions": "Remove Versions", + "Size": "Size", + "SuccessFullyRemoved": "Successfully removed {{count}} versions.", + "Version": "Version" + }, "comp:BAIImportArtifactModal": { - "Description": "Description", - "Name": "Name", + "ExcludedVersions": "{{count}} versions are excluded.", + "FailedToPullVersions": "Failed to pull versions.", + "OnlySCANNEDVersionsCanBePulled": "Only SCANNED versions can be pulled.", "Pull": "Pull", - "PullArtifact": "Pull Artifact", - "PulledVersionsAreExcluded": "Pulled versions are excluded.", - "Source": "Source", - "Type": "Type" + "PullVersion": "Pull Version", + "Size": "Size", + "SuccessFullyPulled": "Successfully requested pull for {{count}} versions.", + "Version": "Version" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Enter a model ID. (e.g. openai/gpt-oss-20b)", + "EnterAVersion": "Enter a version. (default: main)", + "Failed to import model from hugging face": "Failed to import model from hugging face", + "Import": "Import", + "ModalDescription": "Import a model from Hugging Face by specifying the Model ID and Version.", + "ModalTitle": "Import From Hugging Face", + "ModelID": "Model ID", + "SuccessfullyImportedModelFromHuggingFace": "Successfully requested import of model from Hugging Face", + "Version": "Version" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Search", "ResetFilter": "Reset filters" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Cancel Pull", + "CancelingWillRestartThePulling": "Canceling will restart the pulling", + "FailedToCancelThePulling": "Failed to cancel the pulling.", + "VersionIsPullingNow": "{{version}} version is pulling now.", + "VersionPullCanceledSuccessfully": "Pull of {{version}} version canceled successfully.", + "WARNING": "WARNING", + "YouAreAboutToCancelThisVersion": "You are about to cancel this version" + }, + "comp:BAIResourceWithSteppedProgress": { + "Unlimited": "Unlimited" + }, "comp:BAISessionAgentIds": { "Agent": "Agent" }, @@ -82,10 +124,14 @@ }, "general": { "NSelected": "{{count}} selected", + "TotalItems": "Total {{total}} items", "button": { + "Cancel": "Cancel", + "Close": "Close", "CopyAll": "Copy All", "Create": "Create", "Delete": "Delete", + "Remove": "Remove", "Upload": "Upload" } } diff --git a/packages/backend.ai-ui/src/locale/es.json b/packages/backend.ai-ui/src/locale/es.json index 6091e9811c..0d8b02d079 100644 --- a/packages/backend.ai-ui/src/locale/es.json +++ b/packages/backend.ai-ui/src/locale/es.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Descripción", + "Name": "Nombre", + "Source": "Fuente", + "Type": "Tipo" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Acción", + "Control": "Control", "LatestVersion": "Última versión", "Name": "Nombre", + "PullThisVersion": "Tire de esta versión", + "RemoveThisVersion": "Eliminar esta versión", "Size": "Tamaño", "Status": "Estado", "Updated": "Actualizado", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Acción", "PullLatestVersion": "Tire de la última versión", + "Scanned": "Escaneado", "Size": "Tamaño", "Updated": "Actualizado", "Version": "Versión" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "Las versiones {{count}} están excluidas.", + "FailedToRemoveVersions": "No se pudo eliminar las versiones.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Solo se pueden eliminar las versiones que no están en tirar o escanear.", + "RemoveVersions": "Eliminar versiones", + "Size": "Tamaño", + "SuccessFullyRemoved": "Las versiones {{count}} eliminadas con éxito.", + "Version": "Versión" + }, "comp:BAIImportArtifactModal": { - "Description": "Descripción", - "Name": "Nombre", + "ExcludedVersions": "Las versiones {{count}} están excluidas.", + "FailedToPullVersions": "No se pudo tirar de versiones.", + "OnlySCANNEDVersionsCanBePulled": "Solo se pueden extraer versiones escaneadas.", "Pull": "Jalar", - "PullArtifact": "Artefacto", - "PulledVersionsAreExcluded": "Se excluyen las versiones extraídas.", - "Source": "Fuente", - "Type": "Tipo" + "PullVersion": "Versión", + "Size": "Tamaño", + "SuccessFullyPulled": "Solicitud solicitada con éxito para las versiones {{count}}.", + "Version": "Versión" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Ingrese una ID de modelo. (por ejemplo, OpenAI/GPT-OSS-20B)", + "EnterAVersion": "Ingrese una versión. (predeterminado: principal)", + "Failed to import model from hugging face": "No se pudo importar el modelo de la cara abrazada", + "Import": "Importar", + "ModalDescription": "Importar un modelo de abrazar la cara especificando el ID y la versión del modelo.", + "ModalTitle": "Importar de la cara abrazada", + "ModelID": "ID de modelo", + "SuccessfullyImportedModelFromHuggingFace": "Solicitado con éxito la importación de modelo de abrazo de la cara", + "Version": "Versión" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Buscar en", "ResetFilter": "Restablecer filtros" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Cancelar pull", + "CancelingWillRestartThePulling": "Cancelar reiniciará la tracción", + "FailedToCancelThePulling": "No se pudo cancelar la tracción.", + "VersionIsPullingNow": "{{version}} La versión está tirando ahora.", + "VersionPullCanceledSuccessfully": "Pull de la versión {{version}} cancelada correctamente.", + "WARNING": "ADVERTENCIA", + "YouAreAboutToCancelThisVersion": "Estás a punto de cancelar esta versión" + }, "comp:BAISessionAgentIds": { "Agent": "Agente" }, @@ -82,10 +121,14 @@ }, "general": { "NSelected": "{{count}} seleccionado", + "TotalItems": "Total {{total}} elementos", "button": { + "Cancel": "Cancelar", + "Close": "Cerca", "CopyAll": "Copiar todo", "Create": "Crear", "Delete": "Borrar", + "Remove": "Eliminar", "Upload": "Subir" } } diff --git a/packages/backend.ai-ui/src/locale/fi.json b/packages/backend.ai-ui/src/locale/fi.json index c8faa225ab..67bce0983d 100644 --- a/packages/backend.ai-ui/src/locale/fi.json +++ b/packages/backend.ai-ui/src/locale/fi.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Kuvaus", + "Name": "Nimi", + "Source": "Lähde", + "Type": "Tyyppi" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Toiminta", + "Control": "Hallinta", "LatestVersion": "Uusin versio", "Name": "Nimi", + "PullThisVersion": "Vedä tämä versio", + "RemoveThisVersion": "Poista tämä versio", "Size": "Koko", "Status": "Status", "Updated": "Päivitetty", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Toiminta", "PullLatestVersion": "Vedä uusin versio", + "Scanned": "Skannattu", "Size": "Koko", "Updated": "Päivitetty", "Version": "Versio" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} versiot jätetään pois.", + "FailedToRemoveVersions": "Versioiden poistaminen epäonnistui.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Vain versiot, jotka eivät ole vetämisessä tai skannattuna, voidaan poistaa.", + "RemoveVersions": "Poista versiot", + "Size": "Koko", + "SuccessFullyRemoved": "Poistettu onnistuneesti {{count}} versiot.", + "Version": "Versio" + }, "comp:BAIImportArtifactModal": { - "Description": "Kuvaus", - "Name": "Nimi", + "ExcludedVersions": "{{count}} versiot jätetään pois.", + "FailedToPullVersions": "Versioiden vetäminen epäonnistui.", + "OnlySCANNEDVersionsCanBePulled": "Vain skannatut versiot voidaan vetää.", "Pull": "Vedä", - "PullArtifact": "Vetää artefakti", - "PulledVersionsAreExcluded": "Vedetyt versiot jätetään pois.", - "Source": "Lähde", - "Type": "Tyyppi" + "PullVersion": "Vetää versio", + "Size": "Koko", + "SuccessFullyPulled": "Onnistuneesti pyydetty veto {{count}} versioille.", + "Version": "Versio" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Syötä mallitunnus. (esim. OpenAi/GPT-OSS-20b)", + "EnterAVersion": "Kirjoita versio. (Oletus: Main)", + "Failed to import model from hugging face": "Mallin tuonti epäonnistui kasvojen halaamisesta", + "Import": "Tuoda", + "ModalDescription": "Tuo malli halaamisesta kasvoista määrittelemällä mallitunnus ja versio.", + "ModalTitle": "Tuo halaus kasvoista", + "ModelID": "Mallitunnus", + "SuccessfullyImportedModelFromHuggingFace": "Onnistuneesti pyydetty mallin tuonti halaamisesta", + "Version": "Versio" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Etsi", "ResetFilter": "Nollaa suodattimet" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Peruuta veto", + "CancelingWillRestartThePulling": "Peruuttaminen käynnistää vetämisen uudelleen", + "FailedToCancelThePulling": "Vedämisen peruuttaminen epäonnistui.", + "VersionIsPullingNow": "{{version}} versio vetää nyt.", + "VersionPullCanceledSuccessfully": "{{version}} versio peruutettu onnistuneesti.", + "WARNING": "VAROITUS", + "YouAreAboutToCancelThisVersion": "Olet peruuttanut tämän version" + }, "comp:BAISessionAgentIds": { "Agent": "Agentti" }, @@ -82,10 +121,14 @@ }, "general": { "NSelected": "{{count}} valittu", + "TotalItems": "Yhteensä {{total}} kohteet", "button": { + "Cancel": "Peruuttaa", + "Close": "Lähellä", "CopyAll": "Kopioida kaikki", "Create": "Luoda", "Delete": "Poistaa", + "Remove": "Poistaa", "Upload": "Ladata" } } diff --git a/packages/backend.ai-ui/src/locale/fr.json b/packages/backend.ai-ui/src/locale/fr.json index d568022ab4..4273bd03ea 100644 --- a/packages/backend.ai-ui/src/locale/fr.json +++ b/packages/backend.ai-ui/src/locale/fr.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Description", + "Name": "Nom", + "Source": "Source", + "Type": "Taper" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Action", + "Control": "Contrôle", "LatestVersion": "Dernière version", "Name": "Nom", + "PullThisVersion": "Tirez cette version", + "RemoveThisVersion": "Supprimer cette version", "Size": "Taille", "Status": "Statut", "Updated": "Mis à jour", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Action", "PullLatestVersion": "Tirez la dernière version", + "Scanned": "Numérisé", "Size": "Taille", "Updated": "Mis à jour", "Version": "Version" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "Les versions {{count}} sont exclues.", + "FailedToRemoveVersions": "Échec de la suppression des versions.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Seules les versions qui ne sont pas en tirant ou numérisées peuvent être supprimées.", + "RemoveVersions": "Supprimer les versions", + "Size": "Taille", + "SuccessFullyRemoved": "Suppression avec succès des versions {{count}}.", + "Version": "Version" + }, "comp:BAIImportArtifactModal": { - "Description": "Description", - "Name": "Nom", + "ExcludedVersions": "Les versions {{count}} sont exclues.", + "FailedToPullVersions": "N'a pas réussi à tirer des versions.", + "OnlySCANNEDVersionsCanBePulled": "Seules les versions numérisées peuvent être tirées.", "Pull": "Tirer", - "PullArtifact": "Tirez l'artefact", - "PulledVersionsAreExcluded": "Les versions tirées sont exclues.", - "Source": "Source", - "Type": "Taper" + "PullVersion": "Version de traction", + "Size": "Taille", + "SuccessFullyPulled": "Pull demandé avec succès pour les versions {{count}}.", + "Version": "Version" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Entrez un ID de modèle. (par exemple OpenAI / GPT-OSS-20B)", + "EnterAVersion": "Entrez une version. (par défaut: Main)", + "Failed to import model from hugging face": "Échec de l'importation du modèle à partir de l'étreinte", + "Import": "Importer", + "ModalDescription": "Importez un modèle à partir de l'étreinte Face en spécifiant l'ID et la version du modèle.", + "ModalTitle": "Importer à partir du visage étreint", + "ModelID": "ID de modèle", + "SuccessfullyImportedModelFromHuggingFace": "A demandé avec succès l'importation de modèle à partir de l'étreinte", + "Version": "Version" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Recherche", "ResetFilter": "Réinitialiser les filtres" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Annuler la traction", + "CancelingWillRestartThePulling": "L'annulation redémarrera le traction", + "FailedToCancelThePulling": "Échec de l'annulation de la traction.", + "VersionIsPullingNow": "La version {{version}} tire maintenant.", + "VersionPullCanceledSuccessfully": "Pull of {{version}} version annulée avec succès.", + "WARNING": "AVERTISSEMENT", + "YouAreAboutToCancelThisVersion": "Vous êtes sur le point d'annuler cette version" + }, "comp:BAISessionAgentIds": { "Agent": "Agent" }, @@ -82,10 +121,14 @@ }, "general": { "NSelected": "{{count}} sélectionné", + "TotalItems": "Éléments totaux {{total}}", "button": { + "Cancel": "Annuler", + "Close": "Fermer", "CopyAll": "Copier tout", "Create": "Créer", "Delete": "Supprimer", + "Remove": "Retirer", "Upload": "Télécharger" } } diff --git a/packages/backend.ai-ui/src/locale/id.json b/packages/backend.ai-ui/src/locale/id.json index 5c77f41e03..4d89952715 100644 --- a/packages/backend.ai-ui/src/locale/id.json +++ b/packages/backend.ai-ui/src/locale/id.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Keterangan", + "Name": "Nama", + "Source": "Sumber", + "Type": "Jenis" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Tindakan", + "Control": "Kontrol", "LatestVersion": "Versi Terbaru", "Name": "Nama", + "PullThisVersion": "Tarik versi ini", + "RemoveThisVersion": "Hapus versi ini", "Size": "Ukuran", "Status": "Status", "Updated": "Diperbarui", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Tindakan", "PullLatestVersion": "Tarik versi terbaru", + "Scanned": "Dipindai", "Size": "Ukuran", "Updated": "Diperbarui", "Version": "Versi" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} versi dikecualikan.", + "FailedToRemoveVersions": "Gagal menghapus versi.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Hanya versi yang tidak menarik atau dipindai yang dapat dilepas.", + "RemoveVersions": "Hapus versi", + "Size": "Ukuran", + "SuccessFullyRemoved": "Berhasil menghapus {{count}} versi.", + "Version": "Versi" + }, "comp:BAIImportArtifactModal": { - "Description": "Keterangan", - "Name": "Nama", + "ExcludedVersions": "{{count}} versi dikecualikan.", + "FailedToPullVersions": "Gagal menarik versi.", + "OnlySCANNEDVersionsCanBePulled": "Hanya versi yang dipindai yang bisa ditarik.", "Pull": "Menarik", - "PullArtifact": "Tarik artefak", - "PulledVersionsAreExcluded": "Versi yang ditarik dikecualikan.", - "Source": "Sumber", - "Type": "Jenis" + "PullVersion": "Tarik versi", + "Size": "Ukuran", + "SuccessFullyPulled": "Berhasil meminta tarik untuk versi {{count}}.", + "Version": "Versi" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Masukkan ID Model. (mis. OpenAi/GPT-OSS-20B)", + "EnterAVersion": "Masukkan versi. (Default: Utama)", + "Failed to import model from hugging face": "Gagal mengimpor model dari wajah memeluk", + "Import": "Impor", + "ModalDescription": "Impor model dari memeluk wajah dengan menentukan ID model dan versi.", + "ModalTitle": "Impor dari Wajah Memeluk", + "ModelID": "ID Model", + "SuccessfullyImportedModelFromHuggingFace": "Berhasil Meminta Impor Model dari Face Memeluk", + "Version": "Versi" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Pencarian", "ResetFilter": "Setel ulang filter" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Batalkan Tarik", + "CancelingWillRestartThePulling": "Membatalkan akan memulai kembali penarikan", + "FailedToCancelThePulling": "Gagal membatalkan penarikan.", + "VersionIsPullingNow": "{{version}} versi menarik sekarang.", + "VersionPullCanceledSuccessfully": "Tarik {{version}} versi berhasil dibatalkan.", + "WARNING": "PERINGATAN", + "YouAreAboutToCancelThisVersion": "Anda akan membatalkan versi ini" + }, "comp:BAISessionAgentIds": { "Agent": "Agen" }, @@ -82,10 +121,14 @@ }, "general": { "NSelected": "{{count}} dipilih", + "TotalItems": "Total {{total}} item", "button": { + "Cancel": "Membatalkan", + "Close": "Menutup", "CopyAll": "Salin semua", "Create": "Membuat", "Delete": "Menghapus", + "Remove": "Menghapus", "Upload": "Mengunggah" } } diff --git a/packages/backend.ai-ui/src/locale/it.json b/packages/backend.ai-ui/src/locale/it.json index efac5ec4d9..a724769691 100644 --- a/packages/backend.ai-ui/src/locale/it.json +++ b/packages/backend.ai-ui/src/locale/it.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Descrizione", + "Name": "Nome", + "Source": "Fonte", + "Type": "Tipo" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Azione", + "Control": "Controllare", "LatestVersion": "Ultima versione", "Name": "Nome", + "PullThisVersion": "Tira questa versione", + "RemoveThisVersion": "Rimuovi questa versione", "Size": "Misurare", "Status": "Stato", "Updated": "Aggiornato", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Azione", "PullLatestVersion": "Estrarre l'ultima versione", + "Scanned": "Scansionato", "Size": "Misurare", "Updated": "Aggiornato", "Version": "Versione" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "Le versioni {{count}} sono escluse.", + "FailedToRemoveVersions": "Impossibile rimuovere le versioni.", + "OnlyVersionsNotInPULLINGOrSCANNED": "È possibile rimuovere solo le versioni che non sono in tiro o scansionati.", + "RemoveVersions": "Rimuovere le versioni", + "Size": "Misurare", + "SuccessFullyRemoved": "Rimosse correttamente {{count}} versioni.", + "Version": "Versione" + }, "comp:BAIImportArtifactModal": { - "Description": "Descrizione", - "Name": "Nome", + "ExcludedVersions": "Le versioni {{count}} sono escluse.", + "FailedToPullVersions": "Non è riuscito a tirare le versioni.", + "OnlySCANNEDVersionsCanBePulled": "È possibile estrarre solo versioni scansionate.", "Pull": "Tiro", - "PullArtifact": "Tirare artefatto", - "PulledVersionsAreExcluded": "Le versioni tirate sono escluse.", - "Source": "Fonte", - "Type": "Tipo" + "PullVersion": "Pull versione", + "Size": "Misurare", + "SuccessFullyPulled": "Pullo correttamente richiesto per le versioni {{count}}.", + "Version": "Versione" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Immettere un ID modello. (ad es. OpenAI/GPT-OSS-20B)", + "EnterAVersion": "Immettere una versione. (Predefinito: Main)", + "Failed to import model from hugging face": "Impossibile importare il modello da abbracciare la faccia", + "Import": "Importare", + "ModalDescription": "Importa un modello da abbracciare la faccia specificando l'ID modello e la versione.", + "ModalTitle": "Importazione da abbracciare la faccia", + "ModelID": "Modello ID", + "SuccessfullyImportedModelFromHuggingFace": "Ha richiesto con successo l'importazione di modello da abbraccio", + "Version": "Versione" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Ricerca", "ResetFilter": "Reimposta i filtri" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Annulla il pull", + "CancelingWillRestartThePulling": "L'annullamento riavvierà la trazione", + "FailedToCancelThePulling": "Impossibile annullare la trazione.", + "VersionIsPullingNow": "{{version}} La versione sta tirando ora.", + "VersionPullCanceledSuccessfully": "Pull of {{versione}} versione cancellata correttamente.", + "WARNING": "AVVERTIMENTO", + "YouAreAboutToCancelThisVersion": "Stai per annullare questa versione" + }, "comp:BAISessionAgentIds": { "Agent": "Agente" }, @@ -82,10 +121,14 @@ }, "general": { "NSelected": "{{count}} selezionato", + "TotalItems": "Totali {{total}} elementi", "button": { + "Cancel": "Cancellare", + "Close": "Vicino", "CopyAll": "Copia tutto", "Create": "Creare", "Delete": "Eliminare", + "Remove": "Rimuovere", "Upload": "Caricamento" } } diff --git a/packages/backend.ai-ui/src/locale/ja.json b/packages/backend.ai-ui/src/locale/ja.json index bb3e0ab145..fea59962dc 100644 --- a/packages/backend.ai-ui/src/locale/ja.json +++ b/packages/backend.ai-ui/src/locale/ja.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "説明", + "Name": "名前", + "Source": "ソース", + "Type": "タイプ" + }, "comp:BAIArtifactRevisionTable": { - "Action": "アクション", + "Control": "コントロール", "LatestVersion": "最新バージョン", "Name": "名前", + "PullThisVersion": "このバージョンをプルします", + "RemoveThisVersion": "このバージョンを削除します", "Size": "サイズ", "Status": "状態", "Updated": "更新", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "アクション", "PullLatestVersion": "最新バージョンをプルします", + "Scanned": "スキャン", "Size": "サイズ", "Updated": "更新", "Version": "バージョン" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}}バージョンは除外されます。", + "FailedToRemoveVersions": "バージョンの削除に失敗しました。", + "OnlyVersionsNotInPULLINGOrSCANNED": "引っ張ったりスキャンしたりしないバージョンのみを削除できます。", + "RemoveVersions": "バージョンを削除します", + "Size": "サイズ", + "SuccessFullyRemoved": "{{count}}バージョンを正常に削除しました。", + "Version": "バージョン" + }, "comp:BAIImportArtifactModal": { - "Description": "説明", - "Name": "名前", + "ExcludedVersions": "{{count}}バージョンは除外されます。", + "FailedToPullVersions": "バージョンを引くことができませんでした。", + "OnlySCANNEDVersionsCanBePulled": "スキャンされたバージョンのみを引くことができます。", "Pull": "引く", - "PullArtifact": "アーティファクトを引っ張ります", - "PulledVersionsAreExcluded": "プルバージョンは除外されます。", - "Source": "ソース", - "Type": "タイプ" + "PullVersion": "プルバージョン", + "Size": "サイズ", + "SuccessFullyPulled": "{{count}}バージョンのプルを正常に要求しました。", + "Version": "バージョン" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "モデルIDを入力します。 (例:openai/gpt-oss-20b)", + "EnterAVersion": "バージョンを入力します。 (デフォルト:メイン)", + "Failed to import model from hugging face": "顔を抱きしめてモデルをインポートできませんでした", + "Import": "インポート", + "ModalDescription": "モデルIDとバージョンを指定することにより、顔を抱きしめることからモデルをインポートします。", + "ModalTitle": "抱きしめる顔からのインポート", + "ModelID": "モデルID", + "SuccessfullyImportedModelFromHuggingFace": "抱き合った顔からモデルのインポートを正常にリクエストしました", + "Version": "バージョン" }, "comp:BAIPropertyFilter": { "PlaceHolder": "検索", "ResetFilter": "フィルターをリセットする" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "キャンセルプル", + "CancelingWillRestartThePulling": "キャンセルすると、引っ張りが再開されます", + "FailedToCancelThePulling": "引っ張りをキャンセルできませんでした。", + "VersionIsPullingNow": "{{version}}バージョンは今プルされています。", + "VersionPullCanceledSuccessfully": "{{version}}バージョンのプルは正常にキャンセルされました。", + "WARNING": "警告", + "YouAreAboutToCancelThisVersion": "このバージョンをキャンセルしようとしています" + }, "comp:BAISessionAgentIds": { "Agent": "エージェント" }, @@ -82,10 +121,14 @@ }, "general": { "NSelected": "{{count}}選択", + "TotalItems": "Total {{total}}アイテム", "button": { + "Cancel": "キャンセル", + "Close": "近い", "CopyAll": "すべてをコピーします", "Create": "作成する", "Delete": "消去", + "Remove": "取り除く", "Upload": "アップロード" } } diff --git a/packages/backend.ai-ui/src/locale/ko.json b/packages/backend.ai-ui/src/locale/ko.json index d5709d33b8..2d15a9a86d 100644 --- a/packages/backend.ai-ui/src/locale/ko.json +++ b/packages/backend.ai-ui/src/locale/ko.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "설명", + "Name": "이름", + "Source": "소스", + "Type": "유형" + }, "comp:BAIArtifactRevisionTable": { - "Action": "행동", + "Control": "제어", "LatestVersion": "최신 버전", "Name": "이름", + "PullThisVersion": "해당 버전 가져오기", + "RemoveThisVersion": "해당 버전 제거하기", "Size": "크기", "Status": "상태", "Updated": "업데이트", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "행동", "PullLatestVersion": "최신 버전을 가져옵니다", + "Scanned": "스캔", "Size": "크기", "Updated": "업데이트", "Version": "버전" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}}개 버전은 제외됐습니다.", + "FailedToRemoveVersions": "버전을 제거하는데 실패했습니다.", + "OnlyVersionsNotInPULLINGOrSCANNED": "SCANNED 또는 PULLING이 아닌 버전만 제거 가능합니다.", + "RemoveVersions": "목록에서 버전 제거하기", + "Size": "크기", + "SuccessFullyRemoved": "{{count}}개 버전을 성공적으로 제거했습니다.", + "Version": "버전" + }, "comp:BAIImportArtifactModal": { - "Description": "설명", - "Name": "이름", + "ExcludedVersions": "{{count}}개 버전은 제외됐습니다.", + "FailedToPullVersions": "버전을 가져오는데 실패했습니다.", + "OnlySCANNEDVersionsCanBePulled": "SCANNED인 버전만 가져올 수 있습니다.", "Pull": "가져오기", - "PullArtifact": "아티팩트 가져오기", - "PulledVersionsAreExcluded": "가져온 버전들은 제외되었습니다.", - "Source": "소스", - "Type": "유형" + "PullVersion": "버전 가져오기", + "Size": "크기", + "SuccessFullyPulled": "{{count}}개 버전에 대한 가져오기 요청을 성공적으로 보냈습니다.", + "Version": "버전" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "모델 ID를 입력하십시오. (예 : OpenAI/GPT-SOSS-20B)", + "EnterAVersion": "버전을 입력하십시오. (기본값 : main)", + "Failed to import model from hugging face": "허깅 페이스에서 모델을 가져오는데 실패했습니다.", + "Import": "가져오기", + "ModalDescription": "특정 모델 ID와 버전을 통해 허깅 페이스에서 모델을 가져옵니다.", + "ModalTitle": "허깅 페이스에서 가져오기", + "ModelID": "모델 ID", + "SuccessfullyImportedModelFromHuggingFace": "허깅 페이스에서 모델 가져오기 요청을 성공적으로 보냈습니다.", + "Version": "버전" }, "comp:BAIPropertyFilter": { "PlaceHolder": "검색", "ResetFilter": "필터 초기화" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "가져오기 취소", + "CancelingWillRestartThePulling": "취소하면 처음부터 가져옵니다.", + "FailedToCancelThePulling": "가져오기를 취소하는데 실패했습니다.", + "VersionIsPullingNow": "{{version}} 버전을 지금 가져오는 중입니다.", + "VersionPullCanceledSuccessfully": "{{version}} 버전 가져오기를 성공적으로 취소했습니다.", + "WARNING": "경고", + "YouAreAboutToCancelThisVersion": "다음의 버전을 취소하려고 합니다" + }, "comp:BAISessionAgentIds": { "Agent": "실행노드" }, @@ -82,10 +121,15 @@ }, "general": { "NSelected": "{{count}}개 선택됨", + "TotalItems": "총 {{total}} 항목", "button": { + "Cancel": "취소", + "Close": "닫기", "CopyAll": "모두 복사", "Create": "생성", "Delete": "삭제", + "Remove": "제거", + "Upload": "업로드" } } diff --git a/packages/backend.ai-ui/src/locale/mn.json b/packages/backend.ai-ui/src/locale/mn.json index 6d286cad36..26bd0f1653 100644 --- a/packages/backend.ai-ui/src/locale/mn.json +++ b/packages/backend.ai-ui/src/locale/mn.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Тодорхойлолт / төрөл анги", + "Name": "Нэр", + "Source": "Язгуур", + "Type": "Маяг" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Үйл ажиллагаа", + "Control": "Удирдах", "LatestVersion": "Хамгийн сүүлийн үеийн хувилбар", "Name": "Нэр", + "PullThisVersion": "Энэ хувилбарыг татаж", + "RemoveThisVersion": "Энэ хувилбарыг арилгах", "Size": "Хэмжээ", "Status": "Байдал", "Updated": "Шинэчилсэн цаг нь", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Үйл ажиллагаа", "PullLatestVersion": "Хамгийн сүүлийн хувилбарыг татах", + "Scanned": "Дээгэрсэн", "Size": "Хэмжээ", "Updated": "Шинэчилсэн цаг нь", "Version": "Таамаглал" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} хувилбарыг хасч болно.", + "FailedToRemoveVersions": "Хувилбаруудыг арилгаж чадсангүй.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Зөвхөн татах, сканнердсан, сканнердах боломжгүй хувилбарыг арилгаж болно.", + "RemoveVersions": "Хувилбарыг устгах", + "Size": "Хэмжээ", + "SuccessFullyRemoved": "Амжилттай хассан {{тоолох} хувилбарууд.", + "Version": "Таамаглал" + }, "comp:BAIImportArtifactModal": { - "Description": "Тодорхойлолт / төрөл анги", - "Name": "Нэр", + "ExcludedVersions": "{{count}} хувилбарыг хасч болно.", + "FailedToPullVersions": "Хувилбаруудыг татаж чадсангүй.", + "OnlySCANNEDVersionsCanBePulled": "Зөвхөн сканнердсан хувилбарыг татаж авах боломжтой.", "Pull": "Татах", - "PullArtifact": "Олдворыг татах", - "PulledVersionsAreExcluded": "Татсан хувилбарыг хассан болно.", - "Source": "Язгуур", - "Type": "Маяг" + "PullVersion": "Хувилбарыг ашиглах", + "Size": "Хэмжээ", + "SuccessFullyPulled": "{{count} хувилбарыг амжилттай хийхийг хүсч байна.", + "Version": "Таамаглал" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Загварын ID-г оруулна уу. (e.g. overai / gpt-oss-20b)", + "EnterAVersion": "Хувилбарыг оруулна уу. (Үндсэн: Үндсэн)", + "Failed to import model from hugging face": "Нүүрээ тэвэрч авахаас загварыг импортлох боломжгүй байна", + "Import": "Импортлох", + "ModalDescription": "Загварын ID болон хувилбарыг зааж өгөх замаар нүүрээ тэвэрч, загварчлалыг импортлох.", + "ModalTitle": "Тэвэрч буй царайг импортлох", + "ModelID": "Загвар он", + "SuccessfullyImportedModelFromHuggingFace": "Нүүр царайг тэвэрч авахаас шууд импортлохыг хүссэн", + "Version": "Таамаглал" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Хайх", "ResetFilter": "Шүүлтүүрийг дахин тохируулах" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Татах", + "CancelingWillRestartThePulling": "Цуцлах нь татах ажлыг дахин эхлүүлэх болно", + "FailedToCancelThePulling": "Татаж авахаа цуцалж чадсангүй.", + "VersionIsPullingNow": "{{version}} хувилбар нь одоо татаж байна.", + "VersionPullCanceledSuccessfully": "Татах {{version}} хувилбар амжилттай цуцаллаа.", + "WARNING": "Анхааруулга", + "YouAreAboutToCancelThisVersion": "Та энэ хувилбарыг цуцлах гэж байна" + }, "comp:BAISessionAgentIds": { "Agent": "Агент" }, @@ -82,10 +121,14 @@ }, "general": { "NSelected": "{{count}} сонгогдсон", + "TotalItems": "Нийт {{total}} зүйлүүд", "button": { + "Cancel": "Цуаах", + "Close": "Ойр дөхөм", "CopyAll": "Бүгдийг хуулбарлах", "Create": "Шуүгиан дэгдээх", "Delete": "Эдгээх", + "Remove": "Зөөх", "Upload": "Байршуулах" } } diff --git a/packages/backend.ai-ui/src/locale/ms.json b/packages/backend.ai-ui/src/locale/ms.json index 8c92c1161f..f52e8b12fe 100644 --- a/packages/backend.ai-ui/src/locale/ms.json +++ b/packages/backend.ai-ui/src/locale/ms.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Penerangan", + "Name": "Nama", + "Source": "Sumber", + "Type": "Jenis" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Tindakan", + "Control": "Kawalan", "LatestVersion": "Versi terkini", "Name": "Nama", + "PullThisVersion": "Tarik versi ini", + "RemoveThisVersion": "Keluarkan versi ini", "Size": "Saiz", "Status": "Status", "Updated": "Dikemas kini", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Tindakan", "PullLatestVersion": "Tarik versi terkini", + "Scanned": "Diimbas", "Size": "Saiz", "Updated": "Dikemas kini", "Version": "Versi" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} versi dikecualikan.", + "FailedToRemoveVersions": "Gagal mengeluarkan versi.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Hanya versi yang tidak menarik atau diimbas boleh dikeluarkan.", + "RemoveVersions": "Keluarkan versi", + "Size": "Saiz", + "SuccessFullyRemoved": "Berjaya dikeluarkan {{count}} versi.", + "Version": "Versi" + }, "comp:BAIImportArtifactModal": { - "Description": "Penerangan", - "Name": "Nama", + "ExcludedVersions": "{{count}} versi dikecualikan.", + "FailedToPullVersions": "Gagal menarik versi.", + "OnlySCANNEDVersionsCanBePulled": "Hanya versi yang diimbas boleh ditarik.", "Pull": "Tarik", - "PullArtifact": "Tarik artifak", - "PulledVersionsAreExcluded": "Versi yang ditarik dikecualikan.", - "Source": "Sumber", - "Type": "Jenis" + "PullVersion": "Tarik versi", + "Size": "Saiz", + "SuccessFullyPulled": "Berjaya meminta tarik untuk {{count}} versi.", + "Version": "Versi" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Masukkan ID Model. (mis. OpenAI/GPT-OSS-20B)", + "EnterAVersion": "Masukkan versi. (Lalai: Utama)", + "Failed to import model from hugging face": "Gagal mengimport model daripada memeluk muka", + "Import": "Import", + "ModalDescription": "Import model dari memeluk muka dengan menentukan ID dan versi model.", + "ModalTitle": "Import dari muka yang memeluk", + "ModelID": "ID Model", + "SuccessfullyImportedModelFromHuggingFace": "Berjaya meminta import model dari memeluk muka", + "Version": "Versi" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Cari", "ResetFilter": "Tetapkan semula penapis" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Batalkan tarik", + "CancelingWillRestartThePulling": "Membatalkan akan memulakan semula menarik", + "FailedToCancelThePulling": "Gagal membatalkan menarik.", + "VersionIsPullingNow": "{{version}} Versi sedang menarik sekarang.", + "VersionPullCanceledSuccessfully": "Tarik versi {{version}} dibatalkan dengan jayanya.", + "WARNING": "Amaran", + "YouAreAboutToCancelThisVersion": "Anda akan membatalkan versi ini" + }, "comp:BAISessionAgentIds": { "Agent": "Ejen" }, @@ -82,10 +121,15 @@ }, "general": { "NSelected": "{{count}} dipilih", + "TotalItems": "Jumlah {{total}} item", + "button": { + "Cancel": "Batalkan", + "Close": "Tutup", "CopyAll": "Salin semua", "Create": "Buat", "Delete": "Padam", + "Remove": "Keluarkan", "Upload": "Muat naik" } } diff --git a/packages/backend.ai-ui/src/locale/pl.json b/packages/backend.ai-ui/src/locale/pl.json index 45e0a42157..ee58f73282 100644 --- a/packages/backend.ai-ui/src/locale/pl.json +++ b/packages/backend.ai-ui/src/locale/pl.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Opis", + "Name": "Nazwa", + "Source": "Źródło", + "Type": "Typ" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Działanie", + "Control": "Kontrola", "LatestVersion": "Najnowsza wersja", "Name": "Nazwa", + "PullThisVersion": "Pociągnij tę wersję", + "RemoveThisVersion": "Usuń tę wersję", "Size": "Rozmiar", "Status": "Status", "Updated": "Zaktualizowane", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Działanie", "PullLatestVersion": "Wyciągnij najnowszą wersję", + "Scanned": "Zeskanowany", "Size": "Rozmiar", "Updated": "Zaktualizowane", "Version": "Wersja" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} wersje są wykluczone.", + "FailedToRemoveVersions": "Nie udało się usunąć wersji.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Tylko wersje, które nie są w ciągnięciu lub skanowane, można usunąć.", + "RemoveVersions": "Usuń wersje", + "Size": "Rozmiar", + "SuccessFullyRemoved": "Pomyślnie usunięte wersje {{count}}.", + "Version": "Wersja" + }, "comp:BAIImportArtifactModal": { - "Description": "Opis", - "Name": "Nazwa", + "ExcludedVersions": "{{count}} wersje są wykluczone.", + "FailedToPullVersions": "Nie udało się wyciągnąć wersji.", + "OnlySCANNEDVersionsCanBePulled": "Można wyciągnąć tylko zeskanowane wersje.", "Pull": "Ciągnąć", - "PullArtifact": "Wyciągnij artefakt", - "PulledVersionsAreExcluded": "Wyciągnięte wersje są wykluczone.", - "Source": "Źródło", - "Type": "Typ" + "PullVersion": "Wersja Pull", + "Size": "Rozmiar", + "SuccessFullyPulled": "Pomyślnie żądane Pull dla wersji {{count}}.", + "Version": "Wersja" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Wprowadź identyfikator modelu. (np. Openai/GPT-ASS-20B)", + "EnterAVersion": "Wprowadź wersję. (Domyślnie: Main)", + "Failed to import model from hugging face": "Nie udało się zaimportować modelu z przytulania twarzy", + "Import": "Import", + "ModalDescription": "Zaimportuj model z przytulania twarzy, określając identyfikator modelu i wersję.", + "ModalTitle": "Importuj z przytulania twarzy", + "ModelID": "Identyfikator modelu", + "SuccessfullyImportedModelFromHuggingFace": "Pomyślnie zażądał importu modelu z przytulania twarzy", + "Version": "Wersja" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Wyszukiwanie", "ResetFilter": "Zresetuj filtry" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Anuluj Pull", + "CancelingWillRestartThePulling": "Anulowanie ponownie uruchomi ciągnięcie", + "FailedToCancelThePulling": "Nie udało się anulować ciągnięcia.", + "VersionIsPullingNow": "{{version}} Wersja jest teraz ciągnąca.", + "VersionPullCanceledSuccessfully": "Pobranie wersji {{version}} anulowano pomyślnie.", + "WARNING": "OSTRZEŻENIE", + "YouAreAboutToCancelThisVersion": "Masz zamiar anulować tę wersję" + }, "comp:BAISessionAgentIds": { "Agent": "Agent" }, @@ -82,10 +121,15 @@ }, "general": { "NSelected": "{{count}}", + "TotalItems": "Total {{total}}", + "button": { + "Cancel": "Anulować", + "Close": "Zamknąć", "CopyAll": "Kopiuj wszystko", "Create": "Tworzyć", "Delete": "Usuwać", + "Remove": "Usunąć", "Upload": "Wgrywać" } } diff --git a/packages/backend.ai-ui/src/locale/pt-BR.json b/packages/backend.ai-ui/src/locale/pt-BR.json index a1c128aa73..244c435420 100644 --- a/packages/backend.ai-ui/src/locale/pt-BR.json +++ b/packages/backend.ai-ui/src/locale/pt-BR.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Descrição", + "Name": "Nome", + "Source": "Fonte", + "Type": "Tipo" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Ação", + "Control": "Controlar", "LatestVersion": "Versão mais recente", "Name": "Nome", + "PullThisVersion": "Puxe esta versão", + "RemoveThisVersion": "Remova esta versão", "Size": "Tamanho", "Status": "Status", "Updated": "Atualizado", @@ -12,10 +20,20 @@ "comp:BAIArtifactTable": { "Action": "Ação", "PullLatestVersion": "Puxe a versão mais recente", + "Scanned": "Digitalizado", "Size": "Tamanho", "Updated": "Atualizado", "Version": "Versão" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} versões são excluídas.", + "FailedToRemoveVersions": "Falha ao remover versões.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Somente versões que não estão em puxar ou digitalizadas podem ser removidas.", + "RemoveVersions": "Remover versões", + "Size": "Tamanho", + "SuccessFullyRemoved": "Removido com sucesso {{count}} versões.", + "Version": "Versão" + }, "comp:BAIImportArtifactModal": { "Description": "Descrição", "Name": "Nome", @@ -25,10 +43,30 @@ "Source": "Fonte", "Type": "Tipo" }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Digite um ID de modelo. (por exemplo, OpenAI/GPT-20B)", + "EnterAVersion": "Digite uma versão. (Padrão: Main)", + "Failed to import model from hugging face": "Falhou ao importar o modelo de abraçar o rosto", + "Import": "Importar", + "ModalDescription": "Importe um modelo de abraçar o rosto especificando o ID e a versão do modelo.", + "ModalTitle": "Importar de abraçar o rosto", + "ModelID": "ID do modelo", + "SuccessfullyImportedModelFromHuggingFace": "Solicitou com sucesso a importação do modelo de abraçar o rosto", + "Version": "Versão" + }, "comp:BAIPropertyFilter": { "PlaceHolder": "Pesquisar", "ResetFilter": "Redefinir filtros" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Cancelar puxar", + "CancelingWillRestartThePulling": "Cancelar irá reiniciar o puxão", + "FailedToCancelThePulling": "Falhou em cancelar a tração.", + "VersionIsPullingNow": "{{version}} A versão está puxando agora.", + "VersionPullCanceledSuccessfully": "Pull da versão {{version}} cancelada com sucesso.", + "WARNING": "AVISO", + "YouAreAboutToCancelThisVersion": "Você está prestes a cancelar esta versão" + }, "comp:BAISessionAgentIds": { "Agent": "Agente" }, @@ -82,10 +120,15 @@ }, "general": { "NSelected": "{{count}} selecionado", + "TotalItems": "Total {{total}} itens", + "button": { + "Cancel": "Cancelar", + "Close": "Fechar", "CopyAll": "Copie tudo", "Create": "Criar", "Delete": "Excluir", + "Remove": "Remover", "Upload": "Carregar" } } diff --git a/packages/backend.ai-ui/src/locale/pt.json b/packages/backend.ai-ui/src/locale/pt.json index a1c128aa73..8e315ed879 100644 --- a/packages/backend.ai-ui/src/locale/pt.json +++ b/packages/backend.ai-ui/src/locale/pt.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Descrição", + "Name": "Nome", + "Source": "Fonte", + "Type": "Tipo" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Ação", + "Control": "Controlar", "LatestVersion": "Versão mais recente", "Name": "Nome", + "PullThisVersion": "Puxe esta versão", + "RemoveThisVersion": "Remova esta versão", "Size": "Tamanho", "Status": "Status", "Updated": "Atualizado", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Ação", "PullLatestVersion": "Puxe a versão mais recente", + "Scanned": "Digitalizado", "Size": "Tamanho", "Updated": "Atualizado", "Version": "Versão" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} versões são excluídas.", + "FailedToRemoveVersions": "Falha ao remover versões.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Somente versões que não estão em puxar ou digitalizadas podem ser removidas.", + "RemoveVersions": "Remover versões", + "Size": "Tamanho", + "SuccessFullyRemoved": "Removido com sucesso {{count}} versões.", + "Version": "Versão" + }, "comp:BAIImportArtifactModal": { - "Description": "Descrição", - "Name": "Nome", + "ExcludedVersions": "{{count}} versões são excluídas.", + "FailedToPullVersions": "Falhou em puxar versões.", + "OnlySCANNEDVersionsCanBePulled": "Somente versões digitalizadas podem ser puxadas.", "Pull": "Puxar", - "PullArtifact": "Puxe artefato", - "PulledVersionsAreExcluded": "As versões puxadas são excluídas.", - "Source": "Fonte", - "Type": "Tipo" + "PullVersion": "Pull versão", + "Size": "Tamanho", + "SuccessFullyPulled": "Pull solicitado com sucesso para {{count}} versões.", + "Version": "Versão" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Enter a model ID. (por exemplo, OpenAI/GPT-20B)", + "EnterAVersion": "Digite uma versão. (Padrão: Main)", + "Failed to import model from hugging face": "Falhou ao importar o modelo de abraçar o rosto", + "Import": "Importar", + "ModalDescription": "Importe um modelo de abraçar o rosto especificando o ID e a versão do modelo.", + "ModalTitle": "Importar de abraçar o rosto", + "ModelID": "ID do modelo", + "SuccessfullyImportedModelFromHuggingFace": "Solicitou com sucesso a importação do modelo de abraçar o rosto", + "Version": "Versão" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Pesquisar", "ResetFilter": "Redefinir filtros" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Cancelar puxar", + "CancelingWillRestartThePulling": "Cancelar irá reiniciar o puxão", + "FailedToCancelThePulling": "Falhou em cancelar a tração.", + "VersionIsPullingNow": "{{version}} A versão está puxando agora.", + "VersionPullCanceledSuccessfully": "Pull da versão {{version}} cancelada com sucesso.", + "WARNING": "AVISO", + "YouAreAboutToCancelThisVersion": "Você está prestes a cancelar esta versão" + }, "comp:BAISessionAgentIds": { "Agent": "Agente" }, @@ -82,10 +121,15 @@ }, "general": { "NSelected": "{{count}} selecionado", + "TotalItems": "Total {{total}} itens", + "button": { + "Cancel": "Cancelar", + "Close": "Fechar", "CopyAll": "Copie tudo", "Create": "Criar", "Delete": "Excluir", + "Remove": "Remover", "Upload": "Carregar" } } diff --git a/packages/backend.ai-ui/src/locale/ru.json b/packages/backend.ai-ui/src/locale/ru.json index b06c9aa1f5..f910cf2a96 100644 --- a/packages/backend.ai-ui/src/locale/ru.json +++ b/packages/backend.ai-ui/src/locale/ru.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Описание", + "Name": "Имя", + "Source": "Источник", + "Type": "Тип" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Действие", + "Control": "Контроль", "LatestVersion": "Последняя версия", "Name": "Имя", + "PullThisVersion": "Вытащите эту версию", + "RemoveThisVersion": "Удалить эту версию", "Size": "Размер", "Status": "Статус", "Updated": "Обновлено", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Действие", "PullLatestVersion": "Вытащите последнюю версию", + "Scanned": "Сканируется", "Size": "Размер", "Updated": "Обновлено", "Version": "Версия" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} версии исключены.", + "FailedToRemoveVersions": "Не удалось удалить версии.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Только версии, которые не притягивают или отсканируют, могут быть удалены.", + "RemoveVersions": "Удалить версии", + "Size": "Размер", + "SuccessFullyRemoved": "Успешно удалено {{count}} версии.", + "Version": "Версия" + }, "comp:BAIImportArtifactModal": { - "Description": "Описание", - "Name": "Имя", + "ExcludedVersions": "{{count}} версии исключены.", + "FailedToPullVersions": "Не удалось вытащить версии.", + "OnlySCANNEDVersionsCanBePulled": "Только отсканированные версии можно вытащить.", "Pull": "Тянуть", - "PullArtifact": "Вытащить артефакт", - "PulledVersionsAreExcluded": "Вытянутые версии исключены.", - "Source": "Источник", - "Type": "Тип" + "PullVersion": "Потянуть версию", + "Size": "Размер", + "SuccessFullyPulled": "Успешно запрошенные тяги для {{count}} версий.", + "Version": "Версия" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Введите идентификатор модели. (например, OpenAI/GPT-OSS-20B)", + "EnterAVersion": "Введите версию. (по умолчанию: главное)", + "Failed to import model from hugging face": "Не удалось импортировать модель от обнимающего лица", + "Import": "Импорт", + "ModalDescription": "Импортируйте модель от обнимающего лица, указав идентификатор модели и версию.", + "ModalTitle": "Импорт от обнимающегося лица", + "ModelID": "Идентификатор модели", + "SuccessfullyImportedModelFromHuggingFace": "Успешно запросил импорт модели от обнимающегося лица", + "Version": "Версия" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Поиск", "ResetFilter": "Сбросить фильтры" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Отменить тяну", + "CancelingWillRestartThePulling": "Отмена возобновит тягу", + "FailedToCancelThePulling": "Не удалось отменить тягу.", + "VersionIsPullingNow": "{{version}} версия сейчас тянет.", + "VersionPullCanceledSuccessfully": "Pull of {{version}} версия отменена успешно.", + "WARNING": "ПРЕДУПРЕЖДЕНИЕ", + "YouAreAboutToCancelThisVersion": "Вы собираетесь отменить эту версию" + }, "comp:BAISessionAgentIds": { "Agent": "Агент" }, @@ -82,10 +121,15 @@ }, "general": { "NSelected": "{{count}} выбрал", + "TotalItems": "Total {{total}} элементы", + "button": { + "Cancel": "Отмена", + "Close": "Закрывать", "CopyAll": "Копировать все", "Create": "Создавать", "Delete": "Удалить", + "Remove": "Удалять", "Upload": "Загрузить" } } diff --git a/packages/backend.ai-ui/src/locale/th.json b/packages/backend.ai-ui/src/locale/th.json index 56516612a2..12eab5cab0 100644 --- a/packages/backend.ai-ui/src/locale/th.json +++ b/packages/backend.ai-ui/src/locale/th.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "คำอธิบาย", + "Name": "ชื่อ", + "Source": "แหล่งที่มา", + "Type": "พิมพ์" + }, "comp:BAIArtifactRevisionTable": { - "Action": "การกระทำ", + "Control": "ควบคุม", "LatestVersion": "เวอร์ชันล่าสุด", "Name": "ชื่อ", + "PullThisVersion": "ดึงเวอร์ชันนี้", + "RemoveThisVersion": "ลบเวอร์ชันนี้", "Size": "ขนาด", "Status": "สถานะ", "Updated": "อัปเดต", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "การกระทำ", "PullLatestVersion": "ดึงเวอร์ชันล่าสุด", + "Scanned": "สแกน", "Size": "ขนาด", "Updated": "อัปเดต", "Version": "รุ่น" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} ไม่รวมรุ่น", + "FailedToRemoveVersions": "ไม่สามารถลบเวอร์ชันได้", + "OnlyVersionsNotInPULLINGOrSCANNED": "เฉพาะเวอร์ชันที่ไม่ได้อยู่ในการดึงหรือสแกนเท่านั้น", + "RemoveVersions": "ลบเวอร์ชัน", + "Size": "ขนาด", + "SuccessFullyRemoved": "ลบเวอร์ชัน {{count}} สำเร็จ", + "Version": "รุ่น" + }, "comp:BAIImportArtifactModal": { - "Description": "คำอธิบาย", - "Name": "ชื่อ", + "ExcludedVersions": "{{count}} ไม่รวมรุ่น", + "FailedToPullVersions": "ไม่สามารถดึงเวอร์ชันได้", + "OnlySCANNEDVersionsCanBePulled": "สามารถดึงรุ่นสแกนได้เท่านั้น", "Pull": "ดึง", - "PullArtifact": "ดึงสิ่งประดิษฐ์", - "PulledVersionsAreExcluded": "ไม่รวมเวอร์ชันที่ดึงออกมา", - "Source": "แหล่งที่มา", - "Type": "พิมพ์" + "PullVersion": "Pull Version", + "Size": "ขนาด", + "SuccessFullyPulled": "ขอให้ดึงได้สำเร็จสำหรับรุ่น {{count}}", + "Version": "รุ่น" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "ป้อนรหัสรุ่น (เช่น OpenAI/GPT-OSS-20B)", + "EnterAVersion": "ป้อนเวอร์ชัน (ค่าเริ่มต้น: หลัก)", + "Failed to import model from hugging face": "ไม่สามารถนำเข้าโมเดลจากการกอดใบหน้า", + "Import": "นำเข้า", + "ModalDescription": "นำเข้าโมเดลจากการกอดใบหน้าโดยการระบุ ID รุ่นและเวอร์ชัน", + "ModalTitle": "นำเข้าจากการกอดใบหน้า", + "ModelID": "ID รุ่น", + "SuccessfullyImportedModelFromHuggingFace": "ร้องขอการนำเข้าโมเดลจากการกอดอย่างประสบความสำเร็จ", + "Version": "รุ่น" }, "comp:BAIPropertyFilter": { "PlaceHolder": "ค้นหา", "ResetFilter": "รีเซ็ตตัวกรอง" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "ยกเลิกการดึง", + "CancelingWillRestartThePulling": "การยกเลิกจะรีสตาร์ทการดึง", + "FailedToCancelThePulling": "ล้มเหลวในการยกเลิกการดึง", + "VersionIsPullingNow": "{{version}} เวอร์ชันกำลังดึงอยู่ในขณะนี้", + "VersionPullCanceledSuccessfully": "ดึง {{version}} ยกเลิกเวอร์ชันสำเร็จ", + "WARNING": "คำเตือน", + "YouAreAboutToCancelThisVersion": "คุณกำลังจะยกเลิกเวอร์ชันนี้" + }, "comp:BAISessionAgentIds": { "Agent": "ตัวแทน" }, @@ -82,10 +121,15 @@ }, "general": { "NSelected": "{{count}} เลือก", + "TotalItems": "รวม {{total}} รายการ", + "button": { + "Cancel": "ยกเลิก", + "Close": "ปิด", "CopyAll": "คัดลอกทั้งหมด", "Create": "สร้าง", "Delete": "ลบ", + "Remove": "ลบ", "Upload": "อัพโหลด" } } diff --git a/packages/backend.ai-ui/src/locale/tr.json b/packages/backend.ai-ui/src/locale/tr.json index 7c0b9edfeb..0f2ba660fc 100644 --- a/packages/backend.ai-ui/src/locale/tr.json +++ b/packages/backend.ai-ui/src/locale/tr.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Tanım", + "Name": "İsim", + "Source": "Kaynak", + "Type": "Tip" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Aksiyon", + "Control": "Kontrol", "LatestVersion": "En son sürüm", "Name": "İsim", + "PullThisVersion": "Bu sürümü çekin", + "RemoveThisVersion": "Bu sürümü kaldır", "Size": "Boyut", "Status": "Durum", "Updated": "Güncellenmiş", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Aksiyon", "PullLatestVersion": "En son sürümü çekin", + "Scanned": "Taranmış", "Size": "Boyut", "Updated": "Güncellenmiş", "Version": "Versiyon" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} sürümleri hariç tutulur.", + "FailedToRemoveVersions": "Sürümleri kaldırılamadı.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Yalnızca çekme veya taranmayan sürümler kaldırılabilir.", + "RemoveVersions": "Sürümleri Kaldır", + "Size": "Boyut", + "SuccessFullyRemoved": "{{count}} sürümlerini başarıyla kaldırdı.", + "Version": "Versiyon" + }, "comp:BAIImportArtifactModal": { - "Description": "Tanım", - "Name": "İsim", + "ExcludedVersions": "{{count}} sürümleri hariç tutulur.", + "FailedToPullVersions": "Sürümleri çekemedi.", + "OnlySCANNEDVersionsCanBePulled": "Yalnızca taranan sürümler çekilebilir.", "Pull": "Çekmek", - "PullArtifact": "Artefakt çekmek", - "PulledVersionsAreExcluded": "Çekilen sürümler hariç tutulur.", - "Source": "Kaynak", - "Type": "Tip" + "PullVersion": "Çekme sürümü", + "Size": "Boyut", + "SuccessFullyPulled": "{{count}} sürümleri için başarıyla talep edildi.", + "Version": "Versiyon" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Bir model kimliği girin. (örn. Openai/GPT-OSS-20B)", + "EnterAVersion": "Bir sürüm girin. (Varsayılan: Main)", + "Failed to import model from hugging face": "Modelin sarılma yüzünden ithal edilemedi", + "Import": "İçe aktarmak", + "ModalDescription": "Model kimliğini ve sürümünü belirterek bir modeli kucaklamadan içe aktarın.", + "ModalTitle": "Sarılma Yüzünden İthalat", + "ModelID": "Model kimliği", + "SuccessfullyImportedModelFromHuggingFace": "Sarılma yüzünden başarılı bir şekilde model ithalatını istedi", + "Version": "Versiyon" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Arama", "ResetFilter": "Filtreleri sıfırla" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Çekmeyi iptal et", + "CancelingWillRestartThePulling": "İptal etme, çekmeyi yeniden başlatacak", + "FailedToCancelThePulling": "Çekmeyi iptal edemedi.", + "VersionIsPullingNow": "{{sürümversion} sürüm şimdi çekiliyor.", + "VersionPullCanceledSuccessfully": "{{version}} sürümünün çekilmesi başarıyla iptal edildi.", + "WARNING": "UYARI", + "YouAreAboutToCancelThisVersion": "Bu sürümü iptal etmek üzeresiniz" + }, "comp:BAISessionAgentIds": { "Agent": "Ajan" }, @@ -77,10 +116,15 @@ }, "general": { "NSelected": "{{count}} seçildi", + "TotalItems": "Total {{total}} öğeleri", + "button": { + "Cancel": "İptal etmek", + "Close": "Kapalı", "CopyAll": "Hepsini kopyala", "Create": "Yaratmak", "Delete": "Silmek", + "Remove": "Kaldırmak", "Upload": "Yüklemek" } } diff --git a/packages/backend.ai-ui/src/locale/vi.json b/packages/backend.ai-ui/src/locale/vi.json index c17ac96898..90c01b0504 100644 --- a/packages/backend.ai-ui/src/locale/vi.json +++ b/packages/backend.ai-ui/src/locale/vi.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "Sự miêu tả", + "Name": "Tên", + "Source": "Nguồn", + "Type": "Kiểu" + }, "comp:BAIArtifactRevisionTable": { - "Action": "Hoạt động", + "Control": "Điều khiển", "LatestVersion": "Phiên bản mới nhất", "Name": "Tên", + "PullThisVersion": "Kéo phiên bản này", + "RemoveThisVersion": "Xóa phiên bản này", "Size": "Kích cỡ", "Status": "Trạng thái", "Updated": "Cập nhật", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "Hoạt động", "PullLatestVersion": "Kéo phiên bản mới nhất", + "Scanned": "Quét", "Size": "Kích cỡ", "Updated": "Cập nhật", "Version": "Phiên bản" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}} Các phiên bản được loại trừ.", + "FailedToRemoveVersions": "Không thể loại bỏ các phiên bản.", + "OnlyVersionsNotInPULLINGOrSCANNED": "Chỉ các phiên bản không kéo hoặc quét mới có thể được loại bỏ.", + "RemoveVersions": "Xóa các phiên bản", + "Size": "Kích cỡ", + "SuccessFullyRemoved": "Đã loại bỏ thành công các phiên bản {{count}}.", + "Version": "Phiên bản" + }, "comp:BAIImportArtifactModal": { - "Description": "Sự miêu tả", - "Name": "Tên", + "ExcludedVersions": "{{count}} Các phiên bản được loại trừ.", + "FailedToPullVersions": "Không thể kéo phiên bản.", + "OnlySCANNEDVersionsCanBePulled": "Chỉ các phiên bản được quét mới có thể được kéo.", "Pull": "Sự lôi kéo", - "PullArtifact": "Kéo tạo tác", - "PulledVersionsAreExcluded": "Các phiên bản kéo được loại trừ.", - "Source": "Nguồn", - "Type": "Kiểu" + "PullVersion": "Phiên bản kéo", + "Size": "Kích cỡ", + "SuccessFullyPulled": "Yêu cầu kéo thành công cho các phiên bản {{count}}.", + "Version": "Phiên bản" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "Nhập ID mô hình. (ví dụ: OpenAI/GPT-OSS-20B)", + "EnterAVersion": "Nhập một phiên bản. (Mặc định: Chính)", + "Failed to import model from hugging face": "Không thể nhập mô hình từ khuôn mặt ôm", + "Import": "Nhập khẩu", + "ModalDescription": "Nhập một mô hình từ Hugging Face bằng cách chỉ định ID mô hình và phiên bản.", + "ModalTitle": "Nhập khẩu từ khuôn mặt ôm", + "ModelID": "Mô hình ID", + "SuccessfullyImportedModelFromHuggingFace": "Yêu cầu nhập khẩu thành công mô hình từ khuôn mặt ôm", + "Version": "Phiên bản" }, "comp:BAIPropertyFilter": { "PlaceHolder": "Tìm kiếm", "ResetFilter": "Đặt lại bộ lọc" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "Hủy kéo", + "CancelingWillRestartThePulling": "Hủy sẽ khởi động lại việc kéo", + "FailedToCancelThePulling": "Không thể hủy bỏ kéo.", + "VersionIsPullingNow": "{{version}} phiên bản hiện đang kéo.", + "VersionPullCanceledSuccessfully": "Kéo phiên bản {{version}} bị hủy thành công.", + "WARNING": "CẢNH BÁO", + "YouAreAboutToCancelThisVersion": "Bạn sắp hủy phiên bản này" + }, "comp:BAISessionAgentIds": { "Agent": "Đại lý" }, @@ -82,10 +121,14 @@ }, "general": { "NSelected": "{{count}} Đã chọn", + "TotalItems": "Tổng số {{total}} các mục", "button": { + "Cancel": "Hủy bỏ", + "Close": "Đóng", "CopyAll": "Sao chép tất cả", "Create": "Tạo nên", "Delete": "Xóa bỏ", + "Remove": "Di dời", "Upload": "Tải lên" } } diff --git a/packages/backend.ai-ui/src/locale/zh-CN.json b/packages/backend.ai-ui/src/locale/zh-CN.json index 2de42f16db..e9d79485c4 100644 --- a/packages/backend.ai-ui/src/locale/zh-CN.json +++ b/packages/backend.ai-ui/src/locale/zh-CN.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "描述", + "Name": "姓名", + "Source": "来源", + "Type": "类型" + }, "comp:BAIArtifactRevisionTable": { - "Action": "行动", + "Control": "控制", "LatestVersion": "最新版本", "Name": "姓名", + "PullThisVersion": "拉这个版本", + "RemoveThisVersion": "删除此版本", "Size": "尺寸", "Status": "地位", "Updated": "更新", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "行动", "PullLatestVersion": "拉最新版本", + "Scanned": "扫描", "Size": "尺寸", "Updated": "更新", "Version": "版本" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}}版本被排除在外。", + "FailedToRemoveVersions": "无法删除版本。", + "OnlyVersionsNotInPULLINGOrSCANNED": "只能删除不进行拉或扫描的版本。", + "RemoveVersions": "删除版本", + "Size": "尺寸", + "SuccessFullyRemoved": "成功删除了{{count}}版本。", + "Version": "版本" + }, "comp:BAIImportArtifactModal": { - "Description": "描述", - "Name": "姓名", + "ExcludedVersions": "{{count}}版本被排除在外。", + "FailedToPullVersions": "未能拉动版本。", + "OnlySCANNEDVersionsCanBePulled": "只能拉出扫描版本。", "Pull": "拉", - "PullArtifact": "拉工子", - "PulledVersionsAreExcluded": "拉动版本被排除在外。", - "Source": "来源", - "Type": "类型" + "PullVersion": "拉版本", + "Size": "尺寸", + "SuccessFullyPulled": "成功请求{{count}}版本的拉动。", + "Version": "版本" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "输入模型ID。 (例如OpenAI/GPT-OSS-20B)", + "EnterAVersion": "输入版本。(默认:main)", + "Failed to import model from hugging face": "无法从拥抱面孔中导入模型", + "Import": "进口", + "ModalDescription": "通过指定模型ID和版本来从拥抱面中导入模型。", + "ModalTitle": "从拥抱脸上进口", + "ModelID": "模型ID", + "SuccessfullyImportedModelFromHuggingFace": "成功要求从拥抱脸部进口模型", + "Version": "版本" }, "comp:BAIPropertyFilter": { "PlaceHolder": "搜索", "ResetFilter": "重置过滤器" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "取消拉力", + "CancelingWillRestartThePulling": "取消将重新启动拉动", + "FailedToCancelThePulling": "未能取消拉力。", + "VersionIsPullingNow": "{{version}}版本现在正在拉动。", + "VersionPullCanceledSuccessfully": "{{version}}版本的拉力成功取消了。", + "WARNING": "警告", + "YouAreAboutToCancelThisVersion": "您即将取消此版本" + }, "comp:BAISessionAgentIds": { "Agent": "代理人" }, @@ -82,10 +121,15 @@ }, "general": { "NSelected": "{{count}}选择", + "TotalItems": "总计{{total}}项目", + "button": { + "Cancel": "取消", + "Close": "关闭", "CopyAll": "复制全部", "Create": "创造", "Delete": "删除", + "Remove": "消除", "Upload": "上传" } } diff --git a/packages/backend.ai-ui/src/locale/zh-TW.json b/packages/backend.ai-ui/src/locale/zh-TW.json index 72dfdeaf3f..6dbdd0f52f 100644 --- a/packages/backend.ai-ui/src/locale/zh-TW.json +++ b/packages/backend.ai-ui/src/locale/zh-TW.json @@ -1,9 +1,17 @@ { "$schema": "../../i18n.schema.json", + "comp:BAIArtifactDescriptions": { + "Description": "描述", + "Name": "姓名", + "Source": "來源", + "Type": "類型" + }, "comp:BAIArtifactRevisionTable": { - "Action": "行動", + "Control": "控制", "LatestVersion": "最新版本", "Name": "姓名", + "PullThisVersion": "拉這個版本", + "RemoveThisVersion": "刪除此版本", "Size": "尺寸", "Status": "地位", "Updated": "更新", @@ -12,23 +20,54 @@ "comp:BAIArtifactTable": { "Action": "行動", "PullLatestVersion": "拉最新版本", + "Scanned": "掃描", "Size": "尺寸", "Updated": "更新", "Version": "版本" }, + "comp:BAIDeleteArtifactModal": { + "ExcludedVersions": "{{count}}版本被排除在外。", + "FailedToRemoveVersions": "無法刪除版本。", + "OnlyVersionsNotInPULLINGOrSCANNED": "只能刪除不進行拉或掃描的版本。", + "RemoveVersions": "刪除版本", + "Size": "尺寸", + "SuccessFullyRemoved": "成功刪除了{{count}}版本。", + "Version": "版本" + }, "comp:BAIImportArtifactModal": { - "Description": "描述", - "Name": "姓名", + "ExcludedVersions": "{{count}}版本被排除在外。", + "FailedToPullVersions": "未能拉動版本。", + "OnlySCANNEDVersionsCanBePulled": "只能拉出掃描版本。", "Pull": "拉", - "PullArtifact": "拉工子", - "PulledVersionsAreExcluded": "拉動版本被排除在外。", - "Source": "來源", - "Type": "類型" + "PullVersion": "拉版本", + "Size": "尺寸", + "SuccessFullyPulled": "成功請求{{count}}版本的拉動。", + "Version": "版本" + }, + "comp:BAIImportFromHuggingFaceModal": { + "EnterAModelID": "輸入模型ID。 (例如OpenAI/GPT-OSS-20B)", + "EnterAVersion": "輸入版本。(默認:main)", + "Failed to import model from hugging face": "無法從擁抱面孔中導入模型", + "Import": "進口", + "ModalDescription": "通過指定模型ID和版本來從擁抱面中導入模型。", + "ModalTitle": "從擁抱臉上進口", + "ModelID": "模型ID", + "SuccessfullyImportedModelFromHuggingFace": "成功要求從擁抱臉部進口模型", + "Version": "版本" }, "comp:BAIPropertyFilter": { "PlaceHolder": "搜索", "ResetFilter": "重置過濾器" }, + "comp:BAIPullingArtifactRevisionAlert": { + "CancelPull": "取消拉力", + "CancelingWillRestartThePulling": "取消將重新啟動拉動", + "FailedToCancelThePulling": "未能取消拉力。", + "VersionIsPullingNow": "{{version}}版本現在正在拉動。", + "VersionPullCanceledSuccessfully": "{{version}}版本的拉力成功取消了。", + "WARNING": "警告", + "YouAreAboutToCancelThisVersion": "您即將取消此版本" + }, "comp:BAISessionAgentIds": { "Agent": "代理人" }, @@ -82,10 +121,14 @@ }, "general": { "NSelected": "{{count}}選擇", + "TotalItems": "總計{{total}}項目", "button": { + "Cancel": "取消", + "Close": "關閉", "CopyAll": "複製全部", "Create": "創造", "Delete": "刪除", + "Remove": "消除", "Upload": "上傳" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4473d1b0f3..a91d7439a4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -482,6 +482,9 @@ importers: dayjs: specifier: ^1.11.13 version: 1.11.13 + graphql: + specifier: ^16.10.0 + version: 16.10.0 i18next: specifier: ^24.2.3 version: 24.2.3(typescript@5.8.2) @@ -570,6 +573,9 @@ importers: '@types/react-resizable': specifier: ^3.0.8 version: 3.0.8 + '@types/relay-runtime': + specifier: ^19.0.2 + version: 19.0.2 '@types/relay-test-utils': specifier: ^19.0.0 version: 19.0.0 @@ -594,9 +600,6 @@ importers: fast-glob: specifier: ^3.3.3 version: 3.3.3 - graphql: - specifier: ^16.10.0 - version: 16.10.0 jest: specifier: ^29.7.0 version: 29.7.0(@types/node@22.4.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.4.1)(typescript@5.8.2)) diff --git a/react/src/App.tsx b/react/src/App.tsx index dbb34127b6..da21d1b185 100644 --- a/react/src/App.tsx +++ b/react/src/App.tsx @@ -470,7 +470,8 @@ const router = createBrowserRouter([ { path: '', Component: () => { - return ( + const baiClient = useSuspendedBackendaiClient(); + return baiClient?.supports('reservoir') ? ( + ) : ( + ); }, }, { path: '/reservoir/:artifactId', - element: ( - - }> - - - - ), - handle: { labelKey: 'Artifact Details' }, + Component: () => { + const baiClient = useSuspendedBackendaiClient(); + return baiClient?.supports('reservoir') ? ( + + }> + + + + ) : ( + + ); + }, + handle: { labelKey: 'webui.menu.ArtifactDetails' }, }, ], }, diff --git a/react/src/components/MainLayout/WebUISider.tsx b/react/src/components/MainLayout/WebUISider.tsx index 4b88ec6301..f66c0f87c6 100644 --- a/react/src/components/MainLayout/WebUISider.tsx +++ b/react/src/components/MainLayout/WebUISider.tsx @@ -54,6 +54,7 @@ import { ExternalLinkIcon, LinkIcon, ClipboardClock, + PackagePlus, } from 'lucide-react'; import React, { ReactNode, useContext, useRef } from 'react'; import { useTranslation } from 'react-i18next'; @@ -286,9 +287,9 @@ const WebUISider: React.FC = (props) => { icon: , key: 'resource-policy', }, - { + baiClient?.supports('reservoir') && { label: {t('webui.menu.Reservoir')}, - icon: , + icon: , key: 'reservoir', }, ]); diff --git a/react/src/components/ReservoirArtifactList.tsx b/react/src/components/ReservoirArtifactList.tsx deleted file mode 100644 index 029070ee62..0000000000 --- a/react/src/components/ReservoirArtifactList.tsx +++ /dev/null @@ -1,429 +0,0 @@ -// import BAILink from './BAILink'; -// import BAITag from './BAITag'; -// import BAIText from './BAIText'; -// import { -// Button, -// TableColumnsType, -// Tag, -// theme, -// Tooltip, -// Typography, -// } from 'antd'; -// import { -// BAIFlex, -// BAITable, -// BAITableProps, -// convertToDecimalUnit, -// filterOutEmpty, -// } from 'backend.ai-ui'; -// import dayjs from 'dayjs'; -// import relativeTime from 'dayjs/plugin/relativeTime'; -// import _ from 'lodash'; -// import { Download } from 'lucide-react'; -// import React from 'react'; -// import { useTranslation } from 'react-i18next'; -// import { graphql, useFragment } from 'react-relay'; -// import { useNavigate } from 'react-router-dom'; -// import { -// ReservoirArtifactList_artifactGroups$data, -// ReservoirArtifactList_artifactGroups$key, -// } from 'src/__generated__/ReservoirArtifactList_artifactGroups.graphql'; -// import { -// getStatusColor, -// getStatusIcon, -// getTypeIcon, -// } from 'src/utils/reservoir'; - -// dayjs.extend(relativeTime); - -// export type ArtifactGroups = NonNullable< -// ReservoirArtifactList_artifactGroups$data[number] -// >; - -// interface ReservoirArtifactListProps -// extends Omit, 'dataSource' | 'columns'> { -// type: 'all' | 'installed' | 'available'; -// artifactGroupsFrgmt: ReservoirArtifactList_artifactGroups$key; -// onClickPull: (artifactId: string) => void; -// } - -// const ReservoirArtifactList: React.FC = ({ -// artifactGroupsFrgmt, -// onClickPull, -// ...tableProps -// }) => { -// const { token } = theme.useToken(); -// const navigate = useNavigate(); -// const { t } = useTranslation(); - -// const artifactGroups = useFragment( -// graphql` -// fragment ReservoirArtifactList_artifactGroups on ArtifactGroup -// @relay(plural: true) { -// id -// name -// type -// description -// status -// lastUpdated: artifacts( -// first: 1 -// orderBy: [{ field: UPDATED_AT, direction: DESC }] -// ) { -// edges { -// node { -// updatedAt -// } -// } -// } -// latestVersion: artifacts( -// first: 1 -// orderBy: [{ field: LATEST_VERSION, direction: DESC }] -// ) { -// edges { -// node { -// id -// version -// updatedAt -// size -// } -// } -// } -// } -// `, -// artifactGroupsFrgmt, -// ); - -// const columns: TableColumnsType = [ -// { -// title: t('reservoirPage.Name'), -// dataIndex: 'name', -// key: 'name', -// render: (name: string, record: ArtifactGroups) => ( -// -// -// {name} -// -// {getTypeIcon(record.type, 14)} {record.type.toUpperCase()} -// -// -// {record.description && ( -// -// {record.description} -// -// )} -// -// ), -// }, -// { -// title: t('reservoirPage.Status'), -// dataIndex: 'status', -// key: 'status', -// render: (status: string, record: ArtifactGroups) => ( -// -// -// {status.toUpperCase()} -// -// {status === 'AVAILABLE' && ( -// -// } style={{ marginBottom: token.marginMD }} @@ -233,14 +250,14 @@ const ReservoirArtifactDetailPage = () => { {artifact?.name} - - {getTypeIcon(artifact?.type ?? '')}  - {artifact?.type.toUpperCase()} - + {artifact && } - {/* {convertToDecimalUnit(latestArtifact?.size, 'auto')?.displayValue} */} + {latestArtifact?.size + ? convertToDecimalUnit(latestArtifact.size, 'auto') + ?.displayValue + : 'N/A'} @@ -269,9 +286,11 @@ const ReservoirArtifactDetailPage = () => { : 'N/A'} - - {artifact?.description || 'No description available'} - + {artifact?.description ? ( + {artifact.description} + ) : ( + 'N/A' + )} @@ -295,8 +314,8 @@ const ReservoirArtifactDetailPage = () => { }} filterProperties={[ { - fixedOperator: 'eq', - propertyLabel: 'Status', + fixedOperator: 'equals', + propertyLabel: t('reservoirPage.Status'), key: 'status', type: 'enum', options: [ @@ -336,12 +355,12 @@ const ReservoirArtifactDetailPage = () => { }, { fixedOperator: 'contains', - propertyLabel: 'Version', + propertyLabel: t('reservoirPage.Version'), key: 'version', type: 'string', }, { - propertyLabel: 'Artifact ID', + propertyLabel: t('reservoirPage.ArtifactID'), key: 'artifactId', valueMode: 'scalar', type: 'string', @@ -351,23 +370,31 @@ const ReservoirArtifactDetailPage = () => { {selectedRevisionIdList.length > 0 ? ( {selectedRevisionIdList.length} selected - -
); diff --git a/react/src/pages/ReservoirPage.tsx b/react/src/pages/ReservoirPage.tsx index a0f9e5f4e0..624c359c37 100644 --- a/react/src/pages/ReservoirPage.tsx +++ b/react/src/pages/ReservoirPage.tsx @@ -1,19 +1,22 @@ import { INITIAL_FETCH_KEY, useUpdatableState } from '../hooks'; import { useBAIPaginationOptionStateOnSearchParam } from '../hooks/reactPaginationQueryOptions'; import { useDeferredQueryParams } from '../hooks/useDeferredQueryParams'; -import { theme, Col, Row, Statistic, Card } from 'antd'; +import { useToggle } from 'ahooks'; +import { theme, Col, Row, Statistic, Card, Button } from 'antd'; import { BAICard, BAIFlex, BAIArtifactTable, BAIImportArtifactModal, BAIGraphQLPropertyFilter, + BAIImportFromHuggingFaceModal, + BAIHuggingFaceIcon, toLocalId, - BAIImportArtifactModalArtifactRevisionFragmentKey, BAIImportArtifactModalArtifactFragmentKey, + BAIImportArtifactModalArtifactRevisionFragmentKey, } from 'backend.ai-ui'; import _ from 'lodash'; -import { Package, Brain, Container } from 'lucide-react'; +import { Brain } from 'lucide-react'; import React, { useMemo, useDeferredValue, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { graphql, useLazyLoadQuery } from 'react-relay'; @@ -34,6 +37,8 @@ const ReservoirPage: React.FC = () => { useState(null); const [selectedRevision, setSelectedRevision] = useState([]); + const [openHuggingFaceModal, { toggle: toggleOpenHuggingFaceModal }] = + useToggle(); const { baiPaginationOption, @@ -48,15 +53,13 @@ const ReservoirPage: React.FC = () => { filter: withDefault(JsonParam, {}), }); - // const queryVariables: ReservoirPageQuery$variables = useMemo(() => ({})); - const queryVariables: ReservoirPageQuery$variables = useMemo( () => ({ offset: baiPaginationOption.offset, limit: baiPaginationOption.limit, order: [ { - field: 'NAME', + field: 'UPDATED_AT', direction: 'DESC', }, ], @@ -90,6 +93,10 @@ const ReservoirPage: React.FC = () => { $offset: Int! $filter: ArtifactFilter! ) { + defaultArtifactRegistry(artifactType: MODEL) { + name + type + } artifacts( orderBy: $order limit: $limit @@ -129,15 +136,17 @@ const ReservoirPage: React.FC = () => { }, ); - const { artifacts } = queryRef; + const { artifacts, defaultArtifactRegistry } = queryRef; + const isAvailableUsingHuggingFace = + defaultArtifactRegistry?.type === 'HUGGINGFACE'; - const typeFilterGenerator = (type: 'IMAGE' | 'PACKAGE' | 'MODEL') => { - return { type: { eq: type } }; - }; - - const handleStatisticCardClick = (type: 'IMAGE' | 'PACKAGE' | 'MODEL') => { - setQuery({ filter: typeFilterGenerator(type) }, 'replaceIn'); - }; + // TODO: implement when reservoir supports other types + // const typeFilterGenerator = (type: 'IMAGE' | 'PACKAGE' | 'MODEL') => { + // return { type: { eq: type } }; + // }; + // const handleStatisticCardClick = (type: 'IMAGE' | 'PACKAGE' | 'MODEL') => { + // setQuery({ filter: typeFilterGenerator(type) }, 'replaceIn'); + // }; return ( @@ -147,93 +156,17 @@ const ReservoirPage: React.FC = () => { size="small" variant="borderless" hoverable - onClick={() => handleStatisticCardClick('MODEL')} style={{ cursor: 'pointer', - border: - queryParams.filter === typeFilterGenerator('MODEL') - ? `1px solid ${token.colorPrimary}` - : `1px solid ${token.colorBorder}`, - backgroundColor: - queryParams.filter === typeFilterGenerator('MODEL') - ? token.colorPrimaryBg - : undefined, - transition: 'all 0.2s ease', + border: `1px solid ${token.colorPrimary}`, }} > } valueStyle={{ - color: - queryParams.filter === typeFilterGenerator('MODEL') - ? token.colorPrimary - : undefined, - }} - /> - - - - handleStatisticCardClick('IMAGE')} - style={{ - cursor: 'pointer', - border: - queryParams.filter === typeFilterGenerator('IMAGE') - ? `1px solid ${token.colorPrimary}` - : `1px solid ${token.colorBorder}`, - backgroundColor: - queryParams.filter === typeFilterGenerator('IMAGE') - ? token.colorPrimaryBg - : undefined, - transition: 'all 0.2s ease', - }} - > - } - valueStyle={{ - color: - queryParams.filter === typeFilterGenerator('IMAGE') - ? token.colorPrimary - : undefined, - }} - /> - - - - handleStatisticCardClick('PACKAGE')} - style={{ - cursor: 'pointer', - border: - queryParams.filter === typeFilterGenerator('PACKAGE') - ? `1px solid ${token.colorPrimary}` - : `1px solid ${token.colorBorder}`, - backgroundColor: - queryParams.filter === typeFilterGenerator('PACKAGE') - ? token.colorPrimaryBg - : undefined, - transition: 'all 0.2s ease', - }} - > - } - valueStyle={{ - color: - queryParams.filter === typeFilterGenerator('PACKAGE') - ? token.colorPrimary - : undefined, + color: token.colorPrimary, }} /> @@ -271,64 +204,60 @@ const ReservoirPage: React.FC = () => { }} value={queryParams.filter} filterProperties={[ - { - fixedOperator: 'eq', - key: 'type', - propertyLabel: 'Type', - type: 'enum', - options: [ - { - label: 'Model', - value: 'MODEL', - }, - { - label: 'Package', - value: 'PACKAGE', - }, - { - label: 'Image', - value: 'IMAGE', - }, - ], - }, { fixedOperator: 'contains', key: 'name', - propertyLabel: 'Name', + propertyLabel: t('reservoirPage.Name'), type: 'string', }, { - fixedOperator: 'eq', + fixedOperator: 'contains', key: 'source', - propertyLabel: 'Source', + propertyLabel: t('reservoirPage.Source'), type: 'string', }, { - fixedOperator: 'eq', + fixedOperator: 'contains', key: 'registry', - propertyLabel: 'Registry', + propertyLabel: t('reservoirPage.Registry'), type: 'string', }, ]} /> - { - updateFetchKey(); - // rescanArtifacts({ - // variables: { - // input: { - // storageId: 'fe878f09-06cc-4b91-9242-4c71015cce07', - // registryId: 'fe878f09-06cc-4b91-9242-4c71015cce05', - // limit: 100, - // }, - // }, - // }); - }} - /> + + { + updateFetchKey(); + // rescanArtifacts({ + // variables: { + // input: { + // registryId: 'fe878f09-06cc-4b91-9242-4c71015cce05', + // limit: 100, + // }, + // }, + // }); + }} + /> + {isAvailableUsingHuggingFace && ( + + )} +
edge.node)} @@ -357,16 +286,6 @@ const ReservoirPage: React.FC = () => { } }, }} - onRow={(record) => ({ - onClick: (event) => { - event.stopPropagation(); - const target = event.target as HTMLElement; - if (target.closest('button') || target.closest('a')) { - return; - } - navigate(`/reservoir/${toLocalId(record.id)}`); - }, - })} /> {/* TODO: implement audit log for reservoir page */} @@ -415,6 +334,14 @@ const ReservoirPage: React.FC = () => { setSelectedRevision([]); }} /> + { + toggleOpenHuggingFaceModal(); + navigate(`/reservoir/${toLocalId(artifactId)}`); + }} + onCancel={toggleOpenHuggingFaceModal} + /> ); }; diff --git a/react/src/utils/reservoir.tsx b/react/src/utils/reservoir.tsx deleted file mode 100644 index b15d7a56eb..0000000000 --- a/react/src/utils/reservoir.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { SyncOutlined } from '@ant-design/icons'; -import { Package, Container, Brain } from 'lucide-react'; - -export const getStatusColor = (status: string) => { - switch (status.toLowerCase()) { - case 'pulling': - return 'processing'; - case 'verifying': - return 'warning'; - case 'available': - return 'default'; - case 'failed': - return 'error'; - default: - return 'default'; - } -}; - -export const getStatusIcon = (status: string) => { - switch (status.toLowerCase()) { - case 'pulling': - case 'verifying': - return ; - default: - return null; - } -}; - -export const getTypeColor = (type: string) => { - switch (type) { - case 'model': - return 'blue'; - case 'package': - return 'green'; - case 'image': - return 'orange'; - default: - return 'default'; - } -}; - -export const getTypeIcon = (type: string, size: number = 16) => { - const colorMap = { - model: '#1677ff', - package: '#52c41a', - image: '#fa8c16', - }; - - switch (type.toLowerCase()) { - case 'model': - return ; - case 'package': - return ; - case 'image': - return ; - default: - return null; - } -}; diff --git a/resources/i18n/de.json b/resources/i18n/de.json index d3bb76c1dd..892a260829 100644 --- a/resources/i18n/de.json +++ b/resources/i18n/de.json @@ -1093,15 +1093,22 @@ "UsernameOptional": "Benutzername (optional)" }, "reservoirPage": { + "ArtifactID": "Artefakt -ID", "BasicInformation": "Grundinformationen", "Description": "Beschreibung", + "FromHuggingFace": "Vom umarmen Gesicht", "LastUpdated": "Zuletzt aktualisiert", "Name": "Name", + "PullLatestVersion": "Pull lasting ({{version}}) Version", + "PullSelectedVersions": "Ziehen Sie ausgewählte Versionen", "Registry": "Registrierung", + "RemoveSelectedVersions": "Entfernen Sie ausgewählte Versionen", "ReservoirArtifacts": "Reservoir -Artefakte", "Size": "Größe", "Source": "Quelle", + "Status": "Status", "Type": "Typ", + "Version": "Version", "VersionList": "Verfügbare Liste" }, "resourceGroup": { @@ -1978,6 +1985,7 @@ "Administration": "Verwaltung", "AgentSummary": "Agent Zusammenfassung", "Architecture": "Architektur", + "ArtifactDetails": "Artefaktdetails", "Cancel": "Stornieren", "ChangePassword": "Kennwort ändern", "Chat": "Chat", diff --git a/resources/i18n/el.json b/resources/i18n/el.json index 49b36b3b44..5ac6794bda 100644 --- a/resources/i18n/el.json +++ b/resources/i18n/el.json @@ -1090,15 +1090,22 @@ "UsernameOptional": "Όνομα χρήστη (προαιρετικό)" }, "reservoirPage": { + "ArtifactID": "Αναγνωριστικό τεχνούργου", "BasicInformation": "Βασικές πληροφορίες", "Description": "Περιγραφή", + "FromHuggingFace": "Από το αγκάλιασμα", "LastUpdated": "Τελευταία ενημερωμένη", "Name": "Ονομα", + "PullLatestVersion": "Τραβήξτε το τελευταίο ({{version}}) έκδοση", + "PullSelectedVersions": "Τραβήξτε επιλεγμένες εκδόσεις", "Registry": "Αρχείο", + "RemoveSelectedVersions": "Αφαιρέστε τις επιλεγμένες εκδόσεις", "ReservoirArtifacts": "Αντικείμενα δεξαμενής", "Size": "Μέγεθος", "Source": "Πηγή", + "Status": "Κατάσταση", "Type": "Τύπος", + "Version": "Εκδοχή", "VersionList": "Διαθέσιμη λίστα" }, "resourceGroup": { @@ -1976,6 +1983,7 @@ "Administration": "Διαχείριση", "AgentSummary": "Περίληψη πράκτορα", "Architecture": "Αρχιτεκτονική", + "ArtifactDetails": "Λεπτομέρειες τεχνητού", "Cancel": "Ματαίωση", "ChangePassword": "Άλλαξε κωδικό", "Chat": "Συνομιλία", diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 48b6a130d6..9a8023c325 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -1098,15 +1098,22 @@ "UsernameOptional": "Username (Optional)" }, "reservoirPage": { + "ArtifactID": "Artifact ID", "BasicInformation": "Basic Information", "Description": "Description", + "FromHuggingFace": "From Hugging Face", "LastUpdated": "Last Updated", "Name": "Name", + "PullLatestVersion": "Pull Latest({{version}}) version", + "PullSelectedVersions": "Pull Selected Versions", "Registry": "Registry", + "RemoveSelectedVersions": "Remove Selected Versions", "ReservoirArtifacts": "Reservoir Artifacts", "Size": "Size", "Source": "Source", + "Status": "Status", "Type": "Type", + "Version": "Version", "VersionList": "Available List" }, "resourceGroup": { @@ -1987,6 +1994,7 @@ "Administration": "Administration", "AgentSummary": "Agent Summary", "Architecture": "Architecture", + "ArtifactDetails": "Artifact Details", "Cancel": "Cancel", "ChangePassword": "Change Password", "Chat": "Chat", diff --git a/resources/i18n/es.json b/resources/i18n/es.json index 3371eaf495..c06ac26143 100644 --- a/resources/i18n/es.json +++ b/resources/i18n/es.json @@ -1093,15 +1093,22 @@ "UsernameOptional": "Nombre de usuario (opcional)" }, "reservoirPage": { + "ArtifactID": "ID de artefacto", "BasicInformation": "Información básica", "Description": "Descripción", + "FromHuggingFace": "De la cara abrazada", "LastUpdated": "Última actualización", "Name": "Nombre", + "PullLatestVersion": "Pull Last ({{version}}) versión", + "PullSelectedVersions": "Tire de versiones seleccionadas", "Registry": "Registro", + "RemoveSelectedVersions": "Eliminar versiones seleccionadas", "ReservoirArtifacts": "Artefactos de embalse", "Size": "Tamaño", "Source": "Fuente", + "Status": "Estado", "Type": "Tipo", + "Version": "Versión", "VersionList": "Lista disponible" }, "resourceGroup": { @@ -1980,6 +1987,7 @@ "Administration": "Administración", "AgentSummary": "Resumen del agente", "Architecture": "Arquitectura", + "ArtifactDetails": "Detalles de artefactos", "Cancel": "Cancelar", "ChangePassword": "Cambiar contraseña", "Chat": "Chat", diff --git a/resources/i18n/fi.json b/resources/i18n/fi.json index 1e469979a4..be2cfe1e83 100644 --- a/resources/i18n/fi.json +++ b/resources/i18n/fi.json @@ -1092,15 +1092,22 @@ "UsernameOptional": "Käyttäjätunnus (valinnainen)" }, "reservoirPage": { + "ArtifactID": "Artefaktitunnus", "BasicInformation": "Perustiedot", "Description": "Kuvaus", + "FromHuggingFace": "Halaamasta kasvoista", "LastUpdated": "Viimeksi päivitetty", "Name": "Nimi", + "PullLatestVersion": "Vedä uusin ({{version}}) versio", + "PullSelectedVersions": "Vedä valittuja versioita", "Registry": "Rekisteröinti", + "RemoveSelectedVersions": "Poista valitut versiot", "ReservoirArtifacts": "Säiliön esineitä", "Size": "Koko", "Source": "Lähde", + "Status": "Status", "Type": "Tyyppi", + "Version": "Versio", "VersionList": "Käytettävissä oleva luettelo" }, "resourceGroup": { @@ -1979,6 +1986,7 @@ "Administration": "Hallinto", "AgentSummary": "Agentin yhteenveto", "Architecture": "Arkkitehtuuri", + "ArtifactDetails": "Esineiden yksityiskohdat", "Cancel": "Peruuta", "ChangePassword": "Vaihda salasana", "Chat": "Chat", diff --git a/resources/i18n/fr.json b/resources/i18n/fr.json index 4af777670d..78b8152a5c 100644 --- a/resources/i18n/fr.json +++ b/resources/i18n/fr.json @@ -1093,15 +1093,22 @@ "UsernameOptional": "Nom d'utilisateur (facultatif)" }, "reservoirPage": { + "ArtifactID": "ID d'artefact", "BasicInformation": "Informations de base", "Description": "Description", + "FromHuggingFace": "De l'étreinte", "LastUpdated": "Dernière mise à jour", "Name": "Nom", + "PullLatestVersion": "Tirez la version ({{version}})", + "PullSelectedVersions": "Tirez les versions sélectionnées", "Registry": "Enregistrement", + "RemoveSelectedVersions": "Supprimer les versions sélectionnées", "ReservoirArtifacts": "Artefacts de réservoir", "Size": "Taille", "Source": "Source", + "Status": "Statut", "Type": "Taper", + "Version": "Version", "VersionList": "Liste disponible" }, "resourceGroup": { @@ -1980,6 +1987,7 @@ "Administration": "Administration", "AgentSummary": "Résumé de l'agent", "Architecture": "Architecture", + "ArtifactDetails": "Détails d'artefacts", "Cancel": "Annuler", "ChangePassword": "Changer le mot de passe", "Chat": "Chat", diff --git a/resources/i18n/id.json b/resources/i18n/id.json index eb7a035084..be3b2341ec 100644 --- a/resources/i18n/id.json +++ b/resources/i18n/id.json @@ -1091,15 +1091,22 @@ "UsernameOptional": "Nama Pengguna (Opsional)" }, "reservoirPage": { + "ArtifactID": "ID Artefak", "BasicInformation": "Informasi dasar", "Description": "Keterangan", + "FromHuggingFace": "Dari wajah memeluk", "LastUpdated": "Terakhir diperbarui", "Name": "Nama", + "PullLatestVersion": "Tarik versi terbaru ({{{version}})", + "PullSelectedVersions": "Tarik versi yang dipilih", "Registry": "Registri", + "RemoveSelectedVersions": "Hapus versi yang dipilih", "ReservoirArtifacts": "Artefak reservoir", "Size": "Ukuran", "Source": "Sumber", + "Status": "Status", "Type": "Jenis", + "Version": "Versi", "VersionList": "Daftar yang tersedia" }, "resourceGroup": { @@ -1979,6 +1986,7 @@ "Administration": "Administrasi", "AgentSummary": "Ringkasan Agen", "Architecture": "Arsitektur", + "ArtifactDetails": "Detail Artefak", "Cancel": "Batal", "ChangePassword": "Ganti kata sandi", "Chat": "Mengobrol", diff --git a/resources/i18n/it.json b/resources/i18n/it.json index 99a4884490..451074ca5e 100644 --- a/resources/i18n/it.json +++ b/resources/i18n/it.json @@ -1091,15 +1091,22 @@ "UsernameOptional": "Nome utente (facoltativo)" }, "reservoirPage": { + "ArtifactID": "ID artefatto", "BasicInformation": "Informazioni di base", "Description": "Descrizione", + "FromHuggingFace": "Dal viso abbracciato", "LastUpdated": "Ultimo aggiornamento", "Name": "Nome", + "PullLatestVersion": "Pull ultime ({{version}}) versione", + "PullSelectedVersions": "Estrarre versioni selezionate", "Registry": "Registro", + "RemoveSelectedVersions": "Rimuovere le versioni selezionate", "ReservoirArtifacts": "Artefatti del serbatoio", "Size": "Misurare", "Source": "Fonte", + "Status": "Stato", "Type": "Tipo", + "Version": "Versione", "VersionList": "Elenco disponibile" }, "resourceGroup": { @@ -1977,6 +1984,7 @@ "Administration": "Amministrazione", "AgentSummary": "Riepilogo dell'agente", "Architecture": "Architettura", + "ArtifactDetails": "Dettagli artefatto", "Cancel": "Annulla", "ChangePassword": "Cambia la password", "Chat": "Chat", diff --git a/resources/i18n/ja.json b/resources/i18n/ja.json index a190db2840..b00a00b7d1 100644 --- a/resources/i18n/ja.json +++ b/resources/i18n/ja.json @@ -1092,15 +1092,22 @@ "UsernameOptional": "ユーザー名(オプション)" }, "reservoirPage": { + "ArtifactID": "アーティファクトID", "BasicInformation": "基本情報", "Description": "説明", + "FromHuggingFace": "顔を抱き締めることから", "LastUpdated": "最後に更新されました", "Name": "名前", + "PullLatestVersion": "最新の({{version}})バージョンをプルします", + "PullSelectedVersions": "選択したバージョンをプルします", "Registry": "レジストリ", + "RemoveSelectedVersions": "選択したバージョンを削除します", "ReservoirArtifacts": "貯水池アーティファクト", "Size": "サイズ", "Source": "ソース", + "Status": "状態", "Type": "タイプ", + "Version": "バージョン", "VersionList": "利用可能なリスト" }, "resourceGroup": { @@ -1979,6 +1986,7 @@ "Administration": "管理", "AgentSummary": "リソース概要", "Architecture": "建築", + "ArtifactDetails": "アーティファクトの詳細", "Cancel": "キャンセル", "ChangePassword": "パスワードを変更する", "Chat": "チャット", diff --git a/resources/i18n/ko.json b/resources/i18n/ko.json index 1a10d82f05..e0a59ab13a 100644 --- a/resources/i18n/ko.json +++ b/resources/i18n/ko.json @@ -1097,15 +1097,22 @@ "UsernameOptional": "사용자 이름 (선택)" }, "reservoirPage": { + "ArtifactID": "아티팩트 ID", "BasicInformation": "기본 정보", "Description": "설명", + "FromHuggingFace": "허깅 페이스로부터", "LastUpdated": "마지막 업데이트", "Name": "이름", + "PullLatestVersion": "최신 ({{version}}) 버전을 가져옵니다", + "PullSelectedVersions": "선택한 버전 가져오기", "Registry": "레지스트리", + "RemoveSelectedVersions": "선택한 버전 제거하기", "ReservoirArtifacts": "리저버 아티팩트", "Size": "크기", "Source": "소스", + "Status": "상태", "Type": "유형", + "Version": "버전", "VersionList": "버전 목록" }, "resourceGroup": { @@ -1985,6 +1992,7 @@ "Administration": "관리", "AgentSummary": "자원 요약", "Architecture": "\b운영체제", + "ArtifactDetails": "아티팩트 상세", "Cancel": "취소", "ChangePassword": "비밀번호 변경", "Chat": "채팅", diff --git a/resources/i18n/mn.json b/resources/i18n/mn.json index 8df431c9de..7ad002945f 100644 --- a/resources/i18n/mn.json +++ b/resources/i18n/mn.json @@ -1091,15 +1091,22 @@ "UsernameOptional": "Хэрэглэгчийн нэр (заавал биш)" }, "reservoirPage": { + "ArtifactID": "Artifact ID", "BasicInformation": "Үндсэн мэдээлэл", "Description": "Тодорхойлолт / төрөл анги", + "FromHuggingFace": "Тэвэрч буй нүүрнээс", "LastUpdated": "Өнөөхээр нь онуулсан өдөр", "Name": "Нэр", + "PullLatestVersion": "СУРГАЛТЫН СУРГАЛТ ({{version}}) хувилбар", + "PullSelectedVersions": "Сонгосон хувилбарыг татаж аваарай", "Registry": "Шлах", + "RemoveSelectedVersions": "Сонгосон хувилбаруудыг устгана уу", "ReservoirArtifacts": "Усан сангийн олдворууд", "Size": "Хэмжээ", "Source": "Язгуур", + "Status": "Байдал", "Type": "Маяг", + "Version": "Таамаглал", "VersionList": "Боломжийн дугаар" }, "resourceGroup": { @@ -1977,6 +1984,7 @@ "Administration": "Админ", "AgentSummary": "Агентын хураангуй", "Architecture": "Уран барилгач", + "ArtifactDetails": "Олдворын дэлгэрэнгүй", "Cancel": "Цуцлах", "ChangePassword": "Нууц үгээ солих", "Chat": "Яриа хөрөө", diff --git a/resources/i18n/ms.json b/resources/i18n/ms.json index 1d07565682..c82ce29371 100644 --- a/resources/i18n/ms.json +++ b/resources/i18n/ms.json @@ -1092,15 +1092,22 @@ "UsernameOptional": "Nama Pengguna (Pilihan)" }, "reservoirPage": { + "ArtifactID": "ID Artifak", "BasicInformation": "Maklumat asas", "Description": "Penerangan", + "FromHuggingFace": "Dari memeluk muka", "LastUpdated": "Dikemas kini terakhir", "Name": "Nama", + "PullLatestVersion": "Tarik versi terkini ({{version}})", + "PullSelectedVersions": "Tarik versi yang dipilih", "Registry": "Pendaftaran", + "RemoveSelectedVersions": "Keluarkan versi yang dipilih", "ReservoirArtifacts": "Artifak Reservoir", "Size": "Saiz", "Source": "Sumber", + "Status": "Status", "Type": "Jenis", + "Version": "Versi", "VersionList": "Senarai yang ada" }, "resourceGroup": { @@ -1977,6 +1984,7 @@ "Administration": "Pentadbiran", "AgentSummary": "Ringkasan Agen", "Architecture": "Seni bina", + "ArtifactDetails": "Butiran artifak", "Cancel": "Batal", "ChangePassword": "Tukar kata laluan", "Chat": "Berbual", diff --git a/resources/i18n/pl.json b/resources/i18n/pl.json index 3b4bed71ba..24174bae7f 100644 --- a/resources/i18n/pl.json +++ b/resources/i18n/pl.json @@ -1092,15 +1092,22 @@ "UsernameOptional": "Nazwa użytkownika (opcjonalnie)" }, "reservoirPage": { + "ArtifactID": "Identyfikator artefaktu", "BasicInformation": "Podstawowe informacje", "Description": "Opis", + "FromHuggingFace": "Od przytulania twarzy", "LastUpdated": "Ostatnia aktualizacja", "Name": "Nazwa", + "PullLatestVersion": "Pull najnowszy ({{version}}) wersja", + "PullSelectedVersions": "Wyciągnij wybrane wersje", "Registry": "Rejestr", + "RemoveSelectedVersions": "Usuń wybrane wersje", "ReservoirArtifacts": "Artefakty zbiornikowe", "Size": "Rozmiar", "Source": "Źródło", + "Status": "Status", "Type": "Typ", + "Version": "Wersja", "VersionList": "Dostępna lista" }, "resourceGroup": { @@ -1979,6 +1986,7 @@ "Administration": "Administracja", "AgentSummary": "Podsumowanie agenta", "Architecture": "Architektura", + "ArtifactDetails": "Szczegóły artefaktu", "Cancel": "Anuluj", "ChangePassword": "Zmień hasło", "Chat": "Czat", diff --git a/resources/i18n/pt-BR.json b/resources/i18n/pt-BR.json index d97b5c82e2..ed705c39fa 100644 --- a/resources/i18n/pt-BR.json +++ b/resources/i18n/pt-BR.json @@ -1093,15 +1093,22 @@ "UsernameOptional": "Nome de usuário (opcional)" }, "reservoirPage": { + "ArtifactID": "Id de artefato", "BasicInformation": "Informações básicas", "Description": "Descrição", + "FromHuggingFace": "De abraçar o rosto", "LastUpdated": "Última atualização", "Name": "Nome", + "PullLatestVersion": "Puxe a versão mais recente ({{version}})", + "PullSelectedVersions": "Puxe versões selecionadas", "Registry": "Registro", + "RemoveSelectedVersions": "Remova versões selecionadas", "ReservoirArtifacts": "Artefatos de reservatório", "Size": "Tamanho", "Source": "Fonte", + "Status": "Status", "Type": "Tipo", + "Version": "Versão", "VersionList": "Lista disponível" }, "resourceGroup": { @@ -1980,6 +1987,7 @@ "Administration": "Administração", "AgentSummary": "Resumo do agente", "Architecture": "Arquitetura", + "ArtifactDetails": "Detalhes do artefato", "Cancel": "Cancelar", "ChangePassword": "Alterar a senha", "Chat": "Conversa", diff --git a/resources/i18n/pt.json b/resources/i18n/pt.json index b7f8f9b772..e061564dfb 100644 --- a/resources/i18n/pt.json +++ b/resources/i18n/pt.json @@ -1092,15 +1092,22 @@ "UsernameOptional": "Nome de usuário (opcional)" }, "reservoirPage": { + "ArtifactID": "Id de artefato", "BasicInformation": "Informações básicas", "Description": "Descrição", + "FromHuggingFace": "De abraçar o rosto", "LastUpdated": "Última atualização", "Name": "Nome", + "PullLatestVersion": "Puxe a versão mais recente ({{version}})", + "PullSelectedVersions": "Puxe versões selecionadas", "Registry": "Registro", + "RemoveSelectedVersions": "Remova versões selecionadas", "ReservoirArtifacts": "Artefatos de reservatório", "Size": "Tamanho", "Source": "Fonte", + "Status": "Status", "Type": "Tipo", + "Version": "Versão", "VersionList": "Lista disponível" }, "resourceGroup": { @@ -1979,6 +1986,7 @@ "Administration": "Administração", "AgentSummary": "Resumo do agente", "Architecture": "Arquitetura", + "ArtifactDetails": "Detalhes do artefato", "Cancel": "Cancelar", "ChangePassword": "Alterar a senha", "Chat": "Conversa", diff --git a/resources/i18n/ru.json b/resources/i18n/ru.json index 7387f1995b..7383f43f5d 100644 --- a/resources/i18n/ru.json +++ b/resources/i18n/ru.json @@ -1092,15 +1092,22 @@ "UsernameOptional": "Имя пользователя (необязательно)" }, "reservoirPage": { + "ArtifactID": "Идентификатор артефакта", "BasicInformation": "Основная информация", "Description": "Описание", + "FromHuggingFace": "От обнимающего лица", "LastUpdated": "Последнее обновлено", "Name": "Имя", + "PullLatestVersion": "Вытащите последнюю версию ({{version}})", + "PullSelectedVersions": "Вытащите выбранные версии", "Registry": "Реестр", + "RemoveSelectedVersions": "Удалить выбранные версии", "ReservoirArtifacts": "Артефакты водохранилища", "Size": "Размер", "Source": "Источник", + "Status": "Статус", "Type": "Тип", + "Version": "Версия", "VersionList": "Доступный список" }, "resourceGroup": { @@ -1979,6 +1986,7 @@ "Administration": "Администрация", "AgentSummary": "Резюме агента", "Architecture": "Архитектура", + "ArtifactDetails": "Детали артефакта", "Cancel": "Отмена", "ChangePassword": "Изменить пароль", "Chat": "Чат", diff --git a/resources/i18n/th.json b/resources/i18n/th.json index 6664d1af66..3c3c3559fc 100644 --- a/resources/i18n/th.json +++ b/resources/i18n/th.json @@ -1082,15 +1082,22 @@ "UsernameOptional": "ชื่อผู้ใช้ (ไม่บังคับ)" }, "reservoirPage": { + "ArtifactID": "ID สิ่งประดิษฐ์", "BasicInformation": "ข้อมูลพื้นฐาน", "Description": "คำอธิบาย", + "FromHuggingFace": "จากการกอดใบหน้า", "LastUpdated": "อัปเดตล่าสุด", "Name": "ชื่อ", + "PullLatestVersion": "ดึงเวอร์ชันล่าสุด ({{version}})", + "PullSelectedVersions": "ดึงเวอร์ชันที่เลือก", "Registry": "การลงทะเบียน", + "RemoveSelectedVersions": "ลบเวอร์ชันที่เลือก", "ReservoirArtifacts": "สิ่งประดิษฐ์อ่างเก็บน้ำ", "Size": "ขนาด", "Source": "แหล่งที่มา", + "Status": "สถานะ", "Type": "พิมพ์", + "Version": "รุ่น", "VersionList": "รายการที่มีอยู่" }, "resourceGroup": { @@ -1963,6 +1970,7 @@ "Administration": "การจัดการระบบ", "AgentSummary": "สรุปตัวแทน", "Architecture": "สถาปัตยกรรม", + "ArtifactDetails": "รายละเอียดสิ่งประดิษฐ์", "Cancel": "ยกเลิก", "ChangePassword": "เปลี่ยนรหัสผ่าน", "Chat": "แชท", diff --git a/resources/i18n/tr.json b/resources/i18n/tr.json index 5c050c9067..8ac251e427 100644 --- a/resources/i18n/tr.json +++ b/resources/i18n/tr.json @@ -1093,15 +1093,22 @@ "UsernameOptional": "Kullanıcı adı (İsteğe bağlı)" }, "reservoirPage": { + "ArtifactID": "Artefakt kimliği", "BasicInformation": "Temel Bilgi", "Description": "Tanım", + "FromHuggingFace": "Sarılma Yüzünden", "LastUpdated": "Son güncellendi", "Name": "İsim", + "PullLatestVersion": "En son ({{version}}) sürümü çekin", + "PullSelectedVersions": "Seçilen sürümleri çekin", "Registry": "Sicil", + "RemoveSelectedVersions": "Seçilen sürümleri kaldırın", "ReservoirArtifacts": "Rezervuar eserleri", "Size": "Boyut", "Source": "Kaynak", + "Status": "Durum", "Type": "Tip", + "Version": "Versiyon", "VersionList": "Mevcut liste" }, "resourceGroup": { @@ -1980,6 +1987,7 @@ "Administration": "yönetim", "AgentSummary": "Temsilci Özeti", "Architecture": "Mimarlık", + "ArtifactDetails": "Eser detayları", "Cancel": "İptal etmek", "ChangePassword": "Şifre değiştir", "Chat": "Sohbet", diff --git a/resources/i18n/vi.json b/resources/i18n/vi.json index ad814151d6..15773059d9 100644 --- a/resources/i18n/vi.json +++ b/resources/i18n/vi.json @@ -1093,15 +1093,22 @@ "UsernameOptional": "Tên người dùng (Tùy chọn)" }, "reservoirPage": { + "ArtifactID": "Id cổ vật", "BasicInformation": "Thông tin cơ bản", "Description": "Sự miêu tả", + "FromHuggingFace": "Từ khuôn mặt ôm", "LastUpdated": "Cập nhật lần cuối", "Name": "Tên", + "PullLatestVersion": "Kéo phiên bản mới nhất ({{version}})", + "PullSelectedVersions": "Kéo các phiên bản được chọn", "Registry": "Đăng ký", + "RemoveSelectedVersions": "Xóa các phiên bản đã chọn", "ReservoirArtifacts": "Cổ vật hồ chứa", "Size": "Kích cỡ", "Source": "Nguồn", + "Status": "Trạng thái", "Type": "Kiểu", + "Version": "Phiên bản", "VersionList": "Danh sách có sẵn" }, "resourceGroup": { @@ -1980,6 +1987,7 @@ "Administration": "Hành chính", "AgentSummary": "Tóm tắt đại lý", "Architecture": "Ngành kiến ​​​​trúc", + "ArtifactDetails": "Chi tiết tạo tác", "Cancel": "Huỷ bỏ", "ChangePassword": "Đổi mật khẩu", "Chat": "Trò chuyện", diff --git a/resources/i18n/zh-CN.json b/resources/i18n/zh-CN.json index 5ad491c0f6..c7797c444b 100644 --- a/resources/i18n/zh-CN.json +++ b/resources/i18n/zh-CN.json @@ -1093,15 +1093,22 @@ "UsernameOptional": "用户名(可选)" }, "reservoirPage": { + "ArtifactID": "文物ID", "BasicInformation": "基本信息", "Description": "描述", + "FromHuggingFace": "从拥抱脸", "LastUpdated": "最后更新", "Name": "姓名", + "PullLatestVersion": "拉最新({{version}})版本", + "PullSelectedVersions": "拉选定的版本", "Registry": "注册表", + "RemoveSelectedVersions": "删除选定的版本", "ReservoirArtifacts": "水库工件", "Size": "尺寸", "Source": "来源", + "Status": "地位", "Type": "类型", + "Version": "版本", "VersionList": "可用列表" }, "resourceGroup": { @@ -1980,6 +1987,7 @@ "Administration": "行政", "AgentSummary": "代理摘要", "Architecture": "建筑学", + "ArtifactDetails": "文物细节", "Cancel": "取消", "ChangePassword": "更改密码", "Chat": "聊天", diff --git a/resources/i18n/zh-TW.json b/resources/i18n/zh-TW.json index e767006188..a5b8796170 100644 --- a/resources/i18n/zh-TW.json +++ b/resources/i18n/zh-TW.json @@ -1092,15 +1092,22 @@ "UsernameOptional": "用戶名(可選)" }, "reservoirPage": { + "ArtifactID": "文物ID", "BasicInformation": "基本信息", "Description": "描述", + "FromHuggingFace": "從擁抱臉", "LastUpdated": "最後更新", "Name": "姓名", + "PullLatestVersion": "拉最新({{version}})版本", + "PullSelectedVersions": "拉選定的版本", "Registry": "註冊表", + "RemoveSelectedVersions": "刪除選定的版本", "ReservoirArtifacts": "水庫工件", "Size": "尺寸", "Source": "來源", + "Status": "地位", "Type": "類型", + "Version": "版本", "VersionList": "可用列表" }, "resourceGroup": { @@ -1978,6 +1985,7 @@ "Administration": "行政", "AgentSummary": "代理摘要", "Architecture": "建築學", + "ArtifactDetails": "文物細節", "Cancel": "取消", "ChangePassword": "更改密碼", "Chat": "聊天", diff --git a/src/lib/backend.ai-client-esm.ts b/src/lib/backend.ai-client-esm.ts index 6fe3493f2e..a0aa3fc62b 100644 --- a/src/lib/backend.ai-client-esm.ts +++ b/src/lib/backend.ai-client-esm.ts @@ -817,6 +817,9 @@ class Client { if (this.isManagerVersionCompatibleWith('25.13.0')) { this._features['pending-session-list'] = true; } + if (this.isManagerVersionCompatibleWith('25.12.0')) { + this._features['reservoir'] = true; + } } /**