Skip to content

Commit 8d31ceb

Browse files
committed
refactor: i18n in sfc style
1 parent 12489b8 commit 8d31ceb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1541
-1403
lines changed

.vscode/settings.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,9 @@
7373
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
7474
},
7575
"i18n-ally.enabledFrameworks": [
76-
"vue"
76+
"vue-sfc"
7777
],
7878
"i18n-ally.localesPaths": [
79-
"frontend/src/locales"
80-
],
81-
"i18n-ally.keystyle": "nested"
79+
"frontend/src/**/*.vue"
80+
]
8281
}

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"vue-sonner": "^2.0.2"
3535
},
3636
"devDependencies": {
37+
"@intlify/unplugin-vue-i18n": "^6.0.8",
3738
"@types/node": "^22.16.5",
3839
"@vitejs/plugin-vue": "^6.0.1",
3940
"@vitejs/plugin-vue-jsx": "^5.0.1",

frontend/src/App.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ onUIOpened()
7575
<div class="text-center space-y-4">
7676
<div class="w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin mx-auto" />
7777
<p class="text-muted-foreground">
78-
{{ t('common.loading') }}
78+
{{ t('loading') }}
7979
</p>
8080
</div>
8181
</div>
@@ -94,7 +94,7 @@ onUIOpened()
9494
<Zap class="h-3 w-3" />
9595
</div>
9696
<h1 class="text-base font-semibold">
97-
{{ t('app.name') }}
97+
{{ t('appName') }}
9898
</h1>
9999
</div>
100100
</div>
@@ -109,6 +109,15 @@ onUIOpened()
109109
</div>
110110
</template>
111111

112+
<i18n lang="yaml">
113+
zh-CN:
114+
loading: 加载中...
115+
appName: UniToken
116+
en-US:
117+
loading: Loading...
118+
appName: UniToken
119+
</i18n>
120+
112121
<style>
113122
/* Global styles using UnoCSS */
114123
</style>

frontend/src/components/AddKeyDialog.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ async function handleConfigured(key: string) {
2222
<Dialog v-model:open="open">
2323
<DialogContent class="sm:max-w-2xl max-h-[90vh] overflow-y-auto">
2424
<DialogHeader>
25-
<DialogTitle>{{ t('keys.addKeyDialog.title') }}</DialogTitle>
25+
<DialogTitle>{{ t('title') }}</DialogTitle>
2626
<DialogDescription>
27-
{{ t('keys.addKeyDialog.description') }}
27+
{{ t('description') }}
2828
</DialogDescription>
2929
</DialogHeader>
3030

@@ -35,3 +35,12 @@ async function handleConfigured(key: string) {
3535
</DialogContent>
3636
</Dialog>
3737
</template>
38+
39+
<i18n lang="yaml">
40+
zh-CN:
41+
title: 添加 API Key
42+
description: 选择一个提供商来添加 API Key
43+
en-US:
44+
title: Add API Key
45+
description: Choose a provider to add API Key
46+
</i18n>

frontend/src/components/AppDetailDialog.vue

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ async function handleDeleteApp() {
2121
loading.value = true
2222
try {
2323
await appStore.deleteApp(props.app.id)
24-
toast.success(t('appDetailDialog.deleteSuccess'))
24+
toast.success(t('deleteSuccess'))
2525
open.value = false
2626
}
2727
catch (error) {
2828
console.error('Delete Failed:', error)
29-
toast.error(t('appDetailDialog.deleteFailed'))
29+
toast.error(t('deleteFailed'))
3030
}
3131
finally {
3232
loading.value = false
@@ -35,12 +35,12 @@ async function handleDeleteApp() {
3535
3636
function formatDate(dateString: string) {
3737
if (!dateString)
38-
return t('appDetailDialog.unknown')
38+
return t('unknown')
3939
try {
4040
return new Date(dateString).toLocaleString()
4141
}
4242
catch {
43-
return t('appDetailDialog.invalidDate')
43+
return t('invalidDate')
4444
}
4545
}
4646
</script>
@@ -49,7 +49,7 @@ function formatDate(dateString: string) {
4949
<Dialog v-model:open="open">
5050
<DialogContent class="max-w-md">
5151
<DialogHeader>
52-
<DialogTitle>{{ t('appDetailDialog.title') }}</DialogTitle>
52+
<DialogTitle>{{ t('title') }}</DialogTitle>
5353
</DialogHeader>
5454

5555
<div class="space-y-4">
@@ -61,14 +61,14 @@ function formatDate(dateString: string) {
6161
</div>
6262

6363
<p class="text-muted-foreground text-sm">
64-
{{ app.description || t('appDetailDialog.noDescription') }}
64+
{{ app.description || t('noDescription') }}
6565
</p>
6666
</div>
6767

6868
<div class="space-y-3 border-t pt-4">
6969
<div class="text-sm">
7070
<div>
71-
<span class="text-gray-500 dark:text-gray-200">{{ t('appDetailDialog.appId') }}:</span>
71+
<span class="text-gray-500 dark:text-gray-200">{{ t('appId') }}:</span>
7272
<p class="font-mono text-xs bg-gray-100 dark:bg-white/10 p-1 rounded mt-1 break-all">
7373
{{ app.id }}
7474
</p>
@@ -77,13 +77,13 @@ function formatDate(dateString: string) {
7777

7878
<div class="grid grid-cols-2 gap-4 text-sm">
7979
<div>
80-
<span class="text-gray-500">{{ t('appDetailDialog.createdAt') }}:</span>
80+
<span class="text-gray-500">{{ t('createdAt') }}:</span>
8181
<p class="mt-1">
8282
{{ formatDate(app.createdAt) }}
8383
</p>
8484
</div>
8585
<div v-if="app.lastActiveAt">
86-
<span class="text-gray-500">{{ t('appDetailDialog.lastActiveAt') }}:</span>
86+
<span class="text-gray-500">{{ t('lastActiveAt') }}:</span>
8787
<p class="mt-1">
8888
{{ formatDate(app.lastActiveAt) }}
8989
</p>
@@ -93,25 +93,25 @@ function formatDate(dateString: string) {
9393

9494
<div class="border-t border-red-200 dark:border-red-800 pt-4">
9595
<h4 class="text-sm font-medium text-red-800 dark:text-red-500 mb-2">
96-
{{ t('appDetailDialog.dangerZone') }}
96+
{{ t('dangerZone') }}
9797
</h4>
9898
<AlertDialog>
9999
<AlertDialogTrigger as-child>
100100
<Button variant="destructive" size="sm" class="w-full bg-red-600/70! hover:bg-red-600/60!" :disabled="loading">
101-
{{ t('appDetailDialog.deleteApp') }}
101+
{{ t('deleteApp') }}
102102
</Button>
103103
</AlertDialogTrigger>
104104
<AlertDialogContent>
105105
<AlertDialogHeader>
106-
<AlertDialogTitle>{{ t('appDetailDialog.confirmDeleteTitle') }}</AlertDialogTitle>
106+
<AlertDialogTitle>{{ t('confirmDeleteTitle') }}</AlertDialogTitle>
107107
<AlertDialogDescription>
108-
{{ t('appDetailDialog.confirmDeleteDescription', { appName: app.name }) }}
108+
{{ t('confirmDeleteDescription', { appName: app.name }) }}
109109
</AlertDialogDescription>
110110
</AlertDialogHeader>
111111
<AlertDialogFooter>
112-
<AlertDialogCancel>{{ t('common.cancel') }}</AlertDialogCancel>
112+
<AlertDialogCancel>{{ t('cancel') }}</AlertDialogCancel>
113113
<AlertDialogAction @click="handleDeleteApp">
114-
{{ t('common.delete') }}
114+
{{ t('delete') }}
115115
</AlertDialogAction>
116116
</AlertDialogFooter>
117117
</AlertDialogContent>
@@ -121,3 +121,40 @@ function formatDate(dateString: string) {
121121
</DialogContent>
122122
</Dialog>
123123
</template>
124+
125+
<i18n lang="yaml">
126+
en-US:
127+
title: Application Details
128+
noDescription: No description
129+
appId: Application ID
130+
createdAt: Created At
131+
lastActiveAt: Last Active
132+
unknown: Unknown
133+
invalidDate: Invalid Date
134+
dangerZone: Danger Zone
135+
deleteApp: Delete Application
136+
confirmDeleteTitle: Confirm Delete Application
137+
confirmDeleteDescription: |
138+
Are you sure you want to delete application "{appName}"? This action cannot
139+
be undone and all application data will be permanently deleted.
140+
deleteSuccess: Application deleted successfully
141+
deleteFailed: Failed to delete application
142+
delete: Delete
143+
cancel: Cancel
144+
zh-CN:
145+
title: 应用详细信息
146+
noDescription: 暂无描述
147+
appId: 应用ID
148+
createdAt: 创建时间
149+
lastActiveAt: 最后活跃
150+
unknown: 未知
151+
invalidDate: 无效日期
152+
dangerZone: 危险操作
153+
deleteApp: 删除应用
154+
confirmDeleteTitle: 确认删除应用
155+
confirmDeleteDescription: '您确定要删除应用 "{appName}" 吗?此操作不可撤销,应用的所有数据将被永久删除。'
156+
deleteSuccess: 应用删除成功
157+
deleteFailed: 删除应用失败
158+
delete: 删除
159+
cancel: 取消
160+
</i18n>

frontend/src/components/AppSidebar.vue

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,25 @@ const { t } = useI18n()
2929
</div>
3030
<div>
3131
<h1 class="text-lg font-semibold">
32-
{{ t('app.name') }}
32+
{{ t('appName') }}
3333
</h1>
3434
<p class="text-xs text-sidebar-foreground/70">
35-
{{ t('app.description') }}
35+
{{ t('appDescription') }}
3636
</p>
3737
</div>
3838
</div>
3939
</SidebarHeader>
4040

4141
<SidebarContent>
4242
<SidebarGroup>
43-
<SidebarGroupLabel>{{ t('navigation.title') }}</SidebarGroupLabel>
43+
<SidebarGroupLabel>{{ t('navigation') }}</SidebarGroupLabel>
4444
<SidebarGroupContent>
4545
<SidebarMenu>
4646
<SidebarMenuItem>
4747
<SidebarMenuButton as-child :is-active="$route.path === '/apps'">
4848
<router-link to="/apps" class="flex items-center gap-2">
4949
<Grid3X3 class="h-4 w-4" />
50-
<span>{{ t('navigation.appManagement') }}</span>
50+
<span>{{ t('appManagement') }}</span>
5151
</router-link>
5252
</SidebarMenuButton>
5353
</SidebarMenuItem>
@@ -56,7 +56,7 @@ const { t } = useI18n()
5656
<SidebarMenuButton as-child :is-active="$route.path === '/models'">
5757
<router-link to="/models" class="flex items-center gap-2">
5858
<Brain class="h-4 w-4" />
59-
<span>{{ t('navigation.models') }}</span>
59+
<span>{{ t('models') }}</span>
6060
</router-link>
6161
</SidebarMenuButton>
6262
</SidebarMenuItem>
@@ -65,7 +65,7 @@ const { t } = useI18n()
6565
<SidebarMenuButton as-child :is-active="$route.path === '/usage'">
6666
<router-link to="/usage" class="flex items-center gap-2">
6767
<BarChart3 class="h-4 w-4" />
68-
<span>{{ t('navigation.usage') }}</span>
68+
<span>{{ t('usage') }}</span>
6969
</router-link>
7070
</SidebarMenuButton>
7171
</SidebarMenuItem>
@@ -74,14 +74,14 @@ const { t } = useI18n()
7474
</SidebarGroup>
7575

7676
<SidebarGroup>
77-
<SidebarGroupLabel>{{ t('navigation.tools') }}</SidebarGroupLabel>
77+
<SidebarGroupLabel>{{ t('tools') }}</SidebarGroupLabel>
7878
<SidebarGroupContent>
7979
<SidebarMenu>
8080
<SidebarMenuItem>
8181
<SidebarMenuButton as-child :is-active="$route.path === '/settings'">
8282
<router-link to="/settings" class="flex items-center gap-2">
8383
<Settings class="h-4 w-4" />
84-
<span>{{ t('navigation.settings') }}</span>
84+
<span>{{ t('settings') }}</span>
8585
</router-link>
8686
</SidebarMenuButton>
8787
</SidebarMenuItem>
@@ -90,7 +90,7 @@ const { t } = useI18n()
9090
<SidebarMenuButton as-child :is-active="$route.path === '/about'">
9191
<router-link to="/about" class="flex items-center gap-2">
9292
<InfoIcon class="h-4 w-4" />
93-
<span>{{ t('navigation.about') }}</span>
93+
<span>{{ t('about') }}</span>
9494
</router-link>
9595
</SidebarMenuButton>
9696
</SidebarMenuItem>
@@ -110,3 +110,26 @@ const { t } = useI18n()
110110
</SidebarFooter>
111111
</Sidebar>
112112
</template>
113+
114+
<i18n lang="yaml">
115+
zh-CN:
116+
appName: UniToken
117+
appDescription: AI Token 聚合服务
118+
navigation: 导航
119+
appManagement: 应用管理
120+
models: 模型提供商
121+
usage: 用量统计
122+
tools: 工具
123+
settings: 设置
124+
about: 关于
125+
en-US:
126+
appName: UniToken
127+
appDescription: AI Token Aggregation Service
128+
navigation: Navigation
129+
appManagement: App Management
130+
models: Model Providers
131+
usage: Usage Statistics
132+
tools: Tools
133+
settings: Settings
134+
about: About
135+
</i18n>

frontend/src/components/Captcha.vue

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ function onClick() {
7474
}
7575
7676
const statusText = computed(() => ({
77-
loading: t('common.loading'),
78-
init: t('captcha.getCode'),
79-
pending: t('captcha.getCode'),
80-
success: t('captcha.smsSent'),
77+
loading: t('loading'),
78+
init: t('getCode'),
79+
pending: t('getCode'),
80+
success: t('smsSent'),
8181
})[state.value])
8282
</script>
8383

@@ -86,3 +86,15 @@ const statusText = computed(() => ({
8686
{{ statusText }}
8787
</button>
8888
</template>
89+
90+
<i18n lang="yaml">
91+
en-US:
92+
loading: Authenticating...
93+
getCode: Get Verification Code
94+
smsSent: Code Sent
95+
96+
zh-CN:
97+
loading: 加载中...
98+
getCode: 获取验证码
99+
smsSent: 已发送
100+
</i18n>

0 commit comments

Comments
 (0)