TechCorp/lib/i18n/useTranslation.ts

139 lines
4.6 KiB
TypeScript
Raw Permalink Normal View History

2025-09-16 17:40:37 +08:00
'use client';
import { useState, useEffect, useRef, useCallback } from 'react';
import { useRouter, usePathname, useSearchParams } from 'next/navigation';
import { Language, defaultLanguage } from './config';
import { getTranslation } from './translations';
import {
getLanguageFromPath,
removeLanguageFromPath,
addLanguageToPath,
getStoredLanguage,
setStoredLanguage,
getBrowserLanguage,
} from './utils';
export const useTranslation = (initialLanguage?: Language) => {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const isChangingLanguage = useRef(false);
const [language, setLanguage] = useState<Language>(() => {
if (initialLanguage) return initialLanguage;
return defaultLanguage;
});
const [isInitialized, setIsInitialized] = useState(false);
const t = getTranslation(language);
const changeLanguage = useCallback(
(newLanguage: Language) => {
if (isChangingLanguage.current) return;
isChangingLanguage.current = true;
setLanguage(newLanguage);
setStoredLanguage(newLanguage);
// 使用 setTimeout 来避免状态更新冲突
setTimeout(() => {
// 首页特殊处理,切换语言时加上 ?lang=xx
if (pathname === '/' || pathname === '') {
const url = newLanguage === defaultLanguage ? '/' : `/?lang=${newLanguage}`;
router.push(url);
}
// 产品页面特殊处理
else if (pathname === '/products') {
const url =
newLanguage === defaultLanguage
? '/products'
: `/products?lang=${newLanguage}`;
router.push(url);
}
// 新闻页面特殊处理
else if (pathname === '/news') {
const url =
newLanguage === defaultLanguage ? '/news' : `/news?lang=${newLanguage}`;
router.push(url);
}
// 其他页面保持原有逻辑
else {
const currentPath = removeLanguageFromPath(pathname);
const newPath = addLanguageToPath(currentPath, newLanguage);
if (newPath !== pathname) {
router.push(newPath);
}
}
// 重置标志
setTimeout(() => {
isChangingLanguage.current = false;
}, 100);
}, 0);
},
[pathname, router],
);
const getLocalizedPath = useCallback(
(path: string) => {
return addLanguageToPath(path, language);
},
[language],
);
// 初始化语言设置
useEffect(() => {
if (isInitialized || isChangingLanguage.current) return;
let detectedLanguage = defaultLanguage;
if (initialLanguage) {
detectedLanguage = initialLanguage;
} else {
// 首页和产品页面支持 ?lang=xx
const search = searchParams ? `?${searchParams.toString()}` : '';
const urlLanguage = getLanguageFromPath(pathname, search);
if (urlLanguage !== defaultLanguage) {
detectedLanguage = urlLanguage;
} else {
// 尝试从存储中获取语言
const storedLanguage = getStoredLanguage();
if (storedLanguage !== defaultLanguage) {
detectedLanguage = storedLanguage;
} else {
// 最后尝试浏览器语言
detectedLanguage = getBrowserLanguage();
}
}
}
if (detectedLanguage !== language) {
setLanguage(detectedLanguage);
}
setIsInitialized(true);
}, [initialLanguage, pathname, searchParams, language, isInitialized]);
// 监听URL变化但避免在语言切换过程中触发
useEffect(() => {
if (!isInitialized || isChangingLanguage.current) return;
const search = searchParams ? `?${searchParams.toString()}` : '';
const urlLanguage = getLanguageFromPath(pathname, search);
if (urlLanguage !== language) {
setLanguage(urlLanguage);
}
}, [pathname, searchParams, language, isInitialized]);
return {
language,
t,
changeLanguage,
getLocalizedPath,
isInitialized,
};
};