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
@@ -1,4 +1,4 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import { ArrowLeftSmallIcon } from '@blocksuite/icons/rc';
import type { FC } from 'react';
@@ -6,7 +6,7 @@ import type { ButtonProps } from '../../ui/button';
import { Button } from '../../ui/button';
export const BackButton: FC<ButtonProps> = props => {
const t = useAFFiNEI18N();
const t = useI18n();
return (
<Button
type="plain"
@@ -1,4 +1,4 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import { useCallback, useState } from 'react';
import { Button } from '../../ui/button';
@@ -13,7 +13,7 @@ export const ChangeEmailPage = ({
onChangeEmail: (email: string) => Promise<boolean>;
onOpenAffine: () => void;
}) => {
const t = useAFFiNEI18N();
const t = useI18n();
const [hasSetUp, setHasSetUp] = useState(false);
const [email, setEmail] = useState('');
const [isValidEmail, setIsValidEmail] = useState(true);
@@ -1,5 +1,5 @@
import type { PasswordLimitsFragment } from '@affine/graphql';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import type { FC } from 'react';
import { useCallback, useState } from 'react';
@@ -20,7 +20,7 @@ export const ChangePasswordPage: FC<{
onSetPassword: propsOnSetPassword,
onOpenAffine,
}) => {
const t = useAFFiNEI18N();
const t = useI18n();
const [hasSetUp, setHasSetUp] = useState(false);
const onSetPassword = useCallback(
@@ -1,4 +1,4 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import type { FC } from 'react';
import { Button } from '../../ui/button';
@@ -7,7 +7,7 @@ import { AuthPageContainer } from './auth-page-container';
export const ConfirmChangeEmail: FC<{
onOpenAffine: () => void;
}> = ({ onOpenAffine }) => {
const t = useAFFiNEI18N();
const t = useI18n();
return (
<AuthPageContainer
@@ -1,4 +1,4 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import type { FC } from 'react';
import { Button } from '../../ui/button';
@@ -7,7 +7,7 @@ import { AuthPageContainer } from './auth-page-container';
export const ConfirmChangeEmail: FC<{
onOpenAffine: () => void;
}> = ({ onOpenAffine }) => {
const t = useAFFiNEI18N();
const t = useI18n();
return (
<AuthPageContainer
@@ -1,5 +1,5 @@
import { type PasswordLimitsFragment } from '@affine/graphql';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import { type Options, passwordStrength } from 'check-password-strength';
import { type FC, useEffect, useMemo } from 'react';
import { useCallback, useState } from 'react';
@@ -43,7 +43,7 @@ export const PasswordInput: FC<
onPrevent: () => void;
}
> = ({ passwordLimits, onPass, onPrevent, ...inputProps }) => {
const t = useAFFiNEI18N();
const t = useI18n();
const [status, setStatus] = useState<Status | null>(null);
const [confirmStatus, setConfirmStatus] = useState<
@@ -1,5 +1,5 @@
import type { PasswordLimitsFragment } from '@affine/graphql';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import type { FC } from 'react';
import { useCallback, useState } from 'react';
@@ -20,7 +20,7 @@ export const SetPasswordPage: FC<{
onSetPassword: propsOnSetPassword,
onOpenAffine,
}) => {
const t = useAFFiNEI18N();
const t = useI18n();
const [hasSetUp, setHasSetUp] = useState(false);
const onSetPassword = useCallback(
@@ -1,5 +1,5 @@
import type { PasswordLimitsFragment } from '@affine/graphql';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import type { FC } from 'react';
import { useCallback, useRef, useState } from 'react';
@@ -13,7 +13,7 @@ export const SetPassword: FC<{
onLater?: () => void;
onSetPassword: (password: string) => void;
}> = ({ passwordLimits, onLater, onSetPassword, showLater = false }) => {
const t = useAFFiNEI18N();
const t = useI18n();
const [passwordPass, setPasswordPass] = useState(false);
const passwordRef = useRef('');
@@ -1,4 +1,4 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import type { FC } from 'react';
import { Button } from '../../ui/button';
@@ -7,7 +7,7 @@ import { AuthPageContainer } from './auth-page-container';
export const SignInSuccessPage: FC<{
onOpenAffine: () => void;
}> = ({ onOpenAffine }) => {
const t = useAFFiNEI18N();
const t = useI18n();
return (
<AuthPageContainer
title={t['com.affine.auth.signed.success.title']()}
@@ -1,5 +1,5 @@
import type { PasswordLimitsFragment } from '@affine/graphql';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useI18n } from '@affine/i18n';
import type { FC } from 'react';
import { useCallback, useState } from 'react';
@@ -21,7 +21,7 @@ export const SignUpPage: FC<{
onOpenAffine,
openButtonText,
}) => {
const t = useAFFiNEI18N();
const t = useI18n();
const [hasSetUp, setHasSetUp] = useState(false);
const onSetPassword = useCallback(