From 5f28f5f515ae859d1f9cf58f9cbf17f3cad417e5 Mon Sep 17 00:00:00 2001 From: dfliess Date: Mon, 29 Jun 2026 09:52:33 +0200 Subject: [PATCH 1/4] feat(i18n): add Paraglide JS framework with EN/ES catalogs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set up Paraglide JS v2 for frontend internationalization: - Add @inlang/paraglide-js and @inlang/plugin-message-format dependencies - Configure Vite plugin with cookie → preferredLanguage → baseLocale strategy - Add inlang project config at web-common/project.inlang/settings.json - Add 1732 message keys in EN/ES with full parity - Commit compiled Paraglide output (locale-modules structure) --- package-lock.json | 343 ++++- web-admin/package.json | 3 +- web-admin/vite.config.ts | 13 +- web-common/messages/en.json | 1734 +++++++++++++++++++++++ web-common/messages/es.json | 1734 +++++++++++++++++++++++ web-common/package.json | 1 + web-common/project.inlang/settings.json | 9 + 7 files changed, 3767 insertions(+), 70 deletions(-) create mode 100644 web-common/messages/en.json create mode 100644 web-common/messages/es.json create mode 100644 web-common/project.inlang/settings.json diff --git a/package-lock.json b/package-lock.json index d18f5b7eb96f..1847231a0c55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5296,7 +5296,6 @@ "os": [ "aix" ], - "peer": true, "engines": { "node": ">=18" } @@ -5314,7 +5313,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=18" } @@ -5332,7 +5330,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=18" } @@ -5350,7 +5347,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=18" } @@ -5368,7 +5364,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=18" } @@ -5386,7 +5381,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=18" } @@ -5404,7 +5398,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -5422,7 +5415,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -5440,7 +5432,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -5458,7 +5449,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -5476,7 +5466,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -5494,7 +5483,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -5512,7 +5500,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -5530,7 +5517,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -5548,7 +5534,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -5566,7 +5551,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -5584,7 +5568,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -5602,7 +5585,6 @@ "os": [ "netbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -5620,7 +5602,6 @@ "os": [ "netbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -5638,7 +5619,6 @@ "os": [ "openbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -5656,7 +5636,6 @@ "os": [ "openbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -5674,7 +5653,6 @@ "os": [ "openharmony" ], - "peer": true, "engines": { "node": ">=18" } @@ -5692,7 +5670,6 @@ "os": [ "sunos" ], - "peer": true, "engines": { "node": ">=18" } @@ -5710,7 +5687,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=18" } @@ -5728,7 +5704,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=18" } @@ -5746,7 +5721,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=18" } @@ -6242,6 +6216,123 @@ "mlly": "^1.8.0" } }, + "node_modules/@inlang/paraglide-js": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/@inlang/paraglide-js/-/paraglide-js-2.20.1.tgz", + "integrity": "sha512-8mDhvcociFkWZDy3J+ZIIWkl0GTtJjVXS/kcBT2QG2l88y7+bFT45s8I00a7Hp1eFP9y6ScJMmNXWy87Krt7wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inlang/recommend-sherlock": "^0.2.1", + "@inlang/sdk": "^2.10.0", + "commander": "11.1.0", + "consola": "3.4.0", + "json5": "2.2.3", + "unplugin": "^2.1.2", + "urlpattern-polyfill": "^10.0.0" + }, + "bin": { + "paraglide-js": "bin/run.js" + }, + "peerDependencies": { + "typescript": ">=5.6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@inlang/paraglide-js/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/@inlang/paraglide-js/node_modules/consola": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.0.tgz", + "integrity": "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/@inlang/plugin-message-format": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@inlang/plugin-message-format/-/plugin-message-format-4.4.0.tgz", + "integrity": "sha512-n4aXt6XVg5kxhKoLAhi9nMgZtCA9iS0QOaXte56VqxWHcfj9O4c4gOkyVQZH7H9D8h7OZufCrO1sZGYOypPwEA==", + "dev": true, + "dependencies": { + "flat": "^6.0.1" + } + }, + "node_modules/@inlang/plugin-message-format/node_modules/flat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-6.0.1.tgz", + "integrity": "sha512-/3FfIa8mbrg3xE7+wAhWeV+bd7L2Mof+xtZb5dRDKZ+wDvYJK4WDYeIOuOhre5Yv5aQObZrlbRmk3RTSiuQBtw==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inlang/recommend-sherlock": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@inlang/recommend-sherlock/-/recommend-sherlock-0.2.1.tgz", + "integrity": "sha512-ckv8HvHy/iTqaVAEKrr+gnl+p3XFNwe5D2+6w6wJk2ORV2XkcRkKOJ/XsTUJbPSiyi4PI+p+T3bqbmNx/rDUlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "comment-json": "^4.2.3" + } + }, + "node_modules/@inlang/sdk": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@inlang/sdk/-/sdk-2.10.2.tgz", + "integrity": "sha512-O1ki72SNK6LPagaGrvlioBb1mWKvump7cO7P85hfGZjdFTmDdn3icI0A6MvaBsB3P9KQHAjzyubnN1OslGufTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lix-js/sdk": "0.4.10", + "@sinclair/typebox": "^0.31.17", + "kysely": "^0.28.12", + "sqlite-wasm-kysely": "0.3.0", + "uuid": "^14.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@inlang/sdk/node_modules/@sinclair/typebox": { + "version": "0.31.28", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.31.28.tgz", + "integrity": "sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@inlang/sdk/node_modules/uuid": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", + "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, "node_modules/@internationalized/date": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.12.0.tgz", @@ -7019,6 +7110,46 @@ "@lezer/lr": "^1.4.0" } }, + "node_modules/@lix-js/sdk": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@lix-js/sdk/-/sdk-0.4.10.tgz", + "integrity": "sha512-0dMInAJK/67guTG5rRZaCEhvzC5cCXENOjaePA5AqMXrCE97kaY7SRor9e2vnoGsFIiGqXKlT0MCIoZj36G0gg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@lix-js/server-protocol-schema": "0.1.1", + "dedent": "1.5.1", + "human-id": "^4.1.1", + "js-sha256": "^0.11.0", + "kysely": "^0.28.12", + "sqlite-wasm-kysely": "0.3.0", + "uuid": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@lix-js/sdk/node_modules/uuid": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", + "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/@lix-js/server-protocol-schema": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@lix-js/server-protocol-schema/-/server-protocol-schema-0.1.1.tgz", + "integrity": "sha512-jBeALB6prAbtr5q4vTuxnRZZv1M2rKe8iNqRQhFJ4Tv7150unEa0vKyz0hs8Gl3fUGsWaNJBh3J8++fpbrpRBQ==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/@marijn/find-cluster-break": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", @@ -7109,7 +7240,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@tybys/wasm-util": "^0.10.1" }, @@ -7173,18 +7303,6 @@ "node": ">= 8" } }, - "node_modules/@opentelemetry/api": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", - "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "peer": true, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/@orval/angular": { "version": "7.21.0", "resolved": "https://registry.npmjs.org/@orval/angular/-/angular-7.21.0.tgz", @@ -8613,7 +8731,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8631,7 +8748,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8649,7 +8765,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8667,7 +8782,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8685,7 +8799,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8703,7 +8816,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8721,7 +8833,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8739,7 +8850,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8757,7 +8867,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8775,7 +8884,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8793,7 +8901,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8811,7 +8918,6 @@ "os": [ "openharmony" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8826,7 +8932,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, @@ -8847,7 +8952,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -8865,7 +8969,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -9107,6 +9210,16 @@ ], "license": "MIT" }, + "node_modules/@sqlite.org/sqlite-wasm": { + "version": "3.48.0-build4", + "resolved": "https://registry.npmjs.org/@sqlite.org/sqlite-wasm/-/sqlite-wasm-3.48.0-build4.tgz", + "integrity": "sha512-hI6twvUkzOmyGZhQMza1gpfqErZxXRw6JEsiVjUbo7tFanVD+8Oil0Ih3l2nGzHdxPI41zFmfUQG7GHqhciKZQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "sqlite-wasm": "bin/index.js" + } + }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", @@ -10411,7 +10524,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -12517,6 +12629,13 @@ "dev": true, "license": "MIT" }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true, + "license": "MIT" + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -14255,6 +14374,20 @@ "node": ">=18" } }, + "node_modules/comment-json": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.6.2.tgz", + "integrity": "sha512-R2rze/hDX30uul4NZoIZ76ImSJLFxn/1/ZxtKC1L77y2X1k+yYu1joKbAtMA2Fg3hZrTOiw0I5mwVMo0cf250w==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-timsort": "^1.0.3", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/common-path-prefix": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", @@ -15945,6 +16078,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -19775,6 +19923,16 @@ "node": ">= 14" } }, + "node_modules/human-id": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.2.0.tgz", + "integrity": "sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA==", + "dev": true, + "license": "MIT", + "bin": { + "human-id": "dist/cli.js" + } + }, "node_modules/human-signals": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", @@ -20877,6 +21035,13 @@ "node": ">=0.10.0" } }, + "node_modules/js-sha256": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.11.1.tgz", + "integrity": "sha512-o6WSo/LUvY2uC4j7mO50a2ms7E/EAdbP0swigLV+nzHKTTaYnaLIWJ02VdXrsJX0vGedDESQnLsOekr94ryfjg==", + "dev": true, + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -21184,6 +21349,16 @@ "dev": true, "license": "MIT" }, + "node_modules/kysely": { + "version": "0.28.17", + "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.17.tgz", + "integrity": "sha512-nbD8lB9EB3wNdMhOCdx5Li8DxnLbvKByylRLcJ1h+4SkrowVeECAyZlyiKMThF7xFdRz0jSQ2MoJr+wXux2y0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/langium": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/langium/-/langium-4.2.1.tgz", @@ -21368,7 +21543,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -21390,7 +21564,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -21412,7 +21585,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -21434,7 +21606,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -21456,7 +21627,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -21478,7 +21648,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -21500,7 +21669,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -21522,7 +21690,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -21544,7 +21711,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -21566,7 +21732,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -21588,7 +21753,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -30803,6 +30967,18 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/sqlite-wasm-kysely": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/sqlite-wasm-kysely/-/sqlite-wasm-kysely-0.3.0.tgz", + "integrity": "sha512-TzjBNv7KwRw6E3pdKdlRyZiTmUIE0UttT/Sl56MVwVARl/u5gp978KepazCJZewFUnlWHz9i3NQd4kOtP/Afdg==", + "dev": true, + "dependencies": { + "@sqlite.org/sqlite-wasm": "^3.48.0-build2" + }, + "peerDependencies": { + "kysely": "*" + } + }, "node_modules/srcset": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", @@ -32751,7 +32927,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } @@ -33292,6 +33467,22 @@ "node": ">= 0.8" } }, + "node_modules/unplugin": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.11.tgz", + "integrity": "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "acorn": "^8.15.0", + "picomatch": "^4.0.3", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=18.12.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -33528,6 +33719,13 @@ "dev": true, "license": "BSD" }, + "node_modules/urlpattern-polyfill": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", + "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==", + "dev": true, + "license": "MIT" + }, "node_modules/use-sync-external-store": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", @@ -34287,7 +34485,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } @@ -34881,6 +35078,13 @@ "node": ">=10.13.0" } }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT" + }, "node_modules/webpack/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -35715,6 +35919,7 @@ "version": "0.0.0", "devDependencies": { "@fontsource/fira-mono": "^4.5.0", + "@inlang/paraglide-js": "^2.20.1", "@playwright/test": "^1.50.1", "@sveltejs/adapter-static": "^3.0.10", "@sveltejs/kit": "^2.55.0", @@ -35761,6 +35966,7 @@ "@dagrejs/dagre": "^1.1.3", "@exodus/schemasafe": "^1.3.0", "@floating-ui/dom": "^1.7.4", + "@inlang/plugin-message-format": "^4.4.0", "@replit/codemirror-indentation-markers": "^6.5.3", "@sveltejs/kit": "^2.55.0", "@tanstack/svelte-query": "~5.76.0", @@ -35856,6 +36062,7 @@ "version": "0.0.0", "devDependencies": { "@clickhouse/client": "^1.11.0", + "@inlang/paraglide-js": "^2.20.1", "@playwright/test": "^1.50.1", "@sveltejs/adapter-static": "^3.0.10", "@sveltejs/kit": "^2.55.0", diff --git a/web-admin/package.json b/web-admin/package.json index 136ac21d5414..758c63182b6a 100644 --- a/web-admin/package.json +++ b/web-admin/package.json @@ -20,11 +20,11 @@ }, "devDependencies": { "@fontsource/fira-mono": "^4.5.0", + "@inlang/paraglide-js": "^2.20.1", "@playwright/test": "^1.50.1", "@sveltejs/adapter-static": "^3.0.10", "@sveltejs/kit": "^2.55.0", "@tanstack/svelte-query": "~5.76.0", - "tanstack-table-8-svelte-5": "^0.1.2", "autoprefixer": "^10.4.20", "axios": "1.13.6", "cronstrue": "^2.41.0", @@ -35,6 +35,7 @@ "svelte-check": "^4.0.4", "svelte-preprocess": "^6.0.3", "tailwindcss": "^3.4.13", + "tanstack-table-8-svelte-5": "^0.1.2", "vitest": "^4.1.1", "web-common": "*" }, diff --git a/web-admin/vite.config.ts b/web-admin/vite.config.ts index 111d208462df..edf0d3e2c198 100644 --- a/web-admin/vite.config.ts +++ b/web-admin/vite.config.ts @@ -1,3 +1,4 @@ +import { paraglideVitePlugin } from "@inlang/paraglide-js"; import { sveltekit } from "@sveltejs/kit/vite"; import dns from "dns"; import { defineConfig } from "vitest/config"; @@ -39,7 +40,17 @@ export default defineConfig({ ], exclude: ["sveltekit-superforms"], }, - plugins: [sveltekit()], + plugins: [ + paraglideVitePlugin({ + project: "../web-common/project.inlang", + outdir: "../web-common/src/paraglide", + strategy: ["cookie", "preferredLanguage", "baseLocale"], + emitGitIgnore: false, + emitPrettierIgnore: false, + outputStructure: "locale-modules", + }), + sveltekit(), + ], envDir: "../", envPrefix: "RILL_UI_PUBLIC_", }); diff --git a/web-common/messages/en.json b/web-common/messages/en.json new file mode 100644 index 000000000000..162a4d8823a9 --- /dev/null +++ b/web-common/messages/en.json @@ -0,0 +1,1734 @@ +{ + "alert_context_menu_aria": "Alert context menu", + "alert_create_alert": "Create alert", + "alert_created_by": "Created by {name}", + "alert_created_through_code": "Created through code", + "alert_criteria": "Criteria", + "alert_dashboard": "Dashboard", + "alert_dashboard_not_exist": "Dashboard does not exist", + "alert_delete": "Delete Alert", + "alert_edit": "Edit alert", + "alert_email_notifications": "Email notifications", + "alert_filters_label": "Filters ({count})", + "alert_form_back": "Back", + "alert_form_cancel": "Cancel", + "alert_form_create": "Create", + "alert_form_create_title": "Create Alert", + "alert_form_created": "Alert created", + "alert_form_criteria_description": "Trigger alert when these conditions are met", + "alert_form_criteria_group_aria": "Criteria group operation", + "alert_form_criteria_measure_aria": "Criteria measure", + "alert_form_criteria_measure_placeholder": "Measure", + "alert_form_criteria_operator_aria": "Criteria operator", + "alert_form_criteria_operator_placeholder": "Operator", + "alert_form_criteria_preview_title": "Alert Preview", + "alert_form_criteria_title": "Criteria", + "alert_form_criteria_type_aria": "Criteria type", + "alert_form_criteria_type_placeholder": "type", + "alert_form_criteria_value_title": "Criteria value", + "alert_form_data_filters": "Filters", + "alert_form_data_measure": "Measure", + "alert_form_data_measure_placeholder": "Select a measure", + "alert_form_data_measures_desc": "Select the measures you want to monitor.", + "alert_form_data_none": "None", + "alert_form_data_preview": "Data preview", + "alert_form_data_preview_desc": "Here's a look at the data you've selected above.", + "alert_form_data_split_by": "Split by dimension", + "alert_form_data_split_placeholder": "Select a dimension", + "alert_form_data_title": "Alert data", + "alert_form_edit_title": "Edit Alert", + "alert_form_edited": "Alert edited", + "alert_form_email_desc": "We'll email alerts to these addresses. Make sure they have access to your project.", + "alert_form_email_placeholder": "Enter an email address", + "alert_form_email_title": "Email notifications", + "alert_form_go_to_alerts": "Go to alerts", + "alert_form_name_placeholder": "My alert", + "alert_form_name_title": "Alert name", + "alert_form_next": "Next", + "alert_form_no_criteria": "No criteria selected", + "alert_form_no_data": "No data to preview", + "alert_form_preview_cell": "Preview cell", + "alert_form_preview_table_aria": "alert preview table", + "alert_form_select_criteria": "Select criteria to see a preview", + "alert_form_slack_channels_desc": "We'll send alerts directly to these channels.", + "alert_form_slack_not_configured": "Slack has not been configured for this project. Read the docs to learn more.", + "alert_form_slack_placeholder": "# Enter a Slack channel name", + "alert_form_slack_title": "Slack notifications", + "alert_form_slack_users_desc": "We'll alert them with direct messages in Slack.", + "alert_form_snooze_desc": "Set a snooze period to silence repeat notifications for the same alert.", + "alert_form_snooze_title": "Snooze", + "alert_form_tab_criteria": "Criteria", + "alert_form_tab_data": "Data", + "alert_form_tab_delivery": "Delivery", + "alert_form_trigger": "Trigger", + "alert_form_trigger_data_refresh": "Whenever data refreshes", + "alert_form_trigger_set_schedule": "Set schedule", + "alert_form_update": "Update", + "alert_go_to_page": "Go to Alerts page", + "alert_has_not_run_yet": "This alert has not run yet", + "alert_last_checked": "Last checked {time}", + "alert_loading": "Loading...", + "alert_name_label": "Name", + "alert_no_filters_body": "No filters were applied to the dashboard that this alert was created from.", + "alert_no_filters_heading": "No filters selected", + "alert_no_filters_hint": "To apply filters, close this window and filter your dashboard.", + "alert_none": "None", + "alert_not_checked_yet": "Hasn't been checked yet", + "alert_recent_history": "Recent history", + "alert_schedule": "Schedule", + "alert_set_non_custom_time_range": "To create an alert, set a non-custom time range.", + "alert_showing_recent_checks": "Showing up to 25 most recent checks", + "alert_slack_notifications": "Slack notifications", + "alert_snooze": "Snooze", + "alert_split_by_dimension": "Split by dimension", + "alert_status_checked": "Checked", + "alert_status_checking": "Checking", + "alert_status_failed": "Failed", + "alert_status_not_triggered": "Not triggered", + "alert_status_running": "Running", + "alert_status_triggered": "Triggered", + "alert_status_unknown": "Status unknown", + "alert_unable_to_open": "Unable to open Alert", + "alert_unsubscribe_failed": "Failed to unsubscribe.", + "alert_unsubscribed": "Unsubscribed from alert.", + "alert_unsubscribing": "Unsubscribing...", + "alert_whenever_data_refreshes": "Whenever your data refreshes", + "alerts_empty_action": "Create {alertsLink} from any dashboard or {codeLink}.", + "alerts_empty_message": "You don't have any alerts yet", + "alerts_link_text": "alerts", + "alerts_via_code": "via code", + "auth_access_requested": "Access requested", + "auth_allow_domain_access": "Allow domain access", + "auth_authenticating_as": "You are authenticating into Rill as {email}.", + "auth_authorize_rill_cli": "Authorize Rill CLI", + "auth_check_email_to_verify": "Please check your email to verify your account.", + "auth_cli_success_message": "Close this page and continue in the Rill CLI.", + "auth_cli_success_title": "Successfully authorized Rill CLI", + "auth_confirm_code": "Confirm code", + "auth_confirm_code_displayed": "Please confirm this is the code displayed in the Rill CLI.", + "auth_continue": "Continue", + "auth_denying_access": "Denying {email} access to {project}", + "auth_device_code_confirmation_failed": "User code confirmation failed", + "auth_device_code_confirmed": "User code confirmed, this page can be closed now", + "auth_device_code_rejected": "User code rejected, this page can be closed now", + "auth_device_code_rejection_failed": "User code rejection failed", + "auth_device_meta_description": "User code confirmation", + "auth_grant_access": "Grant access", + "auth_grant_access_description": "Select a role for {email} to access the project {project}.", + "auth_grant_access_title": "Grant access to this project", + "auth_invite_by_email": "Invite by email", + "auth_invite_teammates": "Invite teammates to your project", + "auth_log_in_sign_up": "Log In / Sign Up", + "auth_request_access": "Request access", + "auth_request_access_description": "You can view {project} once your request is approved.", + "auth_request_access_title": "Request access to this project", + "auth_request_sent": "Your request has been sent to the project admin. You'll get an email when it's approved.", + "auth_skip_for_now": "Skip for now", + "auth_thanks_for_signing_up": "Thanks for signing up!", + "auth_user_added_to_project": "{email} has been added to {project} as a {role}", + "auth_user_denied_access": "{email} has been denied access to {project}", + "avatar_contact_support": "Contact Rill support", + "avatar_copied_url": "Copied URL", + "avatar_copy_url": "Copy URL", + "avatar_copy_url_for_view": "Copy URL for this view", + "avatar_create_public_url": "Create public URL", + "avatar_documentation": "Documentation", + "avatar_join_discord": "Join us on Discord", + "avatar_logout": "Logout", + "avatar_share": "Share", + "avatar_share_dashboard": "Share dashboard", + "avatar_share_description": "Share your current view with another project member.", + "avatar_view_as": "View as", + "bignumber_copy_value": "Copy this value to clipboard", + "bignumber_shift_click": "+ Click", + "billing_30_day_free_trial": "30 day free trial", + "billing_30_days": "30 days", + "billing_access_until": "but you still have access until {date}", + "billing_assign_as_contact": "Assign as billing contact", + "billing_available_credit": "Available credit", + "billing_billing_address_short": "billing address", + "billing_cancel": "Cancel", + "billing_cancel_anytime": "Cancel anytime.", + "billing_cancel_plan": "Cancel plan", + "billing_cancel_plan_desc": "If you cancel your plan, you'll still be able to access your account through {date}.", + "billing_cancel_plan_title": "Cancel your {planName} plan?", + "billing_cancel_subscription": "Cancel subscription", + "billing_change_billing_contact": "Change billing contact", + "billing_change_subscription": "Change subscription", + "billing_choose_a_plan": "Choose a plan", + "billing_choose_plan_name": "Choose {planName}", + "billing_choose_plan_to_maintain": "Choose a plan to maintain access.", + "billing_choosing_plan_ends_trial": "Choosing a plan ends your trial and starts your billing cycle today.", + "billing_close": "Close", + "billing_congrats_plan": "Congrats on starting your {planName} plan. To get the most out of your plan, {docsLink}", + "billing_contact_assigned": "{name} has been assigned as billing contact.", + "billing_contact_header": "Billing Contact", + "billing_contact_reassign_failed": "Failed to reassign billing contact. Please try again or contact support.", + "billing_contact_support": "contact support", + "billing_contact_us_cta": "Contact us", + "billing_contact_us_link": "contact us", + "billing_contact_us_to_maintain": "To maintain access, please contact us.", + "billing_contact_us_to_regain": "Contact us to regain access.", + "billing_credit_percent_used": "{percent}% used, projects will hibernate when credits run out.", + "billing_credits_depleted": "Trial credit is used up. Projects are hibernated and dashboards are offline.", + "billing_current": "Current", + "billing_cycle_will_resume": "Your billing cycle will resume {resumeText}.", + "billing_data_size": "Data Size", + "billing_days_remaining": "Days remaining", + "billing_days_used": "Days used", + "billing_dev_compute_units": "{count} Dev Compute Units", + "billing_dialog_title_org": "To create another organization, choose a plan", + "billing_dialog_title_proj": "To deploy a second project, choose a plan", + "billing_dialog_title_renew": "Renew your plan", + "billing_dialog_title_size": "Deploying more than 10 GB requires a paid plan", + "billing_dialog_title_trial_expired": "Your trial has ended — choose a plan", + "billing_enterprise_desc": "Custom contract", + "billing_enterprise_desc_managed": "Custom contract · Fully managed", + "billing_enterprise_details": "Fully managed slots, dedicated CSM, white-label capabilities, and custom SLAs. Contact your CSM for contract details or changes.", + "billing_error_redirect_payment": "Error redirecting to payment portal", + "billing_fix_payment_issues": "Please fix payment issues: {details}", + "billing_free_credit_desc": "$250 free credit", + "billing_free_trial_info": "free trial · 30 days, no credit card required. Projects hibernate when trial ends.", + "billing_free_trial_with_credits": "You are on a free trial with ${amount} in credits.", + "billing_got_it": "Got it", + "billing_highlight_1m_ai_tokens": "1M AI tokens / seat / month", + "billing_highlight_2m_ai_tokens": "2M AI tokens / seat / month", + "billing_highlight_bring_own_ai": "Bring your own AI model", + "billing_highlight_embedded_analytics": "Embedded analytics", + "billing_input_valid_to_maintain": "Input a valid {methods} to maintain access.", + "billing_input_valid_to_wake": "Input a valid {methods} to wake projects and regain full access.", + "billing_invoice_past_due": "Your invoice is past due{suffix}.", + "billing_keep_plan": "Keep plan", + "billing_manage_cards_via_stripe": "Manage your cards via Stripe", + "billing_manage_in_stripe": "Manage in Stripe", + "billing_no_billing_contact": "This org has no billing contact.", + "billing_no_payment_method": "No payment method on file.", + "billing_no_time_limit": "No time limit, use it until it's gone.", + "billing_no_valid_on_file": "No valid {methods} on file.", + "billing_on_date": "on {date}", + "billing_or": "or", + "billing_payment_method_on_file": "Payment method on file", + "billing_payment_method_short": "payment method", + "billing_payment_methods_header": "Payment methods", + "billing_per_day": "day", + "billing_plan_badge_enterprise": "Enterprise", + "billing_plan_badge_free_trial": "Free Trial", + "billing_plan_badge_managed": "Managed", + "billing_plan_badge_pro": "Pro", + "billing_plan_badge_pro_trial": "Pro Trial", + "billing_plan_badge_team": "Team", + "billing_plan_cancelled": "Your plan is cancelled {accessTimeout}.", + "billing_plan_header": "Plan", + "billing_plan_name_growth": "Growth", + "billing_plan_name_starter": "Starter", + "billing_plan_price_unit": "/ seat / month", + "billing_plan_renewed": "Your {planName} plan was renewed", + "billing_plan_tagline_growth": "For growing teams and embedded analytics.", + "billing_plan_tagline_starter": "For small teams getting started.", + "billing_plan_was_cancelled": "Your {planName} plan was cancelled", + "billing_prod_compute_units": "{count} Prod Compute Units", + "billing_projects": "Projects", + "billing_projects_hibernating": " and this org's projects are now hibernating", + "billing_quota_api_calls": "{value} API calls / seat / month", + "billing_quota_compute_units": "Up to {value} compute units", + "billing_quota_managed_db": "Managed database up to {value}", + "billing_quota_projects": "Up to {value} projects", + "billing_quota_seats": "Up to {value} seats", + "billing_recommended": "Recommended", + "billing_refer_to_docs": "refer to our docs", + "billing_renew": "Renew", + "billing_renew_to_maintain_access": "To maintain access, renew your plan.", + "billing_renewing_plan": "Renewing {plan} plan...", + "billing_see_pricing_details": "See pricing details", + "billing_select_admin_as_contact": "Select another org admin as billing contact.", + "billing_subscription_ended": "and your subscription has ended", + "billing_subscription_past_due": "Your subscription is past due{suffix}.", + "billing_team_details": "Flat-rate plan. $250/mo includes up to 8 slots and 10 GB storage, with $25/GB for overages.", + "billing_team_info": "$250/mo flat rate + storage overages. 10 GB included · $25/GB over. Up to 8 slots.", + "billing_team_price_desc": "$250/mo flat + storage", + "billing_today": "today", + "billing_trial_credit_running_low": "Your trial credit is running low.", + "billing_trial_expired": "Your trial has expired.", + "billing_trial_expired_hibernated": "Trial expired · Projects hibernated", + "billing_trial_expired_hibernating": "Your trial has expired and this org's projects are now hibernating.", + "billing_trial_expires_in": "Your trial expires in {duration}.", + "billing_trial_percent_used": "{percent}% of trial used, projects will hibernate when trial ends", + "billing_unit_spec": "1 unit = 4GiB RAM, 1vGPU", + "billing_unknown": "Unknown", + "billing_unlimited": "Unlimited", + "billing_update_payment": "Update payment", + "billing_update_payment_methods": "Update payment methods", + "billing_upgrade_to_pro": "Upgrade to Pro", + "billing_upgrade_to_team": "Upgrade to Team plan", + "billing_upgrade_to_wake": "Upgrade to wake projects and regain full access.", + "billing_upgrade_within_to_maintain": "Upgrade within {duration} to maintain access.", + "billing_upgrading_plan": "Upgrading to {plan} plan...", + "billing_usage_based_pricing": "Usage based pricing", + "billing_usage_coming_soon": "Detailed usage metrics are coming soon.", + "billing_usage_description": "View slot usage, storage consumption, and billing details for your organization.", + "billing_usage_of_quota": "{usage} of {quota} ({percent}%)", + "billing_usage_title": "Usage", + "billing_used_credit": "Used credit", + "billing_view_detailed_usage": "View detailed usage", + "billing_welcome_to_rill": "Welcome to rill.", + "billing_welcome_to_rill_cloud": "Welcome to Rill Cloud", + "billing_x_of_y": "{current} of {total}", + "bookmark_absolute_time_range": "Absolute time range", + "bookmark_absolute_time_tooltip": "The bookmark will use the dashboard's relative time if this toggle is off.", + "bookmark_category": "Category", + "bookmark_category_tooltip": "Your bookmarks can only be viewed by you.\nManaged bookmarks will be available to all viewers of this dashboard.", + "bookmark_created": "Bookmark created", + "bookmark_created_by_admin": "Created by project admin", + "bookmark_current_view": "Bookmark current view", + "bookmark_current_view_as_home": "Bookmark current view as Home.", + "bookmark_default_label": "Default Label", + "bookmark_delete_bookmark": "Delete bookmark", + "bookmark_delete_home_bookmark": "Delete Home bookmark", + "bookmark_deleted": "Bookmark {name} deleted", + "bookmark_description": "Description", + "bookmark_edit": "Edit bookmark", + "bookmark_filters": "Filters", + "bookmark_filters_inherited": "Inherited from underlying dashboard view.", + "bookmark_filters_only_tooltip": "Toggling this on will only save the filter set above, not the full dashboard layout and state.", + "bookmark_go_to_home": "Go to Home", + "bookmark_home_created": "Home bookmark created", + "bookmark_home_description": "This will be everyone's main view for this dashboard.", + "bookmark_label": "Label", + "bookmark_managed_bookmarks": "Managed bookmarks", + "bookmark_no_bookmarks": "You have no bookmarks for this dashboard.", + "bookmark_no_shared": "There are no shared bookmarks for this dashboard.", + "bookmark_return_to_home": "Return to dashboard home", + "bookmark_save": "Save", + "bookmark_save_filters_only": "Save filters only", + "bookmark_updated": "Bookmark updated", + "bookmark_your_bookmarks": "Your bookmarks", + "branch_add_from_cli": "Add a branch from the CLI:", + "branch_author": "Author", + "branch_branch": "Branch", + "branch_branches": "Branches", + "branch_current": "Current", + "branch_delete_failed": "Failed to delete branch: {error}", + "branch_error_loading": "Error loading branches: {error}", + "branch_hibernate": "Hibernate", + "branch_hibernate_failed": "Failed to hibernate branch: {error}", + "branch_last_updated": "Last updated", + "branch_loading": "Loading branches", + "branch_no_branches": "No branches", + "branch_not_editable": "This deployment isn't configured for editing.", + "branch_open_editor": "Open editor", + "branch_production": "Production", + "branch_read_only": "Read-only", + "branch_recreate_with": "To edit this branch, recreate it with", + "branch_resume": "Resume branch", + "branch_resume_failed": "Failed to resume branch: {error}", + "branch_slots": "Slots", + "branch_status_error": "Error", + "branch_status_pending": "Pending", + "branch_status_ready": "Ready", + "branch_status_stopped": "Stopped", + "calendar_apply": "Apply", + "calendar_range_exceeds_limit": "Range exceeds the {capLabel} query limit.", + "canvas_add_widget": "Add widget", + "canvas_ai_generating_chart": "AI is generating chart", + "canvas_ai_hint": "Opens the AI assistant to edit this chart", + "canvas_ai_is_editing": "AI is editing", + "canvas_ai_manual_hint": "Use the inspector panel to write Metrics SQL and Vega-Lite spec manually.", + "canvas_ai_write_manually": "Write SQL & Vega-Lite manually", + "canvas_align_bottom": "Align bottom", + "canvas_align_center": "Align center", + "canvas_align_left": "Align left", + "canvas_align_middle": "Align middle", + "canvas_align_right": "Align right", + "canvas_align_top": "Align top", + "canvas_alignment_label": "Alignment", + "canvas_apply_measure_formatting_label": "Apply measure value formatting", + "canvas_back_to_prompt": "← Back to prompt", + "canvas_blues": "Blues", + "canvas_breakdown_by_label": "Breakdown by", + "canvas_cancel": "Cancel", + "canvas_chart": "Chart", + "canvas_chart_type": "Chart type", + "canvas_cividis": "Cividis", + "canvas_clear_filters": "Clear filters", + "canvas_color_label": "Color", + "canvas_color_mapping": "Color mapping", + "canvas_column_dimensions_label": "Column dimensions", + "canvas_columns_label": "Columns", + "canvas_comparison_values_label": "Comparison values", + "canvas_configuration": "{label} Configuration", + "canvas_configurations": "Canvas configurations", + "canvas_custom_chart": "Custom Chart", + "canvas_data_labels_label": "Data labels", + "canvas_delete": "Delete", + "canvas_delete_widget": "Delete widget?", + "canvas_delete_widget_description": "This widget and its configuration will be permanently removed.", + "canvas_describe_chart_changes": "Describe chart changes...", + "canvas_describe_chart_prompt": "Describe the chart you want to see...", + "canvas_description_label": "Description", + "canvas_description_placeholder": "Add additional context for this component", + "canvas_dimension_label": "Dimension", + "canvas_dimensions_label": "Dimensions", + "canvas_display_name": "Display name", + "canvas_diverging_theme": "Diverging (Theme)", + "canvas_edit": "Edit", + "canvas_edit_with_ai": "Edit with AI", + "canvas_end_color": "End color", + "canvas_enter_a_number": "Enter a number", + "canvas_evenly_distribute": "Evenly distribute widgets", + "canvas_filter_bar": "Filter bar", + "canvas_filters": "Filters", + "canvas_format": "Format", + "canvas_generate": "Generate", + "canvas_gradient": "Gradient", + "canvas_greens": "Greens", + "canvas_greys": "Greys", + "canvas_hide_labels_below": "Hide labels below (%)", + "canvas_hide_total_column_label": "Hide total column", + "canvas_hide_total_row_label": "Hide total row", + "canvas_image": "Image", + "canvas_inferno": "Inferno", + "canvas_inner_radius_label": "Inner Radius (%)", + "canvas_insert_widget": "Insert widget", + "canvas_insert_widget_at": "Insert widget in row {row} at column {col}", + "canvas_insert_widget_at_col": "Insert widget at column {col}", + "canvas_insert_widget_at_row": "Insert widget in row {row}", + "canvas_kpi": "KPI", + "canvas_label_angle": "Label angle", + "canvas_leaderboard": "Leaderboard", + "canvas_left_y_axis_label": "Left Y-Axis", + "canvas_legend_bottom": "Bottom", + "canvas_legend_left": "Left", + "canvas_legend_none": "None", + "canvas_legend_orientation": "Legend orientation", + "canvas_legend_right": "Right", + "canvas_legend_top": "Top", + "canvas_limit": "Limit", + "canvas_local_filters": "Local filters", + "canvas_local_time_range": "Local time range", + "canvas_magma": "Magma", + "canvas_mark_type": "Mark type", + "canvas_markdown_label": "Markdown", + "canvas_max": "Max", + "canvas_max_width": "Max width", + "canvas_measure_label": "Measure", + "canvas_measures_label": "Measures", + "canvas_metrics_sql_label": "Metrics SQL", + "canvas_metrics_view_description": "This will determine the measures and dimensions you can explore on this dashboard.", + "canvas_metrics_view_label": "Metrics view", + "canvas_min": "Min", + "canvas_mode_label": "Mode", + "canvas_name_option": "Name", + "canvas_no_color_values_found": "No color values found", + "canvas_no_components_added": "No components added", + "canvas_no_filters_selected": "No filters selected", + "canvas_no_valid_component": "No valid component {id} in project", + "canvas_no_valid_metrics_view": "No valid metrics view in project", + "canvas_not_found": "Canvas not found", + "canvas_number_of_rows_label": "Number of rows", + "canvas_oranges": "Oranges", + "canvas_order_option": "Order", + "canvas_percent_of_label": "Percent of", + "canvas_plasma": "Plasma", + "canvas_previous_option": "Previous", + "canvas_purples": "Purples", + "canvas_reds": "Reds", + "canvas_remove_query_aria": "Remove query {idx}", + "canvas_reset_to_default": "Reset to default", + "canvas_resize_aria": "Resize row {row} column {col}", + "canvas_right_y_axis_label": "Right Y-Axis", + "canvas_row_dimensions_label": "Row dimensions", + "canvas_save_as_default": "Save as default", + "canvas_saved_default_filters": "Saved default filters", + "canvas_saving_default_filters": "Saving default filters", + "canvas_scheme": "Scheme", + "canvas_see_less": "See less", + "canvas_see_more_value": "See 1 more value", + "canvas_see_more_values": "See {count} more values", + "canvas_select_metrics_view": "Select a metrics view", + "canvas_sequential_theme": "Sequential (Theme)", + "canvas_show_axis_title": "Show axis title", + "canvas_show_description_as_tooltip_label": "Show description as tooltip", + "canvas_show_null_values": "Show null values", + "canvas_show_other_bucket_label": "Show \"Other\" bucket", + "canvas_show_totals_value": "Show totals value", + "canvas_size_label": "Size", + "canvas_sort": "Sort", + "canvas_sparkline_below": "Show sparkline below the value", + "canvas_sparkline_label": "Sparkline", + "canvas_sparkline_right": "Show sparkline to the right of the value", + "canvas_spectral": "Spectral", + "canvas_stage_label": "Stage", + "canvas_start_color": "Start color", + "canvas_switch_mark_type_aria": "Switch to {mark} editor", + "canvas_table": "Table", + "canvas_table_type": "Table type", + "canvas_teal_blues": "Teal blues", + "canvas_teals": "Teals", + "canvas_text_markdown": "Text/Markdown", + "canvas_time_range_display_label": "Time range display", + "canvas_time_ranges": "Time ranges", + "canvas_time_zones": "Time zones", + "canvas_title_label": "Title", + "canvas_title_placeholder": "Add a title to describe this component", + "canvas_tooltip_label": "Tooltip", + "canvas_top_option": "Top", + "canvas_turbo": "Turbo", + "canvas_unknown_error": "An unknown error occurred.", + "canvas_url_label": "URL", + "canvas_value_option": "Value", + "canvas_vega_lite_spec_label": "Vega Lite Spec", + "canvas_viewing_default_state": "Viewing default state", + "canvas_viridis": "Viridis", + "canvas_which_metrics_view": "Which metrics view should this dashboard reference?", + "canvas_width_option": "Width", + "canvas_x_axis_label": "X-axis", + "canvas_y_axis_label": "Y-axis", + "canvas_zero_based_origin": "Zero based origin", + "chart_adaptive": "Adaptive", + "chart_adaptive_tooltip": "Adaptive: Line chart by default. Switches to bar when there are few data points, and stacked bar when comparing dimension", + "chart_add_comparison_to_use": "Add comparison values to use {chartType} chart", + "chart_bar": "Bar", + "chart_copy_to_clipboard": "Copy", + "chart_line": "Line", + "chart_stacked_area": "Stacked area", + "chart_stacked_bar": "Stacked bar", + "chart_undo_zoom": "Undo zoom", + "chart_undo_zoom_label": "Undo Zoom", + "chart_vs": "vs", + "chart_zoom": "Zoom", + "chart_zoom_label": "Zoom", + "chat_ai_disclaimer": "AI can make mistakes. Consider your dashboard the source of truth.", + "chat_cancel_streaming": "Cancel streaming", + "chat_close": "Close chat", + "chat_connect_client": "Connect your own client", + "chat_conversation_history": "Conversation history", + "chat_downvote_aria": "Downvote response", + "chat_downvote_tooltip": "This response needs improvement", + "chat_duration_less_than_second": "less than a second", + "chat_duration_minutes": "{count} minutes", + "chat_duration_one_minute": "1 minute", + "chat_duration_one_second": "1 second", + "chat_duration_seconds": "{count} seconds", + "chat_empty_label": "Happy to help explore your data", + "chat_failed_to_generate": "Failed to generate response", + "chat_feedback_analyzing": "Analyzing feedback...", + "chat_feedback_comments": "Comments", + "chat_feedback_placeholder": "Type here...", + "chat_feedback_select_all": "Select all that apply.", + "chat_feedback_skip": "Skip", + "chat_feedback_submit": "Submit", + "chat_feedback_title": "Give feedback", + "chat_group_days_ago": "{days}d ago", + "chat_group_older": "Older", + "chat_group_today": "Today", + "chat_group_yesterday": "Yesterday", + "chat_happy_to_explore": "Happy to help explore your data", + "chat_how_can_i_help": "How can I help you today?", + "chat_new_conversation": "New conversation", + "chat_no_conversations": "No conversations yet.", + "chat_placeholder_analyst": "Type a question, or press @ to insert a metric, dimension, or measure.", + "chat_send_message": "Send message", + "chat_share_conversation": "Share conversation", + "chat_share_copied": "Copied!", + "chat_share_create_link": "Create link", + "chat_share_creating": "Creating link...", + "chat_share_description": "Share this conversation with other project members. They can view and continue the conversation.", + "chat_share_start_first": "Start a conversation to share", + "chat_show_details": "Show details", + "chat_thinking": "Thinking", + "chat_thought_for": "Thought for {duration}", + "chat_unable_to_load": "Unable to load conversation", + "chat_upvote_aria": "Upvote response", + "chat_upvote_tooltip": "This response was helpful", + "common_all": "All", + "common_allow_domain_access": "Allow domain access", + "common_allow_domain_join_project": "Allow existing and new Rill users with a {domain} email address to join this project as a {role}.", + "common_apply": "Apply", + "common_back": "Back", + "common_cancel": "Cancel", + "common_close_search": "Close search", + "common_contact_us": "Contact us", + "common_continue": "Continue", + "common_delete": "Delete", + "common_got_it": "Got it", + "common_learn_more": "Learn more", + "common_loading": "Loading...", + "common_must_be_number": "Value must be a valid number", + "common_name": "Name", + "common_no_results_found": "No results found.", + "common_preview": "Preview", + "common_required": "Required", + "common_search": "Search", + "common_search_list": "Search list", + "common_status": "Status", + "common_type": "Type", + "common_undo": "Undo", + "dashboard_add_all_dims_rows": "Add all dimensions in {name} to rows", + "dashboard_add_all_to_columns": "Add all to columns", + "dashboard_add_all_to_columns_tag": "Add all in {name} to columns", + "dashboard_add_all_to_rows": "Add all to rows", + "dashboard_add_column": "Add Column", + "dashboard_add_filter": "Add filter", + "dashboard_add_filter_button": "Add filter button", + "dashboard_add_filter_button_aria": "Add filter button", + "dashboard_add_mock_user": "Add mock user", + "dashboard_add_row": "Add Row", + "dashboard_add_to_columns": "Add to columns", + "dashboard_add_to_rows": "Add to rows", + "dashboard_added_items_filter": "Added {count} items to filter", + "dashboard_all": "All", + "dashboard_all_measures": "All measures", + "dashboard_always_show_as": "Always show as", + "dashboard_anchor_period_end": "Anchor to period end", + "dashboard_as_of": "as of", + "dashboard_as_of_ref": "as of", + "dashboard_auto_arrange": "Auto-arrange", + "dashboard_auto_arrange_tag": "Auto-arrange {name}: dimensions to rows, measures to columns", + "dashboard_cancel": "Cancel", + "dashboard_change_over_comparison": "Change over comparison period", + "dashboard_clear": "Clear", + "dashboard_clear_filters": "Clear filters", + "dashboard_clear_recents": "Clear recents", + "dashboard_clear_view": "Clear view", + "dashboard_click_to_edit_values": "Click to edit the values", + "dashboard_cmd_click_replace": "⌘ + Click to replace", + "dashboard_collapse_all": "Collapse All", + "dashboard_columns": "Columns", + "dashboard_comparison_column_aria": "Comparison column", + "dashboard_comparison_select_tooltip": "Select a comparison for the dashboard", + "dashboard_complete_data": "complete data", + "dashboard_complete_data_description": "Timestamp prior to which data frames are considered complete, also known as the watermark", + "dashboard_connect_sparse_data": "Connect sparse data", + "dashboard_contains": "Contains", + "dashboard_copied_error_clipboard": "Copied error to clipboard", + "dashboard_copy_error": "Copy full error message", + "dashboard_copy_error_clipboard": "Copy error to clipboard", + "dashboard_copy_error_to_clipboard_aria": "Copy error message to clipboard", + "dashboard_create_a_dashboard": "Create a dashboard", + "dashboard_current_time": "current time", + "dashboard_current_time_description": "Server clock in selected timezone", + "dashboard_currently_flat": "Currently showing flat view", + "dashboard_currently_pivot": "Currently showing pivot view", + "dashboard_custom": "Custom", + "dashboard_deselect_all": "Deselect all", + "dashboard_deselect_all_selections": "Deselect all selections", + "dashboard_dimension_display_aria": "Dimension Display", + "dashboard_dimension_search_results_aria": "Dimension search results", + "dashboard_dimension_table_aria": "Dimension table", + "dashboard_dimensions": "Dimensions", + "dashboard_dimensions_count": "{count} dimensions", + "dashboard_dimensions_label": "DIMENSIONS", + "dashboard_download_png": "Download PNG", + "dashboard_drag_dimensions": "Drag dimensions here", + "dashboard_drag_dimensions_or_measures": "Drag dimensions or measures here", + "dashboard_drag_list_zone": "Drag list {zone}", + "dashboard_dynamic_y_axis": "Dynamic Y-axis scale", + "dashboard_empty_state": "You don't have any dashboards yet", + "dashboard_end": "end", + "dashboard_error_occurred": "An error occurred", + "dashboard_error_occurred_hover": "An error occurred. Hover for details.", + "dashboard_error_tag": "Error", + "dashboard_errored_contact_admin": "Contact your project's admin for help.", + "dashboard_errored_need_help": "Need help? Reach out to us on {link}", + "dashboard_errored_title": "Sorry, your dashboard isn't working right now!", + "dashboard_errored_view_project": "View project", + "dashboard_errored_view_status": "View project status for errors that may help you find a fix.", + "dashboard_errored_view_status_button": "View project status", + "dashboard_exclude": "Exclude", + "dashboard_explore": "Explore", + "dashboard_export_chart": "Export chart", + "dashboard_export_dimension_table_data": "Export dimension table data", + "dashboard_export_model_data": "Export model data", + "dashboard_export_pivot_data": "Export pivot data", + "dashboard_export_table_data": "Export table data", + "dashboard_filter_by_value": "Filter by this value", + "dashboard_filter_dimension_value": "Filter dimension value", + "dashboard_filter_required_set_value": "This filter is required. Set a value to load the dashboard.", + "dashboard_flat": "Flat", + "dashboard_generated": "Generated {time}", + "dashboard_generating": "Generating…", + "dashboard_grain": "Grain", + "dashboard_hide_panels": "Hide panels", + "dashboard_in_list": "In list", + "dashboard_include_exclude_toggle": "Include exclude toggle", + "dashboard_invalid_time_range": "Invalid time range", + "dashboard_last_refreshed_ago": "Last refreshed {time}", + "dashboard_latest_data": "latest data", + "dashboard_latest_data_description": "Timestamp of latest data point", + "dashboard_leaderboards_aria": "Leaderboards", + "dashboard_list_create": "Create a dashboard", + "dashboard_list_create_to_start": "{link} to get started", + "dashboard_list_empty": "You don't have any dashboards yet", + "dashboard_list_see_all": "See all dashboards", + "dashboard_measure_chart_aria": "Measure Chart for {name}", + "dashboard_measures": "Measures", + "dashboard_measures_count": "{count} measures", + "dashboard_measures_label": "MEASURES", + "dashboard_menu_all_dimensions": "All Dimensions", + "dashboard_no_additional_details": "No additional details available.", + "dashboard_no_available_fields": "No available fields", + "dashboard_no_comparison_dimension": "No comparison dimension selected", + "dashboard_no_dashboards_found": "No dashboards found", + "dashboard_no_filters_selected": "No filters selected", + "dashboard_no_matching_tags": "No matching tags", + "dashboard_no_mock_users": "No mock users", + "dashboard_no_options_found": "No options found", + "dashboard_no_search_results": "No search results to show", + "dashboard_no_timezones_configured": "No timezones configured", + "dashboard_no_valid_grains": "No valid grains available.", + "dashboard_of": "of", + "dashboard_open_dimension_details_aria": "Open dimension details", + "dashboard_other": "other", + "dashboard_others": "others", + "dashboard_output_excludes": "Output excludes selected values", + "dashboard_output_includes": "Output includes selected values", + "dashboard_percent_of_total": "Percent of total", + "dashboard_percentage_change": "Percentage change over comparison period", + "dashboard_pivot": "Pivot", + "dashboard_pivot_add_measure": "Add a measure to complete your table.", + "dashboard_pivot_building_table": "Hang tight! We're building your table...", + "dashboard_pivot_give_data": "Give it some data to keep it company.", + "dashboard_pivot_keep_it_up": "Keep it up!", + "dashboard_pivot_learn_more": "Learn more about tables in our", + "dashboard_pivot_need_help_discord": "Need help? Reach out to us on", + "dashboard_pivot_no_data": "No data to show for the selected filters.", + "dashboard_pivot_table_lonely": "Your table looks lonely", + "dashboard_readonly_filter_chips_aria": "Readonly Filter Chips", + "dashboard_recent": "Recent", + "dashboard_reference": "Reference", + "dashboard_remove_label": "Remove {label}", + "dashboard_removed_items_filter": "Removed {count} items from filter", + "dashboard_replace": "Replace", + "dashboard_replace_auto_arrange": "Replace rows and columns with auto-arranged {name}", + "dashboard_replace_columns_tag": "Replace columns with items in {name}", + "dashboard_replace_columns_tag_items": "Replace columns with this tag's items", + "dashboard_replace_pivot_description": "Starting a new table will lose your previous work. Bookmark tables you want to keep", + "dashboard_replace_pivot_title": "Replace current pivot table?", + "dashboard_replace_rows_cols_tag": "Replace rows and columns with this tag", + "dashboard_replace_rows_tag": "Replace rows with dimensions in {name}", + "dashboard_replace_rows_tag_dims": "Replace rows with this tag's dimensions", + "dashboard_required_measure": "required measure", + "dashboard_row_limit": "Row limit", + "dashboard_row_limit_tooltip": "Only up to top N child rows are shown under each dimension", + "dashboard_rows": "Rows", + "dashboard_search_dimension": "Search Dimension", + "dashboard_search_dimensions": "Search dimensions", + "dashboard_search_results": "Search Results", + "dashboard_see_all": "See all dashboards →", + "dashboard_see_more": "See more", + "dashboard_select_aggregation_grain_aria": "Select aggregation grain", + "dashboard_select_all": "Select all", + "dashboard_select_comparison_dimension": "Select a comparison dimension", + "dashboard_select_comparison_hint": "To see more values, select a comparison dimension above.", + "dashboard_select_ref_time_grain": "Select reference time and grain", + "dashboard_select_time_axis": "Select time axis", + "dashboard_select_time_comparison_aria": "Select time comparison option", + "dashboard_select_time_dimension": "Select {label} time dimension", + "dashboard_select_time_grain": "Select a time grain", + "dashboard_select_time_range": "Select time range", + "dashboard_select_time_range_aria": "Select time range", + "dashboard_selected": "selected", + "dashboard_show_panels": "Show panels", + "dashboard_sort_by_absolute_change_aria": "Toggle sort leaderboards by absolute change", + "dashboard_sort_by_percent_change_aria": "Toggle sort leaderboards by percent change", + "dashboard_sort_by_percent_total_aria": "Toggle sort leaderboards by percent of total", + "dashboard_sort_by_value_aria": "Toggle sort leaderboards by value", + "dashboard_start": "start", + "dashboard_start_pivot": "Start Pivot", + "dashboard_switch_flat": "Switch to flat view", + "dashboard_switch_pivot": "Switch to pivot view", + "dashboard_table_mode": "Table mode", + "dashboard_tags": "Tags", + "dashboard_tdd_contact_discord": "If the issue persists, please contact us on", + "dashboard_tdd_error": "We encountered an error while loading the data. Please try refreshing the page.", + "dashboard_tdd_no_comparison": "No Comparison", + "dashboard_tdd_time": "Time", + "dashboard_time": "Time", + "dashboard_time_axis": "Time axis", + "dashboard_time_label": "TIME", + "dashboard_time_zone": "Time zone", + "dashboard_timezone_selector": "Timezone selector", + "dashboard_to": "to", + "dashboard_to_get_started": "to get started", + "dashboard_toggle_exclude": "Toggle to exclude values", + "dashboard_toggle_include": "Toggle to include values", + "dashboard_toggle_rows_viewer_aria": "Toggle rows viewer", + "dashboard_toggle_time_comparison_aria": "Toggle time comparison", + "dashboard_total_column": "Total column", + "dashboard_total_row": "Total row", + "dashboard_view_as": "View as", + "dashboard_viewing_as": "Viewing as", + "dialog_close_without_saving_alert_desc": "You haven't saved changes to this alert yet, so closing this window will lose your work.", + "dialog_close_without_saving_cancel": "Keep editing", + "dialog_close_without_saving_confirm": "Close", + "dialog_close_without_saving_title": "Close without saving?", + "edit_back_to_projects": "Back to projects", + "edit_branch_name": "Branch name", + "edit_changes_committed_pushed": "Changes committed and pushed", + "edit_describe_changes": "Describe your changes...", + "edit_failed_to_commit": "Failed to commit and push changes", + "edit_failed_to_merge": "Failed to merge", + "edit_failed_to_publish": "Failed to publish", + "edit_failed_to_start": "Failed to start edit session.", + "edit_merging": "Merging...", + "edit_no_changes_detected": "No changes detected", + "edit_popup_blocked": "Pop-up was blocked.", + "edit_provisioning_env": "Provisioning your editing environment...", + "edit_publishing": "Publishing...", + "edit_pushing": "Pushing...", + "edit_return_to_org": "Return to organization", + "edit_return_to_project": "Return to project home", + "edit_starting": "Starting...", + "edit_starting_env": "Starting your editing environment...", + "edit_taking_longer": "This is taking longer than usual.", + "edit_updating_env": "Updating your editing environment...", + "embed_explore_error": "Explore Error", + "embed_explore_not_found": "Explore not found", + "embed_explore_not_found_body": "The Explore dashboard you requested could not be found. Please check that you provided the name of a working dashboard.", + "embed_home": "Home", + "embed_missing_required_params": "Missing required param(s) {params}", + "embed_unsupported_kind": "Embedding for this resource type is currently unavailable.", + "env_add_title": "Add environment variables", + "env_add_variable_button": "Add variable", + "env_cancel_button": "Cancel", + "env_click_to_copy_tooltip": "Click to copy", + "env_copied_tooltip": "Copied!", + "env_create_button": "Create", + "env_delete_action": "Delete", + "env_delete_description": "The environment variable {name} will no longer be available for this project.", + "env_delete_title": "Delete this environment variable?", + "env_development_label": "Development", + "env_development_production_label": "Development, Production", + "env_documentation_link": "documentation", + "env_duplicate_keys_error": "Duplicate keys are not allowed", + "env_edit_action": "Edit", + "env_edit_button": "Edit", + "env_edit_title": "Edit environment variable", + "env_empty_value": "Empty", + "env_environment_label": "Environment", + "env_error_loading": "Error loading environment variables:", + "env_for_help_see": "For help, see", + "env_import_dotenv": "Import .env", + "env_key_duplicated_error": "This key is duplicated", + "env_key_exists_error": "This key already exists for your target environment(s)", + "env_key_placeholder": "Key", + "env_keys_exist_error": "These keys already exist for your target environment(s)", + "env_learn_more": "Learn more ->", + "env_must_select_environment": "You must select at least one environment", + "env_new_key_button": "New key", + "env_no_match_filters": "No environment variables match the selected filters", + "env_no_variables": "No environment variables", + "env_page_description": "Manage your environment variables here.", + "env_page_title": "Environment variables", + "env_production_label": "Production", + "env_some_keys_duplicated_error": "Some keys are duplicated or already exist in target environment(s)", + "env_table_activity_header": "Activity", + "env_table_key_header": "Key", + "env_table_value_header": "Value", + "env_value_placeholder": "Value", + "env_variable_delete_error_notification": "Error deleting environment variable", + "env_variable_deleted_notification": "Environment variable deleted", + "env_variable_label": "Variable", + "env_variable_update_error_notification": "Error updating project variable", + "env_variable_updated_notification": "Environment variable updated", + "env_variables_label": "Variables", + "env_variables_update_error_notification": "Error updating project variables", + "env_variables_updated_notification": "Environment variables updated", + "env_yes_delete_button": "Yes, delete", + "error_access_denied_body": "You don't have access to this page. Please check that you have the correct permissions.", + "error_access_denied_header": "Access denied", + "error_auth_body": "Try refreshing the page. If the problem persists, try signing out and back in.", + "error_auth_header": "Authentication error", + "error_back_to_home": "Back to home", + "error_conversation_not_found_body": "Please check that you have the correct link or if you have access to it.", + "error_conversation_not_found_header": "Conversation not found", + "error_dashboard_not_found": "Dashboard not found", + "error_deploy_dashboards": "Failed to deploy dashboards", + "error_deploying_project": "There was an error deploying your project. Please contact support.", + "error_deployment_error": "Deployment Error", + "error_deployment_not_found_body": "This is potentially a temporary state if the project has just been reset.", + "error_deployment_not_found_header": "Project deployment not found", + "error_fetching_deployment": "Error fetching deployment", + "error_generic_body": "Try refreshing the page, and reach out to us if the problem persists.", + "error_generic_header": "Sorry, something went wrong!", + "error_hide_details": "Hide details", + "error_link_expired_body": "It looks like this link is no longer active. Please reach out to the sender to request a new link.", + "error_link_expired_header": "Oops! This link has expired", + "error_network_body": "It seems we're having trouble reaching our servers. Check your connection or try again later.", + "error_network_header": "Network Error", + "error_occurred": "An error occurred", + "error_org_not_found_body": "The organization you requested could not be found. Please check that you have provided a valid organization name.", + "error_org_not_found_header": "Organization not found", + "error_page_not_found": "Page not found", + "error_page_not_found_body": "The page you're looking for might have been removed, had its name changed, or is temporarily unavailable.", + "error_page_not_found_header": "Sorry, we can't find this page!", + "error_project_not_found_body": "The project you requested could not be found. Please check that you have provided a valid project name.", + "error_project_not_found_header": "Project not found", + "error_resource_not_found_body": "This resource may have been deleted, renamed, or is temporarily unavailable.", + "error_resource_not_found_header": "Resource not found", + "error_retry_now": "Retry now", + "error_show_details": "Show details", + "explore_all_dimensions": "All Dimensions", + "explore_all_measures": "All Measures", + "explore_by_grain_prefix": "by", + "explore_check_yaml_errors": "Please check your dashboard's YAML file for errors.", + "explore_choose_dimensions": "Choose dimensions to display", + "explore_choose_measures": "Choose measures to display", + "explore_clear_filter": "Clear filter", + "explore_clear_filter_tag": "Clear filter {tag}", + "explore_clear_search_to_reorder_dimensions": "Clear search to reorder dimensions.", + "explore_clear_search_to_reorder_measures": "Clear search to reorder measures.", + "explore_clear_tag_filter": "Clear tag filter", + "explore_clear_tag_filter_to_reorder_dimensions": "Clear the tag filter to reorder dimensions.", + "explore_clear_tag_filter_to_reorder_measures": "Clear the tag filter to reorder measures.", + "explore_dashboard_not_found": "Dashboard not found", + "explore_dimensions_count": "{count} of {total} Dimensions", + "explore_error_building": "Error building dashboard", + "explore_error_fetching": "Error fetching dashboard", + "explore_error_parsing": "Error parsing dashboard", + "explore_filter_by_tag": "Filter by {tag}", + "explore_filter_label": "Filter", + "explore_go_to_dashboard": "Go to Explore Dashboard", + "explore_go_to_explore": "Go to Explore", + "explore_go_to_named": "Go to {name}", + "explore_hidden_dimensions": "Hidden dimensions", + "explore_hidden_measures": "Hidden measures", + "explore_hide_all": "Hide all", + "explore_hide_all_in_named_tag": "Hide all in {tag}", + "explore_hide_all_in_tag": "Hide all in tag", + "explore_hide_item": "Hide {name}", + "explore_measures_count": "{count} of {total} Measures", + "explore_multi_select": "Multi-select", + "explore_must_show_one_dimension": "Must show at least one dimension", + "explore_must_show_one_measure": "Must show at least one measure", + "explore_n_measures": "{count} measures", + "explore_no_dimensions_from_tag": "No dimensions from this tag are shown", + "explore_no_dimensions_or_tags": "No dimensions or tags found", + "explore_no_dimensions_shown": "No dimensions shown", + "explore_no_hidden_dimensions": "No hidden dimensions", + "explore_no_hidden_measures": "No hidden measures", + "explore_no_matching_dimensions_shown": "No matching dimensions shown", + "explore_no_matching_hidden_dimensions": "No matching hidden dimensions", + "explore_no_matching_hidden_measures": "No matching hidden measures", + "explore_no_matching_leaderboard_measures": "No matching leaderboard measures shown", + "explore_no_matching_measures_shown": "No matching measures shown", + "explore_no_matching_tags": "No matching tags", + "explore_no_measures": "No measures available", + "explore_no_measures_from_tag": "No measures from this tag are shown", + "explore_no_measures_or_tags": "No measures or tags found", + "explore_no_measures_shown": "No measures shown", + "explore_only_show_tag": "Only show {tag}", + "explore_only_show_this_tag": "Only show this tag", + "explore_search_dimensions": "Search dimensions", + "explore_search_dimensions_or_tags": "Search dimensions or tags", + "explore_search_list": "Search list", + "explore_search_measures": "Search measures", + "explore_search_measures_or_tags": "Search measures or tags", + "explore_security_policy_warning": "The security policy for this dashboard may make contents invisible to you. If you deploy this dashboard, {email} will see a 404.", + "explore_show_all": "Show all", + "explore_show_all_in_named_tag": "Show all in {tag}", + "explore_show_all_in_tag": "Show all in tag", + "explore_show_context_for_all_measures": "Show context for all measures", + "explore_show_item": "Show {name}", + "explore_showing": "Showing", + "explore_shown_dimensions": "Shown dimensions", + "explore_shown_measures": "Shown measures", + "explore_tag_shown_count": "{visible} of {total} shown", + "explore_tags": "Tags", + "explore_unable_to_open": "Unable to open Explore Dashboard", + "explore_unknown_build_error": "An unknown error occurred while building the dashboard.", + "explore_unknown_dimension": "Unknown dimension", + "explore_unknown_measure": "Unknown measure", + "explore_user_no_access": "This user can't access this dashboard", + "field_list_add_fields": "Add {label} fields", + "field_list_aria": "{label} field list", + "field_list_dimensions": "DIMENSIONS", + "field_list_measures": "MEASURES", + "field_list_time": "TIME", + "filter_advanced_beta": "Advanced (BETA)", + "filter_advanced_warning": "Advanced filters are a bleeding edge feature! There may be bugs.", + "filter_dimensions": "DIMENSIONS", + "filter_enter_search_term": "Enter search term", + "filter_make_optional": "Make filter optional", + "filter_make_required": "Make filter required", + "filter_measure_for_dimension": "for {dimension}", + "filter_measure_from_comparison": "from {comparison}", + "filter_measure_op_between": "Between", + "filter_measure_op_does_not_equal": "Does Not Equal", + "filter_measure_op_equals": "Equals", + "filter_measure_op_greater_than": "Greater Than", + "filter_measure_op_greater_than_or_equals": "Greater Than Or Equals", + "filter_measure_op_less_than": "Less Than", + "filter_measure_op_less_than_or_equals": "Less Than Or Equals", + "filter_measure_op_not_between": "Not Between", + "filter_measure_type_change_from": "change from", + "filter_measure_type_percent_change_from": "% change from", + "filter_measure_type_percent_of_total": "% of total", + "filter_measure_type_value": "value", + "filter_measures": "MEASURES", + "filter_mode_contains": "Contains", + "filter_mode_contains_description": "Create a dynamic filter based on a search term", + "filter_mode_in_list": "In List", + "filter_mode_in_list_description": "Create a filter based on a list of values", + "filter_mode_select": "Select", + "filter_mode_select_description": "Manually select values for this filter", + "filter_paste_list_hint": "Paste a list separated by commas or \\n", + "filter_pin": "Pin filter", + "filter_pin_tooltip": "Click to pin or unpin : Keep this filter visible at the top so it can't be removed by other users.", + "filter_required_tooltip": "Click to mark this filter as required. Viewers must set a value for the dashboard to load.", + "filter_unpin": "Unpin filter", + "footer_report_issue": "Report an issue", + "footer_rill_developer": "Rill Developer", + "footer_shortcut_click": "Click", + "footer_unknown_version": "unknown (built from source)", + "footer_version": "version", + "footer_view_documentation": "View documentation", + "form_optional": "(optional)", + "github_access_requested_title": "GitHub access requested", + "github_branch": "branch", + "github_click_to_reauthorize": "Click the button below to re-authorize/authorize another account.", + "github_click_to_retry": "Click the button below to retry.", + "github_close_and_continue_cli": "Close this page and continue setup in the Rill CLI.", + "github_close_page_now": ". You can close this page now.", + "github_connect_other_orgs": "+ Connect other orgs", + "github_connect_other_repos": "+ Connect other repos", + "github_connect_project_description": "Connect this project to GitHub.", + "github_connect_to_github": "Connect to GitHub", + "github_connected_successfully": "GitHub connected successfully", + "github_connection_failed": "Failed to connect to GitHub. Please try again.", + "github_could_not_connect": "Could not connect to GitHub", + "github_create_and_push": "Create and push", + "github_create_repository": "Create repository", + "github_deploy_continuously": "Rill projects deploy continuously when you push changes to GitHub.", + "github_did_not_grant_access": "It looks like you did not grant access to the desired repository at", + "github_error_push_failed": "Unable to complete push. Please check your repo and subpath settings and try again.", + "github_error_repo_exists": "This repo already exists. Please choose a new repo name.", + "github_error_subpath_exists": "The subpath you specified already exists in this repo. Please use a different subpath or remove the existing folder before pushing.", + "github_existing_repository": "Existing repository", + "github_grant_access_to_repo": "Please grant access to your repository", + "github_no_access_to_repo": "Your authorized GitHub account does not have access to the repository.", + "github_organization": "Organization", + "github_overwrite_warning": "Current project contents will be overwritten with the contents of the repository. There is no way to retrieve this current project. Are you sure?", + "github_pull_changes": "Pull changes", + "github_pull_changes_from": "Pull changes from {path}?", + "github_reconnect": "Reconnect", + "github_repository": "Repository", + "github_repository_name": "Repository name", + "github_requested_access": "You requested access to", + "github_select_organization": "Select organization", + "github_select_repository": "Select repository", + "github_subpath": "subpath", + "github_synced": "Synced", + "github_type_to_confirm": "Type {text} in the box below to confirm:", + "github_unlock_bi_as_code": "Unlock the power of BI-as-code with GitHub-backed collaboration, version control, and approval workflows.", + "groups_changes_saved": "User group changes saved successfully", + "groups_create_a_group": "Create a group", + "groups_create_group": "Create group", + "groups_created": "User group created", + "groups_delete": "Delete", + "groups_delete_confirm_desc": "This user group will no longer be able to access the organization.", + "groups_delete_confirm_title": "Delete this user group?", + "groups_deleted": "User group deleted", + "groups_edit": "Edit", + "groups_edit_group": "Edit group", + "groups_error_adding_role": "Error adding role to user group", + "groups_error_deleting": "Error deleting user group", + "groups_error_loading": "Error loading organization user groups:", + "groups_error_revoking_role": "Error revoking user group role", + "groups_error_updating_role": "Error updating user group role", + "groups_removed": "User group removed", + "groups_renamed": "User group renamed", + "groups_role_added": "User group role added", + "groups_role_revoked": "User group role revoked", + "groups_role_updated": "User group role updated", + "groups_table_empty": "No groups found", + "groups_table_header_group": "Group", + "groups_total_count": "{count} total groups", + "groups_yes_delete": "Yes, delete", + "home_dashboards_heading": "Dashboards", + "home_greeting": "Hi {name}!", + "home_subtitle_no_chat": "Explore your dashboards below", + "home_subtitle_with_chat": "Ask questions about your data, or explore your dashboards below", + "home_welcome_getting_started": "It looks like you're just starting out! Check out our {link}.", + "home_welcome_quickstart_link": "Quickstart to create your first project", + "home_welcome_to": "Welcome to {projectName}", + "interval_day": "Day", + "interval_hour": "Hour", + "interval_none": "None", + "interval_week": "Week", + "kpi_no_change": "no change", + "kpi_no_data": "no data", + "kpi_not_available": "n/a", + "kpi_vs_comparison": "vs {comparison}", + "language_en": "English", + "language_es": "Español", + "language_switcher_label": "Language", + "layout_inspector_panel_aria": "Inspector Panel", + "leaderboard_compare": "Compare", + "leaderboard_copy_value": "Copy this value to clipboard", + "leaderboard_expand_table": "(Expand Table)", + "leaderboard_expand_tooltip": "Expand dimension to see more values", + "leaderboard_no_available_values": "(No available values)", + "leaderboard_remove_comparison": "Remove comparison", + "leaderboard_shift_click": "+ Click", + "leaderboard_toggle_breakdown": "Toggle breakdown for {name} dimension", + "mcp_add_to_config": "Add this to your MCP client's configuration file.", + "mcp_add_url": "Add this URL to your AI client's MCP server settings:", + "mcp_configuration": "Configuration", + "mcp_create_token": "Create token", + "mcp_create_token_desc": "Because this project is {privateLabel}, you need a {tokenLabel} to use in your MCP configuration. This token authenticates your requests.", + "mcp_create_token_title": "Create a personal access token", + "mcp_dialog_description": "Ask questions of your Rill project using natural language in any AI client that supports the Model Context Protocol (MCP).", + "mcp_dialog_title": "Connect your own AI client", + "mcp_issuing": "Issuing...", + "mcp_learn_more": "Learn more", + "mcp_manual_tab": "Manual", + "mcp_oauth_auto": "The OAuth flow will start automatically in your browser.", + "mcp_oauth_tab": "OAuth", + "mcp_personal_access_token": "personal access token", + "mcp_private": "private", + "mcp_recommended": "Recommended", + "mcp_token_created": "Token created! Your new token is now included in the configuration snippet below.", + "mcp_token_failed": "Failed to issue token. Please try again.", + "measure_filter_apply": "Apply", + "measure_filter_by_dimension": "By dimension", + "measure_filter_enter_number": "Enter a number", + "measure_filter_higher_value": "Higher value", + "measure_filter_lower_value": "Lower value", + "measure_filter_select_dimension": "Select dimension to split by", + "measure_filter_threshold": "Threshold", + "measures_choose_tooltip": "Choose measures to display", + "measures_label": "Measures", + "nav_close_sidebar": "Close sidebar", + "nav_dashboards": "Dashboards", + "nav_data_explorer": "Data Explorer", + "nav_show_sidebar": "Show sidebar", + "nav_status": "Status", + "nav_tab_ai": "AI", + "nav_tab_alerts": "Alerts", + "nav_tab_dashboards": "Dashboards", + "nav_tab_home": "Home", + "nav_tab_query": "Query", + "nav_tab_reports": "Reports", + "nav_tab_settings": "Settings", + "nav_tab_status": "Status", + "org_check_out_projects": "Check out your projects below.", + "org_new_project": "+ New project", + "org_role_admin_description": "Full access to org settings, members, and all projects", + "org_role_editor_description": "Can create/manage projects and non-admin members", + "org_role_guest_description": "Access to invited projects only", + "org_role_viewer_description": "Read-only access to all org projects", + "org_search_add_remove_users": "Search to add/remove users", + "org_tab_projects": "Projects", + "org_tab_settings": "Settings", + "org_tab_users": "Users", + "pivot_collapse_row": "Collapse row", + "pivot_dim_one": "dim", + "pivot_dim_other": "dims", + "pivot_drop_arrange_aria": "Drop here to auto-arrange tag", + "pivot_drop_replace_aria": "Drop here to replace rows and columns with this tag", + "pivot_drop_replace_text": "Drop to replace: {dimCount} {dimLabel} → rows, {measureCount} {measureLabel} → columns", + "pivot_drop_split_hint": "Drop to replace", + "pivot_drop_split_text": "Drop here to split: {dimCount} {dimLabel} → rows, {measureCount} {measureLabel} → columns", + "pivot_expand_row": "Expand row", + "pivot_measure_one": "measure", + "pivot_measure_other": "measures", + "pivot_tags": "TAGS", + "pivot_time_dimension_header": "Time {grain}", + "pivot_time_prefix": "Time", + "project_branch_hibernated": "Branch hibernated", + "project_branch_is_hibernated": "This branch is hibernated.", + "project_contact_admin_to_redeploy": "Contact the project's administrator to redeploy the project.", + "project_create_first": "Create your first project", + "project_create_new": "Create a new project", + "project_create_project": "Create project", + "project_dashboards_title": "Project dashboards", + "project_delete": "Delete", + "project_deploying": "Deploying your project...", + "project_edit": "Edit", + "project_failed_to_wake": "Failed to wake project: {error}", + "project_hibernating": "Hibernating...", + "project_is_hibernating": "Your project is hibernating", + "project_name_first": "Name your first project", + "project_name_format_error": "Name must start with a letter or number and may only contain letters, numbers, hyphens, and underscores", + "project_name_max_length": "Name must be at most 40 characters", + "project_name_min_length": "Name must be at least 1 character", + "project_name_new": "Name your project", + "project_name_required": "Name is required", + "project_rename": "Rename", + "project_rename_anytime": "You can rename your project anytime.", + "project_resume_branch": "Resume branch", + "project_role_admin": "Admin", + "project_role_guest_description": "Access to invited projects only", + "project_role_viewer": "Viewer", + "project_search_or_invite": "Search or invite by email", + "project_search_users": "Search for users", + "project_share": "Share", + "project_share_failed_to_invite": "Failed to invite.", + "project_share_heading": "Share project: {project}", + "project_share_invalid_email": "Invalid email address", + "project_share_invalid_email_or_group": "Invalid email or group name", + "project_share_role_admin": "Admin", + "project_share_role_admin_description": "Can manage project settings and members", + "project_share_role_editor": "Editor", + "project_share_role_editor_description": "Can edit project resources", + "project_share_role_viewer": "Viewer", + "project_share_role_viewer_description": "Can view dashboards", + "project_share_tooltip": "Share project", + "project_starting": "Starting...", + "project_starting_branch_deployment": "Starting branch deployment...", + "project_this_is_hibernating": "This project is hibernating", + "project_wake": "Wake project", + "project_waking": "Waking...", + "project_waking_up": "Waking up your project...", + "public_url_cancel_button": "Cancel", + "public_url_copied_button": "Copied URL", + "public_url_copied_to_clipboard": "Public URL copied to clipboard", + "public_url_copy_button": "Copy Public URL", + "public_url_copy_url_action": "Copy URL", + "public_url_create_button": "Create", + "public_url_create_heading": "Create a shareable public URL for this view.", + "public_url_delete_action": "Delete", + "public_url_delete_description": "Recipients of this URL will no longer be able to access it.", + "public_url_delete_error_notification": "Error deleting public URL", + "public_url_delete_title": "Delete this public URL?", + "public_url_deleted_notification": "Public URL deleted", + "public_url_edit_expiration": "Edit expiration date", + "public_url_error_loading": "Error loading public URLs", + "public_url_filters_locked_hidden": "The following filters will be locked and hidden:", + "public_url_label_placeholder": "Label this URL", + "public_url_learn_more": "Learn more ->", + "public_url_measures_dimensions_limited": "Measures and dimensions will be limited to current visible set.", + "public_url_no_match_search": "No public URLs match your search", + "public_url_no_urls_description": "To create a public URL that you can share with anyone, click the Share button in a dashboard.", + "public_url_no_urls_empty": "To create a public URL, click the Share button in a dashboard.", + "public_url_no_urls_title": "You don't have any public URLs yet", + "public_url_page_description": "Manage shared public URLs for your dashboards.", + "public_url_page_title": "Public URLs", + "public_url_set_expiration": "Set expiration", + "public_url_success_message": "Success! A public URL has been created.", + "public_url_table_created_by_header": "Created by", + "public_url_table_dashboard_header": "Dashboard", + "public_url_table_dashboard_title_header": "Dashboard title", + "public_url_table_expires_header": "Expires on", + "public_url_table_filters_header": "Filters", + "public_url_table_label_header": "Label", + "public_url_table_last_accessed_header": "Last accessed", + "public_url_title_required": "Title is required", + "public_url_untitled": "Untitled", + "public_url_yes_delete_button": "Yes, delete", + "report_adhoc": "Ad-hoc", + "report_adhoc_tooltip": "This report was run manually off-schedule.", + "report_context_menu_aria": "Report context menu", + "report_created_by": "Created by {name}", + "report_created_through_code": "Report created through code", + "report_dashboard": "Dashboard", + "report_dashboard_not_exist": "Dashboard does not exist", + "report_delete": "Delete report", + "report_download_failed": "Download failed", + "report_download_retry_hint": "If your download fails, refresh the page to try again.", + "report_downloading": "Downloading report...", + "report_edit": "Edit report", + "report_email_recipients": "Email recipients", + "report_email_validation": "At least one email recipient, slack user, or slack channel is required", + "report_form_cancel": "Cancel", + "report_form_channels": "Channels", + "report_form_clear_filters": "Clear filters", + "report_form_columns": "Columns", + "report_form_create": "Create report", + "report_form_create_button": "Create", + "report_form_created_notification": "Report created", + "report_form_day": "Day", + "report_form_day_first": "First day", + "report_form_day_friday": "Friday", + "report_form_day_monday": "Monday", + "report_form_day_saturday": "Saturday", + "report_form_day_sunday": "Sunday", + "report_form_day_thursday": "Thursday", + "report_form_day_tuesday": "Tuesday", + "report_form_day_wednesday": "Wednesday", + "report_form_docs": "docs", + "report_form_edited_notification": "Report edited", + "report_form_email_hint": "Recipients will receive different views based on their security policy.", + "report_form_email_placeholder": "Enter an email address", + "report_form_email_recipients": "Email Recipients", + "report_form_email_recurring": "Email recurring exports to recipients.", + "report_form_filters": "Filters", + "report_form_filters_aria": "Filters form", + "report_form_format": "Format", + "report_form_format_csv": "CSV", + "report_form_format_parquet": "Parquet", + "report_form_format_xlsx": "XLSX", + "report_form_freq_daily": "Daily", + "report_form_freq_monthly": "Monthly", + "report_form_freq_weekdays": "Weekdays", + "report_form_freq_weekly": "Weekly", + "report_form_frequency": "Frequency", + "report_form_go_to_reports": "Go to scheduled reports", + "report_form_include_metadata": "Include metadata", + "report_form_invalid_email": "Invalid email", + "report_form_local_suffix": " (Local)", + "report_form_metadata_tooltip": "Adds a header to the file that includes filters, time range, and other metadata.", + "report_form_no_rows_selected": "No rows selected", + "report_form_recipients_must_be_project": "Recipients must be part of the project when running as recipient", + "report_form_required": "Required", + "report_form_row_limit": "Row limit", + "report_form_row_limit_placeholder": "1000", + "report_form_rows": "Rows", + "report_form_run_as": "Run as", + "report_form_run_as_creator": "Creator", + "report_form_run_as_creator_desc": "Works for any recipient, including external recipient. It does NOT grant access beyond the report's filters and dashboard.", + "report_form_run_as_recipient": "Recipient", + "report_form_run_as_recipient_desc": "Does NOT work for non-project members.", + "report_form_save": "Save report", + "report_form_save_button": "Save", + "report_form_schedule": "Schedule report", + "report_form_slack_channels_hint": "We'll send alerts directly to these channels.", + "report_form_slack_not_configured": "Slack has not been configured for this project. Read the {link} to learn more.", + "report_form_slack_title": "Slack notifications", + "report_form_slack_users": "Users", + "report_form_slack_users_hint": "We'll alert them with direct messages in Slack.", + "report_form_time": "Time", + "report_form_timezone": "Time zone", + "report_form_title_label": "Report title", + "report_form_title_placeholder": "My report", + "report_format_csv": "CSV", + "report_format_parquet": "Parquet", + "report_format_unknown": "Unknown", + "report_format_unspecified": "Unspecified Format", + "report_format_xlsx": "Excel (XLSX)", + "report_go_to_page": "Go to report page", + "report_has_not_run_yet": "This report has not run yet", + "report_hasnt_run_yet": "Hasn't run yet", + "report_last_run": "Last run {time}", + "report_loading": "Loading...", + "report_name_label": "Name", + "report_next_run": "Next run", + "report_no_row_limit": "No row limit", + "report_recent_history": "Recent history", + "report_recipients": "Recipients ({count})", + "report_repeats": "Repeats", + "report_row_limit": "{count} row limit", + "report_run_now": "Run now", + "report_run_now_tooltip": "Run this report immediately. A new report will be generated and emailed to recipients.", + "report_showing_recent_runs": "Showing up to 10 most recent runs", + "report_slack_recipients": "Slack recipients", + "report_status_failed": "Failed", + "report_status_sent": "Report sent", + "report_triggered_adhoc": "Triggered an ad-hoc run of this report.", + "report_unable_to_open": "Unable to open report", + "report_unsubscribe_failed": "Failed to unsubscribe.", + "report_unsubscribed": "Unsubscribed from report.", + "report_unsubscribing": "Unsubscribing...", + "reports_empty_action": "Schedule {reportsLink} from any dashboard", + "reports_empty_message": "You don't have any reports yet", + "reports_link_text": "reports", + "resource_error_contact_support": "If this error persists, please contact support.", + "resource_error_loading": "Error loading {kind}s", + "resource_search_placeholder": "Search", + "resource_type_canvas": "Canvas", + "resource_type_explore": "Explore", + "role_admin": "Admin", + "role_editor": "Editor", + "role_guest": "Guest", + "role_guest_desc": "Access to invited projects only", + "role_org_admin_desc": "Full control over organization settings and members", + "role_org_admin_detail": "Full access to org settings, members, and all projects", + "role_org_editor_desc": "Can manage projects and most org resources", + "role_org_editor_detail": "Can create/manage projects and non-admin members", + "role_org_viewer_desc": "Read-only access to organization and projects", + "role_org_viewer_detail": "Read-only access to all org projects", + "role_project_admin_desc": "Full control of project settings and members", + "role_project_editor_desc": "Can create and edit dashboards; manage non-admin access", + "role_project_viewer_desc": "Read-only access to all project resources", + "role_viewer": "Viewer", + "route_error_dashboard_not_found": "Unable to find a dashboard", + "route_error_fetching_billing_issues": "Error fetching billing issues", + "route_error_fetching_billing_subscription": "Failed to fetch billing subscription", + "route_error_fetching_organization": "Error fetching organization", + "route_error_fetching_project": "Error fetching project", + "route_error_no_org_permission": "You do not have permission to access this organization", + "route_error_token_not_found": "Unable to find token", + "route_error_token_resource_not_found": "Unable to find the token's resource", + "settings_allow_domain_description": "Allow existing and new Rill users with a {domain} email address to join this org as a {role}.", + "settings_allow_domain_title": "Allow domain access", + "settings_branch_callout": "These settings apply to the entire project, not just the {branch} branch.", + "settings_cancel_button": "Cancel", + "settings_danger_zone_title": "Danger Zone", + "settings_dark_logo_label": "Dark Logo", + "settings_delete_button": "Delete", + "settings_delete_org_button": "Delete Organization", + "settings_delete_org_confirm_description": "The organization \"{organization}\" will be permanently deleted along with all its projects, data, and settings. This action cannot be undone.", + "settings_delete_org_confirm_title": "Delete this organization?", + "settings_delete_org_description": "Permanently delete this organization and all of its contents from the Rill platform. This action is not reversible — please continue with caution.", + "settings_delete_org_title": "Delete Organization", + "settings_delete_project_button": "Delete Project", + "settings_delete_project_confirm_description": "The project \"{project}\" will be permanently deleted along with all its dashboards, data, and settings. This action cannot be undone.", + "settings_delete_project_confirm_title": "Delete Project?", + "settings_delete_project_description": "Permanently delete this project and all of its contents from the Rill platform. This action is not reversible — please continue with caution.", + "settings_delete_project_title": "Delete Project", + "settings_deleted_org_notification": "Deleted organization", + "settings_deleted_project_notification": "Deleted project", + "settings_description_label": "Description", + "settings_description_placeholder": "Describe your organization", + "settings_domain_not_allowed_public": "Domain allowlisting is not allowed with a public domain.", + "settings_domains_added_by_admins": "Domains added to allowlist by other admins", + "settings_favicon_description": "Click to upload your favicon and customize Rill for your organization. Upload a square icon to get the best results.", + "settings_favicon_title": "Favicon", + "settings_github_title": "GitHub", + "settings_hibernate_button": "Hibernate", + "settings_hibernate_confirm_description": "The project will be paused and will not consume resources. It can be woken up at any time.", + "settings_hibernate_confirm_title": "Hibernate this project?", + "settings_hibernate_failed_notification": "Failed to hibernate project", + "settings_hibernate_project_button": "Hibernate project", + "settings_hibernate_project_description": "Put this project into hibernation mode. Hibernated projects are paused and do not consume resources. The project can be woken up at any time.", + "settings_hibernate_project_title": "Hibernate Project", + "settings_learn_more": "Learn more", + "settings_light_logo_label": "Light Logo", + "settings_logo_description": "Click to upload your logo and customize Rill for your organization.", + "settings_logo_title": "Logo", + "settings_make_private_button": "Make private", + "settings_make_public_button": "Make public", + "settings_name_already_taken": "The name {name} is already taken", + "settings_name_label": "Name", + "settings_nav_billing": "Billing", + "settings_nav_console": "Console", + "settings_nav_env_vars": "Environment Variables", + "settings_nav_general": "General", + "settings_nav_public_urls": "Public URLs", + "settings_nav_token_mgmt": "Token Management", + "settings_none": "none", + "settings_org_page_title": "Organization settings", + "settings_org_title": "Organization", + "settings_org_url_description": "Your org URL will be https://ui.rilldata.com/{slug}, to comply with our naming rules.", + "settings_project_hibernated_notification": "Project hibernated", + "settings_project_now_private_notification": "Project is now private", + "settings_project_now_public_notification": "Project is now public", + "settings_project_page_title": "Project settings", + "settings_project_title": "Project", + "settings_project_url_description": "Your project will be available at https://ui.rilldata.com/{org}/{slug}.", + "settings_project_visibility_private": "This project is currently Private. Only members of the organization can access this project.", + "settings_project_visibility_public": "This project is currently Public. Anyone with the URL can view this project.", + "settings_project_visibility_title": "Project Visibility", + "settings_remove_button": "Remove", + "settings_rename_button": "Rename", + "settings_rename_project_title": "Rename Project", + "settings_save_button": "Save", + "settings_thumbnail_description": "Click to upload your thumbnail. The thumbnail will be used when sharing links to Rill in applications like Slack.", + "settings_thumbnail_title": "Thumbnail", + "settings_updated_org_notification": "Updated organization", + "settings_updated_project_notification": "Updated project", + "settings_upload_org_image_title": "Upload org {label}", + "settings_usage_coming_soon": "Detailed usage metrics are coming soon.", + "settings_usage_description": "View slot usage, storage consumption, and billing details for your organization.", + "settings_usage_title": "Usage", + "settings_visibility_update_failed": "Failed to update visibility", + "share_limited_view": "Limited view. For full access and features, visit the {link}.", + "share_original_dashboard": "original dashboard", + "snooze_off": "Off", + "status_action_describe": "Describe", + "status_action_full_refresh": "Full Refresh", + "status_action_incremental_refresh": "Incremental Refresh", + "status_action_refresh_errored_partitions": "Refresh Errored Partitions", + "status_action_view_logs": "View Logs", + "status_action_view_partitions": "View Partitions", + "status_all_types": "All Types", + "status_cancel": "Cancel", + "status_checking_errors": "Checking for errors...", + "status_clear": "Clear", + "status_clone_description": "Clone this project to develop locally.", + "status_column_database_size": "Database Size", + "status_column_last_refresh": "Last refresh", + "status_column_model_name": "Model Name", + "status_column_name": "Name", + "status_column_next_refresh": "Next refresh", + "status_column_table_name": "Table Name", + "status_column_type": "Type", + "status_complete": "Complete", + "status_compute_unit": "Compute unit", + "status_compute_units": "Compute units", + "status_connection_failed": "Connection failed: {error}", + "status_copied_error_message": "Copied error message to clipboard", + "status_copied_test_error": "Copied test error to clipboard", + "status_data_accessible": "Data accessible", + "status_data_size": "Data size", + "status_database_size": "Database Size", + "status_deploy_deleted": "Deleted", + "status_deploy_deleting": "Deleting", + "status_deploy_error": "Error", + "status_deploy_not_deployed": "Not deployed", + "status_deploy_pending": "Pending", + "status_deploy_ready": "Ready", + "status_deploy_stopped": "Stopped", + "status_deploy_stopping": "Stopping", + "status_deploy_updating": "Updating", + "status_deployment": "Deployment", + "status_download_project": "Download Project", + "status_error_loading_resources": "Error loading resources", + "status_error_loading_tables": "Error loading tables", + "status_error_plural": "errors", + "status_error_singular": "error", + "status_errors": "Errors", + "status_external_tables_section": "External Tables", + "status_filter_error": "Error", + "status_filter_ok": "OK", + "status_filter_warn": "Warn", + "status_full_refresh": "Full Refresh", + "status_full_refresh_warning": "⚠️ Warning: A full refresh will re-ingest ALL data from scratch. This operation can take a significant amount of time and will update all dependent resources. Only proceed if you're certain this is necessary.", + "status_incremental_refresh": "Incremental Refresh", + "status_incremental_refresh_description": "Refreshing this resource will update all dependent resources.", + "status_label_ai_connector": "AI Connector", + "status_label_branch": "Branch", + "status_label_cluster_size": "Cluster Size", + "status_label_environment": "Environment", + "status_label_last_synced": "Last synced", + "status_label_olap_engine": "OLAP Engine", + "status_label_repo": "Repo", + "status_label_runtime": "Runtime", + "status_label_status": "Status", + "status_learn_about_external_olap": "Learn about connecting external OLAP engines", + "status_learn_more": "Learn more ->", + "status_levels_selected": "{first}, +{count} other(s)", + "status_load_more_tables": "Load more tables", + "status_loading": "Loading...", + "status_loading_models": "Loading models", + "status_loading_resources": "Loading resources...", + "status_loading_tables": "Loading tables...", + "status_loading_tables_short": "Loading tables", + "status_logs_all_levels": "All levels", + "status_logs_connecting": "Connecting", + "status_logs_connection_failed": "Connection failed", + "status_logs_disconnected": "Disconnected", + "status_logs_idle": "Idle", + "status_logs_level_debug": "Debug", + "status_logs_level_error": "Error", + "status_logs_level_info": "Info", + "status_logs_level_warn": "Warn", + "status_logs_live": "Live", + "status_logs_no_match": "No logs match the current filters", + "status_logs_retry": "Retry", + "status_logs_waiting": "Waiting for logs...", + "status_model_name": "Model Name", + "status_model_partitions": "Model Partitions", + "status_model_reconciling": "Model is currently being reconciled", + "status_models_created_in_developer": "Models are created in Rill Developer.", + "status_models_section": "Models", + "status_nav_analytics": "Analytics", + "status_nav_branches": "Branches", + "status_nav_logs": "Logs", + "status_nav_overview": "Overview", + "status_nav_resources": "Resources", + "status_nav_tables": "Tables", + "status_no_errors": "No errors detected.", + "status_no_external_tables": "No external tables", + "status_no_external_tables_match_filters": "No external tables match the current filters", + "status_no_models": "No models", + "status_no_models_match_filters": "No models match the current filters", + "status_no_parse_errors": "No parse errors", + "status_no_resource_data": "No resource data available", + "status_no_resources": "No resources found.", + "status_no_resources_match_filters": "No resources match the current filters", + "status_no_tables": "No tables found.", + "status_note": "Note:", + "status_one_level": "1 level", + "status_owned_by_other": "Owned by another user", + "status_owned_by_you": "Owned by you", + "status_page_title": "Project Status", + "status_parse_error": "Parse error", + "status_parse_errors": "Parse errors", + "status_parse_errors_title": "Parse Errors", + "status_reconciling": "Reconciling", + "status_refresh_all": "Refresh all", + "status_refresh_all_confirm_body": "This will refresh all project sources and models.", + "status_refresh_all_confirm_tip": "To refresh a single resource, scroll to the source or model, click the '...' button, and select the refresh option.", + "status_refresh_all_confirm_title": "Refresh all sources and models?", + "status_refresh_all_sources_models": "Refresh all sources and models", + "status_refresh_errored_confirm_body": "This will re-execute all partitions that failed during their last run. The refresh will happen in the background.", + "status_refresh_errored_confirm_title": "Refresh Errored Partitions for {modelName}?", + "status_refreshing": "Refreshing...", + "status_resource_reconciling": "Resource is currently being reconciled", + "status_rill_managed": "Rill Managed", + "status_table": "Table", + "status_table_name": "Table Name", + "status_table_plural": "Tables", + "status_table_singular": "Table", + "status_tables": "Tables", + "status_unable_to_check_errors": "Unable to check for errors.", + "status_view_all": "View all", + "status_view_plural": "Views", + "status_view_singular": "View", + "status_views": "Views", + "status_yes_refresh": "Yes, refresh", + "theme_beta": "Beta", + "theme_dark": "Dark", + "theme_label": "Theme", + "theme_light": "Light", + "theme_system": "System", + "time_1_day_ago": "1 day ago", + "time_1_hour_ago": "1 hour ago", + "time_1_minute_ago": "1 minute ago", + "time_1_month_ago": "1 month ago", + "time_1_week_ago": "1 week ago", + "time_1_year_ago": "1 year ago", + "time_ago": "{duration} ago", + "time_all_time": "All Time", + "time_comparing": "Comparing", + "time_comparison_previous_day": "Previous day", + "time_comparison_previous_period": "Previous period", + "time_custom": "Custom", + "time_custom_range": "Custom range", + "time_enter_time_range": "Enter a time range", + "time_from_now": "{duration} from now", + "time_grain_by": "by", + "time_grain_complete": "complete", + "time_grain_day": "day", + "time_grain_days": "days", + "time_grain_hour": "hour", + "time_grain_hours": "hours", + "time_grain_minute": "minute", + "time_grain_minutes": "minutes", + "time_grain_month": "month", + "time_grain_months": "months", + "time_grain_quarter": "quarter", + "time_grain_quarters": "quarters", + "time_grain_time": "Time", + "time_grain_week": "week", + "time_grain_weeks": "weeks", + "time_grain_year": "year", + "time_grain_years": "years", + "time_just_now": "Just now", + "time_last_duration": "Last {duration}", + "time_month_to_date": "Month to Date", + "time_n_days_ago": "{count} days ago", + "time_n_hours_ago": "{count} hours ago", + "time_n_minutes_ago": "{count} minutes ago", + "time_n_months_ago": "{count} months ago", + "time_n_weeks_ago": "{count} weeks ago", + "time_n_years_ago": "{count} years ago", + "time_no_comparison_dimension": "No comparison dimension", + "time_no_comparison_period": "no comparison period", + "time_previous_month": "Previous month", + "time_previous_quarter": "Previous quarter", + "time_previous_week": "Previous week", + "time_previous_year": "Previous year", + "time_quarter_to_date": "Quarter to Date", + "time_range_grain_to_date": "{grain} to date", + "time_range_last_n_grains": "last {count} {grains}", + "time_range_next_grain": "next {grain}", + "time_range_next_n_grains": "next {count} {grains}", + "time_range_previous_grain": "previous {grain}", + "time_range_this_grain": "this {grain}", + "time_ref_complete": "complete", + "time_ref_complete_data": "complete data", + "time_ref_current": "current", + "time_ref_earliest": "earliest", + "time_ref_latest": "latest", + "time_ref_now": "now", + "time_relative_hours_short": "{count}h ago", + "time_relative_minutes_short": "{count}m ago", + "time_relative_now": "now", + "time_today": "Today", + "time_unable_to_parse": "Unable to parse time string", + "time_vs": "vs", + "time_week_to_date": "Week to Date", + "time_year_to_date": "Year to Date", + "time_yesterday": "Yesterday", + "users_access_changed_everyone": "Project access changed to everyone", + "users_access_changed_invite_only": "Project access changed to invite-only", + "users_access_level": "Access level", + "users_add_guest": "Add guest", + "users_add_guests_button": "Add guests", + "users_add_guests_description": "Guests can only access provisioned projects with assigned roles. They do not have organization-wide access.", + "users_add_guests_title": "Add guest users", + "users_add_users": "Add users", + "users_added_groups_count": "Added {count} groups", + "users_already_member": "{emails} already a member of this organization", + "users_and_more": "and {count} more", + "users_billing_change_role_desc": "This user is currently the billing contact. To change their role, assign another admin as the billing contact first.", + "users_billing_change_role_title": "Assign a new billing contact first to change this user's role", + "users_billing_remove_desc": "This user is the current billing contact and can't be removed. To proceed, assign another admin as the billing contact.", + "users_billing_remove_title": "Assign a new billing contact first to remove this user", + "users_cancel": "Cancel", + "users_change_billing_contact": "Change billing contact", + "users_convert": "Convert", + "users_convert_to_member": "Convert to member", + "users_convert_user_to_role": "Convert {user} to {role}", + "users_copy_url": "Copy URL", + "users_create": "Create", + "users_email_or_group_placeholder": "Email or group, separated by commas", + "users_email_placeholder": "Add emails, separated by commas", + "users_error": "Error", + "users_error_loading_members": "Error loading organization members:", + "users_error_removing": "Error removing user from organization", + "users_error_removing_user": "Error removing user", + "users_error_updating_role": "Error updating user role", + "users_error_upgrading_role": "Error upgrading user role", + "users_everyone_at_org": "Everyone at {organization}", + "users_failed_add_groups": "Failed to add groups: {groups}", + "users_failed_invite": "Failed to invite {emails}", + "users_failed_invite_users": "Failed to invite users: {emails}", + "users_failed_load_projects": "Failed to load projects", + "users_failed_load_users": "Failed to load users", + "users_filter_admins": "Admins", + "users_filter_all": "All", + "users_filter_all_roles": "All Roles", + "users_filter_all_users": "All users", + "users_filter_editors": "Editors", + "users_filter_members": "Members", + "users_filter_pending_invites": "Pending invites", + "users_filter_viewers": "Viewers", + "users_form_name": "Name", + "users_form_untitled": "Untitled", + "users_form_users": "Users", + "users_general_access": "General Access", + "users_group_count": "{count} Groups", + "users_guest_upgraded": "Guest upgraded to member and assigned {role} role", + "users_guest_upgraded_to": "Guest upgraded to {role}", + "users_guests_invited_success": "Invited {count} guests as {role}", + "users_invalid_email": "Invalid email", + "users_invite": "Invite", + "users_invite_only": "Invite only", + "users_invited_count": "Invited {count} people", + "users_invited_success": "Successfully invited {count} people as {role}", + "users_learn_more_sharing": "Learn more about sharing", + "users_loading": "Loading...", + "users_loading_more": "Loading more...", + "users_member_count": "{count} members", + "users_no_groups": "No groups", + "users_no_projects": "No projects", + "users_no_users": "No users", + "users_only_admins_access": "Only admins and invited users can access", + "users_org_members_access": "Org members can access", + "users_page_title": "Manage users", + "users_pending_invitation": "Pending invitation", + "users_project_access": "Project access", + "users_project_count": "{count} Projects", + "users_projects_count": "{count} Projects", + "users_remove": "Remove", + "users_remove_confirm_desc": "This user will no longer be able to access the organization.", + "users_remove_confirm_title": "Remove user from organization?", + "users_removed": "User removed", + "users_removed_from_org": "User removed from organization", + "users_retry": "Retry", + "users_role_updated": "User role updated", + "users_save": "Save", + "users_searching": "Searching...", + "users_section_groups": "GROUPS", + "users_section_guests": "GUESTS", + "users_section_members": "MEMBERS", + "users_select_projects": "Select projects", + "users_tab_groups": "Groups ({count})", + "users_tab_guests": "Guests ({count})", + "users_tab_members": "Members ({count})", + "users_table_empty": "No users found", + "users_table_header_groups": "Groups", + "users_table_header_org_role": "Organization Role", + "users_table_header_projects": "Projects", + "users_table_header_user": "User", + "users_upgrade_confirm_desc": "Upgrading a guest to {role} will grant this user access to all open projects in the organization. Would you like to upgrade this guest user to {role}?", + "users_upgrade_confirm_title": "Upgrade guest to {role}?", + "users_url_copied": "URL copied", + "users_user_count": "{count} Users", + "users_yes_remove": "Yes, remove", + "users_yes_upgrade": "Yes, upgrade" +} diff --git a/web-common/messages/es.json b/web-common/messages/es.json new file mode 100644 index 000000000000..f15d0ebbf21d --- /dev/null +++ b/web-common/messages/es.json @@ -0,0 +1,1734 @@ +{ + "alert_context_menu_aria": "Menú contextual de alerta", + "alert_create_alert": "Crear alerta", + "alert_created_by": "Creado por {name}", + "alert_created_through_code": "Creado mediante código", + "alert_criteria": "Criterios", + "alert_dashboard": "Dashboard", + "alert_dashboard_not_exist": "El tablero no existe", + "alert_delete": "Eliminar alerta", + "alert_edit": "Editar alerta", + "alert_email_notifications": "Notificaciones por correo", + "alert_filters_label": "Filtros ({count})", + "alert_form_back": "Atrás", + "alert_form_cancel": "Cancelar", + "alert_form_create": "Crear", + "alert_form_create_title": "Crear alerta", + "alert_form_created": "Alerta creada", + "alert_form_criteria_description": "Activar alerta cuando se cumplan estas condiciones", + "alert_form_criteria_group_aria": "Operación del grupo de criterios", + "alert_form_criteria_measure_aria": "Medida del criterio", + "alert_form_criteria_measure_placeholder": "Medida", + "alert_form_criteria_operator_aria": "Operador del criterio", + "alert_form_criteria_operator_placeholder": "Operador", + "alert_form_criteria_preview_title": "Vista previa de la alerta", + "alert_form_criteria_title": "Criterios", + "alert_form_criteria_type_aria": "Tipo de criterio", + "alert_form_criteria_type_placeholder": "tipo", + "alert_form_criteria_value_title": "Valor del criterio", + "alert_form_data_filters": "Filtros", + "alert_form_data_measure": "Medida", + "alert_form_data_measure_placeholder": "Selecciona una medida", + "alert_form_data_measures_desc": "Selecciona las medidas que deseas monitorear.", + "alert_form_data_none": "Ninguno", + "alert_form_data_preview": "Vista previa de datos", + "alert_form_data_preview_desc": "Esta es una vista previa de los datos que seleccionaste arriba.", + "alert_form_data_split_by": "Dividir por dimensión", + "alert_form_data_split_placeholder": "Selecciona una dimensión", + "alert_form_data_title": "Datos de la alerta", + "alert_form_edit_title": "Editar alerta", + "alert_form_edited": "Alerta editada", + "alert_form_email_desc": "Enviaremos alertas por correo a estas direcciones. Asegúrate de que tengan acceso a tu proyecto.", + "alert_form_email_placeholder": "Ingresa una dirección de correo", + "alert_form_email_title": "Notificaciones por correo", + "alert_form_go_to_alerts": "Ir a alertas", + "alert_form_name_placeholder": "Mi alerta", + "alert_form_name_title": "Nombre de la alerta", + "alert_form_next": "Siguiente", + "alert_form_no_criteria": "No hay criterios seleccionados", + "alert_form_no_data": "No hay datos para previsualizar", + "alert_form_preview_cell": "Celda de vista previa", + "alert_form_preview_table_aria": "tabla de vista previa de alerta", + "alert_form_select_criteria": "Selecciona criterios para ver una vista previa", + "alert_form_slack_channels_desc": "Enviaremos alertas directamente a estos canales.", + "alert_form_slack_not_configured": "Slack no ha sido configurado para este proyecto. Lee la documentación para saber más.", + "alert_form_slack_placeholder": "# Ingresa un nombre de canal de Slack", + "alert_form_slack_title": "Notificaciones de Slack", + "alert_form_slack_users_desc": "Les enviaremos mensajes directos en Slack.", + "alert_form_snooze_desc": "Establece un periodo de pausa para silenciar las notificaciones repetidas de la misma alerta.", + "alert_form_snooze_title": "Posponer", + "alert_form_tab_criteria": "Criterios", + "alert_form_tab_data": "Datos", + "alert_form_tab_delivery": "Entrega", + "alert_form_trigger": "Disparador", + "alert_form_trigger_data_refresh": "Cada vez que los datos se actualicen", + "alert_form_trigger_set_schedule": "Establecer horario", + "alert_form_update": "Actualizar", + "alert_go_to_page": "Ir a la página de alertas", + "alert_has_not_run_yet": "Esta alerta aún no se ha ejecutado", + "alert_last_checked": "Última verificación {time}", + "alert_loading": "Cargando...", + "alert_name_label": "Nombre", + "alert_no_filters_body": "No se aplicaron filtros al panel desde el que se creó esta alerta.", + "alert_no_filters_heading": "Sin filtros seleccionados", + "alert_no_filters_hint": "Para aplicar filtros, cierre esta ventana y filtre su panel.", + "alert_none": "Ninguno", + "alert_not_checked_yet": "Aún no se ha verificado", + "alert_recent_history": "Historial reciente", + "alert_schedule": "Programación", + "alert_set_non_custom_time_range": "Para crear una alerta, establece un rango de tiempo no personalizado.", + "alert_showing_recent_checks": "Mostrando hasta las 25 verificaciones más recientes", + "alert_slack_notifications": "Notificaciones de Slack", + "alert_snooze": "Posponer", + "alert_split_by_dimension": "Dividir por dimensión", + "alert_status_checked": "Verificado", + "alert_status_checking": "Verificando", + "alert_status_failed": "Fallida", + "alert_status_not_triggered": "No activada", + "alert_status_running": "Ejecutando", + "alert_status_triggered": "Activada", + "alert_status_unknown": "Estado desconocido", + "alert_unable_to_open": "No se pudo abrir la alerta", + "alert_unsubscribe_failed": "Error al cancelar la suscripción.", + "alert_unsubscribed": "Suscripción a la alerta cancelada.", + "alert_unsubscribing": "Cancelando suscripción...", + "alert_whenever_data_refreshes": "Cada vez que tus datos se actualizan", + "alerts_empty_action": "Crea {alertsLink} desde cualquier dashboard o {codeLink}.", + "alerts_empty_message": "Aún no tienes alertas", + "alerts_link_text": "alertas", + "alerts_via_code": "por código", + "auth_access_requested": "Acceso solicitado", + "auth_allow_domain_access": "Permitir acceso por dominio", + "auth_authenticating_as": "Está autenticando en Rill como {email}.", + "auth_authorize_rill_cli": "Autorizar Rill CLI", + "auth_check_email_to_verify": "Revise su correo electrónico para verificar su cuenta.", + "auth_cli_success_message": "Cierre esta página y continúe en el Rill CLI.", + "auth_cli_success_title": "Rill CLI autorizado exitosamente", + "auth_confirm_code": "Confirmar código", + "auth_confirm_code_displayed": "Confirme que este es el código que aparece en el Rill CLI.", + "auth_continue": "Continuar", + "auth_denying_access": "Denegando acceso de {email} a {project}", + "auth_device_code_confirmation_failed": "Error al confirmar el código de usuario", + "auth_device_code_confirmed": "Código de usuario confirmado, puede cerrar esta página", + "auth_device_code_rejected": "Código de usuario rechazado, puede cerrar esta página", + "auth_device_code_rejection_failed": "Error al rechazar el código de usuario", + "auth_device_meta_description": "Confirmación de código de usuario", + "auth_grant_access": "Conceder acceso", + "auth_grant_access_description": "Seleccione un rol para que {email} acceda al proyecto {project}.", + "auth_grant_access_title": "Conceder acceso a este proyecto", + "auth_invite_by_email": "Invitar por correo electrónico", + "auth_invite_teammates": "Invite a sus compañeros al proyecto", + "auth_log_in_sign_up": "Iniciar sesión / Registrarse", + "auth_request_access": "Solicitar acceso", + "auth_request_access_description": "Podrá ver {project} una vez que su solicitud sea aprobada.", + "auth_request_access_title": "Solicitar acceso a este proyecto", + "auth_request_sent": "Su solicitud ha sido enviada al administrador del proyecto. Recibirá un correo cuando sea aprobada.", + "auth_skip_for_now": "Omitir por ahora", + "auth_thanks_for_signing_up": "¡Gracias por registrarse!", + "auth_user_added_to_project": "{email} ha sido agregado a {project} como {role}", + "auth_user_denied_access": "Se ha denegado el acceso de {email} a {project}", + "avatar_contact_support": "Contactar soporte de Rill", + "avatar_copied_url": "URL copiada", + "avatar_copy_url": "Copiar URL", + "avatar_copy_url_for_view": "Copiar URL de esta vista", + "avatar_create_public_url": "Crear URL pública", + "avatar_documentation": "Documentación", + "avatar_join_discord": "Únete a nosotros en Discord", + "avatar_logout": "Cerrar sesión", + "avatar_share": "Compartir", + "avatar_share_dashboard": "Compartir dashboard", + "avatar_share_description": "Comparte tu vista actual con otro miembro del proyecto.", + "avatar_view_as": "Ver como", + "bignumber_copy_value": "Copiar este valor al portapapeles", + "bignumber_shift_click": "+ Clic", + "billing_30_day_free_trial": "Prueba gratuita de 30 días", + "billing_30_days": "30 días", + "billing_access_until": "pero aún tiene acceso hasta el {date}", + "billing_assign_as_contact": "Asignar como contacto de facturación", + "billing_available_credit": "Crédito disponible", + "billing_billing_address_short": "dirección de facturación", + "billing_cancel": "Cancelar", + "billing_cancel_anytime": "Cancele en cualquier momento.", + "billing_cancel_plan": "Cancelar plan", + "billing_cancel_plan_desc": "Si cancela su plan, aún podrá acceder a su cuenta hasta el {date}.", + "billing_cancel_plan_title": "¿Cancelar su plan {planName}?", + "billing_cancel_subscription": "Cancelar suscripción", + "billing_change_billing_contact": "Cambiar contacto de facturación", + "billing_change_subscription": "Cambiar suscripción", + "billing_choose_a_plan": "Elegir un plan", + "billing_choose_plan_name": "Elegir {planName}", + "billing_choose_plan_to_maintain": "Elija un plan para mantener el acceso.", + "billing_choosing_plan_ends_trial": "Elegir un plan finaliza su prueba e inicia su ciclo de facturación hoy.", + "billing_close": "Cerrar", + "billing_congrats_plan": "Felicitaciones por iniciar su plan {planName}. Para aprovechar al máximo su plan, {docsLink}", + "billing_contact_assigned": "{name} ha sido asignado como contacto de facturación.", + "billing_contact_header": "Contacto de facturación", + "billing_contact_reassign_failed": "No se pudo reasignar el contacto de facturación. Inténtelo de nuevo o contacte al soporte.", + "billing_contact_support": "contactar soporte", + "billing_contact_us_cta": "Contáctenos", + "billing_contact_us_link": "contáctenos", + "billing_contact_us_to_maintain": "Para mantener el acceso, por favor contáctenos.", + "billing_contact_us_to_regain": "Contáctenos para recuperar el acceso.", + "billing_credit_percent_used": "{percent}% usado, los proyectos entrarán en hibernación cuando se agoten los créditos.", + "billing_credits_depleted": "El crédito de prueba se ha agotado. Los proyectos están en hibernación y los dashboards están fuera de línea.", + "billing_current": "Actual", + "billing_cycle_will_resume": "Su ciclo de facturación se reanudará {resumeText}.", + "billing_data_size": "Tamaño de datos", + "billing_days_remaining": "Días restantes", + "billing_days_used": "Días usados", + "billing_dev_compute_units": "{count} unidades de cómputo de desarrollo", + "billing_dialog_title_org": "Para crear otra organización, elija un plan", + "billing_dialog_title_proj": "Para desplegar un segundo proyecto, elija un plan", + "billing_dialog_title_renew": "Renueve su plan", + "billing_dialog_title_size": "Desplegar más de 10 GB requiere un plan de pago", + "billing_dialog_title_trial_expired": "Su prueba ha finalizado — elija un plan", + "billing_enterprise_desc": "Contrato personalizado", + "billing_enterprise_desc_managed": "Contrato personalizado · Totalmente gestionado", + "billing_enterprise_details": "Slots totalmente gestionados, CSM dedicado, capacidades de marca blanca y SLAs personalizados. Contacte a su CSM para detalles o cambios del contrato.", + "billing_error_redirect_payment": "Error al redirigir al portal de pagos", + "billing_fix_payment_issues": "Por favor, soluciona los problemas de pago: {details}", + "billing_free_credit_desc": "$250 de crédito gratis", + "billing_free_trial_info": "prueba gratuita · 30 días, no se requiere tarjeta de crédito. Los proyectos entran en hibernación cuando finaliza la prueba.", + "billing_free_trial_with_credits": "Está en una prueba gratuita con ${amount} en créditos.", + "billing_got_it": "Entendido", + "billing_highlight_1m_ai_tokens": "1M tokens de IA / puesto / mes", + "billing_highlight_2m_ai_tokens": "2M tokens de IA / puesto / mes", + "billing_highlight_bring_own_ai": "Traiga su propio modelo de IA", + "billing_highlight_embedded_analytics": "Analítica embebida", + "billing_input_valid_to_maintain": "Ingrese un {methods} válido para mantener el acceso.", + "billing_input_valid_to_wake": "Ingrese un {methods} válido para reactivar los proyectos y recuperar el acceso completo.", + "billing_invoice_past_due": "Su factura está vencida{suffix}.", + "billing_keep_plan": "Mantener plan", + "billing_manage_cards_via_stripe": "Gestione sus tarjetas a través de Stripe", + "billing_manage_in_stripe": "Gestionar en Stripe", + "billing_no_billing_contact": "Esta organización no tiene contacto de facturación.", + "billing_no_payment_method": "No hay método de pago registrado.", + "billing_no_time_limit": "Sin límite de tiempo, úselo hasta que se agote.", + "billing_no_valid_on_file": "No hay {methods} válido registrado.", + "billing_on_date": "el {date}", + "billing_or": "o", + "billing_payment_method_on_file": "Método de pago registrado", + "billing_payment_method_short": "método de pago", + "billing_payment_methods_header": "Métodos de pago", + "billing_per_day": "día", + "billing_plan_badge_enterprise": "Empresarial", + "billing_plan_badge_free_trial": "Prueba gratuita", + "billing_plan_badge_managed": "Gestionado", + "billing_plan_badge_pro": "Pro", + "billing_plan_badge_pro_trial": "Prueba Pro", + "billing_plan_badge_team": "Equipo", + "billing_plan_cancelled": "Su plan ha sido cancelado {accessTimeout}.", + "billing_plan_header": "Plan", + "billing_plan_name_growth": "Growth", + "billing_plan_name_starter": "Starter", + "billing_plan_price_unit": "/ puesto / mes", + "billing_plan_renewed": "Su plan {planName} ha sido renovado", + "billing_plan_tagline_growth": "Para equipos en crecimiento y analítica embebida.", + "billing_plan_tagline_starter": "Para equipos pequeños que están comenzando.", + "billing_plan_was_cancelled": "Su plan {planName} ha sido cancelado", + "billing_prod_compute_units": "{count} unidades de cómputo de producción", + "billing_projects": "Proyectos", + "billing_projects_hibernating": " y los proyectos de esta organización están en hibernación", + "billing_quota_api_calls": "{value} llamadas API / puesto / mes", + "billing_quota_compute_units": "Hasta {value} unidades de cómputo", + "billing_quota_managed_db": "Base de datos gestionada hasta {value}", + "billing_quota_projects": "Hasta {value} proyectos", + "billing_quota_seats": "Hasta {value} puestos", + "billing_recommended": "Recomendado", + "billing_refer_to_docs": "consulte nuestra documentación", + "billing_renew": "Renovar", + "billing_renew_to_maintain_access": "Para mantener el acceso, renueve su plan.", + "billing_renewing_plan": "Renovando plan {plan}...", + "billing_see_pricing_details": "Ver detalles de precios", + "billing_select_admin_as_contact": "Seleccione otro administrador de la organización como contacto de facturación.", + "billing_subscription_ended": "y su suscripción ha finalizado", + "billing_subscription_past_due": "Su suscripción está vencida{suffix}.", + "billing_team_details": "Plan de tarifa fija. $250/mes incluye hasta 8 slots y 10 GB de almacenamiento, con $25/GB por excedentes.", + "billing_team_info": "$250/mes tarifa fija + excedentes de almacenamiento. 10 GB incluidos · $25/GB adicional. Hasta 8 slots.", + "billing_team_price_desc": "$250/mes fijo + almacenamiento", + "billing_today": "hoy", + "billing_trial_credit_running_low": "Su crédito de prueba se está agotando.", + "billing_trial_expired": "Su prueba ha expirado.", + "billing_trial_expired_hibernated": "Prueba expirada · Proyectos en hibernación", + "billing_trial_expired_hibernating": "Su prueba ha expirado y los proyectos de esta organización están en hibernación.", + "billing_trial_expires_in": "Su prueba expira en {duration}.", + "billing_trial_percent_used": "{percent}% de la prueba usado, los proyectos entrarán en hibernación cuando finalice la prueba", + "billing_unit_spec": "1 unidad = 4GiB RAM, 1vGPU", + "billing_unknown": "Desconocido", + "billing_unlimited": "Ilimitado", + "billing_update_payment": "Actualizar pago", + "billing_update_payment_methods": "Actualizar métodos de pago", + "billing_upgrade_to_pro": "Actualizar a Pro", + "billing_upgrade_to_team": "Actualizar al plan Equipo", + "billing_upgrade_to_wake": "Actualice para reactivar los proyectos y recuperar el acceso completo.", + "billing_upgrade_within_to_maintain": "Actualice dentro de {duration} para mantener el acceso.", + "billing_upgrading_plan": "Actualizando al plan {plan}...", + "billing_usage_based_pricing": "Precios basados en uso", + "billing_usage_coming_soon": "Las métricas detalladas de uso estarán disponibles próximamente.", + "billing_usage_description": "Vea el uso de slots, consumo de almacenamiento y detalles de facturación de su organización.", + "billing_usage_of_quota": "{usage} de {quota} ({percent}%)", + "billing_usage_title": "Uso", + "billing_used_credit": "Crédito usado", + "billing_view_detailed_usage": "Ver uso detallado", + "billing_welcome_to_rill": "Bienvenido a Rill.", + "billing_welcome_to_rill_cloud": "Bienvenido a Rill Cloud", + "billing_x_of_y": "{current} de {total}", + "bookmark_absolute_time_range": "Rango de tiempo absoluto", + "bookmark_absolute_time_tooltip": "El marcador usará el tiempo relativo del dashboard si este interruptor está desactivado.", + "bookmark_category": "Categoría", + "bookmark_category_tooltip": "Tus marcadores solo pueden ser vistos por ti.\nLos marcadores gestionados estarán disponibles para todos los espectadores de este dashboard.", + "bookmark_created": "Marcador creado", + "bookmark_created_by_admin": "Creado por el administrador del proyecto", + "bookmark_current_view": "Guardar vista actual", + "bookmark_current_view_as_home": "Guardar vista actual como Inicio.", + "bookmark_default_label": "Etiqueta predeterminada", + "bookmark_delete_bookmark": "Eliminar marcador", + "bookmark_delete_home_bookmark": "Eliminar marcador de Inicio", + "bookmark_deleted": "Marcador {name} eliminado", + "bookmark_description": "Descripción", + "bookmark_edit": "Editar marcador", + "bookmark_filters": "Filtros", + "bookmark_filters_inherited": "Heredado de la vista del dashboard subyacente.", + "bookmark_filters_only_tooltip": "Activar esto solo guardará el conjunto de filtros anterior, no el diseño y estado completo del dashboard.", + "bookmark_go_to_home": "Ir a Inicio", + "bookmark_home_created": "Marcador de Inicio creado", + "bookmark_home_description": "Esta será la vista principal de todos para este dashboard.", + "bookmark_label": "Etiqueta", + "bookmark_managed_bookmarks": "Marcadores gestionados", + "bookmark_no_bookmarks": "No tienes marcadores para este dashboard.", + "bookmark_no_shared": "No hay marcadores compartidos para este dashboard.", + "bookmark_return_to_home": "Volver al inicio del dashboard", + "bookmark_save": "Guardar", + "bookmark_save_filters_only": "Guardar solo filtros", + "bookmark_updated": "Marcador actualizado", + "bookmark_your_bookmarks": "Tus marcadores", + "branch_add_from_cli": "Agrega una rama desde la CLI:", + "branch_author": "Autor", + "branch_branch": "Rama", + "branch_branches": "Ramas", + "branch_current": "Actual", + "branch_delete_failed": "Error al eliminar la rama: {error}", + "branch_error_loading": "Error al cargar las ramas: {error}", + "branch_hibernate": "Hibernar", + "branch_hibernate_failed": "Error al hibernar la rama: {error}", + "branch_last_updated": "Última actualización", + "branch_loading": "Cargando ramas", + "branch_no_branches": "Sin ramas", + "branch_not_editable": "Este despliegue no está configurado para edición.", + "branch_open_editor": "Abrir editor", + "branch_production": "Producción", + "branch_read_only": "Solo lectura", + "branch_recreate_with": "Para editar esta rama, recréala con", + "branch_resume": "Reanudar rama", + "branch_resume_failed": "Error al reanudar la rama: {error}", + "branch_slots": "Slots", + "branch_status_error": "Error", + "branch_status_pending": "Pendiente", + "branch_status_ready": "Listo", + "branch_status_stopped": "Detenido", + "calendar_apply": "Aplicar", + "calendar_range_exceeds_limit": "El rango excede el límite de consulta de {capLabel}.", + "canvas_add_widget": "Agregar widget", + "canvas_ai_generating_chart": "La IA está generando el gráfico", + "canvas_ai_hint": "Abre el asistente de IA para editar este gráfico", + "canvas_ai_is_editing": "La IA está editando", + "canvas_ai_manual_hint": "Usa el panel del inspector para escribir Metrics SQL y la especificación Vega-Lite manualmente.", + "canvas_ai_write_manually": "Escribir SQL y Vega-Lite manualmente", + "canvas_align_bottom": "Alinear abajo", + "canvas_align_center": "Alinear al centro", + "canvas_align_left": "Alinear a la izquierda", + "canvas_align_middle": "Alinear al medio", + "canvas_align_right": "Alinear a la derecha", + "canvas_align_top": "Alinear arriba", + "canvas_alignment_label": "Alineación", + "canvas_apply_measure_formatting_label": "Aplicar formato de valores de medida", + "canvas_back_to_prompt": "← Volver al prompt", + "canvas_blues": "Azules", + "canvas_breakdown_by_label": "Desglosar por", + "canvas_cancel": "Cancelar", + "canvas_chart": "Gráfico", + "canvas_chart_type": "Tipo de gráfico", + "canvas_cividis": "Cividis", + "canvas_clear_filters": "Limpiar filtros", + "canvas_color_label": "Color", + "canvas_color_mapping": "Mapeo de colores", + "canvas_column_dimensions_label": "Dimensiones de columna", + "canvas_columns_label": "Columnas", + "canvas_comparison_values_label": "Valores de comparación", + "canvas_configuration": "Configuración de {label}", + "canvas_configurations": "Configuraciones del canvas", + "canvas_custom_chart": "Gráfico personalizado", + "canvas_data_labels_label": "Etiquetas de datos", + "canvas_delete": "Eliminar", + "canvas_delete_widget": "¿Eliminar widget?", + "canvas_delete_widget_description": "Este widget y su configuración se eliminarán permanentemente.", + "canvas_describe_chart_changes": "Describe los cambios del gráfico...", + "canvas_describe_chart_prompt": "Describe el gráfico que quieres ver...", + "canvas_description_label": "Descripción", + "canvas_description_placeholder": "Agrega contexto adicional para este componente", + "canvas_dimension_label": "Dimensión", + "canvas_dimensions_label": "Dimensiones", + "canvas_display_name": "Nombre visible", + "canvas_diverging_theme": "Divergente (Tema)", + "canvas_edit": "Editar", + "canvas_edit_with_ai": "Editar con IA", + "canvas_end_color": "Color final", + "canvas_enter_a_number": "Ingresa un número", + "canvas_evenly_distribute": "Distribuir widgets uniformemente", + "canvas_filter_bar": "Barra de filtros", + "canvas_filters": "Filtros", + "canvas_format": "Formato", + "canvas_generate": "Generar", + "canvas_gradient": "Degradado", + "canvas_greens": "Verdes", + "canvas_greys": "Grises", + "canvas_hide_labels_below": "Ocultar etiquetas menores a (%)", + "canvas_hide_total_column_label": "Ocultar columna de totales", + "canvas_hide_total_row_label": "Ocultar fila de totales", + "canvas_image": "Imagen", + "canvas_inferno": "Inferno", + "canvas_inner_radius_label": "Radio interior (%)", + "canvas_insert_widget": "Insertar widget", + "canvas_insert_widget_at": "Insertar widget en fila {row} en columna {col}", + "canvas_insert_widget_at_col": "Insertar widget en columna {col}", + "canvas_insert_widget_at_row": "Insertar widget en fila {row}", + "canvas_kpi": "KPI", + "canvas_label_angle": "Ángulo de etiqueta", + "canvas_leaderboard": "Ranking", + "canvas_left_y_axis_label": "Eje Y izquierdo", + "canvas_legend_bottom": "Abajo", + "canvas_legend_left": "Izquierda", + "canvas_legend_none": "Ninguna", + "canvas_legend_orientation": "Orientación de leyenda", + "canvas_legend_right": "Derecha", + "canvas_legend_top": "Arriba", + "canvas_limit": "Límite", + "canvas_local_filters": "Filtros locales", + "canvas_local_time_range": "Rango de tiempo local", + "canvas_magma": "Magma", + "canvas_mark_type": "Tipo de marca", + "canvas_markdown_label": "Markdown", + "canvas_max": "Máx", + "canvas_max_width": "Ancho máximo", + "canvas_measure_label": "Medida", + "canvas_measures_label": "Medidas", + "canvas_metrics_sql_label": "SQL de métricas", + "canvas_metrics_view_description": "Esto determinará las medidas y dimensiones que puedes explorar en este panel.", + "canvas_metrics_view_label": "Vista de métricas", + "canvas_min": "Mín", + "canvas_mode_label": "Modo", + "canvas_name_option": "Nombre", + "canvas_no_color_values_found": "No se encontraron valores de color", + "canvas_no_components_added": "No se han agregado componentes", + "canvas_no_filters_selected": "Sin filtros seleccionados", + "canvas_no_valid_component": "No se encontró el componente {id} en el proyecto", + "canvas_no_valid_metrics_view": "No hay una vista de métricas válida en el proyecto", + "canvas_not_found": "Canvas no encontrado", + "canvas_number_of_rows_label": "Número de filas", + "canvas_oranges": "Naranjas", + "canvas_order_option": "Orden", + "canvas_percent_of_label": "Porcentaje de", + "canvas_plasma": "Plasma", + "canvas_previous_option": "Anterior", + "canvas_purples": "Púrpuras", + "canvas_reds": "Rojos", + "canvas_remove_query_aria": "Eliminar consulta {idx}", + "canvas_reset_to_default": "Restablecer valores predeterminados", + "canvas_resize_aria": "Redimensionar fila {row} columna {col}", + "canvas_right_y_axis_label": "Eje Y derecho", + "canvas_row_dimensions_label": "Dimensiones de fila", + "canvas_save_as_default": "Guardar como predeterminado", + "canvas_saved_default_filters": "Filtros predeterminados guardados", + "canvas_saving_default_filters": "Guardando filtros predeterminados", + "canvas_scheme": "Esquema", + "canvas_see_less": "Ver menos", + "canvas_see_more_value": "Ver 1 valor más", + "canvas_see_more_values": "Ver {count} valores más", + "canvas_select_metrics_view": "Seleccionar una vista de métricas", + "canvas_sequential_theme": "Secuencial (Tema)", + "canvas_show_axis_title": "Mostrar título del eje", + "canvas_show_description_as_tooltip_label": "Mostrar descripción como tooltip", + "canvas_show_null_values": "Mostrar valores nulos", + "canvas_show_other_bucket_label": "Mostrar grupo \"Otros\"", + "canvas_show_totals_value": "Mostrar valor total", + "canvas_size_label": "Tamaño", + "canvas_sort": "Ordenar", + "canvas_sparkline_below": "Mostrar minigráfico debajo del valor", + "canvas_sparkline_label": "Sparkline", + "canvas_sparkline_right": "Mostrar minigráfico a la derecha del valor", + "canvas_spectral": "Espectral", + "canvas_stage_label": "Etapa", + "canvas_start_color": "Color inicial", + "canvas_switch_mark_type_aria": "Cambiar al editor de {mark}", + "canvas_table": "Tabla", + "canvas_table_type": "Tipo de tabla", + "canvas_teal_blues": "Azules verdosos", + "canvas_teals": "Verdeazulados", + "canvas_text_markdown": "Texto/Markdown", + "canvas_time_range_display_label": "Visualización de rango temporal", + "canvas_time_ranges": "Rangos de tiempo", + "canvas_time_zones": "Zonas horarias", + "canvas_title_label": "Título", + "canvas_title_placeholder": "Agrega un título para describir este componente", + "canvas_tooltip_label": "Tooltip", + "canvas_top_option": "Superior", + "canvas_turbo": "Turbo", + "canvas_unknown_error": "Ocurrió un error desconocido.", + "canvas_url_label": "URL", + "canvas_value_option": "Valor", + "canvas_vega_lite_spec_label": "Especificación Vega Lite", + "canvas_viewing_default_state": "Viendo estado predeterminado", + "canvas_viridis": "Viridis", + "canvas_which_metrics_view": "¿Qué vista de métricas debe referenciar este panel?", + "canvas_width_option": "Ancho", + "canvas_x_axis_label": "Eje X", + "canvas_y_axis_label": "Eje Y", + "canvas_zero_based_origin": "Origen en cero", + "chart_adaptive": "Adaptativo", + "chart_adaptive_tooltip": "Adaptativo: Gráfico de línea por defecto. Cambia a barras con pocos datos, y barras apiladas al comparar dimensiones", + "chart_add_comparison_to_use": "Agrega valores de comparación para usar gráfico de {chartType}", + "chart_bar": "Barras", + "chart_copy_to_clipboard": "Copiar", + "chart_line": "Línea", + "chart_stacked_area": "Área apilada", + "chart_stacked_bar": "Barras apiladas", + "chart_undo_zoom": "Deshacer zoom", + "chart_undo_zoom_label": "Deshacer zoom", + "chart_vs": "vs", + "chart_zoom": "Zoom", + "chart_zoom_label": "Zoom", + "chat_ai_disclaimer": "La IA puede cometer errores. Considere su panel de control como la fuente de verdad.", + "chat_cancel_streaming": "Cancelar transmisión", + "chat_close": "Cerrar chat", + "chat_connect_client": "Conecta tu propio cliente", + "chat_conversation_history": "Historial de conversaciones", + "chat_downvote_aria": "Valorar negativamente", + "chat_downvote_tooltip": "Esta respuesta necesita mejora", + "chat_duration_less_than_second": "menos de un segundo", + "chat_duration_minutes": "{count} minutos", + "chat_duration_one_minute": "1 minuto", + "chat_duration_one_second": "1 segundo", + "chat_duration_seconds": "{count} segundos", + "chat_empty_label": "Encantado de ayudarte a explorar tus datos", + "chat_failed_to_generate": "No se pudo generar la respuesta", + "chat_feedback_analyzing": "Analizando retroalimentación...", + "chat_feedback_comments": "Comentarios", + "chat_feedback_placeholder": "Escribe aquí...", + "chat_feedback_select_all": "Selecciona todo lo que aplique.", + "chat_feedback_skip": "Omitir", + "chat_feedback_submit": "Enviar", + "chat_feedback_title": "Dar retroalimentación", + "chat_group_days_ago": "Hace {days}d", + "chat_group_older": "Anteriores", + "chat_group_today": "Hoy", + "chat_group_yesterday": "Ayer", + "chat_happy_to_explore": "Encantado de ayudarte a explorar tus datos", + "chat_how_can_i_help": "¿Cómo puedo ayudarte hoy?", + "chat_new_conversation": "Nueva conversación", + "chat_no_conversations": "Aún no hay conversaciones.", + "chat_placeholder_analyst": "Escribe una pregunta, o presiona @ para insertar una métrica, dimensión o medida.", + "chat_send_message": "Enviar mensaje", + "chat_share_conversation": "Compartir conversación", + "chat_share_copied": "¡Copiado!", + "chat_share_create_link": "Crear enlace", + "chat_share_creating": "Creando enlace...", + "chat_share_description": "Comparte esta conversación con otros miembros del proyecto. Pueden ver y continuar la conversación.", + "chat_share_start_first": "Inicia una conversación para compartir", + "chat_show_details": "Mostrar detalles", + "chat_thinking": "Pensando", + "chat_thought_for": "Pensó durante {duration}", + "chat_unable_to_load": "No se pudo cargar la conversación", + "chat_upvote_aria": "Valorar positivamente", + "chat_upvote_tooltip": "Esta respuesta fue útil", + "common_all": "Todos", + "common_allow_domain_access": "Permitir acceso por dominio", + "common_allow_domain_join_project": "Permitir que usuarios de Rill existentes y nuevos con una dirección de correo {domain} se unan a este proyecto como {role}.", + "common_apply": "Aplicar", + "common_back": "Volver", + "common_cancel": "Cancelar", + "common_close_search": "Cerrar búsqueda", + "common_contact_us": "Contáctenos", + "common_continue": "Continuar", + "common_delete": "Eliminar", + "common_got_it": "Entendido", + "common_learn_more": "Más información", + "common_loading": "Cargando...", + "common_must_be_number": "El valor debe ser un número válido", + "common_name": "Nombre", + "common_no_results_found": "No se encontraron resultados.", + "common_preview": "Vista previa", + "common_required": "Requerido", + "common_search": "Buscar", + "common_search_list": "Buscar en la lista", + "common_status": "Estado", + "common_type": "Tipo", + "common_undo": "Deshacer", + "dashboard_add_all_dims_rows": "Agregar todas las dimensiones de {name} a filas", + "dashboard_add_all_to_columns": "Agregar todo a columnas", + "dashboard_add_all_to_columns_tag": "Agregar todo de {name} a columnas", + "dashboard_add_all_to_rows": "Agregar todo a filas", + "dashboard_add_column": "Agregar columna", + "dashboard_add_filter": "Agregar filtro", + "dashboard_add_filter_button": "Botón de agregar filtro", + "dashboard_add_filter_button_aria": "Botón para agregar filtro", + "dashboard_add_mock_user": "Agregar usuario de prueba", + "dashboard_add_row": "Agregar fila", + "dashboard_add_to_columns": "Agregar a columnas", + "dashboard_add_to_rows": "Agregar a filas", + "dashboard_added_items_filter": "Se agregaron {count} elementos al filtro", + "dashboard_all": "Todos", + "dashboard_all_measures": "Todas las medidas", + "dashboard_always_show_as": "Mostrar siempre como", + "dashboard_anchor_period_end": "Anclar al final del período", + "dashboard_as_of": "a partir de", + "dashboard_as_of_ref": "a partir de", + "dashboard_auto_arrange": "Disposición automática", + "dashboard_auto_arrange_tag": "Disposición automática de {name}: dimensiones a filas, medidas a columnas", + "dashboard_cancel": "Cancelar", + "dashboard_change_over_comparison": "Cambio respecto al período de comparación", + "dashboard_clear": "Limpiar", + "dashboard_clear_filters": "Limpiar filtros", + "dashboard_clear_recents": "Limpiar recientes", + "dashboard_clear_view": "Limpiar vista", + "dashboard_click_to_edit_values": "Haz clic para editar los valores", + "dashboard_cmd_click_replace": "⌘ + Clic para reemplazar", + "dashboard_collapse_all": "Colapsar todo", + "dashboard_columns": "Columnas", + "dashboard_comparison_column_aria": "Columna de comparación", + "dashboard_comparison_select_tooltip": "Selecciona una comparación para el panel", + "dashboard_complete_data": "datos completos", + "dashboard_complete_data_description": "Marca temporal antes de la cual los marcos de datos se consideran completos, también conocida como watermark", + "dashboard_connect_sparse_data": "Conectar datos dispersos", + "dashboard_contains": "Contiene", + "dashboard_copied_error_clipboard": "Error copiado al portapapeles", + "dashboard_copy_error": "Copiar mensaje de error completo", + "dashboard_copy_error_clipboard": "Copiar error al portapapeles", + "dashboard_copy_error_to_clipboard_aria": "Copiar mensaje de error al portapapeles", + "dashboard_create_a_dashboard": "Crear un tablero", + "dashboard_current_time": "hora actual", + "dashboard_current_time_description": "Reloj del servidor en la zona horaria seleccionada", + "dashboard_currently_flat": "Mostrando vista plana actualmente", + "dashboard_currently_pivot": "Mostrando vista de pivote actualmente", + "dashboard_custom": "Personalizado", + "dashboard_deselect_all": "Deseleccionar todo", + "dashboard_deselect_all_selections": "Deseleccionar todas las selecciones", + "dashboard_dimension_display_aria": "Visualización de dimensión", + "dashboard_dimension_search_results_aria": "Resultados de búsqueda de dimensiones", + "dashboard_dimension_table_aria": "Tabla de dimensión", + "dashboard_dimensions": "Dimensiones", + "dashboard_dimensions_count": "{count} dimensiones", + "dashboard_dimensions_label": "DIMENSIONES", + "dashboard_download_png": "Descargar PNG", + "dashboard_drag_dimensions": "Arrastra dimensiones aquí", + "dashboard_drag_dimensions_or_measures": "Arrastra dimensiones o medidas aquí", + "dashboard_drag_list_zone": "Lista de arrastre {zone}", + "dashboard_dynamic_y_axis": "Escala dinámica del eje Y", + "dashboard_empty_state": "Aún no tienes tableros", + "dashboard_end": "fin", + "dashboard_error_occurred": "Ocurrió un error", + "dashboard_error_occurred_hover": "Ocurrió un error. Pasa el cursor para ver detalles.", + "dashboard_error_tag": "Error", + "dashboard_errored_contact_admin": "Contacta al administrador de tu proyecto para obtener ayuda.", + "dashboard_errored_need_help": "¿Necesitas ayuda? Escríbenos en {link}", + "dashboard_errored_title": "Lo sentimos, tu dashboard no está funcionando en este momento.", + "dashboard_errored_view_project": "Ver proyecto", + "dashboard_errored_view_status": "Revisa el estado del proyecto para encontrar errores que puedan ayudarte a solucionarlo.", + "dashboard_errored_view_status_button": "Ver estado del proyecto", + "dashboard_exclude": "Excluir", + "dashboard_explore": "Explorar", + "dashboard_export_chart": "Exportar gráfico", + "dashboard_export_dimension_table_data": "Exportar datos de tabla de dimensión", + "dashboard_export_model_data": "Exportar datos del modelo", + "dashboard_export_pivot_data": "Exportar datos de tabla dinámica", + "dashboard_export_table_data": "Exportar datos de tabla", + "dashboard_filter_by_value": "Filtrar por este valor", + "dashboard_filter_dimension_value": "Filtrar valor de dimensión", + "dashboard_filter_required_set_value": "Este filtro es obligatorio. Establece un valor para cargar el panel.", + "dashboard_flat": "Plana", + "dashboard_generated": "Generado {time}", + "dashboard_generating": "Generando…", + "dashboard_grain": "Granularidad", + "dashboard_hide_panels": "Ocultar paneles", + "dashboard_in_list": "En lista", + "dashboard_include_exclude_toggle": "Alternar incluir/excluir", + "dashboard_invalid_time_range": "Rango de tiempo inválido", + "dashboard_last_refreshed_ago": "Última actualización {time}", + "dashboard_latest_data": "datos más recientes", + "dashboard_latest_data_description": "Marca temporal del punto de datos más reciente", + "dashboard_leaderboards_aria": "Tablas de clasificación", + "dashboard_list_create": "Crea un dashboard", + "dashboard_list_create_to_start": "{link} para comenzar", + "dashboard_list_empty": "Aún no tienes ningún dashboard", + "dashboard_list_see_all": "Ver todos los dashboards", + "dashboard_measure_chart_aria": "Gráfico de medida para {name}", + "dashboard_measures": "Medidas", + "dashboard_measures_count": "{count} medidas", + "dashboard_measures_label": "MEDIDAS", + "dashboard_menu_all_dimensions": "Todas las Dimensiones", + "dashboard_no_additional_details": "No hay detalles adicionales disponibles.", + "dashboard_no_available_fields": "No hay campos disponibles", + "dashboard_no_comparison_dimension": "No se seleccionó dimensión de comparación", + "dashboard_no_dashboards_found": "No se encontraron tableros", + "dashboard_no_filters_selected": "No hay filtros seleccionados", + "dashboard_no_matching_tags": "No hay etiquetas coincidentes", + "dashboard_no_mock_users": "No hay usuarios de prueba", + "dashboard_no_options_found": "No se encontraron opciones", + "dashboard_no_search_results": "No hay resultados de búsqueda para mostrar", + "dashboard_no_timezones_configured": "No hay zonas horarias configuradas", + "dashboard_no_valid_grains": "No hay granularidades válidas disponibles.", + "dashboard_of": "de", + "dashboard_open_dimension_details_aria": "Abrir detalles de dimensión", + "dashboard_other": "otro", + "dashboard_others": "otros", + "dashboard_output_excludes": "La salida excluye los valores seleccionados", + "dashboard_output_includes": "La salida incluye los valores seleccionados", + "dashboard_percent_of_total": "Porcentaje del total", + "dashboard_percentage_change": "Cambio porcentual respecto al período de comparación", + "dashboard_pivot": "Pivote", + "dashboard_pivot_add_measure": "Agrega una medida para completar tu tabla.", + "dashboard_pivot_building_table": "¡Un momento! Estamos construyendo tu tabla...", + "dashboard_pivot_give_data": "Déle algunos datos para hacerle compañía.", + "dashboard_pivot_keep_it_up": "¡Sigue así!", + "dashboard_pivot_learn_more": "Aprenda más sobre tablas en nuestra", + "dashboard_pivot_need_help_discord": "¿Necesitas ayuda? Contáctanos en", + "dashboard_pivot_no_data": "No hay datos para mostrar con los filtros seleccionados.", + "dashboard_pivot_table_lonely": "Tu tabla se ve sola", + "dashboard_readonly_filter_chips_aria": "Chips de filtro de solo lectura", + "dashboard_recent": "Recientes", + "dashboard_reference": "Referencia", + "dashboard_remove_label": "Eliminar {label}", + "dashboard_removed_items_filter": "Se eliminaron {count} elementos del filtro", + "dashboard_replace": "Reemplazar", + "dashboard_replace_auto_arrange": "Reemplazar filas y columnas con disposición automática de {name}", + "dashboard_replace_columns_tag": "Reemplazar columnas con elementos de {name}", + "dashboard_replace_columns_tag_items": "Reemplazar columnas con los elementos de esta etiqueta", + "dashboard_replace_pivot_description": "Iniciar una nueva tabla perderá tu trabajo anterior. Guarda como marcador las tablas que quieras conservar", + "dashboard_replace_pivot_title": "¿Reemplazar la tabla dinámica actual?", + "dashboard_replace_rows_cols_tag": "Reemplazar filas y columnas con esta etiqueta", + "dashboard_replace_rows_tag": "Reemplazar filas con dimensiones de {name}", + "dashboard_replace_rows_tag_dims": "Reemplazar filas con las dimensiones de esta etiqueta", + "dashboard_required_measure": "medida requerida", + "dashboard_row_limit": "Límite de filas", + "dashboard_row_limit_tooltip": "Solo se muestran hasta las N filas secundarias principales bajo cada dimensión", + "dashboard_rows": "Filas", + "dashboard_search_dimension": "Buscar dimensión", + "dashboard_search_dimensions": "Buscar dimensiones", + "dashboard_search_results": "Resultados de búsqueda", + "dashboard_see_all": "Ver todos los tableros →", + "dashboard_see_more": "Ver más", + "dashboard_select_aggregation_grain_aria": "Seleccionar granularidad de agregación", + "dashboard_select_all": "Seleccionar todo", + "dashboard_select_comparison_dimension": "Seleccionar dimensión de comparación", + "dashboard_select_comparison_hint": "Para ver más valores, selecciona una dimensión de comparación arriba.", + "dashboard_select_ref_time_grain": "Seleccionar tiempo de referencia y granularidad", + "dashboard_select_time_axis": "Seleccionar eje de tiempo", + "dashboard_select_time_comparison_aria": "Seleccionar opción de comparación temporal", + "dashboard_select_time_dimension": "Seleccionar dimensión de tiempo {label}", + "dashboard_select_time_grain": "Seleccionar granularidad temporal", + "dashboard_select_time_range": "Seleccionar rango de tiempo", + "dashboard_select_time_range_aria": "Seleccionar rango de tiempo", + "dashboard_selected": "seleccionados", + "dashboard_show_panels": "Mostrar paneles", + "dashboard_sort_by_absolute_change_aria": "Alternar orden por cambio absoluto", + "dashboard_sort_by_percent_change_aria": "Alternar orden por cambio porcentual", + "dashboard_sort_by_percent_total_aria": "Alternar orden por porcentaje del total", + "dashboard_sort_by_value_aria": "Alternar orden por valor", + "dashboard_start": "inicio", + "dashboard_start_pivot": "Iniciar pivote", + "dashboard_switch_flat": "Cambiar a vista plana", + "dashboard_switch_pivot": "Cambiar a vista de pivote", + "dashboard_table_mode": "Modo de tabla", + "dashboard_tags": "Etiquetas", + "dashboard_tdd_contact_discord": "Si el problema persiste, contáctanos en", + "dashboard_tdd_error": "Encontramos un error al cargar los datos. Por favor, intenta actualizar la página.", + "dashboard_tdd_no_comparison": "Sin comparación", + "dashboard_tdd_time": "Tiempo", + "dashboard_time": "Tiempo", + "dashboard_time_axis": "Eje de tiempo", + "dashboard_time_label": "TIEMPO", + "dashboard_time_zone": "Zona horaria", + "dashboard_timezone_selector": "Selector de zona horaria", + "dashboard_to": "hasta", + "dashboard_to_get_started": "para comenzar", + "dashboard_toggle_exclude": "Cambiar para excluir valores", + "dashboard_toggle_include": "Cambiar para incluir valores", + "dashboard_toggle_rows_viewer_aria": "Alternar visor de filas", + "dashboard_toggle_time_comparison_aria": "Alternar comparación temporal", + "dashboard_total_column": "Columna de totales", + "dashboard_total_row": "Fila de totales", + "dashboard_view_as": "Ver como", + "dashboard_viewing_as": "Viendo como", + "dialog_close_without_saving_alert_desc": "Aún no has guardado los cambios de esta alerta, por lo que cerrar esta ventana perderá tu trabajo.", + "dialog_close_without_saving_cancel": "Seguir editando", + "dialog_close_without_saving_confirm": "Cerrar", + "dialog_close_without_saving_title": "¿Cerrar sin guardar?", + "edit_back_to_projects": "Volver a proyectos", + "edit_branch_name": "Nombre de rama", + "edit_changes_committed_pushed": "Cambios confirmados y enviados", + "edit_describe_changes": "Describe tus cambios...", + "edit_failed_to_commit": "Error al confirmar y enviar los cambios", + "edit_failed_to_merge": "Error al fusionar", + "edit_failed_to_publish": "Error al publicar", + "edit_failed_to_start": "Error al iniciar la sesión de edición.", + "edit_merging": "Fusionando...", + "edit_no_changes_detected": "No se detectaron cambios", + "edit_popup_blocked": "La ventana emergente fue bloqueada.", + "edit_provisioning_env": "Aprovisionando tu entorno de edición...", + "edit_publishing": "Publicando...", + "edit_pushing": "Enviando...", + "edit_return_to_org": "Volver a la organización", + "edit_return_to_project": "Volver al inicio del proyecto", + "edit_starting": "Iniciando...", + "edit_starting_env": "Iniciando tu entorno de edición...", + "edit_taking_longer": "Esto está tardando más de lo habitual.", + "edit_updating_env": "Actualizando tu entorno de edición...", + "embed_explore_error": "Error del Explorador", + "embed_explore_not_found": "Explorador no encontrado", + "embed_explore_not_found_body": "No se pudo encontrar el panel Explorador solicitado. Verifique que haya proporcionado el nombre de un panel funcional.", + "embed_home": "Inicio", + "embed_missing_required_params": "Faltan parámetros obligatorios: {params}", + "embed_unsupported_kind": "La incrustación de este tipo de recurso no está disponible actualmente.", + "env_add_title": "Agregar variables de entorno", + "env_add_variable_button": "Agregar variable", + "env_cancel_button": "Cancelar", + "env_click_to_copy_tooltip": "Clic para copiar", + "env_copied_tooltip": "¡Copiado!", + "env_create_button": "Crear", + "env_delete_action": "Eliminar", + "env_delete_description": "La variable de entorno {name} ya no estará disponible para este proyecto.", + "env_delete_title": "¿Eliminar esta variable de entorno?", + "env_development_label": "Desarrollo", + "env_development_production_label": "Desarrollo, Producción", + "env_documentation_link": "documentación", + "env_duplicate_keys_error": "No se permiten claves duplicadas", + "env_edit_action": "Editar", + "env_edit_button": "Editar", + "env_edit_title": "Editar variable de entorno", + "env_empty_value": "Vacío", + "env_environment_label": "Entorno", + "env_error_loading": "Error al cargar las variables de entorno:", + "env_for_help_see": "Para más ayuda, consulte la", + "env_import_dotenv": "Importar .env", + "env_key_duplicated_error": "Esta clave está duplicada", + "env_key_exists_error": "Esta clave ya existe en los entornos de destino", + "env_key_placeholder": "Clave", + "env_keys_exist_error": "Estas claves ya existen en los entornos de destino", + "env_learn_more": "Más información ->", + "env_must_select_environment": "Debe seleccionar al menos un entorno", + "env_new_key_button": "Nueva clave", + "env_no_match_filters": "Ninguna variable de entorno coincide con los filtros seleccionados", + "env_no_variables": "Sin variables de entorno", + "env_page_description": "Administre sus variables de entorno aquí.", + "env_page_title": "Variables de entorno", + "env_production_label": "Producción", + "env_some_keys_duplicated_error": "Algunas claves están duplicadas o ya existen en los entornos de destino", + "env_table_activity_header": "Actividad", + "env_table_key_header": "Clave", + "env_table_value_header": "Valor", + "env_value_placeholder": "Valor", + "env_variable_delete_error_notification": "Error al eliminar la variable de entorno", + "env_variable_deleted_notification": "Variable de entorno eliminada", + "env_variable_label": "Variable", + "env_variable_update_error_notification": "Error al actualizar la variable del proyecto", + "env_variable_updated_notification": "Variable de entorno actualizada", + "env_variables_label": "Variables", + "env_variables_update_error_notification": "Error al actualizar las variables del proyecto", + "env_variables_updated_notification": "Variables de entorno actualizadas", + "env_yes_delete_button": "Sí, eliminar", + "error_access_denied_body": "No tienes acceso a esta página. Verifica que tengas los permisos correctos.", + "error_access_denied_header": "Acceso denegado", + "error_auth_body": "Intenta recargar la página. Si el problema persiste, intenta cerrar sesión y volver a iniciarla.", + "error_auth_header": "Error de autenticación", + "error_back_to_home": "Volver al inicio", + "error_conversation_not_found_body": "Verifica que tengas el enlace correcto o que tengas acceso a la conversación.", + "error_conversation_not_found_header": "Conversación no encontrada", + "error_dashboard_not_found": "Tablero no encontrado", + "error_deploy_dashboards": "Error al desplegar tableros", + "error_deploying_project": "Hubo un error al desplegar tu proyecto. Contacta a soporte.", + "error_deployment_error": "Error de despliegue", + "error_deployment_not_found_body": "Este es potencialmente un estado temporal si el proyecto se acaba de reiniciar.", + "error_deployment_not_found_header": "Despliegue del proyecto no encontrado", + "error_fetching_deployment": "Error al obtener el despliegue", + "error_generic_body": "Intenta recargar la página y contáctanos si el problema persiste.", + "error_generic_header": "Algo salió mal.", + "error_hide_details": "Ocultar detalles", + "error_link_expired_body": "Parece que este enlace ya no está activo. Contacta al remitente para solicitar un nuevo enlace.", + "error_link_expired_header": "Este enlace ha expirado", + "error_network_body": "Parece que tenemos problemas para conectarnos a nuestros servidores. Verifica tu conexión o intenta de nuevo más tarde.", + "error_network_header": "Error de red", + "error_occurred": "Ocurrió un error", + "error_org_not_found_body": "La organización solicitada no se pudo encontrar. Verifica que hayas proporcionado un nombre de organización válido.", + "error_org_not_found_header": "Organización no encontrada", + "error_page_not_found": "Página no encontrada", + "error_page_not_found_body": "La página que buscas puede haber sido eliminada, cambiada de nombre o no estar disponible temporalmente.", + "error_page_not_found_header": "No podemos encontrar esta página.", + "error_project_not_found_body": "El proyecto solicitado no se pudo encontrar. Verifica que hayas proporcionado un nombre de proyecto válido.", + "error_project_not_found_header": "Proyecto no encontrado", + "error_resource_not_found_body": "Este recurso puede haber sido eliminado, renombrado o no estar disponible temporalmente.", + "error_resource_not_found_header": "Recurso no encontrado", + "error_retry_now": "Reintentar ahora", + "error_show_details": "Mostrar detalles", + "explore_all_dimensions": "Todas las dimensiones", + "explore_all_measures": "Todas las medidas", + "explore_by_grain_prefix": "por", + "explore_check_yaml_errors": "Por favor, revisa el archivo YAML de tu tablero en busca de errores.", + "explore_choose_dimensions": "Elegir dimensiones para mostrar", + "explore_choose_measures": "Elegir medidas para mostrar", + "explore_clear_filter": "Limpiar filtro", + "explore_clear_filter_tag": "Limpiar filtro {tag}", + "explore_clear_search_to_reorder_dimensions": "Limpie la búsqueda para reordenar dimensiones.", + "explore_clear_search_to_reorder_measures": "Limpie la búsqueda para reordenar medidas.", + "explore_clear_tag_filter": "Limpiar filtro de etiqueta", + "explore_clear_tag_filter_to_reorder_dimensions": "Limpie el filtro de etiqueta para reordenar dimensiones.", + "explore_clear_tag_filter_to_reorder_measures": "Limpie el filtro de etiqueta para reordenar medidas.", + "explore_dashboard_not_found": "Tablero no encontrado", + "explore_dimensions_count": "{count} de {total} dimensiones", + "explore_error_building": "Error al construir el tablero", + "explore_error_fetching": "Error al obtener el tablero", + "explore_error_parsing": "Error al analizar el tablero", + "explore_filter_by_tag": "Filtrar por {tag}", + "explore_filter_label": "Filtro", + "explore_go_to_dashboard": "Ir al panel de exploración", + "explore_go_to_explore": "Ir a Explorar", + "explore_go_to_named": "Ir a {name}", + "explore_hidden_dimensions": "Dimensiones ocultas", + "explore_hidden_measures": "Medidas ocultas", + "explore_hide_all": "Ocultar todo", + "explore_hide_all_in_named_tag": "Ocultar todo en {tag}", + "explore_hide_all_in_tag": "Ocultar todo en etiqueta", + "explore_hide_item": "Ocultar {name}", + "explore_measures_count": "{count} de {total} medidas", + "explore_multi_select": "Selección múltiple", + "explore_must_show_one_dimension": "Debe mostrar al menos una dimensión", + "explore_must_show_one_measure": "Debe mostrar al menos una medida", + "explore_n_measures": "{count} medidas", + "explore_no_dimensions_from_tag": "No se muestran dimensiones de esta etiqueta", + "explore_no_dimensions_or_tags": "No se encontraron dimensiones ni etiquetas", + "explore_no_dimensions_shown": "No hay dimensiones mostradas", + "explore_no_hidden_dimensions": "No hay dimensiones ocultas", + "explore_no_hidden_measures": "No hay medidas ocultas", + "explore_no_matching_dimensions_shown": "No hay dimensiones coincidentes mostradas", + "explore_no_matching_hidden_dimensions": "No hay dimensiones ocultas coincidentes", + "explore_no_matching_hidden_measures": "No hay medidas ocultas coincidentes", + "explore_no_matching_leaderboard_measures": "No se encontraron medidas de clasificación coincidentes", + "explore_no_matching_measures_shown": "No hay medidas coincidentes mostradas", + "explore_no_matching_tags": "No hay etiquetas coincidentes", + "explore_no_measures": "No hay medidas disponibles", + "explore_no_measures_from_tag": "No se muestran medidas de esta etiqueta", + "explore_no_measures_or_tags": "No se encontraron medidas ni etiquetas", + "explore_no_measures_shown": "No hay medidas mostradas", + "explore_only_show_tag": "Mostrar solo {tag}", + "explore_only_show_this_tag": "Mostrar solo esta etiqueta", + "explore_search_dimensions": "Buscar dimensiones", + "explore_search_dimensions_or_tags": "Buscar dimensiones o etiquetas", + "explore_search_list": "Buscar en lista", + "explore_search_measures": "Buscar medidas", + "explore_search_measures_or_tags": "Buscar medidas o etiquetas", + "explore_security_policy_warning": "La política de seguridad de este tablero puede hacer que el contenido sea invisible para ti. Si despliegas este tablero, {email} verá un 404.", + "explore_show_all": "Mostrar todo", + "explore_show_all_in_named_tag": "Mostrar todo en {tag}", + "explore_show_all_in_tag": "Mostrar todo en etiqueta", + "explore_show_context_for_all_measures": "Mostrar contexto para todas las medidas", + "explore_show_item": "Mostrar {name}", + "explore_showing": "Mostrando", + "explore_shown_dimensions": "Dimensiones mostradas", + "explore_shown_measures": "Medidas mostradas", + "explore_tag_shown_count": "{visible} de {total} mostrados", + "explore_tags": "Etiquetas", + "explore_unable_to_open": "No se pudo abrir el panel de exploración", + "explore_unknown_build_error": "Ocurrió un error desconocido al construir el tablero.", + "explore_unknown_dimension": "Dimensión desconocida", + "explore_unknown_measure": "Medida desconocida", + "explore_user_no_access": "Este usuario no puede acceder a este tablero", + "field_list_add_fields": "Agregar campos de {label}", + "field_list_aria": "Lista de campos de {label}", + "field_list_dimensions": "DIMENSIONES", + "field_list_measures": "MEDIDAS", + "field_list_time": "TIEMPO", + "filter_advanced_beta": "Avanzado (BETA)", + "filter_advanced_warning": "Los filtros avanzados son una funcionalidad experimental. Puede haber errores.", + "filter_dimensions": "DIMENSIONES", + "filter_enter_search_term": "Ingresa un término de búsqueda", + "filter_make_optional": "Hacer filtro opcional", + "filter_make_required": "Hacer filtro obligatorio", + "filter_measure_for_dimension": "para {dimension}", + "filter_measure_from_comparison": "desde {comparison}", + "filter_measure_op_between": "Entre", + "filter_measure_op_does_not_equal": "No es igual", + "filter_measure_op_equals": "Igual", + "filter_measure_op_greater_than": "Mayor que", + "filter_measure_op_greater_than_or_equals": "Mayor o igual que", + "filter_measure_op_less_than": "Menor que", + "filter_measure_op_less_than_or_equals": "Menor o igual que", + "filter_measure_op_not_between": "No está entre", + "filter_measure_type_change_from": "cambio respecto a", + "filter_measure_type_percent_change_from": "% de cambio respecto a", + "filter_measure_type_percent_of_total": "% del total", + "filter_measure_type_value": "valor", + "filter_measures": "MEDIDAS", + "filter_mode_contains": "Contiene", + "filter_mode_contains_description": "Crear un filtro dinámico basado en un término de búsqueda", + "filter_mode_in_list": "En lista", + "filter_mode_in_list_description": "Crear un filtro basado en una lista de valores", + "filter_mode_select": "Seleccionar", + "filter_mode_select_description": "Seleccionar valores manualmente para este filtro", + "filter_paste_list_hint": "Pegar una lista separada por comas o \\n", + "filter_pin": "Fijar filtro", + "filter_pin_tooltip": "Haz clic para fijar o desfijar: mantener este filtro visible en la parte superior para que otros usuarios no puedan eliminarlo.", + "filter_required_tooltip": "Haz clic para marcar este filtro como obligatorio. Los usuarios deben establecer un valor para que el tablero se cargue.", + "filter_unpin": "Desfijar filtro", + "footer_report_issue": "Reportar un problema", + "footer_rill_developer": "Rill Developer", + "footer_shortcut_click": "Clic", + "footer_unknown_version": "desconocido (compilado desde el código fuente)", + "footer_version": "versión", + "footer_view_documentation": "Ver documentación", + "form_optional": "(opcional)", + "github_access_requested_title": "Acceso a GitHub solicitado", + "github_branch": "rama", + "github_click_to_reauthorize": "Haga clic en el botón de abajo para reautorizar u otra cuenta.", + "github_click_to_retry": "Haga clic en el botón de abajo para reintentar.", + "github_close_and_continue_cli": "Cierre esta página y continúe la configuración en el Rill CLI.", + "github_close_page_now": ". Puede cerrar esta página ahora.", + "github_connect_other_orgs": "+ Conectar otras organizaciones", + "github_connect_other_repos": "+ Conectar otros repositorios", + "github_connect_project_description": "Conectar este proyecto a GitHub.", + "github_connect_to_github": "Conectar con GitHub", + "github_connected_successfully": "GitHub conectado exitosamente", + "github_connection_failed": "Error al conectar con GitHub. Inténtelo de nuevo.", + "github_could_not_connect": "No se pudo conectar con GitHub", + "github_create_and_push": "Crear y enviar", + "github_create_repository": "Crear repositorio", + "github_deploy_continuously": "Los proyectos de Rill se despliegan continuamente cuando envía cambios a GitHub.", + "github_did_not_grant_access": "Parece que no otorgó acceso al repositorio deseado en", + "github_error_push_failed": "No se pudo completar el envío. Por favor, revisa la configuración del repositorio y subdirectorio e intenta de nuevo.", + "github_error_repo_exists": "Este repositorio ya existe. Por favor, elige un nombre de repositorio nuevo.", + "github_error_subpath_exists": "La subruta especificada ya existe en este repositorio. Usa una subruta diferente o elimina la carpeta existente antes de enviar.", + "github_existing_repository": "Repositorio existente", + "github_grant_access_to_repo": "Otorgue acceso a su repositorio", + "github_no_access_to_repo": "Su cuenta de GitHub autorizada no tiene acceso al repositorio.", + "github_organization": "Organización", + "github_overwrite_warning": "El contenido actual del proyecto se sobrescribirá con el contenido del repositorio. No hay forma de recuperar este proyecto actual. ¿Está seguro?", + "github_pull_changes": "Obtener cambios", + "github_pull_changes_from": "¿Obtener cambios de {path}?", + "github_reconnect": "Reconectar", + "github_repository": "Repositorio", + "github_repository_name": "Nombre del repositorio", + "github_requested_access": "Solicitó acceso a", + "github_select_organization": "Seleccionar organización", + "github_select_repository": "Seleccionar repositorio", + "github_subpath": "subruta", + "github_synced": "Sincronizado", + "github_type_to_confirm": "Escriba {text} en el campo de abajo para confirmar:", + "github_unlock_bi_as_code": "Desbloquee el poder de BI-as-code con colaboración respaldada por GitHub, control de versiones y flujos de aprobación.", + "groups_changes_saved": "Los cambios del grupo de usuarios se guardaron exitosamente", + "groups_create_a_group": "Crear un grupo", + "groups_create_group": "Crear grupo", + "groups_created": "Grupo de usuarios creado", + "groups_delete": "Eliminar", + "groups_delete_confirm_desc": "Este grupo de usuarios ya no podrá acceder a la organización.", + "groups_delete_confirm_title": "¿Eliminar este grupo de usuarios?", + "groups_deleted": "Grupo de usuarios eliminado", + "groups_edit": "Editar", + "groups_edit_group": "Editar grupo", + "groups_error_adding_role": "Error al agregar rol al grupo de usuarios", + "groups_error_deleting": "Error al eliminar el grupo de usuarios", + "groups_error_loading": "Error al cargar los grupos de usuarios de la organización:", + "groups_error_revoking_role": "Error al revocar el rol del grupo de usuarios", + "groups_error_updating_role": "Error al actualizar el rol del grupo de usuarios", + "groups_removed": "Grupo de usuarios eliminado", + "groups_renamed": "Grupo de usuarios renombrado", + "groups_role_added": "Rol del grupo de usuarios agregado", + "groups_role_revoked": "Rol del grupo de usuarios revocado", + "groups_role_updated": "Rol del grupo de usuarios actualizado", + "groups_table_empty": "No se encontraron grupos", + "groups_table_header_group": "Grupo", + "groups_total_count": "{count} grupos en total", + "groups_yes_delete": "Sí, eliminar", + "home_dashboards_heading": "Dashboards", + "home_greeting": "¡Hola {name}!", + "home_subtitle_no_chat": "Explora tus dashboards a continuación", + "home_subtitle_with_chat": "Haz preguntas sobre tus datos o explora tus dashboards a continuación", + "home_welcome_getting_started": "¡Parece que estás comenzando! Consulta nuestro {link}.", + "home_welcome_quickstart_link": "Inicio rápido para crear tu primer proyecto", + "home_welcome_to": "Bienvenido a {projectName}", + "interval_day": "Día", + "interval_hour": "Hora", + "interval_none": "Ninguno", + "interval_week": "Semana", + "kpi_no_change": "sin cambio", + "kpi_no_data": "sin datos", + "kpi_not_available": "n/d", + "kpi_vs_comparison": "vs {comparison}", + "language_en": "English", + "language_es": "Español", + "language_switcher_label": "Idioma", + "layout_inspector_panel_aria": "Panel del inspector", + "leaderboard_compare": "Comparar", + "leaderboard_copy_value": "Copiar este valor al portapapeles", + "leaderboard_expand_table": "(Expandir tabla)", + "leaderboard_expand_tooltip": "Expandir dimensión para ver más valores", + "leaderboard_no_available_values": "(Sin valores disponibles)", + "leaderboard_remove_comparison": "Eliminar comparación", + "leaderboard_shift_click": "+ Clic", + "leaderboard_toggle_breakdown": "Alternar desglose para dimensión {name}", + "mcp_add_to_config": "Agrega esto al archivo de configuración de tu cliente MCP.", + "mcp_add_url": "Agrega esta URL a la configuración del servidor MCP de tu cliente de IA:", + "mcp_configuration": "Configuración", + "mcp_create_token": "Crear token", + "mcp_create_token_desc": "Porque este proyecto es {privateLabel}, necesitas un {tokenLabel} para usar en tu configuración MCP. Este token autentica tus solicitudes.", + "mcp_create_token_title": "Crea un token de acceso personal", + "mcp_dialog_description": "Haz preguntas sobre tu proyecto Rill usando lenguaje natural en cualquier cliente de IA que soporte el Model Context Protocol (MCP).", + "mcp_dialog_title": "Conecta tu propio cliente de IA", + "mcp_issuing": "Generando...", + "mcp_learn_more": "Más información", + "mcp_manual_tab": "Manual", + "mcp_oauth_auto": "El flujo de OAuth se iniciará automáticamente en tu navegador.", + "mcp_oauth_tab": "OAuth", + "mcp_personal_access_token": "token de acceso personal", + "mcp_private": "privado", + "mcp_recommended": "Recomendado", + "mcp_token_created": "Token creado. Tu nuevo token ya está incluido en el fragmento de configuración a continuación.", + "mcp_token_failed": "Error al generar el token. Intenta de nuevo.", + "measure_filter_apply": "Aplicar", + "measure_filter_by_dimension": "Por dimensión", + "measure_filter_enter_number": "Ingresa un número", + "measure_filter_higher_value": "Valor superior", + "measure_filter_lower_value": "Valor inferior", + "measure_filter_select_dimension": "Seleccionar dimensión para dividir", + "measure_filter_threshold": "Umbral", + "measures_choose_tooltip": "Seleccionar medidas a mostrar", + "measures_label": "Medidas", + "nav_close_sidebar": "Cerrar barra lateral", + "nav_dashboards": "Tableros", + "nav_data_explorer": "Explorador de datos", + "nav_show_sidebar": "Mostrar barra lateral", + "nav_status": "Estado", + "nav_tab_ai": "IA", + "nav_tab_alerts": "Alertas", + "nav_tab_dashboards": "Dashboards", + "nav_tab_home": "Inicio", + "nav_tab_query": "Consulta", + "nav_tab_reports": "Informes", + "nav_tab_settings": "Configuración", + "nav_tab_status": "Estado", + "org_check_out_projects": "Explora tus proyectos a continuación.", + "org_new_project": "+ Nuevo proyecto", + "org_role_admin_description": "Acceso completo a la configuración de la org, miembros y todos los proyectos", + "org_role_editor_description": "Puede crear/gestionar proyectos y miembros no administradores", + "org_role_guest_description": "Acceso solo a proyectos invitados", + "org_role_viewer_description": "Acceso de solo lectura a todos los proyectos de la org", + "org_search_add_remove_users": "Buscar para agregar/quitar usuarios", + "org_tab_projects": "Proyectos", + "org_tab_settings": "Configuración", + "org_tab_users": "Usuarios", + "pivot_collapse_row": "Contraer fila", + "pivot_dim_one": "dim", + "pivot_dim_other": "dims", + "pivot_drop_arrange_aria": "Soltar aquí para organizar automáticamente", + "pivot_drop_replace_aria": "Soltar aquí para reemplazar filas y columnas con esta etiqueta", + "pivot_drop_replace_text": "Soltar para reemplazar: {dimCount} {dimLabel} → filas, {measureCount} {measureLabel} → columnas", + "pivot_drop_split_hint": "Soltar para reemplazar", + "pivot_drop_split_text": "Soltar aquí para dividir: {dimCount} {dimLabel} → filas, {measureCount} {measureLabel} → columnas", + "pivot_expand_row": "Expandir fila", + "pivot_measure_one": "medida", + "pivot_measure_other": "medidas", + "pivot_tags": "ETIQUETAS", + "pivot_time_dimension_header": "Tiempo {grain}", + "pivot_time_prefix": "Tiempo", + "project_branch_hibernated": "Rama en hibernación", + "project_branch_is_hibernated": "Esta rama está en hibernación.", + "project_contact_admin_to_redeploy": "Contacte al administrador del proyecto para redesplegar el proyecto.", + "project_create_first": "Crea tu primer proyecto", + "project_create_new": "Crear un nuevo proyecto", + "project_create_project": "Crear proyecto", + "project_dashboards_title": "Dashboards del proyecto", + "project_delete": "Eliminar", + "project_deploying": "Desplegando tu proyecto...", + "project_edit": "Editar", + "project_failed_to_wake": "No se pudo reactivar el proyecto: {error}", + "project_hibernating": "Hibernando...", + "project_is_hibernating": "Su proyecto está en hibernación", + "project_name_first": "Nombra tu primer proyecto", + "project_name_format_error": "El nombre debe comenzar con una letra o número y solo puede contener letras, números, guiones y guiones bajos", + "project_name_max_length": "El nombre debe tener como máximo 40 caracteres", + "project_name_min_length": "El nombre debe tener al menos 1 carácter", + "project_name_new": "Nombra tu proyecto", + "project_name_required": "El nombre es obligatorio", + "project_rename": "Renombrar", + "project_rename_anytime": "Puedes renombrar tu proyecto en cualquier momento.", + "project_resume_branch": "Reanudar rama", + "project_role_admin": "Administrador", + "project_role_guest_description": "Acceso solo a proyectos invitados", + "project_role_viewer": "Visualizador", + "project_search_or_invite": "Buscar o invitar por correo", + "project_search_users": "Buscar usuarios", + "project_share": "Compartir", + "project_share_failed_to_invite": "Error al invitar.", + "project_share_heading": "Compartir proyecto: {project}", + "project_share_invalid_email": "Dirección de correo electrónico no válida", + "project_share_invalid_email_or_group": "Correo electrónico o nombre de grupo no válido", + "project_share_role_admin": "Administrador", + "project_share_role_admin_description": "Puede gestionar la configuración del proyecto y los miembros", + "project_share_role_editor": "Editor", + "project_share_role_editor_description": "Puede editar los recursos del proyecto", + "project_share_role_viewer": "Visualizador", + "project_share_role_viewer_description": "Puede ver tableros", + "project_share_tooltip": "Compartir proyecto", + "project_starting": "Iniciando...", + "project_starting_branch_deployment": "Iniciando despliegue de rama...", + "project_this_is_hibernating": "Este proyecto está en hibernación", + "project_wake": "Reactivar proyecto", + "project_waking": "Reactivando...", + "project_waking_up": "Reactivando su proyecto...", + "public_url_cancel_button": "Cancelar", + "public_url_copied_button": "URL copiada", + "public_url_copied_to_clipboard": "URL pública copiada al portapapeles", + "public_url_copy_button": "Copiar URL pública", + "public_url_copy_url_action": "Copiar URL", + "public_url_create_button": "Crear", + "public_url_create_heading": "Cree una URL pública compartible para esta vista.", + "public_url_delete_action": "Eliminar", + "public_url_delete_description": "Los destinatarios de esta URL ya no podrán acceder a ella.", + "public_url_delete_error_notification": "Error al eliminar la URL pública", + "public_url_delete_title": "¿Eliminar esta URL pública?", + "public_url_deleted_notification": "URL pública eliminada", + "public_url_edit_expiration": "Editar fecha de expiración", + "public_url_error_loading": "Error al cargar las URLs públicas", + "public_url_filters_locked_hidden": "Los siguientes filtros estarán bloqueados y ocultos:", + "public_url_label_placeholder": "Etiquetar esta URL", + "public_url_learn_more": "Más información ->", + "public_url_measures_dimensions_limited": "Las medidas y dimensiones se limitarán al conjunto visible actual.", + "public_url_no_match_search": "Ninguna URL pública coincide con su búsqueda", + "public_url_no_urls_description": "Para crear una URL pública que pueda compartir con cualquier persona, haga clic en el botón Compartir en un panel.", + "public_url_no_urls_empty": "Para crear una URL pública, haga clic en el botón Compartir en un panel.", + "public_url_no_urls_title": "Aún no tiene ninguna URL pública", + "public_url_page_description": "Administre las URLs públicas compartidas de sus paneles.", + "public_url_page_title": "URLs públicas", + "public_url_set_expiration": "Establecer expiración", + "public_url_success_message": "¡Listo! Se ha creado una URL pública.", + "public_url_table_created_by_header": "Creado por", + "public_url_table_dashboard_header": "Panel", + "public_url_table_dashboard_title_header": "Título del panel", + "public_url_table_expires_header": "Expira el", + "public_url_table_filters_header": "Filtros", + "public_url_table_label_header": "Etiqueta", + "public_url_table_last_accessed_header": "Último acceso", + "public_url_title_required": "El título es obligatorio", + "public_url_untitled": "Sin título", + "public_url_yes_delete_button": "Sí, eliminar", + "report_adhoc": "Ad hoc", + "report_adhoc_tooltip": "Este informe se ejecutó manualmente fuera del horario programado.", + "report_context_menu_aria": "Menú contextual del informe", + "report_created_by": "Creado por {name}", + "report_created_through_code": "Informe creado mediante código", + "report_dashboard": "Dashboard", + "report_dashboard_not_exist": "El tablero no existe", + "report_delete": "Eliminar informe", + "report_download_failed": "La descarga falló", + "report_download_retry_hint": "Si la descarga falla, actualice la página para intentar de nuevo.", + "report_downloading": "Descargando informe...", + "report_edit": "Editar informe", + "report_email_recipients": "Destinatarios de correo", + "report_email_validation": "Se requiere al menos un destinatario de correo, usuario de Slack o canal de Slack", + "report_form_cancel": "Cancelar", + "report_form_channels": "Canales", + "report_form_clear_filters": "Limpiar filtros", + "report_form_columns": "Columnas", + "report_form_create": "Crear informe", + "report_form_create_button": "Crear", + "report_form_created_notification": "Informe creado", + "report_form_day": "Día", + "report_form_day_first": "Primer día", + "report_form_day_friday": "Viernes", + "report_form_day_monday": "Lunes", + "report_form_day_saturday": "Sábado", + "report_form_day_sunday": "Domingo", + "report_form_day_thursday": "Jueves", + "report_form_day_tuesday": "Martes", + "report_form_day_wednesday": "Miércoles", + "report_form_docs": "documentación", + "report_form_edited_notification": "Informe editado", + "report_form_email_hint": "Los destinatarios recibirán vistas diferentes según su política de seguridad.", + "report_form_email_placeholder": "Ingresa una dirección de correo", + "report_form_email_recipients": "Destinatarios de correo", + "report_form_email_recurring": "Envía exportaciones recurrentes por correo a los destinatarios.", + "report_form_filters": "Filtros", + "report_form_filters_aria": "Formulario de filtros", + "report_form_format": "Formato", + "report_form_format_csv": "CSV", + "report_form_format_parquet": "Parquet", + "report_form_format_xlsx": "XLSX", + "report_form_freq_daily": "Diario", + "report_form_freq_monthly": "Mensual", + "report_form_freq_weekdays": "Días laborables", + "report_form_freq_weekly": "Semanal", + "report_form_frequency": "Frecuencia", + "report_form_go_to_reports": "Ir a informes programados", + "report_form_include_metadata": "Incluir metadatos", + "report_form_invalid_email": "Correo inválido", + "report_form_local_suffix": " (Local)", + "report_form_metadata_tooltip": "Agrega un encabezado al archivo que incluye filtros, rango de tiempo y otros metadatos.", + "report_form_no_rows_selected": "No hay filas seleccionadas", + "report_form_recipients_must_be_project": "Los destinatarios deben ser parte del proyecto cuando se ejecuta como destinatario", + "report_form_required": "Obligatorio", + "report_form_row_limit": "Límite de filas", + "report_form_row_limit_placeholder": "1000", + "report_form_rows": "Filas", + "report_form_run_as": "Ejecutar como", + "report_form_run_as_creator": "Creador", + "report_form_run_as_creator_desc": "Funciona para cualquier destinatario, incluyendo externos. NO otorga acceso más allá de los filtros e informes del dashboard.", + "report_form_run_as_recipient": "Destinatario", + "report_form_run_as_recipient_desc": "NO funciona para usuarios que no son miembros del proyecto.", + "report_form_save": "Guardar informe", + "report_form_save_button": "Guardar", + "report_form_schedule": "Programar informe", + "report_form_slack_channels_hint": "Enviaremos alertas directamente a estos canales.", + "report_form_slack_not_configured": "Slack no ha sido configurado para este proyecto. Lee la {link} para saber más.", + "report_form_slack_title": "Notificaciones de Slack", + "report_form_slack_users": "Usuarios", + "report_form_slack_users_hint": "Les enviaremos mensajes directos en Slack.", + "report_form_time": "Hora", + "report_form_timezone": "Zona horaria", + "report_form_title_label": "Título del informe", + "report_form_title_placeholder": "Mi informe", + "report_format_csv": "CSV", + "report_format_parquet": "Parquet", + "report_format_unknown": "Desconocido", + "report_format_unspecified": "Formato no especificado", + "report_format_xlsx": "Excel (XLSX)", + "report_go_to_page": "Ir a la página del informe", + "report_has_not_run_yet": "Este informe aún no se ha ejecutado", + "report_hasnt_run_yet": "Aún no se ha ejecutado", + "report_last_run": "Última ejecución {time}", + "report_loading": "Cargando...", + "report_name_label": "Nombre", + "report_next_run": "Próxima ejecución", + "report_no_row_limit": "Sin límite de filas", + "report_recent_history": "Historial reciente", + "report_recipients": "Destinatarios ({count})", + "report_repeats": "Se repite", + "report_row_limit": "Límite de {count} filas", + "report_run_now": "Ejecutar ahora", + "report_run_now_tooltip": "Ejecutar este informe de inmediato. Se generará un nuevo informe y se enviará por correo a los destinatarios.", + "report_showing_recent_runs": "Mostrando hasta las 10 ejecuciones más recientes", + "report_slack_recipients": "Destinatarios de Slack", + "report_status_failed": "Fallido", + "report_status_sent": "Informe enviado", + "report_triggered_adhoc": "Se activó una ejecución ad-hoc de este informe.", + "report_unable_to_open": "No se pudo abrir el informe", + "report_unsubscribe_failed": "Error al cancelar la suscripción.", + "report_unsubscribed": "Suscripción al informe cancelada.", + "report_unsubscribing": "Cancelando suscripción...", + "reports_empty_action": "Programa {reportsLink} desde cualquier dashboard", + "reports_empty_message": "Aún no tienes informes", + "reports_link_text": "informes", + "resource_error_contact_support": "Si este error persiste, contacta a soporte.", + "resource_error_loading": "Error al cargar {kind}s", + "resource_search_placeholder": "Buscar", + "resource_type_canvas": "Canvas", + "resource_type_explore": "Explorar", + "role_admin": "Administrador", + "role_editor": "Editor", + "role_guest": "Invitado", + "role_guest_desc": "Acceso solo a proyectos invitados", + "role_org_admin_desc": "Control total sobre la configuración y miembros de la organización", + "role_org_admin_detail": "Acceso completo a configuración, miembros y todos los proyectos de la organización", + "role_org_editor_desc": "Puede gestionar proyectos y la mayoría de recursos de la organización", + "role_org_editor_detail": "Puede crear/gestionar proyectos y miembros no administradores", + "role_org_viewer_desc": "Acceso de solo lectura a la organización y proyectos", + "role_org_viewer_detail": "Acceso de solo lectura a todos los proyectos de la organización", + "role_project_admin_desc": "Control total de la configuración y miembros del proyecto", + "role_project_editor_desc": "Puede crear y editar dashboards; gestionar acceso no-admin", + "role_project_viewer_desc": "Acceso de solo lectura a todos los recursos del proyecto", + "role_viewer": "Lector", + "route_error_dashboard_not_found": "No se pudo encontrar un tablero", + "route_error_fetching_billing_issues": "Error al obtener los problemas de facturación", + "route_error_fetching_billing_subscription": "Error al obtener la suscripción de facturación", + "route_error_fetching_organization": "Error al obtener la organización", + "route_error_fetching_project": "Error al obtener el proyecto", + "route_error_no_org_permission": "No tienes permiso para acceder a esta organización", + "route_error_token_not_found": "No se pudo encontrar el token", + "route_error_token_resource_not_found": "No se pudo encontrar el recurso del token", + "settings_allow_domain_description": "Permitir que los usuarios de Rill existentes y nuevos con una dirección de correo {domain} se unan a esta organización como {role}.", + "settings_allow_domain_title": "Permitir acceso por dominio", + "settings_branch_callout": "Estas configuraciones aplican a todo el proyecto, no solo a la rama {branch}.", + "settings_cancel_button": "Cancelar", + "settings_danger_zone_title": "Zona de peligro", + "settings_dark_logo_label": "Logo oscuro", + "settings_delete_button": "Eliminar", + "settings_delete_org_button": "Eliminar organización", + "settings_delete_org_confirm_description": "La organización \"{organization}\" será eliminada permanentemente junto con todos sus proyectos, datos y configuraciones. Esta acción no se puede deshacer.", + "settings_delete_org_confirm_title": "¿Eliminar esta organización?", + "settings_delete_org_description": "Eliminar permanentemente esta organización y todo su contenido de la plataforma Rill. Esta acción no es reversible — continúe con precaución.", + "settings_delete_org_title": "Eliminar organización", + "settings_delete_project_button": "Eliminar proyecto", + "settings_delete_project_confirm_description": "El proyecto \"{project}\" será eliminado permanentemente junto con todos sus paneles, datos y configuraciones. Esta acción no se puede deshacer.", + "settings_delete_project_confirm_title": "¿Eliminar proyecto?", + "settings_delete_project_description": "Eliminar permanentemente este proyecto y todo su contenido de la plataforma Rill. Esta acción no es reversible — continúe con precaución.", + "settings_delete_project_title": "Eliminar proyecto", + "settings_deleted_org_notification": "Organización eliminada", + "settings_deleted_project_notification": "Proyecto eliminado", + "settings_description_label": "Descripción", + "settings_description_placeholder": "Describa su organización", + "settings_domain_not_allowed_public": "La lista de dominios permitidos no está disponible con un dominio público.", + "settings_domains_added_by_admins": "Dominios añadidos a la lista permitida por otros administradores", + "settings_favicon_description": "Haga clic para subir su favicon y personalizar Rill para su organización. Suba un icono cuadrado para obtener los mejores resultados.", + "settings_favicon_title": "Favicon", + "settings_github_title": "GitHub", + "settings_hibernate_button": "Hibernar", + "settings_hibernate_confirm_description": "El proyecto se pausará y no consumirá recursos. Se puede reactivar en cualquier momento.", + "settings_hibernate_confirm_title": "¿Hibernar este proyecto?", + "settings_hibernate_failed_notification": "Error al hibernar el proyecto", + "settings_hibernate_project_button": "Hibernar proyecto", + "settings_hibernate_project_description": "Poner este proyecto en modo de hibernación. Los proyectos hibernados están pausados y no consumen recursos. El proyecto se puede reactivar en cualquier momento.", + "settings_hibernate_project_title": "Hibernar proyecto", + "settings_learn_more": "Más información", + "settings_light_logo_label": "Logo claro", + "settings_logo_description": "Haga clic para subir su logo y personalizar Rill para su organización.", + "settings_logo_title": "Logo", + "settings_make_private_button": "Hacer privado", + "settings_make_public_button": "Hacer público", + "settings_name_already_taken": "El nombre {name} ya está en uso", + "settings_name_label": "Nombre", + "settings_nav_billing": "Facturación", + "settings_nav_console": "Consola", + "settings_nav_env_vars": "Variables de entorno", + "settings_nav_general": "General", + "settings_nav_public_urls": "URLs públicas", + "settings_nav_token_mgmt": "Gestión de tokens", + "settings_none": "ninguno", + "settings_org_page_title": "Configuración de la organización", + "settings_org_title": "Organización", + "settings_org_url_description": "La URL de su organización será https://ui.rilldata.com/{slug}, conforme a nuestras reglas de nomenclatura.", + "settings_project_hibernated_notification": "Proyecto hibernado", + "settings_project_now_private_notification": "El proyecto es ahora privado", + "settings_project_now_public_notification": "El proyecto es ahora público", + "settings_project_page_title": "Configuración del proyecto", + "settings_project_title": "Proyecto", + "settings_project_url_description": "Su proyecto estará disponible en https://ui.rilldata.com/{org}/{slug}.", + "settings_project_visibility_private": "Este proyecto es actualmente Privado. Solo los miembros de la organización pueden acceder a este proyecto.", + "settings_project_visibility_public": "Este proyecto es actualmente Público. Cualquier persona con la URL puede ver este proyecto.", + "settings_project_visibility_title": "Visibilidad del proyecto", + "settings_remove_button": "Eliminar", + "settings_rename_button": "Renombrar", + "settings_rename_project_title": "Renombrar proyecto", + "settings_save_button": "Guardar", + "settings_thumbnail_description": "Haga clic para subir su miniatura. La miniatura se usará al compartir enlaces a Rill en aplicaciones como Slack.", + "settings_thumbnail_title": "Miniatura", + "settings_updated_org_notification": "Organización actualizada", + "settings_updated_project_notification": "Proyecto actualizado", + "settings_upload_org_image_title": "Subir {label} de la organización", + "settings_usage_coming_soon": "Las métricas detalladas de uso estarán disponibles próximamente.", + "settings_usage_description": "Vea el uso de slots, consumo de almacenamiento y detalles de facturación de su organización.", + "settings_usage_title": "Uso", + "settings_visibility_update_failed": "Error al actualizar la visibilidad", + "share_limited_view": "Vista limitada. Para acceso completo y todas las funciones, visita el {link}.", + "share_original_dashboard": "dashboard original", + "snooze_off": "Desactivado", + "status_action_describe": "Describir", + "status_action_full_refresh": "Actualización completa", + "status_action_incremental_refresh": "Actualización incremental", + "status_action_refresh_errored_partitions": "Actualizar particiones con error", + "status_action_view_logs": "Ver registros", + "status_action_view_partitions": "Ver particiones", + "status_all_types": "Todos los tipos", + "status_cancel": "Cancelar", + "status_checking_errors": "Verificando errores...", + "status_clear": "Limpiar", + "status_clone_description": "Clona este proyecto para desarrollar en local.", + "status_column_database_size": "Tamaño en base de datos", + "status_column_last_refresh": "Última actualización", + "status_column_model_name": "Nombre del modelo", + "status_column_name": "Nombre", + "status_column_next_refresh": "Próxima actualización", + "status_column_table_name": "Nombre de tabla", + "status_column_type": "Tipo", + "status_complete": "Completo", + "status_compute_unit": "Unidad de cómputo", + "status_compute_units": "Unidades de cómputo", + "status_connection_failed": "Conexión fallida: {error}", + "status_copied_error_message": "Mensaje de error copiado al portapapeles", + "status_copied_test_error": "Error de prueba copiado al portapapeles", + "status_data_accessible": "Datos accesibles", + "status_data_size": "Tamaño de datos", + "status_database_size": "Tamaño de base de datos", + "status_deploy_deleted": "Eliminado", + "status_deploy_deleting": "Eliminando", + "status_deploy_error": "Error", + "status_deploy_not_deployed": "Sin desplegar", + "status_deploy_pending": "Pendiente", + "status_deploy_ready": "Listo", + "status_deploy_stopped": "Detenido", + "status_deploy_stopping": "Deteniendo", + "status_deploy_updating": "Actualizando", + "status_deployment": "Despliegue", + "status_download_project": "Descargar proyecto", + "status_error_loading_resources": "Error al cargar recursos", + "status_error_loading_tables": "Error al cargar tablas", + "status_error_plural": "errores", + "status_error_singular": "error", + "status_errors": "Errores", + "status_external_tables_section": "Tablas externas", + "status_filter_error": "Error", + "status_filter_ok": "OK", + "status_filter_warn": "Advertencia", + "status_full_refresh": "Actualización completa", + "status_full_refresh_warning": "⚠️ Advertencia: Una actualización completa reingestará TODOS los datos desde cero. Esta operación puede tomar un tiempo considerable y actualizará todos los recursos dependientes. Solo procede si estás seguro de que es necesario.", + "status_incremental_refresh": "Actualización incremental", + "status_incremental_refresh_description": "Actualizar este recurso actualizará todos los recursos dependientes.", + "status_label_ai_connector": "Conector de IA", + "status_label_branch": "Rama", + "status_label_cluster_size": "Tamaño del clúster", + "status_label_environment": "Entorno", + "status_label_last_synced": "Última sincronización", + "status_label_olap_engine": "Motor OLAP", + "status_label_repo": "Repositorio", + "status_label_runtime": "Entorno de ejecución", + "status_label_status": "Estado", + "status_learn_about_external_olap": "Aprende a conectar motores OLAP externos", + "status_learn_more": "Más información ->", + "status_levels_selected": "{first}, +{count} otro(s)", + "status_load_more_tables": "Cargar más tablas", + "status_loading": "Cargando...", + "status_loading_models": "Cargando modelos", + "status_loading_resources": "Cargando recursos...", + "status_loading_tables": "Cargando tablas...", + "status_loading_tables_short": "Cargando tablas", + "status_logs_all_levels": "Todos los niveles", + "status_logs_connecting": "Conectando", + "status_logs_connection_failed": "Conexión fallida", + "status_logs_disconnected": "Desconectado", + "status_logs_idle": "Inactivo", + "status_logs_level_debug": "Depuración", + "status_logs_level_error": "Error", + "status_logs_level_info": "Información", + "status_logs_level_warn": "Advertencia", + "status_logs_live": "En vivo", + "status_logs_no_match": "Ningún registro coincide con los filtros actuales", + "status_logs_retry": "Reintentar", + "status_logs_waiting": "Esperando registros...", + "status_model_name": "Nombre del modelo", + "status_model_partitions": "Particiones del modelo", + "status_model_reconciling": "El modelo se está reconciliando actualmente", + "status_models_created_in_developer": "Los modelos se crean en Rill Developer.", + "status_models_section": "Modelos", + "status_nav_analytics": "Analítica", + "status_nav_branches": "Ramas", + "status_nav_logs": "Registros", + "status_nav_overview": "Resumen", + "status_nav_resources": "Recursos", + "status_nav_tables": "Tablas", + "status_no_errors": "No se detectaron errores.", + "status_no_external_tables": "Sin tablas externas", + "status_no_external_tables_match_filters": "Ninguna tabla externa coincide con los filtros actuales", + "status_no_models": "Sin modelos", + "status_no_models_match_filters": "Ningún modelo coincide con los filtros actuales", + "status_no_parse_errors": "Sin errores de análisis", + "status_no_resource_data": "No hay datos del recurso disponibles", + "status_no_resources": "No se encontraron recursos.", + "status_no_resources_match_filters": "Ningún recurso coincide con los filtros actuales", + "status_no_tables": "No se encontraron tablas.", + "status_note": "Nota:", + "status_one_level": "1 nivel", + "status_owned_by_other": "Propiedad de otro usuario", + "status_owned_by_you": "De tu propiedad", + "status_page_title": "Estado del proyecto", + "status_parse_error": "Error de análisis", + "status_parse_errors": "Errores de análisis", + "status_parse_errors_title": "Errores de análisis", + "status_reconciling": "Reconciliando", + "status_refresh_all": "Actualizar todo", + "status_refresh_all_confirm_body": "Se actualizarán todas las fuentes y modelos del proyecto.", + "status_refresh_all_confirm_tip": "Para actualizar un solo recurso, desplázate hasta la fuente o modelo, haz clic en el botón '...' y selecciona la opción de actualización.", + "status_refresh_all_confirm_title": "¿Actualizar todas las fuentes y modelos?", + "status_refresh_all_sources_models": "Actualizar todas las fuentes y modelos", + "status_refresh_errored_confirm_body": "Se reejecutarán todas las particiones que fallaron en su última ejecución. La actualización se realizará en segundo plano.", + "status_refresh_errored_confirm_title": "¿Actualizar particiones con error de {modelName}?", + "status_refreshing": "Actualizando...", + "status_resource_reconciling": "El recurso se está reconciliando", + "status_rill_managed": "Gestionado por Rill", + "status_table": "Tabla", + "status_table_name": "Nombre de tabla", + "status_table_plural": "Tablas", + "status_table_singular": "Tabla", + "status_tables": "Tablas", + "status_unable_to_check_errors": "No se pudieron verificar los errores.", + "status_view_all": "Ver todo", + "status_view_plural": "Vistas", + "status_view_singular": "Vista", + "status_views": "Vistas", + "status_yes_refresh": "Sí, actualizar", + "theme_beta": "Beta", + "theme_dark": "Oscuro", + "theme_label": "Tema", + "theme_light": "Claro", + "theme_system": "Sistema", + "time_1_day_ago": "hace 1 día", + "time_1_hour_ago": "hace 1 hora", + "time_1_minute_ago": "hace 1 minuto", + "time_1_month_ago": "hace 1 mes", + "time_1_week_ago": "hace 1 semana", + "time_1_year_ago": "hace 1 año", + "time_ago": "hace {duration}", + "time_all_time": "Todo el período", + "time_comparing": "Comparando", + "time_comparison_previous_day": "Día anterior", + "time_comparison_previous_period": "Período anterior", + "time_custom": "Personalizado", + "time_custom_range": "Rango personalizado", + "time_enter_time_range": "Ingresa un rango de tiempo", + "time_from_now": "en {duration}", + "time_grain_by": "por", + "time_grain_complete": "completo", + "time_grain_day": "día", + "time_grain_days": "días", + "time_grain_hour": "hora", + "time_grain_hours": "horas", + "time_grain_minute": "minuto", + "time_grain_minutes": "minutos", + "time_grain_month": "mes", + "time_grain_months": "meses", + "time_grain_quarter": "trimestre", + "time_grain_quarters": "trimestres", + "time_grain_time": "Tiempo", + "time_grain_week": "semana", + "time_grain_weeks": "semanas", + "time_grain_year": "año", + "time_grain_years": "años", + "time_just_now": "Ahora mismo", + "time_last_duration": "Últimos {duration}", + "time_month_to_date": "Mes actual", + "time_n_days_ago": "hace {count} días", + "time_n_hours_ago": "hace {count} horas", + "time_n_minutes_ago": "hace {count} minutos", + "time_n_months_ago": "hace {count} meses", + "time_n_weeks_ago": "hace {count} semanas", + "time_n_years_ago": "hace {count} años", + "time_no_comparison_dimension": "Sin dimensión de comparación", + "time_no_comparison_period": "sin período de comparación", + "time_previous_month": "Mes anterior", + "time_previous_quarter": "Trimestre anterior", + "time_previous_week": "Semana anterior", + "time_previous_year": "Año anterior", + "time_quarter_to_date": "Trimestre actual", + "time_range_grain_to_date": "{grain} hasta la fecha", + "time_range_last_n_grains": "últimos {count} {grains}", + "time_range_next_grain": "siguiente {grain}", + "time_range_next_n_grains": "siguientes {count} {grains}", + "time_range_previous_grain": "{grain} anterior", + "time_range_this_grain": "{grain} actual", + "time_ref_complete": "completo", + "time_ref_complete_data": "datos completos", + "time_ref_current": "actual", + "time_ref_earliest": "más antiguo", + "time_ref_latest": "más reciente", + "time_ref_now": "ahora", + "time_relative_hours_short": "hace {count}h", + "time_relative_minutes_short": "hace {count}m", + "time_relative_now": "ahora", + "time_today": "Hoy", + "time_unable_to_parse": "No se pudo interpretar el rango de tiempo", + "time_vs": "vs", + "time_week_to_date": "Semana actual", + "time_year_to_date": "Año actual", + "time_yesterday": "Ayer", + "users_access_changed_everyone": "El acceso al proyecto cambió a todos", + "users_access_changed_invite_only": "El acceso al proyecto cambió a solo por invitación", + "users_access_level": "Nivel de acceso", + "users_add_guest": "Agregar invitado", + "users_add_guests_button": "Agregar invitados", + "users_add_guests_description": "Los invitados solo pueden acceder a proyectos provisionados con roles asignados. No tienen acceso a toda la organización.", + "users_add_guests_title": "Agregar usuarios invitados", + "users_add_users": "Agregar usuarios", + "users_added_groups_count": "Se agregaron {count} grupos", + "users_already_member": "{emails} ya es miembro de esta organización", + "users_and_more": "y {count} más", + "users_billing_change_role_desc": "Este usuario es actualmente el contacto de facturación. Para cambiar su rol, asigne otro administrador como contacto de facturación primero.", + "users_billing_change_role_title": "Asigne un nuevo contacto de facturación primero para cambiar el rol de este usuario", + "users_billing_remove_desc": "Este usuario es el contacto de facturación actual y no puede ser eliminado. Para continuar, asigne otro administrador como contacto de facturación.", + "users_billing_remove_title": "Asigne un nuevo contacto de facturación primero para eliminar este usuario", + "users_cancel": "Cancelar", + "users_change_billing_contact": "Cambiar contacto de facturación", + "users_convert": "Convertir", + "users_convert_to_member": "Convertir a miembro", + "users_convert_user_to_role": "Convertir {user} a {role}", + "users_copy_url": "Copiar URL", + "users_create": "Crear", + "users_email_or_group_placeholder": "Correo o grupo, separados por comas", + "users_email_placeholder": "Agregar correos, separados por comas", + "users_error": "Error", + "users_error_loading_members": "Error al cargar miembros de la organización:", + "users_error_removing": "Error al eliminar usuario de la organización", + "users_error_removing_user": "Error al eliminar usuario", + "users_error_updating_role": "Error al actualizar el rol del usuario", + "users_error_upgrading_role": "Error al promover el rol del usuario", + "users_everyone_at_org": "Todos en {organization}", + "users_failed_add_groups": "Error al agregar grupos: {groups}", + "users_failed_invite": "Error al invitar a {emails}", + "users_failed_invite_users": "Error al invitar usuarios: {emails}", + "users_failed_load_projects": "Error al cargar proyectos", + "users_failed_load_users": "Error al cargar usuarios", + "users_filter_admins": "Administradores", + "users_filter_all": "Todos", + "users_filter_all_roles": "Todos los roles", + "users_filter_all_users": "Todos los usuarios", + "users_filter_editors": "Editores", + "users_filter_members": "Miembros", + "users_filter_pending_invites": "Invitaciones pendientes", + "users_filter_viewers": "Lectores", + "users_form_name": "Nombre", + "users_form_untitled": "Sin título", + "users_form_users": "Usuarios", + "users_general_access": "Acceso general", + "users_group_count": "{count} Grupos", + "users_guest_upgraded": "Invitado promovido a miembro con rol {role}", + "users_guest_upgraded_to": "Invitado promovido a {role}", + "users_guests_invited_success": "Se invitaron {count} invitados como {role}", + "users_invalid_email": "Correo electrónico no válido", + "users_invite": "Invitar", + "users_invite_only": "Solo por invitación", + "users_invited_count": "Se invitaron {count} personas", + "users_invited_success": "Se invitaron {count} personas como {role} exitosamente", + "users_learn_more_sharing": "Más información sobre compartir", + "users_loading": "Cargando...", + "users_loading_more": "Cargando más...", + "users_member_count": "{count} miembros", + "users_no_groups": "Sin grupos", + "users_no_projects": "Sin proyectos", + "users_no_users": "Sin usuarios", + "users_only_admins_access": "Solo administradores y usuarios invitados pueden acceder", + "users_org_members_access": "Los miembros de la organización pueden acceder", + "users_page_title": "Gestionar usuarios", + "users_pending_invitation": "Invitación pendiente", + "users_project_access": "Acceso al proyecto", + "users_project_count": "{count} Proyectos", + "users_projects_count": "{count} Proyectos", + "users_remove": "Eliminar", + "users_remove_confirm_desc": "Este usuario ya no podrá acceder a la organización.", + "users_remove_confirm_title": "¿Eliminar usuario de la organización?", + "users_removed": "Usuario eliminado", + "users_removed_from_org": "Usuario eliminado de la organización", + "users_retry": "Reintentar", + "users_role_updated": "Rol del usuario actualizado", + "users_save": "Guardar", + "users_searching": "Buscando...", + "users_section_groups": "GRUPOS", + "users_section_guests": "INVITADOS", + "users_section_members": "MIEMBROS", + "users_select_projects": "Seleccionar proyectos", + "users_tab_groups": "Grupos ({count})", + "users_tab_guests": "Invitados ({count})", + "users_tab_members": "Miembros ({count})", + "users_table_empty": "No se encontraron usuarios", + "users_table_header_groups": "Grupos", + "users_table_header_org_role": "Rol en la organización", + "users_table_header_projects": "Proyectos", + "users_table_header_user": "Usuario", + "users_upgrade_confirm_desc": "Promover un invitado a {role} le otorgará acceso a todos los proyectos abiertos en la organización. ¿Desea promover este usuario invitado a {role}?", + "users_upgrade_confirm_title": "¿Promover invitado a {role}?", + "users_url_copied": "URL copiada", + "users_user_count": "{count} Usuarios", + "users_yes_remove": "Sí, eliminar", + "users_yes_upgrade": "Sí, promover" +} diff --git a/web-common/package.json b/web-common/package.json index 5463152b988b..b585ef565ac0 100644 --- a/web-common/package.json +++ b/web-common/package.json @@ -32,6 +32,7 @@ "@dagrejs/dagre": "^1.1.3", "@exodus/schemasafe": "^1.3.0", "@floating-ui/dom": "^1.7.4", + "@inlang/plugin-message-format": "^4.4.0", "@replit/codemirror-indentation-markers": "^6.5.3", "@sveltejs/kit": "^2.55.0", "@tanstack/svelte-query": "~5.76.0", diff --git a/web-common/project.inlang/settings.json b/web-common/project.inlang/settings.json new file mode 100644 index 000000000000..df0bfdbab5cc --- /dev/null +++ b/web-common/project.inlang/settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://inlang.com/schema/project-settings", + "baseLocale": "en", + "locales": ["en", "es"], + "modules": ["../node_modules/@inlang/plugin-message-format/dist/index.js"], + "plugin.inlang.messageFormat": { + "pathPattern": "./messages/{locale}.json" + } +} From b50e377bd1b88bfb298beb936d2733e80bfa08c5 Mon Sep 17 00:00:00 2001 From: dfliess Date: Mon, 29 Jun 2026 09:52:46 +0200 Subject: [PATCH 2/4] feat(i18n): localize shared viewer components (web-common) EN/ES Instrument all user-facing strings in web-common with Paraglide messages: - Dashboard viewer: KPI, time series, leaderboard, big numbers - Explore: measures/dimensions dropdowns, tags, search, grain selector - Canvas: inspector, alignment, sparkline, error states - Chat: input, thinking block, feedback, history, sharing, error messages - Time controls: grain names, range labels, comparisons, relative time - Filters: dimension/measure headers, pin/required, advanced - Bookmarks: popover, form, home bookmark, categories - Alerts/Reports: forms, delivery tabs, criteria, intervals, snooze - Shared components: search, select, combobox, dialog, theme toggle - Status tables: resource tables, model actions, refresh dialogs - Connectors: database explorer, schema entry --- web-common/src/components/ErrorPage.svelte | 7 +- .../src/components/combobox/Combobox.svelte | 11 +- .../draggable-list/DraggableList.svelte | 3 +- web-common/src/components/forms/Select.svelte | 5 +- .../components/i18n/LanguageSwitcher.spec.ts | 54 +++++++ .../components/i18n/LanguageSwitcher.svelte | 39 +++++ .../i18n/__fixtures__/ClickableItem.svelte | 9 ++ .../i18n/__fixtures__/SlotPassthrough.svelte | 6 + .../menu/DashboardMetricsDraggableList.svelte | 107 +++++++++---- .../menu/DashboardMetricsTagRow.svelte | 22 ++- .../menu/LeaderboardAdvancedActions.svelte | 3 +- .../LeaderboardMeasureNamesDropdown.svelte | 13 +- .../components/menu/TagFilterBanner.svelte | 7 +- .../src/components/search/Search.svelte | 12 +- .../SearchableMenuContent.svelte | 3 +- .../table-toolbar/TableToolbarSearch.svelte | 7 +- .../src/features/alerts/AlertForm.svelte | 25 +-- .../features/alerts/AlertPreviewTable.svelte | 5 +- .../src/features/alerts/create-alert-utils.ts | 4 +- .../AlertDialogCriteriaTab.svelte | 7 +- .../alerts/criteria-tab/AlertPreview.svelte | 5 +- .../alerts/criteria-tab/CriteriaForm.svelte | 15 +- .../alerts/criteria-tab/CriteriaGroup.svelte | 5 +- .../alerts/data-tab/AlertDialogDataTab.svelte | 21 +-- .../alerts/data-tab/DataPreview.svelte | 3 +- .../alerts/data-tab/NoFiltersSelected.svelte | 8 +- .../AlertDialogDeliveryTab.svelte | 46 +++--- .../features/alerts/delivery-tab/intervals.ts | 40 ++--- .../features/alerts/delivery-tab/snooze.ts | 47 +++--- .../authentication/LocalAvatarButton.svelte | 2 + .../canvas/AddComponentDropdown.svelte | 41 +++-- .../src/features/canvas/CanvasBuilder.svelte | 11 +- .../canvas/CanvasDashboardEmbed.svelte | 5 +- .../features/canvas/CanvasEditButton.svelte | 5 +- .../features/canvas/CanvasLoadingState.svelte | 5 +- .../features/canvas/CreateCanvasDialog.svelte | 12 +- .../features/canvas/EditableCanvasRow.svelte | 3 +- .../src/features/canvas/ElementDivider.svelte | 8 +- .../features/canvas/StaticCanvasRow.svelte | 3 +- .../src/features/canvas/chat-context.ts | 6 +- .../components/SaveDefaultsButton.svelte | 15 +- .../canvas/components/charts/BaseChart.ts | 14 +- .../custom-chart/AgenticChartPrompt.svelte | 13 +- .../components/charts/custom-chart/index.ts | 18 ++- .../canvas/components/charts/index.ts | 6 + .../charts/variants/CartesianChart.ts | 109 +++++++------ .../charts/variants/CircularChart.ts | 95 +++++------ .../components/charts/variants/ComboChart.ts | 121 +++++++------- .../components/charts/variants/FunnelChart.ts | 149 +++++++++--------- .../charts/variants/HeatmapChart.ts | 121 +++++++------- .../charts/variants/ScatterPlotChart.ts | 105 ++++++------ .../features/canvas/components/image/index.ts | 10 +- .../canvas/components/kpi-grid/index.ts | 23 ++- .../features/canvas/components/kpi/KPI.svelte | 3 +- .../canvas/components/leaderboard/index.ts | 14 +- .../canvas/components/markdown/index.ts | 8 +- .../features/canvas/components/pivot/index.ts | 32 ++-- .../src/features/canvas/components/util.ts | 66 +++++--- .../filters/CanvasComparisonPill.svelte | 5 +- .../canvas/filters/CanvasFilters.svelte | 7 +- .../canvas/inspector/AIGenerateButton.svelte | 9 +- .../canvas/inspector/AlignmentInput.svelte | 17 +- .../canvas/inspector/ComponentTabs.svelte | 3 +- .../canvas/inspector/LabelsInput.svelte | 9 +- .../canvas/inspector/PageEditor.svelte | 13 +- .../canvas/inspector/SparklineInput.svelte | 7 +- .../canvas/inspector/TableTypeSelector.svelte | 11 +- .../inspector/chart/ChartTypeSelector.svelte | 3 +- .../inspector/chart/MetricsSQLInput.svelte | 3 +- .../field-config/ColorPaletteSelector.svelte | 21 +-- .../field-config/ColorRangeSelector.svelte | 55 ++++--- .../field-config/FieldConfigPopover.svelte | 41 ++--- .../chart/field-config/MarkTypeToggle.svelte | 7 +- .../chart/field-config/SortConfig.svelte | 3 +- .../filters/DimensionFiltersInput.svelte | 5 +- .../inspector/filters/TimeFiltersInput.svelte | 3 +- .../chat/core/feedback/FeedbackButtons.svelte | 11 +- .../chat/core/feedback/FeedbackModal.svelte | 15 +- .../chat/core/input/ChatFooter.svelte | 9 +- .../features/chat/core/input/ChatInput.svelte | 5 +- .../features/chat/core/messages/Error.svelte | 3 +- .../chat/core/messages/Messages.svelte | 7 +- .../messages/thinking/ThinkingBlock.svelte | 21 +-- .../fullpage/ConversationSidebar.svelte | 9 +- .../sidebar/ConversationHistoryMenu.svelte | 10 +- .../chat/layouts/sidebar/SidebarHeader.svelte | 11 +- .../layouts/sidebar/conversation-grouping.ts | 23 +++ .../chat/share/ShareChatPopover.svelte | 20 +-- .../explorer/DatabaseExplorer.svelte | 3 +- .../explorer/DatabaseSchemaEntry.svelte | 5 +- .../big-number/BigNumberTooltipContent.svelte | 7 +- .../big-number/MeasureBigNumber.svelte | 23 +-- .../big-number/MeasuresContainer.svelte | 5 +- .../src/features/dashboards/chat-context.ts | 6 +- .../GlobalDimensionSearch.svelte | 3 +- .../GlobalDimensionSearchResults.svelte | 3 +- .../dimension-table/DimensionDisplay.svelte | 3 +- .../dimension-table/DimensionHeader.svelte | 5 +- .../dimension-table/DimensionTable.svelte | 5 +- .../DimensionValueHeader.svelte | 3 +- .../dimension-table/dimension-table-utils.ts | 7 +- .../errors/InlineErrorIndicator.svelte | 14 +- .../dashboards/filters/AdvancedFilter.svelte | 5 +- .../filters/CanvasFilterButton.svelte | 11 +- .../filters/CanvasFilterChipsReadOnly.svelte | 3 +- .../dashboards/filters/FilterButton.svelte | 11 +- .../filters/FilterChipsReadOnly.svelte | 3 +- .../dashboards/filters/Filters.svelte | 10 +- .../dashboards/filters/PinButton.svelte | 6 +- .../dashboards/filters/RequiredButton.svelte | 6 +- .../filters/TimeRangeReadOnly.svelte | 7 +- .../DimensionFilterChipBody.svelte | 15 +- .../DimensionFilterFooter.svelte | 13 +- .../filters/dimension-filters/constants.ts | 29 +++- .../filters/dimension-filters/helpers.ts | 9 +- .../measure-filters/MeasureFilter.svelte | 13 +- .../measure-filters/MeasureFilterBody.svelte | 8 +- .../measure-filters/MeasureFilterForm.svelte | 29 ++-- .../measure-filters/measure-filter-options.ts | 54 +++++-- .../ViewAsButton.svelte | 13 +- .../leaderboard/DimensionCompareMenu.svelte | 5 +- .../dashboards/leaderboard/Leaderboard.svelte | 7 +- .../leaderboard/LeaderboardCell.svelte | 8 +- .../leaderboard/LeaderboardDisplay.svelte | 6 +- .../leaderboard/LeaderboardHeader.svelte | 16 +- .../dashboards/listing/DashboardsTable.svelte | 9 +- .../DashboardsTableCompositeCell.svelte | 8 +- .../features/dashboards/pivot/AddField.svelte | 15 +- .../features/dashboards/pivot/DragList.svelte | 15 +- .../pivot/PivotAutoArrangeZone.svelte | 44 ++++-- .../dashboards/pivot/PivotChip.svelte | 16 +- .../dashboards/pivot/PivotDisplay.svelte | 3 +- .../dashboards/pivot/PivotDrag.svelte | 13 +- .../dashboards/pivot/PivotEmpty.svelte | 28 ++-- .../dashboards/pivot/PivotError.svelte | 5 +- .../pivot/PivotExpandableCell.svelte | 3 +- .../dashboards/pivot/PivotHeader.svelte | 11 +- .../dashboards/pivot/PivotSidebar.svelte | 27 +++- .../dashboards/pivot/PivotTable.svelte | 5 +- .../dashboards/pivot/PivotTagRow.svelte | 49 +++--- .../dashboards/pivot/PivotToolbar.svelte | 27 ++-- .../pivot/ReplacePivotDialog.svelte | 10 +- .../pivot/pivot-column-definition.ts | 4 +- .../features/dashboards/pivot/pivot-export.ts | 5 + .../rows-viewer/RowsViewerAccordion.svelte | 8 +- .../actions/dimension-filters.ts | 5 +- .../features/dashboards/tab-bar/TabBar.svelte | 5 +- .../time-controls/ComparisonSelector.svelte | 13 +- .../time-controls/TimeGrainSelector.svelte | 20 +-- .../comparison-pill/ComparisonPill.svelte | 5 +- .../time-controls/new-time-controls.ts | 57 +++++-- .../components/CalendarPlusDateInput.svelte | 5 +- .../super-pill/components/Comparison.svelte | 12 +- .../super-pill/components/Metadata.svelte | 7 +- .../super-pill/components/RangePicker.svelte | 3 +- .../components/TimeRangeMenu.svelte | 7 +- .../components/TimeRangeSearch.svelte | 7 +- .../super-pill/components/Zone.svelte | 16 +- .../super-pill/components/ZoneContent.svelte | 11 +- .../PrimaryRangeTooltip.svelte | 5 +- .../new-time-dropdown/RangePickerV2.svelte | 19 ++- .../TruncationSelector.svelte | 79 +++++----- .../time-dimension-details/TDDHeader.svelte | 3 +- .../TimeDimensionDisplay.svelte | 25 +-- .../charts/ChartTypeSelector.svelte | 26 +-- .../time-dimension-data-store.ts | 5 +- .../time-series/BackToExplore.svelte | 3 +- .../time-series/ChartInteractions.svelte | 7 +- .../time-series/ChartSettingsMenu.svelte | 7 +- .../MetricsTimeSeriesCharts.svelte | 33 +++- .../time-series/ScreenshotContainer.svelte | 13 +- .../measure-chart/ComparisonTooltip.svelte | 3 +- .../MeasureChartAnnotationPopover.svelte | 3 +- .../measure-chart/MeasureChartBody.svelte | 3 +- .../MeasureChartHoverTooltip.svelte | 3 +- .../dashboards/toolbars/ExcludeButton.svelte | 15 +- .../dashboards/toolbars/SearchButton.svelte | 3 +- .../toolbars/SelectAllButton.svelte | 9 +- .../toolbars/StartPivotButton.svelte | 3 +- .../url-state/time-ranges/RillTime.ts | 49 ++++-- .../ResourceTypeBadge.svelte | 10 +- .../explores/explore-link/ExploreLink.svelte | 9 +- .../partitions/PartitionsBrowser.svelte | 1 - .../workspace/ModelWorkspaceCTAs.svelte | 3 +- .../src/features/project/chat-context.ts | 10 +- .../projects/status/ActionsCell.svelte | 7 +- .../features/projects/status/NameCell.svelte | 3 +- .../RefreshResourceConfirmDialog.svelte | 14 +- .../status/ResourceErrorMessage.svelte | 9 +- .../projects/status/ResourceSpecDialog.svelte | 3 +- .../status/overview/OverviewCard.svelte | 4 +- .../status/tables/ExternalTablesTable.svelte | 7 +- .../status/tables/MaterializationCell.svelte | 3 +- .../status/tables/ModelActionsCell.svelte | 13 +- .../tables/ModelPartitionsDialog.svelte | 4 +- .../projects/status/tables/ModelsTable.svelte | 11 +- .../RefreshErroredPartitionsDialog.svelte | 10 +- ...eshAllSourcesAndModelsConfirmDialog.svelte | 13 +- .../features/resources/ResourceError.svelte | 8 +- .../resources/ResourceListToolbar.svelte | 3 +- .../resources/ResourcesFilterableTable.svelte | 14 +- .../BaseScheduledReportForm.svelte | 82 +++++----- .../scheduled-reports/FiltersForm.svelte | 9 +- .../scheduled-reports/ScheduleForm.svelte | 46 +++--- .../ScheduledReportDialog.svelte | 36 +++-- .../scheduled-reports/fields/FieldList.svelte | 11 +- .../fields/RowsAndColumnsForm.svelte | 9 +- .../features/scheduled-reports/time-utils.ts | 9 +- .../src/features/themes/ThemeToggle.svelte | 11 +- .../features/workspaces/CrumbTrigger.svelte | 3 +- .../features/workspaces/VisualMetrics.svelte | 3 +- .../src/layout/navigation/Footer.svelte | 14 +- .../src/layout/navigation/Navigation.svelte | 5 +- .../navigation/SurfaceControlButton.svelte | 3 +- .../src/layout/workspace/Inspector.svelte | 3 +- .../i18n/__tests__/catalog-integrity.spec.ts | 66 ++++++++ web-common/src/lib/i18n/document-locale.ts | 18 +++ web-common/src/lib/i18n/escape-html.ts | 9 ++ web-common/src/lib/i18n/index.ts | 14 ++ web-common/src/lib/i18n/luxon-locale.ts | 6 + web-common/src/lib/i18n/normalize-locale.ts | 14 ++ web-common/src/lib/time/comparisons/index.ts | 13 +- web-common/src/lib/time/config.ts | 45 ++++-- web-common/src/lib/time/new-grains.ts | 67 ++++++++ web-common/src/lib/time/ranges/iso-ranges.ts | 3 +- web-common/src/lib/time/relative-time.ts | 42 +++-- 226 files changed, 2412 insertions(+), 1389 deletions(-) create mode 100644 web-common/src/components/i18n/LanguageSwitcher.spec.ts create mode 100644 web-common/src/components/i18n/LanguageSwitcher.svelte create mode 100644 web-common/src/components/i18n/__fixtures__/ClickableItem.svelte create mode 100644 web-common/src/components/i18n/__fixtures__/SlotPassthrough.svelte create mode 100644 web-common/src/lib/i18n/__tests__/catalog-integrity.spec.ts create mode 100644 web-common/src/lib/i18n/document-locale.ts create mode 100644 web-common/src/lib/i18n/escape-html.ts create mode 100644 web-common/src/lib/i18n/index.ts create mode 100644 web-common/src/lib/i18n/luxon-locale.ts create mode 100644 web-common/src/lib/i18n/normalize-locale.ts diff --git a/web-common/src/components/ErrorPage.svelte b/web-common/src/components/ErrorPage.svelte index 964140afb376..f7937b4bec75 100644 --- a/web-common/src/components/ErrorPage.svelte +++ b/web-common/src/components/ErrorPage.svelte @@ -6,6 +6,7 @@ import CtaMessage from "@rilldata/web-common/components/calls-to-action/CTAMessage.svelte"; import { isEmbedPage } from "../layout/navigation/navigation-utils"; import AlertCircleOutline from "./icons/AlertCircleOutline.svelte"; + import * as m from "@rilldata/web-common/paraglide/messages.js"; export let statusCode: number | null | undefined = undefined; export let header: string; @@ -32,7 +33,7 @@
{#if !fatal && !onEmbedPage} - + {/if}
{/if} @@ -43,9 +44,9 @@ onclick={() => (showDetail = !showDetail)} > {#if !showDetail} - Show details + {m.error_show_details()} {:else} - Hide details + {m.error_hide_details()} {/if} {#if showDetail} diff --git a/web-common/src/components/combobox/Combobox.svelte b/web-common/src/components/combobox/Combobox.svelte index 608e88d6d8b8..f65dbdec6cda 100644 --- a/web-common/src/components/combobox/Combobox.svelte +++ b/web-common/src/components/combobox/Combobox.svelte @@ -1,4 +1,5 @@ + + + {m.language_switcher_label()} + + {#each LOCALES as loc} + selectLocale(loc.code)} + > + {loc.label()} + + {/each} + + diff --git a/web-common/src/components/i18n/__fixtures__/ClickableItem.svelte b/web-common/src/components/i18n/__fixtures__/ClickableItem.svelte new file mode 100644 index 000000000000..5ee7dbf2a6db --- /dev/null +++ b/web-common/src/components/i18n/__fixtures__/ClickableItem.svelte @@ -0,0 +1,9 @@ + + + diff --git a/web-common/src/components/i18n/__fixtures__/SlotPassthrough.svelte b/web-common/src/components/i18n/__fixtures__/SlotPassthrough.svelte new file mode 100644 index 000000000000..fc9910864ccc --- /dev/null +++ b/web-common/src/components/i18n/__fixtures__/SlotPassthrough.svelte @@ -0,0 +1,6 @@ + + +{@render children?.()} diff --git a/web-common/src/components/menu/DashboardMetricsDraggableList.svelte b/web-common/src/components/menu/DashboardMetricsDraggableList.svelte index 10be1ed7d26e..b1147564262a 100644 --- a/web-common/src/components/menu/DashboardMetricsDraggableList.svelte +++ b/web-common/src/components/menu/DashboardMetricsDraggableList.svelte @@ -11,6 +11,7 @@ } from "@rilldata/web-common/runtime-client"; import * as Tooltip from "@rilldata/web-common/components/tooltip-v2"; import Resizer from "@rilldata/web-common/layout/Resizer.svelte"; + import * as m from "@rilldata/web-common/paraglide/messages.js"; import { Button } from "../button"; import Search from "../search/Search.svelte"; import DashboardMetricsTagRow from "./DashboardMetricsTagRow.svelte"; @@ -48,10 +49,24 @@ $: allItemsMap = new Map(allItems.map((item) => [item.name, item])); $: numAvailable = allItems?.length ?? 0; $: numShown = selectedItems?.filter((x) => x).length ?? 0; - $: numShownString = - numAvailable === numShown ? "All" : `${numShown} of ${numAvailable}`; - $: tooltipText = `Choose ${type === "measure" ? "measures" : "dimensions"} to display`; - $: pluralLabel = type === "measure" ? "measures" : "dimensions"; + $: buttonLabel = + numAvailable === numShown + ? type === "measure" + ? m.explore_all_measures() + : m.explore_all_dimensions() + : type === "measure" + ? m.explore_measures_count({ + count: String(numShown), + total: String(numAvailable), + }) + : m.explore_dimensions_count({ + count: String(numShown), + total: String(numAvailable), + }); + $: tooltipText = + type === "measure" + ? m.explore_choose_measures() + : m.explore_choose_dimensions(); $: tags = tagIndex.tags; @@ -135,7 +150,7 @@ {/if} @@ -280,19 +301,29 @@ {#snippet empty()} {searchActive && hasTags && filteredTags.length === 0 - ? `No ${pluralLabel} or tags found` + ? type === "measure" + ? m.explore_no_measures_or_tags() + : m.explore_no_dimensions_or_tags() : filterActive - ? `No ${pluralLabel} from this tag are shown` + ? type === "measure" + ? m.explore_no_measures_from_tag() + : m.explore_no_dimensions_from_tag() : searchActive - ? `No matching ${pluralLabel} shown` - : `No ${pluralLabel} shown`} + ? type === "measure" + ? m.explore_no_matching_measures_shown() + : m.explore_no_matching_dimensions_shown() + : type === "measure" + ? m.explore_no_measures_shown() + : m.explore_no_dimensions_shown()} {/snippet} {#snippet item({ item })} {@const itemData = allItemsMap.get(item.id)} {@const displayName = itemData?.displayName ?? - `Unknown ${type === "measure" ? "measure" : "dimension"}`} + (type === "measure" + ? m.explore_unknown_measure() + : m.explore_unknown_dimension())}
{#if itemData?.description || selectedItems.length === 1} @@ -321,7 +352,7 @@ class:pointer-events-none={selectedItems.length === 1} class:opacity-50={selectedItems.length === 1} - aria-label="Hide {displayName}" + aria-label={m.explore_hide_item({ name: displayName })} data-testid="toggle-visibility-button" type="button" > @@ -334,9 +365,9 @@ class="bg-popover text-fg-primary z-popover" > {#if selectedItems.length === 1} - Must show at least one {type === "measure" - ? "measure" - : "dimension"} + {type === "measure" + ? m.explore_must_show_one_measure() + : m.explore_must_show_one_dimension()} {:else} {itemData?.description} {/if} @@ -364,7 +395,7 @@ disabled={selectedItems.length === 1} class:pointer-events-none={selectedItems.length === 1} class:opacity-50={selectedItems.length === 1} - aria-label={`Hide ${displayName}`} + aria-label={m.explore_hide_item({ name: displayName })} type="button" > @@ -393,21 +424,23 @@

- Hidden {pluralLabel} + {type === "measure" + ? m.explore_hidden_measures() + : m.explore_hidden_dimensions()}

{#if !filterActive} {:else} {/if}
@@ -415,15 +448,21 @@ {#snippet empty()} {searchActive - ? `No matching hidden ${pluralLabel}` - : `No hidden ${pluralLabel}`} + ? type === "measure" + ? m.explore_no_matching_hidden_measures() + : m.explore_no_matching_hidden_dimensions() + : type === "measure" + ? m.explore_no_hidden_measures() + : m.explore_no_hidden_dimensions()} {/snippet} {#snippet item({ item })} {@const itemData = allItemsMap.get(item.id)} {@const displayName = itemData?.displayName ?? - `Unknown ${type === "measure" ? "measure" : "dimension"}`} + (type === "measure" + ? m.explore_unknown_measure() + : m.explore_unknown_dimension())}
@@ -443,7 +482,7 @@ e.stopPropagation(); handleHiddenItemClick({ item }); }} - aria-label={`Show ${displayName}`} + aria-label={m.explore_show_item({ name: displayName })} data-testid="toggle-visibility-button" type="button" > @@ -470,7 +509,7 @@ e.stopPropagation(); handleHiddenItemClick({ item }); }} - aria-label={`Show ${displayName}`} + aria-label={m.explore_show_item({ name: displayName })} data-testid="toggle-visibility-button" type="button" > @@ -490,13 +529,17 @@
- Clear the tag filter to reorder {pluralLabel}. + {type === "measure" + ? m.explore_clear_tag_filter_to_reorder_measures() + : m.explore_clear_tag_filter_to_reorder_dimensions()}
{:else if searchActive && !filterActive}
- Clear search to reorder {pluralLabel}. + {type === "measure" + ? m.explore_clear_search_to_reorder_measures() + : m.explore_clear_search_to_reorder_dimensions()}
{/if}
diff --git a/web-common/src/components/menu/DashboardMetricsTagRow.svelte b/web-common/src/components/menu/DashboardMetricsTagRow.svelte index 5db37761108e..efe94938f5c8 100644 --- a/web-common/src/components/menu/DashboardMetricsTagRow.svelte +++ b/web-common/src/components/menu/DashboardMetricsTagRow.svelte @@ -3,6 +3,7 @@ import EyeOffIcon from "@rilldata/web-common/components/icons/EyeInvisible.svelte"; import * as Tooltip from "@rilldata/web-common/components/tooltip-v2"; import { detectOverflow } from "@rilldata/web-common/lib/actions/detect-overflow"; + import * as m from "@rilldata/web-common/paraglide/messages.js"; import type { DimensionTag, TagVisibilityState } from "./tag-utils"; type Props = { @@ -40,7 +41,9 @@ type="button" class="flex items-center gap-x-2 flex-1 min-w-0 text-left" onclick={onSelect} - aria-label={`${selected ? "Clear filter" : "Filter by"} ${tag.name}`} + aria-label={selected + ? m.explore_clear_filter_tag({ tag: tag.name }) + : m.explore_filter_by_tag({ tag: tag.name })} aria-pressed={selected} > {visibility.visibleCount}/{visibility.totalCount} @@ -105,7 +111,7 @@ e.stopPropagation(); onShowOnly(); }} - aria-label={`Only show ${tag.name}`} + aria-label={m.explore_only_show_tag({ tag: tag.name })} > @@ -123,7 +129,7 @@ side="top" class="bg-popover text-fg-primary z-popover text-xs px-2 py-1" > - Only show this tag + {m.explore_only_show_this_tag()} @@ -136,7 +142,7 @@ e.stopPropagation(); onShowAll(); }} - aria-label={`Show all in ${tag.name}`} + aria-label={m.explore_show_all_in_named_tag({ tag: tag.name })} > @@ -145,7 +151,7 @@ side="top" class="bg-popover text-fg-primary z-popover text-xs px-2 py-1" > - Show all in tag + {m.explore_show_all_in_tag()} @@ -158,7 +164,7 @@ e.stopPropagation(); onHideAll(); }} - aria-label={`Hide all in ${tag.name}`} + aria-label={m.explore_hide_all_in_named_tag({ tag: tag.name })} > @@ -167,7 +173,7 @@ side="top" class="bg-popover text-fg-primary z-popover text-xs px-2 py-1" > - Hide all in tag + {m.explore_hide_all_in_tag()} diff --git a/web-common/src/components/menu/LeaderboardAdvancedActions.svelte b/web-common/src/components/menu/LeaderboardAdvancedActions.svelte index 4c2cdf6dcada..79cef834c309 100644 --- a/web-common/src/components/menu/LeaderboardAdvancedActions.svelte +++ b/web-common/src/components/menu/LeaderboardAdvancedActions.svelte @@ -10,6 +10,7 @@ import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers"; import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; import { useTimeControlStore } from "@rilldata/web-common/features/dashboards/time-controls/time-control-store"; + import * as m from "@rilldata/web-common/paraglide/messages.js"; const ctx = getStateManagers(); const { @@ -44,7 +45,7 @@ side="bottom" class="flex flex-row items-center justify-between gap-x-2 w-[286px] px-3.5 py-2.5" > - Show context for all measures + {m.explore_show_context_for_all_measures()} 1 - ? `${selectedMeasureNames.length} measures` + ? m.explore_n_measures({ count: String(selectedMeasureNames.length) }) : getMeasureDisplayText(leaderboardSortByMeasureName); function onToggleOff() { @@ -136,7 +137,7 @@
- Showing {showingMeasuresText} + {m.explore_showing()} {showingMeasuresText}
@@ -183,7 +184,7 @@ {/each} {:else}
- No matching leaderboard measures shown + {m.explore_no_matching_leaderboard_measures()}
{/if} @@ -202,7 +203,7 @@ @@ -212,7 +213,7 @@
- Choose measures to display + {m.explore_choose_measures()}
diff --git a/web-common/src/components/menu/TagFilterBanner.svelte b/web-common/src/components/menu/TagFilterBanner.svelte index addca27d0e34..55489c8c318f 100644 --- a/web-common/src/components/menu/TagFilterBanner.svelte +++ b/web-common/src/components/menu/TagFilterBanner.svelte @@ -1,5 +1,6 @@
- Filter: + {m.explore_filter_label()}: {tagName} @@ -23,7 +24,7 @@ type="button" class="flex-none text-icon-muted hover:text-fg-primary transition-colors" onclick={onClear} - aria-label="Clear tag filter" + aria-label={m.explore_clear_tag_filter()} > @@ -33,7 +34,7 @@ side="top" class="bg-popover text-fg-primary z-popover text-xs px-2 py-1" > - Clear filter + {m.explore_clear_filter()}
diff --git a/web-common/src/components/search/Search.svelte b/web-common/src/components/search/Search.svelte index 6b23000b877d..bf90c2e31bbb 100644 --- a/web-common/src/components/search/Search.svelte +++ b/web-common/src/components/search/Search.svelte @@ -1,4 +1,5 @@
- + diff --git a/web-common/src/features/alerts/data-tab/DataPreview.svelte b/web-common/src/features/alerts/data-tab/DataPreview.svelte index 594f35be61a8..fa9a6cb1dada 100644 --- a/web-common/src/features/alerts/data-tab/DataPreview.svelte +++ b/web-common/src/features/alerts/data-tab/DataPreview.svelte @@ -2,6 +2,7 @@ import { getAlertPreviewData } from "@rilldata/web-common/features/alerts/alert-preview-data"; import AlertPreviewTable from "@rilldata/web-common/features/alerts/AlertPreviewTable.svelte"; import type { AlertFormValues } from "@rilldata/web-common/features/alerts/form-utils"; + import * as m from "@rilldata/web-common/paraglide/messages.js"; import Spinner from "@rilldata/web-common/features/entity-management/Spinner.svelte"; import { EntityStatus } from "@rilldata/web-common/features/entity-management/types"; import type { Filters } from "@rilldata/web-common/features/dashboards/stores/Filters.ts"; @@ -40,7 +41,7 @@
{:else if !queryResult.data} {:else} diff --git a/web-common/src/features/alerts/data-tab/NoFiltersSelected.svelte b/web-common/src/features/alerts/data-tab/NoFiltersSelected.svelte index f08e3d05900a..adda81ccce2e 100644 --- a/web-common/src/features/alerts/data-tab/NoFiltersSelected.svelte +++ b/web-common/src/features/alerts/data-tab/NoFiltersSelected.svelte @@ -1,5 +1,6 @@ @@ -7,13 +8,12 @@
-

No filters selected

+

{m.alert_no_filters_heading()}

{#if isEditForm} - No filters were applied to the dashboard that this alert was created - from. + {m.alert_no_filters_body()} {:else} - To apply filters, close this window and filter your dashboard. + {m.alert_no_filters_hint()} {/if}
diff --git a/web-common/src/features/alerts/delivery-tab/AlertDialogDeliveryTab.svelte b/web-common/src/features/alerts/delivery-tab/AlertDialogDeliveryTab.svelte index dac0f95b95dc..07bdf69ed9f1 100644 --- a/web-common/src/features/alerts/delivery-tab/AlertDialogDeliveryTab.svelte +++ b/web-common/src/features/alerts/delivery-tab/AlertDialogDeliveryTab.svelte @@ -1,11 +1,12 @@
- + - +
{#if !$form["refreshWhenDataRefreshes"]} @@ -54,26 +55,26 @@
diff --git a/web-common/src/features/canvas/components/charts/custom-chart/index.ts b/web-common/src/features/canvas/components/charts/custom-chart/index.ts index e2ec53aa6119..13b7160f8fc4 100644 --- a/web-common/src/features/canvas/components/charts/custom-chart/index.ts +++ b/web-common/src/features/canvas/components/charts/custom-chart/index.ts @@ -4,7 +4,7 @@ import { type ComponentCommonProperties, type ComponentFilterProperties, } from "@rilldata/web-common/features/canvas/components/types"; -import { commonOptions } from "@rilldata/web-common/features/canvas/components/util"; +import { getCommonOptions } from "@rilldata/web-common/features/canvas/components/util"; import type { InputParams } from "@rilldata/web-common/features/canvas/inspector/types"; import type { CanvasEntity, @@ -22,6 +22,8 @@ import type { V1Resource } from "@rilldata/web-common/runtime-client"; import { get, writable, type Writable } from "svelte/store"; import CanvasCustomChart from "./CanvasCustomChart.svelte"; +import * as m from "@rilldata/web-common/paraglide/messages.js"; + export interface CustomChart extends ComponentCommonProperties, ComponentFilterProperties { @@ -161,10 +163,16 @@ export class CustomChartComponent extends BaseCanvasComponent { inputParams(): InputParams { return { options: { - prompt: { type: "ai_generate", label: "Edit with AI" }, - metrics_sql: { type: "metrics_sql", label: "Metrics SQL" }, - vega_spec: { type: "vega_spec", label: "Vega Lite Spec" }, - ...commonOptions, + prompt: { type: "ai_generate", label: m.canvas_edit_with_ai() }, + metrics_sql: { + type: "metrics_sql", + label: m.canvas_metrics_sql_label(), + }, + vega_spec: { + type: "vega_spec", + label: m.canvas_vega_lite_spec_label(), + }, + ...getCommonOptions(), }, filter: {}, }; diff --git a/web-common/src/features/canvas/components/charts/index.ts b/web-common/src/features/canvas/components/charts/index.ts index 98960508fbff..429b189b8476 100644 --- a/web-common/src/features/canvas/components/charts/index.ts +++ b/web-common/src/features/canvas/components/charts/index.ts @@ -83,6 +83,12 @@ export const CANVAS_CHART_CONFIG: Record = type, { ...config, + // Re-declare title as a lazy getter: spreading `config` above would + // otherwise flatten CHART_CONFIG's title getter into a string frozen to + // the locale active at module load. Delegating keeps it locale-reactive. + get title() { + return CHART_CONFIG[type as ChartType].title; + }, component: getCanvasChartComponent(type as ChartType), }, ]), diff --git a/web-common/src/features/canvas/components/charts/variants/CartesianChart.ts b/web-common/src/features/canvas/components/charts/variants/CartesianChart.ts index c9cca21b4569..34828e69230f 100644 --- a/web-common/src/features/canvas/components/charts/variants/CartesianChart.ts +++ b/web-common/src/features/canvas/components/charts/variants/CartesianChart.ts @@ -24,6 +24,8 @@ import type { } from "../../../stores/canvas-entity"; import { BaseChart, type BaseChartConfig } from "../BaseChart"; +import * as m from "@rilldata/web-common/paraglide/messages.js"; + export type CartesianCanvasChartSpec = BaseChartConfig & CartesianChartSpecBase; const DEFAULT_NOMINAL_LIMIT = 20; @@ -33,64 +35,69 @@ const DEFAULT_SORT = ChartSortType.Y_DESC; export class CartesianChartComponent extends BaseChart { private provider: CartesianChartProvider; - static chartInputParams: Record = { - x: { - type: "positional", - label: "X-axis", - meta: { - chartFieldInput: { - type: "dimension", - axisTitleSelector: true, - sortSelector: { - enable: true, - defaultSort: DEFAULT_SORT, - options: [ - ChartSortType.X_ASC, - ChartSortType.X_DESC, - ChartSortType.Y_ASC, - ChartSortType.Y_DESC, - ChartSortType.Y_DELTA_ASC, - ChartSortType.Y_DELTA_DESC, - ChartSortType.CUSTOM, - ], + // Static getter (not a static field) so the localized labels inside resolve + // in the active locale at access time (render) rather than freezing to the + // locale active when this class was defined at module load. + static get chartInputParams(): Record { + return { + x: { + type: "positional", + label: m.canvas_x_axis_label(), + meta: { + chartFieldInput: { + type: "dimension", + axisTitleSelector: true, + sortSelector: { + enable: true, + defaultSort: DEFAULT_SORT, + options: [ + ChartSortType.X_ASC, + ChartSortType.X_DESC, + ChartSortType.Y_ASC, + ChartSortType.Y_DESC, + ChartSortType.Y_DELTA_ASC, + ChartSortType.Y_DELTA_DESC, + ChartSortType.CUSTOM, + ], + }, + limitSelector: { defaultLimit: DEFAULT_NOMINAL_LIMIT }, + nullSelector: true, + labelAngleSelector: true, }, - limitSelector: { defaultLimit: DEFAULT_NOMINAL_LIMIT }, - nullSelector: true, - labelAngleSelector: true, }, }, - }, - y: { - type: "positional", - label: "Y-axis", - meta: { - chartFieldInput: { - type: "measure", - axisTitleSelector: true, - originSelector: true, - axisRangeSelector: true, - colorMappingSelector: { enable: false }, - multiFieldSelector: true, + y: { + type: "positional", + label: m.canvas_y_axis_label(), + meta: { + chartFieldInput: { + type: "measure", + axisTitleSelector: true, + originSelector: true, + axisRangeSelector: true, + colorMappingSelector: { enable: false }, + multiFieldSelector: true, + }, }, }, - }, - // TODO: Refactor to use simpler primitives - color: { - type: "mark", - label: "Color", - showInUI: true, - meta: { - type: "color", - chartFieldInput: { - type: "dimension", - defaultLegendOrientation: "top", - limitSelector: { defaultLimit: DEFAULT_SPLIT_LIMIT }, - colorMappingSelector: { enable: true }, - nullSelector: true, + // TODO: Refactor to use simpler primitives + color: { + type: "mark", + label: m.canvas_color_label(), + showInUI: true, + meta: { + type: "color", + chartFieldInput: { + type: "dimension", + defaultLegendOrientation: "top", + limitSelector: { defaultLimit: DEFAULT_SPLIT_LIMIT }, + colorMappingSelector: { enable: true }, + nullSelector: true, + }, }, }, - }, - }; + }; + } constructor(resource: V1Resource, parent: CanvasEntity, path: ComponentPath) { super(resource, parent, path); diff --git a/web-common/src/features/canvas/components/charts/variants/CircularChart.ts b/web-common/src/features/canvas/components/charts/variants/CircularChart.ts index 17ca4c495f3d..587db72e3436 100644 --- a/web-common/src/features/canvas/components/charts/variants/CircularChart.ts +++ b/web-common/src/features/canvas/components/charts/variants/CircularChart.ts @@ -23,6 +23,8 @@ import type { } from "../../../stores/canvas-entity"; import { BaseChart, type BaseChartConfig } from "../BaseChart"; +import * as m from "@rilldata/web-common/paraglide/messages.js"; + const DEFAULT_COLOR_LIMIT = 20; const DEFAULT_SORT = ChartSortType.MEASURE_DESC; @@ -32,55 +34,60 @@ export class CircularChartComponent extends BaseChart { private provider: CircularChartProvider; private isTruncated = false; - static chartInputParams: Record = { - measure: { - type: "positional", - label: "Measure", - meta: { - chartFieldInput: { - type: "measure", - totalSelector: true, + // Static getter (not a static field) so the localized labels inside resolve + // in the active locale at access time (render) rather than freezing to the + // locale active when this class was defined at module load. + static get chartInputParams(): Record { + return { + measure: { + type: "positional", + label: m.canvas_measure_label(), + meta: { + chartFieldInput: { + type: "measure", + totalSelector: true, + }, }, }, - }, - innerRadius: { - type: "number", - label: "Inner Radius (%)", - }, - show_other: { - type: "boolean", - label: 'Show "Other" bucket', - }, - labels: { - type: "labels", - label: "Data labels", - }, - color: { - type: "positional", - label: "Color", - meta: { - chartFieldInput: { - type: "dimension", - nullSelector: true, - limitSelector: { defaultLimit: DEFAULT_COLOR_LIMIT }, - hideTimeDimension: true, - defaultLegendOrientation: "right", - sortSelector: { - enable: true, - defaultSort: DEFAULT_SORT, - options: [ - ChartSortType.COLOR_ASC, - ChartSortType.COLOR_DESC, - ChartSortType.MEASURE_ASC, - ChartSortType.MEASURE_DESC, - ChartSortType.CUSTOM, - ], + innerRadius: { + type: "number", + label: m.canvas_inner_radius_label(), + }, + show_other: { + type: "boolean", + label: m.canvas_show_other_bucket_label(), + }, + labels: { + type: "labels", + label: m.canvas_data_labels_label(), + }, + color: { + type: "positional", + label: m.canvas_color_label(), + meta: { + chartFieldInput: { + type: "dimension", + nullSelector: true, + limitSelector: { defaultLimit: DEFAULT_COLOR_LIMIT }, + hideTimeDimension: true, + defaultLegendOrientation: "right", + sortSelector: { + enable: true, + defaultSort: DEFAULT_SORT, + options: [ + ChartSortType.COLOR_ASC, + ChartSortType.COLOR_DESC, + ChartSortType.MEASURE_ASC, + ChartSortType.MEASURE_DESC, + ChartSortType.CUSTOM, + ], + }, + colorMappingSelector: { enable: true }, }, - colorMappingSelector: { enable: true }, }, }, - }, - }; + }; + } constructor(resource: V1Resource, parent: CanvasEntity, path: ComponentPath) { super(resource, parent, path); diff --git a/web-common/src/features/canvas/components/charts/variants/ComboChart.ts b/web-common/src/features/canvas/components/charts/variants/ComboChart.ts index 527384e876fb..a403c67293ee 100644 --- a/web-common/src/features/canvas/components/charts/variants/ComboChart.ts +++ b/web-common/src/features/canvas/components/charts/variants/ComboChart.ts @@ -32,6 +32,8 @@ import type { } from "../../../stores/canvas-entity"; import { BaseChart, type BaseChartConfig } from "../BaseChart"; +import * as m from "@rilldata/web-common/paraglide/messages.js"; + export type ComboCanvasChartSpec = BaseChartConfig & ComboChartSpecBase; const DEFAULT_NOMINAL_LIMIT = 20; @@ -40,72 +42,77 @@ const DEFAULT_SORT = ChartSortType.Y_DESC; export class ComboChartComponent extends BaseChart { private provider: ComboChartProvider; - static chartInputParams: Record = { - x: { - type: "positional", - label: "X-axis", - meta: { - chartFieldInput: { - type: "dimension", - axisTitleSelector: true, - sortSelector: { - enable: true, - defaultSort: DEFAULT_SORT, - options: [ - ChartSortType.X_ASC, - ChartSortType.X_DESC, - ChartSortType.Y_ASC, - ChartSortType.Y_DESC, - ChartSortType.CUSTOM, - ], + // Static getter (not a static field) so the localized labels inside resolve + // in the active locale at access time (render) rather than freezing to the + // locale active when this class was defined at module load. + static get chartInputParams(): Record { + return { + x: { + type: "positional", + label: m.canvas_x_axis_label(), + meta: { + chartFieldInput: { + type: "dimension", + axisTitleSelector: true, + sortSelector: { + enable: true, + defaultSort: DEFAULT_SORT, + options: [ + ChartSortType.X_ASC, + ChartSortType.X_DESC, + ChartSortType.Y_ASC, + ChartSortType.Y_DESC, + ChartSortType.CUSTOM, + ], + }, + limitSelector: { defaultLimit: DEFAULT_NOMINAL_LIMIT }, + nullSelector: true, + labelAngleSelector: true, }, - limitSelector: { defaultLimit: DEFAULT_NOMINAL_LIMIT }, - nullSelector: true, - labelAngleSelector: true, }, }, - }, - y1: { - type: "positional", - label: "Left Y-Axis", - meta: { - chartFieldInput: { - type: "measure", - axisTitleSelector: true, - originSelector: true, - axisRangeSelector: true, - markTypeSelector: true, + y1: { + type: "positional", + label: m.canvas_left_y_axis_label(), + meta: { + chartFieldInput: { + type: "measure", + axisTitleSelector: true, + originSelector: true, + axisRangeSelector: true, + markTypeSelector: true, + }, }, }, - }, - - y2: { - type: "positional", - label: "Right Y-Axis", - meta: { - chartFieldInput: { - type: "measure", - axisTitleSelector: true, - originSelector: true, - axisRangeSelector: true, - markTypeSelector: true, + + y2: { + type: "positional", + label: m.canvas_right_y_axis_label(), + meta: { + chartFieldInput: { + type: "measure", + axisTitleSelector: true, + originSelector: true, + axisRangeSelector: true, + markTypeSelector: true, + }, }, }, - }, - - color: { - type: "mark", - label: "Color", - meta: { - type: "color", - chartFieldInput: { - type: "value", - defaultLegendOrientation: "top", - colorMappingSelector: { enable: true }, + + color: { + type: "mark", + label: m.canvas_color_label(), + meta: { + type: "color", + chartFieldInput: { + type: "value", + defaultLegendOrientation: "top", + colorMappingSelector: { enable: true }, + }, }, }, - }, - }; + }; + } constructor(resource: V1Resource, parent: CanvasEntity, path: ComponentPath) { super(resource, parent, path); diff --git a/web-common/src/features/canvas/components/charts/variants/FunnelChart.ts b/web-common/src/features/canvas/components/charts/variants/FunnelChart.ts index 7880c2344b91..17626bd6f3e4 100644 --- a/web-common/src/features/canvas/components/charts/variants/FunnelChart.ts +++ b/web-common/src/features/canvas/components/charts/variants/FunnelChart.ts @@ -24,6 +24,8 @@ import type { } from "../../../stores/canvas-entity"; import { BaseChart, type BaseChartConfig } from "../BaseChart"; +import * as m from "@rilldata/web-common/paraglide/messages.js"; + const DEFAULT_STAGE_LIMIT = 15; const DEFAULT_SORT = ChartSortType.Y_DESC; @@ -32,82 +34,87 @@ export type FunnelCanvasChartSpec = BaseChartConfig & FunnelChartSpecBase; export class FunnelChartComponent extends BaseChart { private provider: FunnelChartProvider; - static chartInputParams: Record = { - breakdownMode: { - type: "switcher_tab", - label: "Breakdown by", - meta: { - default: "dimension", - options: [ - { label: "Dimension", value: "dimension" }, - { label: "Measures", value: "measures" }, - ], + // Static getter (not a static field) so the localized labels inside resolve + // in the active locale at access time (render) rather than freezing to the + // locale active when this class was defined at module load. + static get chartInputParams(): Record { + return { + breakdownMode: { + type: "switcher_tab", + label: m.canvas_breakdown_by_label(), + meta: { + default: "dimension", + options: [ + { label: m.canvas_dimension_label(), value: "dimension" }, + { label: m.canvas_measures_label(), value: "measures" }, + ], + }, }, - }, - stage: { - type: "positional", - label: "Stage", - meta: { - chartFieldInput: { - type: "dimension", - nullSelector: true, - sortSelector: { - enable: true, - defaultSort: DEFAULT_SORT, - options: [ - ChartSortType.Y_ASC, - ChartSortType.Y_DESC, - ChartSortType.CUSTOM, - ], + stage: { + type: "positional", + label: m.canvas_stage_label(), + meta: { + chartFieldInput: { + type: "dimension", + nullSelector: true, + sortSelector: { + enable: true, + defaultSort: DEFAULT_SORT, + options: [ + ChartSortType.Y_ASC, + ChartSortType.Y_DESC, + ChartSortType.CUSTOM, + ], + }, + limitSelector: { defaultLimit: DEFAULT_STAGE_LIMIT }, + hideTimeDimension: true, }, - limitSelector: { defaultLimit: DEFAULT_STAGE_LIMIT }, - hideTimeDimension: true, }, }, - }, - measure: { - type: "positional", - label: "Measure", - meta: { - chartFieldInput: { - type: "measure", + measure: { + type: "positional", + label: m.canvas_measure_label(), + meta: { + chartFieldInput: { + type: "measure", + }, }, }, - }, - mode: { - type: "select", - label: "Mode", - meta: { - default: "width", - options: [ - { label: "Width", value: "width" }, - { label: "Order", value: "order" }, - ], + mode: { + type: "select", + label: m.canvas_mode_label(), + meta: { + default: "width", + options: [ + { label: m.canvas_width_option(), value: "width" }, + { label: m.canvas_order_option(), value: "order" }, + ], + }, }, - }, - color: { - type: "switcher_tab", - label: "Color", - meta: { - default: "stage", - options: [ - { label: "Stage", value: "stage" }, - { label: "Measure", value: "measure" }, - ], + color: { + type: "switcher_tab", + label: m.canvas_color_label(), + meta: { + default: "stage", + options: [ + { label: m.canvas_stage_label(), value: "stage" }, + { label: m.canvas_measure_label(), value: "measure" }, + ], + }, }, - }, - percentMode: { - type: "switcher_tab", - label: "Percent of", - meta: { - default: "top", - options: [ - { label: "Top", value: "top" }, - { label: "Previous", value: "previous" }, - ], + percentMode: { + type: "switcher_tab", + label: m.canvas_percent_of_label(), + meta: { + default: "top", + options: [ + { label: m.canvas_top_option(), value: "top" }, + { label: m.canvas_previous_option(), value: "previous" }, + ], + }, }, - }, - }; + }; + } constructor(resource: V1Resource, parent: CanvasEntity, path: ComponentPath) { super(resource, parent, path); @@ -143,8 +150,8 @@ export class FunnelChartComponent extends BaseChart { // Update color field for measures mode: Name (discrete) and Value (continuous) inputParams.color.meta!.options = [ - { label: "Name", value: "name" }, - { label: "Value", value: "value" }, + { label: m.canvas_name_option(), value: "name" }, + { label: m.canvas_value_option(), value: "value" }, ]; } else { // In dimension mode, show stage field and single measure selection @@ -155,8 +162,8 @@ export class FunnelChartComponent extends BaseChart { // Update color field for dimension mode inputParams.color.meta!.options = [ - { label: "Stage", value: "stage" }, - { label: "Measure", value: "measure" }, + { label: m.canvas_stage_label(), value: "stage" }, + { label: m.canvas_measure_label(), value: "measure" }, ]; // Exclude the main measure field from multi-field selector diff --git a/web-common/src/features/canvas/components/charts/variants/HeatmapChart.ts b/web-common/src/features/canvas/components/charts/variants/HeatmapChart.ts index 0556214283c2..3b3b317de614 100644 --- a/web-common/src/features/canvas/components/charts/variants/HeatmapChart.ts +++ b/web-common/src/features/canvas/components/charts/variants/HeatmapChart.ts @@ -22,6 +22,8 @@ import type { } from "../../../stores/canvas-entity"; import { BaseChart, type BaseChartConfig } from "../BaseChart"; +import * as m from "@rilldata/web-common/paraglide/messages.js"; + const DEFAULT_NOMINAL_LIMIT = 40; const DEFAULT_SORT = ChartSortType.COLOR_DESC; @@ -30,72 +32,77 @@ export type HeatmapCanvasChartSpec = BaseChartConfig & HeatmapChartSpecBase; export class HeatmapChartComponent extends BaseChart { private provider: HeatmapChartProvider; - static chartInputParams: Record = { - x: { - type: "positional", - label: "X-axis", - meta: { - chartFieldInput: { - type: "dimension", - limitSelector: { defaultLimit: DEFAULT_NOMINAL_LIMIT }, - sortSelector: { - enable: true, - defaultSort: DEFAULT_SORT, - options: [ - ChartSortType.X_ASC, - ChartSortType.X_DESC, - ChartSortType.COLOR_ASC, - ChartSortType.COLOR_DESC, - ChartSortType.CUSTOM, - ], + // Static getter (not a static field) so the localized labels inside resolve + // in the active locale at access time (render) rather than freezing to the + // locale active when this class was defined at module load. + static get chartInputParams(): Record { + return { + x: { + type: "positional", + label: m.canvas_x_axis_label(), + meta: { + chartFieldInput: { + type: "dimension", + limitSelector: { defaultLimit: DEFAULT_NOMINAL_LIMIT }, + sortSelector: { + enable: true, + defaultSort: DEFAULT_SORT, + options: [ + ChartSortType.X_ASC, + ChartSortType.X_DESC, + ChartSortType.COLOR_ASC, + ChartSortType.COLOR_DESC, + ChartSortType.CUSTOM, + ], + }, + axisTitleSelector: true, + nullSelector: true, + labelAngleSelector: true, }, - axisTitleSelector: true, - nullSelector: true, - labelAngleSelector: true, }, }, - }, - y: { - type: "positional", - label: "Y-axis", - meta: { - chartFieldInput: { - type: "dimension", - limitSelector: { defaultLimit: DEFAULT_NOMINAL_LIMIT }, - sortSelector: { - enable: true, - defaultSort: DEFAULT_SORT, - options: [ - ChartSortType.Y_ASC, - ChartSortType.Y_DESC, - ChartSortType.COLOR_ASC, - ChartSortType.COLOR_DESC, - ChartSortType.CUSTOM, - ], + y: { + type: "positional", + label: m.canvas_y_axis_label(), + meta: { + chartFieldInput: { + type: "dimension", + limitSelector: { defaultLimit: DEFAULT_NOMINAL_LIMIT }, + sortSelector: { + enable: true, + defaultSort: DEFAULT_SORT, + options: [ + ChartSortType.Y_ASC, + ChartSortType.Y_DESC, + ChartSortType.COLOR_ASC, + ChartSortType.COLOR_DESC, + ChartSortType.CUSTOM, + ], + }, + axisTitleSelector: true, + nullSelector: true, }, - axisTitleSelector: true, - nullSelector: true, }, }, - }, - color: { - type: "positional", - label: "Color", - meta: { - chartFieldInput: { - type: "measure", - defaultLegendOrientation: "right", - colorRangeSelector: { - enable: true, + color: { + type: "positional", + label: m.canvas_color_label(), + meta: { + chartFieldInput: { + type: "measure", + defaultLegendOrientation: "right", + colorRangeSelector: { + enable: true, + }, }, }, }, - }, - show_data_labels: { - type: "boolean", - label: "Data labels", - }, - }; + show_data_labels: { + type: "boolean", + label: m.canvas_data_labels_label(), + }, + }; + } constructor(resource: V1Resource, parent: CanvasEntity, path: ComponentPath) { super(resource, parent, path); diff --git a/web-common/src/features/canvas/components/charts/variants/ScatterPlotChart.ts b/web-common/src/features/canvas/components/charts/variants/ScatterPlotChart.ts index a0acf62e317a..ba74f10ea718 100644 --- a/web-common/src/features/canvas/components/charts/variants/ScatterPlotChart.ts +++ b/web-common/src/features/canvas/components/charts/variants/ScatterPlotChart.ts @@ -21,6 +21,8 @@ import type { } from "../../../stores/canvas-entity"; import { BaseChart, type BaseChartConfig } from "../BaseChart"; +import * as m from "@rilldata/web-common/paraglide/messages.js"; + export type ScatterPlotCanvasChartSpec = BaseChartConfig & ScatterPlotChartSpecBase; @@ -29,65 +31,70 @@ const DEFAULT_SPLIT_LIMIT = 10; export class ScatterPlotChartComponent extends BaseChart { private provider: ScatterPlotChartProvider; - static chartInputParams: Record = { - x: { - type: "positional", - label: "X-axis", - meta: { - chartFieldInput: { - type: "measure", - axisTitleSelector: true, - axisRangeSelector: true, + // Static getter (not a static field) so the localized labels inside resolve + // in the active locale at access time (render) rather than freezing to the + // locale active when this class was defined at module load. + static get chartInputParams(): Record { + return { + x: { + type: "positional", + label: m.canvas_x_axis_label(), + meta: { + chartFieldInput: { + type: "measure", + axisTitleSelector: true, + axisRangeSelector: true, + }, }, }, - }, - y: { - type: "positional", - label: "Y-axis", - meta: { - chartFieldInput: { - type: "measure", - axisTitleSelector: true, - axisRangeSelector: true, + y: { + type: "positional", + label: m.canvas_y_axis_label(), + meta: { + chartFieldInput: { + type: "measure", + axisTitleSelector: true, + axisRangeSelector: true, + }, }, }, - }, - dimension: { - type: "positional", - label: "Dimension", - meta: { - chartFieldInput: { - type: "dimension", - nullSelector: true, + dimension: { + type: "positional", + label: m.canvas_dimension_label(), + meta: { + chartFieldInput: { + type: "dimension", + nullSelector: true, + }, }, }, - }, - size: { - type: "positional", - label: "Size", - meta: { - chartFieldInput: { - type: "measure", - isRemovable: true, + size: { + type: "positional", + label: m.canvas_size_label(), + meta: { + chartFieldInput: { + type: "measure", + isRemovable: true, + }, }, }, - }, - color: { - type: "mark", - label: "Color", - showInUI: true, - meta: { - type: "color", - chartFieldInput: { - type: "dimension", - defaultLegendOrientation: "top", - limitSelector: { defaultLimit: DEFAULT_SPLIT_LIMIT }, - colorMappingSelector: { enable: true }, - nullSelector: true, + color: { + type: "mark", + label: m.canvas_color_label(), + showInUI: true, + meta: { + type: "color", + chartFieldInput: { + type: "dimension", + defaultLegendOrientation: "top", + limitSelector: { defaultLimit: DEFAULT_SPLIT_LIMIT }, + colorMappingSelector: { enable: true }, + nullSelector: true, + }, }, }, - }, - }; + }; + } constructor(resource: V1Resource, parent: CanvasEntity, path: ComponentPath) { super(resource, parent, path); diff --git a/web-common/src/features/canvas/components/image/index.ts b/web-common/src/features/canvas/components/image/index.ts index 2943ef2884d5..2da279fff8af 100644 --- a/web-common/src/features/canvas/components/image/index.ts +++ b/web-common/src/features/canvas/components/image/index.ts @@ -4,7 +4,7 @@ import { type ComponentAlignment, type ComponentCommonProperties, } from "@rilldata/web-common/features/canvas/components/types"; -import { commonOptions } from "@rilldata/web-common/features/canvas/components/util"; +import { getCommonOptions } from "@rilldata/web-common/features/canvas/components/util"; import type { InputParams } from "@rilldata/web-common/features/canvas/inspector/types"; import type { V1Resource } from "@rilldata/web-common/runtime-client"; import type { CanvasEntity, ComponentPath } from "../../stores/canvas-entity"; @@ -12,6 +12,8 @@ import Image from "./Image.svelte"; export { default as Image } from "./Image.svelte"; +import * as m from "@rilldata/web-common/paraglide/messages.js"; + export const defaultImageAlignment: ComponentAlignment = { horizontal: "center", vertical: "middle", @@ -43,13 +45,13 @@ export class ImageComponent extends BaseCanvasComponent { inputParams(): InputParams { return { options: { - url: { type: "text", label: "URL" }, + url: { type: "text", label: m.canvas_url_label() }, alignment: { type: "alignment", - label: "Alignment", + label: m.canvas_alignment_label(), meta: { defaultAlignment: defaultImageAlignment }, }, - ...commonOptions, + ...getCommonOptions(), }, filter: {}, }; diff --git a/web-common/src/features/canvas/components/kpi-grid/index.ts b/web-common/src/features/canvas/components/kpi-grid/index.ts index 0b1cb6693cab..89f1d8bccf23 100644 --- a/web-common/src/features/canvas/components/kpi-grid/index.ts +++ b/web-common/src/features/canvas/components/kpi-grid/index.ts @@ -1,6 +1,6 @@ import { BaseCanvasComponent } from "@rilldata/web-common/features/canvas/components/BaseCanvasComponent"; import { - commonOptions, + getCommonOptions, getFilterOptions, } from "@rilldata/web-common/features/canvas/components/util"; import type { InputParams } from "@rilldata/web-common/features/canvas/inspector/types"; @@ -23,6 +23,8 @@ import KPIGrid from "./KPIGrid.svelte"; export { default as KPIGrid } from "./KPIGrid.svelte"; +import * as m from "@rilldata/web-common/paraglide/messages.js"; + export const defaultComparisonOptions: ComponentComparisonOptions[] = [ "delta", "percent_change", @@ -77,25 +79,32 @@ export class KPIGridComponent extends BaseCanvasComponent { ); const timeSeriesOptions: InputParams["options"] = { - sparkline: { type: "sparkline", optional: true, label: "Sparkline" }, + sparkline: { + type: "sparkline", + optional: true, + label: m.canvas_sparkline_label(), + }, hide_time_range: { type: "boolean", optional: true, - label: "Time range display", + label: m.canvas_time_range_display_label(), meta: { invertBoolean: true }, }, - comparison: { type: "comparison_options", label: "Comparison values" }, + comparison: { + type: "comparison_options", + label: m.canvas_comparison_values_label(), + }, }; const inputParams: InputParams = { options: { - metrics_view: { type: "metrics", label: "Metrics view" }, + metrics_view: { type: "metrics", label: m.canvas_metrics_view_label() }, measures: { type: "multi_fields", meta: { allowedTypes: ["measure"] }, - label: "Measures", + label: m.canvas_measures_label(), }, ...(hasTimeSeries ? timeSeriesOptions : {}), - ...commonOptions, + ...getCommonOptions(), }, filter: getFilterOptions(), }; diff --git a/web-common/src/features/canvas/components/kpi/KPI.svelte b/web-common/src/features/canvas/components/kpi/KPI.svelte index 0093eaa9f281..3acfcd2366e6 100644 --- a/web-common/src/features/canvas/components/kpi/KPI.svelte +++ b/web-common/src/features/canvas/components/kpi/KPI.svelte @@ -1,4 +1,5 @@
- + { - if (field === "Flat") { + onClick={(index) => { + if (index === 0) { selected = 0; component.updateTableType("table"); - } else if (field === "Pivot") { + } else if (index === 1) { selected = 1; component.updateTableType("pivot"); } diff --git a/web-common/src/features/canvas/inspector/chart/ChartTypeSelector.svelte b/web-common/src/features/canvas/inspector/chart/ChartTypeSelector.svelte index cdba21217a70..9dc145ed8bfe 100644 --- a/web-common/src/features/canvas/inspector/chart/ChartTypeSelector.svelte +++ b/web-common/src/features/canvas/inspector/chart/ChartTypeSelector.svelte @@ -1,4 +1,5 @@
- +
{#each VISIBLE_CHART_TYPES as chart, i (i)} diff --git a/web-common/src/features/canvas/inspector/chart/MetricsSQLInput.svelte b/web-common/src/features/canvas/inspector/chart/MetricsSQLInput.svelte index 2d91c30ea942..5d0f5375adf8 100644 --- a/web-common/src/features/canvas/inspector/chart/MetricsSQLInput.svelte +++ b/web-common/src/features/canvas/inspector/chart/MetricsSQLInput.svelte @@ -1,4 +1,5 @@ diff --git a/web-common/src/features/chat/core/input/ChatInput.svelte b/web-common/src/features/chat/core/input/ChatInput.svelte index b3f11cdb04df..15f7c6cf442d 100644 --- a/web-common/src/features/chat/core/input/ChatInput.svelte +++ b/web-common/src/features/chat/core/input/ChatInput.svelte @@ -9,6 +9,7 @@ import type { ConversationManager } from "../conversation-manager"; import type { ChatConfig } from "@rilldata/web-common/features/chat/core/types.ts"; import Button from "@rilldata/web-common/components/button/Button.svelte"; + import * as m from "@rilldata/web-common/paraglide/messages.js"; import { ArrowUp } from "lucide-svelte"; export let conversationManager: ConversationManager; @@ -138,7 +139,7 @@
{#if canCancel} @@ -149,7 +150,7 @@ {:else} diff --git a/web-common/src/features/chat/layouts/fullpage/ConversationSidebar.svelte b/web-common/src/features/chat/layouts/fullpage/ConversationSidebar.svelte index ce36a91a4ddd..29b8fee04e99 100644 --- a/web-common/src/features/chat/layouts/fullpage/ConversationSidebar.svelte +++ b/web-common/src/features/chat/layouts/fullpage/ConversationSidebar.svelte @@ -6,6 +6,7 @@ import Spinner from "../../../entity-management/Spinner.svelte"; import { EntityStatus } from "../../../entity-management/types"; import type { ConversationManager } from "../../core/conversation-manager"; + import * as m from "@rilldata/web-common/paraglide/messages.js"; export let conversationManager: ConversationManager; export let basePath: string; @@ -47,7 +48,7 @@ - +
@@ -106,13 +107,13 @@ onclick={handleConversationItemClick} >
- {conversation.title || "New conversation"} + {conversation.title || m.chat_new_conversation()}
{/each} {:else}
- No conversations yet + {m.chat_no_conversations()}
{/if}
diff --git a/web-common/src/features/chat/layouts/sidebar/ConversationHistoryMenu.svelte b/web-common/src/features/chat/layouts/sidebar/ConversationHistoryMenu.svelte index c430b14882c3..34efc181f427 100644 --- a/web-common/src/features/chat/layouts/sidebar/ConversationHistoryMenu.svelte +++ b/web-common/src/features/chat/layouts/sidebar/ConversationHistoryMenu.svelte @@ -1,11 +1,13 @@ @@ -25,7 +26,7 @@
{#if showRange} - Custom + {m.time_custom()} {:else} {selectedLabel} {/if} @@ -47,7 +48,7 @@
- vs + {m.time_vs()} {getComparisonLabel(comparisonTimeRange)} diff --git a/web-common/src/features/dashboards/filters/dimension-filters/DimensionFilterChipBody.svelte b/web-common/src/features/dashboards/filters/dimension-filters/DimensionFilterChipBody.svelte index 7aa28b7a3ba7..1398d53d76e1 100644 --- a/web-common/src/features/dashboards/filters/dimension-filters/DimensionFilterChipBody.svelte +++ b/web-common/src/features/dashboards/filters/dimension-filters/DimensionFilterChipBody.svelte @@ -1,6 +1,7 @@ { e.stopPropagation(); if (dimensionName) toggleComparisonDimension(dimensionName); @@ -19,7 +20,7 @@ - {isBeingCompared ? "Remove comparison" : "Compare"} + {isBeingCompared ? m.leaderboard_remove_comparison() : m.leaderboard_compare()} diff --git a/web-common/src/features/dashboards/leaderboard/Leaderboard.svelte b/web-common/src/features/dashboards/leaderboard/Leaderboard.svelte index 93ae8462b384..1192eb3bf3ff 100644 --- a/web-common/src/features/dashboards/leaderboard/Leaderboard.svelte +++ b/web-common/src/features/dashboards/leaderboard/Leaderboard.svelte @@ -1,6 +1,7 @@ -
+
diff --git a/web-common/src/features/dashboards/leaderboard/LeaderboardHeader.svelte b/web-common/src/features/dashboards/leaderboard/LeaderboardHeader.svelte index 0f167eae8343..ede3df680f3f 100644 --- a/web-common/src/features/dashboards/leaderboard/LeaderboardHeader.svelte +++ b/web-common/src/features/dashboards/leaderboard/LeaderboardHeader.svelte @@ -1,4 +1,5 @@ @@ -169,22 +172,22 @@ id="truncation-selector-trigger" type="button" class="flex gap-x-1 items-center flex-none truncate" - aria-label="Select reference time and grain" + aria-label={m.dashboard_select_ref_time_grain()} data-state={open ? "open" : "closed"} >

- as of + {m.dashboard_as_of_ref()} {humanizedRef} {#if dateTimeUnit} - {dateTimeUnit} + {translateGrainName(dateTimeUnit)} {/if} {#if grain} {#if snapToEnd || ref === RillTimeLabel.Watermark} - end + {m.dashboard_end()} {:else} - start + {m.dashboard_start()} {/if} {/if}

@@ -213,7 +216,7 @@

- Reference + {m.dashboard_reference()}

{#each options as { id, label, description, timestamp } (id)} {#if id !== RillTimeLabel.Watermark || (id === RillTimeLabel.Watermark && !!timestamp)} @@ -272,7 +275,9 @@ -

Grain

+

+ {m.dashboard_grain()} +

{#each grainOptions as option, i (i)} - {V1TimeGrainToDateTimeUnit[option]} + {translateV1TimeGrain(option)} {:else}
- No valid grains available. + {m.dashboard_no_valid_grains()}
{/each}
@@ -295,7 +300,7 @@ {#if dateTimeUnit} diff --git a/web-admin/src/features/billing/contact/ChangeBillingContactDialog.svelte b/web-admin/src/features/billing/contact/ChangeBillingContactDialog.svelte index 91231b81c7ef..86f07fd4bcfc 100644 --- a/web-admin/src/features/billing/contact/ChangeBillingContactDialog.svelte +++ b/web-admin/src/features/billing/contact/ChangeBillingContactDialog.svelte @@ -7,6 +7,7 @@ import * as Dialog from "@rilldata/web-common/components/dialog"; import Select from "@rilldata/web-common/components/forms/Select.svelte"; import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus"; + import * as m from "@rilldata/web-common/paraglide/messages.js"; import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient"; import { getOrgAdminMembers } from "@rilldata/web-admin/features/organizations/user-management/selectors.ts"; @@ -47,13 +48,12 @@ }); eventBus.emit("notification", { - message: `${selectedBillingContactLabel} has been assigned as billing contact.`, + message: m.billing_contact_assigned({ name: selectedBillingContactLabel }), }); } catch (error) { console.error("Error assigning user as billing contact", error); eventBus.emit("notification", { - message: - "Failed to reassign billing contact. Please try again or contact support.", + message: m.billing_contact_reassign_failed(), type: "error", }); } @@ -73,11 +73,11 @@ - Change billing contact + {m.billing_change_billing_contact()}
- Select another org admin as billing contact. + {m.billing_select_admin_as_contact()}
- + {#if hasOwnSessions && currentTab === "existing"}
- +