mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00: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:
@@ -1,5 +1,5 @@
|
||||
import { Button, IconButton } from '@affine/component/ui/button';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { CloseIcon } from '@blocksuite/icons/rc';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
@@ -18,7 +18,7 @@ export const LocalDemoTips = ({
|
||||
onLogin,
|
||||
onEnableCloud,
|
||||
}: LocalDemoTipsProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const buttonLabel = isLoggedIn
|
||||
? t['Enable AFFiNE Cloud']()
|
||||
: t['Sign in and Enable']();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { Logo1Icon } from '@blocksuite/icons/rc';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
@@ -12,7 +12,7 @@ export const AffineOtherPageLayout = ({
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
|
||||
const openDownloadLink = useCallback(() => {
|
||||
open(runtimeConfig.downloadUrl, '_blank');
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useNavConfig = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
return useMemo(
|
||||
() => [
|
||||
{
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
import type { ConfirmModalProps } from '../../ui/modal';
|
||||
import { ConfirmModal } from '../../ui/modal';
|
||||
|
||||
export const PublicLinkDisableModal = (props: ConfirmModalProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
|
||||
return (
|
||||
<ConfirmModal
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AuthPageContainer } from '@affine/component/auth-components';
|
||||
import type { GetInviteInfoQuery } from '@affine/graphql';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
import { Avatar } from '../../ui/avatar';
|
||||
import { Button } from '../../ui/button';
|
||||
@@ -13,7 +13,7 @@ export const AcceptInvitePage = ({
|
||||
onOpenWorkspace: () => void;
|
||||
inviteInfo: GetInviteInfoQuery['getInviteInfo'];
|
||||
}) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
return (
|
||||
<AuthPageContainer
|
||||
title={t['Successfully joined!']()}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Permission } from '@affine/graphql';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { ConfirmModal } from '../../ui/modal';
|
||||
@@ -19,7 +19,7 @@ export const InviteModal = ({
|
||||
onConfirm,
|
||||
isMutating,
|
||||
}: InviteModalProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const [inviteEmail, setInviteEmail] = useState('');
|
||||
const [permission] = useState(Permission.Write);
|
||||
const [isValidEmail, setIsValidEmail] = useState(true);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ConfirmModal } from '@affine/component/ui/modal';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export interface MemberLimitModalProps {
|
||||
@@ -19,7 +19,7 @@ export const MemberLimitModal = ({
|
||||
setOpen,
|
||||
onConfirm,
|
||||
}: MemberLimitModalProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const handleConfirm = useCallback(() => {
|
||||
setOpen(false);
|
||||
if (isFreePlan) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { SignOutIcon } from '@blocksuite/icons/rc';
|
||||
|
||||
import { Avatar } from '../../ui/avatar';
|
||||
@@ -25,7 +25,7 @@ export const NoPermissionOrNotFound = ({
|
||||
onSignOut,
|
||||
signInComponent,
|
||||
}: NotFoundPageProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
|
||||
return (
|
||||
<AffineOtherPageLayout>
|
||||
@@ -69,7 +69,7 @@ export const NotFoundPage = ({
|
||||
onBack,
|
||||
onSignOut,
|
||||
}: NotFoundPageProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
|
||||
return (
|
||||
<AffineOtherPageLayout>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// License on the MIT
|
||||
// https://github.com/emilkowalski/sonner/blob/5cb703edc108a23fd74979235c2f3c4005edd2a7/src/index.tsx
|
||||
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { CloseIcon, InformationFillDuotoneIcon } from '@blocksuite/icons/rc';
|
||||
import * as Toast from '@radix-ui/react-toast';
|
||||
import clsx from 'clsx';
|
||||
@@ -72,7 +72,7 @@ const typeColorMap = {
|
||||
};
|
||||
|
||||
function NotificationCard(props: NotificationCardProps): ReactNode {
|
||||
const t = useAFFiNEI18N();
|
||||
const t = useI18n();
|
||||
const removeNotification = useSetAtom(removeNotificationAtom);
|
||||
const { notification, notifications, setHeights, heights, index } = props;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user