aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/main/src/i18n/I18nStore.ts16
-rw-r--r--packages/main/src/stores/MainStore.ts7
-rw-r--r--packages/renderer/src/devTools.ts9
-rw-r--r--packages/renderer/src/index.tsx4
-rw-r--r--packages/shared/src/schemas/Action.ts3
-rw-r--r--scripts/watch.js21
6 files changed, 54 insertions, 6 deletions
diff --git a/packages/main/src/i18n/I18nStore.ts b/packages/main/src/i18n/I18nStore.ts
index d833e8a..c364f0e 100644
--- a/packages/main/src/i18n/I18nStore.ts
+++ b/packages/main/src/i18n/I18nStore.ts
@@ -82,7 +82,12 @@ export default class I18nStore {
82 }; 82 };
83 83
84 const loadAsync = async () => { 84 const loadAsync = async () => {
85 await this.i18next.loadNamespaces([ns]); 85 try {
86 await this.i18next.loadNamespaces([ns]);
87 } catch (error) {
88 setImmediate(loaded);
89 throw error;
90 }
86 if (this.i18next.isInitialized) { 91 if (this.i18next.isInitialized) {
87 setImmediate(loaded); 92 setImmediate(loaded);
88 return; 93 return;
@@ -98,7 +103,14 @@ export default class I18nStore {
98 103
99 loadAsync().catch((error) => { 104 loadAsync().catch((error) => {
100 log.error('Failed to load translations for namespace', ns, error); 105 log.error('Failed to load translations for namespace', ns, error);
101 setImmediate(loaded);
102 }); 106 });
103 } 107 }
108
109 async reloadTranslations(): Promise<void> {
110 await this.i18next.reloadResources();
111 setImmediate(() => {
112 this.languageChangedAtom.reportChanged();
113 });
114 log.debug('Reloaded translations');
115 }
104} 116}
diff --git a/packages/main/src/stores/MainStore.ts b/packages/main/src/stores/MainStore.ts
index 873f998..93cabb9 100644
--- a/packages/main/src/stores/MainStore.ts
+++ b/packages/main/src/stores/MainStore.ts
@@ -96,6 +96,13 @@ const MainStore = types
96 case 'reload-all-services': 96 case 'reload-all-services':
97 self.services.forEach((service) => service.reload()); 97 self.services.forEach((service) => service.reload());
98 break; 98 break;
99 case 'reload-all-translations':
100 if (self.i18n !== undefined) {
101 self.i18n.reloadTranslations().catch((error) => {
102 log.error('Failed to reload translations', error);
103 });
104 }
105 break;
99 case 'dispatch-service-action': { 106 case 'dispatch-service-action': {
100 const { serviceId, serviceAction } = action; 107 const { serviceId, serviceAction } = action;
101 const service = self.shared.servicesById.get(serviceId); 108 const service = self.shared.servicesById.get(serviceId);
diff --git a/packages/renderer/src/devTools.ts b/packages/renderer/src/devTools.ts
index cb695c3..1fe39f7 100644
--- a/packages/renderer/src/devTools.ts
+++ b/packages/renderer/src/devTools.ts
@@ -52,13 +52,18 @@ export async function exposeToReduxDevtools(
52} 52}
53 53
54/** 54/**
55 * Sends a message to the main process to reload all services when 55 * Sends a message to the main process to reload all services or translations when
56 * `build/watch.js` sends a reload event on bundle write. 56 * `build/watch.js` sends a reload event on bundle write.
57 */ 57 */
58export function hotReloadServices(): void { 58export function hotReload(): void {
59 import.meta.hot?.on('sophie:reload-services', () => { 59 import.meta.hot?.on('sophie:reload-services', () => {
60 window.sophieRenderer.dispatchAction({ 60 window.sophieRenderer.dispatchAction({
61 action: 'reload-all-services', 61 action: 'reload-all-services',
62 }); 62 });
63 }); 63 });
64 import.meta.hot?.on('sophie:reload-translations', () => {
65 window.sophieRenderer.dispatchAction({
66 action: 'reload-all-translations',
67 });
68 });
64} 69}
diff --git a/packages/renderer/src/index.tsx b/packages/renderer/src/index.tsx
index e87ab8b..54e157c 100644
--- a/packages/renderer/src/index.tsx
+++ b/packages/renderer/src/index.tsx
@@ -30,7 +30,7 @@ import { render } from 'react-dom';
30import App from './components/App'; 30import App from './components/App';
31import StoreProvider from './components/StoreProvider'; 31import StoreProvider from './components/StoreProvider';
32import ThemeProvider from './components/ThemeProvider'; 32import ThemeProvider from './components/ThemeProvider';
33import { exposeToReduxDevtools, hotReloadServices } from './devTools'; 33import { exposeToReduxDevtools, hotReload } from './devTools';
34import { createAndConnectRendererStore } from './stores/RendererStore'; 34import { createAndConnectRendererStore } from './stores/RendererStore';
35import { getLogger } from './utils/log'; 35import { getLogger } from './utils/log';
36 36
@@ -39,7 +39,7 @@ const isDevelopment = import.meta.env.MODE === 'development';
39const log = getLogger('index'); 39const log = getLogger('index');
40 40
41if (isDevelopment) { 41if (isDevelopment) {
42 hotReloadServices(); 42 hotReload();
43} 43}
44 44
45const store = createAndConnectRendererStore(window.sophieRenderer); 45const store = createAndConnectRendererStore(window.sophieRenderer);
diff --git a/packages/shared/src/schemas/Action.ts b/packages/shared/src/schemas/Action.ts
index d5d0a8d..8d6ca3a 100644
--- a/packages/shared/src/schemas/Action.ts
+++ b/packages/shared/src/schemas/Action.ts
@@ -46,6 +46,9 @@ export const Action = /* @__PURE__ */ (() =>
46 action: z.literal('reload-all-services'), 46 action: z.literal('reload-all-services'),
47 }), 47 }),
48 z.object({ 48 z.object({
49 action: z.literal('reload-all-translations'),
50 }),
51 z.object({
49 action: z.literal('dispatch-service-action'), 52 action: z.literal('dispatch-service-action'),
50 serviceId: z.string(), 53 serviceId: z.string(),
51 serviceAction: ServiceAction, 54 serviceAction: ServiceAction,
diff --git a/scripts/watch.js b/scripts/watch.js
index 8ea5f29..be05f2b 100644
--- a/scripts/watch.js
+++ b/scripts/watch.js
@@ -191,6 +191,25 @@ function setupMainPackageWatcher(viteDevServer) {
191} 191}
192 192
193/** 193/**
194 * @param {(event: import('vite').HMRPayload) => void} sendEvent
195 */
196function setupTranslationsWatcher(sendEvent) {
197 const localesDir = path.join(thisDir, '../locales');
198 const watcher = watch(localesDir, {
199 ignored: /\.missing\.json$/,
200 ignoreInitial: true,
201 persistent: true,
202 });
203 watcher.on('change', () => {
204 console.log(`\u26A1 Reloading translations`);
205 sendEvent({
206 type: 'custom',
207 event: 'sophie:reload-translations',
208 });
209 });
210}
211
212/**
194 * @returns {Promise<void>} 213 * @returns {Promise<void>}
195 */ 214 */
196async function setupDevEnvironment() { 215async function setupDevEnvironment() {
@@ -246,6 +265,8 @@ async function setupDevEnvironment() {
246 return; 265 return;
247 } 266 }
248 267
268 setupTranslationsWatcher(sendEvent);
269
249 console.log('\uD83C\uDF80 Sophie is starting up'); 270 console.log('\uD83C\uDF80 Sophie is starting up');
250 await setupMainPackageWatcher(viteDevServer); 271 await setupMainPackageWatcher(viteDevServer);
251} 272}