mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-08 06:19:05 +08:00
feat: integrate i18n support into migration process
- Added internationalization support to the MigrationApp component, enabling dynamic language changes. - Updated button labels and informational texts to use translation keys for better localization. - Introduced a language selector to allow users to switch between languages during the migration process. - Ensured that the migration process waits for i18n initialization before rendering the main application.
This commit is contained in:
parent
db10bdd539
commit
1685590a07
@ -1,9 +1,10 @@
|
|||||||
import { Button } from '@cherrystudio/ui'
|
import { Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@cherrystudio/ui'
|
||||||
import { AppLogo } from '@renderer/config/env'
|
import { AppLogo } from '@renderer/config/env'
|
||||||
import { loggerService } from '@renderer/services/LoggerService'
|
import { loggerService } from '@renderer/services/LoggerService'
|
||||||
import { Progress, Space, Steps } from 'antd'
|
import { Progress, Space, Steps } from 'antd'
|
||||||
import { AlertTriangle, CheckCircle, CheckCircle2, Database, Loader2, Rocket } from 'lucide-react'
|
import { AlertTriangle, CheckCircle, CheckCircle2, Database, Loader2, Rocket } from 'lucide-react'
|
||||||
import React, { useMemo, useState } from 'react'
|
import React, { useMemo, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import { MigratorProgressList } from './components'
|
import { MigratorProgressList } from './components'
|
||||||
@ -14,10 +15,15 @@ import { MigrationIpcChannels } from './types'
|
|||||||
const logger = loggerService.withContext('MigrationApp')
|
const logger = loggerService.withContext('MigrationApp')
|
||||||
|
|
||||||
const MigrationApp: React.FC = () => {
|
const MigrationApp: React.FC = () => {
|
||||||
|
const { t, i18n } = useTranslation()
|
||||||
const { progress, lastError, confirmComplete } = useMigrationProgress()
|
const { progress, lastError, confirmComplete } = useMigrationProgress()
|
||||||
const actions = useMigrationActions()
|
const actions = useMigrationActions()
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
|
const handleLanguageChange = (lang: string) => {
|
||||||
|
i18n.changeLanguage(lang)
|
||||||
|
}
|
||||||
|
|
||||||
const handleStartMigration = async () => {
|
const handleStartMigration = async () => {
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
try {
|
try {
|
||||||
@ -118,19 +124,19 @@ const MigrationApp: React.FC = () => {
|
|||||||
case 'introduction':
|
case 'introduction':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onClick={actions.cancel}>取消</Button>
|
<Button onClick={actions.cancel}>{t('migration.buttons.cancel')}</Button>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<Button onClick={actions.proceedToBackup}>下一步</Button>
|
<Button onClick={actions.proceedToBackup}>{t('migration.buttons.next')}</Button>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
case 'backup_required':
|
case 'backup_required':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onClick={actions.cancel}>取消</Button>
|
<Button onClick={actions.cancel}>{t('migration.buttons.cancel')}</Button>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<Space>
|
<Space>
|
||||||
<Button onClick={actions.showBackupDialog}>创建备份</Button>
|
<Button onClick={actions.showBackupDialog}>{t('migration.buttons.create_backup')}</Button>
|
||||||
<Button onClick={actions.confirmBackup}>我已备份,开始迁移</Button>
|
<Button onClick={actions.confirmBackup}>{t('migration.buttons.confirm_backup')}</Button>
|
||||||
</Space>
|
</Space>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
@ -139,17 +145,17 @@ const MigrationApp: React.FC = () => {
|
|||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<div></div>
|
<div></div>
|
||||||
<Button disabled loading>
|
<Button disabled loading>
|
||||||
正在备份...
|
{t('migration.buttons.backing_up')}
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
)
|
)
|
||||||
case 'backup_confirmed':
|
case 'backup_confirmed':
|
||||||
return (
|
return (
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button onClick={actions.cancel}>取消</Button>
|
<Button onClick={actions.cancel}>{t('migration.buttons.cancel')}</Button>
|
||||||
<Space>
|
<Space>
|
||||||
<Button onClick={handleStartMigration} loading={isLoading}>
|
<Button onClick={handleStartMigration} loading={isLoading}>
|
||||||
开始迁移
|
{t('migration.buttons.start_migration')}
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
@ -158,29 +164,29 @@ const MigrationApp: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<div></div>
|
<div></div>
|
||||||
<Button disabled>迁移进行中...</Button>
|
<Button disabled>{t('migration.buttons.migrating')}</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
)
|
)
|
||||||
case 'migration_completed':
|
case 'migration_completed':
|
||||||
return (
|
return (
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<div></div>
|
<div></div>
|
||||||
<Button onClick={confirmComplete}>确定</Button>
|
<Button onClick={confirmComplete}>{t('migration.buttons.confirm')}</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
)
|
)
|
||||||
case 'completed':
|
case 'completed':
|
||||||
return (
|
return (
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<div></div>
|
<div></div>
|
||||||
<Button onClick={actions.restart}>重启应用</Button>
|
<Button onClick={actions.restart}>{t('migration.buttons.restart')}</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
)
|
)
|
||||||
case 'error':
|
case 'error':
|
||||||
return (
|
return (
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button onClick={actions.cancel}>关闭应用</Button>
|
<Button onClick={actions.cancel}>{t('migration.buttons.close')}</Button>
|
||||||
<Space>
|
<Space>
|
||||||
<Button onClick={actions.retry}>重新尝试</Button>
|
<Button onClick={actions.retry}>{t('migration.buttons.retry')}</Button>
|
||||||
</Space>
|
</Space>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
)
|
)
|
||||||
@ -193,7 +199,7 @@ const MigrationApp: React.FC = () => {
|
|||||||
<Container>
|
<Container>
|
||||||
<Header>
|
<Header>
|
||||||
<HeaderLogo src={AppLogo} />
|
<HeaderLogo src={AppLogo} />
|
||||||
<HeaderTitle>数据迁移向导</HeaderTitle>
|
<HeaderTitle>{t('migration.title')}</HeaderTitle>
|
||||||
</Header>
|
</Header>
|
||||||
|
|
||||||
<MainContent>
|
<MainContent>
|
||||||
@ -204,9 +210,25 @@ const MigrationApp: React.FC = () => {
|
|||||||
current={currentStep}
|
current={currentStep}
|
||||||
status={stepStatus}
|
status={stepStatus}
|
||||||
size="small"
|
size="small"
|
||||||
items={[{ title: '介绍' }, { title: '备份' }, { title: '迁移' }, { title: '完成' }]}
|
items={[
|
||||||
|
{ title: t('migration.stages.introduction') },
|
||||||
|
{ title: t('migration.stages.backup') },
|
||||||
|
{ title: t('migration.stages.migration') },
|
||||||
|
{ title: t('migration.stages.completed') }
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
</StepsContainer>
|
</StepsContainer>
|
||||||
|
<LanguageSelectorContainer>
|
||||||
|
<Select value={i18n.language} onValueChange={handleLanguageChange}>
|
||||||
|
<SelectTrigger size="sm">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="zh-CN">中文</SelectItem>
|
||||||
|
<SelectItem value="en-US">English</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</LanguageSelectorContainer>
|
||||||
</LeftSidebar>
|
</LeftSidebar>
|
||||||
|
|
||||||
<RightContent>
|
<RightContent>
|
||||||
@ -215,46 +237,44 @@ const MigrationApp: React.FC = () => {
|
|||||||
|
|
||||||
{progress.stage === 'introduction' && (
|
{progress.stage === 'introduction' && (
|
||||||
<InfoCard>
|
<InfoCard>
|
||||||
<InfoTitle>将数据迁移到新的架构中</InfoTitle>
|
<InfoTitle>{t('migration.introduction.title')}</InfoTitle>
|
||||||
<InfoDescription>
|
<InfoDescription>
|
||||||
Cherry Studio对数据的存储和使用方式进行了重大重构,在新的架构下,效率和安全性将会得到极大提升。
|
{t('migration.introduction.description_1')}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
数据必须进行迁移,才能在新版本中使用。
|
{t('migration.introduction.description_2')}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
我们会指导你完成迁移,迁移过程不会损坏原来的数据,你随时可以取消迁移,并继续使用旧版本。
|
{t('migration.introduction.description_3')}
|
||||||
</InfoDescription>
|
</InfoDescription>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{progress.stage === 'backup_required' && (
|
{progress.stage === 'backup_required' && (
|
||||||
<InfoCard variant="warning">
|
<InfoCard variant="warning">
|
||||||
<InfoTitle>创建数据备份</InfoTitle>
|
<InfoTitle>{t('migration.backup_required.title')}</InfoTitle>
|
||||||
<InfoDescription>
|
<InfoDescription>{t('migration.backup_required.description')}</InfoDescription>
|
||||||
迁移前必须创建数据备份以确保数据安全。请选择备份位置或确认已有最新备份。
|
|
||||||
</InfoDescription>
|
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{progress.stage === 'backup_progress' && (
|
{progress.stage === 'backup_progress' && (
|
||||||
<InfoCard variant="warning">
|
<InfoCard variant="warning">
|
||||||
<InfoTitle>准备数据备份</InfoTitle>
|
<InfoTitle>{t('migration.backup_progress.title')}</InfoTitle>
|
||||||
<InfoDescription>请选择备份位置,保存后等待备份完成。</InfoDescription>
|
<InfoDescription>{t('migration.backup_progress.description')}</InfoDescription>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{progress.stage === 'backup_confirmed' && (
|
{progress.stage === 'backup_confirmed' && (
|
||||||
<InfoCard variant="success">
|
<InfoCard variant="success">
|
||||||
<InfoTitle>备份完成</InfoTitle>
|
<InfoTitle>{t('migration.backup_confirmed.title')}</InfoTitle>
|
||||||
<InfoDescription>数据备份已完成,现在可以安全地开始迁移。</InfoDescription>
|
<InfoDescription>{t('migration.backup_confirmed.description')}</InfoDescription>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{progress.stage === 'migration' && (
|
{progress.stage === 'migration' && (
|
||||||
<div style={{ width: '100%', maxWidth: '600px', margin: '0 auto' }}>
|
<div style={{ width: '100%', maxWidth: '600px', margin: '0 auto' }}>
|
||||||
<InfoCard>
|
<InfoCard>
|
||||||
<InfoTitle>正在迁移数据...</InfoTitle>
|
<InfoTitle>{t('migration.migration.title')}</InfoTitle>
|
||||||
<InfoDescription>{progress.currentMessage}</InfoDescription>
|
<InfoDescription>{progress.currentMessage}</InfoDescription>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
<ProgressContainer>
|
<ProgressContainer>
|
||||||
@ -273,8 +293,8 @@ const MigrationApp: React.FC = () => {
|
|||||||
{progress.stage === 'migration_completed' && (
|
{progress.stage === 'migration_completed' && (
|
||||||
<div style={{ width: '100%', maxWidth: '600px', margin: '0 auto' }}>
|
<div style={{ width: '100%', maxWidth: '600px', margin: '0 auto' }}>
|
||||||
<InfoCard variant="success">
|
<InfoCard variant="success">
|
||||||
<InfoTitle>数据迁移完成!</InfoTitle>
|
<InfoTitle>{t('migration.migration_completed.title')}</InfoTitle>
|
||||||
<InfoDescription>所有数据已成功迁移到新架构,请点击确定继续。</InfoDescription>
|
<InfoDescription>{t('migration.migration_completed.description')}</InfoDescription>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
<ProgressContainer>
|
<ProgressContainer>
|
||||||
<Progress percent={100} strokeColor={getProgressColor()} trailColor="#f0f0f0" />
|
<Progress percent={100} strokeColor={getProgressColor()} trailColor="#f0f0f0" />
|
||||||
@ -287,19 +307,20 @@ const MigrationApp: React.FC = () => {
|
|||||||
|
|
||||||
{progress.stage === 'completed' && (
|
{progress.stage === 'completed' && (
|
||||||
<InfoCard variant="success">
|
<InfoCard variant="success">
|
||||||
<InfoTitle>迁移完成</InfoTitle>
|
<InfoTitle>{t('migration.completed.title')}</InfoTitle>
|
||||||
<InfoDescription>数据已成功迁移,重启应用后即可正常使用。</InfoDescription>
|
<InfoDescription>{t('migration.completed.description')}</InfoDescription>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{progress.stage === 'error' && (
|
{progress.stage === 'error' && (
|
||||||
<InfoCard variant="error">
|
<InfoCard variant="error">
|
||||||
<InfoTitle>迁移失败</InfoTitle>
|
<InfoTitle>{t('migration.error.title')}</InfoTitle>
|
||||||
<InfoDescription>
|
<InfoDescription>
|
||||||
迁移过程遇到错误,您可以重新尝试或继续使用之前版本(原始数据完好保存)。
|
{t('migration.error.description')}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
错误信息:{lastError || progress.error || '发生未知错误'}
|
{t('migration.error.error_prefix')}
|
||||||
|
{lastError || progress.error || 'Unknown error'}
|
||||||
</InfoDescription>
|
</InfoDescription>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
)}
|
)}
|
||||||
@ -385,6 +406,11 @@ const StepsContainer = styled.div`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const LanguageSelectorContainer = styled.div`
|
||||||
|
padding: 16px 24px 24px 24px;
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
`
|
||||||
|
|
||||||
const RightContent = styled.div`
|
const RightContent = styled.div`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import { CheckCircle2, Circle, Loader2, XCircle } from 'lucide-react'
|
import { CheckCircle2, Circle, Loader2, XCircle } from 'lucide-react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled, { keyframes } from 'styled-components'
|
import styled, { keyframes } from 'styled-components'
|
||||||
|
|
||||||
import type { MigratorProgress as MigratorProgressType, MigratorStatus } from '../types'
|
import type { MigratorProgress as MigratorProgressType, MigratorStatus } from '../types'
|
||||||
@ -41,14 +42,13 @@ const SpinningIcon = styled.div`
|
|||||||
animation: ${spin} 1s linear infinite;
|
animation: ${spin} 1s linear infinite;
|
||||||
`
|
`
|
||||||
|
|
||||||
const statusTextMap: Record<MigratorStatus, string> = {
|
|
||||||
pending: '等待中',
|
|
||||||
running: '进行中',
|
|
||||||
completed: '完成',
|
|
||||||
failed: '失败'
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MigratorProgressList: React.FC<Props> = ({ migrators }) => {
|
export const MigratorProgressList: React.FC<Props> = ({ migrators }) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const getStatusText = (status: MigratorStatus): string => {
|
||||||
|
return t(`migration.status.${status}`)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<List>
|
<List>
|
||||||
@ -58,7 +58,7 @@ export const MigratorProgressList: React.FC<Props> = ({ migrators }) => {
|
|||||||
<StatusIcon status={migrator.status} />
|
<StatusIcon status={migrator.status} />
|
||||||
<ItemName>{migrator.name}</ItemName>
|
<ItemName>{migrator.name}</ItemName>
|
||||||
</ItemLeft>
|
</ItemLeft>
|
||||||
<ItemStatus status={migrator.status}>{migrator.error || statusTextMap[migrator.status]}</ItemStatus>
|
<ItemStatus status={migrator.status}>{migrator.error || getStatusText(migrator.status)}</ItemStatus>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import '@ant-design/v5-patch-for-react-19'
|
|||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client'
|
||||||
|
|
||||||
|
import { initI18n } from './i18n'
|
||||||
import MigrationApp from './MigrationApp'
|
import MigrationApp from './MigrationApp'
|
||||||
|
|
||||||
// Initialize logger for this window
|
// Initialize logger for this window
|
||||||
@ -16,4 +17,7 @@ loggerService.initWindowSource('MigrationV2')
|
|||||||
|
|
||||||
const root = createRoot(document.getElementById('root') as HTMLElement)
|
const root = createRoot(document.getElementById('root') as HTMLElement)
|
||||||
|
|
||||||
root.render(<MigrationApp />)
|
// Wait for i18n to be fully initialized before rendering
|
||||||
|
initI18n().then(() => {
|
||||||
|
root.render(<MigrationApp />)
|
||||||
|
})
|
||||||
|
|||||||
43
src/renderer/src/windows/migrationV2/i18n/index.ts
Normal file
43
src/renderer/src/windows/migrationV2/i18n/index.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* i18n initialization for migration window
|
||||||
|
* Detects system language independently without relying on preferenceService
|
||||||
|
*/
|
||||||
|
|
||||||
|
import i18n from 'i18next'
|
||||||
|
import { initReactI18next } from 'react-i18next'
|
||||||
|
|
||||||
|
import { enUS, zhCN } from './locales'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect system language independently
|
||||||
|
* Rule: If system language contains 'zh', use Chinese, otherwise use English
|
||||||
|
*/
|
||||||
|
function detectLanguage(): 'zh-CN' | 'en-US' {
|
||||||
|
const browserLang = navigator.language || navigator.languages?.[0] || 'en-US'
|
||||||
|
|
||||||
|
// If contains 'zh' (zh, zh-CN, zh-TW, zh-HK, etc.), use Chinese
|
||||||
|
return browserLang.toLowerCase().includes('zh') ? 'zh-CN' : 'en-US'
|
||||||
|
}
|
||||||
|
|
||||||
|
const language = detectLanguage()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize i18n asynchronously
|
||||||
|
* Must be called and awaited before rendering components
|
||||||
|
*/
|
||||||
|
const initI18n = async () => {
|
||||||
|
await i18n.use(initReactI18next).init({
|
||||||
|
resources: {
|
||||||
|
'zh-CN': { translation: zhCN },
|
||||||
|
'en-US': { translation: enUS }
|
||||||
|
},
|
||||||
|
lng: language,
|
||||||
|
fallbackLng: 'en-US',
|
||||||
|
interpolation: {
|
||||||
|
escapeValue: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default i18n
|
||||||
|
export { initI18n }
|
||||||
139
src/renderer/src/windows/migrationV2/i18n/locales.ts
Normal file
139
src/renderer/src/windows/migrationV2/i18n/locales.ts
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/**
|
||||||
|
* Migration window translations
|
||||||
|
* Supports Chinese (zh-CN) and English (en-US)
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const zhCN = {
|
||||||
|
migration: {
|
||||||
|
title: '数据迁移向导',
|
||||||
|
stages: {
|
||||||
|
introduction: '介绍',
|
||||||
|
backup: '备份',
|
||||||
|
migration: '迁移',
|
||||||
|
completed: '完成'
|
||||||
|
},
|
||||||
|
buttons: {
|
||||||
|
cancel: '取消',
|
||||||
|
next: '下一步',
|
||||||
|
create_backup: '创建备份',
|
||||||
|
confirm_backup: '我已备份,开始迁移',
|
||||||
|
start_migration: '开始迁移',
|
||||||
|
confirm: '确定',
|
||||||
|
restart: '重启应用',
|
||||||
|
retry: '重新尝试',
|
||||||
|
close: '关闭应用',
|
||||||
|
backing_up: '正在备份...',
|
||||||
|
migrating: '迁移进行中...'
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
pending: '等待中',
|
||||||
|
running: '进行中',
|
||||||
|
completed: '完成',
|
||||||
|
failed: '失败'
|
||||||
|
},
|
||||||
|
introduction: {
|
||||||
|
title: '将数据迁移到新的架构中',
|
||||||
|
description_1:
|
||||||
|
'Cherry Studio对数据的存储和使用方式进行了重大重构,在新的架构下,效率和安全性将会得到极大提升。',
|
||||||
|
description_2: '数据必须进行迁移,才能在新版本中使用。',
|
||||||
|
description_3: '我们会指导你完成迁移,迁移过程不会损坏原来的数据,你随时可以取消迁移,并继续使用旧版本。'
|
||||||
|
},
|
||||||
|
backup_required: {
|
||||||
|
title: '创建数据备份',
|
||||||
|
description: '迁移前必须创建数据备份以确保数据安全。请选择备份位置或确认已有最新备份。'
|
||||||
|
},
|
||||||
|
backup_progress: {
|
||||||
|
title: '准备数据备份',
|
||||||
|
description: '请选择备份位置,保存后等待备份完成。'
|
||||||
|
},
|
||||||
|
backup_confirmed: {
|
||||||
|
title: '备份完成',
|
||||||
|
description: '数据备份已完成,现在可以安全地开始迁移。'
|
||||||
|
},
|
||||||
|
migration: {
|
||||||
|
title: '正在迁移数据...'
|
||||||
|
},
|
||||||
|
migration_completed: {
|
||||||
|
title: '数据迁移完成!',
|
||||||
|
description: '所有数据已成功迁移到新架构,请点击确定继续。'
|
||||||
|
},
|
||||||
|
completed: {
|
||||||
|
title: '迁移完成',
|
||||||
|
description: '数据已成功迁移,重启应用后即可正常使用。'
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
title: '迁移失败',
|
||||||
|
description: '迁移过程遇到错误,您可以重新尝试或继续使用之前版本(原始数据完好保存)。',
|
||||||
|
error_prefix: '错误信息:'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enUS = {
|
||||||
|
migration: {
|
||||||
|
title: 'Data Migration Wizard',
|
||||||
|
stages: {
|
||||||
|
introduction: 'Introduction',
|
||||||
|
backup: 'Backup',
|
||||||
|
migration: 'Migration',
|
||||||
|
completed: 'Completed'
|
||||||
|
},
|
||||||
|
buttons: {
|
||||||
|
cancel: 'Cancel',
|
||||||
|
next: 'Next',
|
||||||
|
create_backup: 'Create Backup',
|
||||||
|
confirm_backup: 'I Have Backup, Start Migration',
|
||||||
|
start_migration: 'Start Migration',
|
||||||
|
confirm: 'OK',
|
||||||
|
restart: 'Restart App',
|
||||||
|
retry: 'Retry',
|
||||||
|
close: 'Close App',
|
||||||
|
backing_up: 'Backing up...',
|
||||||
|
migrating: 'Migrating...'
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
pending: 'Pending',
|
||||||
|
running: 'Running',
|
||||||
|
completed: 'Completed',
|
||||||
|
failed: 'Failed'
|
||||||
|
},
|
||||||
|
introduction: {
|
||||||
|
title: 'Migrate Data to New Architecture',
|
||||||
|
description_1:
|
||||||
|
'Cherry Studio has undergone a major refactoring of data storage and usage. The new architecture will greatly improve efficiency and security.',
|
||||||
|
description_2: 'Data migration is required to use the new version.',
|
||||||
|
description_3:
|
||||||
|
'We will guide you through the migration process. The migration will not damage your original data, and you can cancel at any time and continue using the old version.'
|
||||||
|
},
|
||||||
|
backup_required: {
|
||||||
|
title: 'Create Data Backup',
|
||||||
|
description:
|
||||||
|
'A data backup must be created before migration to ensure data safety. Please select a backup location or confirm you have a recent backup.'
|
||||||
|
},
|
||||||
|
backup_progress: {
|
||||||
|
title: 'Preparing Data Backup',
|
||||||
|
description: 'Please select a backup location, save, and wait for the backup to complete.'
|
||||||
|
},
|
||||||
|
backup_confirmed: {
|
||||||
|
title: 'Backup Completed',
|
||||||
|
description: 'Data backup has been completed. You can now safely start the migration.'
|
||||||
|
},
|
||||||
|
migration: {
|
||||||
|
title: 'Migrating Data...'
|
||||||
|
},
|
||||||
|
migration_completed: {
|
||||||
|
title: 'Data Migration Completed!',
|
||||||
|
description: 'All data has been successfully migrated to the new architecture. Please click OK to continue.'
|
||||||
|
},
|
||||||
|
completed: {
|
||||||
|
title: 'Migration Completed',
|
||||||
|
description: 'Data has been successfully migrated. The application will work normally after restart.'
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
title: 'Migration Failed',
|
||||||
|
description:
|
||||||
|
'An error occurred during migration. You can retry or continue using the previous version (original data is intact).',
|
||||||
|
error_prefix: 'Error: '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user