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:
EYHN
2024-06-20 02:19:41 +00:00
parent 5b0f56399c
commit 7c0a686cd9
193 changed files with 553 additions and 575 deletions

View File

@@ -15,7 +15,7 @@ import {
sendVerifyChangeEmailMutation,
verifyEmailMutation,
} from '@affine/graphql';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import { useLiveData, useService } from '@toeverything/infra';
import type { ReactElement } from 'react';
import { useCallback, useEffect } from 'react';
@@ -43,7 +43,7 @@ const authTypeSchema = z.enum([
export const AuthPage = (): ReactElement | null => {
const authService = useService(AuthService);
const account = useLiveData(authService.session.account$);
const t = useAFFiNEI18N();
const t = useI18n();
const serverConfig = useService(ServerConfigService).serverConfig;
const passwordLimits = useLiveData(
serverConfig.credentialsRequirement$.map(r => r?.password)

View File

@@ -1,12 +1,12 @@
import { AuthPageContainer } from '@affine/component/auth-components';
import { Button } from '@affine/component/ui/button';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import { useCallback } from 'react';
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
export const Component = () => {
const t = useAFFiNEI18N();
const t = useI18n();
const { jumpToIndex } = useNavigateHelper();
const onOpenAffine = useCallback(() => {
jumpToIndex(RouteLogic.REPLACE);

View File

@@ -1,8 +1,7 @@
import { Button } from '@affine/component/ui/button';
import type { GetCurrentUserQuery } from '@affine/graphql';
import { fetcher, getCurrentUserQuery } from '@affine/graphql';
import { Trans } from '@affine/i18n';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { Trans, useI18n } from '@affine/i18n';
import { Logo1Icon } from '@blocksuite/icons/rc';
import { useCallback, useMemo } from 'react';
import type { LoaderFunction } from 'react-router-dom';
@@ -59,7 +58,7 @@ interface LoaderData {
}
const OpenAppImpl = ({ urlToOpen, channel }: OpenAppProps) => {
const t = useAFFiNEI18N();
const t = useI18n();
const openDownloadLink = useCallback(() => {
const url = `https://affine.pro/download?channel=${channel}`;
open(url, '_blank');

View File

@@ -3,7 +3,7 @@ import { useActiveBlocksuiteEditor } from '@affine/core/hooks/use-block-suite-ed
import { usePageDocumentTitle } from '@affine/core/hooks/use-global-state';
import { AuthService } from '@affine/core/modules/cloud';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import { noop } from '@blocksuite/global/utils';
import { Logo1Icon } from '@blocksuite/icons/rc';
import type { AffineEditorContainer } from '@blocksuite/presets';
@@ -117,7 +117,7 @@ export const Component = () => {
} = useLoaderData() as LoaderData;
const workspacesService = useService(WorkspacesService);
const t = useAFFiNEI18N();
const t = useI18n();
const [workspace, setWorkspace] = useState<Workspace | null>(null);
const [page, setPage] = useState<Doc | null>(null);
const [_, setActiveBlocksuiteEditor] = useActiveBlocksuiteEditor();

View File

@@ -1,10 +1,10 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import { ArrowRightBigIcon } from '@blocksuite/icons/rc';
import * as styles from './share-footer.css';
export const ShareFooter = () => {
const t = useAFFiNEI18N();
const t = useI18n();
return (
<div className={styles.footerContainer}>
<div className={styles.footer}>

View File

@@ -7,7 +7,7 @@ import {
} from '@affine/core/components/page-list';
import { useAllPageListConfig } from '@affine/core/hooks/affine/use-all-page-list-config';
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
import { nanoid } from 'nanoid';
import { useCallback, useMemo, useState } from 'react';
@@ -19,7 +19,7 @@ import { AllCollectionHeader } from './header';
import * as styles from './index.css';
export const AllCollection = () => {
const t = useAFFiNEI18N();
const t = useI18n();
const currentWorkspace = useService(WorkspaceService).workspace;
const [hideHeaderCreateNew, setHideHeaderCreateNew] = useState(true);

View File

@@ -8,8 +8,7 @@ import { useAllPageListConfig } from '@affine/core/hooks/affine/use-all-page-lis
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { CollectionService } from '@affine/core/modules/collection';
import type { Collection } from '@affine/env/filter';
import { Trans } from '@affine/i18n';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { Trans, useI18n } from '@affine/i18n';
import {
CloseIcon,
FilterIcon,
@@ -123,7 +122,7 @@ const Placeholder = ({ collection }: { collection: Collection }) => {
setShowTips(false);
localStorage.setItem('hide-empty-collection-help-info', 'true');
}, []);
const t = useAFFiNEI18N();
const t = useI18n();
const handleJumpToCollections = useCallback(() => {
jumpToCollections(workspace.id);

View File

@@ -1,6 +1,5 @@
import { Empty } from '@affine/component';
import { Trans } from '@affine/i18n';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { Trans, useI18n } from '@affine/i18n';
import type { DocCollection } from '@blocksuite/store';
import type { ReactNode } from 'react';
import { useCallback } from 'react';
@@ -18,7 +17,7 @@ export const EmptyPageList = ({
heading?: ReactNode;
}) => {
const { createPage } = usePageHelper(docCollection);
const t = useAFFiNEI18N();
const t = useI18n();
const onCreatePage = useCallback(() => {
createPage?.();
}, [createPage]);
@@ -69,7 +68,7 @@ export const EmptyPageList = ({
};
export const EmptyCollectionList = ({ heading }: { heading: ReactNode }) => {
const t = useAFFiNEI18N();
const t = useI18n();
return (
<div className={styles.pageListEmptyStyle}>
{heading && <div>{heading}</div>}
@@ -79,7 +78,7 @@ export const EmptyCollectionList = ({ heading }: { heading: ReactNode }) => {
};
export const EmptyTagList = ({ heading }: { heading: ReactNode }) => {
const t = useAFFiNEI18N();
const t = useI18n();
return (
<div className={styles.pageListEmptyStyle}>
{heading && <div>{heading}</div>}

View File

@@ -4,7 +4,7 @@ import {
} from '@affine/core/components/page-list';
import { Header } from '@affine/core/components/pure/header';
import { useBlockSuiteDocMeta } from '@affine/core/hooks/use-block-suite-page-meta';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import { assertExists } from '@blocksuite/global/utils';
import { DeleteIcon } from '@blocksuite/icons/rc';
import { useService, WorkspaceService } from '@toeverything/infra';
@@ -14,7 +14,7 @@ import { EmptyPageList } from './page-list-empty';
import * as styles from './trash-page.css';
const TrashHeader = () => {
const t = useAFFiNEI18N();
const t = useI18n();
return (
<Header
left={