diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 35c51c9..ffea9ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1103,58 +1103,58 @@ packages: peerDependencies: vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 - '@unrs/rspack-resolver-binding-darwin-arm64@1.1.1': - resolution: {integrity: sha512-myn6gHyM77Y6XXGls9Wkfuu+yexGkmhPBDmBUkThrbkXtHq38vsr7o1Dyzruiqtt/okSs0tFF9P77kI6wWF9iQ==} + '@unrs/rspack-resolver-binding-darwin-arm64@1.1.2': + resolution: {integrity: sha512-bQx2L40UF5XxsXwkD26PzuspqUbUswWVbmclmUC+c83Cv/EFrFJ1JaZj5Q5jyYglKGOtyIWY/hXTCdWRN9vT0Q==} cpu: [arm64] os: [darwin] - '@unrs/rspack-resolver-binding-darwin-x64@1.1.1': - resolution: {integrity: sha512-A/5xK8zb8lJlom+mznrp9YA8lYzHjD2QcUdQ3PkWha8x996fPjSns4ilNYHW+eGXFcEAnfVwf78q9vYf59JJmA==} + '@unrs/rspack-resolver-binding-darwin-x64@1.1.2': + resolution: {integrity: sha512-dMi9a7//BsuPTnhWEDxmdKZ6wxQlPnAob8VSjefGbKX/a+pHfTaX1pm/jv2VPdarP96IIjCKPatJS/TtLQeGQA==} cpu: [x64] os: [darwin] - '@unrs/rspack-resolver-binding-freebsd-x64@1.1.1': - resolution: {integrity: sha512-Ew3bqEa8roijTPUS8xvb1X4K8S//rw6oDGKPhwQ8WoABVrrGZtMKlUEfH1+zBduJZtJAbpiDebFhh9OEoFM9Lw==} + '@unrs/rspack-resolver-binding-freebsd-x64@1.1.2': + resolution: {integrity: sha512-RiBZQ+LSORQObfhV1yH7jGz+4sN3SDYtV53jgc8tUVvqdqVDaUm1KA3zHLffmoiYNGrYkE3sSreGC+FVpsB4Vg==} cpu: [x64] os: [freebsd] - '@unrs/rspack-resolver-binding-linux-arm-gnueabihf@1.1.1': - resolution: {integrity: sha512-9Mm53MmrXQHfrUFotM19407A/9GjtdXyo9GkF7W1pb/ZXS7j7GTpruj8txWdaQrlxg0yjhjJst/xuNMbBFi1hQ==} + '@unrs/rspack-resolver-binding-linux-arm-gnueabihf@1.1.2': + resolution: {integrity: sha512-IyKIFBtOvuPCJt1WPx9e9ovTGhZzrIbW11vWzw4aPmx3VShE+YcMpAldqQubdCep0UVKZyFt+2hQDQZwFiJ4jg==} cpu: [arm] os: [linux] - '@unrs/rspack-resolver-binding-linux-arm64-gnu@1.1.1': - resolution: {integrity: sha512-yXs9e7hk7LzNT7LFwG6pxSnzVt6feC1SjFJM6naIRgFI8/4KngY8BUjM/Xx7rCS4Iz6FnCVIolpSrNqsRHpRrg==} + '@unrs/rspack-resolver-binding-linux-arm64-gnu@1.1.2': + resolution: {integrity: sha512-RfYtlCtJrv5i6TO4dSlpbyOJX9Zbhmkqrr9hjDfr6YyE5KD0ywLRzw8UjXsohxG1XWgRpb2tvPuRYtURJwbqWg==} cpu: [arm64] os: [linux] - '@unrs/rspack-resolver-binding-linux-arm64-musl@1.1.1': - resolution: {integrity: sha512-5i/Jq2Bb3He0JYCLOBzLxj+eX57rip2fOQUZX4i7H/ReZm9U64vVmWGNq7HlC0kNGo5AhGtRXCg5HbsBiBsyBw==} + '@unrs/rspack-resolver-binding-linux-arm64-musl@1.1.2': + resolution: {integrity: sha512-MaITzkoqsn1Rm3+YnplubgAQEfOt+2jHfFvuFhXseUfcfbxe8Zyc3TM7LKwgv7mRVjIl+/yYN5JqL0cjbnhAnQ==} cpu: [arm64] os: [linux] - '@unrs/rspack-resolver-binding-linux-x64-gnu@1.1.1': - resolution: {integrity: sha512-gAUWCEvtLGoKn2+dPrWXqE2xMfUjyvsUDa1+8yjKnyEqfGCyKcyaSSWkXq7k2VQnS5XxOThQJPPnZol4EOBxpw==} + '@unrs/rspack-resolver-binding-linux-x64-gnu@1.1.2': + resolution: {integrity: sha512-Nu981XmzQqis/uB3j4Gi3p5BYCd/zReU5zbJmjMrEH7IIRH0dxZpdOmS/+KwEk6ao7Xd8P2D2gDHpHD/QTp0aQ==} cpu: [x64] os: [linux] - '@unrs/rspack-resolver-binding-linux-x64-musl@1.1.1': - resolution: {integrity: sha512-o1Ik61ahhy+UHIWQB3t/kGwOUPmECbyXVuiW6D/ieKUWslspGE6qjFnyDxWqj9bDGsgjlbl/+O5QabXuAdUsJQ==} + '@unrs/rspack-resolver-binding-linux-x64-musl@1.1.2': + resolution: {integrity: sha512-xJupeDvaRpV0ADMuG1dY9jkOjhUzTqtykvchiU2NldSD+nafSUcMWnoqzNUx7HGiqbTMOw9d9xT8ZiFs+6ZFyQ==} cpu: [x64] os: [linux] - '@unrs/rspack-resolver-binding-wasm32-wasi@1.1.1': - resolution: {integrity: sha512-uGqUQlEe9NUtw/VQOVLpuEPD6RBNmdUoGSHH8lGfKI5B3xHZYZ7nhKW38JeAnK9IymFJQpsyMHZXAyFR+NK8iw==} + '@unrs/rspack-resolver-binding-wasm32-wasi@1.1.2': + resolution: {integrity: sha512-un6X/xInks+KEgGpIHFV8BdoODHRohaDRvOwtjq+FXuoI4Ga0P6sLRvf4rPSZDvoMnqUhZtVNG0jG9oxOnrrLQ==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@unrs/rspack-resolver-binding-win32-arm64-msvc@1.1.1': - resolution: {integrity: sha512-UfpkOv54SOqD/TyzGIVCPQHSuXIVjeIIbMqrhl06695Sjlu5ls4Wxq6nllofC3Igak4h5ovulGvLLH/GRMdVYQ==} + '@unrs/rspack-resolver-binding-win32-arm64-msvc@1.1.2': + resolution: {integrity: sha512-2lCFkeT1HYUb/OOStBS1m67aZOf9BQxRA+Wf/xs94CGgzmoQt7H4V/BrkB/GSGKsudXjkiwt2oHNkHiowAS90A==} cpu: [arm64] os: [win32] - '@unrs/rspack-resolver-binding-win32-x64-msvc@1.1.1': - resolution: {integrity: sha512-oBZjxVKfLVQxCdFDbafibNtJQKhT6DTW5FcNM25Vay86Yi7Mw4ftYg5NknR70WxM5qSNXIOgTHgzEUFfZ3Q7JA==} + '@unrs/rspack-resolver-binding-win32-x64-msvc@1.1.2': + resolution: {integrity: sha512-EYfya5HCQ/8Yfy7rvAAX2rGytu81+d/CIhNCbZfNKLQ690/qFsdEeTXRsMQW1afHoluMM50PsjPYu8ndy8fSQg==} cpu: [x64] os: [win32] @@ -3145,8 +3145,8 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - rspack-resolver@1.1.1: - resolution: {integrity: sha512-SwTjuIOS9jIYViQpYiDOmLTf/nuP6j9fz9VSxdNyIFiFaivEt6TOO5z0qQAwVloTz8RqjbPAzhVr1isiyHNRHw==} + rspack-resolver@1.1.2: + resolution: {integrity: sha512-eHhz+9JWHFdbl/CVVqEP6kviLFZqw1s0MWxLdsGMtUKUspSO3SERptPohmrUIC9jT1bGV9Bd3+r8AmWbdfNAzQ==} run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -4898,39 +4898,39 @@ snapshots: transitivePeerDependencies: - vue - '@unrs/rspack-resolver-binding-darwin-arm64@1.1.1': + '@unrs/rspack-resolver-binding-darwin-arm64@1.1.2': optional: true - '@unrs/rspack-resolver-binding-darwin-x64@1.1.1': + '@unrs/rspack-resolver-binding-darwin-x64@1.1.2': optional: true - '@unrs/rspack-resolver-binding-freebsd-x64@1.1.1': + '@unrs/rspack-resolver-binding-freebsd-x64@1.1.2': optional: true - '@unrs/rspack-resolver-binding-linux-arm-gnueabihf@1.1.1': + '@unrs/rspack-resolver-binding-linux-arm-gnueabihf@1.1.2': optional: true - '@unrs/rspack-resolver-binding-linux-arm64-gnu@1.1.1': + '@unrs/rspack-resolver-binding-linux-arm64-gnu@1.1.2': optional: true - '@unrs/rspack-resolver-binding-linux-arm64-musl@1.1.1': + '@unrs/rspack-resolver-binding-linux-arm64-musl@1.1.2': optional: true - '@unrs/rspack-resolver-binding-linux-x64-gnu@1.1.1': + '@unrs/rspack-resolver-binding-linux-x64-gnu@1.1.2': optional: true - '@unrs/rspack-resolver-binding-linux-x64-musl@1.1.1': + '@unrs/rspack-resolver-binding-linux-x64-musl@1.1.2': optional: true - '@unrs/rspack-resolver-binding-wasm32-wasi@1.1.1': + '@unrs/rspack-resolver-binding-wasm32-wasi@1.1.2': dependencies: '@napi-rs/wasm-runtime': 0.2.7 optional: true - '@unrs/rspack-resolver-binding-win32-arm64-msvc@1.1.1': + '@unrs/rspack-resolver-binding-win32-arm64-msvc@1.1.2': optional: true - '@unrs/rspack-resolver-binding-win32-x64-msvc@1.1.1': + '@unrs/rspack-resolver-binding-win32-x64-msvc@1.1.2': optional: true '@vitest/eslint-plugin@1.1.37(@typescript-eslint/utils@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)': @@ -5761,7 +5761,7 @@ snapshots: eslint-import-resolver-node: 0.3.9 get-tsconfig: 4.10.0 picomatch: 4.0.2 - rspack-resolver: 1.1.1 + rspack-resolver: 1.1.2 semver: 7.7.1 stable-hash: 0.0.5 tslib: 2.8.1 @@ -7672,19 +7672,19 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.35.0 fsevents: 2.3.3 - rspack-resolver@1.1.1: + rspack-resolver@1.1.2: optionalDependencies: - '@unrs/rspack-resolver-binding-darwin-arm64': 1.1.1 - '@unrs/rspack-resolver-binding-darwin-x64': 1.1.1 - '@unrs/rspack-resolver-binding-freebsd-x64': 1.1.1 - '@unrs/rspack-resolver-binding-linux-arm-gnueabihf': 1.1.1 - '@unrs/rspack-resolver-binding-linux-arm64-gnu': 1.1.1 - '@unrs/rspack-resolver-binding-linux-arm64-musl': 1.1.1 - '@unrs/rspack-resolver-binding-linux-x64-gnu': 1.1.1 - '@unrs/rspack-resolver-binding-linux-x64-musl': 1.1.1 - '@unrs/rspack-resolver-binding-wasm32-wasi': 1.1.1 - '@unrs/rspack-resolver-binding-win32-arm64-msvc': 1.1.1 - '@unrs/rspack-resolver-binding-win32-x64-msvc': 1.1.1 + '@unrs/rspack-resolver-binding-darwin-arm64': 1.1.2 + '@unrs/rspack-resolver-binding-darwin-x64': 1.1.2 + '@unrs/rspack-resolver-binding-freebsd-x64': 1.1.2 + '@unrs/rspack-resolver-binding-linux-arm-gnueabihf': 1.1.2 + '@unrs/rspack-resolver-binding-linux-arm64-gnu': 1.1.2 + '@unrs/rspack-resolver-binding-linux-arm64-musl': 1.1.2 + '@unrs/rspack-resolver-binding-linux-x64-gnu': 1.1.2 + '@unrs/rspack-resolver-binding-linux-x64-musl': 1.1.2 + '@unrs/rspack-resolver-binding-wasm32-wasi': 1.1.2 + '@unrs/rspack-resolver-binding-win32-arm64-msvc': 1.1.2 + '@unrs/rspack-resolver-binding-win32-x64-msvc': 1.1.2 run-parallel@1.2.0: dependencies: diff --git a/public/image/og-screenshot.png b/public/image/og-screenshot.png deleted file mode 100644 index 4ca8c30..0000000 Binary files a/public/image/og-screenshot.png and /dev/null differ diff --git a/src/components/Widgets/LanguageSwitcher.astro b/src/components/Widgets/LanguageSwitcher.astro index 805ddc1..55ef9a7 100644 --- a/src/components/Widgets/LanguageSwitcher.astro +++ b/src/components/Widgets/LanguageSwitcher.astro @@ -1,5 +1,5 @@ --- -import { getNextLangUrl, getNextSupportedLangUrl } from '@/i18n/path' +import { getNextGlobalLangPath, getNextSupportedLangPath } from '@/i18n/path' import { isPostPage, isTagPage } from '@/utils/page' interface Props { @@ -16,8 +16,8 @@ const useSupportedLangs = isPost || (isTag && supportedLangs.length > 0) // Choose a language switch list according to the page type const nextUrl = useSupportedLangs - ? getNextSupportedLangUrl(currentPath, supportedLangs) // Switch between supported languages - : getNextLangUrl(currentPath) // Switch between all languages + ? getNextSupportedLangPath(currentPath, supportedLangs) // Switch between supported languages + : getNextGlobalLangPath(currentPath) // Switch between all languages --- path.startsWith(`/${lang}/`), ) - return secondaryLang || defaultLocale + return currentLang || defaultLocale } -/** - * 获取下一个语言代码 - * @param currentLang 当前语言代码 - * @returns 下一个语言代码 - */ -export function getNextLang(currentLang: string): string { - // 获取默认语言和所有支持的语言 - // 直接使用导入的变量 - - // 找到当前语言在列表中的索引 +// Get the next language code in the global language cycle +export function getNextGlobalLang(currentLang: string): string { + // Get index of current language const currentIndex = allLocales.indexOf(currentLang) - - // 如果当前语言不在列表中,返回默认语言 if (currentIndex === -1) { return defaultLocale } - // 计算下一个语言的索引(循环) + // Calculate and return next language in cycle const nextIndex = (currentIndex + 1) % allLocales.length - - // 返回下一个语言代码 return allLocales[nextIndex] } - -/** - * 获取文章支持的语言 - * @param lang 文章的语言属性 - * @returns 支持的语言数组 - */ -export function getSupportedLangs(lang?: string): string[] { - // 直接使用导入的变量 - - // 如果指定了语言且不为空 - if (lang && typeof lang === 'string' && lang.trim() !== '') { - return [lang] - } - - // 否则返回所有支持的语言 - return allLocales -} diff --git a/src/i18n/path.ts b/src/i18n/path.ts index 191a993..8b83dbb 100644 --- a/src/i18n/path.ts +++ b/src/i18n/path.ts @@ -1,5 +1,5 @@ import { defaultLocale, moreLocales } from '@/config' -import { getLangFromPath, getNextLang } from '@/i18n/lang' +import { getLangFromPath, getNextGlobalLang } from '@/i18n/lang' import { cleanPath } from '@/utils/page' // Generates a localized path based on current language @@ -15,96 +15,67 @@ export function getLocalizedPath(path: string, currentLang?: string) { } /** - * 构建下一个语言的URL - * @param currentPath 当前页面路径 - * @param currentLang 当前语言代码 - * @param nextLang 下一个语言代码 - * @returns 下一个语言的URL + * Build path for next language + * @param currentPath Current page path + * @param currentLang Current language code + * @param nextLang Next language code to switch to + * @returns Path for next language */ -export function buildNextLangUrl(currentPath: string, currentLang: string, nextLang: string): string { - // 直接使用导入的变量 - let nextUrl = '' - - if (nextLang === defaultLocale) { - // 如果下一个是默认语言,移除语言代码 - nextUrl = currentPath.replace(`/${currentLang}`, '') || '/' - } - else { - // 如果当前是默认语言(没有语言代码在路径中) - if (currentLang === defaultLocale) { - // 在路径前添加新的语言代码 - nextUrl = `/${nextLang}${currentPath}` - } - else { - // 替换当前语言代码为新的语言代码 - nextUrl = currentPath.replace(`/${currentLang}`, `/${nextLang}`) - } - } - - // 确保URL格式正确 - if (nextUrl === '') - nextUrl = '/' - - // 确保非根路径的URL末尾有斜杠 - if (nextUrl !== '/' && !nextUrl.endsWith('/')) { - nextUrl = `${nextUrl}/` - } - - return nextUrl -} - -/** - * 直接从当前路径获取下一个语言的URL - * @param currentPath 当前页面路径 - * @returns 下一个语言的URL - */ -export function getNextLangUrl(currentPath: string): string { - // 从路径提取当前语言 - const currentLang = getLangFromPath(currentPath) - - // 获取下一个语言 - const nextLang = getNextLang(currentLang) - - // 构建下一个语言的URL - return buildNextLangUrl(currentPath, currentLang, nextLang) -} - -/** - * 根据支持的语言列表获取下一个语言的URL - * @param currentPath 当前路径 - * @param supportedLangs 文章支持的语言列表 - * @returns 下一个可用语言的URL - */ -export function getNextSupportedLangUrl(currentPath: string, supportedLangs: string[]): string { - // 从路径提取当前语言 - const currentLang = getLangFromPath(currentPath) - - // 如果没有提供支持的语言或列表为空,使用普通的语言切换 - if (!supportedLangs || supportedLangs.length === 0) { - return getNextLangUrl(currentPath) - } - - // 确保supportedLangs按照allLocales的顺序排序 - const sortedLangs = [...supportedLangs].sort((a, b) => { - // 使用导入的allLocales变量 - const allLocales = [defaultLocale, ...moreLocales] - return allLocales.indexOf(a) - allLocales.indexOf(b) - }) - - // 找到当前语言在支持的语言中的索引 - const currentIndex = sortedLangs.indexOf(currentLang) - - // 如果当前语言不在支持的语言中,或者路径是根路径,返回第一个支持的语言 - if (currentIndex === -1 || currentPath === '/') { - const nextLang = sortedLangs[0] - // 如果下一个语言是默认语言,返回根路径 +export function buildNextLangPath(currentPath: string, currentLang: string, nextLang: string): string { + if (currentPath === '/') { return nextLang === defaultLocale ? '/' : `/${nextLang}/` } - // 计算下一个语言的索引 - const nextIndex = (currentIndex + 1) % sortedLangs.length - const nextLang = sortedLangs[nextIndex] + // Build path based on language change + const nextPath = (() => { + if (nextLang === defaultLocale) { + return currentPath.replace(`/${currentLang}`, '') || '/' + } - // 构建下一个语言的URL - return buildNextLangUrl(currentPath, currentLang, nextLang) + if (currentLang === defaultLocale) { + return `/${nextLang}${currentPath}` + } + + return currentPath.replace(`/${currentLang}`, `/${nextLang}`) + })() + + return nextPath.endsWith('/') ? nextPath : `${nextPath}/` +} + +/** + * Get next language path from global language list + * @param currentPath Current page path + * @returns Path for next supported language + */ +export function getNextGlobalLangPath(currentPath: string): string { + const currentLang = getLangFromPath(currentPath) + const nextLang = getNextGlobalLang(currentLang) + return buildNextLangPath(currentPath, currentLang, nextLang) +} + +/** + * Get next language path from supported language list + * @param currentPath Current page path + * @param supportedLangs List of supported language codes + * @returns Path for next supported language + */ +export function getNextSupportedLangPath(currentPath: string, supportedLangs: string[]): string { + if (!supportedLangs.length) { + return getNextGlobalLangPath(currentPath) + } + + // Sort supported languages by global priority + const langPriority = new Map( + [defaultLocale, ...moreLocales].map((lang, index) => [lang, index]), + ) + const sortedLangs = [...supportedLangs].sort( + (a, b) => langPriority.get(a)! - langPriority.get(b)!, + ) + + // Get current language and next in cycle + const currentLang = getLangFromPath(currentPath) + const currentIndex = sortedLangs.indexOf(currentLang) + const nextLang = sortedLangs[(currentIndex + 1) % sortedLangs.length] + + return buildNextLangPath(currentPath, currentLang, nextLang) } diff --git a/src/layouts/Head.astro b/src/layouts/Head.astro index 209abc0..0446ed8 100644 --- a/src/layouts/Head.astro +++ b/src/layouts/Head.astro @@ -31,7 +31,7 @@ const pageImage = postSlug ? `${url}/og/${postSlug}.png` : apiflashKey ? `https://api.apiflash.com/v1/urltoimage?access_key=${apiflashKey}&url=${url}${langCode}&format=png&width=1500&height=788&ttl=86400&wait_until=network_idle&no_tracking=true` - : `/public/image/og-screenshot.png` + : `https://api.apiflash.com/v1/urltoimage?access_key=02a837b6188f4ba0a7fd9fbeff03a83e&url=https://retypeset.radishzz.cc${langCode}&format=png&width=1500&height=788&ttl=604800&wait_until=network_idle&no_tracking=true` --- diff --git a/src/utils/page.ts b/src/utils/page.ts index d26b5d1..b281c59 100644 --- a/src/utils/page.ts +++ b/src/utils/page.ts @@ -6,6 +6,7 @@ import { getLocalizedPath } from '@/i18n/path' export function cleanPath(path: string) { return path.replace(/^\/|\/$/g, '') } + // Checks if the current path is the home/post/tag/about page export function isHomePage(path: string) { const clean = cleanPath(path)