CloudTech/lib/i18n.ts
2025-09-16 18:00:27 +08:00

110 lines
3.1 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.

import { useState, useEffect } from 'react';
import { useParams, useRouter } from 'next/navigation';
type Locale = 'zh-CN' | 'zh-TW' | 'en';
interface TranslationData {
[key: string]: any;
}
const translations: Record<Locale, Record<string, TranslationData>> = {
'zh-CN': {},
'zh-TW': {},
en: {},
};
// Load translation files dynamically
const loadTranslations = async (locale: Locale, namespace: string): Promise<TranslationData> => {
if (translations[locale][namespace]) {
return translations[locale][namespace];
}
try {
const response = await fetch(`/locales/${locale}/${namespace}.json`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
translations[locale][namespace] = data;
return data;
} catch (error) {
console.error(`Failed to load translation: ${locale}/${namespace}`, error);
return {};
}
};
export const useTranslation = (namespace: string = 'common') => {
const params = useParams();
const router = useRouter();
const urlLocale = params?.locale as Locale;
const [locale, setLocale] = useState<Locale>(urlLocale || 'zh-CN');
const [translations, setTranslations] = useState<TranslationData>({});
const [loading, setLoading] = useState(true);
useEffect(() => {
// 如果URL中有locale参数优先使用URL中的语言
if (urlLocale && urlLocale !== locale) {
setLocale(urlLocale);
}
}, [urlLocale, locale]);
useEffect(() => {
const loadData = async () => {
setLoading(true);
const data = await loadTranslations(locale, namespace);
setTranslations(data);
setLoading(false);
};
loadData();
}, [locale, namespace]);
const changeLocale = (newLocale: Locale) => {
// 更新localStorage
localStorage.setItem('language', newLocale);
// 构建新的URL路径
const currentPath = window.location.pathname;
const pathWithoutLocale = currentPath.replace(/^\/[^\/]+/, '');
const newPath = `/${newLocale}${pathWithoutLocale}`;
// 导航到新的语言路径
router.push(newPath);
};
const t = (key: string, defaultValue?: string): string => {
const keys = key.split('.');
let value = translations;
for (const k of keys) {
if (value && typeof value === 'object' && k in value) {
value = value[k];
} else {
return defaultValue || key;
}
}
return typeof value === 'string' ? value : defaultValue || key;
};
return {
t,
locale,
setLocale: changeLocale,
loading,
};
};
// 语言切换工具函数
export const getLocalizedPath = (path: string, locale: Locale): string => {
return `/${locale}${path}`;
};
// 验证locale是否有效
export const isValidLocale = (locale: string): locale is Locale => {
return ['zh-CN', 'zh-TW', 'en'].includes(locale);
};
export type { Locale };