chore: restructure project and add i18n support
- Reorganize project structure with new electron and shared directories - Add comprehensive i18n support with Chinese, English, and Japanese locales - Update build configurations and TypeScript paths for new structure - Add various UI components including chat interface and task management - Include Windows release binaries and localization files - Update dependencies and fix import paths throughout the codebase
This commit is contained in:
106
src/i18n/index.ts
Normal file
106
src/i18n/index.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { createI18n, type I18n, type I18nOptions } from 'vue-i18n';
|
||||
import { SUPPORTED_LANGUAGE_CODES, SUPPORTED_LANGUAGES, NAMESPACES, type LanguageCode } from './constants';
|
||||
import { resolveSupportedLanguage, detectSystemLanguage } from './resolver';
|
||||
|
||||
// 使用 import.meta.glob 动态加载所有语言文件
|
||||
// 文件路径模式:./locales/{语言}/{命名空间}.json
|
||||
const modules = import.meta.glob('./locales/*/*.json', { eager: true });
|
||||
|
||||
// 构建 vue-i18n 格式的资源对象:{ [locale]: { [namespace]: messages } }
|
||||
function buildResources() {
|
||||
const resources: Record<string, Record<string, any>> = {};
|
||||
|
||||
// 初始化每种语言的空对象
|
||||
SUPPORTED_LANGUAGE_CODES.forEach(lang => {
|
||||
resources[lang] = {};
|
||||
});
|
||||
|
||||
// 遍历所有模块,按语言和命名空间组织
|
||||
for (const [path, module] of Object.entries(modules)) {
|
||||
// 路径示例:'./locales/en/common.json'
|
||||
const match = path.match(/\.\/locales\/([a-z]{2})\/([a-z]+)\.json$/);
|
||||
if (!match) continue;
|
||||
|
||||
const [, lang, namespace] = match;
|
||||
if (!SUPPORTED_LANGUAGE_CODES.includes(lang as LanguageCode) || !NAMESPACES.includes(namespace as any)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// @ts-expect-error: module 可能是 Module 类型
|
||||
const messages = (module as any).default || module;
|
||||
resources[lang][namespace] = messages;
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
// 获取持久化的语言设置(稍后由 Pinia store 提供)
|
||||
function getPersistedLanguage(): LanguageCode | null {
|
||||
try {
|
||||
const saved = localStorage.getItem('diona-language');
|
||||
return saved && SUPPORTED_LANGUAGE_CODES.includes(saved as LanguageCode) ? saved as LanguageCode : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 确定初始语言:持久化设置 > 系统语言 > 默认中文
|
||||
function determineInitialLocale(): LanguageCode {
|
||||
const persisted = getPersistedLanguage();
|
||||
if (persisted) return persisted;
|
||||
|
||||
const systemLang = detectSystemLanguage();
|
||||
return systemLang;
|
||||
}
|
||||
|
||||
async function createI18nInstance() {
|
||||
const resources = buildResources();
|
||||
const initialLocale = determineInitialLocale();
|
||||
|
||||
const options: I18nOptions = {
|
||||
legacy: false,
|
||||
locale: initialLocale,
|
||||
fallbackLocale: 'zh',
|
||||
messages: resources, // 使用构建的资源对象
|
||||
availableLocales: SUPPORTED_LANGUAGE_CODES,
|
||||
fallbackFormat: true,
|
||||
datetimeFormats: {},
|
||||
numberFormats: {},
|
||||
};
|
||||
|
||||
const i18n = createI18n(options);
|
||||
return i18n;
|
||||
}
|
||||
|
||||
// 创建 i18n 实例
|
||||
export const i18n = await createI18nInstance();
|
||||
|
||||
// 兼容性 API
|
||||
export async function setLanguage(lang: LanguageCode, _i18n?: I18n) {
|
||||
const __i18n = _i18n ?? i18n;
|
||||
|
||||
if (__i18n.mode === 'legacy') {
|
||||
__i18n.global.locale = lang;
|
||||
return;
|
||||
}
|
||||
|
||||
(__i18n.global.locale as unknown as { value: LanguageCode }).value = lang;
|
||||
|
||||
// 持久化到 localStorage(稍后由 Pinia store 处理)
|
||||
try {
|
||||
localStorage.setItem('diona-language', lang);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
export function getLanguage() {
|
||||
if (i18n.mode === 'legacy') {
|
||||
return i18n.global.locale;
|
||||
}
|
||||
|
||||
return (i18n.global.locale as unknown as { value: LanguageCode }).value;
|
||||
}
|
||||
|
||||
// 导出类型和常量
|
||||
export type { LanguageCode };
|
||||
export { SUPPORTED_LANGUAGE_CODES, SUPPORTED_LANGUAGES, NAMESPACES };
|
||||
export default i18n;
|
||||
Reference in New Issue
Block a user