feat: UI i18n depends on router (#289)

This commit is contained in:
Dream Hunter
2024-06-01 12:12:13 +08:00
committed by GitHub
parent 7a368d7b23
commit b792c196c1
38 changed files with 106 additions and 102 deletions

View File

@@ -9,18 +9,14 @@ import Footer from './views/Footer.vue';
const {
localeCache, isDark, loading, useSideMargin,
telegramApp, isTelegram
isDark, loading, useSideMargin, telegramApp, isTelegram
} = useGlobalState()
const { locale } = useI18n({});
const theme = computed(() => isDark.value ? darkTheme : null)
const localeConfig = computed(() => localeCache.value == 'zh' ? zhCN : null)
const localeConfig = computed(() => locale.value == 'zh' ? zhCN : null)
const isMobile = useIsMobile()
const showSideMargin = computed(() => !isMobile.value && useSideMargin.value);
const { locale } = useI18n({
useScope: 'global',
});
locale.value = localeCache.value;
onMounted(async () => {
const token = import.meta.env.VITE_CF_WEB_ANALY_TOKEN;

View File

@@ -1,6 +1,5 @@
<script setup>
import { watch, onMounted, ref, onBeforeUnmount } from "vue";
import { useRouter } from "vue-router";
import { useMessage } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { useGlobalState } from '../store'
@@ -10,7 +9,6 @@ import { processItem, getDownloadEmlUrl } from '../utils/email-parser'
const message = useMessage()
const isMobile = useIsMobile()
const router = useRouter()
const props = defineProps({
enableUserDeleteEmail: {
@@ -41,7 +39,7 @@ const props = defineProps({
})
const {
localeCache, isDark, mailboxSplitSize, indexTab,
isDark, mailboxSplitSize, indexTab,
useIframeShowMail, sendMailModel, preferShowTextMail
} = useGlobalState()
const autoRefresh = ref(false)
@@ -59,7 +57,6 @@ const curMail = ref(null);
const showTextMail = ref(preferShowTextMail.value)
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
success: 'Success',

View File

@@ -20,7 +20,7 @@ const props = defineProps({
},
})
const { localeCache, isDark, mailboxSplitSize } = useGlobalState()
const { isDark, mailboxSplitSize } = useGlobalState()
const data = ref([])
const count = ref(0)
@@ -31,7 +31,6 @@ const curMail = ref(null);
const showCode = ref(false)
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
success: 'Success',

View File

@@ -2,12 +2,11 @@
import { ref, watch, defineModel, onMounted } from "vue";
import { useI18n } from 'vue-i18n'
import { useGlobalState } from '../store'
const { localeCache, openSettings, isDark } = useGlobalState()
const { openSettings, isDark } = useGlobalState()
const cfToken = defineModel('value')
const { t } = useI18n({
locale: localeCache.value || 'zh',
const { locale, t } = useI18n({
messages: {
en: {
refresh: 'Refresh'
@@ -42,7 +41,7 @@ const checkCfTurnstile = async (remove) => {
"#cf-turnstile",
{
sitekey: openSettings.value.cfTurnstileSiteKey,
language: localeCache.value == 'zh' ? 'zh-CN' : 'en-US',
language: locale.value == 'zh' ? 'zh-CN' : 'en-US',
theme: isDark.value ? 'dark' : 'light',
callback: function (token) {
cfToken.value = token;

View File

@@ -17,6 +17,16 @@ const i18n = createI18n({
messages: {}
}
})
router.beforeEach((to, from) => {
if (to.params.lang) {
i18n.global.locale.value = to.params.lang
} else {
i18n.global.locale.value = 'zh'
}
});
const head = createHead()
const app = createApp(App)
app.use(i18n)

View File

@@ -1,26 +1,36 @@
import { createRouter, createWebHistory } from 'vue-router'
import Index from '../views/Index.vue'
import User from '../views/User.vue'
import { useGlobalState } from '../store'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
alias: "/:lang/",
component: Index
},
{
path: '/user',
alias: "/:lang/user",
component: User
},
{
path: '/admin',
alias: "/:lang/admin",
component: () => import('../views/Admin.vue')
},
{
path: '/telegram_mail',
alias: "/:lang/telegram_mail",
component: () => import('../views/telegram/Mail.vue')
},
{
name: 'not-found',
path: '/:pathMatch(.*)*',
redirect: '/'
}
]
})

View File

@@ -45,7 +45,6 @@ export const useGlobalState = createGlobalState(
const auth = useStorage('auth', '');
const adminAuth = useStorage('adminAuth', '');
const jwt = useStorage('jwt', '');
const localeCache = useStorage('locale', 'zh');
const adminTab = ref("account");
const adminMailTabAddress = ref("");
const adminSendBoxTabAddress = ref("");
@@ -82,7 +81,6 @@ export const useGlobalState = createGlobalState(
showAddressCredential,
auth,
jwt,
localeCache,
adminAuth,
showAdminAuth,
adminTab,

View File

@@ -1,6 +1,13 @@
export const hashPassword = async (password) => {
export const hashPassword = async (password: string) => {
// user crypto to hash password
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(password));
const hashArray = Array.from(new Uint8Array(digest));
return hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
}
export const getRouterPathWithLang = (path: string, lang: string) => {
if (!lang || lang === 'zh') {
return path;
}
return `/${lang}${path}`;
}

View File

@@ -21,7 +21,7 @@ import Telegram from './admin/Telegram.vue';
import Webhook from './admin/Webhook.vue';
const {
localeCache, adminAuth, showAdminAuth, adminTab, loading, globalTabplacement
adminAuth, showAdminAuth, adminTab, loading, globalTabplacement
} = useGlobalState()
const message = useMessage()
@@ -34,7 +34,6 @@ const authFunc = async () => {
}
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
accessHeader: 'Admin Password',

View File

@@ -1,11 +1,10 @@
<script setup>
import { useI18n } from 'vue-i18n'
import { useGlobalState } from '../store'
const { localeCache, openSettings } = useGlobalState()
const { openSettings } = useGlobalState()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
copyright: "Copyright"

View File

@@ -12,10 +12,12 @@ import { GithubAlt, Language, User, Home } from '@vicons/fa'
import { useGlobalState } from '../store'
import { api } from '../api'
import { getRouterPathWithLang } from '../utils'
const message = useMessage()
const {
localeCache, toggleDark, isDark, isTelegram,
toggleDark, isDark, isTelegram,
showAuth, adminAuth, auth, loading, openSettings
} = useGlobalState()
const route = useRoute()
@@ -37,13 +39,15 @@ const authFunc = async () => {
}
}
const changeLocale = (locale) => {
localeCache.value = locale;
location.reload()
const changeLocale = async (lang) => {
if (lang == 'zh') {
await router.push(route.fullPath.replace('/en', ''));
} else {
await router.push(`/${lang}${route.fullPath}`);
}
}
const { t } = useI18n({
locale: localeCache.value || 'zh',
const { locale, t } = useI18n({
messages: {
en: {
title: 'Cloudflare Temp Email',
@@ -80,7 +84,10 @@ const menuOptions = computed(() => [
size: "small",
type: menuValue.value == "home" ? "primary" : "default",
style: "width: 100%",
onClick: async () => { await router.push('/'); showMobileMenu.value = false; }
onClick: async () => {
await router.push(getRouterPathWithLang('/', locale.value));
showMobileMenu.value = false;
}
},
{
default: () => t('home'),
@@ -96,7 +103,10 @@ const menuOptions = computed(() => [
size: "small",
type: menuValue.value == "user" ? "primary" : "default",
style: "width: 100%",
onClick: async () => { await router.push("/user"); showMobileMenu.value = false; }
onClick: async () => {
await router.push(getRouterPathWithLang("/user", locale.value));
showMobileMenu.value = false;
}
},
{
default: () => t('user'),
@@ -114,7 +124,10 @@ const menuOptions = computed(() => [
size: "small",
type: menuValue.value == "admin" ? "primary" : "default",
style: "width: 100%",
onClick: async () => { await router.push('/admin'); showMobileMenu.value = false; }
onClick: async () => {
await router.push(getRouterPathWithLang('/admin', locale.value));
showMobileMenu.value = false;
}
},
{
default: () => "Admin",
@@ -149,13 +162,13 @@ const menuOptions = computed(() => [
text: true,
size: "small",
style: "width: 100%",
onClick: () => {
localeCache.value == 'zh' ? changeLocale('en') : changeLocale('zh');
onClick: async () => {
locale.value == 'zh' ? await changeLocale('en') : await changeLocale('zh');
showMobileMenu.value = false;
}
},
{
default: () => localeCache.value == 'zh' ? "English" : "中文",
default: () => locale.value == 'zh' ? "English" : "中文",
icon: () => h(
NIcon, { component: Language }
)

View File

@@ -14,10 +14,9 @@ import WenHook from './index/Webhook.vue';
import About from './common/About.vue';
const SendMail = defineAsyncComponent(() => import('./index/SendMail.vue'));
const { localeCache, settings, openSettings, indexTab, globalTabplacement } = useGlobalState()
const { settings, openSettings, indexTab, globalTabplacement } = useGlobalState()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
mailbox: 'Mail Box',

View File

@@ -9,11 +9,10 @@ import UserBar from './user/UserBar.vue';
import BindAddress from './user/BindAddress.vue';
const {
localeCache, userTab, globalTabplacement, userSettings
userTab, globalTabplacement, userSettings
} = useGlobalState()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
address_management: 'Address Management',

View File

@@ -9,13 +9,12 @@ import { NButton, NMenu } from 'naive-ui';
import { MenuFilled } from '@vicons/material'
const {
localeCache, adminAuth, showAdminAuth, loading,
adminAuth, showAdminAuth, loading,
adminTab, adminMailTabAddress, adminSendBoxTabAddress
} = useGlobalState()
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
name: 'Name',

View File

@@ -5,11 +5,10 @@ import { useI18n } from 'vue-i18n'
import { useGlobalState } from '../../store'
import { api } from '../../api'
const { localeCache, loading } = useGlobalState()
const { loading } = useGlobalState()
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
save: 'Save',

View File

@@ -6,12 +6,11 @@ import { useGlobalState } from '../../store'
import { api } from '../../api'
const {
localeCache, loading, openSettings,
loading, openSettings,
} = useGlobalState()
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
address: 'Address',

View File

@@ -7,12 +7,11 @@ import { api } from '../../api'
import MailBox from '../../components/MailBox.vue';
const {
localeCache, adminAuth, showAdminAuth,
adminAuth, showAdminAuth,
adminMailTabAddress
} = useGlobalState()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
addressQueryTip: 'Leave blank to query all addresses',

View File

@@ -6,7 +6,7 @@ import { CleaningServicesFilled } from '@vicons/material'
import { useGlobalState } from '../../store'
import { api } from '../../api'
const { localeCache, adminAuth, showAdminAuth } = useGlobalState()
const { adminAuth, showAdminAuth } = useGlobalState()
const message = useMessage()
const cleanupModel = ref({
enableMailsAutoCleanup: false,
@@ -20,7 +20,6 @@ const cleanupModel = ref({
})
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
tip: 'Please input the cleanup days',

View File

@@ -5,10 +5,9 @@ import { useGlobalState } from '../../store'
import { api } from '../../api'
import SendBox from '../../components/SendBox.vue';
const { localeCache, adminSendBoxTabAddress } = useGlobalState()
const { adminSendBoxTabAddress } = useGlobalState()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
query: 'Query',

View File

@@ -5,11 +5,10 @@ import { useI18n } from 'vue-i18n'
import { useGlobalState } from '../../store'
import { api } from '../../api'
const { localeCache, loading } = useGlobalState()
const { loading } = useGlobalState()
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
address: 'Address',

View File

@@ -7,11 +7,10 @@ import { SendOutlined } from '@vicons/material'
import { useGlobalState } from '../../store'
import { api } from '../../api'
const { localeCache, adminAuth } = useGlobalState()
const { adminAuth } = useGlobalState()
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
userCount: 'Account Count',

View File

@@ -6,13 +6,10 @@ import { useI18n } from 'vue-i18n'
import { useGlobalState } from '../../store'
// @ts-ignore
import { api } from '../../api'
const { localeCache } = useGlobalState()
// @ts-ignore
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
init: 'Init',

View File

@@ -8,11 +8,10 @@ import { useGlobalState } from '../../store'
import { api } from '../../api'
import { hashPassword } from '../../utils';
const { localeCache, loading } = useGlobalState()
const { loading } = useGlobalState()
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
success: 'Success',

View File

@@ -5,11 +5,10 @@ import { useI18n } from 'vue-i18n'
import { useGlobalState } from '../../store'
import { api } from '../../api'
const { localeCache, loading } = useGlobalState()
const { loading } = useGlobalState()
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
save: 'Save',

View File

@@ -6,13 +6,10 @@ import { useI18n } from 'vue-i18n'
import { useGlobalState } from '../../store'
// @ts-ignore
import { api } from '../../api'
const { localeCache } = useGlobalState()
// @ts-ignore
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
successTip: 'Success',

View File

@@ -1,10 +1,9 @@
<script setup>
import { useI18n } from 'vue-i18n'
import { useGlobalState } from '../../store'
const { localeCache, openSettings } = useGlobalState()
const { openSettings } = useGlobalState()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
adminContact: 'If you need help, please contact the administrator ({msg})',

View File

@@ -5,13 +5,12 @@ import { useIsMobile } from '../../utils/composables'
import { useGlobalState } from '../../store'
const {
localeCache, mailboxSplitSize, useIframeShowMail, preferShowTextMail,
mailboxSplitSize, useIframeShowMail, preferShowTextMail,
globalTabplacement, useSideMargin
} = useGlobalState()
const isMobile = useIsMobile()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
mailboxSplitSize: 'Mailbox Split Size',

View File

@@ -9,6 +9,7 @@ import Turnstile from '../../components/Turnstile.vue'
import { useGlobalState } from '../../store'
import { api } from '../../api'
import { getRouterPathWithLang } from '../../utils'
const props = defineProps({
bindUserAddress: {
@@ -36,7 +37,7 @@ const message = useMessage()
const router = useRouter()
const {
jwt, localeCache, loading, openSettings,
jwt, loading, openSettings,
showAddressCredential, userSettings
} = useGlobalState()
@@ -59,14 +60,13 @@ const login = async () => {
} catch (error) {
message.error(`${t('bindUserAddressError')}: ${error.message}`);
}
await router.push("/");
await router.push(getRouterPathWithLang("/", locale.value));
} catch (error) {
message.error(error.message || "error");
}
}
const { t } = useI18n({
locale: localeCache.value || 'zh',
const { locale, t } = useI18n({
messages: {
en: {
login: 'Login',
@@ -128,7 +128,7 @@ const newEmail = async () => {
);
jwt.value = res["jwt"];
await api.getSettings();
await router.push("/");
await router.push(getRouterPathWithLang("/", locale.value));
showAddressCredential.value = true;
try {
await props.bindUserAddress();

View File

@@ -6,17 +6,17 @@ import { useRouter } from 'vue-router'
import { useGlobalState } from '../../store'
import { api } from '../../api'
import Appearance from '../common/Appearance.vue'
import { getRouterPathWithLang } from '../../utils'
const {
jwt, localeCache, settings, showAddressCredential, loading
jwt, settings, showAddressCredential, loading
} = useGlobalState()
const router = useRouter()
const message = useMessage()
const showLogout = ref(false)
const showDelteAccount = ref(false)
const { t } = useI18n({
locale: localeCache.value || 'zh',
const { locale, t } = useI18n({
messages: {
en: {
logout: "Logout",
@@ -39,7 +39,7 @@ const { t } = useI18n({
const logout = async () => {
jwt.value = '';
await router.push('/')
await router.push(getRouterPathWithLang("/", locale.value))
location.reload()
}
@@ -49,7 +49,7 @@ const deleteAccount = async () => {
method: 'DELETE'
});
jwt.value = '';
await router.push('/')
await router.push(getRouterPathWithLang("/", locale.value))
location.reload()
} catch (error) {
message.error(error.message || "error");

View File

@@ -11,18 +11,18 @@ import Login from '../common/Login.vue'
import AddressManagement from '../user/AddressManagement.vue'
import TelegramAddress from './TelegramAddress.vue'
import LocalAddress from './LocalAddress.vue'
import { getRouterPathWithLang } from '../../utils'
const { toClipboard } = useClipboard()
const message = useMessage()
const router = useRouter()
const {
jwt, localeCache, settings, showAddressCredential, userJwt,
jwt, settings, showAddressCredential, userJwt,
isTelegram
} = useGlobalState()
const { t } = useI18n({
locale: localeCache.value || 'zh',
const { locale, t } = useI18n({
messages: {
en: {
addressManage: 'Address Manage',
@@ -62,6 +62,10 @@ const copy = async () => {
}
}
const onUserLogin = async () => {
await router.push(getRouterPathWithLang("/user", locale.value))
}
onMounted(async () => {
await api.getSettings();
});
@@ -104,7 +108,7 @@ onMounted(async () => {
</n-alert>
<Login />
<n-divider />
<n-button @click="router.push('/user')" type="primary" block secondary strong>
<n-button @click="onUserLogin" type="primary" block secondary strong>
<template #icon>
<n-icon :component="User" />
</template>

View File

@@ -9,12 +9,11 @@ import { useGlobalState } from '../../store'
// @ts-ignore
import Login from '../common/Login.vue';
const { localeCache, jwt } = useGlobalState()
const { jwt } = useGlobalState()
// @ts-ignore
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
tip: 'These addresses are stored in your browser, maybe loss if you clear the browser cache.',

View File

@@ -10,12 +10,11 @@ import { api } from '../../api'
// @ts-ignore
import Login from '../common/Login.vue';
const { localeCache, jwt, telegramApp } = useGlobalState()
const { jwt, telegramApp } = useGlobalState()
// @ts-ignore
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
success: 'success',

View File

@@ -7,12 +7,11 @@ import { useGlobalState } from '../../store'
// @ts-ignore
import { api } from '../../api'
const { localeCache, settings } = useGlobalState()
const { settings } = useGlobalState()
// @ts-ignore
const message = useMessage()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
successTip: 'Success',

View File

@@ -6,13 +6,13 @@ import { NBadge, NPopconfirm, NButton } from 'naive-ui'
import { useGlobalState } from '../../store'
import { api } from '../../api'
import { getRouterPathWithLang } from '../../utils'
const { localeCache, jwt } = useGlobalState()
const { jwt } = useGlobalState()
const message = useMessage()
const router = useRouter()
const { t } = useI18n({
locale: localeCache.value || 'zh',
const { locale, t } = useI18n({
messages: {
en: {
success: 'success',
@@ -48,7 +48,7 @@ const changeMailAddress = async (address_id) => {
return;
}
jwt.value = res.jwt;
await router.push('/');
await router.push(getRouterPathWithLang("/", locale.value))
location.reload();
} catch (error) {
console.log(error)

View File

@@ -6,10 +6,9 @@ import { useRouter } from 'vue-router'
import { useGlobalState } from '../../store'
import Login from '../common/Login.vue'
const { userJwt, localeCache, userSettings, } = useGlobalState()
const { userJwt, userSettings, } = useGlobalState()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
logout: 'Logout',

View File

@@ -11,11 +11,10 @@ const message = useMessage()
const router = useRouter()
const {
localeCache, userSettings, userJwt, userOpenSettings
userSettings, userJwt, userOpenSettings
} = useGlobalState()
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
currentUser: 'Current Login User',

View File

@@ -10,12 +10,11 @@ import { hashPassword } from '../../utils';
import Turnstile from '../../components/Turnstile.vue';
const { userJwt, localeCache, userTab, userOpenSettings } = useGlobalState()
const { userJwt, userTab, userOpenSettings } = useGlobalState()
const message = useMessage();
const router = useRouter();
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
login: 'Login',

View File

@@ -6,14 +6,13 @@ import { useRouter } from 'vue-router'
import { useGlobalState } from '../../store'
import { api } from '../../api'
const { userJwt, localeCache, userSettings, } = useGlobalState()
const { userJwt, userSettings, } = useGlobalState()
const router = useRouter()
const message = useMessage()
const showLogout = ref(false)
const { t } = useI18n({
locale: localeCache.value || 'zh',
messages: {
en: {
logout: 'Logout',