diff --git a/.changeset/decouple-error-i18n.md b/.changeset/decouple-error-i18n.md new file mode 100644 index 0000000000..568f4dc2f5 --- /dev/null +++ b/.changeset/decouple-error-i18n.md @@ -0,0 +1,23 @@ +--- +"@prosopo/api-express-router": patch +"@prosopo/procaptcha-frictionless": patch +"@prosopo/procaptcha-bundle": patch +"@prosopo/procaptcha-react": patch +"@prosopo/types-database": patch +"@prosopo/procaptcha-pow": patch +"@prosopo/database": patch +"@prosopo/datasets-fs": patch +"@prosopo/provider": patch +"@prosopo/common": patch +"@prosopo/locale": patch +"@prosopo/env": patch +"@prosopo/cli": patch +--- + +Decouple error classes from i18n and logging, and move translations into a conventional i18n structure. + +- `ProsopoBaseError` and its subclasses no longer translate or log at construction time. They carry a `translationKey` and a fallback `message`; translation happens at the presentation layer (UI render or HTTP response via `unwrapError`). +- Removed the `i18n`, `logger` and `logLevel` constructor options from the error classes; callers log explicitly via their own logger. +- Error keys are validated against the translation files at compile time (`TranslationKey`), and the curated backend error-key registry (`BACKEND_ERROR_KEYS_ARRAY`) is preserved in the frontend bundle. +- Added the translation keys referenced by backend errors to every locale so the locale key sets stay in sync. +- Every error class now takes a required `TranslationKey` as its first argument and an optional causing `Error` via `options.cause` (whose message becomes the fallback). `ProsopoApiError` no longer accepts a raw `Error`. Internal/CLI errors that have no user-facing key use the `GENERAL.UNKNOWN` placeholder with the detail carried in `options.message`. diff --git a/demos/client-example-server/src/app.ts b/demos/client-example-server/src/app.ts index 34a9323c2f..c364782637 100644 --- a/demos/client-example-server/src/app.ts +++ b/demos/client-example-server/src/app.ts @@ -101,7 +101,6 @@ async function main() { if (!process.env.PROSOPO_SITE_PRIVATE_KEY) { const mnemonicError = new ProsopoEnvError("GENERAL.MNEMONIC_UNDEFINED", { context: { missingParams: ["PROSOPO_SITE_PRIVATE_KEY"] }, - logger, }); logger.error(() => ({ err: mnemonicError })); diff --git a/demos/provider-mock/src/api.ts b/demos/provider-mock/src/api.ts index 81b8f0afa3..eb73a1abb2 100644 --- a/demos/provider-mock/src/api.ts +++ b/demos/provider-mock/src/api.ts @@ -53,7 +53,6 @@ export function prosopoRouter(): Router { return next( new ProsopoApiError("CAPTCHA.PARSE_ERROR", { context: { error: err, code: 400 }, - logLevel: "info", }), ); } diff --git a/demos/provider-mock/src/db.ts b/demos/provider-mock/src/db.ts index fc89b0d338..84367321a1 100644 --- a/demos/provider-mock/src/db.ts +++ b/demos/provider-mock/src/db.ts @@ -101,7 +101,6 @@ export class JA4Database extends MongoDatabase { if (!this.tables) { throw new ProsopoDBError("DATABASE.TABLES_UNDEFINED", { context: { failedFuncName: this.getTables.name }, - logger: this.logger, }); } return this.tables; diff --git a/dev/config/src/vite/vite-plugin-remove-unused-translations.ts b/dev/config/src/vite/vite-plugin-remove-unused-translations.ts index 74228e9fc4..3e12ec1858 100644 --- a/dev/config/src/vite/vite-plugin-remove-unused-translations.ts +++ b/dev/config/src/vite/vite-plugin-remove-unused-translations.ts @@ -63,10 +63,22 @@ export const unflatten = ( return result; }; +// This plugin uses static string scanning: it scans each source file for the +// presence of each known translation key as a literal substring. It only works +// for keys that appear verbatim in the bundled source — keys constructed at +// runtime (e.g. template literals, variable lookups, or keys from API responses) +// will be treated as unused and stripped. Add such keys to translationKeys +// statically, or they will be missing from the bundle. +// +// Backend error keys are always preserved in the bundle since they're returned +// by the server and not found in frontend source code. export default function VitePluginRemoveUnusedTranslations( translationKeys: string[], jsonPattern: string, + backendErrorKeys?: string[], ): Plugin { + const backendKeys = new Set(backendErrorKeys || []); + return { name: "remove-unused-translations", transform(code: string) { @@ -94,9 +106,11 @@ export default function VitePluginRemoveUnusedTranslations( const jsonData = JSON.parse(content); const jsonDataFlattened = flatten(jsonData); - // Remove keys that are not in `used` + // Keep keys that are either used in frontend code or are backend error keys const filteredData = Object.fromEntries( - Object.entries(jsonDataFlattened).filter(([key]) => used.has(key)), + Object.entries(jsonDataFlattened).filter( + ([key]) => used.has(key) || backendKeys.has(key), + ), ); const unflattened = unflatten(filteredData); diff --git a/package-lock.json b/package-lock.json index 742ea4acb7..e20c740036 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@prosopo/captcha", - "version": "3.6.35", + "version": "3.6.36", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@prosopo/captcha", - "version": "3.6.35", + "version": "3.6.36", "license": "Apache-2.0", "workspaces": [ "dev/*", @@ -35548,7 +35548,6 @@ "@prosopo/api-route": "2.6.46", "@prosopo/common": "3.1.38", "@prosopo/env": "3.5.10", - "@prosopo/locale": "3.2.4", "@prosopo/logger": "1.0.2", "@prosopo/types": "4.4.0", "@prosopo/util-crypto": "13.5.29", @@ -35701,12 +35700,11 @@ "license": "Apache-2.0", "dependencies": { "@prosopo/locale": "3.2.4", - "@prosopo/logger": "1.0.2", - "i18next": "24.1.0", "zod": "3.23.8" }, "devDependencies": { "@prosopo/config": "3.3.1", + "@prosopo/logger": "1.0.2", "@prosopo/types": "4.4.0", "@types/node": "22.10.2", "@vitest/coverage-v8": "3.2.4", @@ -36522,6 +36520,7 @@ "dependencies": { "@emotion/cache": "11.11.0", "@emotion/react": "11.11.1", + "@prosopo/common": "3.1.38", "@prosopo/dotenv": "3.0.43", "@prosopo/locale": "3.2.4", "@prosopo/procaptcha-common": "2.10.19", diff --git a/packages/api-express-router/package.json b/packages/api-express-router/package.json index 292f3e5abb..7c431dbac6 100644 --- a/packages/api-express-router/package.json +++ b/packages/api-express-router/package.json @@ -30,7 +30,6 @@ "@prosopo/common": "3.1.38", "@prosopo/logger": "1.0.2", "@prosopo/env": "3.5.10", - "@prosopo/locale": "3.2.4", "@prosopo/types": "4.4.0", "@prosopo/util-crypto": "13.5.29", "dotenv": "16.4.5", diff --git a/packages/api-express-router/src/errorHandler.ts b/packages/api-express-router/src/errorHandler.ts index 9a43084032..1aedb44204 100644 --- a/packages/api-express-router/src/errorHandler.ts +++ b/packages/api-express-router/src/errorHandler.ts @@ -24,7 +24,11 @@ export const handleErrors = ( response: Response, next: NextFunction, ) => { - const { code, statusMessage, jsonError } = unwrapError(err, request.i18n); + // `request.logger` is populated by the request-logger middleware; guard the + // call so a missing logger (e.g. a minimal app without that middleware) + // doesn't throw and mask the original error. + request.logger?.error(() => ({ err })); + const { code, statusMessage, jsonError } = unwrapError(err); response.statusMessage = statusMessage; response.set("content-type", "application/json"); response.status(code); diff --git a/packages/api-express-router/src/middlewares/authMiddleware.ts b/packages/api-express-router/src/middlewares/authMiddleware.ts index 9a44fd50e0..5f1f1f0f32 100644 --- a/packages/api-express-router/src/middlewares/authMiddleware.ts +++ b/packages/api-express-router/src/middlewares/authMiddleware.ts @@ -26,8 +26,6 @@ export const authMiddleware = ( try { const jwt = extractJWT(req); - let error: ProsopoApiError | undefined; - if (authAccount?.jwtVerify(jwt).isValid) { next(); return; @@ -39,8 +37,8 @@ export const authMiddleware = ( } res.status(401).json({ - error: new ProsopoEnvError(error || "API.UNAUTHORIZED", { - context: { i18n: req.i18n, code: 401 }, + error: new ProsopoEnvError("API.UNAUTHORIZED", { + context: { code: 401 }, }), }); return; diff --git a/packages/api-express-router/src/tests/unit/errorHandler.unit.test.ts b/packages/api-express-router/src/tests/unit/errorHandler.unit.test.ts index 3f2bea15e9..6ac6db0ad5 100644 --- a/packages/api-express-router/src/tests/unit/errorHandler.unit.test.ts +++ b/packages/api-express-router/src/tests/unit/errorHandler.unit.test.ts @@ -13,18 +13,17 @@ // limitations under the License. import { ProsopoApiError, ProsopoEnvError } from "@prosopo/common"; -import { loadI18next } from "@prosopo/locale"; import type { NextFunction, Request, Response } from "express"; import { describe, expect, it, vi } from "vitest"; import { ZodError } from "zod"; import { handleErrors } from "../../errorHandler.js"; -describe("handleErrors", async () => { - const i18n = await loadI18next(true); - await i18n.changeLanguage("en"); +describe("handleErrors", () => { + const mockRequest = { + logger: { error: vi.fn() }, + } as unknown as Request; - it("should handle ProsopoApiError", async () => { - const mockRequest = { i18n } as unknown as Request; + it("should handle ProsopoApiError", () => { const mockResponse = { writeHead: vi.fn().mockReturnThis(), set: vi.fn().mockReturnThis(), @@ -36,9 +35,7 @@ describe("handleErrors", async () => { const error = new ProsopoApiError("CONTRACT.INVALID_DATA_FORMAT", { context: { code: 400 }, - i18n, }); - console.log(error); handleErrors(error, mockRequest, mockResponse, mockNext); @@ -50,15 +47,14 @@ describe("handleErrors", async () => { error: { code: 400, key: "CONTRACT.INVALID_DATA_FORMAT", - message: "Invalid data format", + message: "CONTRACT.INVALID_DATA_FORMAT", }, }); expect(mockResponse.status).toHaveBeenCalledWith(400); expect(mockResponse.end).toHaveBeenCalled(); }); - it("should not return SyntaxError", async () => { - const mockRequest = { i18n } as unknown as Request; + it("should not return SyntaxError", () => { const mockResponse = { writeHead: vi.fn().mockReturnThis(), set: vi.fn().mockReturnThis(), @@ -89,7 +85,6 @@ describe("handleErrors", async () => { }); it("should handle ZodError", () => { - const mockRequest = { i18n } as unknown as Request; const mockResponse = { writeHead: vi.fn().mockReturnThis(), set: vi.fn().mockReturnThis(), @@ -119,8 +114,7 @@ describe("handleErrors", async () => { expect(mockResponse.end).toHaveBeenCalled(); }); - it("should unwrap nested ProsopoBaseError", async () => { - const mockRequest = { i18n } as unknown as Request; + it("should unwrap nested ProsopoBaseError", () => { const mockResponse = { writeHead: vi.fn().mockReturnThis(), set: vi.fn().mockReturnThis(), @@ -131,9 +125,11 @@ describe("handleErrors", async () => { const mockNext = vi.fn() as unknown as NextFunction; const envError = new ProsopoEnvError("GENERAL.ENVIRONMENT_NOT_READY", { - i18n, + context: { code: 500 }, + }); + const apiError = new ProsopoApiError("API.UNKNOWN", { + context: { error: envError }, }); - const apiError = new ProsopoApiError(envError); handleErrors(apiError, mockRequest, mockResponse, mockNext); @@ -146,14 +142,13 @@ describe("handleErrors", async () => { error: { code: 500, key: "GENERAL.ENVIRONMENT_NOT_READY", - message: "Environment not ready", + message: "GENERAL.ENVIRONMENT_NOT_READY", }, }); expect(mockResponse.end).toHaveBeenCalled(); }); - it("should unwrap nested ProsopoBaseErrors but not an Error that is nested inside them", async () => { - const mockRequest = { i18n } as unknown as Request; + it("should unwrap nested ProsopoBaseErrors but not an Error that is nested inside them", () => { const mockResponse = { writeHead: vi.fn().mockReturnThis(), set: vi.fn().mockReturnThis(), @@ -168,7 +163,6 @@ describe("handleErrors", async () => { const error = new Error("Some error"); const apiError = new ProsopoApiError(key, { context: { code, error }, - i18n, }); handleErrors(apiError, mockRequest, mockResponse, mockNext); @@ -182,7 +176,7 @@ describe("handleErrors", async () => { error: { code, key, - message: "Unknown API error", + message: "API.UNKNOWN", }, }); expect(mockResponse.end).toHaveBeenCalled(); diff --git a/packages/api-express-router/src/tests/unit/middlewares/authMiddleware.unit.test.ts b/packages/api-express-router/src/tests/unit/middlewares/authMiddleware.unit.test.ts index 3cd809331d..a35df8e619 100644 --- a/packages/api-express-router/src/tests/unit/middlewares/authMiddleware.unit.test.ts +++ b/packages/api-express-router/src/tests/unit/middlewares/authMiddleware.unit.test.ts @@ -138,7 +138,7 @@ describe("authMiddleware", () => { expect(mockRes.status).toHaveBeenCalledWith(401); expect(mockRes.json).toHaveBeenCalledWith({ error: new ProsopoEnvError("API.UNAUTHORIZED", { - context: { i18n: mockReq.i18n, code: 401 }, + context: { code: 401 }, }), }); }); @@ -176,7 +176,7 @@ describe("authMiddleware", () => { expect(mockRes.status).toHaveBeenCalledWith(401); expect(mockRes.json).toHaveBeenCalledWith({ error: new ProsopoEnvError("API.UNAUTHORIZED", { - context: { i18n: mockReq.i18n, code: 401 }, + context: { code: 401 }, }), }); }); diff --git a/packages/api-express-router/tsconfig.cjs.json b/packages/api-express-router/tsconfig.cjs.json index 4a645e16f7..34a2c59d03 100644 --- a/packages/api-express-router/tsconfig.cjs.json +++ b/packages/api-express-router/tsconfig.cjs.json @@ -21,9 +21,6 @@ { "path": "../env/tsconfig.cjs.json" }, - { - "path": "../locale/tsconfig.cjs.json" - }, { "path": "../types/tsconfig.cjs.json" }, diff --git a/packages/api-express-router/tsconfig.json b/packages/api-express-router/tsconfig.json index e6bd4c9d60..6261eae902 100644 --- a/packages/api-express-router/tsconfig.json +++ b/packages/api-express-router/tsconfig.json @@ -28,9 +28,6 @@ { "path": "../env" }, - { - "path": "../locale" - }, { "path": "../types" }, diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 3c1e021b65..9edbb26bde 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -14,7 +14,7 @@ import process from "node:process"; import { loadEnv } from "@prosopo/dotenv"; import { getPair } from "@prosopo/keyring"; -import { loadI18next } from "@prosopo/locale"; +import { loadI18nextBackend } from "@prosopo/locale"; import { LogLevel, getLogger } from "@prosopo/logger"; import type { ProsopoConfigOutput } from "@prosopo/types"; import { isMain } from "@prosopo/util"; @@ -59,7 +59,7 @@ async function main() { //if main process if (isMain(import.meta.url, "provider")) { - loadI18next(true).then(() => { + loadI18nextBackend().then(() => { main() .then(() => { log.info(() => ({ msg: "Running main process..." })); diff --git a/packages/common/package.json b/packages/common/package.json index 2fb9905cf2..e2cb604790 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -34,12 +34,11 @@ "license": "Apache-2.0", "dependencies": { "@prosopo/locale": "3.2.4", - "@prosopo/logger": "1.0.2", - "i18next": "24.1.0", "zod": "3.23.8" }, "devDependencies": { "@prosopo/config": "3.3.1", + "@prosopo/logger": "1.0.2", "@types/node": "22.10.2", "@prosopo/types": "4.4.0", "@vitest/coverage-v8": "3.2.4", diff --git a/packages/common/src/error.ts b/packages/common/src/error.ts index 43612f93e0..541f3b8bc1 100644 --- a/packages/common/src/error.ts +++ b/packages/common/src/error.ts @@ -13,19 +13,16 @@ // limitations under the License. import type { TranslationKey } from "@prosopo/locale"; -import { type LogLevel, type Logger, getLogger } from "@prosopo/logger"; import type { ApiJsonError } from "@prosopo/types"; -import type { TFunction } from "i18next"; import { ZodError } from "zod"; type BaseErrorOptions = { name?: string; - translationKey?: TranslationKey; - logger?: Logger; - logLevel?: LogLevel; + message?: string; + // The underlying error that caused this one, if any. Its message is used as + // the fallback `message` when no explicit `message` is provided. + cause?: Error; context?: ContextType; - silent?: boolean; - i18n?: { t: TFunction }; }; interface BaseContextParams { @@ -44,183 +41,89 @@ type ApiContextParams = BaseContextParams & { code?: number; }; -// if i18n is not loaded then we use this -const backupTranslationObj = { t: (key: string) => key }; - export abstract class ProsopoBaseError< ContextType extends BaseContextParams = BaseContextParams, > extends Error { - translationKey: string | undefined; + translationKey: TranslationKey | undefined; + override message: string; context: ContextType | undefined; + cause: Error | undefined; constructor( - error: Error | TranslationKey, + translationKey: TranslationKey, options?: BaseErrorOptions, ) { - const logger = options?.logger || getLogger("info", import.meta.url); - const logLevel = options?.logLevel || "error"; - const i18n = options?.i18n || backupTranslationObj; - if (error instanceof Error) { - super(i18n.t(error.message)); - this.translationKey = options?.translationKey; - this.context = options?.context; - } else { - super(i18n.t(error)); - this.translationKey = error; - this.context = options?.context; - } - if (!options?.silent) this.logError(logger, logLevel, options?.name); - } - - private logError(logger: Logger, logLevel: LogLevel, errorName?: string) { - // `err` at the top level is the queryable, locale-stable identifier in - // log aggregators — prefer the translation key over the translated - // message so dashboards can filter on a constant. - const err = this.translationKey || this.message; - const data = { - errorType: errorName || this.name, - ...(this.context ? { context: this.context } : {}), - }; - if (logLevel === "debug") { - logger.debug(() => ({ err, data: { ...data, stack: this.stack } })); - return; - } - logger.error(() => ({ err, data })); + const message = + options?.message ?? options?.cause?.message ?? translationKey; + super(message); + this.translationKey = translationKey; + this.message = message; + this.cause = options?.cause; + this.context = options?.context; + this.name = options?.name || this.constructor.name; } } // Generic error class -export class ProsopoError extends ProsopoBaseError { - constructor( - error: Error | TranslationKey, - options?: BaseErrorOptions, - ) { - const errorName = options?.name || "ProsopoError"; - const optionsAll = { ...options, name: errorName }; - super(error, optionsAll); - } -} +export class ProsopoError extends ProsopoBaseError {} -export class ProsopoEnvError extends ProsopoBaseError { - constructor( - error: Error | TranslationKey, - options?: BaseErrorOptions, - ) { - const errorName = options?.name || "ProsopoEnvError"; - const optionsAll = { ...options, name: errorName }; - super(error, optionsAll); - } -} +export class ProsopoEnvError extends ProsopoBaseError {} -export class ProsopoContractError extends ProsopoBaseError { - constructor( - error: Error | TranslationKey, - options?: BaseErrorOptions, - ) { - const errorName = options?.name || "ProsopoContractError"; - const optionsAll = { ...options, name: errorName }; - super(error, optionsAll); - } -} +export class ProsopoContractError extends ProsopoBaseError {} -export class ProsopoTxQueueError extends ProsopoBaseError { - constructor( - error: Error | TranslationKey, - options?: BaseErrorOptions, - ) { - const errorName = options?.name || "ProsopoTxQueueError"; - const optionsAll = { ...options, name: errorName }; - super(error, optionsAll); - } -} +export class ProsopoTxQueueError extends ProsopoBaseError {} -export class ProsopoDBError extends ProsopoBaseError { - constructor( - error: Error | TranslationKey, - options?: BaseErrorOptions, - ) { - const errorName = options?.name || "ProsopoDBError"; - const optionsAll = { ...options, name: errorName }; - super(error, optionsAll); - } -} +export class ProsopoDBError extends ProsopoBaseError {} -export class ProsopoCliError extends ProsopoBaseError { - constructor( - error: Error | TranslationKey, - options?: BaseErrorOptions, - ) { - const errorName = options?.name || "ProsopoCliError"; - const optionsAll = { ...options, name: errorName }; - super(error, optionsAll); - } -} +export class ProsopoCliError extends ProsopoBaseError {} -export class ProsopoDatasetError extends ProsopoBaseError { - constructor( - error: Error | TranslationKey, - options?: BaseErrorOptions, - ) { - const errorName = options?.name || "ProsopoDatasetError"; - const optionsAll = { ...options, name: errorName }; - super(error, optionsAll); - } -} +export class ProsopoDatasetError extends ProsopoBaseError {} export class ProsopoApiError extends ProsopoBaseError { code: number; constructor( - error: Error | TranslationKey, + translationKey: TranslationKey, options?: BaseErrorOptions, ) { - const errorName = options?.name || "ProsopoApiError"; const code = options?.context?.code || 500; const optionsAll = { ...options, - name: errorName, context: { ...options?.context, code, - ...(error instanceof ProsopoBaseError && error.translationKey - ? { translationKey: error.translationKey } - : {}), }, }; - super(error, optionsAll); + super(translationKey, optionsAll); this.code = code; } } -export const unwrapError = ( - err: ProsopoBaseError | SyntaxError | ZodError, - i18nInstance?: { t: TFunction }, -) => { - const i18n = i18nInstance || backupTranslationObj; +export const unwrapError = (err: ProsopoBaseError | SyntaxError | ZodError) => { let code = "code" in err ? (err.code as number) : 400; + const baseError = err as ProsopoBaseError; - const message = i18n.t(err.message); // should be translated already - let jsonError: ApiJsonError = { code, message }; + let jsonError: ApiJsonError = { + code, + message: baseError.message || baseError.translationKey || err.message, + }; const statusMessage = "Bad Request"; - jsonError.message = message; - jsonError.key = "translationKey" in err ? err.translationKey : "API.UNKNOWN"; + jsonError.key = baseError.translationKey ?? "API.UNKNOWN"; // unwrap the errors to get the actual error message while (err instanceof ProsopoBaseError && err.context) { - // base error will not have a translation key const contextTranslationKey = typeof err.context.translationKey === "string" ? err.context.translationKey : undefined; jsonError.key = contextTranslationKey || err.translationKey || "API.UNKNOWN"; - jsonError.message = i18n.t(err.message); + jsonError.message = err.message || err.translationKey || "Unknown error"; jsonError.data = err.context.data as Record | undefined; const contextCode = typeof err.context.code === "number" ? err.context.code : undefined; code = contextCode ?? jsonError.code; - // Only move to the next error if ProsopoBaseError or ZodError if ( err.context.error && (err.context.error instanceof ProsopoBaseError || diff --git a/packages/common/src/errorKeys.ts b/packages/common/src/errorKeys.ts new file mode 100644 index 0000000000..79e1ee8356 --- /dev/null +++ b/packages/common/src/errorKeys.ts @@ -0,0 +1,92 @@ +// Copyright 2021-2026 Prosopo (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import type { TranslationKey } from "@prosopo/locale"; + +// Single source of truth for all valid API error keys +export const API_ERROR_KEYS = { + FORBIDDEN: "API.FORBIDDEN", + NO_CONTENT_TYPE_HEADER: "API.NO_CONTENT_TYPE_HEADER", + MISSING_QUERY_PARAMETERS: "API.MISSING_QUERY_PARAMETERS", + MISSING_BODY: "API.MISSING_BODY", + INVALID_BODY: "API.INVALID_BODY", + PARSE_ERROR: "API.PARSE_ERROR", + MISSING_AUTHORIZATION_HEADER: "API.MISSING_AUTHORIZATION_HEADER", + INVALID_AUTHORIZATION_HEADER: "API.INVALID_AUTHORIZATION_HEADER", + INSUFFICIENT_PERMISSIONS: "API.INSUFFICIENT_PERMISSIONS", + NO_PERMISSIONS: "API.NO_PERMISSIONS", + FEATURE_NOT_ENABLED: "API.FEATURE_NOT_ENABLED", + SITE_KEY_NOT_REGISTERED: "API.SITE_KEY_NOT_REGISTERED", + INVALID_SITE_KEY: "API.INVALID_SITE_KEY", + INVALID_DOMAIN: "API.INVALID_DOMAIN", + PROVIDER_VERIFY_FAILED: "API.PROVIDER_VERIFY_FAILED", + TIMESTAMP_TOO_OLD: "API.TIMESTAMP_TOO_OLD", + UNKNOWN: "API.UNKNOWN", +} as const; + +export const GENERAL_ERROR_KEYS = { + ACCOUNT_NOT_FOUND: "GENERAL.ACCOUNT_NOT_FOUND", + SITE_KEY_NOT_FOUND: "GENERAL.SITE_KEY_NOT_FOUND", + MISSING_SECRET_KEY: "GENERAL.MISSING_SECRET_KEY", + INVALID_SIGNATURE: "GENERAL.INVALID_SIGNATURE", + // Thrown by the backend (auth middleware / env guards) and returned to the + // frontend as the error key, so they must be preserved in the frontend + // translation bundle by the Vite pruning plugin. + MISSING_AUTH_HEADER: "GENERAL.MISSING_AUTH_HEADER", + INVALID_JWT: "GENERAL.INVALID_JWT", + UNKNOWN: "GENERAL.UNKNOWN", +} as const; + +export const PORTAL_ERROR_KEYS = { + CANNOT_MODIFY_OWNER_USER: "PORTAL.CANNOT_MODIFY_OWNER_USER", + CANNOT_MODIFY_USER: "PORTAL.CANNOT_MODIFY_USER", + CANNOT_DELETE_OWN_USER: "PORTAL.CANNOT_DELETE_OWN_USER", + CANNOT_DELETE_LAST_USER: "PORTAL.CANNOT_DELETE_LAST_USER", + USER_ALREADY_EXISTS: "PORTAL.USER_ALREADY_EXISTS", + NO_SUGGESTIONS_FOUND: "PORTAL.NO_SUGGESTIONS_FOUND", + CANNOT_DEACTIVATE_LAST_SITE: "PORTAL.CANNOT_DEACTIVATE_LAST_SITE", + API_KEYS_INVALID_NUMBER_OF_SITES: "PORTAL.API_KEYS_INVALID_NUMBER_OF_SITES", + API_KEYS_NOT_FOUND: "PORTAL.API_KEYS_NOT_FOUND", +} as const; + +export const BILLING_ERROR_KEYS = { + STRIPE_PORTAL: "BILLING.STRIPE_PORTAL", + STRIPE_SESSION_NOT_FOUND: "BILLING.STRIPE_SESSION_NOT_FOUND", + STRIPE_PAYMENT_FAILED: "BILLING.STRIPE_PAYMENT_FAILED", +} as const; + +// Union of all error keys +export const ALL_ERROR_KEYS = { + ...API_ERROR_KEYS, + ...GENERAL_ERROR_KEYS, + ...PORTAL_ERROR_KEYS, + ...BILLING_ERROR_KEYS, +} as const; + +// Derive type from keys - this gives TypeScript enforcement +export type ValidErrorKey = + | (typeof API_ERROR_KEYS)[keyof typeof API_ERROR_KEYS] + | (typeof GENERAL_ERROR_KEYS)[keyof typeof GENERAL_ERROR_KEYS] + | (typeof PORTAL_ERROR_KEYS)[keyof typeof PORTAL_ERROR_KEYS] + | (typeof BILLING_ERROR_KEYS)[keyof typeof BILLING_ERROR_KEYS]; + +// Array of all keys for the Vite plugin +export const BACKEND_ERROR_KEYS_ARRAY = Object.values(ALL_ERROR_KEYS); + +// Compile-time check: every backend error key must exist in the locale JSON. +// `BACKEND_ERROR_KEYS_ARRAY` is typed `ValidErrorKey[]`; assigning it to a +// `TranslationKey[]` fails to compile if any `ValidErrorKey` is not a +// `TranslationKey` (i.e. a key here is missing from the translation files). +export const _validateErrorKeysExistInTranslations: readonly TranslationKey[] = + BACKEND_ERROR_KEYS_ARRAY; diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 81012f6526..d55b1c8e8d 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -13,5 +13,6 @@ // limitations under the License. export * from "./error.js"; +export * from "./errorKeys.js"; export * from "./utils/utils.js"; export * from "./utils/batches.js"; diff --git a/packages/common/src/tests/error.unit.test.ts b/packages/common/src/tests/error.unit.test.ts index 87d099a711..708e285711 100644 --- a/packages/common/src/tests/error.unit.test.ts +++ b/packages/common/src/tests/error.unit.test.ts @@ -12,188 +12,62 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { - type LogObject, - type LogRecord, - type LogRecordFn, - type Logger, - NativeLogger, -} from "@prosopo/logger"; -import type { TFunction } from "i18next"; +import { NativeLogger } from "@prosopo/logger"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { ProsopoApiError, ProsopoEnvError, unwrapError } from "../error.js"; -// Tiny stand-in for the i18next translator. Keys present in the map are -// translated, anything else falls through unchanged (mirrors i18next behavior -// for unknown keys). -const makeI18n = (translations: Record): { t: TFunction } => { - const t = ((key: string) => translations[key] ?? key) as unknown as TFunction; - return { t }; -}; - -const englishI18n = makeI18n({ - "CAPTCHA.NO_SESSION_FOUND": "No session found", - "API.INVALID_SITE_KEY": "Invalid site key", - "API.UNKNOWN": "Unknown error", -}); - -const frenchI18n = makeI18n({ - "CAPTCHA.NO_SESSION_FOUND": "Aucune session trouvée", - "API.INVALID_SITE_KEY": "Clé de site invalide", -}); - -// Mock logger that captures the LogRecord produced by each invocation so we -// can assert on the emitted shape. -type CapturedLog = { level: string; record: LogRecord }; - -const makeCapturingLogger = (): { - logger: Logger; - logs: CapturedLog[]; -} => { - const logs: CapturedLog[] = []; - const capture = (level: string) => (fn: LogRecordFn) => { - logs.push({ level, record: fn() }); - }; - const logger: Logger = { - setLogLevel: () => {}, - getLogLevel: () => "info", - getScope: () => "test", - info: capture("info"), - debug: capture("debug"), - trace: capture("trace"), - warn: capture("warn"), - error: capture("error"), - fatal: capture("fatal"), - log: (level, fn) => capture(level)(fn), - with: () => logger, - getPretty: () => false, - setPretty: () => {}, - getPrintStack: () => false, - setPrintStack: () => {}, - getFormat: () => "json", - setFormat: () => {}, - }; - return { logger, logs }; -}; - -describe("ProsopoBaseError.logError", () => { - it("logs the translation key as the top-level `err` field, not the translated message", () => { - const { logger, logs } = makeCapturingLogger(); - - new ProsopoApiError("CAPTCHA.NO_SESSION_FOUND", { +describe("ProsopoBaseError construction is decoupled from i18n and logging", () => { + it("stores the translation key without translating it", () => { + const err = new ProsopoApiError("API.INVALID_SITE_KEY", { context: { code: 400 }, - i18n: englishI18n, - logger, }); - expect(logs).toHaveLength(1); - expect(logs[0]?.level).toBe("error"); - expect(logs[0]?.record.err).toBe("CAPTCHA.NO_SESSION_FOUND"); - // The translated string must not be the top-level err. - expect(logs[0]?.record.err).not.toBe("No session found"); + // The error carries the key verbatim; translation is deferred to the + // presentation layer (UI render / HTTP response), not construction. + expect(err.translationKey).toBe("API.INVALID_SITE_KEY"); + expect(err.message).toBe("API.INVALID_SITE_KEY"); + expect(err.code).toBe(400); }); - it("logs the same translation key regardless of locale", () => { - const { logger: enLogger, logs: enLogs } = makeCapturingLogger(); - const { logger: frLogger, logs: frLogs } = makeCapturingLogger(); - - new ProsopoApiError("CAPTCHA.NO_SESSION_FOUND", { + it("uses an explicit message option as the fallback message while keeping the key", () => { + const err = new ProsopoApiError("API.INVALID_SITE_KEY", { + message: "Invalid site key", context: { code: 400 }, - i18n: englishI18n, - logger: enLogger, }); - new ProsopoApiError("CAPTCHA.NO_SESSION_FOUND", { - context: { code: 400 }, - i18n: frenchI18n, - logger: frLogger, - }); - - expect(enLogs[0]?.record.err).toBe("CAPTCHA.NO_SESSION_FOUND"); - expect(frLogs[0]?.record.err).toBe("CAPTCHA.NO_SESSION_FOUND"); - }); - it("emits errorType and context under `data`, with no `errorParams` nesting", () => { - const { logger, logs } = makeCapturingLogger(); - - new ProsopoApiError("API.INVALID_SITE_KEY", { - context: { code: 400, siteKey: "abc" }, - i18n: englishI18n, - logger, - }); - - const data = logs[0]?.record.data as LogObject & { - errorType?: string; - context?: Record; - errorParams?: unknown; - }; - expect(data?.errorType).toBe("ProsopoApiError"); - expect(data?.context?.code).toBe(400); - expect(data?.context?.siteKey).toBe("abc"); - expect(data?.errorParams).toBeUndefined(); + expect(err.translationKey).toBe("API.INVALID_SITE_KEY"); + expect(err.message).toBe("Invalid site key"); }); - it("does not inject a translated `translationMessage` into context when wrapping an Error", () => { - const { logger, logs } = makeCapturingLogger(); - + it("keeps the causing Error as `cause` and uses its message as the fallback", () => { const inner = new Error("kaboom"); - new ProsopoEnvError(inner, { - translationKey: "API.UNKNOWN", + const err = new ProsopoEnvError("API.UNKNOWN", { + cause: inner, context: { code: 500 }, - i18n: englishI18n, - logger, }); - const data = logs[0]?.record.data as LogObject & { - context?: Record; - }; - expect(data?.context?.translationMessage).toBeUndefined(); - // The translation key still appears at the top level via `err`. - expect(logs[0]?.record.err).toBe("API.UNKNOWN"); + expect(err.cause).toBe(inner); + expect(err.message).toBe("kaboom"); + expect(err.translationKey).toBe("API.UNKNOWN"); }); - it("falls back to `message` when no translation key is available", () => { - const { logger, logs } = makeCapturingLogger(); - - // Constructed from a plain Error with no translationKey option. - new ProsopoEnvError(new Error("raw failure"), { - i18n: englishI18n, - logger, - }); - - expect(logs[0]?.record.err).toBe("raw failure"); - }); - - it("respects `silent: true` and does not log", () => { - const { logger, logs } = makeCapturingLogger(); - - new ProsopoApiError("API.INVALID_SITE_KEY", { - context: { code: 400 }, - i18n: englishI18n, - logger, - silent: true, + it("falls back to the cause's message while keeping a placeholder key", () => { + const err = new ProsopoEnvError("GENERAL.UNKNOWN", { + cause: new Error("raw failure"), }); - expect(logs).toHaveLength(0); + expect(err.translationKey).toBe("GENERAL.UNKNOWN"); + expect(err.message).toBe("raw failure"); }); - it("logs at debug level and includes the stack when logLevel is 'debug'", () => { - const { logger, logs } = makeCapturingLogger(); - - new ProsopoApiError("API.INVALID_SITE_KEY", { - context: { code: 400 }, - i18n: englishI18n, - logger, - logLevel: "debug", - }); + it("defaults the API error code to 500 when none is supplied", () => { + const err = new ProsopoApiError("API.UNKNOWN"); - expect(logs[0]?.level).toBe("debug"); - expect(logs[0]?.record.err).toBe("API.INVALID_SITE_KEY"); - const data = logs[0]?.record.data as LogObject & { stack?: string }; - expect(typeof data?.stack).toBe("string"); + expect(err.code).toBe(500); }); }); -describe("Logger.unpackError prefers translationKey over translated message", () => { +describe("Logger.unpackError prefers translationKey over the translated message", () => { let consoleErrorSpy: ReturnType; beforeEach(() => { @@ -204,27 +78,21 @@ describe("Logger.unpackError prefers translationKey over translated message", () consoleErrorSpy.mockRestore(); }); - it("emits the translation key as the top-level `err` when a ProsopoApiError is passed via { err }", () => { - // Build the error first with `silent: true` so its own auto-log doesn't - // interfere with the spy. - const apiError = new ProsopoApiError("CAPTCHA.NO_SESSION_FOUND", { + it("emits the translation key as the top-level `err` when a ProsopoApiError is logged", () => { + const apiError = new ProsopoApiError("API.INVALID_SITE_KEY", { + message: "Invalid site key", context: { code: 400 }, - i18n: frenchI18n, // .message is "Aucune session trouvée" - silent: true, }); - // `apiError.message` is the (French) translation; we want the logger - // to emit the *key* at top level instead. - expect(apiError.message).toBe("Aucune session trouvée"); - const logger = new NativeLogger("test"); logger.error(() => ({ err: apiError })); expect(consoleErrorSpy).toHaveBeenCalledTimes(1); const output = consoleErrorSpy.mock.calls[0]?.[0] as string; const parsed = JSON.parse(output) as { err?: string }; - expect(parsed.err).toBe("CAPTCHA.NO_SESSION_FOUND"); - expect(parsed.err).not.toBe("Aucune session trouvée"); + // The locale-stable key is logged, not the human-readable message. + expect(parsed.err).toBe("API.INVALID_SITE_KEY"); + expect(parsed.err).not.toBe("Invalid site key"); }); it("falls back to `message` when the error has no translationKey", () => { @@ -238,40 +106,23 @@ describe("Logger.unpackError prefers translationKey over translated message", () }); }); -describe("unwrapError still produces a translated HTTP response", () => { - it("translates the message via i18n for the response body even though the log emits the key", () => { - // Build silently so we don't pollute test output. - const err = new ProsopoApiError("CAPTCHA.NO_SESSION_FOUND", { +describe("unwrapError produces a JSON response carrying the translation key", () => { + it("exposes the translation key and code on the JSON response", () => { + const err = new ProsopoApiError("API.INVALID_SITE_KEY", { + message: "Invalid site key", context: { code: 400 }, - i18n: englishI18n, - silent: true, }); - const { jsonError } = unwrapError(err, englishI18n); - expect(jsonError.message).toBe("No session found"); - expect(jsonError.key).toBe("CAPTCHA.NO_SESSION_FOUND"); + const { code, jsonError } = unwrapError(err); + expect(jsonError.key).toBe("API.INVALID_SITE_KEY"); + expect(jsonError.message).toBe("Invalid site key"); expect(jsonError.code).toBe(400); + expect(code).toBe(400); }); - it("exposes the translation key on the JSON response regardless of construction locale", () => { - // Same error constructed under two different locales; both responses - // must carry the same `key` so clients can branch on it consistently. - const enErr = new ProsopoApiError("CAPTCHA.NO_SESSION_FOUND", { - context: { code: 400 }, - i18n: englishI18n, - silent: true, - }); - const frErr = new ProsopoApiError("CAPTCHA.NO_SESSION_FOUND", { - context: { code: 400 }, - i18n: frenchI18n, - silent: true, - }); - - expect(unwrapError(enErr, englishI18n).jsonError.key).toBe( - "CAPTCHA.NO_SESSION_FOUND", - ); - expect(unwrapError(frErr, frenchI18n).jsonError.key).toBe( - "CAPTCHA.NO_SESSION_FOUND", - ); + it("defaults the key to API.UNKNOWN for a non-Prosopo error that has no translation key", () => { + const { jsonError } = unwrapError(new SyntaxError("raw failure")); + expect(jsonError.key).toBe("API.UNKNOWN"); + expect(jsonError.message).toBe("raw failure"); }); }); diff --git a/packages/database/src/base/mongo.ts b/packages/database/src/base/mongo.ts index 03452fbd15..ea55e92184 100644 --- a/packages/database/src/base/mongo.ts +++ b/packages/database/src/base/mongo.ts @@ -65,7 +65,6 @@ export class MongoDatabase implements IDatabase { if (!this.connection) { throw new ProsopoDBError("DATABASE.CONNECTION_UNDEFINED", { context: { failedFuncName: this.getConnection.name }, - logger: this.logger, }); } return this.connection; diff --git a/packages/database/src/databases/captcha.ts b/packages/database/src/databases/captcha.ts index 37e2b5669d..e963aa59a5 100644 --- a/packages/database/src/databases/captcha.ts +++ b/packages/database/src/databases/captcha.ts @@ -83,7 +83,6 @@ export class CaptchaDatabase extends MongoDatabase implements ICaptchaDatabase { if (!this.tables) { throw new ProsopoDBError("DATABASE.TABLES_UNDEFINED", { context: { failedFuncName: this.getTables.name }, - logger: this.logger, }); } return this.tables; @@ -234,7 +233,6 @@ export class CaptchaDatabase extends MongoDatabase implements ICaptchaDatabase { limit, failedFuncName: this.getCaptchas.name, }, - logger: this.logger, }); } finally { await this.close(); diff --git a/packages/database/src/databases/client.ts b/packages/database/src/databases/client.ts index 8f1c918d95..04f7e6c912 100644 --- a/packages/database/src/databases/client.ts +++ b/packages/database/src/databases/client.ts @@ -58,7 +58,6 @@ export class ClientDatabase extends MongoDatabase implements IClientDatabase { if (!this.tables) { throw new ProsopoDBError("DATABASE.TABLES_UNDEFINED", { context: { failedFuncName: this.getTables.name }, - logger: this.logger, }); } return this.tables; diff --git a/packages/database/src/databases/provider.ts b/packages/database/src/databases/provider.ts index 3fec9953c0..d0b9c1149f 100644 --- a/packages/database/src/databases/provider.ts +++ b/packages/database/src/databases/provider.ts @@ -280,7 +280,6 @@ export class ProviderDatabase if (!this.tables) { throw new ProsopoDBError("DATABASE.TABLES_UNDEFINED", { context: { failedFuncName: this.getTables.name }, - logger: this.logger, }); } return this.tables; @@ -446,7 +445,6 @@ export class ProviderDatabase } catch (err) { throw new ProsopoDBError("DATABASE.DATASET_LOAD_FAILED", { context: { failedFuncName: this.storeDataset.name, error: err }, - logger: this.logger, }); } } @@ -805,7 +803,6 @@ export class ProviderDatabase serverChecked, ipInfo, }, - logger: this.logger, }); this.logger.error(() => ({ err: error, @@ -826,7 +823,6 @@ export class ProviderDatabase if (!this.tables) { throw new ProsopoDBError("DATABASE.DATABASE_UNDEFINED", { context: { failedFuncName: this.getPowCaptchaRecordByChallenge.name }, - logger: this.logger, }); } @@ -870,7 +866,6 @@ export class ProviderDatabase } catch (error) { const err = new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", { context: { error, challenge }, - logger: this.logger, }); this.logger.error(() => ({ err: err, @@ -931,7 +926,6 @@ export class ProviderDatabase challenge, ...update, }, - logger: this.logger, }); this.logger.info(() => ({ err: err, @@ -966,7 +960,6 @@ export class ProviderDatabase challenge, ...update, }, - logger: this.logger, }); this.logger.error(() => ({ err: err, @@ -1057,7 +1050,6 @@ export class ProviderDatabase challenge, ipInfo, }, - logger: this.logger, }); this.logger.error(() => ({ err: error, @@ -1080,7 +1072,6 @@ export class ProviderDatabase context: { failedFuncName: this.getPuzzleCaptchaRecordByChallenge.name, }, - logger: this.logger, }); } @@ -1129,7 +1120,6 @@ export class ProviderDatabase } catch (error) { const err = new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", { context: { error, challenge }, - logger: this.logger, }); this.logger.error(() => ({ err: err, @@ -1193,7 +1183,6 @@ export class ProviderDatabase challenge, ...update, }, - logger: this.logger, }); this.logger.info(() => ({ err: err, @@ -1215,7 +1204,6 @@ export class ProviderDatabase challenge, ...update, }, - logger: this.logger, }); this.logger.error(() => ({ err: err, @@ -1434,7 +1422,6 @@ export class ProviderDatabase } catch (err) { throw new ProsopoDBError("DATABASE.SESSION_STORE_FAILED", { context: { error: err, sessionId: sessionRecord.sessionId }, - logger: this.logger, }); } } @@ -1499,7 +1486,6 @@ export class ProviderDatabase } catch (err) { throw new ProsopoDBError("DATABASE.SESSION_CHECK_REMOVE_FAILED", { context: { error: err, sessionId }, - logger: this.logger, }); } } @@ -1551,7 +1537,6 @@ export class ProviderDatabase } catch (err) { throw new ProsopoDBError("DATABASE.SESSION_GET_FAILED", { context: { error: err, sessionId }, - logger: this.logger, }); } } @@ -1582,7 +1567,6 @@ export class ProviderDatabase } catch (err) { throw new ProsopoDBError("DATABASE.SESSION_GET_FAILED", { context: { error: err, sessionId, stage }, - logger: this.logger, }); } } @@ -1633,7 +1617,6 @@ export class ProviderDatabase } catch (err) { throw new ProsopoDBError("DATABASE.SESSION_GET_FAILED", { context: { error: err, sessionId }, - logger: this.logger, }); } } @@ -1665,7 +1648,6 @@ export class ProviderDatabase } catch (err) { throw new ProsopoDBError("DATABASE.SESSION_GET_FAILED", { context: { error: err, userSitekeyIpHash }, - logger: this.logger, }); } } diff --git a/packages/datasets-fs/src/commands/generate.ts b/packages/datasets-fs/src/commands/generate.ts index 86c17aea66..06c46d29e7 100644 --- a/packages/datasets-fs/src/commands/generate.ts +++ b/packages/datasets-fs/src/commands/generate.ts @@ -90,21 +90,15 @@ export abstract class Generate< // if specified, check files exist const labelledMapFile: string | undefined = args.labelled; if (labelledMapFile && !fs.existsSync(labelledMapFile)) { - throw new ProsopoDatasetError( - new Error(`labelled map file does not exist: ${labelledMapFile}`), - { - translationKey: "FS.FILE_NOT_FOUND", - }, - ); + throw new ProsopoDatasetError("FS.FILE_NOT_FOUND", { + message: `labelled map file does not exist: ${labelledMapFile}`, + }); } const unlabelledMapFile: string | undefined = args.unlabelled; if (unlabelledMapFile && !fs.existsSync(unlabelledMapFile)) { - throw new ProsopoDatasetError( - new Error(`unlabelled map file does not exist: ${unlabelledMapFile}`), - { - translationKey: "FS.FILE_NOT_FOUND", - }, - ); + throw new ProsopoDatasetError("FS.FILE_NOT_FOUND", { + message: `unlabelled map file does not exist: ${unlabelledMapFile}`, + }); } this.labelledMapFile = labelledMapFile || ""; this.unlabelledMapFile = unlabelledMapFile || ""; diff --git a/packages/datasets-fs/src/commands/generateV1.ts b/packages/datasets-fs/src/commands/generateV1.ts index a01b16db2b..595b552cd1 100644 --- a/packages/datasets-fs/src/commands/generateV1.ts +++ b/packages/datasets-fs/src/commands/generateV1.ts @@ -84,12 +84,9 @@ export class GenerateV1 extends Generate { bar.increment(); if (this.targets.length <= 1) { - throw new ProsopoDatasetError( - new Error("not enough different labels in labelled data"), - { - translationKey: "DATASET.NOT_ENOUGH_LABELS", - }, - ); + throw new ProsopoDatasetError("DATASET.NOT_ENOUGH_LABELS", { + message: "not enough different labels in labelled data", + }); } // uniformly sample targets @@ -107,20 +104,14 @@ export class GenerateV1 extends Generate { ); if (targetItems.length < nCorrect) { - throw new ProsopoEnvError( - new Error(`not enough images for target (${target})`), - { - translationKey: "DATASET.NOT_ENOUGH_IMAGES", - }, - ); + throw new ProsopoEnvError("DATASET.NOT_ENOUGH_IMAGES", { + message: `not enough images for target (${target})`, + }); } if (notTargetItems.length < nIncorrect) { - throw new ProsopoDatasetError( - new Error(`not enough non-matching images for target (${target})`), - { - translationKey: "DATASET.NOT_ENOUGH_IMAGES", - }, - ); + throw new ProsopoDatasetError("DATASET.NOT_ENOUGH_IMAGES", { + message: `not enough non-matching images for target (${target})`, + }); } // get the correct items @@ -180,22 +171,16 @@ export class GenerateV1 extends Generate { for (let i = 0; i < unsolved; i++) { bar.increment(); if (this.unlabelled.length <= size) { - throw new ProsopoDatasetError( - new Error("unlabelled map file does not contain enough data"), - { - translationKey: "DATASET.NOT_ENOUGH_IMAGES", - }, - ); + throw new ProsopoDatasetError("DATASET.NOT_ENOUGH_IMAGES", { + message: "unlabelled map file does not contain enough data", + }); } // pick a random label to be the target // note that these are potentially different to the labelled data labels if (this.labels.length <= 0) { - throw new ProsopoDatasetError( - new Error("no labels found for unlabelled data"), - { - translationKey: "DATASET.NOT_ENOUGH_LABELS", - }, - ); + throw new ProsopoDatasetError("DATASET.NOT_ENOUGH_LABELS", { + message: "no labels found for unlabelled data", + }); } const index = _.random(0, this.labels.length - 1); const target = at(this.labels, index); diff --git a/packages/datasets-fs/src/commands/generateV2.ts b/packages/datasets-fs/src/commands/generateV2.ts index 8eb2025a97..a9ec62db07 100644 --- a/packages/datasets-fs/src/commands/generateV2.ts +++ b/packages/datasets-fs/src/commands/generateV2.ts @@ -95,12 +95,9 @@ export class GenerateV2 extends Generate { private setupTarget(i: number) { const _ = lodash(); if (this.targets.length <= 1) { - throw new ProsopoDatasetError( - new Error("not enough different labels in labelled data"), - { - translationKey: "DATASET.NOT_ENOUGH_LABELS", - }, - ); + throw new ProsopoDatasetError("DATASET.NOT_ENOUGH_LABELS", { + message: "not enough different labels in labelled data", + }); } // uniformly sample targets @@ -122,25 +119,19 @@ export class GenerateV2 extends Generate { ); if (this.unlabelled.length > 0 && nUnlabelled > this.unlabelled.length) { - throw new ProsopoDatasetError(new Error("not enough unlabelled data"), { - translationKey: "DATASET.NOT_ENOUGH_IMAGES", + throw new ProsopoDatasetError("DATASET.NOT_ENOUGH_IMAGES", { + message: "not enough unlabelled data", }); } if (nCorrect > targetItems.length) { - throw new ProsopoDatasetError( - new Error(`not enough images for target (${target})`), - { - translationKey: "DATASET.NOT_ENOUGH_IMAGES", - }, - ); + throw new ProsopoDatasetError("DATASET.NOT_ENOUGH_IMAGES", { + message: `not enough images for target (${target})`, + }); } if (nIncorrect > notTargetItems.length) { - throw new ProsopoDatasetError( - new Error(`not enough non-matching images for target (${target})`), - { - translationKey: "DATASET.NOT_ENOUGH_IMAGES", - }, - ); + throw new ProsopoDatasetError("DATASET.NOT_ENOUGH_IMAGES", { + message: `not enough non-matching images for target (${target})`, + }); } this.#nCorrect = nCorrect; diff --git a/packages/datasets-fs/src/commands/labels.ts b/packages/datasets-fs/src/commands/labels.ts index 6d2130114f..046be109a2 100644 --- a/packages/datasets-fs/src/commands/labels.ts +++ b/packages/datasets-fs/src/commands/labels.ts @@ -46,8 +46,8 @@ export class Labels extends InputOutputCliCommand { const file = args.input; if (!fs.existsSync(file)) { - throw new ProsopoDatasetError(new Error(`file does not exist: ${file}`), { - translationKey: "FS.FILE_NOT_FOUND", + throw new ProsopoDatasetError("FS.FILE_NOT_FOUND", { + message: `file does not exist: ${file}`, }); } diff --git a/packages/datasets-fs/src/commands/resize.ts b/packages/datasets-fs/src/commands/resize.ts index 73cdb0bb3f..070545b267 100644 --- a/packages/datasets-fs/src/commands/resize.ts +++ b/packages/datasets-fs/src/commands/resize.ts @@ -68,22 +68,16 @@ export class Resize extends InputOutputCliCommand { const mapFile: string = args.input; if (!fs.existsSync(mapFile)) { - throw new ProsopoDatasetError( - new Error(`Map file does not exist: ${mapFile}`), - { - translationKey: "FS.FILE_NOT_FOUND", - }, - ); + throw new ProsopoDatasetError("FS.FILE_NOT_FOUND", { + message: `Map file does not exist: ${mapFile}`, + }); } const outDir: string = args.output; const overwrite = args.overwrite || false; if (!overwrite && fs.existsSync(outDir)) { - throw new ProsopoEnvError( - new Error(`Output directory already exists: ${outDir}`), - { - translationKey: "FS.FILE_NOT_FOUND", - }, - ); + throw new ProsopoEnvError("FS.FILE_ALREADY_EXISTS", { + message: `Output directory already exists: ${outDir}`, + }); } // create the output directory diff --git a/packages/datasets-fs/src/utils/input.ts b/packages/datasets-fs/src/utils/input.ts index 64ed4094ee..2a03532716 100644 --- a/packages/datasets-fs/src/utils/input.ts +++ b/packages/datasets-fs/src/utils/input.ts @@ -47,12 +47,9 @@ export class InputCliCommand< await super._check(args); // input must exist if (!fs.existsSync(args.input)) { - throw new ProsopoDatasetError( - new Error(`input path does not exist: ${args.input}`), - { - translationKey: "FS.FILE_NOT_FOUND", - }, - ); + throw new ProsopoDatasetError("FS.FILE_NOT_FOUND", { + message: `input path does not exist: ${args.input}`, + }); } } } diff --git a/packages/datasets-fs/src/utils/output.ts b/packages/datasets-fs/src/utils/output.ts index 051746ec39..2de8f22a03 100644 --- a/packages/datasets-fs/src/utils/output.ts +++ b/packages/datasets-fs/src/utils/output.ts @@ -64,12 +64,9 @@ export class OutputCliCommand< // output must not exist, unless overwrite is true if (this.outputExists()) { if (!args.overwrite) { - throw new ProsopoEnvError( - new Error(`output path already exists: ${args.output}`), - { - translationKey: "FS.FILE_ALREADY_EXISTS", - }, - ); + throw new ProsopoEnvError("FS.FILE_ALREADY_EXISTS", { + message: `output path already exists: ${args.output}`, + }); } } } diff --git a/packages/env/src/env.ts b/packages/env/src/env.ts index 870cf49e78..e2e5ee645e 100644 --- a/packages/env/src/env.ts +++ b/packages/env/src/env.ts @@ -97,27 +97,27 @@ export class Environment implements ProsopoEnvironment { getDb(): ProviderDatabase { if (this.db === undefined) { - throw new ProsopoEnvError( - new Error("db not setup! Please call isReady() first"), - ); + throw new ProsopoEnvError("GENERAL.UNKNOWN", { + message: "db not setup! Please call isReady() first", + }); } return this.db; } getAssetsResolver(): AssetsResolver { if (this.assetsResolver === undefined) { - throw new ProsopoEnvError( - new Error("assetsResolver not setup! Please call isReady() first"), - ); + throw new ProsopoEnvError("GENERAL.UNKNOWN", { + message: "assetsResolver not setup! Please call isReady() first", + }); } return this.assetsResolver; } getPair(): KeyringPair { if (this.pair === undefined) { - throw new ProsopoEnvError( - new Error("pair not setup! Please call isReady() first"), - ); + throw new ProsopoEnvError("GENERAL.UNKNOWN", { + message: "pair not setup! Please call isReady() first", + }); } return this.pair; } @@ -157,7 +157,6 @@ export class Environment implements ProsopoEnvironment { } catch (err) { throw new ProsopoEnvError("GENERAL.ENVIRONMENT_NOT_READY", { context: { error: err }, - logger: this.logger, }); } } diff --git a/packages/locale/src/i18SharedOptions.ts b/packages/locale/src/i18SharedOptions.ts index 5e15c75288..8d82b527ec 100644 --- a/packages/locale/src/i18SharedOptions.ts +++ b/packages/locale/src/i18SharedOptions.ts @@ -23,7 +23,8 @@ const logLevel = export const i18nSharedOptions = { debug: logLevel === "debug", fallbackLng: LanguageSchema.enum.en, - namespace: "translation", + defaultNS: "translation", + ns: ["translation"], supportedLngs: Object.values(Languages), nonExplicitSupportedLngs: false, }; diff --git a/packages/locale/src/i18nBackend.ts b/packages/locale/src/i18nBackend.ts index 5284ae83af..ecb5e8e52b 100644 --- a/packages/locale/src/i18nBackend.ts +++ b/packages/locale/src/i18nBackend.ts @@ -28,7 +28,12 @@ const loadPath = export function initializeI18n( i18nLoadedCallback?: (value: typeof i18n) => void, ) { - if (!i18n.isInitialized && isServerSide()) { + if (!isServerSide()) { + throw new Error( + "initializeI18n (backend) must not be called in browser context — use i18nFrontend instead", + ); + } + if (!i18n.isInitialized) { const lngDetector = new MiddlewareLanguageDetector(null, { order: ["header", "query", "cookie"], }); @@ -38,7 +43,6 @@ export function initializeI18n( .use(lngDetector) // this line should switch the language to the one the user reports in the Accept-Language header .init({ ...i18nSharedOptions, - ns: ["translation"], backend: { loadPath, }, diff --git a/packages/locale/src/i18nMiddleware.ts b/packages/locale/src/i18nMiddleware.ts index ecdbe56d95..a4e39ebf91 100644 --- a/packages/locale/src/i18nMiddleware.ts +++ b/packages/locale/src/i18nMiddleware.ts @@ -13,12 +13,12 @@ // limitations under the License. import { type HandleOptions, handle } from "i18next-http-middleware"; -import loadI18next from "./loadI18next.js"; +import { loadI18nextBackend } from "./loadI18next.js"; async function i18nMiddleware( options: HandleOptions, ): Promise> { - const i18n = await loadI18next(true); + const i18n = await loadI18nextBackend(); return handle(i18n, { ...options }); } diff --git a/packages/locale/src/index.ts b/packages/locale/src/index.ts index 23c12e3387..a93ec0c235 100644 --- a/packages/locale/src/index.ts +++ b/packages/locale/src/index.ts @@ -13,7 +13,11 @@ // limitations under the License. export { default as i18nMiddleware } from "./i18nMiddleware.js"; -export { default as loadI18next } from "./loadI18next.js"; +export { + default as loadI18next, + loadI18nextFrontend, + loadI18nextBackend, +} from "./loadI18next.js"; export { Languages, LanguageSchema } from "./translations.js"; export { isClientSide } from "./util.js"; export { TranslationKeysSchema } from "./translationKey.js"; diff --git a/packages/locale/src/loadI18next.ts b/packages/locale/src/loadI18next.ts index a63f48caa9..3ef8fd3132 100644 --- a/packages/locale/src/loadI18next.ts +++ b/packages/locale/src/loadI18next.ts @@ -13,35 +13,109 @@ // limitations under the License. import type { i18n } from "i18next"; -let i18nInstance: i18n; -async function loadI18next(backend: boolean): Promise { - return new Promise((resolve, reject) => { - try { - if (backend) { - import("./i18nBackend.js").then(({ default: initializeI18n }) => { - if (!i18nInstance) { - // pass the resolver into the i18n init fn which will resolve after i18n connected fires - i18nInstance = initializeI18n(resolve); - } else { - // we've already initialised i18n so just return it - resolve(i18nInstance); - } - }); - } else { - import("./i18nFrontend.js").then(({ default: initializeI18n }) => { - if (!i18nInstance) { - // pass the resolver into the i18 init fn which will resolve after i18 connected fires - i18nInstance = initializeI18n(resolve); - } else { - // we've already initialised i18n so just return it - resolve(i18nInstance); - } - }); - } - } catch (e) { - reject(e); - } - }); + +let frontendInstance: i18n | undefined; +let frontendPromise: Promise | undefined; +let frontendInitialized = false; + +let backendInstance: i18n | undefined; +let backendPromise: Promise | undefined; +let backendInitialized = false; + +export async function loadI18nextFrontend(): Promise { + // Only short-circuit once the instance is fully initialized; while + // initialization is in flight, fall through to the shared promise so + // concurrent callers await readiness instead of a half-ready instance. + if (frontendInstance?.isInitialized) return frontendInstance; + if (!frontendPromise) { + frontendPromise = import("./i18nFrontend.js") + .then( + ({ default: initializeI18n }) => + new Promise((resolve, reject) => { + try { + // Prevent race conditions: only initialize once + if (frontendInitialized) { + if (frontendInstance) return resolve(frontendInstance); + // Still initializing, wait for completion + return; + } + frontendInitialized = true; + + frontendInstance = initializeI18n((i18n) => { + frontendInstance = i18n; + resolve(i18n); + }); + // If init was synchronous (already initialized), resolve now; + // otherwise the loaded callback above resolves it. + if (frontendInstance?.isInitialized) { + resolve(frontendInstance); + } + } catch (e) { + frontendInitialized = false; + reject(e); + } + }), + ) + .catch((e) => { + // Reset cached state so a future call can retry after a failure. + frontendPromise = undefined; + frontendInitialized = false; + throw e; + }); + } + return frontendPromise; +} + +export function getFrontendI18n(): i18n | undefined { + return frontendInstance; +} + +export async function loadI18nextBackend(): Promise { + // Only short-circuit once the instance is fully initialized; while + // initialization is in flight, fall through to the shared promise so + // concurrent callers await readiness instead of a half-ready instance. + if (backendInstance?.isInitialized) return backendInstance; + if (!backendPromise) { + backendPromise = import("./i18nBackend.js") + .then( + ({ default: initializeI18n }) => + new Promise((resolve, reject) => { + try { + // Prevent race conditions: only initialize once + if (backendInitialized) { + if (backendInstance) return resolve(backendInstance); + // Still initializing, wait for completion + return; + } + backendInitialized = true; + + backendInstance = initializeI18n((i18n) => { + backendInstance = i18n; + resolve(i18n); + }); + // If init was synchronous (already initialized), resolve now; + // otherwise the loaded callback above resolves it. + if (backendInstance?.isInitialized) { + resolve(backendInstance); + } + } catch (e) { + backendInitialized = false; + reject(e); + } + }), + ) + .catch((e) => { + // Reset cached state so a future call can retry after a failure. + backendPromise = undefined; + backendInitialized = false; + throw e; + }); + } + return backendPromise; +} + +export async function loadI18next(backend: boolean): Promise { + return backend ? loadI18nextBackend() : loadI18nextFrontend(); } export type { i18n as Ti18n }; diff --git a/packages/locale/src/locales/ar/translation.json b/packages/locale/src/locales/ar/translation.json index 9cc415a235..a3ada4b153 100644 --- a/packages/locale/src/locales/ar/translation.json +++ b/packages/locale/src/locales/ar/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "توقيع غير صالح", "SITE_KEY_MISSING": "مفتاح الموقع مفقود", "ACCOUNT_NOT_FOUND": "الحساب غير موجود", - "INVALID_TIMESTAMP": "الطابع الزمني غير صالح" + "INVALID_TIMESTAMP": "الطابع الزمني غير صالح", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "صلاحيات غير كافية لأداء هذا الإجراء", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "لا يُسمح بالطلبات من شبكات الهاتف المحمول لهذا الموقع", "SATELLITE_BLOCKED": "لا يُسمح بالطلبات من الاتصالات الفضائية لهذا الموقع", "CRAWLER_BLOCKED": "لا يُسمح بالطلبات من برامج الزحف المعروفة لهذا الموقع", - "DISALLOWED_WEBVIEW": "الطلبات من المتصفحات داخل التطبيقات (WebView) غير مسموح بها لهذا الموقع" + "DISALLOWED_WEBVIEW": "الطلبات من المتصفحات داخل التطبيقات (WebView) غير مسموح بها لهذا الموقع", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "لا يمكن تعديل مالك المستخدم", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "لم يتم العثور على اقتراحات", "CANNOT_DEACTIVATE_LAST_SITE": "لا يمكن تعطيل آخر موقع نشط", "DUPLICATE_SITE_NAME": "يوجد موقع بهذا الاسم بالفعل", - "INVALID_SITE_NAME": "يجب أن يحتوي اسم الموقع على أحرف وأرقام وشرطات وشرطات سفلية فقط" + "INVALID_SITE_NAME": "يجب أن يحتوي اسم الموقع على أحرف وأرقام وشرطات وشرطات سفلية فقط", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "طائرات", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "جداول غير معرفة", "CONNECTION_UNDEFINED": "الاتصال غير معرف", "COMMITMENT_FLAG_FAILED": "فشل في تحديد التعهد كمعالج", - "UNKNOWN": "خطأ غير معروف في قاعدة البيانات" + "UNKNOWN": "خطأ غير معروف في قاعدة البيانات", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "خطأ في تحليل كلمة التحقق", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "عناوين IP غير متطابقة", "INVALID_TOKEN": "الرمز غير صالح", "INVALID_SOLUTION": "الحل غير صالح", - "DECRYPTION_ERROR": "خطأ في فك التشفير" + "DECRYPTION_ERROR": "خطأ في فك التشفير", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "معلمة غير صالحة" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "زوج مزود مفقود", "MISSING_ENV_VARIABLE": "متغير البيئة مفقود", "GENERAL": "خطأ تطوير عام، انظر السياق", - "METHOD_NOT_IMPLEMENTED": "الطريقة غير مُنفّذة" + "METHOD_NOT_IMPLEMENTED": "الطريقة غير مُنفّذة", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "الملف غير موجود", "FILE_ALREADY_EXISTS": "الملف موجود بالفعل", "INVALID_DIR_FORMAT": "تنسيق دليل غير صالح" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/az/translation.json b/packages/locale/src/locales/az/translation.json index a32c8a8434..80539d044c 100644 --- a/packages/locale/src/locales/az/translation.json +++ b/packages/locale/src/locales/az/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Yanlış imza", "SITE_KEY_MISSING": "SITE KEY çatışmır", "ACCOUNT_NOT_FOUND": "Hesab tapılmadı", - "INVALID_TIMESTAMP": "Yanlış vaxt damğı" + "INVALID_TIMESTAMP": "Yanlış vaxt damğı", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Bu əməliyyatı yerinə yetirmək üçün kifayət qədər icazə yoxdur", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Bu sayt üçün mobil şəbəkə bağlantılarından sorğulara icazə verilmir", "SATELLITE_BLOCKED": "Bu sayt üçün peyk bağlantılarından sorğulara icazə verilmir", "CRAWLER_BLOCKED": "Bu sayt üçün tanınmış tarayıcılardan sorğulara icazə verilmir", - "DISALLOWED_WEBVIEW": "Bu sayt üçün tətbiqdaxili brauzerlərdən (WebView) sorğulara icazə verilmir" + "DISALLOWED_WEBVIEW": "Bu sayt üçün tətbiqdaxili brauzerlərdən (WebView) sorğulara icazə verilmir", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Sahib istifadəçini dəyişmək olmaz", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Təklif tapılmadı", "CANNOT_DEACTIVATE_LAST_SITE": "Sonaktiv saytı deaktiv etmək olmaz", "DUPLICATE_SITE_NAME": "Bu adda sayt artıq mövcuddur", - "INVALID_SITE_NAME": "Sayt adı yalnız hərflərdən, rəqəmlərdən, defislərdən və alt xətlərdən ibarət olmalıdır" + "INVALID_SITE_NAME": "Sayt adı yalnız hərflərdən, rəqəmlərdən, defislərdən və alt xətlərdən ibarət olmalıdır", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "təyyarələr", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Cədvəllər müəyyən edilməyib", "CONNECTION_UNDEFINED": "Qoşulma müəyyənləndirilməyib", "COMMITMENT_FLAG_FAILED": "Müvafiq olaraq işarələmək alınmadı", - "UNKNOWN": "Naməlum verilənlər bazası səhvi" + "UNKNOWN": "Naməlum verilənlər bazası səhvi", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Captcha analiz edərkən səhv", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP ünvanları uyğun gəlmir", "INVALID_TOKEN": "Yanlış token", "INVALID_SOLUTION": "Yanlış həll", - "DECRYPTION_ERROR": "Şifrəni çözərkən səhv" + "DECRYPTION_ERROR": "Şifrəni çözərkən səhv", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Yanlış parametr" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Təminatçı cütü yoxdur", "MISSING_ENV_VARIABLE": "Mühit dəyişkəni yoxdur", "GENERAL": "Ümumi Dev Xəta, məzmunu gör", - "METHOD_NOT_IMPLEMENTED": "Metod icra olunmadı" + "METHOD_NOT_IMPLEMENTED": "Metod icra olunmadı", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Fayl tapılmadı", "FILE_ALREADY_EXISTS": "Fayl artıq mövcuddur", "INVALID_DIR_FORMAT": "Yanlış qovluq formatı" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/cs/translation.json b/packages/locale/src/locales/cs/translation.json index fa69d50406..d83e5ac6ce 100644 --- a/packages/locale/src/locales/cs/translation.json +++ b/packages/locale/src/locales/cs/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Neplatný podpis", "SITE_KEY_MISSING": "Chybějící SITE KEY", "ACCOUNT_NOT_FOUND": "Účet nenalezen", - "INVALID_TIMESTAMP": "Neplatný časový razítko" + "INVALID_TIMESTAMP": "Neplatný časový razítko", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Nedostatečná oprávnění k provedení této akce", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Požadavky z mobilních sítí nejsou pro tento web povoleny", "SATELLITE_BLOCKED": "Požadavky ze satelitních připojení nejsou pro tento web povoleny", "CRAWLER_BLOCKED": "Požadavky ze známých crawlerů nejsou pro tento web povoleny", - "DISALLOWED_WEBVIEW": "Požadavky z prohlížečů v aplikacích (WebView) nejsou pro tento web povoleny" + "DISALLOWED_WEBVIEW": "Požadavky z prohlížečů v aplikacích (WebView) nejsou pro tento web povoleny", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Nelze upravit vlastníka uživatele", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Nebyly nalezeny žádné návrhy", "CANNOT_DEACTIVATE_LAST_SITE": "Nelze deaktivovat poslední aktivní web", "DUPLICATE_SITE_NAME": "Web s tímto názvem již existuje", - "INVALID_SITE_NAME": "Název webu smí obsahovat pouze písmena, čísla, pomlčky a podtržítka" + "INVALID_SITE_NAME": "Název webu smí obsahovat pouze písmena, čísla, pomlčky a podtržítka", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "letadla", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Tabulky nedefinovány", "CONNECTION_UNDEFINED": "Připojení není definováno", "COMMITMENT_FLAG_FAILED": "Nepodařilo se označit závazek jako zpracovaný", - "UNKNOWN": "Neznámá chyba databáze" + "UNKNOWN": "Neznámá chyba databáze", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Chyba při analýze captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP adresy se neshodují", "INVALID_TOKEN": "Neplatný token", "INVALID_SOLUTION": "Neplatné řešení", - "DECRYPTION_ERROR": "Chyba dešifrování" + "DECRYPTION_ERROR": "Chyba dešifrování", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Neplatný parametr" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Chybějící dvojice poskytovatelů", "MISSING_ENV_VARIABLE": "Chybějící proměnná prostředí", "GENERAL": "Obecná chyba vývoje, viz kontext", - "METHOD_NOT_IMPLEMENTED": "Metoda není implementována" + "METHOD_NOT_IMPLEMENTED": "Metoda není implementována", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Soubor nenalezen", "FILE_ALREADY_EXISTS": "Soubor již existuje", "INVALID_DIR_FORMAT": "Neplatný formát adresáře" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/de/translation.json b/packages/locale/src/locales/de/translation.json index 0d03575339..559dbbb631 100644 --- a/packages/locale/src/locales/de/translation.json +++ b/packages/locale/src/locales/de/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Ungültige Signatur", "SITE_KEY_MISSING": "SITE-KEY fehlt", "ACCOUNT_NOT_FOUND": "Konto nicht gefunden", - "INVALID_TIMESTAMP": "Ungültiger Zeitstempel" + "INVALID_TIMESTAMP": "Ungültiger Zeitstempel", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Unzureichende Berechtigungen zur Ausführung dieser Aktion", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Anfragen von Mobilfunkverbindungen sind für diese Website nicht erlaubt", "SATELLITE_BLOCKED": "Anfragen von Satellitenverbindungen sind für diese Website nicht erlaubt", "CRAWLER_BLOCKED": "Anfragen von bekannten Crawlern sind für diese Website nicht erlaubt", - "DISALLOWED_WEBVIEW": "Anfragen aus In-App-Browsern (WebView) sind für diese Website nicht erlaubt" + "DISALLOWED_WEBVIEW": "Anfragen aus In-App-Browsern (WebView) sind für diese Website nicht erlaubt", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Kann den Besitzerbenutzer nicht ändern", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Keine Vorschläge gefunden", "CANNOT_DEACTIVATE_LAST_SITE": "Kann den letzten aktiven Standort nicht deaktivieren", "DUPLICATE_SITE_NAME": "Eine Website mit diesem Namen existiert bereits", - "INVALID_SITE_NAME": "Der Websitename darf nur Buchstaben, Zahlen, Bindestriche und Unterstriche enthalten" + "INVALID_SITE_NAME": "Der Websitename darf nur Buchstaben, Zahlen, Bindestriche und Unterstriche enthalten", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "ACCOUNT": { "NO_POLKADOT_EXTENSION": "Polkadot-Erweiterung nicht gefunden" @@ -121,7 +136,15 @@ "TABLES_UNDEFINED": "Tabellen undefiniert", "CONNECTION_UNDEFINED": "Verbindung undefiniert", "COMMITMENT_FLAG_FAILED": "Verpflichtung konnte nicht als verarbeitet markiert werden", - "UNKNOWN": "Unbekannter Datenbankfehler" + "UNKNOWN": "Unbekannter Datenbankfehler", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Fehler beim Parsen des Captchas", @@ -139,7 +162,11 @@ "IP_ADDRESS_MISMATCH": "IP-Adresse stimmt nicht überein", "INVALID_TOKEN": "Ungültiges Token", "INVALID_SOLUTION": "Ungültige Lösung", - "DECRYPTION_ERROR": "Fehler beim Entschlüsseln" + "DECRYPTION_ERROR": "Fehler beim Entschlüsseln", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Ungültiger Parameter" @@ -150,7 +177,8 @@ "MISSING_PROVIDER_PAIR": "Fehlendes Anbieterpaar", "MISSING_ENV_VARIABLE": "Fehlende Umgebungsvariable", "GENERAL": "Allgemeiner Entwicklerfehler, siehe Kontext", - "METHOD_NOT_IMPLEMENTED": "Methode nicht implementiert" + "METHOD_NOT_IMPLEMENTED": "Methode nicht implementiert", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Datei nicht gefunden", @@ -455,5 +483,10 @@ "sword": "Schwert", "syringe": "Spritze", "tambourine": "Tamburin" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/el/translation.json b/packages/locale/src/locales/el/translation.json index 06a284e328..7151c428b4 100644 --- a/packages/locale/src/locales/el/translation.json +++ b/packages/locale/src/locales/el/translation.json @@ -38,7 +38,13 @@ "MOBILE_BLOCKED": "Αιτήματα από συνδέσεις κινητών δικτύων δεν επιτρέπονται για αυτόν τον ιστότοπο", "SATELLITE_BLOCKED": "Αιτήματα από δορυφορικές συνδέσεις δεν επιτρέπονται για αυτόν τον ιστότοπο", "CRAWLER_BLOCKED": "Αιτήματα από γνωστά προγράμματα ανίχνευσης δεν επιτρέπονται για αυτόν τον ιστότοπο", - "DISALLOWED_WEBVIEW": "Δεν επιτρέπονται αιτήματα από ενσωματωμένους περιηγητές (WebView) για αυτόν τον ιστότοπο" + "DISALLOWED_WEBVIEW": "Δεν επιτρέπονται αιτήματα από ενσωματωμένους περιηγητές (WebView) για αυτόν τον ιστότοπο", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "TARGET": { "animals": "ζώα", @@ -350,7 +356,13 @@ "INVALID_SIGNATURE": "Μη έγκυρη υπογραφή", "SITE_KEY_MISSING": "Λείπει το SITE KEY", "ACCOUNT_NOT_FOUND": "Δεν βρέθηκε λογαριασμός", - "INVALID_TIMESTAMP": "Μη έγκυρη σφραγίδα χρόνου" + "INVALID_TIMESTAMP": "Μη έγκυρη σφραγίδα χρόνου", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Δεν είναι δυνατή η τροποποίηση του χρήστη-κατόχου", @@ -360,7 +372,10 @@ "NO_SUGGESTIONS_FOUND": "Δεν βρέθηκαν προτάσεις", "CANNOT_DEACTIVATE_LAST_SITE": "Δεν είναι δυνατή η απενεργοποίηση του τελευταίου ιστότοπου", "DUPLICATE_SITE_NAME": "Υπάρχει ήδη ιστότοπος με αυτό το όνομα", - "INVALID_SITE_NAME": "Το όνομα ιστότοπου πρέπει να περιέχει μόνο γράμματα, αριθμούς, παύλες και κάτω παύλες" + "INVALID_SITE_NAME": "Το όνομα ιστότοπου πρέπει να περιέχει μόνο γράμματα, αριθμούς, παύλες και κάτω παύλες", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "ACCOUNT": { "NO_POLKADOT_EXTENSION": "Δεν βρέθηκε επέκταση Polkadot" @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Οι πίνακες δεν έχουν οριστεί", "CONNECTION_UNDEFINED": "Η σύνδεση δεν έχει οριστεί", "COMMITMENT_FLAG_FAILED": "Αποτυχία σημαίας δέσμευσης ως επεξεργασμένη", - "UNKNOWN": "Άγνωστο σφάλμα βάσης δεδομένων" + "UNKNOWN": "Άγνωστο σφάλμα βάσης δεδομένων", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Σφάλμα ανάλυσης captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "Οι διευθύνσεις IP δεν ταιριάζουν", "INVALID_TOKEN": "Μη έγκυρο τεκμήριο", "INVALID_SOLUTION": "Μη έγκυρη λύση", - "DECRYPTION_ERROR": "Σφάλμα αποκρυπτογράφησης" + "DECRYPTION_ERROR": "Σφάλμα αποκρυπτογράφησης", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Μη έγκυρη παράμετρος" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Λείπει ζεύγος παρόχου", "MISSING_ENV_VARIABLE": "Λείπει μεταβλητή περιβάλλοντος", "GENERAL": "Γενικό σφάλμα ανάπτυξης, δες τα συμφραζόμενα", - "METHOD_NOT_IMPLEMENTED": "Η μέθοδος δεν έχει υλοποιηθεί" + "METHOD_NOT_IMPLEMENTED": "Η μέθοδος δεν έχει υλοποιηθεί", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Αρχείο δεν βρέθηκε", "FILE_ALREADY_EXISTS": "Το αρχείο υπάρχει ήδη", "INVALID_DIR_FORMAT": "Μη έγκυρος τύπος φακέλου" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/en/translation.json b/packages/locale/src/locales/en/translation.json index 2b47a5e7b7..88cab62658 100644 --- a/packages/locale/src/locales/en/translation.json +++ b/packages/locale/src/locales/en/translation.json @@ -24,8 +24,14 @@ "SITE_KEY_MISSING": "SITE KEY missing", "ACCOUNT_NOT_FOUND": "Account not found", "SITE_KEY_NOT_FOUND": "Site key not found", + "UNKNOWN": "Unknown error", "INVALID_TIMESTAMP": "Invalid timestamp", - "MISSING_SECRET_KEY": "Missing secret key" + "MISSING_SECRET_KEY": "Missing secret key", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing" }, "CONTRACT": { "INVALID_ADDRESS": "Failed to encode invalid address", @@ -70,9 +76,19 @@ "TABLES_UNDEFINED": "Tables undefined", "CONNECTION_UNDEFINED": "Connection undefined", "COMMITMENT_FLAG_FAILED": "Failed to flag commitment as processed", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined", "UNKNOWN": "Unknown database error" }, "CAPTCHA": { + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", "PARSE_ERROR": "Error parsing captcha", "INVALID_CAPTCHA_ID": "Invalid captcha id", "INVALID_ITEM_FORMAT": "Only image and text item types allowed", @@ -83,11 +99,13 @@ "MISSING_ITEM_HASH": "missing item hash", "INVALID_CAPTCHA_CHALLENGE": "Invalid captcha challenge", "DAPP_USER_SOLUTION_NOT_FOUND": "Dapp user solution not found", + "SOLUTION_NOT_FOUND": "Solution not found", "NO_CAPTCHA": "No captcha found", "NO_SESSION_FOUND": "No session found", "IP_ADDRESS_MISMATCH": "IP address mismatch detected", "INVALID_TOKEN": "Invalid token", "INVALID_SOLUTION": "Invalid solution", + "INVALID_TIMESTAMP": "Invalid timestamp", "DECRYPTION_ERROR": "Error decrypting" }, "API": { @@ -100,6 +118,8 @@ "USER_NOT_VERIFIED_NO_SOLUTION": "User not verified. No captcha solution found.", "USER_ALREADY_VERIFIED": "This solution has already been verified. User should complete a new captcha.", "UNKNOWN": "Unknown API error", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", "SITE_KEY_NOT_REGISTERED": "Site key not registered", "INCORRECT_CAPTCHA_TYPE": "Incorrect CAPTCHA type", "INSUFFICIENT_PERMISSIONS": "Insufficient permissions to perform this action", @@ -119,6 +139,10 @@ "ACCESS_POLICY_BLOCK": "Access blocked by policy", "FORBIDDEN": "Forbidden", "PROVIDER_VERIFY_FAILED": "Provider verification failed", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account", "SPAM_EMAIL_DOMAIN": "Email domain not allowed", "SPAM_EMAIL_RULE": "Email address blocked by spam filter rules", "VPN_BLOCKED": "Requests from VPN connections are not allowed for this site", @@ -133,13 +157,21 @@ }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Cannot modify owner user", + "CANNOT_MODIFY_USER": "Cannot modify this user", "CANNOT_DELETE_OWN_USER": "Cannot delete your own account", "CANNOT_DELETE_LAST_USER": "Cannot delete last user", "USER_ALREADY_EXISTS": "User already exists", "NO_SUGGESTIONS_FOUND": "No suggestions found", "CANNOT_DEACTIVATE_LAST_SITE": "Cannot deactivate the last active site", "DUPLICATE_SITE_NAME": "A site with this name already exists", - "INVALID_SITE_NAME": "Site name must contain only letters, numbers, hyphens, and underscores" + "INVALID_SITE_NAME": "Site name must contain only letters, numbers, hyphens, and underscores", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" }, "CLI": { "PARAMETER_ERROR": "Invalid parameter" @@ -149,6 +181,7 @@ "PROVIDER_NO_CAPTCHA": "No captchas returned from provider", "MISSING_PROVIDER_PAIR": "Missing provider pair", "MISSING_ENV_VARIABLE": "Missing environment variable", + "MISSING_SECRET_KEY": "Missing secret key", "GENERAL": "General Dev Error, see context", "METHOD_NOT_IMPLEMENTED": "Method not implemented" }, diff --git a/packages/locale/src/locales/es/translation.json b/packages/locale/src/locales/es/translation.json index 6b7ad3f9eb..04f810489c 100644 --- a/packages/locale/src/locales/es/translation.json +++ b/packages/locale/src/locales/es/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Firma inválida", "SITE_KEY_MISSING": "Falta la CLAVE DEL SITIO", "ACCOUNT_NOT_FOUND": "Cuenta no encontrada", - "INVALID_TIMESTAMP": "Marca de tiempo inválida" + "INVALID_TIMESTAMP": "Marca de tiempo inválida", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Permisos insuficientes para realizar esta acción", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Las solicitudes desde redes móviles no están permitidas para este sitio", "SATELLITE_BLOCKED": "Las solicitudes desde conexiones satelitales no están permitidas para este sitio", "CRAWLER_BLOCKED": "Las solicitudes desde rastreadores conocidos no están permitidas para este sitio", - "DISALLOWED_WEBVIEW": "No se permiten solicitudes desde navegadores integrados en aplicaciones (WebView) para este sitio" + "DISALLOWED_WEBVIEW": "No se permiten solicitudes desde navegadores integrados en aplicaciones (WebView) para este sitio", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "No se puede modificar el usuario propietario", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "No se encontraron sugerencias", "CANNOT_DEACTIVATE_LAST_SITE": "No se puede desactivar el último sitio activo", "DUPLICATE_SITE_NAME": "Ya existe un sitio con este nombre", - "INVALID_SITE_NAME": "El nombre del sitio solo debe contener letras, números, guiones y guiones bajos" + "INVALID_SITE_NAME": "El nombre del sitio solo debe contener letras, números, guiones y guiones bajos", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "ACCOUNT": { "NO_POLKADOT_EXTENSION": "Extensión Polkadot no encontrada" @@ -121,7 +136,15 @@ "TABLES_UNDEFINED": "Tablas indefinidas", "CONNECTION_UNDEFINED": "Conexión indefinida", "COMMITMENT_FLAG_FAILED": "Error al marcar el compromiso como procesado", - "UNKNOWN": "Error desconocido de base de datos" + "UNKNOWN": "Error desconocido de base de datos", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Error al analizar el captcha", @@ -139,7 +162,11 @@ "IP_ADDRESS_MISMATCH": "Las direcciones IP no coinciden", "INVALID_TOKEN": "Token inválido", "INVALID_SOLUTION": "Solución inválida", - "DECRYPTION_ERROR": "Error de descifrado" + "DECRYPTION_ERROR": "Error de descifrado", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Parámetro inválido" @@ -150,7 +177,8 @@ "MISSING_PROVIDER_PAIR": "Falta el par de proveedor", "MISSING_ENV_VARIABLE": "Falta una variable de entorno", "GENERAL": "Error general de desarrollo, ver contexto", - "METHOD_NOT_IMPLEMENTED": "Método no implementado" + "METHOD_NOT_IMPLEMENTED": "Método no implementado", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Archivo no encontrado", @@ -455,5 +483,10 @@ "sword": "espada", "syringe": "jeringa", "tambourine": "pandereta" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/fi/translation.json b/packages/locale/src/locales/fi/translation.json index 5b56aacfa2..74f1ad19e4 100644 --- a/packages/locale/src/locales/fi/translation.json +++ b/packages/locale/src/locales/fi/translation.json @@ -15,7 +15,11 @@ "INVALID_CAPTCHA_ID": "Virheellinen captcha-tunnus", "INVALID_ITEM_FORMAT": "Vain kuvan ja tekstin tyyppiset kohteet sallittu", "INVALID_SOLUTION_TYPE": "Virheellinen ratkaisun tyyppi", - "INVALID_ITEM_HASH": "Virheellinen kohteen hajautusarvo" + "INVALID_ITEM_HASH": "Virheellinen kohteen hajautusarvo", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "API": { "CAPTCHA_FAILED": "Vastasit yhteen tai useampaan captchan kysymykseen väärin. Yritä uudelleen", @@ -56,7 +60,13 @@ "MOBILE_BLOCKED": "Mobiiliverkkoyhteyksien pyynnöt eivät ole sallittuja tälle sivustolle", "SATELLITE_BLOCKED": "Satelliittiyhteyksien pyynnöt eivät ole sallittuja tälle sivustolle", "CRAWLER_BLOCKED": "Tunnettujen indeksoijien pyynnöt eivät ole sallittuja tälle sivustolle", - "DISALLOWED_WEBVIEW": "Sovelluksen sisäisistä selaimista (WebView) tulevia pyyntöjä ei sallita tällä sivustolla" + "DISALLOWED_WEBVIEW": "Sovelluksen sisäisistä selaimista (WebView) tulevia pyyntöjä ei sallita tällä sivustolla", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "CLI": { "PARAMETER_ERROR": "Virheellinen parametri" @@ -67,7 +77,8 @@ "MISSING_PROVIDER_PAIR": "Puuttuva palveluntarjoaja pari", "MISSING_ENV_VARIABLE": "Puuttuva ympäristömuuttuja", "GENERAL": "Yleinen kehitysvirhe, katso konteksti", - "METHOD_NOT_IMPLEMENTED": "Menetelmää ei ole toteutettu" + "METHOD_NOT_IMPLEMENTED": "Menetelmää ei ole toteutettu", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Tiedostoa ei löytynyt", @@ -85,7 +96,13 @@ "INVALID_SIGNATURE": "Virheellinen allekirjoitus", "SITE_KEY_MISSING": "Sivuston avain puuttuu", "ACCOUNT_NOT_FOUND": "Tiliä ei löytynyt", - "INVALID_TIMESTAMP": "Virheellinen aikaleima" + "INVALID_TIMESTAMP": "Virheellinen aikaleima", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Ei voida muokata omistajakäyttäjää", @@ -95,7 +112,10 @@ "NO_SUGGESTIONS_FOUND": "Ei ehdotuksia löytynyt", "CANNOT_DEACTIVATE_LAST_SITE": "Viimeistä aktiivista sivustoa ei voi poistaa", "DUPLICATE_SITE_NAME": "Tämänniminen sivusto on jo olemassa", - "INVALID_SITE_NAME": "Sivuston nimi saa sisältää vain kirjaimia, numeroita, väliviivoja ja alaviivoja" + "INVALID_SITE_NAME": "Sivuston nimi saa sisältää vain kirjaimia, numeroita, väliviivoja ja alaviivoja", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "ilmailukoneet", @@ -454,6 +474,19 @@ "TABLES_UNDEFINED": "Tauluja ei määritelty", "CONNECTION_UNDEFINED": "Yhteyttä ei määritelty", "COMMITMENT_FLAG_FAILED": "Sitoumuksen merkitseminen käsitellyksi epäonnistui", - "UNKNOWN": "Tuntematon tietokantavirhe" + "UNKNOWN": "Tuntematon tietokantavirhe", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/fr/translation.json b/packages/locale/src/locales/fr/translation.json index 64700eeef2..76f6085886 100644 --- a/packages/locale/src/locales/fr/translation.json +++ b/packages/locale/src/locales/fr/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Signature invalide", "SITE_KEY_MISSING": "CLÉ DU SITE manquante", "ACCOUNT_NOT_FOUND": "Compte non trouvé", - "INVALID_TIMESTAMP": "Horodatage invalide" + "INVALID_TIMESTAMP": "Horodatage invalide", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Permissions insuffisantes pour effectuer cette action", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Les requêtes provenant de réseaux mobiles ne sont pas autorisées pour ce site", "SATELLITE_BLOCKED": "Les requêtes provenant de connexions satellite ne sont pas autorisées pour ce site", "CRAWLER_BLOCKED": "Les requêtes provenant de robots d'exploration connus ne sont pas autorisées pour ce site", - "DISALLOWED_WEBVIEW": "Les requêtes provenant de navigateurs intégrés aux applications (WebView) ne sont pas autorisées pour ce site" + "DISALLOWED_WEBVIEW": "Les requêtes provenant de navigateurs intégrés aux applications (WebView) ne sont pas autorisées pour ce site", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Impossible de modifier le propriétaire de l'utilisateur", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Aucune suggestion trouvée", "CANNOT_DEACTIVATE_LAST_SITE": "Impossible de désactiver le dernier site actif", "DUPLICATE_SITE_NAME": "Un site avec ce nom existe déjà", - "INVALID_SITE_NAME": "Le nom du site ne doit contenir que des lettres, des chiffres, des tirets et des traits de soulignement" + "INVALID_SITE_NAME": "Le nom du site ne doit contenir que des lettres, des chiffres, des tirets et des traits de soulignement", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "ACCOUNT": { "NO_POLKADOT_EXTENSION": "Extension Polkadot non trouvée" @@ -121,7 +136,15 @@ "TABLES_UNDEFINED": "Tables non définies", "CONNECTION_UNDEFINED": "Connexion non définie", "COMMITMENT_FLAG_FAILED": "Échec du marquage de l'engagement comme traité", - "UNKNOWN": "Erreur de base de données inconnue" + "UNKNOWN": "Erreur de base de données inconnue", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Erreur d'analyse du captcha", @@ -139,7 +162,11 @@ "IP_ADDRESS_MISMATCH": "Les adresses IP ne correspondent pas", "INVALID_TOKEN": "Jeton invalide", "INVALID_SOLUTION": "Solution invalide", - "DECRYPTION_ERROR": "Erreur de décryptage" + "DECRYPTION_ERROR": "Erreur de décryptage", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Paramètre invalide" @@ -150,7 +177,8 @@ "MISSING_PROVIDER_PAIR": "Paire de fournisseurs manquante", "MISSING_ENV_VARIABLE": "Variable d'environnement manquante", "GENERAL": "Erreur Dev Générale, voir le contexte", - "METHOD_NOT_IMPLEMENTED": "Méthode non implémentée" + "METHOD_NOT_IMPLEMENTED": "Méthode non implémentée", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Fichier non trouvé", @@ -455,5 +483,10 @@ "sword": "épée", "syringe": "seringue", "tambourine": "tambourin" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/hi/translation.json b/packages/locale/src/locales/hi/translation.json index 73288b631b..9a616cf270 100644 --- a/packages/locale/src/locales/hi/translation.json +++ b/packages/locale/src/locales/hi/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "अवध हसतकषर", "SITE_KEY_MISSING": "सइट कज गयब ह", "ACCOUNT_NOT_FOUND": "खत नह मल", - "INVALID_TIMESTAMP": "अवध समय चहन" + "INVALID_TIMESTAMP": "अवध समय चहन", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "TARGET": { "pelecaniformes": "पलकनफरमस", @@ -350,7 +356,13 @@ "MOBILE_BLOCKED": "इस साइट के लिए मोबाइल नेटवर्क कनेक्शन से अनुरोध की अनुमति नहीं है", "SATELLITE_BLOCKED": "इस साइट के लिए सैटेलाइट कनेक्शन से अनुरोध की अनुमति नहीं है", "CRAWLER_BLOCKED": "इस साइट के लिए ज्ञात क्रॉलर से अनुरोध की अनुमति नहीं है", - "DISALLOWED_WEBVIEW": "इस साइट के लिए इन-ऐप ब्राउज़र (WebView) से अनुरोध की अनुमति नहीं है" + "DISALLOWED_WEBVIEW": "इस साइट के लिए इन-ऐप ब्राउज़र (WebView) से अनुरोध की अनुमति नहीं है", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "मलक उपयगकरत क सशधत नह कय ज सकत", @@ -360,7 +372,10 @@ "NO_SUGGESTIONS_FOUND": "कई सझव नह मल", "CANNOT_DEACTIVATE_LAST_SITE": "अतम सकरय सइट क नषकरय नह कय ज सकत", "DUPLICATE_SITE_NAME": "इस नाम की साइट पहले से मौजूद है", - "INVALID_SITE_NAME": "साइट के नाम में केवल अक्षर, संख्याएँ, हाइफ़न और अंडरस्कोर होने चाहिए" + "INVALID_SITE_NAME": "साइट के नाम में केवल अक्षर, संख्याएँ, हाइफ़न और अंडरस्कोर होने चाहिए", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "ACCOUNT": { "NO_POLKADOT_EXTENSION": "पलकडट एकसटशन नह मल" @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "टबल अनरदषट", "CONNECTION_UNDEFINED": "कनकशन अनरदषट", "COMMITMENT_FLAG_FAILED": "परतबदधत क परससकरण क रप म झड चढन म वफल", - "UNKNOWN": "अजञत डटबस तरट" + "UNKNOWN": "अजञत डटबस तरट", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "कपच क परस करन म तरट", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP पते मेल नहीं खाते", "INVALID_TOKEN": "अमनय टकन", "INVALID_SOLUTION": "अमनय समधन", - "DECRYPTION_ERROR": "डकरपशन तरट" + "DECRYPTION_ERROR": "डकरपशन तरट", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "अमनय परमटर" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "परवइडर जड गयब ह", "MISSING_ENV_VARIABLE": "परयवरण म गयब चर", "GENERAL": "समनय डव तरट, सदरभ दख", - "METHOD_NOT_IMPLEMENTED": "वध क लग नह कय गय ह" + "METHOD_NOT_IMPLEMENTED": "वध क लग नह कय गय ह", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "फइल नह मल", "FILE_ALREADY_EXISTS": "फइल पहल स मजद ह", "INVALID_DIR_FORMAT": "अमनय नरदशक पररप" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/hu/translation.json b/packages/locale/src/locales/hu/translation.json index 2fd6bf0b95..3225ab4a67 100644 --- a/packages/locale/src/locales/hu/translation.json +++ b/packages/locale/src/locales/hu/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Érvénytelen aláírás", "SITE_KEY_MISSING": "Az oldal kulcs hiányzik", "ACCOUNT_NOT_FOUND": "Felhasználó nem található", - "INVALID_TIMESTAMP": "Érvénytelen időbélyeg" + "INVALID_TIMESTAMP": "Érvénytelen időbélyeg", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Nincs elegendő engedély a művelet végrehajtásához", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Mobilhálózati kapcsolatokról érkező kérések nem engedélyezettek ezen az oldalon", "SATELLITE_BLOCKED": "Műholdas kapcsolatokról érkező kérések nem engedélyezettek ezen az oldalon", "CRAWLER_BLOCKED": "Ismert webrobotoktól érkező kérések nem engedélyezettek ezen az oldalon", - "DISALLOWED_WEBVIEW": "Az alkalmazáson belüli böngészőkből (WebView) érkező kérések nem engedélyezettek ezen az oldalon" + "DISALLOWED_WEBVIEW": "Az alkalmazáson belüli böngészőkből (WebView) érkező kérések nem engedélyezettek ezen az oldalon", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Nem lehet módosítani a tulajdonos felhasználót", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Nincsenek javaslatok", "CANNOT_DEACTIVATE_LAST_SITE": "Nem lehet inaktiválni az utolsó aktív webhelyet", "DUPLICATE_SITE_NAME": "Már létezik ilyen nevű webhely", - "INVALID_SITE_NAME": "A webhely neve csak betűket, számokat, kötőjeleket és aláhúzásjeleket tartalmazhat" + "INVALID_SITE_NAME": "A webhely neve csak betűket, számokat, kötőjeleket és aláhúzásjeleket tartalmazhat", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "repülőgépek", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Táblák nincsenek meghatározva", "CONNECTION_UNDEFINED": "Kapcsolat meghatározatlan", "COMMITMENT_FLAG_FAILED": "Az elkötelezettség jelzése feldolgozottként sikertelen", - "UNKNOWN": "Ismeretlen adatbázis hiba" + "UNKNOWN": "Ismeretlen adatbázis hiba", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Hiba a captcha elemzésekor", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "Az IP címek nem egyeznek", "INVALID_TOKEN": "Érvénytelen token", "INVALID_SOLUTION": "Érvénytelen megoldás", - "DECRYPTION_ERROR": "Hiba a titkosítás közben" + "DECRYPTION_ERROR": "Hiba a titkosítás közben", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Érvénytelen paraméter" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Hiányzó ellátópár", "MISSING_ENV_VARIABLE": "Hiányzó környezeti változó", "GENERAL": "Általános fejlesztői hiba, lásd a kontextust", - "METHOD_NOT_IMPLEMENTED": "Az eljárás nincs implementálva" + "METHOD_NOT_IMPLEMENTED": "Az eljárás nincs implementálva", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Fájl nem található", "FILE_ALREADY_EXISTS": "A fájl már létezik", "INVALID_DIR_FORMAT": "Érvénytelen könyvtár formátum" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/id/translation.json b/packages/locale/src/locales/id/translation.json index 7af8df3436..fa6a1fb15c 100644 --- a/packages/locale/src/locales/id/translation.json +++ b/packages/locale/src/locales/id/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Tanda tangan tidak valid", "SITE_KEY_MISSING": "SITE KEY hilang", "ACCOUNT_NOT_FOUND": "Akun tidak ditemukan", - "INVALID_TIMESTAMP": "Timestamp tidak valid" + "INVALID_TIMESTAMP": "Timestamp tidak valid", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Insufficient permissions to perform this action", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Permintaan dari koneksi jaringan seluler tidak diizinkan untuk situs ini", "SATELLITE_BLOCKED": "Permintaan dari koneksi satelit tidak diizinkan untuk situs ini", "CRAWLER_BLOCKED": "Permintaan dari crawler yang dikenal tidak diizinkan untuk situs ini", - "DISALLOWED_WEBVIEW": "Permintaan dari peramban dalam aplikasi (WebView) tidak diizinkan untuk situs ini" + "DISALLOWED_WEBVIEW": "Permintaan dari peramban dalam aplikasi (WebView) tidak diizinkan untuk situs ini", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Cannot modify owner user", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "No suggestions found", "CANNOT_DEACTIVATE_LAST_SITE": "Cannot deactivate the last active site", "DUPLICATE_SITE_NAME": "Situs dengan nama ini sudah ada", - "INVALID_SITE_NAME": "Nama situs hanya boleh berisi huruf, angka, tanda hubung, dan garis bawah" + "INVALID_SITE_NAME": "Nama situs hanya boleh berisi huruf, angka, tanda hubung, dan garis bawah", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "eroplano", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Tabel tidak ditentukan", "CONNECTION_UNDEFINED": "Koneksi tidak ditentukan", "COMMITMENT_FLAG_FAILED": "Gagal menandai komitmen sebagai diproses", - "UNKNOWN": "Kesalahan database tidak dikenal" + "UNKNOWN": "Kesalahan database tidak dikenal", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Kesalahan parsing captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "Alamat IP tidak cocok", "INVALID_TOKEN": "Invalid token", "INVALID_SOLUTION": "Invalid solution", - "DECRYPTION_ERROR": "Error decrypting" + "DECRYPTION_ERROR": "Error decrypting", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Invalid parameter" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Missing provider pair", "MISSING_ENV_VARIABLE": "Missing environment variable", "GENERAL": "General Dev Error, see context", - "METHOD_NOT_IMPLEMENTED": "Method not implemented" + "METHOD_NOT_IMPLEMENTED": "Method not implemented", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "File not found", "FILE_ALREADY_EXISTS": "File already exists", "INVALID_DIR_FORMAT": "Invalid directory format" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/it/translation.json b/packages/locale/src/locales/it/translation.json index 666f287e82..247ec37702 100644 --- a/packages/locale/src/locales/it/translation.json +++ b/packages/locale/src/locales/it/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Firma non valida", "SITE_KEY_MISSING": "Manca la chiave del sito", "ACCOUNT_NOT_FOUND": "Account non trovato", - "INVALID_TIMESTAMP": "Timestamp non valido" + "INVALID_TIMESTAMP": "Timestamp non valido", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Permissões insuficientes para realizar esta ação", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Le richieste da connessioni di rete mobile non sono consentite per questo sito", "SATELLITE_BLOCKED": "Le richieste da connessioni satellitari non sono consentite per questo sito", "CRAWLER_BLOCKED": "Le richieste da crawler noti non sono consentite per questo sito", - "DISALLOWED_WEBVIEW": "Le richieste da browser integrati nelle app (WebView) non sono consentite per questo sito" + "DISALLOWED_WEBVIEW": "Le richieste da browser integrati nelle app (WebView) non sono consentite per questo sito", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Não é possível modificar o usuário proprietário", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Nenhuma sugestão encontrada", "CANNOT_DEACTIVATE_LAST_SITE": "Não é possível desativar o último site ativo", "DUPLICATE_SITE_NAME": "Esiste già un sito con questo nome", - "INVALID_SITE_NAME": "Il nome del sito deve contenere solo lettere, numeri, trattini e trattini bassi" + "INVALID_SITE_NAME": "Il nome del sito deve contenere solo lettere, numeri, trattini e trattini bassi", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "ACCOUNT": { "NO_POLKADOT_EXTENSION": "Estensione Polkadot non trovata" @@ -121,7 +136,15 @@ "TABLES_UNDEFINED": "Tabelle indefinite", "CONNECTION_UNDEFINED": "Connessione indefinita", "COMMITMENT_FLAG_FAILED": "Impossibile contrassegnare l'impegno come elaborato", - "UNKNOWN": "Errore database sconosciuto" + "UNKNOWN": "Errore database sconosciuto", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Errore nell'analisi del captcha", @@ -139,7 +162,11 @@ "IP_ADDRESS_MISMATCH": "Gli indirizzi IP non corrispondono", "INVALID_TOKEN": "Token non valido", "INVALID_SOLUTION": "Soluzione non valida", - "DECRYPTION_ERROR": "Errore di decodifica" + "DECRYPTION_ERROR": "Errore di decodifica", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Parametro non valido" @@ -150,7 +177,8 @@ "MISSING_PROVIDER_PAIR": "Coppia di fornitori mancante", "MISSING_ENV_VARIABLE": "Variabile d'ambiente mancante", "GENERAL": "Errore di sviluppo generale, vedere il contesto", - "METHOD_NOT_IMPLEMENTED": "Metodo non implementato" + "METHOD_NOT_IMPLEMENTED": "Metodo non implementato", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "File non trovato", @@ -455,5 +483,10 @@ "sword": "spada", "syringe": "siringa", "tambourine": "tamburello" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/ja/translation.json b/packages/locale/src/locales/ja/translation.json index 08a33c49a6..9689350700 100644 --- a/packages/locale/src/locales/ja/translation.json +++ b/packages/locale/src/locales/ja/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "無効な署名", "SITE_KEY_MISSING": "SITE KEYが見つかりません", "ACCOUNT_NOT_FOUND": "アカウントが見つかりません", - "INVALID_TIMESTAMP": "無効なタイムスタンプ" + "INVALID_TIMESTAMP": "無効なタイムスタンプ", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "TARGET": { "homer-simpson": "homer-simpson", @@ -350,7 +356,13 @@ "MOBILE_BLOCKED": "このサイトではモバイルネットワーク接続からのリクエストは許可されていません", "SATELLITE_BLOCKED": "このサイトでは衛星接続からのリクエストは許可されていません", "CRAWLER_BLOCKED": "このサイトでは既知のクローラーからのリクエストは許可されていません", - "DISALLOWED_WEBVIEW": "このサイトではアプリ内ブラウザ (WebView) からのリクエストは許可されていません" + "DISALLOWED_WEBVIEW": "このサイトではアプリ内ブラウザ (WebView) からのリクエストは許可されていません", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "所有者ユーザーを変更できません", @@ -360,7 +372,10 @@ "NO_SUGGESTIONS_FOUND": "提案は見つかりません", "CANNOT_DEACTIVATE_LAST_SITE": "最後のアクティブサイトを無効にすることはできません", "DUPLICATE_SITE_NAME": "この名前のサイトはすでに存在しています", - "INVALID_SITE_NAME": "サイト名には英字、数字、ハイフン、アンダースコアのみ使用できます" + "INVALID_SITE_NAME": "サイト名には英字、数字、ハイフン、アンダースコアのみ使用できます", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "ACCOUNT": { "NO_POLKADOT_EXTENSION": "Polkadot拡張機能が見つかりません" @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "テーブルが未定義です", "CONNECTION_UNDEFINED": "接続が未定義です", "COMMITMENT_FLAG_FAILED": "コミットメントを処理済みとフラグ付けするのに失敗しました", - "UNKNOWN": "不明なデータベースエラー" + "UNKNOWN": "不明なデータベースエラー", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "キャプチャの解析エラー", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IPアドレスが一致しません", "INVALID_TOKEN": "無効なトークン", "INVALID_SOLUTION": "無効なソリューション", - "DECRYPTION_ERROR": "復号エラー" + "DECRYPTION_ERROR": "復号エラー", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "無効なパラメーター" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "プロバイダーペアがありません", "MISSING_ENV_VARIABLE": "環境変数が見つかりません", "GENERAL": "一般的なDevエラー、コンテキストを参照してください", - "METHOD_NOT_IMPLEMENTED": "メソッドは実装されていません" + "METHOD_NOT_IMPLEMENTED": "メソッドは実装されていません", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "ファイルが見つかりません", "FILE_ALREADY_EXISTS": "ファイルはすでに存在します", "INVALID_DIR_FORMAT": "無効なディレクトリ形式" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/jv/translation.json b/packages/locale/src/locales/jv/translation.json index 57c442fb1a..14e7514f21 100644 --- a/packages/locale/src/locales/jv/translation.json +++ b/packages/locale/src/locales/jv/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Tanda tangan tidak valid", "SITE_KEY_MISSING": "Kunci SITUS hilang", "ACCOUNT_NOT_FOUND": "Akun tidak ditemukan", - "INVALID_TIMESTAMP": "Cap waktu tidak valid" + "INVALID_TIMESTAMP": "Cap waktu tidak valid", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Insufficient permissions to perform this action", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Panjaluk saka sambungan jaringan seluler ora diidini kanggo situs iki", "SATELLITE_BLOCKED": "Panjaluk saka sambungan satelit ora diidini kanggo situs iki", "CRAWLER_BLOCKED": "Panjaluk saka crawler sing dikenal ora diidini kanggo situs iki", - "DISALLOWED_WEBVIEW": "Panjaluk saka browser ing aplikasi (WebView) ora diidini kanggo situs iki" + "DISALLOWED_WEBVIEW": "Panjaluk saka browser ing aplikasi (WebView) ora diidini kanggo situs iki", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Cannot modify owner user", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "No suggestions found", "CANNOT_DEACTIVATE_LAST_SITE": "Cannot deactivate the last active site", "DUPLICATE_SITE_NAME": "Situs kanthi jeneng iki wis ana", - "INVALID_SITE_NAME": "Jeneng situs mung kena ngemot aksara, angka, tanda hubung, lan garis ngisor" + "INVALID_SITE_NAME": "Jeneng situs mung kena ngemot aksara, angka, tanda hubung, lan garis ngisor", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "airplanes", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Tabel-tabel tidak ditentukan", "CONNECTION_UNDEFINED": "Koneksi tidak ditentukan", "COMMITMENT_FLAG_FAILED": "Gagal menandai komitmen sebagai diproses", - "UNKNOWN": "Kesalahan database yang tidak diketahui" + "UNKNOWN": "Kesalahan database yang tidak diketahui", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Kesalahan memparsing captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "Alamat IP ora cocok", "INVALID_TOKEN": "Token tidak valid", "INVALID_SOLUTION": "Solusi tidak valid", - "DECRYPTION_ERROR": "Kesalahan dekripsi" + "DECRYPTION_ERROR": "Kesalahan dekripsi", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Parameter tidak valid" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Pasangan penyedia hilang", "MISSING_ENV_VARIABLE": "Variabel lingkungan hilang", "GENERAL": "Kesalahan Dev Umum, lihat konteks", - "METHOD_NOT_IMPLEMENTED": "Metode tidak diimplementasikan" + "METHOD_NOT_IMPLEMENTED": "Metode tidak diimplementasikan", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "File tidak ditemukan", "FILE_ALREADY_EXISTS": "File sudah ada", "INVALID_DIR_FORMAT": "Format direktori tidak valid" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/ko/translation.json b/packages/locale/src/locales/ko/translation.json index cf2ed51441..90b0fc47b8 100644 --- a/packages/locale/src/locales/ko/translation.json +++ b/packages/locale/src/locales/ko/translation.json @@ -10,7 +10,13 @@ "ENVIRONMENT_NOT_READY": "환경이 준비되지 않음", "INVALID_SIGNATURE": "잘못된 서명", "SITE_KEY_MISSING": "SITE KEY가 누락됨", - "INVALID_TIMESTAMP": "잘못된 타임스탬프" + "INVALID_TIMESTAMP": "잘못된 타임스탬프", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "이 작업을 수행할 권한이 충분하지 않음", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "이 사이트에서는 모바일 네트워크 연결의 요청이 허용되지 않습니다", "SATELLITE_BLOCKED": "이 사이트에서는 위성 연결의 요청이 허용되지 않습니다", "CRAWLER_BLOCKED": "이 사이트에서는 알려진 크롤러의 요청이 허용되지 않습니다", - "DISALLOWED_WEBVIEW": "이 사이트에서는 인앱 브라우저(WebView)의 요청이 허용되지 않습니다" + "DISALLOWED_WEBVIEW": "이 사이트에서는 인앱 브라우저(WebView)의 요청이 허용되지 않습니다", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "소유자 사용자를 수정할 수 없음", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "제안을 찾을 수 없음", "CANNOT_DEACTIVATE_LAST_SITE": "마지막 활성 사이트를 비활성화할 수 없음", "DUPLICATE_SITE_NAME": "이 이름의 사이트가 이미 존재합니다", - "INVALID_SITE_NAME": "사이트 이름에는 문자, 숫자, 하이픈 및 밑줄만 포함할 수 있습니다" + "INVALID_SITE_NAME": "사이트 이름에는 문자, 숫자, 하이픈 및 밑줄만 포함할 수 있습니다", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "비행기", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "테이블 정의되지 않음", "CONNECTION_UNDEFINED": "연결 정의되지 않음", "COMMITMENT_FLAG_FAILED": "커밋먼트를 처리된 것으로 플래그 처리 실패함", - "UNKNOWN": "알 수 없는 데이터베이스 오류" + "UNKNOWN": "알 수 없는 데이터베이스 오류", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "캡차 구문 분석 오류", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP 주소가 일치하지 않습니다", "INVALID_TOKEN": "유효하지 않은 토큰", "INVALID_SOLUTION": "유효하지 않은 솔루션", - "DECRYPTION_ERROR": "해제 오류" + "DECRYPTION_ERROR": "해제 오류", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "잘못된 매개변수" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "누락된 제공자 쌍", "MISSING_ENV_VARIABLE": "누락된 환경 변수", "GENERAL": "일반 개발 오류, 상황을 확인하십시오", - "METHOD_NOT_IMPLEMENTED": "구현되지 않은 메소드" + "METHOD_NOT_IMPLEMENTED": "구현되지 않은 메소드", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "파일을 찾을 수 없습니다", "FILE_ALREADY_EXISTS": "파일이 이미 존재합니다", "INVALID_DIR_FORMAT": "유효하지 않은 디렉토리 형식" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/ml/translation.json b/packages/locale/src/locales/ml/translation.json index 9e1d3c922c..aa25073e88 100644 --- a/packages/locale/src/locales/ml/translation.json +++ b/packages/locale/src/locales/ml/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Invalid nga lagda", "SITE_KEY_MISSING": "Nanginahanglan og SITE KEY", "ACCOUNT_NOT_FOUND": "Account dili makita", - "INVALID_TIMESTAMP": "Invalid nga timestamp" + "INVALID_TIMESTAMP": "Invalid nga timestamp", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Insufficientway ermissionspay otay erformpay histay actionway", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "ഈ സൈറ്റിന് മൊബൈൽ നെറ്റ്വർക്ക് കണക്ഷനുകളിൽ നിന്നുള്ള അഭ്യർത്ഥനകൾ അനുവദനീയമല്ല", "SATELLITE_BLOCKED": "ഈ സൈറ്റിന് ഉപഗ്രഹ കണക്ഷനുകളിൽ നിന്നുള്ള അഭ്യർത്ഥനകൾ അനുവദനീയമല്ല", "CRAWLER_BLOCKED": "ഈ സൈറ്റിന് അറിയപ്പെടുന്ന ക്രോളറുകളിൽ നിന്നുള്ള അഭ്യർത്ഥനകൾ അനുവദനീയമല്ല", - "DISALLOWED_WEBVIEW": "ഈ സൈറ്റിന് ഇൻ-ആപ്പ് ബ്രൗസറുകളിൽ (WebView) നിന്നുള്ള അഭ്യർത്ഥനകൾ അനുവദനീയമല്ല" + "DISALLOWED_WEBVIEW": "ഈ സൈറ്റിന് ഇൻ-ആപ്പ് ബ്രൗസറുകളിൽ (WebView) നിന്നുള്ള അഭ്യർത്ഥനകൾ അനുവദനീയമല്ല", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Annotcay odifymay ownerway seruy", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Onay uggestionssay oundfay", "CANNOT_DEACTIVATE_LAST_SITE": "Annotcay eactivateday ethay astlay activeay itesay", "DUPLICATE_SITE_NAME": "ഈ പേരിൽ ഒരു സൈറ്റ് ഇതിനകം നിലവിലുണ്ട്", - "INVALID_SITE_NAME": "സൈറ്റ് പേരിൽ അക്ഷരങ്ങൾ, അക്കങ്ങൾ, ഹൈഫനുകൾ, അടിവരകൾ എന്നിവ മാത്രമേ അടങ്ങിയിരിക്കാവൂ" + "INVALID_SITE_NAME": "സൈറ്റ് പേരിൽ അക്ഷരങ്ങൾ, അക്കങ്ങൾ, ഹൈഫനുകൾ, അടിവരകൾ എന്നിവ മാത്രമേ അടങ്ങിയിരിക്കാവൂ", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "eroplano", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Mga lamesa way butang", "CONNECTION_UNDEFINED": "Koneksiyon wala pa nahimutang", "COMMITMENT_FLAG_FAILED": "Nahimong pakyas ang pag-flag sa commitment nga giproseso", - "UNKNOWN": "Sayop sa dili masayod na database" + "UNKNOWN": "Sayop sa dili masayod na database", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Sayop sa pag-parse sa captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP വിലാസങ്ങൾ പൊരുത്തപ്പെടുന്നില്ല", "INVALID_TOKEN": "Hindi wastong token", "INVALID_SOLUTION": "Hindi wastong solusyon", - "DECRYPTION_ERROR": "Error sa pagdedecrypt" + "DECRYPTION_ERROR": "Error sa pagdedecrypt", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Hindi wastong parameter" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Nawawalang provider pair", "MISSING_ENV_VARIABLE": "Nawawalang environment variable", "GENERAL": "Pangkalahatang Dev Error, tingnan ang konteksto", - "METHOD_NOT_IMPLEMENTED": "Paraan hindi pa naipatutupad" + "METHOD_NOT_IMPLEMENTED": "Paraan hindi pa naipatutupad", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "File ay hindi natagpuan", "FILE_ALREADY_EXISTS": "File ay mayroon na", "INVALID_DIR_FORMAT": "Hindi wastong format ng directory" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/ms/translation.json b/packages/locale/src/locales/ms/translation.json index afba1cc1ca..6cba70cc54 100644 --- a/packages/locale/src/locales/ms/translation.json +++ b/packages/locale/src/locales/ms/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Invalid signature", "SITE_KEY_MISSING": "SITE KEY missing", "ACCOUNT_NOT_FOUND": "Account not found", - "INVALID_TIMESTAMP": "Invalid timestamp" + "INVALID_TIMESTAMP": "Invalid timestamp", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "TARGET": { "horseshoe-crab": "ladam-ketam", @@ -350,7 +356,13 @@ "MOBILE_BLOCKED": "Permintaan daripada sambungan rangkaian mudah alih tidak dibenarkan untuk laman ini", "SATELLITE_BLOCKED": "Permintaan daripada sambungan satelit tidak dibenarkan untuk laman ini", "CRAWLER_BLOCKED": "Permintaan daripada perangkak yang dikenali tidak dibenarkan untuk laman ini", - "DISALLOWED_WEBVIEW": "Permintaan daripada pelayar dalam aplikasi (WebView) tidak dibenarkan untuk laman ini" + "DISALLOWED_WEBVIEW": "Permintaan daripada pelayar dalam aplikasi (WebView) tidak dibenarkan untuk laman ini", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Cannot modify owner user", @@ -360,7 +372,10 @@ "NO_SUGGESTIONS_FOUND": "No suggestions found", "CANNOT_DEACTIVATE_LAST_SITE": "Cannot deactivate the last active site", "DUPLICATE_SITE_NAME": "Laman dengan nama ini sudah wujud", - "INVALID_SITE_NAME": "Nama laman hanya boleh mengandungi huruf, nombor, tanda sempang dan garis bawah" + "INVALID_SITE_NAME": "Nama laman hanya boleh mengandungi huruf, nombor, tanda sempang dan garis bawah", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "ACCOUNT": { "NO_POLKADOT_EXTENSION": "Polkadot extension not found" @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Tables undefined", "CONNECTION_UNDEFINED": "Connection undefined", "COMMITMENT_FLAG_FAILED": "Failed to flag commitment as processed", - "UNKNOWN": "Unknown database error" + "UNKNOWN": "Unknown database error", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Error parsing captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "Alamat IP tidak sepadan", "INVALID_TOKEN": "Invalid token", "INVALID_SOLUTION": "Invalid solution", - "DECRYPTION_ERROR": "Error decrypting" + "DECRYPTION_ERROR": "Error decrypting", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Invalid parameter" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Missing provider pair", "MISSING_ENV_VARIABLE": "Missing environment variable", "GENERAL": "General Dev Error, see context", - "METHOD_NOT_IMPLEMENTED": "Method not implemented" + "METHOD_NOT_IMPLEMENTED": "Method not implemented", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "File not found", "FILE_ALREADY_EXISTS": "File already exists", "INVALID_DIR_FORMAT": "Invalid directory format" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/nl/translation.json b/packages/locale/src/locales/nl/translation.json index a7af38c340..f65e166b0c 100644 --- a/packages/locale/src/locales/nl/translation.json +++ b/packages/locale/src/locales/nl/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Ongeldige handtekening", "SITE_KEY_MISSING": "SITE KEY ontbreekt", "ACCOUNT_NOT_FOUND": "Account niet gevonden", - "INVALID_TIMESTAMP": "Ongeldige tijdstempel" + "INVALID_TIMESTAMP": "Ongeldige tijdstempel", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "TARGET": { "yo-yo": "jojo", @@ -350,7 +356,13 @@ "MOBILE_BLOCKED": "Verzoeken van mobiele netwerkverbindingen zijn niet toegestaan voor deze site", "SATELLITE_BLOCKED": "Verzoeken van satellietverbindingen zijn niet toegestaan voor deze site", "CRAWLER_BLOCKED": "Verzoeken van bekende crawlers zijn niet toegestaan voor deze site", - "DISALLOWED_WEBVIEW": "Verzoeken van in-app-browsers (WebView) zijn niet toegestaan voor deze site" + "DISALLOWED_WEBVIEW": "Verzoeken van in-app-browsers (WebView) zijn niet toegestaan voor deze site", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Kan eigenaar gebruiker niet wijzigen", @@ -360,7 +372,10 @@ "NO_SUGGESTIONS_FOUND": "Geen suggesties gevonden", "CANNOT_DEACTIVATE_LAST_SITE": "Kan de laatste actieve site niet deactiveren", "DUPLICATE_SITE_NAME": "Er bestaat al een site met deze naam", - "INVALID_SITE_NAME": "De sitenaam mag alleen letters, cijfers, koppeltekens en underscores bevatten" + "INVALID_SITE_NAME": "De sitenaam mag alleen letters, cijfers, koppeltekens en underscores bevatten", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "ACCOUNT": { "NO_POLKADOT_EXTENSION": "Polkadot-extensie niet gevonden" @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Tabellen niet gedefinieerd", "CONNECTION_UNDEFINED": "Verbinding niet gedefinieerd", "COMMITMENT_FLAG_FAILED": "Mislukt om toezegging te markeren als verwerkt", - "UNKNOWN": "Onbekende databasefout" + "UNKNOWN": "Onbekende databasefout", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Fout bij parseren captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP-adressen komen niet overeen", "INVALID_TOKEN": "Ongeldige token", "INVALID_SOLUTION": "Ongeldige oplossing", - "DECRYPTION_ERROR": "Fout bij decoderen" + "DECRYPTION_ERROR": "Fout bij decoderen", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Ongeldige parameter" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Ontbrekend providerpaar", "MISSING_ENV_VARIABLE": "Ontbrekende omgevingsvariabele", "GENERAL": "Algemene Dev-fout, zie context", - "METHOD_NOT_IMPLEMENTED": "Methode niet geïmplementeerd" + "METHOD_NOT_IMPLEMENTED": "Methode niet geïmplementeerd", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Bestand niet gevonden", "FILE_ALREADY_EXISTS": "Bestand bestaat al", "INVALID_DIR_FORMAT": "Ongeldig mapformaat" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/no/translation.json b/packages/locale/src/locales/no/translation.json index 741ea7125d..b39f2310b6 100644 --- a/packages/locale/src/locales/no/translation.json +++ b/packages/locale/src/locales/no/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Ugyldig signatur", "SITE_KEY_MISSING": "SITE KEY mangler", "ACCOUNT_NOT_FOUND": "Konto ikke funnet", - "INVALID_TIMESTAMP": "Ugyldig tidsstempel" + "INVALID_TIMESTAMP": "Ugyldig tidsstempel", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Utilstrekkelige tillatelser for å utføre denne handlingen", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Forespørsler fra mobilnettverkstilkoblinger er ikke tillatt for dette nettstedet", "SATELLITE_BLOCKED": "Forespørsler fra satellittilkoblinger er ikke tillatt for dette nettstedet", "CRAWLER_BLOCKED": "Forespørsler fra kjente roboter er ikke tillatt for dette nettstedet", - "DISALLOWED_WEBVIEW": "Forespørsler fra innebygde nettlesere (WebView) er ikke tillatt for dette nettstedet" + "DISALLOWED_WEBVIEW": "Forespørsler fra innebygde nettlesere (WebView) er ikke tillatt for dette nettstedet", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Kan ikke endre eierbruker", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Ingen forslag funnet", "CANNOT_DEACTIVATE_LAST_SITE": "Kan ikke deaktivere siste aktive nettsted", "DUPLICATE_SITE_NAME": "Et nettsted med dette navnet finnes allerede", - "INVALID_SITE_NAME": "Nettstednavnet kan bare inneholde bokstaver, tall, bindestreker og understreker" + "INVALID_SITE_NAME": "Nettstednavnet kan bare inneholde bokstaver, tall, bindestreker og understreker", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "flymaskiner", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Tabeller er udefinert", "CONNECTION_UNDEFINED": "Tilkobling udefinert", "COMMITMENT_FLAG_FAILED": "Klarte ikke å flagge engasjement som behandlet", - "UNKNOWN": "Ukjent databasefeil" + "UNKNOWN": "Ukjent databasefeil", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Feil parsing captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP-adresser stemmer ikke overens", "INVALID_TOKEN": "Ugyldig token", "INVALID_SOLUTION": "Ugyldig løsning", - "DECRYPTION_ERROR": "Feil ved dekryptering" + "DECRYPTION_ERROR": "Feil ved dekryptering", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Ugyldig parameter" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Manglende leverandørpar", "MISSING_ENV_VARIABLE": "Manglende miljøvariabel", "GENERAL": "Generell utviklerfeil, se kontekst", - "METHOD_NOT_IMPLEMENTED": "Metoden er ikkje implementert" + "METHOD_NOT_IMPLEMENTED": "Metoden er ikkje implementert", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Filen ble ikkje funnet", "FILE_ALREADY_EXISTS": "Filen eksisterer allerede", "INVALID_DIR_FORMAT": "Ugyldig katalogformat" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/pl/translation.json b/packages/locale/src/locales/pl/translation.json index 954f627280..b447974ffb 100644 --- a/packages/locale/src/locales/pl/translation.json +++ b/packages/locale/src/locales/pl/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Nieprawidłowe podpisanie", "SITE_KEY_MISSING": "BRAK KLUCZA WITRY", "ACCOUNT_NOT_FOUND": "Nie znaleziono konta", - "INVALID_TIMESTAMP": "Nieprawidłowy znacznik czasu" + "INVALID_TIMESTAMP": "Nieprawidłowy znacznik czasu", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Niewystarczające uprawnienia do wykonania tej akcji", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Żądania z połączeń sieci komórkowych nie są dozwolone dla tej strony", "SATELLITE_BLOCKED": "Żądania z połączeń satelitarnych nie są dozwolone dla tej strony", "CRAWLER_BLOCKED": "Żądania od znanych robotów nie są dozwolone dla tej strony", - "DISALLOWED_WEBVIEW": "Żądania z przeglądarek wbudowanych w aplikacje (WebView) nie są dozwolone dla tej strony" + "DISALLOWED_WEBVIEW": "Żądania z przeglądarek wbudowanych w aplikacje (WebView) nie są dozwolone dla tej strony", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Nie można zmodyfikować właściciela użytkownika", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Nie znaleziono sugestii", "CANNOT_DEACTIVATE_LAST_SITE": "Nie można dezaktywować ostatniej aktywnej witryny", "DUPLICATE_SITE_NAME": "Witryna o tej nazwie już istnieje", - "INVALID_SITE_NAME": "Nazwa witryny może zawierać tylko litery, cyfry, łączniki i podkreślenia" + "INVALID_SITE_NAME": "Nazwa witryny może zawierać tylko litery, cyfry, łączniki i podkreślenia", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "samoloty", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Tabele niezdefiniowane", "CONNECTION_UNDEFINED": "Połączenie niezdefiniowane", "COMMITMENT_FLAG_FAILED": "Nie udało się oznaczyć zobowiązania jako przetworzone", - "UNKNOWN": "Nieznany błąd bazy danych" + "UNKNOWN": "Nieznany błąd bazy danych", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Błąd parsowania captchy", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "Adresy IP nie pasują", "INVALID_TOKEN": "Nieprawidłowy token", "INVALID_SOLUTION": "Nieprawidłowe rozwiązanie", - "DECRYPTION_ERROR": "Błąd deszyfrowania" + "DECRYPTION_ERROR": "Błąd deszyfrowania", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Nieprawidłowy parametr" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Brakująca para dostawcy", "MISSING_ENV_VARIABLE": "Brak zmiennej środowiskowej", "GENERAL": "Ogólny błąd dewelopera, zobacz kontekst", - "METHOD_NOT_IMPLEMENTED": "Metoda niezaimplementowana" + "METHOD_NOT_IMPLEMENTED": "Metoda niezaimplementowana", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Plik nie znaleziony", "FILE_ALREADY_EXISTS": "Plik już istnieje", "INVALID_DIR_FORMAT": "Nieprawidłowy format katalogu" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/pt-BR/translation.json b/packages/locale/src/locales/pt-BR/translation.json index 6e4d856bf8..f346a76489 100644 --- a/packages/locale/src/locales/pt-BR/translation.json +++ b/packages/locale/src/locales/pt-BR/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Assinatura inválida", "SITE_KEY_MISSING": "Chave do SITE ausente", "ACCOUNT_NOT_FOUND": "Conta não encontrada", - "INVALID_TIMESTAMP": "Timestamp inválido" + "INVALID_TIMESTAMP": "Timestamp inválido", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Permissões insuficientes para realizar esta ação", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Solicitações de conexões de rede móvel não são permitidas para este site", "SATELLITE_BLOCKED": "Solicitações de conexões por satélite não são permitidas para este site", "CRAWLER_BLOCKED": "Solicitações de crawlers conhecidos não são permitidas para este site", - "DISALLOWED_WEBVIEW": "Solicitações de navegadores incorporados (WebView) não são permitidas para este site" + "DISALLOWED_WEBVIEW": "Solicitações de navegadores incorporados (WebView) não são permitidas para este site", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Não é possível modificar o usuário proprietário", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Nenhuma sugestão encontrada", "CANNOT_DEACTIVATE_LAST_SITE": "Não é possível desativar o último site ativo", "DUPLICATE_SITE_NAME": "Já existe um site com este nome", - "INVALID_SITE_NAME": "O nome do site deve conter apenas letras, números, hifens e sublinhados" + "INVALID_SITE_NAME": "O nome do site deve conter apenas letras, números, hifens e sublinhados", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "ACCOUNT": { "NO_POLKADOT_EXTENSION": "Extensão Polkadot não encontrada" @@ -121,7 +136,15 @@ "TABLES_UNDEFINED": "Tabelas indefinidas", "CONNECTION_UNDEFINED": "Conexão indefinida", "COMMITMENT_FLAG_FAILED": "Falha ao marcar compromisso como processado", - "UNKNOWN": "Erro de banco de dados desconhecido" + "UNKNOWN": "Erro de banco de dados desconhecido", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Erro ao analisar captcha", @@ -139,7 +162,11 @@ "IP_ADDRESS_MISMATCH": "Endereços IP não coincidem", "INVALID_TOKEN": "Token inválido", "INVALID_SOLUTION": "Solução inválida", - "DECRYPTION_ERROR": "Erro ao descriptografar" + "DECRYPTION_ERROR": "Erro ao descriptografar", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Parâmetro inválido" @@ -150,7 +177,8 @@ "MISSING_PROVIDER_PAIR": "Par de provedores ausente", "MISSING_ENV_VARIABLE": "Variável de ambiente ausente", "GENERAL": "Erro de desenvolvedor geral, veja o contexto", - "METHOD_NOT_IMPLEMENTED": "Método não implementado" + "METHOD_NOT_IMPLEMENTED": "Método não implementado", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Arquivo não encontrado", @@ -455,5 +483,10 @@ "sword": "espada", "syringe": "seringa", "tambourine": "tamborim" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/pt/translation.json b/packages/locale/src/locales/pt/translation.json index ae5c97d1ef..cbf9f1f5c9 100644 --- a/packages/locale/src/locales/pt/translation.json +++ b/packages/locale/src/locales/pt/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Assinatura inválida", "SITE_KEY_MISSING": "CHAVE DO SITE ausente", "ACCOUNT_NOT_FOUND": "Conta não encontrada", - "INVALID_TIMESTAMP": "Carimbo de data/hora inválido" + "INVALID_TIMESTAMP": "Carimbo de data/hora inválido", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Permissões insuficientes para realizar esta ação", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Pedidos de ligações de rede móvel não são permitidos para este site", "SATELLITE_BLOCKED": "Pedidos de ligações por satélite não são permitidos para este site", "CRAWLER_BLOCKED": "Pedidos de rastreadores conhecidos não são permitidos para este site", - "DISALLOWED_WEBVIEW": "Pedidos a partir de navegadores incorporados em aplicações (WebView) não são permitidos para este site" + "DISALLOWED_WEBVIEW": "Pedidos a partir de navegadores incorporados em aplicações (WebView) não são permitidos para este site", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Não é possível modificar o utilizador proprietário", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Nenhuma sugestão encontrada", "CANNOT_DEACTIVATE_LAST_SITE": "Não é possível desativar o último site ativo", "DUPLICATE_SITE_NAME": "Já existe um site com este nome", - "INVALID_SITE_NAME": "O nome do site deve conter apenas letras, números, hífenes e sublinhados" + "INVALID_SITE_NAME": "O nome do site deve conter apenas letras, números, hífenes e sublinhados", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "ACCOUNT": { "NO_POLKADOT_EXTENSION": "Extensão Polkadot não encontrada" @@ -121,7 +136,15 @@ "TABLES_UNDEFINED": "Tabelas indefinidas", "CONNECTION_UNDEFINED": "Conexão indefinida", "COMMITMENT_FLAG_FAILED": "Falha ao marcar o compromisso como processado", - "UNKNOWN": "Erro de banco de dados desconhecido" + "UNKNOWN": "Erro de banco de dados desconhecido", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Erro ao analisar o captcha", @@ -139,7 +162,11 @@ "IP_ADDRESS_MISMATCH": "Endereços IP não coincidem", "INVALID_TOKEN": "Token inválido", "INVALID_SOLUTION": "Solução inválida", - "DECRYPTION_ERROR": "Erro de desencriptação" + "DECRYPTION_ERROR": "Erro de desencriptação", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Parâmetro inválido" @@ -150,7 +177,8 @@ "MISSING_PROVIDER_PAIR": "Par de provedor ausente", "MISSING_ENV_VARIABLE": "Variável de ambiente ausente", "GENERAL": "Erro geral de desenvolvimento, veja o contexto", - "METHOD_NOT_IMPLEMENTED": "Método não implementado" + "METHOD_NOT_IMPLEMENTED": "Método não implementado", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Arquivo não encontrado", @@ -455,5 +483,10 @@ "sword": "espada", "syringe": "seringa", "tambourine": "tamborim" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/ro/translation.json b/packages/locale/src/locales/ro/translation.json index e80c4f879b..6bb5f4229d 100644 --- a/packages/locale/src/locales/ro/translation.json +++ b/packages/locale/src/locales/ro/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Semnatura invalida", "SITE_KEY_MISSING": "Cheia SITE lipseste", "ACCOUNT_NOT_FOUND": "Contul nu a fost gasit", - "INVALID_TIMESTAMP": "Timestamp invalid" + "INVALID_TIMESTAMP": "Timestamp invalid", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Permisiuni insuficiente pentru a efectua aceasta actiune", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Solicitările de la conexiuni de rețea mobilă nu sunt permise pentru acest site", "SATELLITE_BLOCKED": "Solicitările de la conexiuni prin satelit nu sunt permise pentru acest site", "CRAWLER_BLOCKED": "Solicitările de la crawlere cunoscute nu sunt permise pentru acest site", - "DISALLOWED_WEBVIEW": "Solicitările din browsere încorporate în aplicații (WebView) nu sunt permise pentru acest site" + "DISALLOWED_WEBVIEW": "Solicitările din browsere încorporate în aplicații (WebView) nu sunt permise pentru acest site", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Nu se poate modifica utilizatorul proprietar", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Nu s-au gasit sugestii", "CANNOT_DEACTIVATE_LAST_SITE": "Nu se poate dezactiva ultimul site activ", "DUPLICATE_SITE_NAME": "Există deja un site cu acest nume", - "INVALID_SITE_NAME": "Numele site-ului trebuie să conțină doar litere, cifre, cratime și liniuțe de subliniere" + "INVALID_SITE_NAME": "Numele site-ului trebuie să conțină doar litere, cifre, cratime și liniuțe de subliniere", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "avioane", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Tabelele sunt nedefinite", "CONNECTION_UNDEFINED": "Conexiunea este nedefinita", "COMMITMENT_FLAG_FAILED": "Esuata la marcarea angajamentului ca procesat", - "UNKNOWN": "Eroare necunoscuta la baza de date" + "UNKNOWN": "Eroare necunoscuta la baza de date", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Eroare la parsarea captcha-ului", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "Adresele IP nu se potrivesc", "INVALID_TOKEN": "Token invalid", "INVALID_SOLUTION": "Solutie invalida", - "DECRYPTION_ERROR": "Eroare la decriptare" + "DECRYPTION_ERROR": "Eroare la decriptare", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Parametru invalid" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Pereche de furnizori lipsa", "MISSING_ENV_VARIABLE": "Variabila de mediu lipsa", "GENERAL": "Eroare generala de dezvoltare, vezi contextul", - "METHOD_NOT_IMPLEMENTED": "Metoda neimplementata" + "METHOD_NOT_IMPLEMENTED": "Metoda neimplementata", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Fisierul nu a fost gasit", "FILE_ALREADY_EXISTS": "Fisierul deja exista", "INVALID_DIR_FORMAT": "Format de director invalid" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/ru/translation.json b/packages/locale/src/locales/ru/translation.json index 08a3898c81..3690e8a21d 100644 --- a/packages/locale/src/locales/ru/translation.json +++ b/packages/locale/src/locales/ru/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Неверная подпись", "SITE_KEY_MISSING": "Отсутствует ключ сайта", "ACCOUNT_NOT_FOUND": "Учетная запись не найдена", - "INVALID_TIMESTAMP": "Недопустимый временной штамп" + "INVALID_TIMESTAMP": "Недопустимый временной штамп", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Недостаточно прав для выполнения этого действия", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Запросы с мобильных сетевых подключений не разрешены для этого сайта", "SATELLITE_BLOCKED": "Запросы со спутниковых подключений не разрешены для этого сайта", "CRAWLER_BLOCKED": "Запросы от известных поисковых роботов не разрешены для этого сайта", - "DISALLOWED_WEBVIEW": "Запросы из встроенных браузеров (WebView) не разрешены для этого сайта" + "DISALLOWED_WEBVIEW": "Запросы из встроенных браузеров (WebView) не разрешены для этого сайта", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Невозможно изменить владельца пользователя", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Предложения не найдены", "CANNOT_DEACTIVATE_LAST_SITE": "Нельзя деактивировать последний активный сайт", "DUPLICATE_SITE_NAME": "Сайт с таким именем уже существует", - "INVALID_SITE_NAME": "Имя сайта должно содержать только буквы, цифры, дефисы и символы подчёркивания" + "INVALID_SITE_NAME": "Имя сайта должно содержать только буквы, цифры, дефисы и символы подчёркивания", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "самолеты", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Таблицы не определены", "CONNECTION_UNDEFINED": "Подключение не определено", "COMMITMENT_FLAG_FAILED": "Не удалось пометить коммитмент как обработанный", - "UNKNOWN": "Неизвестная ошибка базы данных" + "UNKNOWN": "Неизвестная ошибка базы данных", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Ошибка парсинга капчи", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP адреса не совпадают", "INVALID_TOKEN": "Недействительный токен", "INVALID_SOLUTION": "Недопустимое решение", - "DECRYPTION_ERROR": "Ошибка расшифровки" + "DECRYPTION_ERROR": "Ошибка расшифровки", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Недопустимый параметр" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Отсутствует пара поставщиков", "MISSING_ENV_VARIABLE": "Отсутствует переменная среды", "GENERAL": "Общая ошибка Dev, см. контекст", - "METHOD_NOT_IMPLEMENTED": "Метод не реализован" + "METHOD_NOT_IMPLEMENTED": "Метод не реализован", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Файл не найден", "FILE_ALREADY_EXISTS": "Файл уже существует", "INVALID_DIR_FORMAT": "Недопустимый формат каталога" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/sr/translation.json b/packages/locale/src/locales/sr/translation.json index 2f639b5252..da6cd263ef 100644 --- a/packages/locale/src/locales/sr/translation.json +++ b/packages/locale/src/locales/sr/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Неважећи потпис", "SITE_KEY_MISSING": "Недостаје кључ сајта", "ACCOUNT_NOT_FOUND": "Налог није пронађен", - "INVALID_TIMESTAMP": "Неважећа временска ознака" + "INVALID_TIMESTAMP": "Неважећа временска ознака", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Недовољне дозволе за обављање ове радње", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Захтеви са мобилних мрежних конекција нису дозвољени за овај сајт", "SATELLITE_BLOCKED": "З��хтеви са сателитских конекција нису дозвољени за овај сајт", "CRAWLER_BLOCKED": "Захтеви од познатих ботова нису дозвољени за овај сајт", - "DISALLOWED_WEBVIEW": "Захтеви из уграђених прегледача (WebView) нису дозвољени за овај сајт" + "DISALLOWED_WEBVIEW": "Захтеви из уграђених прегледача (WebView) нису дозвољени за овај сајт", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Није могуће изменити власника корисника", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Нису пронађени предлози", "CANNOT_DEACTIVATE_LAST_SITE": "Није могуће деактивирати последњи активни сајт", "DUPLICATE_SITE_NAME": "Сајт са овим именом већ постоји", - "INVALID_SITE_NAME": "Назив сајта сме да садржи само слова, бројеве, цртице и доње црте" + "INVALID_SITE_NAME": "Назив сајта сме да садржи само слова, бројеве, цртице и доње црте", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "авиони", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Табеле нису дефинисане", "CONNECTION_UNDEFINED": "Веза није дефинисана", "COMMITMENT_FLAG_FAILED": "Означавање обавезе као обрађене није успело", - "UNKNOWN": "Непозната грешка базе података" + "UNKNOWN": "Непозната грешка базе података", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Грешка при рашчлањивању капче", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP адресе се не подударају", "INVALID_TOKEN": "Неважећи токен", "INVALID_SOLUTION": "Неважеће решење", - "DECRYPTION_ERROR": "Грешка при дешифровању" + "DECRYPTION_ERROR": "Грешка при дешифровању", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Неважећи параметар" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Недостаје пар провајдера", "MISSING_ENV_VARIABLE": "Недостаје променљива окружења", "GENERAL": "Општа грешка развоја, погледајте контекст", - "METHOD_NOT_IMPLEMENTED": "Метода није имплементирана" + "METHOD_NOT_IMPLEMENTED": "Метода није имплементирана", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Датотека није пронађена", "FILE_ALREADY_EXISTS": "Датотека већ постоји", "INVALID_DIR_FORMAT": "Неважећи формат директоријума" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/sv/translation.json b/packages/locale/src/locales/sv/translation.json index bd6e250f35..fb3768981b 100644 --- a/packages/locale/src/locales/sv/translation.json +++ b/packages/locale/src/locales/sv/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Ogiltig signatur", "SITE_KEY_MISSING": "SITE KEY saknas", "ACCOUNT_NOT_FOUND": "Konto hittades inte", - "INVALID_TIMESTAMP": "Ogiltig tidsstämpel" + "INVALID_TIMESTAMP": "Ogiltig tidsstämpel", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Otillräckliga behörigheter för att utföra denna åtgärd", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Förfrågningar från mobilnätverksanslutningar är inte tillåtna för denna webbplats", "SATELLITE_BLOCKED": "Förfrågningar från satellitanslutningar är inte tillåtna för denna webbplats", "CRAWLER_BLOCKED": "Förfrågningar från kända crawlers är inte tillåtna för denna webbplats", - "DISALLOWED_WEBVIEW": "Förfrågningar från inbäddade webbläsare (WebView) är inte tillåtna för denna webbplats" + "DISALLOWED_WEBVIEW": "Förfrågningar från inbäddade webbläsare (WebView) är inte tillåtna för denna webbplats", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Kan inte ändra ägare användare", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Inga förslag hittades", "CANNOT_DEACTIVATE_LAST_SITE": "Kan inte inaktivera den sista aktiva platsen", "DUPLICATE_SITE_NAME": "En webbplats med detta namn finns redan", - "INVALID_SITE_NAME": "Webbplatsnamnet får bara innehålla bokstäver, siffror, bindestreck och understreck" + "INVALID_SITE_NAME": "Webbplatsnamnet får bara innehålla bokstäver, siffror, bindestreck och understreck", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "flygplan", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Tabeller ospecificerade", "CONNECTION_UNDEFINED": "Anslutning ospecificerad", "COMMITMENT_FLAG_FAILED": "Misslyckades att flagga åtagande som behandlad", - "UNKNOWN": "Okänt databasfel" + "UNKNOWN": "Okänt databasfel", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Fel vid tolkning av captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP-adresser matchar inte", "INVALID_TOKEN": "Ogiltig token", "INVALID_SOLUTION": "Ogiltig lösning", - "DECRYPTION_ERROR": "Fel vid avkryptering" + "DECRYPTION_ERROR": "Fel vid avkryptering", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Ogiltig parameter" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Saknad-leverantör-par", "MISSING_ENV_VARIABLE": "Saknad-miljövariabel", "GENERAL": "Allmänt utvecklarfel, se sammanhang", - "METHOD_NOT_IMPLEMENTED": "Metod-inte-implementerad" + "METHOD_NOT_IMPLEMENTED": "Metod-inte-implementerad", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Fil-inte-hittad", "FILE_ALREADY_EXISTS": "Fil-redan-existerar", "INVALID_DIR_FORMAT": "Ogiltigt mappformat" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/th/translation.json b/packages/locale/src/locales/th/translation.json index 71acbc26eb..36320988c9 100644 --- a/packages/locale/src/locales/th/translation.json +++ b/packages/locale/src/locales/th/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "ลายเซ็นต์ไม่ถูกต้อง", "SITE_KEY_MISSING": "SITE KEY หายไป", "ACCOUNT_NOT_FOUND": "ไม่พบบัญชี", - "INVALID_TIMESTAMP": "เครื่องหมายเวลาไม่ถูกต้อง" + "INVALID_TIMESTAMP": "เครื่องหมายเวลาไม่ถูกต้อง", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "สิทธิ์ไม่เพียงพอในการทำการกระทำนี้", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "คำขอจากการเชื่อมต่อเครือข่ายมือถือไม่ได้รับอนุญาตสำหรับเว็บไซต์นี้", "SATELLITE_BLOCKED": "คำขอจากการเชื่อมต่อดาวเทียมไม่ได้รับอนุญาตสำหรับเว็บไซต์นี้", "CRAWLER_BLOCKED": "คำขอจากโปรแกรมรวบรวมข้อมูลที่รู้จักไม่ได้รับอนุญาตสำหรับเว็บไซต์นี้", - "DISALLOWED_WEBVIEW": "ไม่อนุญาตให้ส่งคำขอจากเบราว์เซอร์ในแอป (WebView) สำหรับเว็บไซต์นี้" + "DISALLOWED_WEBVIEW": "ไม่อนุญาตให้ส่งคำขอจากเบราว์เซอร์ในแอป (WebView) สำหรับเว็บไซต์นี้", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "ไม่สามารถแก้ไขผู้ใช้เจ้าของ", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "ไม่พบข้อเสนอ", "CANNOT_DEACTIVATE_LAST_SITE": "ไม่สามารถปิดใช้งานเว็บไซต์ที่ใช้งานอยู่ครั้งสุดท้าย", "DUPLICATE_SITE_NAME": "มีไซต์ที่ใช้ชื่อนี้อยู่แล้ว", - "INVALID_SITE_NAME": "ชื่อไซต์ต้องประกอบด้วยตัวอักษร ตัวเลข ขีดกลาง และขีดล่างเท่านั้น" + "INVALID_SITE_NAME": "ชื่อไซต์ต้องประกอบด้วยตัวอักษร ตัวเลข ขีดกลาง และขีดล่างเท่านั้น", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "เครื่องบิน", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "ตารางไม่ได้ถูกกำหนดไว้", "CONNECTION_UNDEFINED": "การเชื่อมต่อไม่ได้ถูกกำหนด", "COMMITMENT_FLAG_FAILED": "ล้มเหลวในการทำเครื่องหมายการสนับสนุนว่าดำเนินการแล้ว", - "UNKNOWN": "ข้อผิดพลาดในฐานข้อมูลที่ไม่ทราบสาเหตุ" + "UNKNOWN": "ข้อผิดพลาดในฐานข้อมูลที่ไม่ทราบสาเหตุ", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "ข้อผิดพลาดในการแยกวิเคราะห์ captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "ที่อยู่ IP ไม่ตรงกัน", "INVALID_TOKEN": "โทเคนไม่ถูกต้อง", "INVALID_SOLUTION": "คำตอบไม่ถูกต้อง", - "DECRYPTION_ERROR": "เกิดข้อผิดพลาดในการถอดรหัส" + "DECRYPTION_ERROR": "เกิดข้อผิดพลาดในการถอดรหัส", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "พารามิเตอร์ไม่ถูกต้อง" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "คู่ให้บริการที่ขาดหาย", "MISSING_ENV_VARIABLE": "ตัวแปรสภาพแวดล้อมที่ขาดหาย", "GENERAL": "ข้อผิดพลาด Dev ทั่วไป ดูบริบท", - "METHOD_NOT_IMPLEMENTED": "เมธอดยังไม่ได้นำมาใช้" + "METHOD_NOT_IMPLEMENTED": "เมธอดยังไม่ได้นำมาใช้", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "ไม่พบไฟล์", "FILE_ALREADY_EXISTS": "ไฟล์มีอยู่แล้ว", "INVALID_DIR_FORMAT": "รูปแบบไดเรกทอรีไม่ถูกต้อง" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/tr/translation.json b/packages/locale/src/locales/tr/translation.json index dfd3349a21..2db43a0f68 100644 --- a/packages/locale/src/locales/tr/translation.json +++ b/packages/locale/src/locales/tr/translation.json @@ -10,7 +10,13 @@ "ENVIRONMENT_NOT_READY": "Çevre hazır değil", "INVALID_SIGNATURE": "Geçersiz imza", "SITE_KEY_MISSING": "SITE KEY eksik", - "INVALID_TIMESTAMP": "Geçersiz zaman damgası" + "INVALID_TIMESTAMP": "Geçersiz zaman damgası", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Insufficient permissions to perform this action", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Bu site için mobil ağ bağlantılarından gelen isteklere izin verilmiyor", "SATELLITE_BLOCKED": "Bu site için uydu bağlantılarından gelen isteklere izin verilmiyor", "CRAWLER_BLOCKED": "Bu site için bilinen tarayıcılardan gelen isteklere izin verilmiyor", - "DISALLOWED_WEBVIEW": "Bu site için uygulama içi tarayıcılardan (WebView) gelen isteklere izin verilmiyor" + "DISALLOWED_WEBVIEW": "Bu site için uygulama içi tarayıcılardan (WebView) gelen isteklere izin verilmiyor", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Cannot modify owner user", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "No suggestions found", "CANNOT_DEACTIVATE_LAST_SITE": "Cannot deactivate the last active site", "DUPLICATE_SITE_NAME": "Bu ada sahip bir site zaten mevcut", - "INVALID_SITE_NAME": "Site adı yalnızca harf, rakam, tire ve alt çizgi içermelidir" + "INVALID_SITE_NAME": "Site adı yalnızca harf, rakam, tire ve alt çizgi içermelidir", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "uçaklar", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Tablolar tanımsız", "CONNECTION_UNDEFINED": "Bağlantı tanımsız", "COMMITMENT_FLAG_FAILED": "Taahhütü işlenmiş olarak işaretleme başarısız oldu", - "UNKNOWN": "Bilinmeyen veritabanı hatası" + "UNKNOWN": "Bilinmeyen veritabanı hatası", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Captcha ayrıştırma hatası", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP adresleri eşleşmiyor", "INVALID_TOKEN": "Geçersiz belirteç", "INVALID_SOLUTION": "Geçersiz çözüm", - "DECRYPTION_ERROR": "Şifreleme hatası" + "DECRYPTION_ERROR": "Şifreleme hatası", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Geçersiz parametre" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Eksik sağlayıcı çifti", "MISSING_ENV_VARIABLE": "Eksik ortam değişkeni", "GENERAL": "Genel Geliştirici Hatası, bağlamı kontrol edin", - "METHOD_NOT_IMPLEMENTED": "Yöntem uygulanmadı" + "METHOD_NOT_IMPLEMENTED": "Yöntem uygulanmadı", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Dosya bulunamadı", "FILE_ALREADY_EXISTS": "Dosya zaten var", "INVALID_DIR_FORMAT": "Geçersiz dizin biçimi" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/uk/translation.json b/packages/locale/src/locales/uk/translation.json index 1f2d637e90..1da11cd487 100644 --- a/packages/locale/src/locales/uk/translation.json +++ b/packages/locale/src/locales/uk/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Invalid signature", "SITE_KEY_MISSING": "SITE KEY missing", "ACCOUNT_NOT_FOUND": "Account not found", - "INVALID_TIMESTAMP": "Invalid timestamp" + "INVALID_TIMESTAMP": "Invalid timestamp", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Insufficient permissions to perform this action", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Запити з мобільних мережевих з'єднань не дозволені для цього сайту", "SATELLITE_BLOCKED": "Запити із супутникових з'єднань не дозволені для цього сайту", "CRAWLER_BLOCKED": "Запити від відомих пошукових роботів не дозволені для цього сайту", - "DISALLOWED_WEBVIEW": "Запити з вбудованих браузерів (WebView) не дозволені для цього сайту" + "DISALLOWED_WEBVIEW": "Запити з вбудованих браузерів (WebView) не дозволені для цього сайту", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Cannot modify owner user", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "No suggestions found", "CANNOT_DEACTIVATE_LAST_SITE": "Cannot deactivate the last active site", "DUPLICATE_SITE_NAME": "Сайт із такою назвою вже існує", - "INVALID_SITE_NAME": "Назва сайту повинна містити лише літери, цифри, дефіси та символи підкреслення" + "INVALID_SITE_NAME": "Назва сайту повинна містити лише літери, цифри, дефіси та символи підкреслення", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "aeroplanes", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Tables undefined", "CONNECTION_UNDEFINED": "Connection undefined", "COMMITMENT_FLAG_FAILED": "Failed to flag commitment as processed", - "UNKNOWN": "Unknown database error" + "UNKNOWN": "Unknown database error", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Error parsing captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "IP address mismatch detected", "INVALID_TOKEN": "Invalid token", "INVALID_SOLUTION": "Invalid solution", - "DECRYPTION_ERROR": "Error decrypting" + "DECRYPTION_ERROR": "Error decrypting", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Invalid parameter" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Missing provider pair", "MISSING_ENV_VARIABLE": "Missing environment variable", "GENERAL": "General Dev Error, see context", - "METHOD_NOT_IMPLEMENTED": "Method not implemented" + "METHOD_NOT_IMPLEMENTED": "Method not implemented", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "File not found", "FILE_ALREADY_EXISTS": "File already exists", "INVALID_DIR_FORMAT": "Invalid directory format" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/vi/translation.json b/packages/locale/src/locales/vi/translation.json index f624b4ef19..07fa4c7d5c 100644 --- a/packages/locale/src/locales/vi/translation.json +++ b/packages/locale/src/locales/vi/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "Chữ ký không hợp lệ", "SITE_KEY_MISSING": "SITE KEY thiếu", "ACCOUNT_NOT_FOUND": "Không tìm thấy tài khoản", - "INVALID_TIMESTAMP": "Thời điểm không hợp lệ" + "INVALID_TIMESTAMP": "Thời điểm không hợp lệ", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "Không đủ quyền để thực hiện hành động này", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "Các yêu cầu từ kết nối mạng di động không được phép cho trang web này", "SATELLITE_BLOCKED": "Các yêu cầu từ kết nối vệ tinh không được phép cho trang web này", "CRAWLER_BLOCKED": "Các yêu cầu từ trình thu thập dữ liệu đã biết không được phép cho trang web này", - "DISALLOWED_WEBVIEW": "Yêu cầu từ trình duyệt trong ứng dụng (WebView) không được phép cho trang web này" + "DISALLOWED_WEBVIEW": "Yêu cầu từ trình duyệt trong ứng dụng (WebView) không được phép cho trang web này", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "Không thể sửa đổi người dùng chủ sở hữu", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "Không tìm thấy gợi ý nào", "CANNOT_DEACTIVATE_LAST_SITE": "Không thể vô hiệu hóa trang cuối cùng hoạt động", "DUPLICATE_SITE_NAME": "Đã tồn tại một trang web với tên này", - "INVALID_SITE_NAME": "Tên trang web chỉ được chứa chữ cái, chữ số, dấu gạch ngang và dấu gạch dưới" + "INVALID_SITE_NAME": "Tên trang web chỉ được chứa chữ cái, chữ số, dấu gạch ngang và dấu gạch dưới", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "máy bay", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "Bảng chưa xác định", "CONNECTION_UNDEFINED": "Kết nối không xác định", "COMMITMENT_FLAG_FAILED": "Không thể đánh dấu cam kết là đã xử lý", - "UNKNOWN": "Lỗi cơ sở dữ liệu không xác định" + "UNKNOWN": "Lỗi cơ sở dữ liệu không xác định", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "Lỗi phân tích captcha", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "Phát hiện không khớp địa chỉ IP", "INVALID_TOKEN": "Token không hợp lệ", "INVALID_SOLUTION": "Giải pháp không hợp lệ", - "DECRYPTION_ERROR": "Lỗi giải mã" + "DECRYPTION_ERROR": "Lỗi giải mã", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "Tham số không hợp lệ" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "Thiếu cặp nhà cung cấp", "MISSING_ENV_VARIABLE": "Thiếu biến môi trường", "GENERAL": "Lỗi phát triển chung, xem ngữ cảnh", - "METHOD_NOT_IMPLEMENTED": "Phương thức chưa được triển khai" + "METHOD_NOT_IMPLEMENTED": "Phương thức chưa được triển khai", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "Không tìm thấy tệp", "FILE_ALREADY_EXISTS": "Tệp đã tồn tại", "INVALID_DIR_FORMAT": "Định dạng thư mục không hợp lệ" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/locales/zh-CN/translation.json b/packages/locale/src/locales/zh-CN/translation.json index ae5ef2df16..cb6de16af3 100644 --- a/packages/locale/src/locales/zh-CN/translation.json +++ b/packages/locale/src/locales/zh-CN/translation.json @@ -10,7 +10,13 @@ "INVALID_SIGNATURE": "无效的签名", "SITE_KEY_MISSING": "缺少SITE KEY", "ACCOUNT_NOT_FOUND": "找不到帐户", - "INVALID_TIMESTAMP": "无效的时间戳" + "INVALID_TIMESTAMP": "无效的时间戳", + "BILLING_ERROR": "Billing error", + "INVALID_JWT": "Invalid authentication token", + "MISSING_AUTH_HEADER": "Missing authentication header", + "OBJECT_COUNT_ERROR": "Unexpected object count", + "SECRET_MISSING": "Secret is missing", + "UNKNOWN": "Unknown error" }, "API": { "INSUFFICIENT_PERMISSIONS": "权限不足,无法执行此操作", @@ -51,7 +57,13 @@ "MOBILE_BLOCKED": "此网站不允许来自移动网络连接的请求", "SATELLITE_BLOCKED": "此网站不允许来自卫星连接的请求", "CRAWLER_BLOCKED": "此网站不允许来自已知爬虫的请求", - "DISALLOWED_WEBVIEW": "此站点不允许来自应用内浏览器 (WebView) 的请求" + "DISALLOWED_WEBVIEW": "此站点不允许来自应用内浏览器 (WebView) 的请求", + "INTERNAL_SERVER_ERROR": "Internal server error", + "INVALID_DETECTOR_KEY": "Invalid detector key", + "FEATURE_NOT_ENABLED": "This feature is not enabled", + "INVALID_AUTHORIZATION_HEADER": "Invalid authorization header", + "INVALID_DOMAIN": "Invalid domain", + "NO_PERMISSIONS": "No permissions configured for this account" }, "PORTAL": { "CANNOT_MODIFY_OWNER_USER": "无法修改所有者用户", @@ -61,7 +73,10 @@ "NO_SUGGESTIONS_FOUND": "未找到建议", "CANNOT_DEACTIVATE_LAST_SITE": "无法停用最后一个活动站点", "DUPLICATE_SITE_NAME": "已存在同名站点", - "INVALID_SITE_NAME": "站点名称只能包含字母、数字、连字符和下划线" + "INVALID_SITE_NAME": "站点名称只能包含字母、数字、连字符和下划线", + "CANNOT_MODIFY_USER": "Cannot modify this user", + "API_KEYS_INVALID_NUMBER_OF_SITES": "Invalid number of sites for API key generation", + "API_KEYS_NOT_FOUND": "API keys not found" }, "TARGET": { "airplanes": "飞机", @@ -420,7 +435,15 @@ "TABLES_UNDEFINED": "未定义表", "CONNECTION_UNDEFINED": "连接未定义", "COMMITMENT_FLAG_FAILED": "标记承诺为已处理失败", - "UNKNOWN": "未知数据库错误" + "UNKNOWN": "未知数据库错误", + "QUERY_ERROR": "Database query failed", + "SESSION_STORE_FAILED": "Failed to store session", + "SESSION_CHECK_REMOVE_FAILED": "Failed to check and remove session", + "SESSION_GET_FAILED": "Failed to get session", + "CAPTCHA_SAMPLE_SIZE_EXCEEDED": "Captcha sample size exceeded", + "DATABASE_IMPORT_ERROR": "Database import error", + "REDIS_ACCESS_RULES_CONNECTION_UNDEFINED": "Redis access rules connection is undefined", + "USER_ACCESS_RULES_STORAGE_UNDEFINED": "User access rules storage is undefined" }, "CAPTCHA": { "PARSE_ERROR": "解析验证码时出错", @@ -438,7 +461,11 @@ "IP_ADDRESS_MISMATCH": "检测到 IP 地址不匹配", "INVALID_TOKEN": "无效的令牌", "INVALID_SOLUTION": "无效的解决方案", - "DECRYPTION_ERROR": "解密错误" + "DECRYPTION_ERROR": "解密错误", + "FAILED": "Captcha failed", + "PASSED": "Captcha passed", + "SOLUTION_NOT_FOUND": "Solution not found", + "INVALID_TIMESTAMP": "Invalid timestamp" }, "CLI": { "PARAMETER_ERROR": "无效的参数" @@ -449,11 +476,17 @@ "MISSING_PROVIDER_PAIR": "缺少提供商对", "MISSING_ENV_VARIABLE": "缺少环境变量", "GENERAL": "一般开发错误,请参考上下文", - "METHOD_NOT_IMPLEMENTED": "方法未实现" + "METHOD_NOT_IMPLEMENTED": "方法未实现", + "MISSING_SECRET_KEY": "Missing secret key" }, "FS": { "FILE_NOT_FOUND": "未找到文件", "FILE_ALREADY_EXISTS": "文件已存在", "INVALID_DIR_FORMAT": "无效的目录格式" + }, + "BILLING": { + "STRIPE_PORTAL": "Could not open billing portal", + "STRIPE_SESSION_NOT_FOUND": "Billing session not found", + "STRIPE_PAYMENT_FAILED": "Payment failed" } } diff --git a/packages/locale/src/translationKey.ts b/packages/locale/src/translationKey.ts index d749c4f16c..387ae9f036 100644 --- a/packages/locale/src/translationKey.ts +++ b/packages/locale/src/translationKey.ts @@ -21,9 +21,10 @@ type Node = } | string; +// Returns [""] for a string leaf so the parent can prepend its key without a separator. function getLeafFieldPath(obj: Node): string[] { if (typeof obj === "string") { - return []; + return [""]; } return Object.keys(obj).reduce((arr, key) => { @@ -35,14 +36,20 @@ function getLeafFieldPath(obj: Node): string[] { return arr.concat( children.map((child) => { - return `${key}.${child}`; + return child ? `${key}.${child}` : key; }), ); }, [] as string[]); } +// Recursive conditional type that derives the exact union of dot-notation leaf paths +// from the translation JSON shape at compile time, independently of the runtime function. +type Leaves = { + [K in keyof T & string]: T[K] extends string ? K : `${K}.${Leaves}`; +}[keyof T & string]; + export const TranslationKeysSchema = z.enum( getLeafFieldPath(translationEn) as [string, ...string[]], ); -export type TranslationKey = z.infer; +export type TranslationKey = Leaves; diff --git a/packages/procaptcha-bundle/package.json b/packages/procaptcha-bundle/package.json index c5019ab15e..3562bcc228 100644 --- a/packages/procaptcha-bundle/package.json +++ b/packages/procaptcha-bundle/package.json @@ -39,6 +39,7 @@ }, "browserslist": ["> 0.5%, last 2 versions, not dead"], "dependencies": { + "@prosopo/common": "3.1.38", "@prosopo/dotenv": "3.0.43", "@prosopo/locale": "3.2.4", "@prosopo/procaptcha-common": "2.10.19", diff --git a/packages/procaptcha-bundle/src/util/widgetFactory.ts b/packages/procaptcha-bundle/src/util/widgetFactory.ts index 3e708ba554..ba72f678e5 100644 --- a/packages/procaptcha-bundle/src/util/widgetFactory.ts +++ b/packages/procaptcha-bundle/src/util/widgetFactory.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { loadI18next } from "@prosopo/locale"; +import { loadI18nextFrontend } from "@prosopo/locale"; import type { Ti18n } from "@prosopo/locale"; import { getDefaultCallbacks, @@ -124,7 +124,7 @@ class WidgetFactory { protected async getCaptchaRenderer(): Promise { if (this._i18n === null) { - this._i18n = await loadI18next(false); + this._i18n = await loadI18nextFrontend(); } if (this.captchaRenderer === null) { diff --git a/packages/procaptcha-bundle/tsconfig.cjs.json b/packages/procaptcha-bundle/tsconfig.cjs.json index 8e6144723c..be8081e860 100644 --- a/packages/procaptcha-bundle/tsconfig.cjs.json +++ b/packages/procaptcha-bundle/tsconfig.cjs.json @@ -10,6 +10,9 @@ { "path": "../../dev/config/tsconfig.cjs.json" }, + { + "path": "../common/tsconfig.cjs.json" + }, { "path": "../dotenv/tsconfig.cjs.json" }, diff --git a/packages/procaptcha-bundle/tsconfig.json b/packages/procaptcha-bundle/tsconfig.json index e557f55d25..202e89cf17 100644 --- a/packages/procaptcha-bundle/tsconfig.json +++ b/packages/procaptcha-bundle/tsconfig.json @@ -17,6 +17,9 @@ { "path": "../../dev/config/tsconfig.json" }, + { + "path": "../common" + }, { "path": "../dotenv" }, diff --git a/packages/procaptcha-bundle/vite.config.ts b/packages/procaptcha-bundle/vite.config.ts index f08b9864f3..1db0da159c 100644 --- a/packages/procaptcha-bundle/vite.config.ts +++ b/packages/procaptcha-bundle/vite.config.ts @@ -15,6 +15,7 @@ import { randomBytes } from "node:crypto"; import * as fs from "node:fs"; import * as path from "node:path"; +import { BACKEND_ERROR_KEYS_ARRAY } from "@prosopo/common"; import { ViteFrontendConfig, VitePluginRemoveUnusedTranslations, @@ -167,6 +168,7 @@ export default defineConfig(async ({ command, mode }) => { VitePluginRemoveUnusedTranslations( translationKeys, `${copyDir.destDir}/**/*.json`, + BACKEND_ERROR_KEYS_ARRAY, ), ...(frontendConfig.plugins ? frontendConfig.plugins : []), diff --git a/packages/procaptcha-frictionless/src/ProcaptchaFrictionless.tsx b/packages/procaptcha-frictionless/src/ProcaptchaFrictionless.tsx index e14d941742..ed6d95f51b 100644 --- a/packages/procaptcha-frictionless/src/ProcaptchaFrictionless.tsx +++ b/packages/procaptcha-frictionless/src/ProcaptchaFrictionless.tsx @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { loadI18next } from "@prosopo/locale"; +import { loadI18nextFrontend } from "@prosopo/locale"; import { Checkbox, TestModeBanner, @@ -97,7 +97,7 @@ export const ProcaptchaFrictionless = ({ i18n.changeLanguage(config.language).then((r) => r); } } else { - loadI18next(false).then((i18n) => { + loadI18nextFrontend().then((i18n) => { if (i18n.language !== config.language) i18n.changeLanguage(config.language).then((r) => r); }); diff --git a/packages/procaptcha-pow/src/components/ProcaptchaWidget.tsx b/packages/procaptcha-pow/src/components/ProcaptchaWidget.tsx index 0ebaea94f1..f9ee46dd29 100644 --- a/packages/procaptcha-pow/src/components/ProcaptchaWidget.tsx +++ b/packages/procaptcha-pow/src/components/ProcaptchaWidget.tsx @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { loadI18next, useTranslation } from "@prosopo/locale"; +import { loadI18nextFrontend, useTranslation } from "@prosopo/locale"; import { buildUpdateState, useProcaptcha } from "@prosopo/procaptcha-common"; import { Checkbox, Honeypot } from "@prosopo/procaptcha-common"; import { ModeEnum, type ProcaptchaProps } from "@prosopo/types"; @@ -54,7 +54,7 @@ const Procaptcha = (props: ProcaptchaProps) => { i18n.changeLanguage(config.language).then((r) => r); } } else { - loadI18next(false).then((i18n) => { + loadI18nextFrontend().then((i18n) => { if (i18n.language !== config.language) i18n.changeLanguage(config.language).then((r) => r); }); diff --git a/packages/procaptcha-react/src/components/ProcaptchaWidget.tsx b/packages/procaptcha-react/src/components/ProcaptchaWidget.tsx index c49fa1e86d..d3403321c5 100644 --- a/packages/procaptcha-react/src/components/ProcaptchaWidget.tsx +++ b/packages/procaptcha-react/src/components/ProcaptchaWidget.tsx @@ -14,7 +14,7 @@ /** @jsxImportSource @emotion/react */ -import { loadI18next, useTranslation } from "@prosopo/locale"; +import { loadI18nextFrontend, useTranslation } from "@prosopo/locale"; import { Manager } from "@prosopo/procaptcha"; import { Checkbox, @@ -57,7 +57,7 @@ const ProcaptchaWidget = (props: ProcaptchaProps) => { i18n.changeLanguage(config.language).then((r) => r); } } else { - loadI18next(false).then((i18n) => { + loadI18nextFrontend().then((i18n) => { if (i18n.language !== config.language) i18n.changeLanguage(config.language).then((r) => r); }); @@ -187,7 +187,13 @@ const ProcaptchaWidget = (props: ProcaptchaProps) => { }} checked={state.isHuman} labelText={isTranslationReady ? t("WIDGET.I_AM_HUMAN") : ""} - error={state.error?.message} + error={ + state.error + ? isTranslationReady + ? t(state.error.key as Parameters[0]) + : state.error.key + : undefined + } aria-label="human checkbox" loading={loading} /> diff --git a/packages/provider/src/api/captcha/checkSpamEmail.ts b/packages/provider/src/api/captcha/checkSpamEmail.ts index 09462862a2..be13c5fa4c 100644 --- a/packages/provider/src/api/captcha/checkSpamEmail.ts +++ b/packages/provider/src/api/captcha/checkSpamEmail.ts @@ -65,8 +65,6 @@ export default (env: ProviderEnvironment) => return next( new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -79,8 +77,6 @@ export default (env: ProviderEnvironment) => code: 400, siteKey: dapp, }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -110,8 +106,6 @@ export default (env: ProviderEnvironment) => return next( new ProsopoApiError("API.INTERNAL_SERVER_ERROR", { context: { code: 500 }, - i18n: req.i18n, - logger: req.logger, }), ); } diff --git a/packages/provider/src/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.ts b/packages/provider/src/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.ts index 720a9f2de8..d60f56e214 100644 --- a/packages/provider/src/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.ts +++ b/packages/provider/src/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.ts @@ -348,8 +348,6 @@ const runContextAwareValidation = async ( return next( new ProsopoApiError("API.BAD_REQUEST", { context: { code: 400, siteKey: dapp, user }, - i18n: req.i18n, - logger: req.logger, }), ); } diff --git a/packages/provider/src/api/captcha/getFrictionlessCaptchaChallenge/handler.ts b/packages/provider/src/api/captcha/getFrictionlessCaptchaChallenge/handler.ts index e207c8e8a5..248f66bf21 100644 --- a/packages/provider/src/api/captcha/getFrictionlessCaptchaChallenge/handler.ts +++ b/packages/provider/src/api/captcha/getFrictionlessCaptchaChallenge/handler.ts @@ -145,8 +145,6 @@ export default ( return next( new ProsopoApiError("API.BAD_REQUEST", { context: { code: 400, siteKey: dapp, user }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -157,8 +155,6 @@ export default ( return next( new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -265,8 +261,6 @@ export default ( return next( new ProsopoApiError(reason || "API.BAD_REQUEST", { context: { code: 400, siteKey: dapp, user }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -394,8 +388,6 @@ export default ( return next( new ProsopoApiError("API.BAD_REQUEST", { context: { code: 400, error: err }, - i18n: req.i18n, - logger: req.logger, }), ); } diff --git a/packages/provider/src/api/captcha/getImageCaptchaChallenge.ts b/packages/provider/src/api/captcha/getImageCaptchaChallenge.ts index b230d6be0b..75cba188ed 100644 --- a/packages/provider/src/api/captcha/getImageCaptchaChallenge.ts +++ b/packages/provider/src/api/captcha/getImageCaptchaChallenge.ts @@ -52,8 +52,6 @@ export default ( return next( new ProsopoApiError("API.BAD_REQUEST", { context: { code: 400, error: "IP address not found" }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -66,8 +64,6 @@ export default ( return next( new ProsopoApiError("CAPTCHA.PARSE_ERROR", { context: { code: 400, error: err }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -97,8 +93,6 @@ export default ( return next( new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -153,8 +147,6 @@ export default ( siteKey: dapp, user, }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -246,8 +238,6 @@ export default ( code: 500, params: req.params, }, - i18n: req.i18n, - logger: req.logger, }), ); } diff --git a/packages/provider/src/api/captcha/getPoWCaptchaChallenge.ts b/packages/provider/src/api/captcha/getPoWCaptchaChallenge.ts index 2951a17299..7205af020f 100644 --- a/packages/provider/src/api/captcha/getPoWCaptchaChallenge.ts +++ b/packages/provider/src/api/captcha/getPoWCaptchaChallenge.ts @@ -50,8 +50,6 @@ export default ( return next( new ProsopoApiError("CAPTCHA.PARSE_ERROR", { context: { code: 400, error: err }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -82,8 +80,6 @@ export default ( return next( new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -145,8 +141,6 @@ export default ( siteKey: dapp, user, }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -162,8 +156,6 @@ export default ( siteKey: dapp, user, }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -255,8 +247,6 @@ export default ( user: req.body.user, error: err, }, - i18n: req.i18n, - logger: req.logger, }), ); } diff --git a/packages/provider/src/api/captcha/getPuzzleCaptchaChallenge.ts b/packages/provider/src/api/captcha/getPuzzleCaptchaChallenge.ts index a7a21dbe15..788c9fd0c5 100644 --- a/packages/provider/src/api/captcha/getPuzzleCaptchaChallenge.ts +++ b/packages/provider/src/api/captcha/getPuzzleCaptchaChallenge.ts @@ -50,8 +50,6 @@ export default ( return next( new ProsopoApiError("CAPTCHA.PARSE_ERROR", { context: { code: 400, error: err }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -82,8 +80,6 @@ export default ( return next( new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -144,8 +140,6 @@ export default ( siteKey: dapp, user, }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -161,8 +155,6 @@ export default ( siteKey: dapp, user, }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -256,8 +248,6 @@ export default ( user: req.body.user, error: err, }, - i18n: req.i18n, - logger: req.logger, }), ); } diff --git a/packages/provider/src/api/captcha/submitImageCaptchaSolution.ts b/packages/provider/src/api/captcha/submitImageCaptchaSolution.ts index dcd00f59a0..e1b9e8f0fa 100644 --- a/packages/provider/src/api/captcha/submitImageCaptchaSolution.ts +++ b/packages/provider/src/api/captcha/submitImageCaptchaSolution.ts @@ -58,8 +58,6 @@ export default (env: ProviderEnvironment) => return next( new ProsopoApiError("CAPTCHA.PARSE_ERROR", { context: { code: 400, error: err, body: req.body }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -88,8 +86,6 @@ export default (env: ProviderEnvironment) => return next( new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -135,8 +131,6 @@ export default (env: ProviderEnvironment) => siteKey: req.body.dapp, error: err, }, - i18n: req.i18n, - logger: req.logger, }), ); } diff --git a/packages/provider/src/api/captcha/submitPoWCaptchaSolution.ts b/packages/provider/src/api/captcha/submitPoWCaptchaSolution.ts index 377120dcd0..7c14027248 100644 --- a/packages/provider/src/api/captcha/submitPoWCaptchaSolution.ts +++ b/packages/provider/src/api/captcha/submitPoWCaptchaSolution.ts @@ -58,8 +58,6 @@ export default (env: ProviderEnvironment) => return next( new ProsopoApiError("CAPTCHA.PARSE_ERROR", { context: { code: 400, error: err, body: req.body }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -98,8 +96,6 @@ export default (env: ProviderEnvironment) => return next( new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -163,8 +159,6 @@ export default (env: ProviderEnvironment) => siteKey: req.body.dapp, error: err, }, - i18n: req.i18n, - logger: req.logger, }), ); } diff --git a/packages/provider/src/api/captcha/submitPuzzleCaptchaSolution.ts b/packages/provider/src/api/captcha/submitPuzzleCaptchaSolution.ts index a04d9efdbb..06c7e0c041 100644 --- a/packages/provider/src/api/captcha/submitPuzzleCaptchaSolution.ts +++ b/packages/provider/src/api/captcha/submitPuzzleCaptchaSolution.ts @@ -55,8 +55,6 @@ export default (env: ProviderEnvironment) => return next( new ProsopoApiError("CAPTCHA.PARSE_ERROR", { context: { code: 400, error: err, body: req.body }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -97,8 +95,6 @@ export default (env: ProviderEnvironment) => return next( new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -137,8 +133,6 @@ export default (env: ProviderEnvironment) => siteKey: req.body.dapp, error: err, }, - i18n: req.i18n, - logger: req.logger, }), ); } diff --git a/packages/provider/src/api/domainMiddleware.ts b/packages/provider/src/api/domainMiddleware.ts index 093709c320..1e0eccf9f5 100644 --- a/packages/provider/src/api/domainMiddleware.ts +++ b/packages/provider/src/api/domainMiddleware.ts @@ -134,8 +134,6 @@ const siteKeyNotRegisteredError = ( ) => { return new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp }, - i18n, - logger, }); }; @@ -146,8 +144,6 @@ const invalidSiteKeyError = ( ) => { return new ProsopoApiError("API.INVALID_SITE_KEY", { context: { code: 400, siteKey: siteKey }, - i18n, - logger, }); }; @@ -158,8 +154,6 @@ const unauthorizedOriginError = ( ) => { return new ProsopoApiError("API.UNAUTHORIZED_ORIGIN_URL", { context: { code: 400, origin }, - i18n, - logger, }); }; @@ -177,7 +171,5 @@ const siteKeyInvalidDomainError = ( siteKey: dapp, domain, }, - i18n, - logger, }); }; diff --git a/packages/provider/src/api/validateAddress.ts b/packages/provider/src/api/validateAddress.ts index dd979f2071..e68ccc63a8 100644 --- a/packages/provider/src/api/validateAddress.ts +++ b/packages/provider/src/api/validateAddress.ts @@ -24,7 +24,9 @@ export const validateSiteKey = (siteKey: string, logger?: Logger) => { export const validateAddr = ( address: string, translationKey: TranslationKey = "CONTRACT.INVALID_ADDRESS", - logger?: Logger, + // Errors no longer log at construction (decoupled from i18n/logging); the + // param is kept for call-site compatibility but intentionally unused. + _logger?: Logger, ) => { try { const valid = validateAddress(address, false, 42); @@ -32,13 +34,11 @@ export const validateAddr = ( if (!valid) { throw new ProsopoApiError(translationKey, { context: { code: 400, siteKey: address }, - logger, }); } } catch (err) { throw new ProsopoApiError(translationKey, { context: { code: 400, siteKey: address }, - logger, }); } }; diff --git a/packages/provider/src/api/verify.ts b/packages/provider/src/api/verify.ts index a0846b45bf..c433331c2a 100644 --- a/packages/provider/src/api/verify.ts +++ b/packages/provider/src/api/verify.ts @@ -93,8 +93,6 @@ export function prosopoVerifyRouter(env: ProviderEnvironment): Router { return next( new ProsopoApiError("CAPTCHA.PARSE_ERROR", { context: { code: 400, error: err, body: req.body }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -128,8 +126,6 @@ export function prosopoVerifyRouter(env: ProviderEnvironment): Router { return next( new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp, user }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -174,8 +170,6 @@ export function prosopoVerifyRouter(env: ProviderEnvironment): Router { return next( new ProsopoApiError("API.BAD_REQUEST", { context: { code: 500, siteKey: req.body.dapp, user: req.body.user }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -217,8 +211,6 @@ export function prosopoVerifyRouter(env: ProviderEnvironment): Router { return next( new ProsopoApiError("CAPTCHA.PARSE_ERROR", { context: { code: 400, error: err, body: req.body }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -253,8 +245,6 @@ export function prosopoVerifyRouter(env: ProviderEnvironment): Router { return next( new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -307,8 +297,6 @@ export function prosopoVerifyRouter(env: ProviderEnvironment): Router { return next( new ProsopoApiError("API.BAD_REQUEST", { context: { code: 500, error: err }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -350,8 +338,6 @@ export function prosopoVerifyRouter(env: ProviderEnvironment): Router { return next( new ProsopoApiError("CAPTCHA.PARSE_ERROR", { context: { code: 400, error: err, body: req.body }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -386,8 +372,6 @@ export function prosopoVerifyRouter(env: ProviderEnvironment): Router { return next( new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", { context: { code: 400, siteKey: dapp }, - i18n: req.i18n, - logger: req.logger, }), ); } @@ -438,8 +422,6 @@ export function prosopoVerifyRouter(env: ProviderEnvironment): Router { return next( new ProsopoApiError("API.BAD_REQUEST", { context: { code: 500, error: err }, - i18n: req.i18n, - logger: req.logger, }), ); } diff --git a/packages/provider/src/tasks/client/clientTasks.ts b/packages/provider/src/tasks/client/clientTasks.ts index 66e1dec737..5a42289332 100644 --- a/packages/provider/src/tasks/client/clientTasks.ts +++ b/packages/provider/src/tasks/client/clientTasks.ts @@ -285,7 +285,6 @@ export class ClientTaskManager { } catch (e: unknown) { const getClientListError = new ProsopoApiError("DATABASE.UNKNOWN", { context: { error: e }, - logger: this.logger, }); this.logger.error(() => ({ err: getClientListError, @@ -368,7 +367,6 @@ export class ClientTaskManager { "DATABASE.UNKNOWN", { context: { error: e }, - logger: this.logger, }, ); this.logger.error(() => ({ @@ -429,9 +427,8 @@ export class ClientTaskManager { async updateDetectorKey(detectorKey: string): Promise { if (!isValidPrivateKey(detectorKey)) { - throw new ProsopoApiError("INVALID_DETECTOR_KEY", { + throw new ProsopoApiError("API.INVALID_DETECTOR_KEY", { context: { detectorKey }, - logger: this.logger, }); } await this.providerDB.storeDetectorKey(detectorKey); @@ -445,9 +442,8 @@ export class ClientTaskManager { expirationInSeconds?: number, ): Promise { if (!isValidPrivateKey(detectorKey)) { - throw new ProsopoApiError("INVALID_DETECTOR_KEY", { + throw new ProsopoApiError("API.INVALID_DETECTOR_KEY", { context: { detectorKey }, - logger: this.logger, }); } await this.providerDB.removeDetectorKey(detectorKey, expirationInSeconds); @@ -470,7 +466,6 @@ export class ClientTaskManager { if (scope === DecisionMachineScope.Dapp && !dappAccount) { throw new ProsopoApiError("API.BAD_REQUEST", { context: { scope, dappAccount }, - logger: this.logger, }); } @@ -541,7 +536,6 @@ export class ClientTaskManager { if (!artifact) { throw new ProsopoApiError("API.BAD_REQUEST", { context: { id }, - logger: this.logger, }); } return { @@ -567,7 +561,6 @@ export class ClientTaskManager { if (!success) { throw new ProsopoApiError("API.BAD_REQUEST", { context: { id, message: "Decision machine not found" }, - logger: this.logger, }); } return { diff --git a/packages/provider/src/tasks/imgCaptcha/imgCaptchaTasks.ts b/packages/provider/src/tasks/imgCaptcha/imgCaptchaTasks.ts index 9ab2bea387..d32c1cbed7 100644 --- a/packages/provider/src/tasks/imgCaptcha/imgCaptchaTasks.ts +++ b/packages/provider/src/tasks/imgCaptcha/imgCaptchaTasks.ts @@ -438,7 +438,7 @@ export class ImgCaptchaManager extends CaptchaManager { const writePromises: Promise[] = [ this.db.disapproveDappUserCommitment( commitmentId, - "CAPTCHA.INVALID_SOLUTION", + ResultReason.CAPTCHA_INVALID_SOLUTION, pairs, ), ]; @@ -499,7 +499,7 @@ export class ImgCaptchaManager extends CaptchaManager { const writePromises: Promise[] = [ this.db.disapproveDappUserCommitment( commitmentId, - "CAPTCHA.INVALID_SOLUTION", + ResultReason.CAPTCHA_INVALID_SOLUTION, pairs, ), ]; diff --git a/packages/provider/src/tests/integration/imgCaptcha.integration.test.ts b/packages/provider/src/tests/integration/imgCaptcha.integration.test.ts index 593d4de163..357c11b7da 100644 --- a/packages/provider/src/tests/integration/imgCaptcha.integration.test.ts +++ b/packages/provider/src/tests/integration/imgCaptcha.integration.test.ts @@ -370,7 +370,7 @@ describe("Image Captcha Integration Tests", () => { expect(response.status).toBe(400); const data = (await response.json()) as CaptchaResponseBody; expect(data).toHaveProperty("error"); - expect(data.error?.message).toBe("Site key not registered"); + expect(data.error?.message).toBe("API.SITE_KEY_NOT_REGISTERED"); }); it("should not supply an image captcha challenge to a Dapp User if an invalid site key is provided", async () => { @@ -397,7 +397,7 @@ describe("Image Captcha Integration Tests", () => { const data = (await response.json()) as CaptchaResponseBody; expect(response.status).toBe(400); expect(data).toHaveProperty("error"); - expect(data.error?.message).toBe("Invalid site key"); + expect(data.error?.message).toBe("API.INVALID_SITE_KEY"); }); it("should fail if datasetID is incorrect", async () => { @@ -446,10 +446,10 @@ describe("Image Captcha Integration Tests", () => { expect(response.status).toBe(400); const data = (await response.json()) as CaptchaResponseBody; expect(data).toHaveProperty("error"); - expect(data.error?.message).toBe("Incorrect CAPTCHA type"); + expect(data.error?.message).toBe("API.INCORRECT_CAPTCHA_TYPE"); expect(data.error?.code).toBe(400); }); - it("should return a translated error if the captcha type is set to pow and the language is set to es", async () => { + it("should return the locale-stable error key regardless of Accept-Language (es)", async () => { const origin = "https://localhost"; const getImageCaptchaURL = `${baseUrl}${ClientApiPaths.GetImageCaptchaChallenge}`; await registerSiteKeyInDb(env, dappAccount, CaptchaType.pow); @@ -473,7 +473,7 @@ describe("Image Captcha Integration Tests", () => { expect(response.status).toBe(400); const data = (await response.json()) as CaptchaResponseBody; expect(data).toHaveProperty("error"); - expect(data.error?.message).toBe("Tipo de CAPTCHA incorrecto"); + expect(data.error?.message).toBe("API.INCORRECT_CAPTCHA_TYPE"); expect(data.error?.code).toBe(400); }); }); @@ -500,7 +500,7 @@ describe("Image Captcha Integration Tests", () => { expect(response.status).toBe(400); const data = (await response.json()) as CaptchaResponseBody; expect(data).toHaveProperty("error"); - expect(data.error?.message).toBe("Incorrect CAPTCHA type"); + expect(data.error?.message).toBe("API.INCORRECT_CAPTCHA_TYPE"); expect(data.error?.code).toBe(400); }); diff --git a/packages/provider/src/tests/integration/powCaptcha.integration.test.ts b/packages/provider/src/tests/integration/powCaptcha.integration.test.ts index a8c62fde00..44539f505d 100644 --- a/packages/provider/src/tests/integration/powCaptcha.integration.test.ts +++ b/packages/provider/src/tests/integration/powCaptcha.integration.test.ts @@ -596,7 +596,7 @@ describe("PoW Integration Tests", () => { const data = (await captchaRes.json()) as GetPowCaptchaResponse; expect(data).toHaveProperty("error"); - expect(data.error?.message).toBe("Site key not registered"); + expect(data.error?.message).toBe("API.SITE_KEY_NOT_REGISTERED"); }); }); @@ -619,7 +619,7 @@ describe("PoW Integration Tests", () => { const challengeBody = (await captchaRes.json()) as GetPowCaptchaResponse; expect(challengeBody).toHaveProperty("error"); - expect(challengeBody.error?.message).toBe("Invalid site key"); + expect(challengeBody.error?.message).toBe("API.INVALID_SITE_KEY"); }); it("should return an error if the captcha type is set to image", async () => { @@ -645,7 +645,7 @@ describe("PoW Integration Tests", () => { const challengeBody = (await captchaRes.json()) as GetPowCaptchaResponse; expect(challengeBody).toHaveProperty("error"); - expect(challengeBody.error?.message).toBe("Incorrect CAPTCHA type"); + expect(challengeBody.error?.message).toBe("API.INCORRECT_CAPTCHA_TYPE"); expect(challengeBody.error?.code).toBe(400); }); it("should return an error if the captcha type is set to frictionless and no sessionID is sent", async () => { @@ -671,7 +671,7 @@ describe("PoW Integration Tests", () => { const challengeBody = (await captchaRes.json()) as GetPowCaptchaResponse; expect(challengeBody).toHaveProperty("error"); - expect(challengeBody.error?.message).toBe("Incorrect CAPTCHA type"); + expect(challengeBody.error?.message).toBe("API.INCORRECT_CAPTCHA_TYPE"); expect(challengeBody.error?.code).toBe(400); }); }); diff --git a/packages/provider/src/tests/unit/api/validateAddress.unit.test.ts b/packages/provider/src/tests/unit/api/validateAddress.unit.test.ts index b3d7e96863..9d26854e67 100644 --- a/packages/provider/src/tests/unit/api/validateAddress.unit.test.ts +++ b/packages/provider/src/tests/unit/api/validateAddress.unit.test.ts @@ -161,7 +161,7 @@ describe("validateAddr", () => { it("should validate with different translation keys", () => { const invalidAddress = "invalid-address"; - const customTranslationKey = "API.INVALID_USER"; + const customTranslationKey = "API.INVALID_SITE_KEY"; vi.mocked(validateAddress).mockReturnValue(false); diff --git a/packages/types-database/src/types/provider.ts b/packages/types-database/src/types/provider.ts index ba196c702a..196b550240 100644 --- a/packages/types-database/src/types/provider.ts +++ b/packages/types-database/src/types/provider.ts @@ -13,7 +13,7 @@ // limitations under the License. import type { AllKeys } from "@prosopo/common"; -import { type TranslationKey, TranslationKeysSchema } from "@prosopo/locale"; +import { TranslationKeysSchema } from "@prosopo/locale"; import { CaptchaLabel, CaptchaType, @@ -30,6 +30,7 @@ import { type PendingImageCaptchaRequest, type PoWCaptchaStored, type PuzzleCaptchaStored, + type ResultReason, type Session, type SimdReadingsStage, type SolutionRecord, @@ -804,7 +805,7 @@ export interface IProviderDatabase extends IDatabase { disapproveDappUserCommitment( commitmentId: string, - reason?: TranslationKey, + reason?: ResultReason, coords?: [number, number][][], ): Promise;