Files
DndGamePlayer/app/renderer/editor/i18n/EditorI18nContext.tsx
T
Ivan Fontosh 2979d06f1c feat: multi-material overlays, presentation guides, and release prebuilds
Align control/presentation with presentation screen rect and darkness z-order; sync window titles and session window cleanup. Pack Win/Mac/Linux with npmRebuild disabled and release-native-prep for classic-level and sharp.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-03 11:28:18 +08:00

77 lines
2.4 KiB
TypeScript

import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import {
EDITOR_LOCALE_STORAGE_KEY,
inferEditorLocaleFromSystem,
normalizeEditorLocale,
translateEditorMessage,
type EditorLocale,
} from './editorMessages';
import { getDndApi } from '../../shared/dndApi';
import { ipcChannels } from '../../../shared/ipc/contracts';
type EditorI18nContextValue = {
locale: EditorLocale;
setLocale: (next: EditorLocale) => void;
t: (key: string, vars?: Record<string, string | number>) => string;
};
const EditorI18nContext = createContext<EditorI18nContextValue | null>(null);
function readInitialLocale(): EditorLocale {
try {
return normalizeEditorLocale(localStorage.getItem(EDITOR_LOCALE_STORAGE_KEY));
} catch {
return inferEditorLocaleFromSystem();
}
}
export function EditorI18nProvider({ children }: { children: React.ReactNode }) {
const [locale, setLocaleState] = useState<EditorLocale>(readInitialLocale);
const setLocale = useCallback((next: EditorLocale) => {
setLocaleState(next);
try {
localStorage.setItem(EDITOR_LOCALE_STORAGE_KEY, next);
} catch {
// ignore
}
}, []);
useEffect(() => {
const tag = locale === 'ru' ? 'ru-RU' : 'en-US';
try {
void getDndApi().invoke(ipcChannels.windows.syncChromeTitles, { localeTag: tag });
} catch {
// preload ещё не готов (редко при первом кадре)
}
}, [locale]);
// Другие окна Electron (пульт, материалы) подхватывают смену языка из редактора.
useEffect(() => {
const onStorage = (e: StorageEvent) => {
if (e.key !== EDITOR_LOCALE_STORAGE_KEY) return;
setLocaleState(normalizeEditorLocale(e.newValue));
};
window.addEventListener('storage', onStorage);
return () => window.removeEventListener('storage', onStorage);
}, []);
const t = useCallback(
(key: string, vars?: Record<string, string | number>) => translateEditorMessage(locale, key, vars),
[locale],
);
const value = useMemo<EditorI18nContextValue>(() => ({ locale, setLocale, t }), [locale, setLocale, t]);
return <EditorI18nContext.Provider value={value}>{children}</EditorI18nContext.Provider>;
}
export function useEditorI18n(): EditorI18nContextValue {
const ctx = useContext(EditorI18nContext);
if (!ctx) {
throw new Error('useEditorI18n must be used within EditorI18nProvider');
}
return ctx;
}