mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-08-31 04:57:41 +08:00
* feat(i18n): enhance locale handling and routing - Implemented dynamic locale aliases in router configuration. - Added support for preferred locale storage in global state. - Improved locale resolution logic in router beforeEach guard. - Created utility functions for locale management and path manipulation. - Added tests for locale matching and message extraction. - Updated Header component to allow language selection. - Refactored getRouterPathWithLang to utilize new locale utilities. - Updated Vite configuration to support aliasing for vue-i18n. - Bumped version numbers across various packages to 1.9.0. * feat(i18n): update version to 1.8.0 and enhance locale handling - Updated version numbers across all package.json files to 1.8.0. - Enhanced locale handling in App.vue by centralizing locale configurations. - Improved Turnstile component to support dynamic language rendering. - Refactored i18n utilities to include initial locale setup and empty locale messages. - Updated i18n.ts to utilize the new locale management structure. - Added naive-locale.ts for better integration with Naive UI's locale handling. - Adjusted Header.vue to streamline language selection and locale changes. - Fixed translations in multiple locale files for consistency and accuracy. * fix(i18n): address review feedback * feat(i18n): update default locale to English and enhance language handling in components * fix(i18n): switch locale selector to dropdown * docs: add topbar language and github order design spec * fix(i18n): 修复 Header 语言切换器相关问题,恢复为独立控件并调整样式 * Refactor locale handling in router and add locale-guard utility functions - Improved locale resolution logic in router by introducing utility functions for better readability and maintainability. - Added `locale-guard.js` to encapsulate locale-related functions such as getting route locale, resolving locale for navigation, and applying locale navigation state. - Updated JWT synchronization logic to streamline the handling of JWT from query parameters. - Modified i18n messages test to check for coverage of registered locale message keys instead of extracting English source messages. * 删除顶部栏语言和GitHub顺序设计文档 * fix: 修复前端设置初始化时未返回 domains 数组导致的 undefined 错误 * refactor(i18n): consolidate locale infrastructure * fix(i18n): stabilize locale route switching * fix(i18n): persist default locale selection * fix(i18n): 修复前端设置初始化时未返回 domains 数组导致的 undefined 错误,统一按空数组兜底处理 feat(i18n): 添加 locale 别名处理,支持默认语言的重定向 test(i18n): 增加对默认语言别名重定向的测试用例 * refactor: replace useAppI18n with useScopedI18n in multiple components for improved localization management * fix(tests): 移除不必要的 URL 断言以简化 Passkey 测试 * fix(i18n): 更新语言切换逻辑,确保使用当前语言设置进行路由导航 * fix(i18n): 强制路由切换以确保语言切换后正确导航 * refactor(i18n): 优化消息注册和路由本地化逻辑,移除冗余代码 * refactor(i18n): 拆分 API 文件以优化路由管理,更新语言处理逻辑 * fix: align i18n release notes and frontend test script
156 lines
4.8 KiB
Vue
156 lines
4.8 KiB
Vue
<script setup>
|
|
import {
|
|
darkTheme,
|
|
} from 'naive-ui'
|
|
import { computed, onMounted, watchEffect } from 'vue'
|
|
import { useScript } from '@unhead/vue'
|
|
import { useI18n } from 'vue-i18n'
|
|
import { useGlobalState } from './store'
|
|
import { useIsMobile } from './utils/composables'
|
|
import Header from './views/Header.vue';
|
|
import Footer from './views/Footer.vue';
|
|
import { api } from './api'
|
|
import { getNaiveLocaleConfig } from './i18n/naive-locale'
|
|
import { DEFAULT_LOCALE, isSupportedLocale } from './i18n/utils'
|
|
|
|
const {
|
|
isDark, loading, useSideMargin, telegramApp, isTelegram
|
|
} = useGlobalState()
|
|
const adClient = import.meta.env.VITE_GOOGLE_AD_CLIENT;
|
|
const adSlot = import.meta.env.VITE_GOOGLE_AD_SLOT;
|
|
const { locale } = useI18n({ useScope: 'global' });
|
|
const theme = computed(() => isDark.value ? darkTheme : null)
|
|
const localeConfig = computed(() => getNaiveLocaleConfig(isSupportedLocale(locale.value) ? locale.value : DEFAULT_LOCALE))
|
|
const isMobile = useIsMobile()
|
|
const showSideMargin = computed(() => !isMobile.value && useSideMargin.value);
|
|
const showAd = computed(() => !isMobile.value && adClient && adSlot);
|
|
const gridMaxCols = computed(() => showAd.value ? 8 : 12);
|
|
|
|
watchEffect(() => {
|
|
if (typeof document === 'undefined') return
|
|
document.documentElement.lang = isSupportedLocale(locale.value) ? locale.value : DEFAULT_LOCALE
|
|
})
|
|
|
|
// Load Google Ad script at top level (not inside onMounted)
|
|
if (showAd.value) {
|
|
useScript({
|
|
src: `https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${adClient}`,
|
|
async: true,
|
|
crossorigin: "anonymous",
|
|
})
|
|
}
|
|
|
|
onMounted(async () => {
|
|
try {
|
|
await api.getUserSettings();
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
|
|
const token = import.meta.env.VITE_CF_WEB_ANALY_TOKEN;
|
|
|
|
const exist = document.querySelector('script[src="https://static.cloudflareinsights.com/beacon.min.js"]') !== null
|
|
if (token && !exist) {
|
|
const script = document.createElement('script');
|
|
script.defer = true;
|
|
script.src = 'https://static.cloudflareinsights.com/beacon.min.js';
|
|
script.dataset.cfBeacon = `{ token: ${token} }`;
|
|
document.body.appendChild(script);
|
|
}
|
|
|
|
// check if google ad is enabled
|
|
if (showAd.value) {
|
|
(window.adsbygoogle = window.adsbygoogle || []).push({});
|
|
(window.adsbygoogle = window.adsbygoogle || []).push({});
|
|
}
|
|
|
|
|
|
// check if telegram is enabled
|
|
const enableTelegram = import.meta.env.VITE_IS_TELEGRAM;
|
|
if (
|
|
(typeof enableTelegram === 'boolean' && enableTelegram === true)
|
|
||
|
|
(typeof enableTelegram === 'string' && enableTelegram === 'true')
|
|
) {
|
|
await new Promise((resolve, reject) => {
|
|
const script = document.createElement('script');
|
|
script.src = 'https://telegram.org/js/telegram-web-app.js';
|
|
script.onload = resolve;
|
|
script.onerror = reject;
|
|
document.body.appendChild(script);
|
|
});
|
|
telegramApp.value = window.Telegram?.WebApp || {};
|
|
isTelegram.value = !!window.Telegram?.WebApp?.initData;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<n-config-provider :locale="localeConfig.locale" :date-locale="localeConfig.dateLocale" :theme="theme">
|
|
<n-global-style />
|
|
<n-spin description="loading..." :show="loading">
|
|
<n-notification-provider container-style="margin-top: 60px;">
|
|
<n-message-provider container-style="margin-top: 20px;">
|
|
<n-grid x-gap="12" :cols="gridMaxCols">
|
|
<n-gi v-if="showSideMargin" span="1">
|
|
<div class="side" v-if="showAd">
|
|
<ins class="adsbygoogle" style="display:block" :data-ad-client="adClient" :data-ad-slot="adSlot"
|
|
data-ad-format="auto" data-full-width-responsive="true"></ins>
|
|
</div>
|
|
</n-gi>
|
|
<n-gi :span="!showSideMargin ? gridMaxCols : (gridMaxCols - 2)">
|
|
<div class="main">
|
|
<n-space vertical>
|
|
<n-layout style="min-height: 80vh;">
|
|
<Header />
|
|
<router-view></router-view>
|
|
</n-layout>
|
|
<Footer />
|
|
</n-space>
|
|
</div>
|
|
</n-gi>
|
|
<n-gi v-if="showSideMargin" span="1">
|
|
<div class="side" v-if="showAd">
|
|
<ins class="adsbygoogle" style="display:block" :data-ad-client="adClient" :data-ad-slot="adSlot"
|
|
data-ad-format="auto" data-full-width-responsive="true"></ins>
|
|
</div>
|
|
</n-gi>
|
|
</n-grid>
|
|
<n-back-top />
|
|
</n-message-provider>
|
|
</n-notification-provider>
|
|
</n-spin>
|
|
</n-config-provider>
|
|
</template>
|
|
|
|
|
|
<style>
|
|
.n-switch {
|
|
margin-left: 10px;
|
|
margin-right: 10px;
|
|
}
|
|
</style>
|
|
|
|
<style scoped>
|
|
.side {
|
|
height: 100vh;
|
|
}
|
|
|
|
.main {
|
|
height: 100vh;
|
|
text-align: center;
|
|
}
|
|
|
|
.n-grid {
|
|
height: 100%;
|
|
}
|
|
|
|
.n-gi {
|
|
height: 100%;
|
|
}
|
|
|
|
.n-space {
|
|
height: 100%;
|
|
}
|
|
</style>
|