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:
duanshuwen
2026-04-06 14:39:06 +08:00
parent e76b034d50
commit 6615d11dd6
311 changed files with 823682 additions and 4460 deletions

106
src/i18n/index.ts Normal file
View 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;