feat: implement task management store with IPC integration
- Added a new task store in `src-react/stores/task.ts` to manage tasks and their statuses. - Implemented functions for creating, executing, and retrying tasks, along with handling task progress and completion. - Introduced persistence for tasks using IPC. - Created utility functions for normalizing room types and building subtasks. - Added a new CSS file for global styles in `src-react/styles.css`. - Created runtime types in `src-react/types/runtime.ts` and exported them. - Updated the main entry points for Vue and React applications to support dynamic framework loading. - Refactored chat model interfaces and utility functions into `src/shared/chat-model.ts`. - Updated TypeScript configuration to include paths for React components and types. - Enhanced Vite configuration to support both Vue and React frameworks.
This commit is contained in:
107
src-react/i18n/index.ts
Normal file
107
src-react/i18n/index.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { DEFAULT_LANGUAGE } from '../lib/constants';
|
||||
import type { LanguageCode } from '../types/runtime';
|
||||
import type { Namespace } from './constants';
|
||||
import { detectSystemLanguage, resolveSupportedLanguage } from './resolver';
|
||||
import { messages, type MessageTree } from './messages';
|
||||
|
||||
type InterpolationParams = Record<string, string | number>;
|
||||
|
||||
function lookupMessage(source: MessageTree, path: string): unknown {
|
||||
return path.split('.').reduce<unknown>((current, segment) => {
|
||||
if (!current || typeof current !== 'object') return undefined;
|
||||
return (current as Record<string, unknown>)[segment];
|
||||
}, source);
|
||||
}
|
||||
|
||||
function interpolate(template: string, params?: InterpolationParams): string {
|
||||
if (!params) return template;
|
||||
|
||||
return template.replace(/\{(\w+)\}/g, (_match, token) => {
|
||||
const value = params[token];
|
||||
return typeof value === 'undefined' ? `{${token}}` : String(value);
|
||||
});
|
||||
}
|
||||
|
||||
export interface I18nBridge {
|
||||
getLocale(): LanguageCode;
|
||||
setLocale(locale: string | null | undefined): LanguageCode;
|
||||
t(path: string, params?: InterpolationParams): string;
|
||||
has(path: string): boolean;
|
||||
getMessages(locale?: LanguageCode): MessageTree;
|
||||
subscribe(listener: (locale: LanguageCode) => void): () => void;
|
||||
}
|
||||
|
||||
export function createI18nBridge(initialLocale?: string | null): I18nBridge {
|
||||
let locale = resolveSupportedLanguage(initialLocale ?? detectSystemLanguage() ?? DEFAULT_LANGUAGE);
|
||||
const listeners = new Set<(locale: LanguageCode) => void>();
|
||||
|
||||
const notify = () => {
|
||||
for (const listener of listeners) {
|
||||
listener(locale);
|
||||
}
|
||||
};
|
||||
|
||||
const api: I18nBridge = {
|
||||
getLocale() {
|
||||
return locale;
|
||||
},
|
||||
setLocale(nextLocale: string | null | undefined) {
|
||||
const resolved = resolveSupportedLanguage(nextLocale, locale);
|
||||
if (resolved !== locale) {
|
||||
locale = resolved;
|
||||
notify();
|
||||
}
|
||||
return locale;
|
||||
},
|
||||
t(path: string, params?: InterpolationParams) {
|
||||
const localeMessages = messages[locale] ?? messages[DEFAULT_LANGUAGE];
|
||||
const fallbackMessages = messages[DEFAULT_LANGUAGE];
|
||||
const translated = lookupMessage(localeMessages, path) ?? lookupMessage(fallbackMessages, path);
|
||||
|
||||
if (typeof translated === 'string' || typeof translated === 'number') {
|
||||
return interpolate(String(translated), params);
|
||||
}
|
||||
|
||||
return path;
|
||||
},
|
||||
has(path: string) {
|
||||
const localeMessages = messages[locale] ?? messages[DEFAULT_LANGUAGE];
|
||||
const fallbackMessages = messages[DEFAULT_LANGUAGE];
|
||||
return typeof lookupMessage(localeMessages, path) !== 'undefined' || typeof lookupMessage(fallbackMessages, path) !== 'undefined';
|
||||
},
|
||||
getMessages(targetLocale?: LanguageCode) {
|
||||
return messages[targetLocale ?? locale] ?? messages[DEFAULT_LANGUAGE];
|
||||
},
|
||||
subscribe(listener: (locale: LanguageCode) => void) {
|
||||
listeners.add(listener);
|
||||
return () => listeners.delete(listener);
|
||||
},
|
||||
};
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
export const i18n = createI18nBridge();
|
||||
|
||||
export function setLocale(locale: string | null | undefined): LanguageCode {
|
||||
return i18n.setLocale(locale);
|
||||
}
|
||||
|
||||
export function getLocale(): LanguageCode {
|
||||
return i18n.getLocale();
|
||||
}
|
||||
|
||||
export function t(path: string, params?: InterpolationParams): string {
|
||||
return i18n.t(path, params);
|
||||
}
|
||||
|
||||
export function hasMessage(path: string): boolean {
|
||||
return i18n.has(path);
|
||||
}
|
||||
|
||||
export function getMessages(locale?: LanguageCode): MessageTree {
|
||||
return i18n.getMessages(locale);
|
||||
}
|
||||
|
||||
export { SUPPORTED_LANGUAGE_CODES, SUPPORTED_LANGUAGES, NAMESPACES } from './constants';
|
||||
export type { LanguageCode, Namespace };
|
||||
Reference in New Issue
Block a user