update: Add translations for some components

This commit is contained in:
YuanNiancai
2026-01-22 09:49:19 +08:00
parent 33c70a372d
commit fea8e30725
7 changed files with 85 additions and 26 deletions

View File

@@ -1,6 +1,6 @@
<div align="center">
<img src="public/logo.svg" alt="Claude Code UI" width="64" height="64">
<h1>Cloud CLI (aka Claude Code UI)</h1>
<h1>Cloud CLI (又名 Claude Code UI)</h1>
</div>

View File

@@ -36,7 +36,7 @@ import ProtectedRoute from './components/ProtectedRoute';
import { useVersionCheck } from './hooks/useVersionCheck';
import useLocalStorage from './hooks/useLocalStorage';
import { api, authenticatedFetch } from './utils/api';
import { I18nextProvider } from 'react-i18next';
import { I18nextProvider, useTranslation } from 'react-i18next';
import i18n from './i18n/config.js';
@@ -579,6 +579,7 @@ function AppContent() {
// Version Upgrade Modal Component
const VersionUpgradeModal = () => {
const { t } = useTranslation('common');
const [isUpdating, setIsUpdating] = useState(false);
const [updateOutput, setUpdateOutput] = useState('');
const [updateError, setUpdateError] = useState('');
@@ -639,7 +640,7 @@ function AppContent() {
<button
className="fixed inset-0 bg-black/50 backdrop-blur-sm"
onClick={() => setShowVersionModal(false)}
aria-label="Close version upgrade modal"
aria-label={t('versionUpdate.ariaLabels.closeModal')}
/>
{/* Modal */}
@@ -653,9 +654,9 @@ function AppContent() {
</svg>
</div>
<div>
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">Update Available</h2>
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">{t('versionUpdate.title')}</h2>
<p className="text-sm text-gray-500 dark:text-gray-400">
{releaseInfo?.title || 'A new version is ready'}
{releaseInfo?.title || t('versionUpdate.newVersionReady')}
</p>
</div>
</div>
@@ -672,11 +673,11 @@ function AppContent() {
{/* Version Info */}
<div className="space-y-3">
<div className="flex justify-between items-center p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
<span className="text-sm font-medium text-gray-700 dark:text-gray-300">Current Version</span>
<span className="text-sm font-medium text-gray-700 dark:text-gray-300">{t('versionUpdate.currentVersion')}</span>
<span className="text-sm text-gray-900 dark:text-white font-mono">{currentVersion}</span>
</div>
<div className="flex justify-between items-center p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-700">
<span className="text-sm font-medium text-blue-700 dark:text-blue-300">Latest Version</span>
<span className="text-sm font-medium text-blue-700 dark:text-blue-300">{t('versionUpdate.latestVersion')}</span>
<span className="text-sm text-blue-900 dark:text-blue-100 font-mono">{latestVersion}</span>
</div>
</div>
@@ -685,7 +686,7 @@ function AppContent() {
{releaseInfo?.body && (
<div className="space-y-3">
<div className="flex items-center justify-between">
<h3 className="text-sm font-medium text-gray-900 dark:text-white">What's New:</h3>
<h3 className="text-sm font-medium text-gray-900 dark:text-white">{t('versionUpdate.whatsNew')}</h3>
{releaseInfo?.htmlUrl && (
<a
href={releaseInfo.htmlUrl}
@@ -693,7 +694,7 @@ function AppContent() {
rel="noopener noreferrer"
className="text-xs text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 hover:underline flex items-center gap-1"
>
View full release
{t('versionUpdate.viewFullRelease')}
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
@@ -711,7 +712,7 @@ function AppContent() {
{/* Update Output */}
{updateOutput && (
<div className="space-y-2">
<h3 className="text-sm font-medium text-gray-900 dark:text-white">Update Progress:</h3>
<h3 className="text-sm font-medium text-gray-900 dark:text-white">{t('versionUpdate.updateProgress')}</h3>
<div className="bg-gray-900 dark:bg-gray-950 rounded-lg p-4 border border-gray-700 max-h-48 overflow-y-auto">
<pre className="text-xs text-green-400 font-mono whitespace-pre-wrap">{updateOutput}</pre>
</div>
@@ -721,14 +722,14 @@ function AppContent() {
{/* Upgrade Instructions */}
{!isUpdating && !updateOutput && (
<div className="space-y-3">
<h3 className="text-sm font-medium text-gray-900 dark:text-white">Manual upgrade:</h3>
<h3 className="text-sm font-medium text-gray-900 dark:text-white">{t('versionUpdate.manualUpgrade')}</h3>
<div className="bg-gray-100 dark:bg-gray-800 rounded-lg p-3 border">
<code className="text-sm text-gray-800 dark:text-gray-200 font-mono">
git checkout main && git pull && npm install
</code>
</div>
<p className="text-xs text-gray-600 dark:text-gray-400">
Or click "Update Now" to run the update automatically.
{t('versionUpdate.manualUpgradeHint')}
</p>
</div>
)}
@@ -739,7 +740,7 @@ function AppContent() {
onClick={() => setShowVersionModal(false)}
className="flex-1 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-md transition-colors"
>
{updateOutput ? 'Close' : 'Later'}
{updateOutput ? t('versionUpdate.buttons.close') : t('versionUpdate.buttons.later')}
</button>
{!updateOutput && (
<>
@@ -749,7 +750,7 @@ function AppContent() {
}}
className="flex-1 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-md transition-colors"
>
Copy Command
{t('versionUpdate.buttons.copyCommand')}
</button>
<button
onClick={handleUpdateNow}
@@ -759,10 +760,10 @@ function AppContent() {
{isUpdating ? (
<>
<div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
Updating...
{t('versionUpdate.buttons.updating')}
</>
) : (
'Update Now'
t('versionUpdate.buttons.updateNow')
)}
</button>
</>
@@ -813,8 +814,8 @@ function AppContent() {
<button
onClick={() => setSidebarVisible(true)}
className="p-2 hover:bg-accent rounded-md transition-colors duration-200 group"
aria-label="Show sidebar"
title="Show sidebar"
aria-label={t('versionUpdate.ariaLabels.showSidebar')}
title={t('versionUpdate.ariaLabels.showSidebar')}
>
<svg
className="w-5 h-5 text-foreground group-hover:scale-110 transition-transform"
@@ -830,8 +831,8 @@ function AppContent() {
<button
onClick={() => setShowSettings(true)}
className="p-2 hover:bg-accent rounded-md transition-colors duration-200"
aria-label="Settings"
title="Settings"
aria-label={t('versionUpdate.ariaLabels.settings')}
title={t('versionUpdate.ariaLabels.settings')}
>
<SettingsIcon className="w-5 h-5 text-muted-foreground hover:text-foreground transition-colors" />
</button>
@@ -841,8 +842,8 @@ function AppContent() {
<button
onClick={() => setShowVersionModal(true)}
className="relative p-2 hover:bg-accent rounded-md transition-colors duration-200"
aria-label="Update available"
title="Update available"
aria-label={t('versionUpdate.ariaLabels.updateAvailable')}
title={t('versionUpdate.ariaLabels.updateAvailable')}
>
<Sparkles className="w-5 h-5 text-blue-500" />
<span className="absolute top-1 right-1 w-2 h-2 bg-blue-500 rounded-full animate-pulse" />
@@ -870,7 +871,7 @@ function AppContent() {
e.stopPropagation();
setSidebarOpen(false);
}}
aria-label="Close sidebar"
aria-label={t('versionUpdate.ariaLabels.closeSidebar')}
/>
<div
className={`relative w-[85vw] max-w-sm sm:w-80 h-full bg-card border-r border-border transform transition-transform duration-150 ease-out ${

View File

@@ -669,7 +669,7 @@ function Sidebar({
<p className="text-sm text-muted-foreground">
{t('projects.fetchingProjects')}
</p>
<h3 className="text-base font-medium text-foreground mb-2 md:mb-1">Loading projects...</h3>
<h3 className="text-base font-medium text-foreground mb-2 md:mb-1">{t('projects.loadingProjects')}</h3>
{loadingProgress && loadingProgress.total > 0 ? (
<div className="space-y-2">
<div className="w-full bg-muted rounded-full h-2 overflow-hidden">
@@ -679,7 +679,7 @@ function Sidebar({
/>
</div>
<p className="text-sm text-muted-foreground">
{loadingProgress.current}/{loadingProgress.total} projects
{loadingProgress.current}/{loadingProgress.total} {t('projects.projects')}
</p>
{loadingProgress.currentProject && (
<p className="text-xs text-muted-foreground/70 truncate max-w-[200px] mx-auto" title={loadingProgress.currentProject}>
@@ -689,7 +689,7 @@ function Sidebar({
</div>
) : (
<p className="text-sm text-muted-foreground">
Fetching your Claude projects and sessions
{t('projects.fetchingProjects')}
</p>
)}
</div>

View File

@@ -186,5 +186,33 @@
"providePath": "Please provide a workspace path",
"failedToCreate": "Failed to create workspace"
}
},
"versionUpdate": {
"title": "Update Available",
"newVersionReady": "A new version is ready",
"currentVersion": "Current Version",
"latestVersion": "Latest Version",
"whatsNew": "What's New:",
"viewFullRelease": "View full release",
"updateProgress": "Update Progress:",
"manualUpgrade": "Manual upgrade:",
"manualUpgradeHint": "Or click \"Update Now\" to run the update automatically.",
"updateCompleted": "Update completed successfully!",
"restartServer": "Please restart the server to apply changes.",
"updateFailed": "Update failed",
"buttons": {
"close": "Close",
"later": "Later",
"copyCommand": "Copy Command",
"updateNow": "Update Now",
"updating": "Updating..."
},
"ariaLabels": {
"closeModal": "Close version upgrade modal",
"showSidebar": "Show sidebar",
"settings": "Settings",
"updateAvailable": "Update available",
"closeSidebar": "Close sidebar"
}
}
}

View File

@@ -14,6 +14,7 @@
"newSession": "New Session",
"codexSession": "Codex Session",
"fetchingProjects": "Fetching your Claude projects and sessions",
"projects": "projects",
"noMatchingProjects": "No matching projects",
"tryDifferentSearch": "Try adjusting your search term",
"runClaudeCli": "Run Claude CLI in a project directory to get started"

View File

@@ -186,5 +186,33 @@
"providePath": "请提供工作区路径",
"failedToCreate": "创建工作区失败"
}
},
"versionUpdate": {
"title": "有可用更新",
"newVersionReady": "新版本已准备就绪",
"currentVersion": "当前版本",
"latestVersion": "最新版本",
"whatsNew": "新内容:",
"viewFullRelease": "查看完整发布",
"updateProgress": "更新进度:",
"manualUpgrade": "手动升级:",
"manualUpgradeHint": "或点击'立即更新'以自动运行更新。",
"updateCompleted": "更新成功完成!",
"restartServer": "请重启服务器以应用更改。",
"updateFailed": "更新失败",
"buttons": {
"close": "关闭",
"later": "稍后",
"copyCommand": "复制命令",
"updateNow": "立即更新",
"updating": "更新中..."
},
"ariaLabels": {
"closeModal": "关闭版本升级模态框",
"showSidebar": "显示侧边栏",
"settings": "设置",
"updateAvailable": "有可用更新",
"closeSidebar": "关闭侧边栏"
}
}
}

View File

@@ -14,6 +14,7 @@
"newSession": "新会话",
"codexSession": "Codex 会话",
"fetchingProjects": "正在获取您的 Claude 项目和会话",
"projects": "项目",
"noMatchingProjects": "未找到匹配的项目",
"tryDifferentSearch": "尝试调整您的搜索词",
"runClaudeCli": "在项目目录中运行 Claude CLI 以开始使用"