Skip to content

Commit 471c010

Browse files
fix(ui): invalid language crashes app
- Apparently locales must use hyphens instead of underscores. This must have been a fairly recent change that we didn't catch. It caused i18n to throw for Brasilian Portuguese and both Simplified and Traditional Mandarin. Change the locales to use the right strings. - Move the theme + locale provider inside of the error boundary. This allows errors with locals to be caught by the error boundary instead of hard-crashing the app. The error screen is unstyled if this happens but at least it has the reset button. - Add a migration for the system slice to fix existing users' language selections. For example, if the user had an incorrect language setting of `zh_CN`, it will be changed to the correct `zh-CN`.
1 parent b119302 commit 471c010

File tree

5 files changed

+22
-18
lines changed

5 files changed

+22
-18
lines changed

invokeai/frontend/web/src/app/components/App.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { memo, useCallback } from 'react';
1111
import { ErrorBoundary } from 'react-error-boundary';
1212

1313
import AppErrorBoundaryFallback from './AppErrorBoundaryFallback';
14+
import ThemeLocaleProvider from './ThemeLocaleProvider';
1415
const DEFAULT_CONFIG = {};
1516

1617
interface Props {
@@ -30,12 +31,14 @@ const App = ({ config = DEFAULT_CONFIG, studioInitAction }: Props) => {
3031

3132
return (
3233
<ErrorBoundary onReset={handleReset} FallbackComponent={AppErrorBoundaryFallback}>
33-
<Box id="invoke-app-wrapper" w="100dvw" h="100dvh" position="relative" overflow="hidden">
34-
<AppContent />
35-
{!didStudioInit && <Loading />}
36-
</Box>
37-
<GlobalHookIsolator config={config} studioInitAction={studioInitAction} />
38-
<GlobalModalIsolator />
34+
<ThemeLocaleProvider>
35+
<Box id="invoke-app-wrapper" w="100dvw" h="100dvh" position="relative" overflow="hidden">
36+
<AppContent />
37+
{!didStudioInit && <Loading />}
38+
</Box>
39+
<GlobalHookIsolator config={config} studioInitAction={studioInitAction} />
40+
<GlobalModalIsolator />
41+
</ThemeLocaleProvider>
3942
</ErrorBoundary>
4043
);
4144
};

invokeai/frontend/web/src/app/components/InvokeAIUI.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import { $socketOptions } from 'services/events/stores';
4242
import type { ManagerOptions, SocketOptions } from 'socket.io-client';
4343

4444
const App = lazy(() => import('./App'));
45-
const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider'));
4645

4746
interface Props extends PropsWithChildren {
4847
apiUrl?: string;
@@ -330,9 +329,7 @@ const InvokeAIUI = ({
330329
<React.StrictMode>
331330
<Provider store={store}>
332331
<React.Suspense fallback={<Loading />}>
333-
<ThemeLocaleProvider>
334-
<App config={config} studioInitAction={studioInitAction} />
335-
</ThemeLocaleProvider>
332+
<App config={config} studioInitAction={studioInitAction} />
336333
</React.Suspense>
337334
</Provider>
338335
</React.StrictMode>

invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsLanguageSelect.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ const optionsObject: Record<Language, string> = {
2626
nl: 'Nederlands',
2727
pl: 'Polski',
2828
pt: 'Português',
29-
pt_BR: 'Português do Brasil',
29+
'pt-BR': 'Português do Brasil',
3030
ru: 'Русский',
3131
sv: 'Svenska',
3232
tr: 'Türkçe',
3333
ua: 'Украї́нська',
3434
vi: 'Tiếng Việt',
35-
zh_CN: '简体中文',
36-
zh_Hant: '漢語',
35+
'zh-CN': '简体中文',
36+
'zh-Hant': '漢語',
3737
};
3838

3939
const options = map(optionsObject, (label, value) => ({ label, value }));

invokeai/frontend/web/src/features/system/store/systemSlice.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { uniq } from 'es-toolkit/compat';
99
import type { Language, SystemState } from './types';
1010

1111
const initialSystemState: SystemState = {
12-
_version: 1,
12+
_version: 2,
1313
shouldConfirmOnDelete: true,
1414
shouldAntialiasProgressImage: false,
1515
shouldConfirmOnNewSession: true,
@@ -96,6 +96,10 @@ const migrateSystemState = (state: any): any => {
9696
if (!('_version' in state)) {
9797
state._version = 1;
9898
}
99+
if (state._version === 1) {
100+
state.language = (state as SystemState).language.replace('_', '-');
101+
state._version = 2;
102+
}
99103
return state;
100104
};
101105

invokeai/frontend/web/src/features/system/store/types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ const zLanguage = z.enum([
1717
'nl',
1818
'pl',
1919
'pt',
20-
'pt_BR',
20+
'pt-BR',
2121
'ru',
2222
'sv',
2323
'tr',
2424
'ua',
2525
'vi',
26-
'zh_CN',
27-
'zh_Hant',
26+
'zh-CN',
27+
'zh-Hant',
2828
]);
2929
export type Language = z.infer<typeof zLanguage>;
3030
export const isLanguage = (v: unknown): v is Language => zLanguage.safeParse(v).success;
3131

3232
export interface SystemState {
33-
_version: 1;
33+
_version: 2;
3434
shouldConfirmOnDelete: boolean;
3535
shouldAntialiasProgressImage: boolean;
3636
shouldConfirmOnNewSession: boolean;

0 commit comments

Comments
 (0)