mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-24 09:52:49 +08:00
@@ -15,10 +15,11 @@ export function isNetworkError(error: Error): error is NetworkError {
|
||||
}
|
||||
|
||||
export class BackendError extends Error {
|
||||
constructor(
|
||||
public readonly originError: UserFriendlyError,
|
||||
public readonly status?: number
|
||||
) {
|
||||
get status() {
|
||||
return this.originError.status;
|
||||
}
|
||||
|
||||
constructor(public readonly originError: UserFriendlyError) {
|
||||
super(`Server error: ${originError.message}`);
|
||||
this.stack = originError.stack;
|
||||
}
|
||||
|
||||
@@ -78,10 +78,7 @@ export class FetchService extends Service {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
throw new BackendError(
|
||||
UserFriendlyError.fromAnyError(reason),
|
||||
res.status
|
||||
);
|
||||
throw new BackendError(UserFriendlyError.fromAnyError(reason));
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import {
|
||||
gqlFetcherFactory,
|
||||
GraphQLError,
|
||||
type GraphQLQuery,
|
||||
type QueryOptions,
|
||||
type QueryResponse,
|
||||
UserFriendlyError,
|
||||
} from '@affine/graphql';
|
||||
import { fromPromise, Service } from '@toeverything/infra';
|
||||
import type { Observable } from 'rxjs';
|
||||
@@ -37,12 +39,21 @@ export class GraphQLService extends Service {
|
||||
): Promise<QueryResponse<Query>> => {
|
||||
try {
|
||||
return await this.rawGql(options);
|
||||
} catch (err) {
|
||||
if (err instanceof BackendError && err.status === 403) {
|
||||
} catch (anyError) {
|
||||
let error = anyError;
|
||||
|
||||
// NOTE(@forehalo):
|
||||
// GraphQL error is not present by non-200 status code, but by responding `errors` fields in the body
|
||||
// So it will never be `BackendError` originally.
|
||||
if (anyError instanceof GraphQLError) {
|
||||
error = new BackendError(UserFriendlyError.fromAnyError(anyError));
|
||||
}
|
||||
|
||||
if (error instanceof BackendError && error.status === 403) {
|
||||
this.framework.get(AuthService).session.revalidate();
|
||||
}
|
||||
|
||||
throw err;
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
import { readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import { join, parse } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import { runCli } from '@magic-works/i18n-codegen';
|
||||
|
||||
const isDev = process.argv.includes('--dev');
|
||||
|
||||
const pkgRoot = fileURLToPath(new URL('./', import.meta.url));
|
||||
|
||||
function calcCompletenesses() {
|
||||
const resourcesDir = join(pkgRoot, 'src', 'resources');
|
||||
|
||||
const langs = readdirSync(resourcesDir)
|
||||
.filter(file => file.endsWith('.json'))
|
||||
.reduce((langs, file) => {
|
||||
const filePath = `${resourcesDir}/${file}`;
|
||||
const fileContent = JSON.parse(readFileSync(filePath, 'utf-8'));
|
||||
langs[parse(file).name] = fileContent;
|
||||
return langs;
|
||||
}, {});
|
||||
|
||||
const base = Object.keys(langs.en).length;
|
||||
|
||||
const completenesses = {};
|
||||
|
||||
for (const key in langs) {
|
||||
const [langPart, variantPart] = key.split('-');
|
||||
|
||||
const completeness = Object.keys(
|
||||
variantPart ? { ...langs[langPart], ...langs[key] } : langs[key]
|
||||
).length;
|
||||
|
||||
completenesses[key] = Math.min(
|
||||
Math.ceil(/* avoid 0% */ (completeness / base) * 100),
|
||||
100
|
||||
);
|
||||
}
|
||||
|
||||
writeFileSync(
|
||||
join(pkgRoot, 'src', 'i18n-completenesses.json'),
|
||||
JSON.stringify(completenesses, null, 2) + '\n'
|
||||
);
|
||||
}
|
||||
|
||||
runCli(
|
||||
{
|
||||
config: fileURLToPath(new URL('./.i18n-codegen.json', import.meta.url)),
|
||||
watch: isDev,
|
||||
},
|
||||
error => {
|
||||
console.error(error);
|
||||
if (!isDev) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
calcCompletenesses();
|
||||
128
packages/frontend/i18n/build.ts
Normal file
128
packages/frontend/i18n/build.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
import { readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import { parse } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import { Package } from '@affine-tools/utils/workspace';
|
||||
import { runCli } from '@magic-works/i18n-codegen';
|
||||
|
||||
const isDev = process.argv.includes('--dev');
|
||||
|
||||
const i18nPkg = new Package('@affine/i18n');
|
||||
const resourcesDir = i18nPkg.join('src', 'resources').toString();
|
||||
|
||||
function readResource(lang: string): Record<string, string> {
|
||||
const filePath = `${resourcesDir}/${lang}.json`;
|
||||
const fileContent = JSON.parse(readFileSync(filePath, 'utf-8'));
|
||||
return fileContent;
|
||||
}
|
||||
|
||||
function writeResource(lang: string, resource: Record<string, string>) {
|
||||
const filePath = `${resourcesDir}/${lang}.json`;
|
||||
writeFileSync(filePath, JSON.stringify(resource, null, 2) + '\n');
|
||||
}
|
||||
|
||||
function calcCompletenesses() {
|
||||
const langs = readdirSync(resourcesDir)
|
||||
.filter(file => file.endsWith('.json'))
|
||||
.reduce(
|
||||
(langs, file) => {
|
||||
const lang = parse(file).name;
|
||||
langs[lang] = readResource(lang);
|
||||
return langs;
|
||||
},
|
||||
{} as Record<string, Record<string, string>>
|
||||
);
|
||||
|
||||
const base = Object.keys(langs.en).length;
|
||||
|
||||
const completenesses = {};
|
||||
|
||||
for (const key in langs) {
|
||||
const [langPart, variantPart] = key.split('-');
|
||||
|
||||
const completeness = Object.keys(
|
||||
variantPart ? { ...langs[langPart], ...langs[key] } : langs[key]
|
||||
).length;
|
||||
|
||||
completenesses[key] = Math.min(
|
||||
Math.ceil(/* avoid 0% */ (completeness / base) * 100),
|
||||
100
|
||||
);
|
||||
}
|
||||
|
||||
writeFileSync(
|
||||
i18nPkg.join('src', 'i18n-completenesses.json').toString(),
|
||||
JSON.stringify(completenesses, null, 2) + '\n'
|
||||
);
|
||||
}
|
||||
|
||||
function i18nnext() {
|
||||
runCli(
|
||||
{
|
||||
config: fileURLToPath(new URL('./.i18n-codegen.json', import.meta.url)),
|
||||
watch: isDev,
|
||||
},
|
||||
error => {
|
||||
console.error(error);
|
||||
if (!isDev) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function appendErrorI18n() {
|
||||
const server = new Package('@affine/server');
|
||||
const defFilePath = server.srcPath.join('base/error/def.ts');
|
||||
|
||||
if (!defFilePath.exists()) {
|
||||
throw new Error(
|
||||
`Can not find Server I18n error definition file. It's not placed at [${defFilePath.relativePath}].`
|
||||
);
|
||||
}
|
||||
|
||||
const { USER_FRIENDLY_ERRORS } = await import(
|
||||
defFilePath.toFileUrl().toString()
|
||||
);
|
||||
|
||||
if (!USER_FRIENDLY_ERRORS) {
|
||||
throw new Error(
|
||||
`Can not find Server I18n error definition file. It's not placed at [${defFilePath.relativePath}] with name [USER_FRIENDLY_ERRORS].`
|
||||
);
|
||||
}
|
||||
|
||||
const en = readResource('en');
|
||||
|
||||
Object.keys(en).forEach(key => {
|
||||
if (key.startsWith('error.')) {
|
||||
delete en[key];
|
||||
}
|
||||
});
|
||||
|
||||
for (const key in USER_FRIENDLY_ERRORS) {
|
||||
const def = USER_FRIENDLY_ERRORS[key] as {
|
||||
type: string;
|
||||
args?: Record<string, any>;
|
||||
message: string | ((args: any) => string);
|
||||
};
|
||||
|
||||
en[`error.${key.toUpperCase()}`] =
|
||||
typeof def.message === 'string'
|
||||
? def.message
|
||||
: def.message(
|
||||
Object.keys(def.args ?? {}).reduce(
|
||||
(args, key) => {
|
||||
args[key] = `{{${key}}}`;
|
||||
return args;
|
||||
},
|
||||
{} as Record<string, string>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
writeResource('en', en);
|
||||
}
|
||||
|
||||
await appendErrorI18n();
|
||||
i18nnext();
|
||||
calcCompletenesses();
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"name": "@affine/i18n",
|
||||
"version": "0.19.0",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
@@ -8,8 +9,8 @@
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node build.mjs",
|
||||
"dev": "node build.mjs --dev"
|
||||
"build": "r build.ts",
|
||||
"dev": "r build.ts --dev"
|
||||
},
|
||||
"keywords": [],
|
||||
"repository": {
|
||||
@@ -26,8 +27,9 @@
|
||||
"undici": "^7.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@affine-tools/cli": "workspace:*",
|
||||
"@affine-tools/utils": "workspace:*",
|
||||
"glob": "^11.0.0",
|
||||
"vitest": "3.0.5"
|
||||
},
|
||||
"version": "0.19.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
{
|
||||
"ar": 98,
|
||||
"ar": 92,
|
||||
"ca": 5,
|
||||
"da": 5,
|
||||
"de": 98,
|
||||
"el-GR": 98,
|
||||
"de": 92,
|
||||
"el-GR": 92,
|
||||
"en": 100,
|
||||
"es-AR": 98,
|
||||
"es-CL": 100,
|
||||
"es": 98,
|
||||
"fa": 98,
|
||||
"fr": 98,
|
||||
"es-AR": 92,
|
||||
"es-CL": 94,
|
||||
"es": 92,
|
||||
"fa": 92,
|
||||
"fr": 92,
|
||||
"hi": 2,
|
||||
"it-IT": 98,
|
||||
"it-IT": 92,
|
||||
"it": 1,
|
||||
"ja": 98,
|
||||
"ko": 71,
|
||||
"pl": 98,
|
||||
"pt-BR": 98,
|
||||
"ru": 98,
|
||||
"sv-SE": 98,
|
||||
"uk": 98,
|
||||
"ja": 92,
|
||||
"ko": 67,
|
||||
"pl": 92,
|
||||
"pt-BR": 92,
|
||||
"ru": 92,
|
||||
"sv-SE": 92,
|
||||
"uk": 92,
|
||||
"ur": 2,
|
||||
"zh-Hans": 98,
|
||||
"zh-Hant": 98
|
||||
"zh-Hans": 92,
|
||||
"zh-Hant": 92
|
||||
}
|
||||
|
||||
@@ -5361,6 +5361,14 @@ export function useAFFiNEI18N(): {
|
||||
* `Once enabled, the header of page block will be displayed.`
|
||||
*/
|
||||
["com.affine.settings.workspace.experimental-features.enable-page-block-header.description"](): string;
|
||||
/**
|
||||
* `Editor RTL`
|
||||
*/
|
||||
["com.affine.settings.workspace.experimental-features.enable-editor-rtl.name"](): string;
|
||||
/**
|
||||
* `Once enabled, the editor will be displayed in RTL mode.`
|
||||
*/
|
||||
["com.affine.settings.workspace.experimental-features.enable-editor-rtl.description"](): string;
|
||||
/**
|
||||
* `Only an owner can edit the workspace avatar and name. Changes will be shown for everyone.`
|
||||
*/
|
||||
@@ -5370,7 +5378,7 @@ export function useAFFiNEI18N(): {
|
||||
*/
|
||||
["com.affine.settings.workspace.preferences"](): string;
|
||||
/**
|
||||
* `Team's Team's Billing`
|
||||
* `Team's Billing`
|
||||
*/
|
||||
["com.affine.settings.workspace.billing"](): string;
|
||||
/**
|
||||
@@ -5550,7 +5558,7 @@ export function useAFFiNEI18N(): {
|
||||
*/
|
||||
["com.affine.settings.workspace.backup.import.success.action"](): string;
|
||||
/**
|
||||
* `Deleted {{date}} at {{time}}`
|
||||
* `Deleted on {{date}} at {{time}}`
|
||||
*/
|
||||
["com.affine.settings.workspace.backup.delete-at"](options: Readonly<{
|
||||
date: string;
|
||||
@@ -6662,6 +6670,437 @@ export function useAFFiNEI18N(): {
|
||||
* `Remove template`
|
||||
*/
|
||||
["com.affine.settings.workspace.template.remove"](): string;
|
||||
/**
|
||||
* `Unused blobs`
|
||||
*/
|
||||
["com.affine.settings.workspace.storage.unused-blobs"](): string;
|
||||
/**
|
||||
* `No unused blobs`
|
||||
*/
|
||||
["com.affine.settings.workspace.storage.unused-blobs.empty"](): string;
|
||||
/**
|
||||
* `Selected`
|
||||
*/
|
||||
["com.affine.settings.workspace.storage.unused-blobs.selected"](): string;
|
||||
/**
|
||||
* `Delete blob files`
|
||||
*/
|
||||
["com.affine.settings.workspace.storage.unused-blobs.delete.title"](): string;
|
||||
/**
|
||||
* `Are you sure you want to delete these blob files? This action cannot be undone. Make sure you no longer need them before proceeding.`
|
||||
*/
|
||||
["com.affine.settings.workspace.storage.unused-blobs.delete.warning"](): string;
|
||||
/**
|
||||
* `An internal error occurred.`
|
||||
*/
|
||||
["error.INTERNAL_SERVER_ERROR"](): string;
|
||||
/**
|
||||
* `Too many requests.`
|
||||
*/
|
||||
["error.TOO_MANY_REQUEST"](): string;
|
||||
/**
|
||||
* `Resource not found.`
|
||||
*/
|
||||
["error.NOT_FOUND"](): string;
|
||||
/**
|
||||
* `Query is too long, max length is {{max}}.`
|
||||
*/
|
||||
["error.QUERY_TOO_LONG"](options: {
|
||||
readonly max: string;
|
||||
}): string;
|
||||
/**
|
||||
* `User not found.`
|
||||
*/
|
||||
["error.USER_NOT_FOUND"](): string;
|
||||
/**
|
||||
* `User avatar not found.`
|
||||
*/
|
||||
["error.USER_AVATAR_NOT_FOUND"](): string;
|
||||
/**
|
||||
* `This email has already been registered.`
|
||||
*/
|
||||
["error.EMAIL_ALREADY_USED"](): string;
|
||||
/**
|
||||
* `You are trying to update your account email to the same as the old one.`
|
||||
*/
|
||||
["error.SAME_EMAIL_PROVIDED"](): string;
|
||||
/**
|
||||
* `Wrong user email or password: {{email}}`
|
||||
*/
|
||||
["error.WRONG_SIGN_IN_CREDENTIALS"](options: {
|
||||
readonly email: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Unknown authentication provider {{name}}.`
|
||||
*/
|
||||
["error.UNKNOWN_OAUTH_PROVIDER"](options: {
|
||||
readonly name: string;
|
||||
}): string;
|
||||
/**
|
||||
* `OAuth state expired, please try again.`
|
||||
*/
|
||||
["error.OAUTH_STATE_EXPIRED"](): string;
|
||||
/**
|
||||
* `Invalid callback state parameter.`
|
||||
*/
|
||||
["error.INVALID_OAUTH_CALLBACK_STATE"](): string;
|
||||
/**
|
||||
* `Missing query parameter `{{name}}`.`
|
||||
*/
|
||||
["error.MISSING_OAUTH_QUERY_PARAMETER"](options: {
|
||||
readonly name: string;
|
||||
}): string;
|
||||
/**
|
||||
* `The third-party account has already been connected to another user.`
|
||||
*/
|
||||
["error.OAUTH_ACCOUNT_ALREADY_CONNECTED"](): string;
|
||||
/**
|
||||
* `An invalid email provided: {{email}}`
|
||||
*/
|
||||
["error.INVALID_EMAIL"](options: {
|
||||
readonly email: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Password must be between {{min}} and {{max}} characters`
|
||||
*/
|
||||
["error.INVALID_PASSWORD_LENGTH"](options: Readonly<{
|
||||
min: string;
|
||||
max: string;
|
||||
}>): string;
|
||||
/**
|
||||
* `Password is required.`
|
||||
*/
|
||||
["error.PASSWORD_REQUIRED"](): string;
|
||||
/**
|
||||
* `You are trying to sign in by a different method than you signed up with.`
|
||||
*/
|
||||
["error.WRONG_SIGN_IN_METHOD"](): string;
|
||||
/**
|
||||
* `You don't have early access permission. Visit https://community.affine.pro/c/insider-general/ for more information.`
|
||||
*/
|
||||
["error.EARLY_ACCESS_REQUIRED"](): string;
|
||||
/**
|
||||
* `You are not allowed to sign up.`
|
||||
*/
|
||||
["error.SIGN_UP_FORBIDDEN"](): string;
|
||||
/**
|
||||
* `The email token provided is not found.`
|
||||
*/
|
||||
["error.EMAIL_TOKEN_NOT_FOUND"](): string;
|
||||
/**
|
||||
* `An invalid email token provided.`
|
||||
*/
|
||||
["error.INVALID_EMAIL_TOKEN"](): string;
|
||||
/**
|
||||
* `The link has expired.`
|
||||
*/
|
||||
["error.LINK_EXPIRED"](): string;
|
||||
/**
|
||||
* `You must sign in first to access this resource.`
|
||||
*/
|
||||
["error.AUTHENTICATION_REQUIRED"](): string;
|
||||
/**
|
||||
* `You are not allowed to perform this action.`
|
||||
*/
|
||||
["error.ACTION_FORBIDDEN"](): string;
|
||||
/**
|
||||
* `You do not have permission to access this resource.`
|
||||
*/
|
||||
["error.ACCESS_DENIED"](): string;
|
||||
/**
|
||||
* `You must verify your email before accessing this resource.`
|
||||
*/
|
||||
["error.EMAIL_VERIFICATION_REQUIRED"](): string;
|
||||
/**
|
||||
* `Space {{spaceId}} not found.`
|
||||
*/
|
||||
["error.SPACE_NOT_FOUND"](options: {
|
||||
readonly spaceId: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Member not found in Space {{spaceId}}.`
|
||||
*/
|
||||
["error.MEMBER_NOT_FOUND_IN_SPACE"](options: {
|
||||
readonly spaceId: string;
|
||||
}): string;
|
||||
/**
|
||||
* `You should join in Space {{spaceId}} before broadcasting messages.`
|
||||
*/
|
||||
["error.NOT_IN_SPACE"](options: {
|
||||
readonly spaceId: string;
|
||||
}): string;
|
||||
/**
|
||||
* `You have already joined in Space {{spaceId}}.`
|
||||
*/
|
||||
["error.ALREADY_IN_SPACE"](options: {
|
||||
readonly spaceId: string;
|
||||
}): string;
|
||||
/**
|
||||
* `You do not have permission to access Space {{spaceId}}.`
|
||||
*/
|
||||
["error.SPACE_ACCESS_DENIED"](options: {
|
||||
readonly spaceId: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Owner of Space {{spaceId}} not found.`
|
||||
*/
|
||||
["error.SPACE_OWNER_NOT_FOUND"](options: {
|
||||
readonly spaceId: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Doc {{docId}} under Space {{spaceId}} not found.`
|
||||
*/
|
||||
["error.DOC_NOT_FOUND"](options: Readonly<{
|
||||
docId: string;
|
||||
spaceId: string;
|
||||
}>): string;
|
||||
/**
|
||||
* `You do not have permission to access doc {{docId}} under Space {{spaceId}}.`
|
||||
*/
|
||||
["error.DOC_ACCESS_DENIED"](options: Readonly<{
|
||||
docId: string;
|
||||
spaceId: string;
|
||||
}>): string;
|
||||
/**
|
||||
* `Your client with version {{version}} is rejected by remote sync server. Please upgrade to {{serverVersion}}.`
|
||||
*/
|
||||
["error.VERSION_REJECTED"](options: Readonly<{
|
||||
version: string;
|
||||
serverVersion: string;
|
||||
}>): string;
|
||||
/**
|
||||
* `Invalid doc history timestamp provided.`
|
||||
*/
|
||||
["error.INVALID_HISTORY_TIMESTAMP"](): string;
|
||||
/**
|
||||
* `History of {{docId}} at {{timestamp}} under Space {{spaceId}}.`
|
||||
*/
|
||||
["error.DOC_HISTORY_NOT_FOUND"](options: Readonly<{
|
||||
docId: string;
|
||||
timestamp: string;
|
||||
spaceId: string;
|
||||
}>): string;
|
||||
/**
|
||||
* `Blob {{blobId}} not found in Space {{spaceId}}.`
|
||||
*/
|
||||
["error.BLOB_NOT_FOUND"](options: Readonly<{
|
||||
blobId: string;
|
||||
spaceId: string;
|
||||
}>): string;
|
||||
/**
|
||||
* `Expected to publish a page, not a Space.`
|
||||
*/
|
||||
["error.EXPECT_TO_PUBLISH_PAGE"](): string;
|
||||
/**
|
||||
* `Expected to revoke a public page, not a Space.`
|
||||
*/
|
||||
["error.EXPECT_TO_REVOKE_PUBLIC_PAGE"](): string;
|
||||
/**
|
||||
* `Page is not public.`
|
||||
*/
|
||||
["error.PAGE_IS_NOT_PUBLIC"](): string;
|
||||
/**
|
||||
* `Failed to store doc updates.`
|
||||
*/
|
||||
["error.FAILED_TO_SAVE_UPDATES"](): string;
|
||||
/**
|
||||
* `Failed to store doc snapshot.`
|
||||
*/
|
||||
["error.FAILED_TO_UPSERT_SNAPSHOT"](): string;
|
||||
/**
|
||||
* `Unsupported subscription plan: {{plan}}.`
|
||||
*/
|
||||
["error.UNSUPPORTED_SUBSCRIPTION_PLAN"](options: {
|
||||
readonly plan: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Failed to create checkout session.`
|
||||
*/
|
||||
["error.FAILED_TO_CHECKOUT"](): string;
|
||||
/**
|
||||
* `Invalid checkout parameters provided.`
|
||||
*/
|
||||
["error.INVALID_CHECKOUT_PARAMETERS"](): string;
|
||||
/**
|
||||
* `You have already subscribed to the {{plan}} plan.`
|
||||
*/
|
||||
["error.SUBSCRIPTION_ALREADY_EXISTS"](options: {
|
||||
readonly plan: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Invalid subscription parameters provided.`
|
||||
*/
|
||||
["error.INVALID_SUBSCRIPTION_PARAMETERS"](): string;
|
||||
/**
|
||||
* `You didn't subscribe to the {{plan}} plan.`
|
||||
*/
|
||||
["error.SUBSCRIPTION_NOT_EXISTS"](options: {
|
||||
readonly plan: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Your subscription has already been canceled.`
|
||||
*/
|
||||
["error.SUBSCRIPTION_HAS_BEEN_CANCELED"](): string;
|
||||
/**
|
||||
* `Your subscription has not been canceled.`
|
||||
*/
|
||||
["error.SUBSCRIPTION_HAS_NOT_BEEN_CANCELED"](): string;
|
||||
/**
|
||||
* `Your subscription has expired.`
|
||||
*/
|
||||
["error.SUBSCRIPTION_EXPIRED"](): string;
|
||||
/**
|
||||
* `Your subscription has already been in {{recurring}} recurring state.`
|
||||
*/
|
||||
["error.SAME_SUBSCRIPTION_RECURRING"](options: {
|
||||
readonly recurring: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Failed to create customer portal session.`
|
||||
*/
|
||||
["error.CUSTOMER_PORTAL_CREATE_FAILED"](): string;
|
||||
/**
|
||||
* `You are trying to access a unknown subscription plan.`
|
||||
*/
|
||||
["error.SUBSCRIPTION_PLAN_NOT_FOUND"](): string;
|
||||
/**
|
||||
* `You cannot update an onetime payment subscription.`
|
||||
*/
|
||||
["error.CANT_UPDATE_ONETIME_PAYMENT_SUBSCRIPTION"](): string;
|
||||
/**
|
||||
* `A workspace is required to checkout for team subscription.`
|
||||
*/
|
||||
["error.WORKSPACE_ID_REQUIRED_FOR_TEAM_SUBSCRIPTION"](): string;
|
||||
/**
|
||||
* `Workspace id is required to update team subscription.`
|
||||
*/
|
||||
["error.WORKSPACE_ID_REQUIRED_TO_UPDATE_TEAM_SUBSCRIPTION"](): string;
|
||||
/**
|
||||
* `Copilot session not found.`
|
||||
*/
|
||||
["error.COPILOT_SESSION_NOT_FOUND"](): string;
|
||||
/**
|
||||
* `Copilot session has been deleted.`
|
||||
*/
|
||||
["error.COPILOT_SESSION_DELETED"](): string;
|
||||
/**
|
||||
* `No copilot provider available.`
|
||||
*/
|
||||
["error.NO_COPILOT_PROVIDER_AVAILABLE"](): string;
|
||||
/**
|
||||
* `Failed to generate text.`
|
||||
*/
|
||||
["error.COPILOT_FAILED_TO_GENERATE_TEXT"](): string;
|
||||
/**
|
||||
* `Failed to create chat message.`
|
||||
*/
|
||||
["error.COPILOT_FAILED_TO_CREATE_MESSAGE"](): string;
|
||||
/**
|
||||
* `Unsplash is not configured.`
|
||||
*/
|
||||
["error.UNSPLASH_IS_NOT_CONFIGURED"](): string;
|
||||
/**
|
||||
* `Action has been taken, no more messages allowed.`
|
||||
*/
|
||||
["error.COPILOT_ACTION_TAKEN"](): string;
|
||||
/**
|
||||
* `Copilot message {{messageId}} not found.`
|
||||
*/
|
||||
["error.COPILOT_MESSAGE_NOT_FOUND"](options: {
|
||||
readonly messageId: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Copilot prompt {{name}} not found.`
|
||||
*/
|
||||
["error.COPILOT_PROMPT_NOT_FOUND"](options: {
|
||||
readonly name: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Copilot prompt is invalid.`
|
||||
*/
|
||||
["error.COPILOT_PROMPT_INVALID"](): string;
|
||||
/**
|
||||
* `Provider {{provider}} failed with {{kind}} error: {{message}}`
|
||||
*/
|
||||
["error.COPILOT_PROVIDER_SIDE_ERROR"](options: Readonly<{
|
||||
provider: string;
|
||||
kind: string;
|
||||
message: string;
|
||||
}>): string;
|
||||
/**
|
||||
* `You have exceeded your blob storage quota.`
|
||||
*/
|
||||
["error.BLOB_QUOTA_EXCEEDED"](): string;
|
||||
/**
|
||||
* `You have exceeded your workspace member quota.`
|
||||
*/
|
||||
["error.MEMBER_QUOTA_EXCEEDED"](): string;
|
||||
/**
|
||||
* `You have reached the limit of actions in this workspace, please upgrade your plan.`
|
||||
*/
|
||||
["error.COPILOT_QUOTA_EXCEEDED"](): string;
|
||||
/**
|
||||
* `Runtime config {{key}} not found.`
|
||||
*/
|
||||
["error.RUNTIME_CONFIG_NOT_FOUND"](options: {
|
||||
readonly key: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Invalid runtime config type for '{{key}}', want '{{want}}', but get {{get}}.`
|
||||
*/
|
||||
["error.INVALID_RUNTIME_CONFIG_TYPE"](options: Readonly<{
|
||||
key: string;
|
||||
want: string;
|
||||
get: string;
|
||||
}>): string;
|
||||
/**
|
||||
* `Mailer service is not configured.`
|
||||
*/
|
||||
["error.MAILER_SERVICE_IS_NOT_CONFIGURED"](): string;
|
||||
/**
|
||||
* `Cannot delete all admin accounts.`
|
||||
*/
|
||||
["error.CANNOT_DELETE_ALL_ADMIN_ACCOUNT"](): string;
|
||||
/**
|
||||
* `Cannot delete own account.`
|
||||
*/
|
||||
["error.CANNOT_DELETE_OWN_ACCOUNT"](): string;
|
||||
/**
|
||||
* `Captcha verification failed.`
|
||||
*/
|
||||
["error.CAPTCHA_VERIFICATION_FAILED"](): string;
|
||||
/**
|
||||
* `Invalid session id to generate license key.`
|
||||
*/
|
||||
["error.INVALID_LICENSE_SESSION_ID"](): string;
|
||||
/**
|
||||
* `License key has been revealed. Please check your mail box of the one provided during checkout.`
|
||||
*/
|
||||
["error.LICENSE_REVEALED"](): string;
|
||||
/**
|
||||
* `Workspace already has a license applied.`
|
||||
*/
|
||||
["error.WORKSPACE_LICENSE_ALREADY_EXISTS"](): string;
|
||||
/**
|
||||
* `License not found.`
|
||||
*/
|
||||
["error.LICENSE_NOT_FOUND"](): string;
|
||||
/**
|
||||
* `Invalid license to activate.`
|
||||
*/
|
||||
["error.INVALID_LICENSE_TO_ACTIVATE"](): string;
|
||||
/**
|
||||
* `Invalid license update params. {{reason}}`
|
||||
*/
|
||||
["error.INVALID_LICENSE_UPDATE_PARAMS"](options: {
|
||||
readonly reason: string;
|
||||
}): string;
|
||||
/**
|
||||
* `You cannot downgrade the workspace from team workspace because there are more than {{limit}} members that are currently active.`
|
||||
*/
|
||||
["error.WORKSPACE_MEMBERS_EXCEED_LIMIT_TO_DOWNGRADE"](options: {
|
||||
readonly limit: string;
|
||||
}): string;
|
||||
} { const { t } = useTranslation(); return useMemo(() => createProxy((key) => t.bind(null, key)), [t]); }
|
||||
function createComponent(i18nKey: string) {
|
||||
return (props) => createElement(Trans, { i18nKey, shouldUnescape: true, ...props });
|
||||
|
||||
@@ -1666,5 +1666,91 @@
|
||||
"com.affine.settings.workspace.storage.unused-blobs.empty": "No unused blobs",
|
||||
"com.affine.settings.workspace.storage.unused-blobs.selected": "Selected",
|
||||
"com.affine.settings.workspace.storage.unused-blobs.delete.title": "Delete blob files",
|
||||
"com.affine.settings.workspace.storage.unused-blobs.delete.warning": "Are you sure you want to delete these blob files? This action cannot be undone. Make sure you no longer need them before proceeding."
|
||||
"com.affine.settings.workspace.storage.unused-blobs.delete.warning": "Are you sure you want to delete these blob files? This action cannot be undone. Make sure you no longer need them before proceeding.",
|
||||
"error.INTERNAL_SERVER_ERROR": "An internal error occurred.",
|
||||
"error.TOO_MANY_REQUEST": "Too many requests.",
|
||||
"error.NOT_FOUND": "Resource not found.",
|
||||
"error.QUERY_TOO_LONG": "Query is too long, max length is {{max}}.",
|
||||
"error.USER_NOT_FOUND": "User not found.",
|
||||
"error.USER_AVATAR_NOT_FOUND": "User avatar not found.",
|
||||
"error.EMAIL_ALREADY_USED": "This email has already been registered.",
|
||||
"error.SAME_EMAIL_PROVIDED": "You are trying to update your account email to the same as the old one.",
|
||||
"error.WRONG_SIGN_IN_CREDENTIALS": "Wrong user email or password: {{email}}",
|
||||
"error.UNKNOWN_OAUTH_PROVIDER": "Unknown authentication provider {{name}}.",
|
||||
"error.OAUTH_STATE_EXPIRED": "OAuth state expired, please try again.",
|
||||
"error.INVALID_OAUTH_CALLBACK_STATE": "Invalid callback state parameter.",
|
||||
"error.MISSING_OAUTH_QUERY_PARAMETER": "Missing query parameter `{{name}}`.",
|
||||
"error.OAUTH_ACCOUNT_ALREADY_CONNECTED": "The third-party account has already been connected to another user.",
|
||||
"error.INVALID_EMAIL": "An invalid email provided: {{email}}",
|
||||
"error.INVALID_PASSWORD_LENGTH": "Password must be between {{min}} and {{max}} characters",
|
||||
"error.PASSWORD_REQUIRED": "Password is required.",
|
||||
"error.WRONG_SIGN_IN_METHOD": "You are trying to sign in by a different method than you signed up with.",
|
||||
"error.EARLY_ACCESS_REQUIRED": "You don't have early access permission. Visit https://community.affine.pro/c/insider-general/ for more information.",
|
||||
"error.SIGN_UP_FORBIDDEN": "You are not allowed to sign up.",
|
||||
"error.EMAIL_TOKEN_NOT_FOUND": "The email token provided is not found.",
|
||||
"error.INVALID_EMAIL_TOKEN": "An invalid email token provided.",
|
||||
"error.LINK_EXPIRED": "The link has expired.",
|
||||
"error.AUTHENTICATION_REQUIRED": "You must sign in first to access this resource.",
|
||||
"error.ACTION_FORBIDDEN": "You are not allowed to perform this action.",
|
||||
"error.ACCESS_DENIED": "You do not have permission to access this resource.",
|
||||
"error.EMAIL_VERIFICATION_REQUIRED": "You must verify your email before accessing this resource.",
|
||||
"error.SPACE_NOT_FOUND": "Space {{spaceId}} not found.",
|
||||
"error.MEMBER_NOT_FOUND_IN_SPACE": "Member not found in Space {{spaceId}}.",
|
||||
"error.NOT_IN_SPACE": "You should join in Space {{spaceId}} before broadcasting messages.",
|
||||
"error.ALREADY_IN_SPACE": "You have already joined in Space {{spaceId}}.",
|
||||
"error.SPACE_ACCESS_DENIED": "You do not have permission to access Space {{spaceId}}.",
|
||||
"error.SPACE_OWNER_NOT_FOUND": "Owner of Space {{spaceId}} not found.",
|
||||
"error.DOC_NOT_FOUND": "Doc {{docId}} under Space {{spaceId}} not found.",
|
||||
"error.DOC_ACCESS_DENIED": "You do not have permission to access doc {{docId}} under Space {{spaceId}}.",
|
||||
"error.VERSION_REJECTED": "Your client with version {{version}} is rejected by remote sync server. Please upgrade to {{serverVersion}}.",
|
||||
"error.INVALID_HISTORY_TIMESTAMP": "Invalid doc history timestamp provided.",
|
||||
"error.DOC_HISTORY_NOT_FOUND": "History of {{docId}} at {{timestamp}} under Space {{spaceId}}.",
|
||||
"error.BLOB_NOT_FOUND": "Blob {{blobId}} not found in Space {{spaceId}}.",
|
||||
"error.EXPECT_TO_PUBLISH_PAGE": "Expected to publish a page, not a Space.",
|
||||
"error.EXPECT_TO_REVOKE_PUBLIC_PAGE": "Expected to revoke a public page, not a Space.",
|
||||
"error.PAGE_IS_NOT_PUBLIC": "Page is not public.",
|
||||
"error.FAILED_TO_SAVE_UPDATES": "Failed to store doc updates.",
|
||||
"error.FAILED_TO_UPSERT_SNAPSHOT": "Failed to store doc snapshot.",
|
||||
"error.UNSUPPORTED_SUBSCRIPTION_PLAN": "Unsupported subscription plan: {{plan}}.",
|
||||
"error.FAILED_TO_CHECKOUT": "Failed to create checkout session.",
|
||||
"error.INVALID_CHECKOUT_PARAMETERS": "Invalid checkout parameters provided.",
|
||||
"error.SUBSCRIPTION_ALREADY_EXISTS": "You have already subscribed to the {{plan}} plan.",
|
||||
"error.INVALID_SUBSCRIPTION_PARAMETERS": "Invalid subscription parameters provided.",
|
||||
"error.SUBSCRIPTION_NOT_EXISTS": "You didn't subscribe to the {{plan}} plan.",
|
||||
"error.SUBSCRIPTION_HAS_BEEN_CANCELED": "Your subscription has already been canceled.",
|
||||
"error.SUBSCRIPTION_HAS_NOT_BEEN_CANCELED": "Your subscription has not been canceled.",
|
||||
"error.SUBSCRIPTION_EXPIRED": "Your subscription has expired.",
|
||||
"error.SAME_SUBSCRIPTION_RECURRING": "Your subscription has already been in {{recurring}} recurring state.",
|
||||
"error.CUSTOMER_PORTAL_CREATE_FAILED": "Failed to create customer portal session.",
|
||||
"error.SUBSCRIPTION_PLAN_NOT_FOUND": "You are trying to access a unknown subscription plan.",
|
||||
"error.CANT_UPDATE_ONETIME_PAYMENT_SUBSCRIPTION": "You cannot update an onetime payment subscription.",
|
||||
"error.WORKSPACE_ID_REQUIRED_FOR_TEAM_SUBSCRIPTION": "A workspace is required to checkout for team subscription.",
|
||||
"error.WORKSPACE_ID_REQUIRED_TO_UPDATE_TEAM_SUBSCRIPTION": "Workspace id is required to update team subscription.",
|
||||
"error.COPILOT_SESSION_NOT_FOUND": "Copilot session not found.",
|
||||
"error.COPILOT_SESSION_DELETED": "Copilot session has been deleted.",
|
||||
"error.NO_COPILOT_PROVIDER_AVAILABLE": "No copilot provider available.",
|
||||
"error.COPILOT_FAILED_TO_GENERATE_TEXT": "Failed to generate text.",
|
||||
"error.COPILOT_FAILED_TO_CREATE_MESSAGE": "Failed to create chat message.",
|
||||
"error.UNSPLASH_IS_NOT_CONFIGURED": "Unsplash is not configured.",
|
||||
"error.COPILOT_ACTION_TAKEN": "Action has been taken, no more messages allowed.",
|
||||
"error.COPILOT_MESSAGE_NOT_FOUND": "Copilot message {{messageId}} not found.",
|
||||
"error.COPILOT_PROMPT_NOT_FOUND": "Copilot prompt {{name}} not found.",
|
||||
"error.COPILOT_PROMPT_INVALID": "Copilot prompt is invalid.",
|
||||
"error.COPILOT_PROVIDER_SIDE_ERROR": "Provider {{provider}} failed with {{kind}} error: {{message}}",
|
||||
"error.BLOB_QUOTA_EXCEEDED": "You have exceeded your blob storage quota.",
|
||||
"error.MEMBER_QUOTA_EXCEEDED": "You have exceeded your workspace member quota.",
|
||||
"error.COPILOT_QUOTA_EXCEEDED": "You have reached the limit of actions in this workspace, please upgrade your plan.",
|
||||
"error.RUNTIME_CONFIG_NOT_FOUND": "Runtime config {{key}} not found.",
|
||||
"error.INVALID_RUNTIME_CONFIG_TYPE": "Invalid runtime config type for '{{key}}', want '{{want}}', but get {{get}}.",
|
||||
"error.MAILER_SERVICE_IS_NOT_CONFIGURED": "Mailer service is not configured.",
|
||||
"error.CANNOT_DELETE_ALL_ADMIN_ACCOUNT": "Cannot delete all admin accounts.",
|
||||
"error.CANNOT_DELETE_OWN_ACCOUNT": "Cannot delete own account.",
|
||||
"error.CAPTCHA_VERIFICATION_FAILED": "Captcha verification failed.",
|
||||
"error.INVALID_LICENSE_SESSION_ID": "Invalid session id to generate license key.",
|
||||
"error.LICENSE_REVEALED": "License key has been revealed. Please check your mail box of the one provided during checkout.",
|
||||
"error.WORKSPACE_LICENSE_ALREADY_EXISTS": "Workspace already has a license applied.",
|
||||
"error.LICENSE_NOT_FOUND": "License not found.",
|
||||
"error.INVALID_LICENSE_TO_ACTIVATE": "Invalid license to activate.",
|
||||
"error.INVALID_LICENSE_UPDATE_PARAMS": "Invalid license update params. {{reason}}",
|
||||
"error.WORKSPACE_MEMBERS_EXCEED_LIMIT_TO_DOWNGRADE": "You cannot downgrade the workspace from team workspace because there are more than {{limit}} members that are currently active."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user