Skip to content

Commit

Permalink
refactor(i18n): lazy load languages (#8456)
Browse files Browse the repository at this point in the history
closes AF-1397
  • Loading branch information
forehalo committed Oct 10, 2024
1 parent f833017 commit 9043e66
Show file tree
Hide file tree
Showing 60 changed files with 700 additions and 637 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ static
web-static
public
packages/frontend/i18n/src/i18n-generated.ts
packages/frontend/i18n/src/i18n-completenesses.json
packages/frontend/templates/*.gen.ts
2 changes: 1 addition & 1 deletion .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ jobs:
electron-install: false
full-cache: true
- name: Run i18n codegen
run: yarn i18n-codegen gen
run: yarn workspace @affine/i18n build
- name: Run ESLint
run: yarn lint:eslint --max-warnings=0
- name: Run Prettier
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ Thumbs.db
.vercel
out/
storybook-static
i18n-generated.ts

test-results
playwright-report
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public
packages/backend/server/src/schema.gql
packages/backend/server/src/fundamentals/error/errors.gen.ts
packages/frontend/i18n/src/i18n-generated.ts
packages/frontend/i18n/src/i18n-completenesses.json
packages/frontend/graphql/src/graphql/index.ts
tests/affine-legacy/**/static
.yarnrc.yml
Expand Down
47 changes: 18 additions & 29 deletions packages/frontend/apps/electron/renderer/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Telemetry } from '@affine/core/components/telemetry';
import { router } from '@affine/core/desktop/router';
import { configureCommonModules } from '@affine/core/modules';
import { configureAppTabsHeaderModule } from '@affine/core/modules/app-tabs-header';
import { I18nProvider } from '@affine/core/modules/i18n';
import { configureElectronStateStorageImpls } from '@affine/core/modules/storage';
import { CustomThemeModifier } from '@affine/core/modules/theme-editor';
import { configureSqliteUserspaceStorageProvider } from '@affine/core/modules/userspace';
Expand All @@ -15,7 +16,6 @@ import {
configureSqliteWorkspaceEngineStorageProvider,
} from '@affine/core/modules/workspace-engine';
import createEmotionCache from '@affine/core/utils/create-emotion-cache';
import { createI18n, setUpLanguage } from '@affine/i18n';
import { CacheProvider } from '@emotion/react';
import {
Framework,
Expand Down Expand Up @@ -50,15 +50,6 @@ const future = {
v7_startTransition: true,
} as const;

async function loadLanguage() {
const i18n = createI18n();
document.documentElement.lang = i18n.language;

await setUpLanguage(i18n);
}

let languageLoadingPromise: Promise<void> | null = null;

const framework = new Framework();
configureCommonModules(framework);
configureElectronStateStorageImpls(framework);
Expand All @@ -76,29 +67,27 @@ window.addEventListener('focus', () => {
frameworkProvider.get(LifecycleService).applicationStart();

export function App() {
if (!languageLoadingPromise) {
languageLoadingPromise = loadLanguage().catch(console.error);
}

return (
<Suspense>
<FrameworkRoot framework={frameworkProvider}>
<CacheProvider value={cache}>
<AffineContext store={getCurrentStore()}>
<Telemetry />
<CustomThemeModifier />
<GlobalLoading />
<RouterProvider
fallbackElement={<AppFallback />}
router={router}
future={future}
/>
{environment.isWindows && (
<div style={{ position: 'fixed', right: 0, top: 0, zIndex: 5 }}>
<WindowsAppControls />
</div>
)}
</AffineContext>
<I18nProvider>
<AffineContext store={getCurrentStore()}>
<Telemetry />
<CustomThemeModifier />
<GlobalLoading />
<RouterProvider
fallbackElement={<AppFallback />}
router={router}
future={future}
/>
{environment.isWindows && (
<div style={{ position: 'fixed', right: 0, top: 0, zIndex: 5 }}>
<WindowsAppControls />
</div>
)}
</AffineContext>
</I18nProvider>
</CacheProvider>
</FrameworkRoot>
</Suspense>
Expand Down
9 changes: 0 additions & 9 deletions packages/frontend/apps/electron/renderer/shell/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
import './setup';

import { apis, events } from '@affine/electron-api';
import { createI18n, setUpLanguage } from '@affine/i18n';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

import { App } from './app';

function loadLanguage() {
const i18n = createI18n();
document.documentElement.lang = i18n.language;

setUpLanguage(i18n).catch(console.error);
}

async function main() {
const handleMaximized = (maximized: boolean | undefined) => {
document.documentElement.dataset.maximized = String(maximized);
Expand All @@ -31,7 +23,6 @@ async function main() {
events?.ui.onFullScreen(handleFullscreen);
events?.ui.onTabShellViewActiveChange(handleActive);

loadLanguage();
mountApp();
}

Expand Down
33 changes: 11 additions & 22 deletions packages/frontend/apps/mobile/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { Telemetry } from '@affine/core/components/telemetry';
import { configureMobileModules } from '@affine/core/mobile/modules';
import { router } from '@affine/core/mobile/router';
import { configureCommonModules } from '@affine/core/modules';
import { I18nProvider } from '@affine/core/modules/i18n';
import { configureLocalStorageStateStorageImpls } from '@affine/core/modules/storage';
import { configureIndexedDBUserspaceStorageProvider } from '@affine/core/modules/userspace';
import { configureBrowserWorkbenchModule } from '@affine/core/modules/workbench';
import {
configureBrowserWorkspaceFlavours,
configureIndexedDBWorkspaceEngineStorageProvider,
} from '@affine/core/modules/workspace-engine';
import { createI18n, setUpLanguage } from '@affine/i18n';
import {
Framework,
FrameworkRoot,
Expand All @@ -25,15 +25,6 @@ const future = {
v7_startTransition: true,
} as const;

async function loadLanguage() {
const i18n = createI18n();
document.documentElement.lang = i18n.language;

await setUpLanguage(i18n);
}

let languageLoadingPromise: Promise<void> | null = null;

const framework = new Framework();
configureCommonModules(framework);
configureBrowserWorkbenchModule(framework);
Expand All @@ -51,21 +42,19 @@ window.addEventListener('focus', () => {
frameworkProvider.get(LifecycleService).applicationStart();

export function App() {
if (!languageLoadingPromise) {
languageLoadingPromise = loadLanguage().catch(console.error);
}

return (
<Suspense>
<FrameworkRoot framework={frameworkProvider}>
<AffineContext store={getCurrentStore()}>
<Telemetry />
<RouterProvider
fallbackElement={<AppFallback />}
router={router}
future={future}
/>
</AffineContext>
<I18nProvider>
<AffineContext store={getCurrentStore()}>
<Telemetry />
<RouterProvider
fallbackElement={<AppFallback />}
router={router}
future={future}
/>
</AffineContext>
</I18nProvider>
</FrameworkRoot>
</Suspense>
);
Expand Down
37 changes: 13 additions & 24 deletions packages/frontend/apps/web/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { AppFallback } from '@affine/core/components/affine/app-container';
import { Telemetry } from '@affine/core/components/telemetry';
import { router } from '@affine/core/desktop/router';
import { configureCommonModules } from '@affine/core/modules';
import { I18nProvider } from '@affine/core/modules/i18n';
import { configureLocalStorageStateStorageImpls } from '@affine/core/modules/storage';
import { CustomThemeModifier } from '@affine/core/modules/theme-editor';
import { configureIndexedDBUserspaceStorageProvider } from '@affine/core/modules/userspace';
Expand All @@ -13,7 +14,6 @@ import {
configureIndexedDBWorkspaceEngineStorageProvider,
} from '@affine/core/modules/workspace-engine';
import createEmotionCache from '@affine/core/utils/create-emotion-cache';
import { createI18n, setUpLanguage } from '@affine/i18n';
import { CacheProvider } from '@emotion/react';
import {
Framework,
Expand All @@ -30,15 +30,6 @@ const future = {
v7_startTransition: true,
} as const;

async function loadLanguage() {
const i18n = createI18n();
document.documentElement.lang = i18n.language;

await setUpLanguage(i18n);
}

let languageLoadingPromise: Promise<void> | null = null;

const framework = new Framework();
configureCommonModules(framework);
configureBrowserWorkbenchModule(framework);
Expand All @@ -55,24 +46,22 @@ window.addEventListener('focus', () => {
frameworkProvider.get(LifecycleService).applicationStart();

export function App() {
if (!languageLoadingPromise) {
languageLoadingPromise = loadLanguage().catch(console.error);
}

return (
<Suspense>
<FrameworkRoot framework={frameworkProvider}>
<CacheProvider value={cache}>
<AffineContext store={getCurrentStore()}>
<Telemetry />
<CustomThemeModifier />
<GlobalLoading />
<RouterProvider
fallbackElement={<AppFallback key="RouterFallback" />}
router={router}
future={future}
/>
</AffineContext>
<I18nProvider>
<AffineContext store={getCurrentStore()}>
<Telemetry />
<CustomThemeModifier />
<GlobalLoading />
<RouterProvider
fallbackElement={<AppFallback key="RouterFallback" />}
router={router}
future={future}
/>
</AffineContext>
</I18nProvider>
</CacheProvider>
</FrameworkRoot>
</Suspense>
Expand Down
40 changes: 40 additions & 0 deletions packages/frontend/core/src/commands/affine-i18n.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { I18n } from '@affine/core/modules/i18n';
import type { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { SettingsIcon } from '@blocksuite/icons/rc';

import { registerAffineCommand } from './registry';

export function registerAffineLanguageCommands({
i18n,
t,
}: {
i18n: I18n;
t: ReturnType<typeof useI18n>;
}) {
// Display Language
const disposables = i18n.languageList.map(language => {
return registerAffineCommand({
id: `affine:change-display-language-to-${language.name}`,
label: `${t['com.affine.cmdk.affine.display-language.to']()} ${
language.originalName
}`,
category: 'affine:settings',
icon: <SettingsIcon />,
preconditionStrategy: () =>
i18n.currentLanguage$.value.key !== language.key,
run() {
track.$.cmdk.settings.changeAppSetting({
key: 'language',
value: language.name,
});

i18n.changeLanguage(language.key);
},
});
});

return () => {
disposables.forEach(dispose => dispose());
};
}
27 changes: 0 additions & 27 deletions packages/frontend/core/src/commands/affine-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,21 @@ import { appSettingAtom } from '@toeverything/infra';
import type { createStore } from 'jotai';
import type { useTheme } from 'next-themes';

import type { useLanguageHelper } from '../components/hooks/affine/use-language-helper';
import type { EditorSettingService } from '../modules/editor-settting';
import { registerAffineCommand } from './registry';

export function registerAffineSettingsCommands({
t,
store,
theme,
languageHelper,
editorSettingService,
}: {
t: ReturnType<typeof useI18n>;
store: ReturnType<typeof createStore>;
theme: ReturnType<typeof useTheme>;
languageHelper: ReturnType<typeof useLanguageHelper>;
editorSettingService: EditorSettingService;
}) {
const unsubs: Array<() => void> = [];
const { onLanguageChange, languagesList, currentLanguage } = languageHelper;
const updateSettings = editorSettingService.editorSetting.set.bind(
editorSettingService.editorSetting
);
Expand Down Expand Up @@ -148,29 +144,6 @@ export function registerAffineSettingsCommands({
})
);

// Display Language
languagesList.forEach(language => {
unsubs.push(
registerAffineCommand({
id: `affine:change-display-language-to-${language.name}`,
label: `${t['com.affine.cmdk.affine.display-language.to']()} ${
language.originalName
}`,
category: 'affine:settings',
icon: <SettingsIcon />,
preconditionStrategy: () => currentLanguage?.tag !== language.tag,
run() {
track.$.cmdk.settings.changeAppSetting({
key: 'language',
value: language.name,
});

onLanguageChange(language.tag);
},
})
);
});

// Layout Style
unsubs.push(
registerAffineCommand({
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/core/src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './affine-creation';
export * from './affine-help';
export * from './affine-i18n';
export * from './affine-layout';
export * from './affine-navigation';
export * from './affine-settings';
Expand Down
Loading

0 comments on commit 9043e66

Please sign in to comment.