mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-19 19:16:29 +08:00
refactor(i18n): new hook api (#7273)
# NEW HOOK API
`useI18n`: same as `useAFFiNEI18N`, with additional APIs
```ts
import { useI18n } from '@affine/i18n'
const i18n = useI18n()
i18n['hello world']() -> 你好世界
```
# NEW GLOBAL i18n Instance
`I18n`: use i18n capabilities outside of React
```ts
import { I18n } from '@affine/i18n'
I18n['hello world']() -> 你好世界
```
# NEW TYPES
`I18nKeys` -> all i18n keys
`I18nString` -> An i18n message (key&options)
transfer and store i18n text outside of React
```ts
const msg: I18nString = {
key: 'helloworld',
options: {
arg1: '123'
}
}
I18n.t(msg) -> 你好世界123
```
before:
```ts
registerCommand('open-page', {
name: t('command.open-page')
// ^- translation happens here,
})
```
after:
```ts
registerCommand('open-page', {
name: { key: 'command.open-page' }
// ^- store I18nString here, translate when the command render to UI
})
```
This commit is contained in:
@@ -5,7 +5,7 @@ import { useBlockSuiteDocMeta } from '@affine/core/hooks/use-block-suite-page-me
|
||||
import { FavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||
import { ShareDocsService } from '@affine/core/modules/share-doc';
|
||||
import { PublicPageMode } from '@affine/graphql';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type { DocMeta } from '@blocksuite/store';
|
||||
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
@@ -30,7 +30,7 @@ export const useAllPageListConfig = () => {
|
||||
[pageMetas]
|
||||
);
|
||||
const favAdapter = useService(FavoriteItemsAdapter);
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const favoriteItems = useLiveData(favAdapter.favorites$);
|
||||
|
||||
const isActive = useCallback(
|
||||
|
||||
@@ -2,7 +2,7 @@ import { notify, useConfirmModal } from '@affine/component';
|
||||
import { authAtom } from '@affine/core/atoms';
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import { WorkspaceSubPath } from '@affine/core/shared';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type { Workspace } from '@toeverything/infra';
|
||||
import {
|
||||
useLiveData,
|
||||
@@ -28,7 +28,7 @@ interface ConfirmEnableCloudOptions {
|
||||
type ConfirmEnableArgs = [Workspace, ConfirmEnableCloudOptions | undefined];
|
||||
|
||||
export const useEnableCloud = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const loginStatus = useLiveData(useService(AuthService).session.status$);
|
||||
const setAuthAtom = useSetAtom(authAtom);
|
||||
const { openConfirmModal, closeConfirmModal } = useConfirmModal();
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
} from '@affine/component/global-loading';
|
||||
import { mixpanel } from '@affine/core/utils';
|
||||
import { apis } from '@affine/electron-api';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type { PageRootService, RootBlockModel } from '@blocksuite/blocks';
|
||||
import { HtmlTransformer, MarkdownTransformer } from '@blocksuite/blocks';
|
||||
import type { Doc } from '@blocksuite/store';
|
||||
@@ -59,7 +59,7 @@ async function exportHandler({ page, type }: ExportHandlerOptions) {
|
||||
export const useExportPage = (page: Doc) => {
|
||||
const pushGlobalLoadingEvent = useSetAtom(pushGlobalLoadingEventAtom);
|
||||
const resolveGlobalLoadingEvent = useSetAtom(resolveGlobalLoadingEventAtom);
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
|
||||
const onClickHandler = useCallback(
|
||||
async (type: ExportType) => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { toast } from '@affine/component';
|
||||
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
|
||||
import { CollectionService } from '@affine/core/modules/collection';
|
||||
import { FavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type {
|
||||
Active,
|
||||
DragEndEvent,
|
||||
@@ -152,7 +152,7 @@ export function resolveDragEndIntent(
|
||||
export type GlobalDragEndIntent = ReturnType<typeof resolveDragEndIntent>;
|
||||
|
||||
export const useGlobalDNDHelper = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const currentWorkspace = useService(WorkspaceService).workspace;
|
||||
const favAdapter = useService(FavoriteItemsAdapter);
|
||||
const workspace = currentWorkspace.docCollection;
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
publishPageMutation,
|
||||
revokePublicPageMutation,
|
||||
} from '@affine/graphql';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { type I18nKeys, useI18n } from '@affine/i18n';
|
||||
import { SingleSelectSelectSolidIcon } from '@blocksuite/icons/rc';
|
||||
import type { DocMode, Workspace } from '@toeverything/infra';
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
@@ -15,12 +15,6 @@ import { useCallback, useMemo } from 'react';
|
||||
import { useMutation } from '../use-mutation';
|
||||
import { useQuery } from '../use-query';
|
||||
|
||||
type NoParametersKeys<T> = {
|
||||
[K in keyof T]: T[K] extends () => any ? K : never;
|
||||
}[keyof T];
|
||||
|
||||
type i18nKey = NoParametersKeys<ReturnType<typeof useAFFiNEI18N>>;
|
||||
|
||||
type NotificationKey =
|
||||
| 'enableSuccessTitle'
|
||||
| 'enableSuccessMessage'
|
||||
@@ -34,7 +28,7 @@ type NotificationKey =
|
||||
| 'disableErrorTitle'
|
||||
| 'disableErrorMessage';
|
||||
|
||||
const notificationToI18nKey: Record<NotificationKey, i18nKey> = {
|
||||
const notificationToI18nKey = {
|
||||
enableSuccessTitle:
|
||||
'com.affine.share-menu.create-public-link.notification.success.title',
|
||||
enableSuccessMessage:
|
||||
@@ -57,7 +51,7 @@ const notificationToI18nKey: Record<NotificationKey, i18nKey> = {
|
||||
'com.affine.share-menu.disable-publish-link.notification.fail.title',
|
||||
disableErrorMessage:
|
||||
'com.affine.share-menu.disable-publish-link.notification.fail.message',
|
||||
};
|
||||
} satisfies Record<NotificationKey, I18nKeys>;
|
||||
|
||||
export function useIsSharedPage(
|
||||
workspaceId: string,
|
||||
@@ -69,7 +63,7 @@ export function useIsSharedPage(
|
||||
currentShareMode: DocMode;
|
||||
enableShare: (mode: DocMode) => void;
|
||||
} {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const { data, mutate } = useQuery({
|
||||
query: getWorkspacePublicPagesQuery,
|
||||
variables: {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { LOCALES, useI18N } from '@affine/i18n';
|
||||
import { LOCALES, useI18n } from '@affine/i18n';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
|
||||
export function useLanguageHelper() {
|
||||
const i18n = useI18N();
|
||||
const i18n = useI18n();
|
||||
const currentLanguage = useMemo(
|
||||
() => LOCALES.find(item => item.tag === i18n.language),
|
||||
[i18n.language]
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
|
||||
import { FavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||
import { mixpanel } from '@affine/core/utils';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import { EdgelessIcon, HistoryIcon, PageIcon } from '@blocksuite/icons/rc';
|
||||
import {
|
||||
@@ -28,7 +28,7 @@ export function useRegisterBlocksuiteEditorCommands() {
|
||||
const doc = useService(DocService).doc;
|
||||
const docId = doc.id;
|
||||
const mode = useLiveData(doc.mode$);
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const workspace = useService(WorkspaceService).workspace;
|
||||
const docCollection = workspace.docCollection;
|
||||
const { getDocMeta } = useDocMetaHelper(docCollection);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { notify } from '@affine/component';
|
||||
import { getAffineCloudBaseUrl } from '@affine/core/modules/cloud/services/fetch';
|
||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||
import { mixpanel } from '@affine/core/utils';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
@@ -47,7 +47,7 @@ export const useSharingUrl = ({
|
||||
pageId,
|
||||
urlType,
|
||||
}: UseSharingUrl) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const sharingUrl = useGenerateUrl({ workspaceId, pageId, urlType });
|
||||
|
||||
const onClickCopyLink = useCallback(() => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
type KeyboardShortcutsI18NKeys =
|
||||
@@ -45,9 +45,9 @@ type KeyboardShortcutsI18NKeys =
|
||||
| 'divider'
|
||||
| 'copy-private-link';
|
||||
|
||||
// TODO(550): remove this hook after 'useAFFiNEI18N' support scoped i18n
|
||||
// TODO(550): remove this hook after 'useI18n' support scoped i18n
|
||||
const useKeyboardShortcutsI18N = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
return useCallback(
|
||||
(key: KeyboardShortcutsI18NKeys) =>
|
||||
t[`com.affine.keyboardShortcuts.${key}`](),
|
||||
@@ -55,9 +55,9 @@ const useKeyboardShortcutsI18N = () => {
|
||||
);
|
||||
};
|
||||
|
||||
// TODO(550): remove this hook after 'useAFFiNEI18N' support scoped i18n
|
||||
// TODO(550): remove this hook after 'useI18n' support scoped i18n
|
||||
const useHeadingKeyboardShortcutsI18N = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
return useCallback(
|
||||
(number: string) => t['com.affine.keyboardShortcuts.heading']({ number }),
|
||||
[t]
|
||||
@@ -280,7 +280,7 @@ export const useWinMarkdownShortcuts = (): ShortcutMap => {
|
||||
};
|
||||
|
||||
export const useMarkdownShortcuts = (): ShortcutsInfo => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
|
||||
const macMarkdownShortcuts = useMacMarkdownShortcuts();
|
||||
const winMarkdownShortcuts = useWinMarkdownShortcuts();
|
||||
@@ -292,7 +292,7 @@ export const useMarkdownShortcuts = (): ShortcutsInfo => {
|
||||
};
|
||||
|
||||
export const usePageShortcuts = (): ShortcutsInfo => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
|
||||
const macPageShortcuts = useMacPageKeyboardShortcuts();
|
||||
const winPageShortcuts = useWinPageKeyboardShortcuts();
|
||||
@@ -304,7 +304,7 @@ export const usePageShortcuts = (): ShortcutsInfo => {
|
||||
};
|
||||
|
||||
export const useEdgelessShortcuts = (): ShortcutsInfo => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
|
||||
const macEdgelessShortcuts = useMacEdgelessKeyboardShortcuts();
|
||||
const winEdgelessShortcuts = useWinEdgelessKeyboardShortcuts();
|
||||
@@ -316,7 +316,7 @@ export const useEdgelessShortcuts = (): ShortcutsInfo => {
|
||||
};
|
||||
|
||||
export const useGeneralShortcuts = (): ShortcutsInfo => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
|
||||
const macGeneralShortcuts = useMacGeneralKeyboardShortcuts();
|
||||
const winGeneralShortcuts = useWinGeneralKeyboardShortcuts();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { toast } from '@affine/component';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type { DocCollection } from '@blocksuite/store';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
@@ -8,7 +8,7 @@ import { trashModalAtom } from '../../atoms/trash-modal';
|
||||
import { useBlockSuiteMetaHelper } from './use-block-suite-meta-helper';
|
||||
|
||||
export function useTrashModalHelper(docCollection: DocCollection) {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const [trashModal, setTrashModal] = useAtom(trashModalAtom);
|
||||
const { pageIds } = trashModal;
|
||||
const { removeToTrash } = useBlockSuiteMetaHelper(docCollection);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type { AffineEditorContainer } from '@blocksuite/presets';
|
||||
import { useService, WorkspaceService } from '@toeverything/infra';
|
||||
import { useStore } from 'jotai';
|
||||
@@ -58,7 +58,7 @@ function registerCMDKCommand(
|
||||
|
||||
export function useRegisterWorkspaceCommands() {
|
||||
const store = useStore();
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const theme = useTheme();
|
||||
const currentWorkspace = useService(WorkspaceService).workspace;
|
||||
const languageHelper = useLanguageHelper();
|
||||
|
||||
Reference in New Issue
Block a user