chore(i18n): update i18n (#15191)

#### PR Dependency Tree


* **PR #15191** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Updated sign-in, sign-up, and email content to show the correct server
name for cloud and self-hosted setups.
* Added clearer workspace status messages for syncing, local workspaces,
and server-connected workspaces.
* Introduced localized text updates for more languages, including new
locale coverage.

* **Bug Fixes**
* Replaced outdated “Cloud” wording throughout the app with more
accurate “Sync” and self-hosted terminology.
* Improved account deletion, password reset, sharing, and storage
prompts for clearer user guidance.
* Updated workspace status labels and tooltips to better reflect the
current server connection.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-07-03 18:37:20 +08:00
committed by GitHub
parent cebd7296b1
commit c36b5b201e
42 changed files with 306 additions and 1067 deletions
@@ -11,6 +11,7 @@ import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hoo
import {
AuthService,
CaptchaService,
getSelfHostedServerName,
ServerService,
} from '@affine/core/modules/cloud';
import type { AuthSessionStatus } from '@affine/core/modules/cloud/entities/session';
@@ -58,6 +59,9 @@ export const SignInWithPasswordStep = ({
const serverName = useLiveData(
serverService.server.config$.selector(c => c.serverName)
);
const signInServerName = isSelfhosted
? getSelfHostedServerName(serverName)
: serverName;
const verifyToken = useLiveData(captchaService.verifyToken$);
const needCaptcha = useLiveData(captchaService.needCaptcha$);
@@ -134,7 +138,7 @@ export const SignInWithPasswordStep = ({
<AuthContainer>
<AuthHeader
title={t['com.affine.auth.sign.in']()}
subTitle={serverName}
subTitle={signInServerName}
/>
<AuthContent>
@@ -8,7 +8,11 @@ import {
} from '@affine/component/auth-components';
import { OAuth } from '@affine/core/components/affine/auth/oauth';
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
import { AuthService, ServerService } from '@affine/core/modules/cloud';
import {
AuthService,
getSelfHostedServerName,
ServerService,
} from '@affine/core/modules/cloud';
import type { AuthSessionStatus } from '@affine/core/modules/cloud/entities/session';
import { ServerDeploymentType } from '@affine/graphql';
import { Trans, useI18n } from '@affine/i18n';
@@ -61,6 +65,9 @@ export const SignInStep = ({
c => c.type === ServerDeploymentType.Selfhosted
)
);
const signInServerName = isSelfhosted
? getSelfHostedServerName(serverName)
: serverName;
const authService = useService(AuthService);
const [isMutating, setIsMutating] = useState(false);
@@ -139,7 +146,7 @@ export const SignInStep = ({
<AuthContainer>
<AuthHeader
title={t['com.affine.auth.sign.in']()}
subTitle={serverName}
subTitle={signInServerName}
/>
<AuthContent>
<div>{versionError}</div>
@@ -152,7 +159,7 @@ export const SignInStep = ({
<AuthContainer>
<AuthHeader
title={t['com.affine.auth.sign.in']()}
subTitle={serverName}
subTitle={signInServerName}
/>
<AuthContent>
@@ -3,12 +3,17 @@ import { Loading } from '@affine/component/ui/loading';
import { useSystemOnline } from '@affine/core/components/hooks/use-system-online';
import { useWorkspace } from '@affine/core/components/hooks/use-workspace';
import { useWorkspaceInfo } from '@affine/core/components/hooks/use-workspace-info';
import {
getSelfHostedServerName,
ServersService,
} from '@affine/core/modules/cloud';
import {
type WorkspaceMetadata,
type WorkspaceProfileInfo,
WorkspacesService,
} from '@affine/core/modules/workspace';
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
import { ServerDeploymentType } from '@affine/graphql';
import { useI18n } from '@affine/i18n';
import {
ArrowDownSmallIcon,
@@ -18,6 +23,7 @@ import {
InformationFillDuotoneIcon,
LocalWorkspaceIcon,
NoNetworkIcon,
SelfhostIcon,
SettingsIcon,
TeamWorkspaceIcon,
UnsyncIcon,
@@ -35,11 +41,12 @@ import { WorkspaceAvatar } from '../../workspace-avatar';
import * as styles from './styles.css';
export { PureWorkspaceCard } from './pure-workspace-card';
const CloudWorkspaceStatus = () => {
const RemoteWorkspaceStatus = ({ selfHosted }: { selfHosted?: boolean }) => {
const Icon = selfHosted ? SelfhostIcon : CloudWorkspaceIcon;
return (
<>
<CloudWorkspaceIcon />
Cloud
<Icon />
{selfHosted ? 'AFFiNE' : 'Cloud'}
</>
);
};
@@ -87,6 +94,19 @@ const OfflineStatus = () => {
const useSyncEngineSyncProgress = (meta: WorkspaceMetadata) => {
const isOnline = useSystemOnline();
const workspace = useWorkspace(meta);
const serversService = useService(ServersService);
const server = useLiveData(
useMemo(
() => serversService.server$(meta.flavour),
[meta.flavour, serversService]
)
);
const serverConfig = useLiveData(server?.config$);
const isSelfHostedServer =
serverConfig?.type === ServerDeploymentType.Selfhosted;
const syncTarget = isSelfHostedServer
? getSelfHostedServerName(serverConfig.serverName)
: 'AFFiNE Cloud';
const engineState = useLiveData(
useMemo(() => {
@@ -120,10 +140,10 @@ const useSyncEngineSyncProgress = (meta: WorkspaceMetadata) => {
content = 'Sync disconnected due to unexpected issues, reconnecting.';
} else if (syncing) {
content =
`Syncing with AFFiNE Cloud` +
`Syncing with ${syncTarget}` +
(progress ? ` (${Math.floor(progress * 100)}%)` : '');
} else {
content = 'Synced with AFFiNE Cloud';
content = `Synced with ${syncTarget}`;
}
const CloudWorkspaceSyncStatus = () => {
@@ -134,7 +154,7 @@ const useSyncEngineSyncProgress = (meta: WorkspaceMetadata) => {
} else if (engineState.syncRetrying) {
return UnSyncWorkspaceStatus();
} else {
return CloudWorkspaceStatus();
return <RemoteWorkspaceStatus selfHosted={isSelfHostedServer} />;
}
};
@@ -185,6 +205,19 @@ const WorkspaceSyncInfo = ({
}) => {
const syncStatus = useSyncEngineSyncProgress(workspaceMetadata);
const isCloud = workspaceMetadata.flavour !== 'local';
const serversService = useService(ServersService);
const server = useLiveData(
useMemo(
() =>
workspaceMetadata.flavour === 'local'
? null
: serversService.server$(workspaceMetadata.flavour),
[serversService, workspaceMetadata.flavour]
)
);
const serverConfig = useLiveData(server?.config$);
const isSelfHostedServer =
serverConfig?.type === ServerDeploymentType.Selfhosted;
const { paused, pause } = usePauseAnimation();
// to make sure that animation will play first time
@@ -226,7 +259,11 @@ const WorkspaceSyncInfo = ({
</div>
{!dense ? (
<div className={styles.workspaceStatus}>
{isCloud ? <CloudWorkspaceStatus /> : <LocalWorkspaceStatus />}
{isCloud ? (
<RemoteWorkspaceStatus selfHosted={isSelfHostedServer} />
) : (
<LocalWorkspaceStatus />
)}
</div>
) : null}
</div>
@@ -2,6 +2,7 @@ import { Avatar } from '@affine/component';
import { useSignOut } from '@affine/core/components/hooks/affine/use-sign-out';
import { AuthService } from '@affine/core/modules/cloud';
import { GlobalDialogService } from '@affine/core/modules/dialogs';
import { useI18n } from '@affine/i18n';
import { ArrowRightSmallIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
import { type ReactNode } from 'react';
@@ -74,14 +75,15 @@ const AuthorizedUserProfile = () => {
};
const UnauthorizedUserProfile = () => {
const { t } = useI18n();
const globalDialogService = useService(GlobalDialogService);
return (
<BaseLayout
onClick={() => globalDialogService.open('sign-in', {})}
avatar={<Avatar size={48} rounded={4} />}
title="Sign up / Sign in"
caption="Sync with AFFiNE Cloud"
title={t(`com.affine.settings.sign`)}
caption={t(`com.affine.setting.sign.message`)}
/>
);
};
@@ -4,6 +4,7 @@ import {
ServerFeature,
} from '@affine/graphql';
import { DEFAULT_SELF_HOSTED_SERVER_NAME } from './server-name';
import type { ServerConfig, ServerMetadata } from './types';
export const BUILD_IN_SERVERS: (ServerMetadata & { config: ServerConfig })[] =
@@ -16,7 +17,7 @@ export const BUILD_IN_SERVERS: (ServerMetadata & { config: ServerConfig })[] =
// this is ok for web app, but not for desktop app
// since we never build desktop app in selfhosted mode, so it's fine
config: {
serverName: 'Affine Selfhost',
serverName: DEFAULT_SELF_HOSTED_SERVER_NAME,
features: [],
oauthProviders: [],
type: ServerDeploymentType.Selfhosted,
@@ -37,7 +38,7 @@ export const BUILD_IN_SERVERS: (ServerMetadata & { config: ServerConfig })[] =
? 'http://localhost:8080'
: location.origin,
config: {
serverName: 'Affine Cloud',
serverName: 'AFFiNE Cloud',
features: [
ServerFeature.Indexer,
ServerFeature.Copilot,
@@ -70,7 +71,7 @@ export const BUILD_IN_SERVERS: (ServerMetadata & { config: ServerConfig })[] =
: 'https://app.affine.pro'
: location.origin,
config: {
serverName: 'Affine Cloud',
serverName: 'AFFiNE Cloud',
features: [
ServerFeature.Indexer,
ServerFeature.Copilot,
@@ -103,7 +104,7 @@ export const BUILD_IN_SERVERS: (ServerMetadata & { config: ServerConfig })[] =
: 'https://insider.affine.pro'
: location.origin,
config: {
serverName: 'Affine Cloud',
serverName: 'AFFiNE Cloud',
features: [
ServerFeature.Indexer,
ServerFeature.Copilot,
@@ -132,7 +133,7 @@ export const BUILD_IN_SERVERS: (ServerMetadata & { config: ServerConfig })[] =
id: 'affine-cloud',
baseUrl: 'https://insider.affine.pro',
config: {
serverName: 'Affine Cloud',
serverName: 'AFFiNE Cloud',
features: [
ServerFeature.Indexer,
ServerFeature.Copilot,
@@ -163,7 +164,7 @@ export const BUILD_IN_SERVERS: (ServerMetadata & { config: ServerConfig })[] =
? 'https://affine.fail'
: location.origin,
config: {
serverName: 'Affine Cloud',
serverName: 'AFFiNE Cloud',
features: [
ServerFeature.Indexer,
ServerFeature.Copilot,
@@ -12,6 +12,10 @@ export {
type RealtimeLiveQueryOptions,
} from './realtime/live-query';
export { ServerScope } from './scopes/server';
export {
DEFAULT_SELF_HOSTED_SERVER_NAME,
getSelfHostedServerName,
} from './server-name';
export { AccessTokenService } from './services/access-token';
export { AuthService } from './services/auth';
export { CaptchaService } from './services/captcha';
@@ -0,0 +1,7 @@
export const DEFAULT_SELF_HOSTED_SERVER_NAME = 'AFFiNE Self-hosted';
export function getSelfHostedServerName(serverName?: string | null) {
return serverName && serverName !== DEFAULT_SELF_HOSTED_SERVER_NAME
? `${DEFAULT_SELF_HOSTED_SERVER_NAME} (${serverName})`
: DEFAULT_SELF_HOSTED_SERVER_NAME;
}
@@ -131,7 +131,7 @@ export class DesktopApiService extends Service {
targetServer = defaultServerService.server;
}
if (!targetServer) {
throw new Error('Affine Cloud server not found');
throw new Error('AFFiNE Cloud server not found');
}
const authService = targetServer.scope.get(AuthService);