diff options
-rw-r--r-- | packages/main/esbuild.config.js | 12 | ||||
-rw-r--r-- | packages/main/package.json | 1 | ||||
-rw-r--r-- | packages/main/src/i18n/loadLocalization.ts | 11 | ||||
-rw-r--r-- | packages/main/src/i18n/synchronizeLocalizationSettings.ts | 99 | ||||
-rw-r--r-- | packages/main/src/initReactions.ts | 41 | ||||
-rw-r--r-- | packages/main/src/stores/SharedStore.ts | 3 | ||||
-rw-r--r-- | packages/main/types/importMeta.d.ts | 1 | ||||
-rw-r--r-- | packages/renderer/src/i18n/loadRendererLoalization.ts | 5 | ||||
-rw-r--r-- | packages/shared/src/index.ts | 4 | ||||
-rw-r--r-- | packages/shared/src/stores/GlobalSettingsBase.ts | 3 | ||||
-rw-r--r-- | packages/shared/src/stores/SharedStoreBase.ts | 4 | ||||
-rw-r--r-- | yarn.lock | 26 |
12 files changed, 183 insertions, 27 deletions
diff --git a/packages/main/esbuild.config.js b/packages/main/esbuild.config.js index 996ec5a..ae8565d 100644 --- a/packages/main/esbuild.config.js +++ b/packages/main/esbuild.config.js | |||
@@ -1,9 +1,15 @@ | |||
1 | import { readdir } from 'node:fs/promises'; | ||
2 | import path from 'node:path'; | ||
3 | |||
1 | import getRepoInfo from 'git-repo-info'; | 4 | import getRepoInfo from 'git-repo-info'; |
2 | 5 | ||
3 | import { node } from '../../config/buildConstants.js'; | 6 | import { node } from '../../config/buildConstants.js'; |
4 | import fileUrlToDirname from '../../config/fileUrlToDirname.js'; | 7 | import fileUrlToDirname from '../../config/fileUrlToDirname.js'; |
5 | import getEsbuildConfig from '../../config/getEsbuildConfig.js'; | 8 | import getEsbuildConfig from '../../config/getEsbuildConfig.js'; |
6 | 9 | ||
10 | /** @type {string} */ | ||
11 | const thisDir = fileUrlToDirname(import.meta.url); | ||
12 | |||
7 | const externalPackages = ['electron']; | 13 | const externalPackages = ['electron']; |
8 | 14 | ||
9 | if (process.env.MODE !== 'development') { | 15 | if (process.env.MODE !== 'development') { |
@@ -12,9 +18,12 @@ if (process.env.MODE !== 'development') { | |||
12 | 18 | ||
13 | const gitInfo = getRepoInfo(); | 19 | const gitInfo = getRepoInfo(); |
14 | 20 | ||
21 | /** @type {string[]} */ | ||
22 | const locales = await readdir(path.join(thisDir, '../../locales')); | ||
23 | |||
15 | export default getEsbuildConfig( | 24 | export default getEsbuildConfig( |
16 | { | 25 | { |
17 | absWorkingDir: fileUrlToDirname(import.meta.url), | 26 | absWorkingDir: thisDir, |
18 | entryPoints: ['src/index.ts'], | 27 | entryPoints: ['src/index.ts'], |
19 | outfile: 'dist/index.cjs', | 28 | outfile: 'dist/index.cjs', |
20 | format: 'cjs', | 29 | format: 'cjs', |
@@ -27,5 +36,6 @@ export default getEsbuildConfig( | |||
27 | GIT_SHA: gitInfo.abbreviatedSha, | 36 | GIT_SHA: gitInfo.abbreviatedSha, |
28 | GIT_BRANCH: gitInfo.branch, | 37 | GIT_BRANCH: gitInfo.branch, |
29 | BUILD_DATE: Date.now(), | 38 | BUILD_DATE: Date.now(), |
39 | SUPPORTED_LOCALES: locales, | ||
30 | }, | 40 | }, |
31 | ); | 41 | ); |
diff --git a/packages/main/package.json b/packages/main/package.json index 491e83a..c84816d 100644 --- a/packages/main/package.json +++ b/packages/main/package.json | |||
@@ -23,6 +23,7 @@ | |||
23 | "mobx-state-tree": "^5.1.3", | 23 | "mobx-state-tree": "^5.1.3", |
24 | "ms": "^2.1.3", | 24 | "ms": "^2.1.3", |
25 | "nanoid": "^3.3.2", | 25 | "nanoid": "^3.3.2", |
26 | "os-locale": "^6.0.2", | ||
26 | "os-name": "^5.0.1", | 27 | "os-name": "^5.0.1", |
27 | "slug": "^5.3.0" | 28 | "slug": "^5.3.0" |
28 | }, | 29 | }, |
diff --git a/packages/main/src/i18n/loadLocalization.ts b/packages/main/src/i18n/loadLocalization.ts index ec3cf84..0413373 100644 --- a/packages/main/src/i18n/loadLocalization.ts +++ b/packages/main/src/i18n/loadLocalization.ts | |||
@@ -18,33 +18,31 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { fallbackLng } from '@sophie/shared'; | 21 | import { FALLBACK_LOCALE } from '@sophie/shared'; |
22 | import i18next from 'i18next'; | 22 | import i18next from 'i18next'; |
23 | import { autorun } from 'mobx'; | 23 | import { autorun } from 'mobx'; |
24 | import { addDisposer } from 'mobx-state-tree'; | 24 | import { addDisposer } from 'mobx-state-tree'; |
25 | 25 | ||
26 | import type Resources from '../infrastructure/resources/Resources'; | ||
27 | import type MainStore from '../stores/MainStore'; | 26 | import type MainStore from '../stores/MainStore'; |
28 | import { getLogger } from '../utils/log'; | 27 | import { getLogger } from '../utils/log'; |
29 | 28 | ||
30 | import I18nStore from './I18nStore'; | 29 | import I18nStore from './I18nStore'; |
30 | import LocatlizationRepository from './LocalizationRepository'; | ||
31 | import RepositoryBasedI18nBackend from './RepositoryBasedI18nBackend'; | 31 | import RepositoryBasedI18nBackend from './RepositoryBasedI18nBackend'; |
32 | import i18nLog from './i18nLog'; | 32 | import i18nLog from './i18nLog'; |
33 | import LocalizationFiles from './impl/LocaltizationFiles'; | ||
34 | 33 | ||
35 | const log = getLogger('loadLocationzation'); | 34 | const log = getLogger('loadLocationzation'); |
36 | 35 | ||
37 | export default async function loadLocalization( | 36 | export default async function loadLocalization( |
38 | store: MainStore, | 37 | store: MainStore, |
39 | resources: Resources, | 38 | repository: LocatlizationRepository, |
40 | devMode: boolean, | 39 | devMode: boolean, |
41 | ): Promise<void> { | 40 | ): Promise<void> { |
42 | const repository = new LocalizationFiles(resources); | ||
43 | const backend = new RepositoryBasedI18nBackend(repository, devMode); | 41 | const backend = new RepositoryBasedI18nBackend(repository, devMode); |
44 | const i18n = i18next | 42 | const i18n = i18next |
45 | .createInstance({ | 43 | .createInstance({ |
46 | lng: store.shared.language, | 44 | lng: store.shared.language, |
47 | fallbackLng, | 45 | fallbackLng: [FALLBACK_LOCALE], |
48 | debug: devMode, | 46 | debug: devMode, |
49 | saveMissing: devMode, | 47 | saveMissing: devMode, |
50 | }) | 48 | }) |
@@ -58,6 +56,7 @@ export default async function loadLocalization( | |||
58 | shared: { language }, | 56 | shared: { language }, |
59 | } = store; | 57 | } = store; |
60 | if (i18n.language !== language) { | 58 | if (i18n.language !== language) { |
59 | log.debug('Setting language', language); | ||
61 | i18n.changeLanguage(language).catch((error) => { | 60 | i18n.changeLanguage(language).catch((error) => { |
62 | log.error('Failed to change language', error); | 61 | log.error('Failed to change language', error); |
63 | }); | 62 | }); |
diff --git a/packages/main/src/i18n/synchronizeLocalizationSettings.ts b/packages/main/src/i18n/synchronizeLocalizationSettings.ts new file mode 100644 index 0000000..971a593 --- /dev/null +++ b/packages/main/src/i18n/synchronizeLocalizationSettings.ts | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com> | ||
3 | * | ||
4 | * This file is part of Sophie. | ||
5 | * | ||
6 | * Sophie is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Affero General Public License as | ||
8 | * published by the Free Software Foundation, version 3. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * SPDX-License-Identifier: AGPL-3.0-only | ||
19 | */ | ||
20 | |||
21 | import { FALLBACK_LOCALE, SYSTEM_LOCALE } from '@sophie/shared'; | ||
22 | import { reaction } from 'mobx'; | ||
23 | import { addDisposer } from 'mobx-state-tree'; | ||
24 | |||
25 | import type MainStore from '../stores/MainStore'; | ||
26 | import { getLogger } from '../utils/log'; | ||
27 | |||
28 | const log = getLogger('synchronizeLocalizationSettings'); | ||
29 | |||
30 | export const TEST_LOCALE = 'cimode'; | ||
31 | |||
32 | /** | ||
33 | * Finds the closes requested supported language for the requested one. | ||
34 | * | ||
35 | * If `language` is supported, this function will return it. | ||
36 | * Otherwise, it returns a supported language with the same ISO639 code but | ||
37 | * no country code (e.g., `en` for `en-GB`) if it exists. | ||
38 | * If no supported language matches, `FALLBACK_LOCALE` will be returned. | ||
39 | * | ||
40 | * @param language The requested language. | ||
41 | * @param supportedLanguages The set of supported languages. | ||
42 | * @returns The language to load. | ||
43 | */ | ||
44 | function getMatchingLocale( | ||
45 | language: string, | ||
46 | supportedLanguages: Set<string>, | ||
47 | ): string { | ||
48 | // Also let the test locale (i.e., show localization keys directly) through. | ||
49 | if (language === TEST_LOCALE || supportedLanguages.has(language)) { | ||
50 | return language; | ||
51 | } | ||
52 | const separatorIndex = language.indexOf('-'); | ||
53 | if (separatorIndex < 0) { | ||
54 | return FALLBACK_LOCALE; | ||
55 | } | ||
56 | const iso639 = language.slice(0, Math.max(0, separatorIndex)); | ||
57 | if (supportedLanguages.has(iso639)) { | ||
58 | return iso639; | ||
59 | } | ||
60 | return FALLBACK_LOCALE; | ||
61 | } | ||
62 | |||
63 | export async function synchronizeLocalizationSettings( | ||
64 | store: MainStore, | ||
65 | supportedLanguages: string[], | ||
66 | osLocale: () => Promise<string>, | ||
67 | ): Promise<void> { | ||
68 | const { settings, shared } = store; | ||
69 | const supportedLangaugesSet = new Set(supportedLanguages); | ||
70 | const setLanguageAsync = async (languageSetting: string) => { | ||
71 | const requestedLanguage = | ||
72 | languageSetting === SYSTEM_LOCALE ? await osLocale() : languageSetting; | ||
73 | const matchingLanguage = getMatchingLocale( | ||
74 | requestedLanguage, | ||
75 | supportedLangaugesSet, | ||
76 | ); | ||
77 | log.debug( | ||
78 | 'Setting language', | ||
79 | matchingLanguage, | ||
80 | 'for requested language', | ||
81 | requestedLanguage, | ||
82 | ); | ||
83 | shared.setLanguage(matchingLanguage); | ||
84 | }; | ||
85 | const disposer = reaction( | ||
86 | () => settings.language, | ||
87 | (languageSetting) => { | ||
88 | setLanguageAsync(languageSetting).catch((error) => { | ||
89 | log.error('Failed to update language', error); | ||
90 | }); | ||
91 | }, | ||
92 | { | ||
93 | fireImmediately: false, | ||
94 | }, | ||
95 | ); | ||
96 | addDisposer(store, disposer); | ||
97 | // Make sure that the language is already set when we resolve. | ||
98 | await setLanguageAsync(settings.language); | ||
99 | } | ||
diff --git a/packages/main/src/initReactions.ts b/packages/main/src/initReactions.ts index cdff551..b383c8f 100644 --- a/packages/main/src/initReactions.ts +++ b/packages/main/src/initReactions.ts | |||
@@ -19,8 +19,11 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { app, session } from 'electron'; | 21 | import { app, session } from 'electron'; |
22 | import { osLocale } from 'os-locale'; | ||
22 | 23 | ||
24 | import LocalizationFiles from './i18n/impl/LocaltizationFiles'; | ||
23 | import loadLocalization from './i18n/loadLocalization'; | 25 | import loadLocalization from './i18n/loadLocalization'; |
26 | import { synchronizeLocalizationSettings } from './i18n/synchronizeLocalizationSettings'; | ||
24 | import ConfigFile from './infrastructure/config/impl/ConfigFile'; | 27 | import ConfigFile from './infrastructure/config/impl/ConfigFile'; |
25 | import UserAgents from './infrastructure/electron/UserAgents'; | 28 | import UserAgents from './infrastructure/electron/UserAgents'; |
26 | import ElectronViewFactory from './infrastructure/electron/impl/ElectronViewFactory'; | 29 | import ElectronViewFactory from './infrastructure/electron/impl/ElectronViewFactory'; |
@@ -44,28 +47,36 @@ export default async function initReactions( | |||
44 | store.shared, | 47 | store.shared, |
45 | configRepository, | 48 | configRepository, |
46 | ); | 49 | ); |
50 | const resources = getDistResources(devMode); | ||
51 | const localizationLoaded = (async () => { | ||
52 | const localizationFiles = new LocalizationFiles(resources); | ||
53 | await synchronizeLocalizationSettings( | ||
54 | store, | ||
55 | import.meta.env.SUPPORTED_LOCALES, | ||
56 | osLocale, | ||
57 | ); | ||
58 | await loadLocalization(store, localizationFiles, devMode); | ||
59 | })(); | ||
60 | // Ideally, we would the the chromium `--lang` here, | ||
61 | // but `app.isReady()` is often already `true`, so we're too late to do that. | ||
47 | await app.whenReady(); | 62 | await app.whenReady(); |
48 | const disposeNativeThemeController = synchronizeNativeTheme(store.shared); | 63 | const disposeNativeThemeController = synchronizeNativeTheme(store.shared); |
49 | const resources = getDistResources(devMode); | ||
50 | hardenSession(resources, devMode, session.defaultSession); | 64 | hardenSession(resources, devMode, session.defaultSession); |
51 | if (devMode) { | ||
52 | await installDevToolsExtensions(); | ||
53 | } | ||
54 | const userAgents = new UserAgents(app.userAgentFallback); | 65 | const userAgents = new UserAgents(app.userAgentFallback); |
55 | app.userAgentFallback = userAgents.fallbackUserAgent(devMode); | 66 | app.userAgentFallback = userAgents.fallbackUserAgent(devMode); |
56 | const localizeInterface = async () => { | 67 | const devToolsLoaded = devMode |
57 | await loadLocalization(store, resources, devMode); | 68 | ? installDevToolsExtensions() |
58 | setApplicationMenu(store, devMode, isMac); | 69 | : Promise.resolve(); |
59 | }; | ||
60 | const localization = localizeInterface(); | ||
61 | const viewFactory = new ElectronViewFactory(userAgents, resources, devMode); | 70 | const viewFactory = new ElectronViewFactory(userAgents, resources, devMode); |
62 | const [mainWindow] = await Promise.all([ | 71 | const mainWindow = (async () => { |
63 | viewFactory.createMainWindow(store), | 72 | await localizationLoaded; |
64 | viewFactory.loadServiceInject(), | 73 | setApplicationMenu(store, devMode, isMac); |
65 | ]); | 74 | await devToolsLoaded; |
66 | store.setMainWindow(mainWindow); | 75 | return viewFactory.createMainWindow(store); |
76 | })(); | ||
77 | await viewFactory.loadServiceInject(); | ||
67 | loadServices(store, viewFactory); | 78 | loadServices(store, viewFactory); |
68 | await localization; | 79 | store.setMainWindow(await mainWindow); |
69 | return () => { | 80 | return () => { |
70 | disposeNativeThemeController(); | 81 | disposeNativeThemeController(); |
71 | disposeConfigController(); | 82 | disposeConfigController(); |
diff --git a/packages/main/src/stores/SharedStore.ts b/packages/main/src/stores/SharedStore.ts index 67d58d6..960b65e 100644 --- a/packages/main/src/stores/SharedStore.ts +++ b/packages/main/src/stores/SharedStore.ts | |||
@@ -64,6 +64,9 @@ const SharedStore = defineSharedStoreModel(GlobalSettings, Profile, Service) | |||
64 | loadConfig(config: Config): void { | 64 | loadConfig(config: Config): void { |
65 | loadConfig(self, config); | 65 | loadConfig(self, config); |
66 | }, | 66 | }, |
67 | setLanguage(langauge: string): void { | ||
68 | self.language = langauge; | ||
69 | }, | ||
67 | setShouldUseDarkColors(shouldUseDarkColors: boolean): void { | 70 | setShouldUseDarkColors(shouldUseDarkColors: boolean): void { |
68 | self.shouldUseDarkColors = shouldUseDarkColors; | 71 | self.shouldUseDarkColors = shouldUseDarkColors; |
69 | }, | 72 | }, |
diff --git a/packages/main/types/importMeta.d.ts b/packages/main/types/importMeta.d.ts index 7426961..9818ca1 100644 --- a/packages/main/types/importMeta.d.ts +++ b/packages/main/types/importMeta.d.ts | |||
@@ -7,5 +7,6 @@ interface ImportMeta { | |||
7 | GIT_SHA: string; | 7 | GIT_SHA: string; |
8 | GIT_BRANCH: string; | 8 | GIT_BRANCH: string; |
9 | BUILD_DATE: number; | 9 | BUILD_DATE: number; |
10 | SUPPORTED_LOCALES: string[]; | ||
10 | }; | 11 | }; |
11 | } | 12 | } |
diff --git a/packages/renderer/src/i18n/loadRendererLoalization.ts b/packages/renderer/src/i18n/loadRendererLoalization.ts index 19d1e2d..b078aeb 100644 --- a/packages/renderer/src/i18n/loadRendererLoalization.ts +++ b/packages/renderer/src/i18n/loadRendererLoalization.ts | |||
@@ -18,7 +18,7 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { fallbackLng, SophieRenderer } from '@sophie/shared'; | 21 | import { FALLBACK_LOCALE, SophieRenderer } from '@sophie/shared'; |
22 | import i18next from 'i18next'; | 22 | import i18next from 'i18next'; |
23 | import { autorun } from 'mobx'; | 23 | import { autorun } from 'mobx'; |
24 | import { addDisposer } from 'mobx-state-tree'; | 24 | import { addDisposer } from 'mobx-state-tree'; |
@@ -40,7 +40,7 @@ export default function loadRendererLocalization( | |||
40 | const i18n = i18next | 40 | const i18n = i18next |
41 | .createInstance({ | 41 | .createInstance({ |
42 | lng: store.shared.language, | 42 | lng: store.shared.language, |
43 | fallbackLng, | 43 | fallbackLng: [FALLBACK_LOCALE], |
44 | interpolation: { | 44 | interpolation: { |
45 | escapeValue: false, // Not needed for react | 45 | escapeValue: false, // Not needed for react |
46 | }, | 46 | }, |
@@ -73,6 +73,7 @@ export default function loadRendererLocalization( | |||
73 | shared: { language }, | 73 | shared: { language }, |
74 | } = store; | 74 | } = store; |
75 | if (i18n.language !== language) { | 75 | if (i18n.language !== language) { |
76 | log.debug('Setting language', language); | ||
76 | i18n.changeLanguage(language).catch((error) => { | 77 | i18n.changeLanguage(language).catch((error) => { |
77 | log.error('Failed to change language', error); | 78 | log.error('Failed to change language', error); |
78 | }); | 79 | }); |
diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 51f9f06..c4de885 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts | |||
@@ -18,8 +18,6 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | export const fallbackLng = ['en']; | ||
22 | |||
23 | export type { default as SophieRenderer } from './contextBridge/SophieRenderer'; | 21 | export type { default as SophieRenderer } from './contextBridge/SophieRenderer'; |
24 | 22 | ||
25 | export { MainToRendererIpcMessage, RendererToMainIpcMessage } from './ipc'; | 23 | export { MainToRendererIpcMessage, RendererToMainIpcMessage } from './ipc'; |
@@ -44,6 +42,7 @@ export type { | |||
44 | export { | 42 | export { |
45 | default as GlobalSettingsBase, | 43 | default as GlobalSettingsBase, |
46 | defineGlobalSettingsModel, | 44 | defineGlobalSettingsModel, |
45 | SYSTEM_LOCALE, | ||
47 | } from './stores/GlobalSettingsBase'; | 46 | } from './stores/GlobalSettingsBase'; |
48 | 47 | ||
49 | export { default as Profile } from './stores/Profile'; | 48 | export { default as Profile } from './stores/Profile'; |
@@ -79,4 +78,5 @@ export type { | |||
79 | export { | 78 | export { |
80 | default as SharedStoreBase, | 79 | default as SharedStoreBase, |
81 | defineSharedStoreModel, | 80 | defineSharedStoreModel, |
81 | FALLBACK_LOCALE, | ||
82 | } from './stores/SharedStoreBase'; | 82 | } from './stores/SharedStoreBase'; |
diff --git a/packages/shared/src/stores/GlobalSettingsBase.ts b/packages/shared/src/stores/GlobalSettingsBase.ts index 1bd0628..c74c822 100644 --- a/packages/shared/src/stores/GlobalSettingsBase.ts +++ b/packages/shared/src/stores/GlobalSettingsBase.ts | |||
@@ -30,10 +30,13 @@ import { ThemeSource } from '../schemas/ThemeSource'; | |||
30 | 30 | ||
31 | import ServiceBase from './ServiceBase'; | 31 | import ServiceBase from './ServiceBase'; |
32 | 32 | ||
33 | export const SYSTEM_LOCALE = 'system'; | ||
34 | |||
33 | export function defineGlobalSettingsModel<TS extends IAnyModelType>( | 35 | export function defineGlobalSettingsModel<TS extends IAnyModelType>( |
34 | service: TS, | 36 | service: TS, |
35 | ) { | 37 | ) { |
36 | return types.model('GlobalSettings', { | 38 | return types.model('GlobalSettings', { |
39 | language: SYSTEM_LOCALE, | ||
37 | themeSource: types.optional( | 40 | themeSource: types.optional( |
38 | types.enumeration(ThemeSource.options), | 41 | types.enumeration(ThemeSource.options), |
39 | 'system', | 42 | 'system', |
diff --git a/packages/shared/src/stores/SharedStoreBase.ts b/packages/shared/src/stores/SharedStoreBase.ts index 86bd0fc..a576a0e 100644 --- a/packages/shared/src/stores/SharedStoreBase.ts +++ b/packages/shared/src/stores/SharedStoreBase.ts | |||
@@ -31,6 +31,8 @@ import GlobalSettingsBase from './GlobalSettingsBase'; | |||
31 | import ProfileBase from './Profile'; | 31 | import ProfileBase from './Profile'; |
32 | import ServiceBase from './ServiceBase'; | 32 | import ServiceBase from './ServiceBase'; |
33 | 33 | ||
34 | export const FALLBACK_LOCALE = 'en'; | ||
35 | |||
34 | export function defineSharedStoreModel< | 36 | export function defineSharedStoreModel< |
35 | TG extends IAnyModelType, | 37 | TG extends IAnyModelType, |
36 | TP extends IAnyModelType, | 38 | TP extends IAnyModelType, |
@@ -43,7 +45,7 @@ export function defineSharedStoreModel< | |||
43 | servicesById: types.map(service), | 45 | servicesById: types.map(service), |
44 | services: types.array(types.reference(service)), | 46 | services: types.array(types.reference(service)), |
45 | shouldUseDarkColors: false, | 47 | shouldUseDarkColors: false, |
46 | language: 'en', | 48 | language: FALLBACK_LOCALE, |
47 | }); | 49 | }); |
48 | } | 50 | } |
49 | 51 | ||
@@ -1297,6 +1297,7 @@ __metadata: | |||
1297 | mobx-state-tree: ^5.1.3 | 1297 | mobx-state-tree: ^5.1.3 |
1298 | ms: ^2.1.3 | 1298 | ms: ^2.1.3 |
1299 | nanoid: ^3.3.2 | 1299 | nanoid: ^3.3.2 |
1300 | os-locale: ^6.0.2 | ||
1300 | os-name: ^5.0.1 | 1301 | os-name: ^5.0.1 |
1301 | slug: ^5.3.0 | 1302 | slug: ^5.3.0 |
1302 | source-map-support: ^0.5.21 | 1303 | source-map-support: ^0.5.21 |
@@ -5219,6 +5220,13 @@ __metadata: | |||
5219 | languageName: node | 5220 | languageName: node |
5220 | linkType: hard | 5221 | linkType: hard |
5221 | 5222 | ||
5223 | "invert-kv@npm:^3.0.0": | ||
5224 | version: 3.0.1 | ||
5225 | resolution: "invert-kv@npm:3.0.1" | ||
5226 | checksum: 782c44c97f8b693006f5ba0995301754bf68d2160ec98fc34d96b266e2c28cc0c91d86c341ca058fe993bc3dd91f104f776a40f04b6c75254a9a1a0d716ac814 | ||
5227 | languageName: node | ||
5228 | linkType: hard | ||
5229 | |||
5222 | "ip@npm:^1.1.5": | 5230 | "ip@npm:^1.1.5": |
5223 | version: 1.1.5 | 5231 | version: 1.1.5 |
5224 | resolution: "ip@npm:1.1.5" | 5232 | resolution: "ip@npm:1.1.5" |
@@ -6421,6 +6429,15 @@ __metadata: | |||
6421 | languageName: node | 6429 | languageName: node |
6422 | linkType: hard | 6430 | linkType: hard |
6423 | 6431 | ||
6432 | "lcid@npm:^3.1.1": | ||
6433 | version: 3.1.1 | ||
6434 | resolution: "lcid@npm:3.1.1" | ||
6435 | dependencies: | ||
6436 | invert-kv: ^3.0.0 | ||
6437 | checksum: 7ebab7a2696a3cc6c6c9f25d957ef81dd2a8a2f48b7e2a9185e4bbcfc36d70cb633acf5fa5c9508f3d30badf23a303b1b6afe0bba8f0bb7d353d0f5d59c9ec1b | ||
6438 | languageName: node | ||
6439 | linkType: hard | ||
6440 | |||
6424 | "leven@npm:^3.1.0": | 6441 | "leven@npm:^3.1.0": |
6425 | version: 3.1.0 | 6442 | version: 3.1.0 |
6426 | resolution: "leven@npm:3.1.0" | 6443 | resolution: "leven@npm:3.1.0" |
@@ -7147,6 +7164,15 @@ __metadata: | |||
7147 | languageName: node | 7164 | languageName: node |
7148 | linkType: hard | 7165 | linkType: hard |
7149 | 7166 | ||
7167 | "os-locale@npm:^6.0.2": | ||
7168 | version: 6.0.2 | ||
7169 | resolution: "os-locale@npm:6.0.2" | ||
7170 | dependencies: | ||
7171 | lcid: ^3.1.1 | ||
7172 | checksum: 812d73334c8773b971bf7fd257b84d2ce7b85d5d2184370f2875fe0e51451f530d6f7c272de1faa0b9ff02d0d10dafd665b6425ed85489271705ab5738691a43 | ||
7173 | languageName: node | ||
7174 | linkType: hard | ||
7175 | |||
7150 | "os-name@npm:^5.0.1": | 7176 | "os-name@npm:^5.0.1": |
7151 | version: 5.0.1 | 7177 | version: 5.0.1 |
7152 | resolution: "os-name@npm:5.0.1" | 7178 | resolution: "os-name@npm:5.0.1" |