mirror of
https://github.com/labring/FastGPT.git
synced 2026-02-28 01:02:28 +08:00
* feat(docs): enable i18n language selector * docs(i18n): translate introduction page to English * fix(i18n): fix language switching issue by always showing locale prefix * fix(docs): use relative paths for internal links to preserve language * refactor(i18n): add getLocalizedPath helper to simplify URL generation * refactor(i18n): make getLocalizedPath respect hideLocale config * feat(i18n): fallback to default language when translation missing, keep URL unchanged * feat(i18n): fix language loss in navigation and add language selector - Set hideLocale to 'never' to always show language prefix - Add localized-navigation.ts with useLocalizedRouter hook - Update all navigation points to preserve language: 1. Tab navigation (already using getLocalizedPath) 2. Sidebar navigation (handled by Fumadocs) 3. Home/404 redirects (using getLocalizedPath) 4. MDX Redirect component (using useLocalizedRouter) 5. Old page redirects (updated not-found.tsx) 6. Document links (custom LocalizedLink component) - Configure language selector in layout.config.tsx - Add LOCALIZED_NAVIGATION.md documentation * fix(i18n): fix type errors and useEffect dependencies * refactor(i18n): move redirects to middleware for SSR support - Move old path redirects from client-side (not-found.tsx) to server-side (middleware.ts) - Use 301 permanent redirects for better SEO - Preserve language prefix in redirects - Fix SSR issue caused by client-side redirects * refactor(i18n): clean up not-found.tsx, remove duplicate redirect maps - Remove duplicate exactMap and prefixMap (now in middleware) - Keep dynamic meta.json lookup for unknown pages - Simplify to only handle fallback cases - Two-layer approach: middleware (SSR) + not-found (dynamic) * refactor(i18n): simplify not-found to always redirect to introduction - Remove dynamic meta.json lookup - Always redirect to introduction page on 404 - Ensures no 404 pages are shown - Keep language prefix in redirect * fix(i18n): fix middleware type error with ts-expect-error - Add @ts-expect-error for Fumadocs middleware signature mismatch - Fix syntax error in config matcher (remove literal \n) --------- Co-authored-by: archer <archer@archerdeMac-mini.local>
68 lines
2.4 KiB
TypeScript
68 lines
2.4 KiB
TypeScript
import { createI18nMiddleware } from 'fumadocs-core/i18n';
|
|
import { i18n } from '@/lib/i18n';
|
|
import { NextRequest, NextResponse } from 'next/server';
|
|
|
|
// Old path redirects mapping
|
|
const exactMap: Record<string, string> = {
|
|
'/docs': '/docs/introduction',
|
|
'/docs/intro': '/docs/introduction',
|
|
'/docs/guide/dashboard/workflow/coreferenceresolution':
|
|
'/docs/introduction/guide/dashboard/workflow/coreferenceResolution',
|
|
'/docs/guide/admin/sso_dingtalk':
|
|
'/docs/introduction/guide/admin/sso#/docs/introduction/guide/admin/sso#钉钉',
|
|
'/docs/guide/knowledge_base/rag': '/docs/introduction/guide/knowledge_base/RAG',
|
|
'/docs/commercial/intro/': '/docs/introduction/commercial',
|
|
'/docs/upgrading/intro/': '/docs/upgrading',
|
|
'/docs/introduction/shopping_cart/intro/': '/docs/introduction/commercial'
|
|
};
|
|
|
|
const prefixMap: Record<string, string> = {
|
|
'/docs/development': '/docs/introduction/development',
|
|
'/docs/FAQ': '/docs/faq',
|
|
'/docs/guide': '/docs/introduction/guide',
|
|
'/docs/shopping_cart': '/docs/introduction/shopping_cart',
|
|
'/docs/agreement': '/docs/protocol',
|
|
'/docs/introduction/development/openapi': '/docs/openapi'
|
|
};
|
|
|
|
const i18nMiddleware = createI18nMiddleware(i18n);
|
|
|
|
export default function middleware(request: NextRequest) {
|
|
const { pathname } = request.nextUrl;
|
|
|
|
// Extract language from pathname
|
|
let lang = i18n.defaultLanguage;
|
|
let pathWithoutLang = pathname;
|
|
|
|
for (const language of i18n.languages) {
|
|
if (pathname.startsWith(`/${language}`)) {
|
|
lang = language;
|
|
pathWithoutLang = pathname.slice(`/${language}`.length);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Check exact match redirects
|
|
if (exactMap[pathWithoutLang]) {
|
|
const newUrl = new URL(`/${lang}${exactMap[pathWithoutLang]}`, request.url);
|
|
return NextResponse.redirect(newUrl, 301);
|
|
}
|
|
|
|
// Check prefix match redirects
|
|
for (const [oldPrefix, newPrefix] of Object.entries(prefixMap)) {
|
|
if (pathWithoutLang.startsWith(oldPrefix)) {
|
|
const rest = pathWithoutLang.slice(oldPrefix.length);
|
|
const newUrl = new URL(`/${lang}${newPrefix}${rest}`, request.url);
|
|
return NextResponse.redirect(newUrl, 301);
|
|
}
|
|
}
|
|
|
|
// Continue with i18n middleware
|
|
// @ts-expect-error - Fumadocs middleware signature mismatch
|
|
return i18nMiddleware(request);
|
|
}
|
|
|
|
export const config = {
|
|
matcher: ['/((?!api|_next/static|_next/image|favicon.ico|.*\\.svg|.*\\.png|deploy/.*).*)']
|
|
};
|