TechCorp/lib/i18n/useTranslation.ts
2025-09-16 17:40:37 +08:00

139 lines
4.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'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,
};
};