forked from Mirrors/elk
feat: install and configure i18n features (#177)
Co-authored-by: Shinigami <chrissi92@hotmail.de> Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe> Co-authored-by: Daniel Roe <daniel@roe.dev>
This commit is contained in:
parent
443bd65c05
commit
871076f2d9
9 changed files with 170 additions and 16 deletions
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
|
@ -10,5 +10,10 @@
|
|||
"cSpell.words": [
|
||||
"masto",
|
||||
"Nuxtodon"
|
||||
]
|
||||
],
|
||||
"i18n-ally.localesPaths": [
|
||||
"locales"
|
||||
],
|
||||
"i18n-ally.keystyle": "nested",
|
||||
"i18n-ally.sourceLanguage": "en-US"
|
||||
}
|
||||
|
|
|
@ -5,17 +5,20 @@ const buildTimeAgo = useTimeAgo(buildTime)
|
|||
|
||||
<template>
|
||||
<footer p4 text-sm text-secondary-light flex="~ col">
|
||||
<div flex="~ gap2">
|
||||
<button i-ri-sun-line dark:i-ri-moon-line text-lg mb4 @click="toggleDark()" />
|
||||
<div flex="~ gap2" items-center mb4>
|
||||
<button i-ri-sun-line dark:i-ri-moon-line text-lg @click="toggleDark()" />
|
||||
<button
|
||||
text-lg mb4
|
||||
text-lg
|
||||
:class="isZenMode ? 'i-ri:layout-right-2-line' : 'i-ri:layout-right-line'"
|
||||
@click="toggleZenMode()"
|
||||
/>
|
||||
<NavSelectLanguage />
|
||||
</div>
|
||||
<div>
|
||||
<button cursor-pointer hover:underline @click="openPreviewHelp">
|
||||
Show intro
|
||||
</button>
|
||||
</div>
|
||||
<div>A Mastodon client made with 🧡</div>
|
||||
<div>Built <time :datetime="buildTime" :title="buildTime">{{ buildTimeAgo }}</time> · <a href="https://github.com/elk-zone/elk" target="_blank">GitHub</a></div>
|
||||
</footer>
|
||||
|
|
|
@ -1,21 +1,27 @@
|
|||
<script lang="ts" setup>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav px3 py4 flex="~ col gap2" text-lg>
|
||||
<template v-if="currentUser">
|
||||
<NavSideItem text="Home" to="/home" icon="i-ri:home-5-line" />
|
||||
<NavSideItem text="Notifications" to="/notifications" icon="i-ri:notification-4-line" />
|
||||
<NavSideItem :text="t('nav_side.home')" to="/home" icon="i-ri:home-5-line" />
|
||||
<NavSideItem :text="t('nav_side.notifications')" to="/notifications" icon="i-ri:notification-4-line" />
|
||||
</template>
|
||||
<NavSideItem text="Explore" to="/explore" icon="i-ri:hashtag" />
|
||||
<NavSideItem text="Local" to="/public/local" icon="i-ri:group-2-line " />
|
||||
<NavSideItem text="Federated" to="/public" icon="i-ri:earth-line" />
|
||||
<NavSideItem :text="t('nav_side.explore')" to="/explore" icon="i-ri:hashtag" />
|
||||
<NavSideItem :text="t('nav_side.local')" to="/public/local" icon="i-ri:group-2-line " />
|
||||
<NavSideItem :text="t('nav_side.federated')" to="/public" icon="i-ri:earth-line" />
|
||||
<template v-if="currentUser">
|
||||
<NavSideItem text="Conversations" to="/conversations" icon="i-ri:at-line" />
|
||||
<NavSideItem text="Favourites" to="/favourites" icon="i-ri:heart-3-line" />
|
||||
<NavSideItem text="Bookmarks" to="/bookmarks" icon="i-ri:bookmark-line " />
|
||||
<NavSideItem :text="t('nav_side.conversations')" to="/conversations" icon="i-ri:at-line" />
|
||||
<NavSideItem :text="t('nav_side.favourites')" to="/favourites" icon="i-ri:heart-3-line" />
|
||||
<NavSideItem :text="t('nav_side.bookmarks')" to="/bookmarks" icon="i-ri:bookmark-line " />
|
||||
<NavSideItem :to="getAccountPath(currentUser.account)" icon="i-ri:list-check-2-line">
|
||||
<template #icon>
|
||||
<AccountAvatar :account="currentUser.account" h="1.2em" />
|
||||
</template>
|
||||
<ContentRich :content="getDisplayName(currentUser.account, { rich: true })" :emojis="currentUser.account.emojis" />
|
||||
<ContentRich :content="getDisplayName(currentUser.account, { rich: true }) || t('nav_side.profile')" :emojis="currentUser.account.emojis" />
|
||||
</NavSideItem>
|
||||
</template>
|
||||
</nav>
|
||||
|
|
36
components/nav/SelectLanguage.vue
Normal file
36
components/nav/SelectLanguage.vue
Normal file
|
@ -0,0 +1,36 @@
|
|||
<script lang="ts" setup>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { locale } = useI18n()
|
||||
const languageList = [
|
||||
{
|
||||
value: 'en-US',
|
||||
label: 'English',
|
||||
},
|
||||
{
|
||||
value: 'zh-CN',
|
||||
label: '简体中文',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CommonTooltip placement="bottom" content="Select Language">
|
||||
<CommonDropdown>
|
||||
<button align-top>
|
||||
<div i-ri:earth-line text-lg />
|
||||
</button>
|
||||
|
||||
<template #popper>
|
||||
<CommonDropdownItem
|
||||
v-for="item in languageList"
|
||||
:key="item.value"
|
||||
:checked="item.value === locale"
|
||||
@click="locale = item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</CommonDropdownItem>
|
||||
</template>
|
||||
</CommonDropdown>
|
||||
</CommonTooltip>
|
||||
</template>
|
13
locales/en-US.json
Normal file
13
locales/en-US.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"nav_side": {
|
||||
"home": "Home",
|
||||
"notifications": "Notifications",
|
||||
"explore": "Explore",
|
||||
"local": "Local",
|
||||
"federated": "Federated",
|
||||
"conversations": "Conversations",
|
||||
"favourites": "Favourites",
|
||||
"bookmarks": "Bookmarks",
|
||||
"profile": "Profile"
|
||||
}
|
||||
}
|
13
locales/zh-CN.json
Normal file
13
locales/zh-CN.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"nav_side": {
|
||||
"bookmarks": "书签",
|
||||
"conversations": "私信",
|
||||
"explore": "探索",
|
||||
"favourites": "喜欢",
|
||||
"federated": "跨站",
|
||||
"home": "主页",
|
||||
"local": "本地",
|
||||
"notifications": "通知",
|
||||
"profile": "个人资料"
|
||||
}
|
||||
}
|
|
@ -67,6 +67,7 @@
|
|||
"unplugin-auto-import": "^0.12.0",
|
||||
"vite-plugin-inspect": "^0.7.9",
|
||||
"vitest": "^0.25.3",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-safe-teleport": "^0.1.1",
|
||||
"vue-virtual-scroller": "2.0.0-beta.3"
|
||||
}
|
||||
|
|
25
plugins/i18n.ts
Normal file
25
plugins/i18n.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { createI18n } from 'vue-i18n'
|
||||
import enUS from '../locales/en-US.json'
|
||||
import zhCn from '../locales/zh-CN.json'
|
||||
|
||||
/** Default language environment */
|
||||
export const defaultLocale = 'en-US'
|
||||
|
||||
export const messages = {
|
||||
'en-US': enUS,
|
||||
'zh-CN': zhCn,
|
||||
}
|
||||
|
||||
/** Language Environment List */
|
||||
export const localeList = Object.keys(messages)
|
||||
|
||||
export default defineNuxtPlugin(({ vueApp }) => {
|
||||
const i18n = createI18n({
|
||||
legacy: false,
|
||||
globalInjection: true,
|
||||
locale: defaultLocale,
|
||||
messages,
|
||||
})
|
||||
|
||||
vueApp.use(i18n)
|
||||
})
|
|
@ -52,6 +52,7 @@ specifiers:
|
|||
unplugin-auto-import: ^0.12.0
|
||||
vite-plugin-inspect: ^0.7.9
|
||||
vitest: ^0.25.3
|
||||
vue-i18n: ^9.2.2
|
||||
vue-safe-teleport: ^0.1.1
|
||||
vue-virtual-scroller: 2.0.0-beta.3
|
||||
|
||||
|
@ -107,6 +108,7 @@ devDependencies:
|
|||
unplugin-auto-import: 0.12.0
|
||||
vite-plugin-inspect: 0.7.9
|
||||
vitest: 0.25.3
|
||||
vue-i18n: 9.2.2
|
||||
vue-safe-teleport: 0.1.1
|
||||
vue-virtual-scroller: 2.0.0-beta.3
|
||||
|
||||
|
@ -655,6 +657,44 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@intlify/core-base/9.2.2:
|
||||
resolution: {integrity: sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==}
|
||||
engines: {node: '>= 14'}
|
||||
dependencies:
|
||||
'@intlify/devtools-if': 9.2.2
|
||||
'@intlify/message-compiler': 9.2.2
|
||||
'@intlify/shared': 9.2.2
|
||||
'@intlify/vue-devtools': 9.2.2
|
||||
dev: true
|
||||
|
||||
/@intlify/devtools-if/9.2.2:
|
||||
resolution: {integrity: sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==}
|
||||
engines: {node: '>= 14'}
|
||||
dependencies:
|
||||
'@intlify/shared': 9.2.2
|
||||
dev: true
|
||||
|
||||
/@intlify/message-compiler/9.2.2:
|
||||
resolution: {integrity: sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==}
|
||||
engines: {node: '>= 14'}
|
||||
dependencies:
|
||||
'@intlify/shared': 9.2.2
|
||||
source-map: 0.6.1
|
||||
dev: true
|
||||
|
||||
/@intlify/shared/9.2.2:
|
||||
resolution: {integrity: sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==}
|
||||
engines: {node: '>= 14'}
|
||||
dev: true
|
||||
|
||||
/@intlify/vue-devtools/9.2.2:
|
||||
resolution: {integrity: sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==}
|
||||
engines: {node: '>= 14'}
|
||||
dependencies:
|
||||
'@intlify/core-base': 9.2.2
|
||||
'@intlify/shared': 9.2.2
|
||||
dev: true
|
||||
|
||||
/@ioredis/commands/1.2.0:
|
||||
resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
|
||||
dev: true
|
||||
|
@ -7865,6 +7905,18 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/vue-i18n/9.2.2:
|
||||
resolution: {integrity: sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==}
|
||||
engines: {node: '>= 14'}
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
dependencies:
|
||||
'@intlify/core-base': 9.2.2
|
||||
'@intlify/shared': 9.2.2
|
||||
'@intlify/vue-devtools': 9.2.2
|
||||
'@vue/devtools-api': 6.4.5
|
||||
dev: true
|
||||
|
||||
/vue-observe-visibility/2.0.0-alpha.1:
|
||||
resolution: {integrity: sha512-flFbp/gs9pZniXR6fans8smv1kDScJ8RS7rEpMjhVabiKeq7Qz3D9+eGsypncjfIyyU84saU88XZ0zjbD6Gq/g==}
|
||||
peerDependencies:
|
||||
|
|
Loading…
Reference in a new issue