refactor: internationalize HomePage component
- Replace all hardcoded Chinese text with t() function calls - Add Chinese translations for all new i18n keys in zh-CN.json - Update UI text including buttons, labels, error messages, and status messages - Ensure all user-facing strings are properly internationalized
This commit is contained in:
parent
05fce42cbf
commit
fd84f1458a
@ -1193,5 +1193,30 @@
|
||||
"URL": "URL",
|
||||
"Created": "创建时间",
|
||||
"Last Updated": "最后更新",
|
||||
"Click image to try": "点击图片快速体验"
|
||||
"Click image to try": "点击图片快速体验",
|
||||
"Remove Background": "去除背景",
|
||||
"Download": "下载",
|
||||
"Change Image": "更换图片",
|
||||
"Upload Image": "上传图片",
|
||||
"or": "或",
|
||||
"Paste image URL here": "粘贴图片URL",
|
||||
"Drag and drop your image anywhere, or paste image directly": "拖放图片到任意位置,或直接粘贴图片",
|
||||
"Supports JPG, PNG, WebP formats": "支持 JPG、PNG、WebP 格式",
|
||||
"Loading image from URL...": "加载图片URL中...",
|
||||
"Original": "原图",
|
||||
"Background Removed": "去背景后",
|
||||
"Processing...": "处理中...",
|
||||
"Add new image": "添加新图片",
|
||||
"Delete": "删除",
|
||||
"Unsupported image format. Please use JPG, PNG, or WebP": "不支持的图片格式,请使用 JPG、PNG 或 WebP",
|
||||
"Image size exceeds 10MB limit": "图片大小超过 10MB 限制",
|
||||
"Please upload an image first": "请先上传图片",
|
||||
"Failed to download image": "下载失败",
|
||||
"Please enter an image URL": "请输入图片URL",
|
||||
"Please enter a valid image URL": "请输入有效的图片URL",
|
||||
"Image processing failed, please try again": "图片处理失败,请重试",
|
||||
"Failed to load sample image": "加载示例图片失败",
|
||||
"Failed to remove background": "去背景失败",
|
||||
"Failed to load image from URL": "从URL加载图片失败",
|
||||
"Sign up successful, but auto login failed. Please login manually": "注册成功,但自动登录失败,请手动登录"
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ const handleSignupSubmit = async () => {
|
||||
signupFormData.email = ''
|
||||
signupFormData.phoneNumber = ''
|
||||
} else {
|
||||
message.warning(loginResult.error || t('注册成功,但自动登录失败,请手动登录'))
|
||||
message.warning(loginResult.error || t('Sign up successful, but auto login failed. Please login manually'))
|
||||
showSignupModal.value = false
|
||||
showLoginModal.value = true
|
||||
}
|
||||
@ -385,13 +385,13 @@ const handleFileSelect = (e: Event) => {
|
||||
const processFile = async (file: File) => {
|
||||
const validTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp']
|
||||
if (!validTypes.includes(file.type)) {
|
||||
message.warning('不支持的图片格式,请使用 JPG、PNG 或 WebP')
|
||||
message.warning(t('Unsupported image format. Please use JPG, PNG, or WebP'))
|
||||
return
|
||||
}
|
||||
|
||||
const maxSize = 10 * 1024 * 1024
|
||||
if (file.size > maxSize) {
|
||||
message.warning('图片大小超过 10MB 限制')
|
||||
message.warning(t('Image size exceeds 10MB limit'))
|
||||
return
|
||||
}
|
||||
|
||||
@ -416,7 +416,7 @@ const processFile = async (file: File) => {
|
||||
reader.readAsDataURL(compressedFile)
|
||||
} catch (error) {
|
||||
console.error('图片压缩失败:', error)
|
||||
message.error('图片处理失败,请重试')
|
||||
message.error(t('Image processing failed, please try again'))
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,7 +437,7 @@ const handleSampleImageClick = async (imageUrl: string) => {
|
||||
// 验证文件类型
|
||||
const validTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp']
|
||||
if (!validTypes.includes(blob.type)) {
|
||||
message.warning('不支持的图片格式')
|
||||
message.warning(t('Unsupported image format. Please use JPG, PNG, or WebP'))
|
||||
processing.value = false
|
||||
return
|
||||
}
|
||||
@ -445,7 +445,7 @@ const handleSampleImageClick = async (imageUrl: string) => {
|
||||
// 验证文件大小
|
||||
const maxSize = 10 * 1024 * 1024
|
||||
if (blob.size > maxSize) {
|
||||
message.warning('图片大小超过 10MB 限制')
|
||||
message.warning(t('Image size exceeds 10MB limit'))
|
||||
processing.value = false
|
||||
return
|
||||
}
|
||||
@ -455,12 +455,12 @@ const handleSampleImageClick = async (imageUrl: string) => {
|
||||
await processFile(file)
|
||||
} catch (error: any) {
|
||||
console.error('加载示例图片失败:', error)
|
||||
let errorMessage = '加载示例图片失败'
|
||||
let errorMessage = t('Failed to load sample image')
|
||||
|
||||
if (error.message?.includes('CORS')) {
|
||||
errorMessage = '图片服务器不允许跨域访问'
|
||||
errorMessage = t('CORS error. The image server does not allow cross-origin access.')
|
||||
} else if (error.message?.includes('Failed to load')) {
|
||||
errorMessage = '加载图片失败,请稍后重试'
|
||||
errorMessage = t('Failed to load image. Please check the URL and try again.')
|
||||
}
|
||||
|
||||
message.error(errorMessage)
|
||||
@ -470,7 +470,7 @@ const handleSampleImageClick = async (imageUrl: string) => {
|
||||
|
||||
const handleRemoveBackground = async () => {
|
||||
if (!uploadedImage.value) {
|
||||
message.warning('请先上传图片')
|
||||
message.warning(t('Please upload an image first'))
|
||||
return
|
||||
}
|
||||
|
||||
@ -519,16 +519,16 @@ const handleRemoveBackground = async () => {
|
||||
historyList.value[currentHistoryIndex.value].resultImage = firstResult.image_url
|
||||
}
|
||||
} else {
|
||||
message.error(firstResult.error || '去背景失败')
|
||||
message.error(firstResult.error || t('Failed to remove background'))
|
||||
}
|
||||
} else {
|
||||
message.error(result.error || '去背景失败')
|
||||
message.error(result.error || t('Failed to remove background'))
|
||||
}
|
||||
} else {
|
||||
message.error(response.data?.error || response.data?.message || '去背景失败')
|
||||
message.error(response.data?.error || response.data?.message || t('Failed to remove background'))
|
||||
}
|
||||
} catch (error: any) {
|
||||
let errorMessage = '去背景失败'
|
||||
let errorMessage = t('Failed to remove background')
|
||||
if (error.response?.data?.error) {
|
||||
errorMessage = error.response.data.error
|
||||
} else if (error.message) {
|
||||
@ -596,7 +596,7 @@ const handleDownload = async () => {
|
||||
// 不立即清理 blob URL,保留缓存供后续下载使用
|
||||
} catch (error) {
|
||||
console.error('下载失败:', error)
|
||||
message.error('下载失败')
|
||||
message.error(t('Failed to download image'))
|
||||
}
|
||||
}
|
||||
|
||||
@ -789,12 +789,12 @@ const handleUrlPaste = async (event: ClipboardEvent) => {
|
||||
const handleUrlSubmit = async () => {
|
||||
const url = imageUrl.value.trim()
|
||||
if (!url) {
|
||||
message.warning('请输入图片URL')
|
||||
message.warning(t('Please enter an image URL'))
|
||||
return
|
||||
}
|
||||
|
||||
if (!isValidImageUrl(url)) {
|
||||
message.warning('请输入有效的图片URL')
|
||||
message.warning(t('Please enter a valid image URL'))
|
||||
return
|
||||
}
|
||||
|
||||
@ -813,14 +813,14 @@ const handleUrlSubmit = async () => {
|
||||
|
||||
const validTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp']
|
||||
if (!validTypes.includes(blob.type)) {
|
||||
message.warning('不支持的图片格式,请使用 JPG、PNG 或 WebP')
|
||||
message.warning(t('Unsupported image format. Please use JPG, PNG, or WebP'))
|
||||
processing.value = false
|
||||
return
|
||||
}
|
||||
|
||||
const maxSize = 10 * 1024 * 1024
|
||||
if (blob.size > maxSize) {
|
||||
message.warning('图片大小超过 10MB 限制')
|
||||
message.warning(t('Image size exceeds 10MB limit'))
|
||||
processing.value = false
|
||||
return
|
||||
}
|
||||
@ -842,17 +842,17 @@ const handleUrlSubmit = async () => {
|
||||
await handleRemoveBackground()
|
||||
} catch (error) {
|
||||
console.error('图片压缩失败:', error)
|
||||
message.error('图片处理失败,请重试')
|
||||
message.error(t('Image processing failed, please try again'))
|
||||
processing.value = false
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('加载图片URL失败:', error)
|
||||
let errorMessage = '加载图片URL失败'
|
||||
let errorMessage = t('Failed to load image from URL')
|
||||
|
||||
if (error.message?.includes('CORS')) {
|
||||
errorMessage = 'CORS错误。图片服务器不允许跨域访问。'
|
||||
errorMessage = t('CORS error. The image server does not allow cross-origin access.')
|
||||
} else if (error.message?.includes('Failed to load')) {
|
||||
errorMessage = '加载图片失败。请检查URL并重试。'
|
||||
errorMessage = t('Failed to load image. Please check the URL and try again.')
|
||||
}
|
||||
|
||||
message.error(errorMessage)
|
||||
@ -955,8 +955,8 @@ onUnmounted(() => {
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<n-space :size="12">
|
||||
<n-button quaternary @click="handleSignup">注册</n-button>
|
||||
<n-button type="primary" @click="handleLogin" class="login-btn">登录</n-button>
|
||||
<n-button quaternary @click="handleSignup">{{ t('Sign up') }}</n-button>
|
||||
<n-button type="primary" @click="handleLogin" class="login-btn">{{ t('Login') }}</n-button>
|
||||
</n-space>
|
||||
</div>
|
||||
</div>
|
||||
@ -974,12 +974,12 @@ onUnmounted(() => {
|
||||
|
||||
<div class="tool-page">
|
||||
<div class="page-header">
|
||||
<h2>去除背景</h2>
|
||||
<h2>{{ t('Remove Background') }}</h2>
|
||||
<div v-if="uploadedImage" class="toolbar-actions">
|
||||
<button v-if="resultImage" class="toolbar-btn" @click="handleDownload" title="下载">
|
||||
<button v-if="resultImage" class="toolbar-btn" @click="handleDownload" :title="t('Download')">
|
||||
<i class="fa fa-download"></i>
|
||||
</button>
|
||||
<button class="toolbar-btn" @click="resetUpload" title="更换图片">
|
||||
<button class="toolbar-btn" @click="resetUpload" :title="t('Change Image')">
|
||||
<i class="fa fa-refresh"></i>
|
||||
</button>
|
||||
</div>
|
||||
@ -992,11 +992,11 @@ onUnmounted(() => {
|
||||
<div class="upload-content">
|
||||
<button type="button" class="upload-btn" @click="triggerFileInput" :disabled="processing">
|
||||
<i class="fa fa-upload"></i>
|
||||
<span>上传图片</span>
|
||||
<span>{{ t('Upload Image') }}</span>
|
||||
</button>
|
||||
|
||||
<div class="divider">
|
||||
<span>或</span>
|
||||
<span>{{ t('or') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="url-input-wrapper" @click.stop>
|
||||
@ -1005,19 +1005,19 @@ onUnmounted(() => {
|
||||
v-model="imageUrl"
|
||||
type="text"
|
||||
class="url-input"
|
||||
placeholder="粘贴图片URL"
|
||||
:placeholder="t('Paste image URL here')"
|
||||
@keyup.enter="handleUrlSubmit"
|
||||
@paste="handleUrlPaste"
|
||||
:disabled="processing"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p class="upload-hint">拖放图片到任意位置,或直接粘贴图片</p>
|
||||
<p class="upload-format-hint">支持 JPG、PNG、WebP 格式</p>
|
||||
<p class="upload-hint">{{ t('Drag and drop your image anywhere, or paste image directly') }}</p>
|
||||
<p class="upload-format-hint">{{ t('Supports JPG, PNG, WebP formats') }}</p>
|
||||
</div>
|
||||
<div v-if="processing" class="upload-processing-overlay">
|
||||
<div class="spinner"></div>
|
||||
<p>加载图片URL中...</p>
|
||||
<p>{{ t('Loading image from URL...') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1025,10 +1025,10 @@ onUnmounted(() => {
|
||||
<div class="comparison-view" v-if="resultImage">
|
||||
<div class="comparison-container" ref="comparisonContainerRef">
|
||||
<div class="comparison-image original-image" :style="{ clipPath: `inset(0 ${100 - splitPosition}% 0 0)` }">
|
||||
<img ref="originalImageRef" :src="uploadedImageUrl" alt="原图" @load="adjustContainerSize" />
|
||||
<img ref="originalImageRef" :src="uploadedImageUrl" :alt="t('Original')" @load="adjustContainerSize" />
|
||||
</div>
|
||||
<div class="comparison-image result-image" :style="{ clipPath: `inset(0 0 0 ${splitPosition}%)` }">
|
||||
<img ref="resultImageRef" :src="resultImageUrl" alt="结果" @load="adjustContainerSize" />
|
||||
<img ref="resultImageRef" :src="resultImageUrl" :alt="t('Background Removed')" @load="adjustContainerSize" />
|
||||
</div>
|
||||
<div class="split-line" :class="{ dragging: isDraggingSplitLine }" :style="{ left: `${splitPosition}%` }" @mousedown.prevent.stop="handleSplitLineMouseDown">
|
||||
<div class="split-line-handle">
|
||||
@ -1040,11 +1040,11 @@ onUnmounted(() => {
|
||||
<div v-else class="single-image-view">
|
||||
<div class="image-wrapper" ref="singleImageWrapperRef">
|
||||
<div class="single-image-container">
|
||||
<img ref="singleImageRef" :src="uploadedImageUrl" alt="原图" @load="adjustContainerSize" />
|
||||
<img ref="singleImageRef" :src="uploadedImageUrl" :alt="t('Original')" @load="adjustContainerSize" />
|
||||
</div>
|
||||
<div v-if="processing" class="processing-overlay">
|
||||
<div class="spinner"></div>
|
||||
<p>处理中...</p>
|
||||
<p>{{ t('Processing...') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1057,7 +1057,7 @@ onUnmounted(() => {
|
||||
type="button"
|
||||
class="history-item add-button"
|
||||
@click.stop="triggerFileInput"
|
||||
title="添加新图片"
|
||||
:title="t('Add new image')"
|
||||
>
|
||||
<i class="fa fa-plus"></i>
|
||||
</button>
|
||||
@ -1075,8 +1075,8 @@ onUnmounted(() => {
|
||||
type="button"
|
||||
class="history-delete-btn"
|
||||
@click.stop="removeHistoryItem(index)"
|
||||
title="删除"
|
||||
:aria-label="'删除'"
|
||||
:title="t('Delete')"
|
||||
:aria-label="t('Delete')"
|
||||
></button>
|
||||
</div>
|
||||
</div>
|
||||
@ -1223,12 +1223,12 @@ onUnmounted(() => {
|
||||
|
||||
<div class="tool-page">
|
||||
<div class="page-header">
|
||||
<h2>去除背景</h2>
|
||||
<h2>{{ t('Remove Background') }}</h2>
|
||||
<div v-if="uploadedImage" class="toolbar-actions">
|
||||
<button v-if="resultImage" class="toolbar-btn" @click="handleDownload" title="下载">
|
||||
<button v-if="resultImage" class="toolbar-btn" @click="handleDownload" :title="t('Download')">
|
||||
<i class="fa fa-download"></i>
|
||||
</button>
|
||||
<button class="toolbar-btn" @click="resetUpload" title="更换图片">
|
||||
<button class="toolbar-btn" @click="resetUpload" :title="t('Change Image')">
|
||||
<i class="fa fa-refresh"></i>
|
||||
</button>
|
||||
</div>
|
||||
@ -1241,11 +1241,11 @@ onUnmounted(() => {
|
||||
<div class="upload-content">
|
||||
<button type="button" class="upload-btn" @click="triggerFileInput" :disabled="processing">
|
||||
<i class="fa fa-upload"></i>
|
||||
<span>上传图片</span>
|
||||
<span>{{ t('Upload Image') }}</span>
|
||||
</button>
|
||||
|
||||
<div class="divider">
|
||||
<span>或</span>
|
||||
<span>{{ t('or') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="url-input-wrapper" @click.stop>
|
||||
@ -1254,19 +1254,19 @@ onUnmounted(() => {
|
||||
v-model="imageUrl"
|
||||
type="text"
|
||||
class="url-input"
|
||||
placeholder="粘贴图片URL"
|
||||
:placeholder="t('Paste image URL here')"
|
||||
@keyup.enter="handleUrlSubmit"
|
||||
@paste="handleUrlPaste"
|
||||
:disabled="processing"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p class="upload-hint">拖放图片到任意位置,或直接粘贴图片</p>
|
||||
<p class="upload-format-hint">支持 JPG、PNG、WebP 格式</p>
|
||||
<p class="upload-hint">{{ t('Drag and drop your image anywhere, or paste image directly') }}</p>
|
||||
<p class="upload-format-hint">{{ t('Supports JPG, PNG, WebP formats') }}</p>
|
||||
</div>
|
||||
<div v-if="processing" class="upload-processing-overlay">
|
||||
<div class="spinner"></div>
|
||||
<p>加载图片URL中...</p>
|
||||
<p>{{ t('Loading image from URL...') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1274,10 +1274,10 @@ onUnmounted(() => {
|
||||
<div class="comparison-view" v-if="resultImage">
|
||||
<div class="comparison-container" ref="comparisonContainerRef">
|
||||
<div class="comparison-image original-image" :style="{ clipPath: `inset(0 ${100 - splitPosition}% 0 0)` }">
|
||||
<img ref="originalImageRef" :src="uploadedImageUrl" alt="原图" @load="adjustContainerSize" />
|
||||
<img ref="originalImageRef" :src="uploadedImageUrl" :alt="t('Original')" @load="adjustContainerSize" />
|
||||
</div>
|
||||
<div class="comparison-image result-image" :style="{ clipPath: `inset(0 0 0 ${splitPosition}%)` }">
|
||||
<img ref="resultImageRef" :src="resultImageUrl" alt="结果" @load="adjustContainerSize" />
|
||||
<img ref="resultImageRef" :src="resultImageUrl" :alt="t('Background Removed')" @load="adjustContainerSize" />
|
||||
</div>
|
||||
<div class="split-line" :class="{ dragging: isDraggingSplitLine }" :style="{ left: `${splitPosition}%` }" @mousedown.prevent.stop="handleSplitLineMouseDown">
|
||||
<div class="split-line-handle">
|
||||
@ -1289,11 +1289,11 @@ onUnmounted(() => {
|
||||
<div v-else class="single-image-view">
|
||||
<div class="image-wrapper" ref="singleImageWrapperRef">
|
||||
<div class="single-image-container">
|
||||
<img ref="singleImageRef" :src="uploadedImageUrl" alt="原图" @load="adjustContainerSize" />
|
||||
<img ref="singleImageRef" :src="uploadedImageUrl" :alt="t('Original')" @load="adjustContainerSize" />
|
||||
</div>
|
||||
<div v-if="processing" class="processing-overlay">
|
||||
<div class="spinner"></div>
|
||||
<p>处理中...</p>
|
||||
<p>{{ t('Processing...') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1306,7 +1306,7 @@ onUnmounted(() => {
|
||||
type="button"
|
||||
class="history-item add-button"
|
||||
@click.stop="triggerFileInput"
|
||||
title="添加新图片"
|
||||
:title="t('Add new image')"
|
||||
>
|
||||
<i class="fa fa-plus"></i>
|
||||
</button>
|
||||
@ -1324,8 +1324,8 @@ onUnmounted(() => {
|
||||
type="button"
|
||||
class="history-delete-btn"
|
||||
@click.stop="removeHistoryItem(index)"
|
||||
title="删除"
|
||||
:aria-label="'删除'"
|
||||
:title="t('Delete')"
|
||||
:aria-label="t('Delete')"
|
||||
></button>
|
||||
</div>
|
||||
</div>
|
||||
@ -1909,7 +1909,6 @@ onUnmounted(() => {
|
||||
font-weight: 600;
|
||||
color: #64748b;
|
||||
margin: 0 0 16px 0;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user