Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
P
poc-fe
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
poc
poc-fe
Commits
adb87977
Commit
adb87977
authored
Nov 06, 2024
by
tyyin lan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 多语言切换
parent
6f8d5ac9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
648 additions
and
60 deletions
+648
-60
settings.json
.vscode/settings.json
+2
-1
eslint.config.js
eslint.config.js
+1
-0
language-setting.vue
src/components/language-setting/language-setting.vue
+93
-0
sidebar.vue
src/layout/components/sidebar/sidebar.vue
+50
-39
index.ts
src/locales/index.ts
+4
-1
en.yaml
src/locales/langs/en.yaml
+390
-0
zh-cn.yaml
src/locales/langs/zh-cn.yaml
+1
-1
zh-hk.yaml
src/locales/langs/zh-hk.yaml
+1
-1
messages.ts
src/locales/messages.ts
+2
-0
system-language.ts
src/store/modules/system-language.ts
+80
-0
home.vue
src/views/home/home.vue
+1
-1
login.vue
src/views/login/login.vue
+22
-15
locales.d.ts
types/locales.d.ts
+1
-1
No files found.
.vscode/settings.json
View file @
adb87977
...
...
@@ -16,4 +16,5 @@
"src/locales/langs"
],
"i18n-ally.sourceLanguage"
:
"zh-cn"
,
}
"i18n-ally.keystyle"
:
"nested"
,
}
\ No newline at end of file
eslint.config.js
View file @
adb87977
...
...
@@ -25,6 +25,7 @@ export default [
ConversationMessageItem
:
'readonly'
,
ConversationMessageItemInfo
:
'readonly'
,
MittEvents
:
'readonly'
,
I18n
:
'readonly'
,
},
parser
:
vueParser
,
parserOptions
:
{
...
...
src/components/language-setting/language-setting.vue
0 → 100644
View file @
adb87977
<
script
setup
lang=
"ts"
>
import
{
useSystemLanguageStore
}
from
'@/store/modules/system-language'
import
{
ref
}
from
'vue'
import
{
useI18n
}
from
'vue-i18n'
import
{
Up
,
Translate
,
Down
}
from
'@icon-park/vue-next'
interface
Props
{
arrowDirection
:
'top'
|
'bottom'
btnBgColor
?:
string
}
const
{
arrowDirection
=
'bottom'
,
btnBgColor
=
'#f4f5f5'
}
=
defineProps
<
Props
>
()
const
systemLanguageStore
=
useSystemLanguageStore
()
const
{
locale
}
=
useI18n
()
const
isShowLanguagePopover
=
ref
(
false
)
function
handleLanguageOptionsUpdateShow
(
value
:
boolean
)
{
if
(
value
)
{
isShowLanguagePopover
.
value
=
true
}
else
{
isShowLanguagePopover
.
value
&&
(
isShowLanguagePopover
.
value
=
false
)
}
}
function
handleLanguageOptionSelect
(
key
:
I18n
.
LangType
)
{
systemLanguageStore
.
updateCurrentLanguageInfo
(
key
)
locale
.
value
=
key
isShowLanguagePopover
.
value
=
false
}
</
script
>
<
template
>
<n-popover
placement=
"bottom"
trigger=
"hover"
class=
"!p-[10px]"
:show-arrow=
"false"
:show=
"isShowLanguagePopover"
@
update:show=
"handleLanguageOptionsUpdateShow"
>
<template
#
trigger
>
<button
class=
"flex w-full items-center rounded-[6px] bg-[#f4f5f5] px-[12px] py-[6px] transition hover:bg-[#eceded]"
:style=
"
{ backgroundColor: btnBgColor }"
>
<Translate
theme=
"outline"
size=
"16"
fill=
"#000dff"
:stroke-width=
"3"
/>
<div
class=
"ml-[10px] flex flex-1 items-center justify-between"
>
<span>
{{
systemLanguageStore
.
currentLanguageInfo
.
label
}}
</span>
<Up
v-if=
"arrowDirection === 'top'"
class=
"transition-[rotate] duration-300 ease-in-out"
:class=
"
{ 'rotate-180': isShowLanguagePopover }"
theme="outline"
size="21"
fill="#333"
:stroke-width="3"
/>
<Down
v-else
theme=
"outline"
size=
"21"
fill=
"#333"
:stroke-width=
"3"
class=
"transition-[rotate] duration-300 ease-in-out"
:class=
"
{ 'rotate-180': isShowLanguagePopover }"
/>
</div>
</button>
</
template
>
<ul
class=
"select-none"
>
<li
v-for=
"langItem in systemLanguageStore.languageOptions"
:key=
"langItem.key"
class=
"relative mb-[6px] cursor-pointer bg-[#f3f3f5] px-[20px] py-[4px] text-center transition last:mb-0 hover:bg-[#e7e7e7]"
@
click=
"handleLanguageOptionSelect(langItem.key as I18n.LangType)"
>
{{ langItem.label }}
<i
v-show=
"langItem.key === systemLanguageStore.currentLanguageInfo.key"
class=
"iconfont icon-xuanze text-theme-color absolute bottom-0 right-0 text-[14px]"
></i>
</li>
</ul>
</n-popover>
</template>
src/layout/components/sidebar/sidebar.vue
View file @
adb87977
<
script
setup
lang=
"ts"
>
import
{
h
,
readonly
,
ref
,
shallowReadonly
,
watchEffect
}
from
'vue'
import
{
computed
,
h
,
ref
,
watchEffect
}
from
'vue'
import
{
useRoute
,
useRouter
}
from
'vue-router'
import
{
useI18n
}
from
'vue-i18n'
import
{
Plus
}
from
'@icon-park/vue-next'
import
type
{
MenuOption
}
from
'naive-ui'
import
CustomIcon
from
'@/components/custom-icon/custom-icon.vue'
import
{
useUserStore
}
from
'@/store/modules/user'
import
LanguageSetting
from
'@/components/language-setting/language-setting.vue'
const
{
t
}
=
useI18n
()
...
...
@@ -18,26 +19,30 @@ const defaultAvatar = 'https://gsst-poe-sit.gz.bcebos.com/data/20240910/17259529
const
currentMenuValue
=
ref
(
''
)
const
menuOptions
=
shallowReadonly
<
MenuOption
[]
>
([
{
label
:
()
=>
h
(
'div'
,
{},
t
(
'router_title_module.home'
)),
key
:
'Home'
,
icon
:
()
=>
h
(
'i'
,
{
class
:
'iconfont icon-home'
}),
},
{
label
:
()
=>
h
(
'div'
,
{},
t
(
'router_title_module.personal'
)),
key
:
'PersonalSpace'
,
icon
:
()
=>
h
(
'i'
,
{
class
:
'iconfont icon-personal'
}),
},
])
const
avatarOptions
=
readonly
([
{
label
:
()
=>
h
(
'div'
,
{},
t
(
'common_module.logout'
)),
key
:
'logout'
,
icon
:
()
=>
h
(
CustomIcon
,
{
icon
:
'teenyicons:logout-solid'
}),
},
])
const
menuOptions
=
computed
<
MenuOption
[]
>
(()
=>
{
return
[
{
label
:
()
=>
h
(
'div'
,
{},
t
(
'router_title_module.home'
)),
key
:
'Home'
,
icon
:
()
=>
h
(
'i'
,
{
class
:
'iconfont icon-home'
}),
},
{
label
:
()
=>
h
(
'div'
,
{},
t
(
'router_title_module.personal'
)),
key
:
'PersonalSpace'
,
icon
:
()
=>
h
(
'i'
,
{
class
:
'iconfont icon-personal'
}),
},
]
})
const
avatarOptions
=
computed
(()
=>
{
return
[
{
label
:
()
=>
h
(
'div'
,
{},
t
(
'common_module.logout'
)),
key
:
'logout'
,
icon
:
()
=>
h
(
CustomIcon
,
{
icon
:
'teenyicons:logout-solid'
}),
},
]
})
watchEffect
(()
=>
{
currentMenuValue
.
value
=
(
currentRoute
.
meta
.
belong
as
string
)
||
''
...
...
@@ -98,27 +103,33 @@ function handleMenuValueChange(key: string) {
</n-scrollbar>
</div>
<div
class=
"my-7 px-3"
>
<NDropdown
v-if=
"userStore.isLogin"
trigger=
"click"
placement=
"top-start"
:options=
"avatarOptions"
@
select=
"handleDropdownSelect"
>
<div
class=
"flex h-full cursor-pointer items-center"
>
<NAvatar
round
:size=
"40"
object-fit=
"cover"
:src=
"userStore.userInfo.avatarUrl || defaultAvatar"
/>
<div
class=
"ml-3 line-clamp-1 max-w-[140px] select-none break-all text-base"
>
{{
userStore
.
userInfo
.
nickName
||
t
(
'common_module.not_login_text'
)
}}
<div
class=
"mb-[20px] mt-6 px-[12px]"
>
<div>
<NDropdown
v-if=
"userStore.isLogin"
trigger=
"click"
placement=
"top-start"
:options=
"avatarOptions"
@
select=
"handleDropdownSelect"
>
<div
class=
"flex h-full cursor-pointer items-center"
>
<NAvatar
round
:size=
"40"
object-fit=
"cover"
:src=
"userStore.userInfo.avatarUrl || defaultAvatar"
/>
<div
class=
"ml-3 line-clamp-1 max-w-[140px] select-none break-all text-base"
>
{{
userStore
.
userInfo
.
nickName
||
t
(
'common_module.not_login_text'
)
}}
</div>
</div>
</NDropdown>
<div
v-else
>
<NButton
type=
"primary"
class=
"w-full! rounded-md!"
@
click=
"handleToLogin"
>
{{
t
(
'common_module.login_now'
)
}}
</NButton>
</div>
</
NDropdown
>
</
div
>
<div
v-else
>
<NButton
type=
"primary"
class=
"w-full! rounded-md!"
@
click=
"handleToLogin"
>
{{
t
(
'common_module.login_now'
)
}}
</NButton>
<div
class=
"mt-[10px]"
>
<LanguageSetting
arrow-direction=
"top"
/>
</div>
</div>
</div>
...
...
src/locales/index.ts
View file @
adb87977
import
{
type
App
}
from
'vue'
import
{
createI18n
}
from
'vue-i18n'
import
messages
from
'./messages'
import
{
ss
}
from
'@/utils/storage'
export
const
defaultLocale
=
'zh-CN'
const
i18n
=
createI18n
<
[
I18n
.
Schema
],
I18n
.
LangType
>
({
legacy
:
false
,
locale
:
'zh-CN'
,
locale
:
ss
.
get
(
'i18nextLng'
)
||
defaultLocale
,
fallbackLocale
:
'zh-HK'
,
messages
,
})
...
...
src/locales/langs/en.yaml
0 → 100644
View file @
adb87977
This diff is collapsed.
Click to expand it.
src/locales/langs/zh-cn.yaml
View file @
adb87977
...
...
@@ -116,7 +116,7 @@ home_module:
agent_welcome_message
:
'
Hi,
欢迎使用SuperLink'
agent_description
:
'
在这里,你可以体验多个平台的模型和专属的智能体'
currently_in_the_latest_session
:
'
当前已是最新会话'
switching_over
:
'
切换中
...
'
switching_over
:
'
切换中'
history_application_success
:
'
历史记录应用成功'
history_application_failed_please_try_again
:
'
历史记录应用失败,请重试'
starting_a_new_session
:
'
发起新会话'
...
...
src/locales/langs/zh-hk.yaml
View file @
adb87977
...
...
@@ -118,7 +118,7 @@ home_module:
agent_welcome_message
:
'
Hi,
歡迎使用SuperLink'
agent_description
:
'
在這裏,你可以體驗多個平臺的模型和專屬的智'
currently_in_the_latest_session
:
'
當前已是最新會話'
switching_over
:
'
切換中
...
'
switching_over
:
'
切換中'
history_application_success
:
'
歷史記錄應用成功'
history_application_failed_please_try_again
:
'
歷史記錄應用失敗,請重試'
starting_a_new_session
:
'
發起新會話'
...
...
src/locales/messages.ts
View file @
adb87977
import
zhHK
from
'./langs/zh-hk.yaml'
import
zhCN
from
'./langs/zh-cn.yaml'
import
en
from
'./langs/en.yaml'
const
messages
:
Record
<
I18n
.
LangType
,
I18n
.
Schema
>
=
{
'zh-HK'
:
zhHK
,
'zh-CN'
:
zhCN
,
en
,
}
export
default
messages
src/store/modules/system-language.ts
0 → 100644
View file @
adb87977
import
{
ss
}
from
'@/utils/storage'
import
{
defineStore
}
from
'pinia'
import
{
defaultLocale
}
from
'@/locales/index'
interface
SystemLanguageState
{
currentLanguageInfo
:
{
key
:
string
label
:
string
}
languageOptions
:
{
key
:
string
label
:
string
}[]
}
const
defaultLanguageOptions
=
[
{
label
:
'中文简体'
,
key
:
'zh-CN'
,
},
{
label
:
'中文繁體'
,
key
:
'zh-HK'
,
},
{
label
:
'English'
,
key
:
'en'
,
},
]
const
localeKey
=
ss
.
get
(
'i18nextLng'
)
||
defaultLocale
export
const
useSystemLanguageStore
=
defineStore
(
'system-language-store'
,
{
state
:
():
SystemLanguageState
=>
({
currentLanguageInfo
:
{
key
:
localeKey
,
label
:
defaultLanguageOptions
.
find
((
optionItem
)
=>
optionItem
.
key
===
localeKey
)
!
.
label
,
},
languageOptions
:
defaultLanguageOptions
,
}),
actions
:
{
updateCurrentLanguageInfo
(
key
:
I18n
.
LangType
)
{
if
(
this
.
currentLanguageInfo
.
key
===
key
)
return
''
ss
.
set
(
'i18nextLng'
,
key
)
this
.
currentLanguageInfo
=
this
.
languageOptions
.
find
((
optionItem
)
=>
optionItem
.
key
===
key
)
as
{
key
:
string
label
:
string
}
},
},
})
// export const useSystemLanguageStore = defineStore('system-language-store', () => {
// const currentLanguageInfo = ref({
// key: localeKey,
// label: defaultLanguageOptions.find((optionItem) => optionItem.key === localeKey)!.label,
// })
// const languageOptions = readonly(defaultLanguageOptions)
// function updateCurrentLanguageInfo(key: I18n.LangType) {
// if (currentLanguageInfo.value.key === key) return ''
// ss.set('i18nextLng', key)
// const { locale } = useI18n()
// locale.value = key
// currentLanguageInfo.value = defaultLanguageOptions.find((optionItem) => optionItem.key === key) as {
// key: string
// label: string
// }
// }
// return { currentLanguageInfo, languageOptions, updateCurrentLanguageInfo }
// })
src/views/home/home.vue
View file @
adb87977
...
...
@@ -150,7 +150,7 @@ function onHistoryRecordListUpdate() {
function
onGetMessageRecordList
(
recordId
:
string
)
{
currentSessionId
.
value
=
recordId
const
loadingCtl
=
window
.
$message
.
loading
(
t
(
'home_module.switching_over'
)
)
const
loadingCtl
=
window
.
$message
.
loading
(
`
${
t
(
'home_module.switching_over'
)}
...`
)
fetchMessageRecordList
<
{
...
...
src/views/login/login.vue
View file @
adb87977
<
script
setup
lang=
"ts"
>
import
{
ref
,
shallowReadonly
,
useTemplateRef
,
watchEffect
}
from
'vue'
import
{
computed
,
ref
,
shallowReadonly
,
useTemplateRef
,
watchEffect
}
from
'vue'
import
type
{
FormInst
,
FormRules
,
FormItemRule
,
CountdownInst
}
from
'naive-ui'
import
{
Mail
,
Lock
,
Iphone
,
Down
,
User
}
from
'@icon-park/vue-next'
import
isMobilePhone
from
'validator/es/lib/isMobilePhone'
...
...
@@ -11,6 +11,7 @@ import { useUserStore } from '@/store/modules/user'
import
type
{
UserInfo
}
from
'@/store/types/user'
import
{
useRouter
,
useRoute
}
from
'vue-router'
import
{
useI18n
}
from
'vue-i18n'
import
LanguageSetting
from
'@/components/language-setting/language-setting.vue'
enum
StorageKeyEnum
{
smsCountdownTime
=
'SMS_COUNTDOWN_TIME'
,
...
...
@@ -89,16 +90,18 @@ const emailLoginFormRules = shallowReadonly<FormRules>({
code
:
{
required
:
true
,
message
:
t
(
'login_module.please_enter_the_verification_code'
)
},
})
const
phoneNumberAreaOptions
=
shallowReadonly
([
{
label
:
`+86
${
t
(
'login_module.mainland_china'
)}
`
,
value
:
'+86'
,
},
{
label
:
`+852
${
t
(
'login_module.hong_kong_china'
)}
`
,
value
:
'+852'
,
},
])
const
phoneNumberAreaOptions
=
computed
(()
=>
{
return
[
{
label
:
`+86
${
t
(
'login_module.mainland_china'
)}
`
,
value
:
'+86'
,
},
{
label
:
`+852
${
t
(
'login_module.hong_kong_china'
)}
`
,
value
:
'+852'
,
},
]
})
const
currentPhoneNumberArea
=
ref
<
'+86'
|
'+852'
>
(
'+852'
)
const
countdownActive
=
ref
(
true
)
...
...
@@ -304,6 +307,10 @@ function handleEmailCodeGain() {
class=
"bg-px-logo-png z-100 absolute left-[60px] top-[25px] h-[29px] w-[119px] bg-contain bg-center bg-no-repeat"
></div>
<div
class=
"z-100 absolute right-[60px] top-[25px] w-[140px]"
>
<LanguageSetting
arrow-direction=
"bottom"
btn-bg-color=
"#f4f5f5"
/>
</div>
<div
class=
"absolute right-[14%] top-1/2 h-[458px] w-[390px] -translate-y-1/2"
>
<div
class=
"h-full w-full rounded-[10px] bg-[#fff] px-[29px] shadow-2xl"
...
...
@@ -412,9 +419,9 @@ function handleEmailCodeGain() {
>
<
template
#
suffix
>
<div
class=
"flex items-center"
>
<div
class=
"m
x-[6
px] h-[18px] w-[1px] bg-[#868686]"
></div>
<div
class=
"m
l-[6px] mr-[10
px] h-[18px] w-[1px] bg-[#868686]"
></div>
<div
class=
"
w-[90px]
text-end"
>
<div
class=
"text-end"
>
<n-button
v-show=
"!isShowCountdown"
class=
"!text-[11px]"
...
...
@@ -486,9 +493,9 @@ function handleEmailCodeGain() {
>
<
template
#
suffix
>
<div
class=
"flex items-center"
>
<div
class=
"m
x-[6
px] h-[18px] w-[1px] bg-[#868686]"
></div>
<div
class=
"m
l-[6px] mr-[10
px] h-[18px] w-[1px] bg-[#868686]"
></div>
<div
class=
"
w-[90px]
text-end"
>
<div
class=
"text-end"
>
<n-button
v-show=
"!isShowCountdown"
class=
"!text-[11px]"
...
...
types/locales.d.ts
View file @
adb87977
declare
namespace
I18n
{
type
LangType
=
'zh-HK'
|
'zh-CN'
type
LangType
=
'zh-HK'
|
'zh-CN'
|
'en'
type
Schema
=
{
common_module
:
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment