diff --git a/.github/workflows/code-qa.yml b/.github/workflows/code-qa.yml index 3aab73668d..5084b96733 100644 --- a/.github/workflows/code-qa.yml +++ b/.github/workflows/code-qa.yml @@ -74,8 +74,12 @@ jobs: uses: ./.github/actions/setup-node-pnpm with: install-args: "--frozen-lockfile" + - name: Test translation check scripts + run: pnpm test:translations-check - name: Verify all translations are complete run: node scripts/find-missing-translations.js + - name: Verify plural forms follow CLDR + run: node scripts/validate-plural-forms.js - name: Verify t() calls pass every interpolation variable run: node scripts/check-i18n-interpolation.js diff --git a/.roo/rules-translate/001-general-rules.md b/.roo/rules-translate/001-general-rules.md index e27b9793e2..8c63992d34 100644 --- a/.roo/rules-translate/001-general-rules.md +++ b/.roo/rules-translate/001-general-rules.md @@ -50,14 +50,65 @@ # 5. TECHNICAL IMPLEMENTATION - Use namespaces to organize translations logically -- Handle pluralization using i18next's built-in capabilities +- Handle pluralization with i18next plural keys that follow CLDR rules (see section 6) - Implement proper interpolation for variables using {{variable}} syntax - Don't include defaultValue. The `en` translations are the fallback - Always use apply_diff instead of write_to_file when editing existing translation files (much faster and more reliable) - When using apply_diff, carefully identify the exact JSON structure to edit to avoid syntax errors - Placeholders (like {{variable}}) must remain exactly identical to the English source to maintain code integration and prevent syntax errors -# 6. WORKFLOW AND APPROACH +# 6. PLURALIZATION (CLDR) + +i18next v25 picks a plural form with `Intl.PluralRules`, which implements the [CLDR plural rules](https://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html). Any string that counts something must use plural keys. + +- Never fake plurals with "(s)", "файл(ов)", "richiesta/e" or similar. Split the string into plural forms instead. +- Pass the number as `count`: `t("ns:key", { count: n })`. With ``, pass `count={n}` or `values={{ count: n }}`. +- Name the keys `key_one`, `key_few`, `key_many`, `key_other` (plus an optional `key_zero`). Do not keep a bare `key` next to them: i18next uses it in place of any missing form, which hides the gap. +- Each locale must have exactly its CLDR forms. When a form is missing, i18next falls back to the bare key and then to English. Extra forms are never shown: + +| Locales | Forms | What the forms cover | +| ---------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------- | +| en, de, nl, tr | `one`, `other` | `one` = 1 | +| hi | `one`, `other` | `one` = 0, 1 | +| fr, pt-BR | `one`, `many`, `other` | `one` = 0, 1; `many` = exact millions (1000000) | +| ca, es, it | `one`, `many`, `other` | `one` = 1; `many` = exact millions (1000000) | +| ru | `one`, `few`, `many`, `other` | `one` = 1, 21, 31, 101 (not 11); `few` = 2–4, 22–24 (not 12–14); `many` = 0, 5–20, 25–30; `other` = fractions | +| pl | `one`, `few`, `many`, `other` | `one` = 1 only; `few` = 2–4, 22–24 (not 12–14); `many` = 0, 5–21, 25–31; `other` = fractions | +| id, ja, ko, vi, zh-CN, zh-TW | `other` | No `_one`: these languages do not inflect for number | + +- Every form, including `_one`, must contain `{{count}}`. Do not hardcode "1": `_one` also covers 21 in ru and 0 in fr, pt-BR and hi. +- `_many` in ca, es, fr, it and pt-BR only applies to exact millions printed as digits. Copy the `_other` text. +- `_other` in ru and pl only applies to fractions (1.5). Use the genitive singular: ru "1,5 минуты" (same as `_few`), pl "1,5 minuty", "1,5 wyniku". +- The form depends on the whole phrase, not just the noun. Check the case the preposition or verb requires: + - ru "удалить {{count}} задачу / задачи / задач" + - ru "до {{count}} запроса / запросов / запросов" + - pl negation "nie udało się odłączyć {{count}} serwera / serwerów / serwerów" +- If another number governs the noun (e.g. "{{count}} of {{total}}"), rephrase so the noun no longer depends on a number: "Импортировано историй задач: {{count}} из {{total}}". +- `_zero` is an i18next override for count 0 in every language. Add it in every locale when the English key has it. In ru and pl, 0 otherwise uses `_many`. +- Do not pluralize money amounts, unit abbreviations ("{{count}}s"), numbers that JavaScript updates live in the DOM, or phrases with no counted noun ("and {{count}} more"). + +Example: + +```jsonc +// en +"subtasks_one": "{{count}} subtask", +"subtasks_other": "{{count}} subtasks", + +// ru +"subtasks_one": "{{count}} подзадача", +"subtasks_few": "{{count}} подзадачи", +"subtasks_many": "{{count}} подзадач", +"subtasks_other": "{{count}} подзадачи", + +// ja +"subtasks_other": "{{count}} サブタスク", +``` + +To list the plural forms of any locale, run: `node -p 'new Intl.PluralRules("").resolvedOptions().pluralCategories'` + +`node scripts/find-missing-translations.js` reports a plural key only when a locale has no key with its base name (`key` or `key_*`). `node scripts/validate-plural-forms.js` reports missing forms, forms without `{{count}}`, extra forms, bare keys next to plural forms and plural mistakes in English. + +# 7. WORKFLOW AND APPROACH - First add or modify English strings, then ask for confirmation before translating to all other languages - Use this process for each localization task: @@ -74,7 +125,7 @@ - Tooltip text: Can be slightly more descriptive - Preserve the original perspective: If text is a user command directed at the software, ensure the translation maintains this direction, avoiding language that makes it sound like an instruction from the system to the user -# 7. COMMON PITFALLS TO AVOID +# 8. COMMON PITFALLS TO AVOID - Switching between formal and informal addressing styles - always stay informal ("du" not "Sie") - Translating or altering technical terms and brand names that should remain in English @@ -82,8 +133,9 @@ - Translating domain-specific terms that are commonly used in English in the target language - Changing the meaning or nuance of instructions or error messages - Forgetting to maintain consistent terminology throughout the translation +- Copying the English `_one`/`_other` pair into a locale with different plural forms, or writing "(s)"-style plurals -# 8. QUALITY ASSURANCE +# 9. QUALITY ASSURANCE - Maintain consistent terminology across all translations - Respect the JSON structure of translation files @@ -95,11 +147,16 @@ node scripts/find-missing-translations.js ``` - Address any missing translations identified by the script to ensure complete coverage across all locales +- When you add or change plural keys, also run the plural forms script and fix every problem it reports: + ``` + node scripts/validate-plural-forms.js + ``` -# 9. TRANSLATOR'S CHECKLIST +# 10. TRANSLATOR'S CHECKLIST - ✓ Used informal tone consistently ("du" not "Sie") - ✓ Preserved all placeholders exactly as in the English source +- ✓ Gave each plural key exactly the locale's CLDR forms, each containing `{{count}}` - ✓ Maintained consistent terminology with existing translations - ✓ Kept technical terms and brand names unchanged where appropriate - ✓ Preserved the original perspective (user→system vs system→user) diff --git a/.roo/skills/roo-translation/SKILL.md b/.roo/skills/roo-translation/SKILL.md index 82eab76fbf..c9dbd57471 100644 --- a/.roo/skills/roo-translation/SKILL.md +++ b/.roo/skills/roo-translation/SKILL.md @@ -96,13 +96,64 @@ React component usage: ## Technical Implementation - Use namespaces to organize translations logically -- Handle pluralization using i18next's built-in capabilities +- Handle pluralization with i18next plural keys that follow CLDR rules (see [Pluralization (CLDR)](#pluralization-cldr)) - Implement proper interpolation for variables using `{{variable}}` syntax - Don't include `defaultValue`. The `en` translations are the fallback - Always use `apply_diff` instead of `write_to_file` when editing existing translation files (much faster and more reliable) - When using `apply_diff`, carefully identify the exact JSON structure to edit to avoid syntax errors - Placeholders (like `{{variable}}`) must remain exactly identical to the English source to maintain code integration and prevent syntax errors +## Pluralization (CLDR) + +i18next v25 picks a plural form with `Intl.PluralRules`, which implements the [CLDR plural rules](https://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html). Any string that counts something must use plural keys. + +- Never fake plurals with "(s)", "файл(ов)", "richiesta/e" or similar. Split the string into plural forms instead. +- Pass the number as `count`: `t("ns:key", { count: n })`. With ``, pass `count={n}` or `values={{ count: n }}`. +- Name the keys `key_one`, `key_few`, `key_many`, `key_other` (plus an optional `key_zero`). Do not keep a bare `key` next to them: i18next uses it in place of any missing form, which hides the gap. +- Each locale must have exactly its CLDR forms. When a form is missing, i18next falls back to the bare key and then to English. Extra forms are never shown: + +| Locales | Forms | What the forms cover | +| ---------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------- | +| en, de, nl, tr | `one`, `other` | `one` = 1 | +| hi | `one`, `other` | `one` = 0, 1 | +| fr, pt-BR | `one`, `many`, `other` | `one` = 0, 1; `many` = exact millions (1000000) | +| ca, es, it | `one`, `many`, `other` | `one` = 1; `many` = exact millions (1000000) | +| ru | `one`, `few`, `many`, `other` | `one` = 1, 21, 31, 101 (not 11); `few` = 2–4, 22–24 (not 12–14); `many` = 0, 5–20, 25–30; `other` = fractions | +| pl | `one`, `few`, `many`, `other` | `one` = 1 only; `few` = 2–4, 22–24 (not 12–14); `many` = 0, 5–21, 25–31; `other` = fractions | +| id, ja, ko, vi, zh-CN, zh-TW | `other` | No `_one`: these languages do not inflect for number | + +- Every form, including `_one`, must contain `{{count}}`. Do not hardcode "1": `_one` also covers 21 in ru and 0 in fr, pt-BR and hi. +- `_many` in ca, es, fr, it and pt-BR only applies to exact millions printed as digits. Copy the `_other` text. +- `_other` in ru and pl only applies to fractions (1.5). Use the genitive singular: ru "1,5 минуты" (same as `_few`), pl "1,5 minuty", "1,5 wyniku". +- The form depends on the whole phrase, not just the noun. Check the case the preposition or verb requires: + - ru "удалить {{count}} задачу / задачи / задач" + - ru "до {{count}} запроса / запросов / запросов" + - pl negation "nie udało się odłączyć {{count}} serwera / serwerów / serwerów" +- If another number governs the noun (e.g. "{{count}} of {{total}}"), rephrase so the noun no longer depends on a number: "Импортировано историй задач: {{count}} из {{total}}". +- `_zero` is an i18next override for count 0 in every language. Add it in every locale when the English key has it. In ru and pl, 0 otherwise uses `_many`. +- Do not pluralize money amounts, unit abbreviations ("{{count}}s"), numbers that JavaScript updates live in the DOM, or phrases with no counted noun ("and {{count}} more"). + +Example: + +```jsonc +// en +"subtasks_one": "{{count}} subtask", +"subtasks_other": "{{count}} subtasks", + +// ru +"subtasks_one": "{{count}} подзадача", +"subtasks_few": "{{count}} подзадачи", +"subtasks_many": "{{count}} подзадач", +"subtasks_other": "{{count}} подзадачи", + +// ja +"subtasks_other": "{{count}} サブタスク", +``` + +To list the plural forms of any locale, run: `node -p 'new Intl.PluralRules("").resolvedOptions().pluralCategories'`. + +`node scripts/find-missing-translations.js` reports a plural key only when a locale has no key with its base name (`key` or `key_*`). `node scripts/validate-plural-forms.js` reports missing forms, forms without `{{count}}`, extra forms, bare keys next to plural forms and plural mistakes in English. + ## Translation Workflow 1. First add or modify English strings, then ask for confirmation before translating to all other languages @@ -133,6 +184,12 @@ node scripts/find-missing-translations.js Address any missing translations identified by the script to ensure complete coverage across all locales. +When you add or change plural keys, also run the plural forms script and fix every problem it reports: + +```bash +node scripts/validate-plural-forms.js +``` + ## Common Pitfalls to Avoid - Switching between formal and informal addressing styles - always stay informal ("du" not "Sie") @@ -141,11 +198,13 @@ Address any missing translations identified by the script to ensure complete cov - Translating domain-specific terms that are commonly used in English in the target language - Changing the meaning or nuance of instructions or error messages - Forgetting to maintain consistent terminology throughout the translation +- Copying the English `_one`/`_other` pair into a locale with different plural forms, or writing "(s)"-style plurals ## Translator's Checklist - ✓ Used informal tone consistently ("du" not "Sie") - ✓ Preserved all placeholders exactly as in the English source +- ✓ Gave each plural key exactly the locale's CLDR forms, each containing `{{count}}` - ✓ Maintained consistent terminology with existing translations - ✓ Kept technical terms and brand names unchanged where appropriate - ✓ Preserved the original perspective (user→system vs system→user) diff --git a/package.json b/package.json index 04922487f6..886f3886ff 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,8 @@ "knip": "knip --treat-config-hints-as-errors", "npm:publish:types": "pnpm --filter @roo-code/types npm:publish", "knip:production": "knip --production --treat-config-hints-as-errors", - "test:knip-policy": "node --test scripts/knip-policy.test.mjs" + "test:knip-policy": "node --test scripts/knip-policy.test.mjs", + "test:translations-check": "node --test scripts/find-missing-translations.test.mjs scripts/validate-plural-forms.test.mjs" }, "devDependencies": { "@changesets/cli": "2.31.1", diff --git a/scripts/find-missing-translations.js b/scripts/find-missing-translations.js index fe7577408e..c56b4f5755 100755 --- a/scripts/find-missing-translations.js +++ b/scripts/find-missing-translations.js @@ -13,6 +13,7 @@ const path = require("path") const { promises: fs } = require("fs") +const { PLURAL_FORMS, PLURAL_KEY, findPluralBases } = require("./lib/plural-forms") const readFile = fs.readFile const readdir = fs.readdir @@ -47,6 +48,8 @@ Find Missing Translations A utility script to identify missing translations across locale files. Compares non-English locale files to the English ones to find any missing keys. +A plural key is reported only when a locale has no key with its base name (e.g. no "files_*"). +Run validate-plural-forms.js to check that each locale has exactly its CLDR plural forms. Usage: node scripts/find-missing-translations.js [options] @@ -95,6 +98,22 @@ function findKeys(obj, parentKey = "") { return keys } +// A plural key is translated when the locale has any key with its base name ("files" or "files_
"). +// Locales use different plural suffixes (ru: _few, _many; ja: only _other), so the suffixes are not +// compared here. validate-plural-forms.js checks that each locale has exactly its CLDR forms. +function findMissingPluralKeys(localeContent, pluralBases) { + const missing = [] + + for (const [base, { englishValue }] of pluralBases) { + const related = [base, ...PLURAL_FORMS.map((form) => `${base}_${form}`)] + if (related.every((key) => getValueAtPath(localeContent, key) === undefined)) { + missing.push({ key: `${base}_*`, englishValue }) + } + } + + return missing +} + // Get value at a dotted path in an object function getValueAtPath(obj, path) { const parts = path.split(".") @@ -190,8 +209,14 @@ async function checkAreaTranslations(area) { `Checking ${englishFileContents.length} translation file(s): ${englishFileContents.map((f) => f.name).join(", ")}`, ) - // Precompute English keys per file + // Precompute English keys and plural keys per file const englishFileKeys = new Map(englishFileContents.map((f) => [f.name, findKeys(f.content)])) + const englishPluralBases = new Map( + englishFileContents.map((f) => [ + f.name, + findPluralBases(englishFileKeys.get(f.name).map((key) => [key, getValueAtPath(f.content, key)])), + ]), + ) // Results object to store missing translations const missingTranslations = {} @@ -220,6 +245,9 @@ async function checkAreaTranslations(area) { const missingKeys = [] for (const key of englishKeys) { + // Plural forms differ between locales, so plural keys are matched by base name below + if (PLURAL_KEY.test(key)) continue + const englishValue = getValueAtPath(englishContent, key) const localeValue = getValueAtPath(localeContent, key) @@ -231,6 +259,8 @@ async function checkAreaTranslations(area) { } } + missingKeys.push(...findMissingPluralKeys(localeContent, englishPluralBases.get(name))) + if (missingKeys.length > 0) { missingTranslations[locale][name] = missingKeys } diff --git a/scripts/find-missing-translations.test.mjs b/scripts/find-missing-translations.test.mjs new file mode 100644 index 0000000000..822adfc7ad --- /dev/null +++ b/scripts/find-missing-translations.test.mjs @@ -0,0 +1,188 @@ +import assert from "node:assert/strict" +import { describe, it } from "node:test" + +import { commonFiles, en, ja, locales, ru, runScript } from "./lib/translation-fixture.mjs" + +const run = (files, args) => runScript("find-missing-translations.js", files, args) + +// Plural fixtures in a single common.json per locale. +const checkPlurals = (byLocale) => run(commonFiles(byLocale), ["--area=core"]) + +describe("find-missing-translations keys", () => { + const en = { "common.json": { title: "Title", errors: { notFound: "Not found" } } } + + it("accepts a locale that has every English key", () => { + const { status, output } = run( + locales("core", { en, ru: { "common.json": { title: "Заголовок", errors: { notFound: "Не найдено" } } } }), + ["--area=core"], + ) + assert.equal(status, 0, output) + assert.match(output, /✅ ru: No missing translations/) + }) + + it("accepts extra keys that English does not have", () => { + const ru = { "common.json": { title: "Заголовок", errors: { notFound: "Не найдено", old: "Старое" } } } + const { status, output } = run(locales("core", { en, ru }), ["--area=core"]) + assert.equal(status, 0, output) + }) + + it("reports a missing nested key with its English value", () => { + const { status, output } = run(locales("core", { en, ru: { "common.json": { title: "Заголовок" } } }), [ + "--area=core", + ]) + assert.equal(status, 1, output) + assert.match(output, /📝 ru:/) + assert.match(output, /common\.json: 1 missing translations/) + assert.match(output, /errors\.notFound: "Not found"/) + }) + + it("reports a locale file that is missing entirely", () => { + const { status, output } = run( + locales("core", { en: { ...en, "chat.json": { send: "Send" } }, ru: { "common.json": en["common.json"] } }), + ["--area=core"], + ) + assert.equal(status, 1, output) + assert.match(output, /chat\.json: File is missing entirely/) + }) + + it("checks the webview locales with --area=webview", () => { + const { status, output } = run(locales("webview", { en, ru: { "common.json": { title: "Заголовок" } } }), [ + "--area=webview", + ]) + assert.equal(status, 1, output) + assert.match(output, /FRONTEND Missing Translations Report/) + assert.match(output, /errors\.notFound/) + }) + + it("fails on a locale file that is not valid JSON", () => { + const { status, output } = run(locales("core", { en, ru: { "common.json": "{ not json" } }), ["--area=core"]) + assert.equal(status, 1, output) + assert.match(output, /Error parsing JSON file .*ru.*common\.json/) + }) +}) + +describe("find-missing-translations options", () => { + const fixture = locales("core", { + en: { "common.json": { title: "Title" }, "chat.json": { send: "Send" } }, + ru: { "common.json": {}, "chat.json": { send: "Отправить" } }, + ja: { "common.json": { title: "タイトル" }, "chat.json": {} }, + }) + + it("--locale checks only that locale", () => { + const { status, output } = run(fixture, ["--area=core", "--locale=ja"]) + assert.equal(status, 1, output) + assert.match(output, /chat\.json: 1 missing translations/) + assert.doesNotMatch(output, /ru:/) + }) + + it("--file checks only that file", () => { + const { status, output } = run(fixture, ["--area=core", "--file=chat.json"]) + assert.equal(status, 1, output) + assert.match(output, /send: "Send"/) + assert.doesNotMatch(output, /title: "Title"/) + }) + + it("passes when the filtered locale and file are complete", () => { + const { status, output } = run(fixture, ["--area=core", "--locale=ru", "--file=chat.json"]) + assert.equal(status, 0, output) + }) + + for (const [name, args, expected] of [ + ["an unknown locale", ["--area=core", "--locale=xx"], /Locale 'xx' not found/], + ["an unknown file", ["--area=core", "--file=missing.json"], /File 'missing\.json' not found/], + ["an unknown area", ["--area=backend"], /Invalid area 'backend'/], + ]) { + it(`fails on ${name}`, () => { + const { status, output } = run(fixture, args) + assert.equal(status, 1, output) + assert.match(output, expected) + }) + } + + it("--help prints usage without checking", () => { + const { status, output } = run({}, ["--help"]) + assert.equal(status, 0, output) + assert.match(output, /Usage:/) + assert.doesNotMatch(output, /Starting translation check/) + }) +}) + +describe("find-missing-translations package.nls", () => { + const base = { "extension.displayName": "Zoo Code", "command.newTask": "New Task" } + + it("accepts a locale file that has every base key", () => { + const { status, output } = run( + { "src/package.nls.json": base, "src/package.nls.ru.json": { ...base, "command.newTask": "Новая задача" } }, + ["--area=package-nls"], + ) + assert.equal(status, 0, output) + }) + + it("reports a key missing from a locale file", () => { + const { status, output } = run( + { "src/package.nls.json": base, "src/package.nls.ru.json": { "extension.displayName": "Zoo Code" } }, + ["--area=package-nls"], + ) + assert.equal(status, 1, output) + assert.match(output, /command\.newTask: "New Task"/) + }) + + it("fails on a nested object in a locale file", () => { + const { status, output } = run( + { + "src/package.nls.json": base, + "src/package.nls.ru.json": { ...base, command: { newTask: "Новая задача" } }, + }, + ["--area=package-nls"], + ) + assert.equal(status, 1, output) + assert.match(output, /should be a flat JSON structure. Found nested object at key 'command'/) + }) + + it("skips the check when the base file is missing", () => { + const { status, output } = run({ "src/package.nls.ru.json": base }, ["--area=package-nls"]) + assert.equal(status, 0, output) + assert.match(output, /Base package\.nls\.json not found/) + }) +}) + +describe("find-missing-translations plural keys", () => { + it("accepts a locale with the CLDR forms of each plural key", () => { + const { status, output } = checkPlurals({ en, ru, ja, fr: { ...en, files_many: "{{count}} fichiers" } }) + assert.equal(status, 0, output) + }) + + it("reports a plural key when the locale has no key with its base name", () => { + const { status, output } = checkPlurals({ en, ru: { other_one: "{{count}} другой" } }) + assert.equal(status, 1, output) + assert.match(output, /common\.json: 1 missing translations/) + assert.match(output, /files_\*: "\{\{count\}\} files"/) + }) + + it("reports a plural key once, however many forms the locale needs", () => { + const { output } = checkPlurals({ en: { ...en, files_zero: "No files" }, ru: {} }) + assert.equal(output.match(/files_/g).length, 1, output) + }) + + // validate-plural-forms.js checks the forms; a missing-translations check must not fail on them + for (const [name, byLocale] of [ + ["a missing CLDR form", { en, ru: { ...ru, files_few: undefined } }], + ["a missing many form in fr", { en, fr: en }], + ["a missing zero override that English has", { en: { ...en, files_zero: "No files" }, ru }], + ["an extra form the locale does not have", { en, ja: { ...ja, files_one: "1 ファイル" } }], + ["a bare key next to plural forms", { en, ru: { ...ru, files: "{{count}} файл" } }], + ["a bare key in place of the plural forms", { en, ru: { files: "{{count}} файлов" } }], + ["English with only _other", { en: { files_other: en.files_other }, ja }], + ]) { + it(`accepts ${name}`, () => { + const { status, output } = checkPlurals(byLocale) + assert.equal(status, 0, output) + }) + } + + it("still reports missing keys that are not plural", () => { + const { status, output } = checkPlurals({ en: { ...en, title: "Files" }, ru }) + assert.equal(status, 1, output) + assert.match(output, /title: "Files"/) + }) +}) diff --git a/scripts/lib/plural-forms.js b/scripts/lib/plural-forms.js new file mode 100644 index 0000000000..c0e2566b5a --- /dev/null +++ b/scripts/lib/plural-forms.js @@ -0,0 +1,38 @@ +/** + * Plural key helpers shared by find-missing-translations.js and validate-plural-forms.js. + * + * i18next picks a plural form with Intl.PluralRules (CLDR) and looks it up as a key suffix: + * "files_one", "files_few", "files_many", "files_other". "_zero" is an i18next override for count 0. + */ + +const PLURAL_FORMS = ["zero", "one", "two", "few", "many", "other"] + +// i18next plural keys: "files_one", "files_few", ... +const PLURAL_KEY = new RegExp(`^(.*)_(${PLURAL_FORMS.join("|")})$`) + +// Groups English plural keys by base name: "files_one", "files_other" -> "files". +// `values` maps each dotted key to its English string. +function findPluralBases(values) { + const pluralBases = new Map() + + for (const [key, value] of values) { + const plural = key.match(PLURAL_KEY) + if (!plural) continue + + const [, base, form] = plural + if (!pluralBases.has(base)) pluralBases.set(base, { hasZero: false, englishValue: value }) + if (form === "zero") pluralBases.get(base).hasZero = true + if (form === "other") pluralBases.get(base).englishValue = value + } + + return pluralBases +} + +// The forms a locale needs for one plural key: its CLDR categories (e.g. ru: one, few, many, other; ja: other), +// plus "zero" when the English key has that override. Sorted from "zero" to "other" for readable reports. +function requiredPluralForms(locale, { hasZero }) { + const categories = new Intl.PluralRules(locale).resolvedOptions().pluralCategories + return PLURAL_FORMS.filter((form) => categories.includes(form) || (hasZero && form === "zero")) +} + +module.exports = { PLURAL_FORMS, PLURAL_KEY, findPluralBases, requiredPluralForms } diff --git a/scripts/lib/translation-fixture.mjs b/scripts/lib/translation-fixture.mjs new file mode 100644 index 0000000000..abe57df247 --- /dev/null +++ b/scripts/lib/translation-fixture.mjs @@ -0,0 +1,58 @@ +// Test helper for the translation scripts: runs a real script against a throwaway repository layout. + +import { spawnSync } from "node:child_process" +import { cpSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs" +import { tmpdir } from "node:os" +import path from "node:path" +import { fileURLToPath } from "node:url" + +const scriptsDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..") + +// The scripts resolve the locale directories relative to themselves, so a copy sees only these files. +// `files` maps a path relative to the repository root to JSON content, or to raw text. +export function runScript(script, files, args) { + const root = mkdtempSync(path.join(tmpdir(), "zoo-translations-check-")) + try { + cpSync(path.join(scriptsDir, script), path.join(root, "scripts", script)) + cpSync(path.join(scriptsDir, "lib"), path.join(root, "scripts", "lib"), { recursive: true }) + for (const [file, content] of Object.entries(files)) { + mkdirSync(path.dirname(path.join(root, file)), { recursive: true }) + writeFileSync(path.join(root, file), typeof content === "string" ? content : JSON.stringify(content)) + } + const result = spawnSync(process.execPath, [path.join("scripts", script), ...args], { + cwd: root, + encoding: "utf8", + }) + return { status: result.status, output: result.stdout + result.stderr } + } finally { + rmSync(root, { recursive: true, force: true }) + } +} + +// { ru: { "common.json": {...} } } -> files under src/i18n/locales (core) or webview-ui/src/i18n/locales +export function locales(area, byLocale) { + const dir = area === "core" ? "src/i18n/locales" : "webview-ui/src/i18n/locales" + return Object.fromEntries( + Object.entries(byLocale).flatMap(([locale, files]) => + Object.entries(files).map(([file, content]) => [`${dir}/${locale}/${file}`, content]), + ), + ) +} + +// { ru: {...} } -> one common.json per locale under src/i18n/locales +export function commonFiles(byLocale) { + return locales( + "core", + Object.fromEntries(Object.entries(byLocale).map(([locale, content]) => [locale, { "common.json": content }])), + ) +} + +// Plural fixtures shared by both test files +export const en = { files_one: "{{count}} file", files_other: "{{count}} files" } +export const ru = { + files_one: "{{count}} файл", + files_few: "{{count}} файла", + files_many: "{{count}} файлов", + files_other: "{{count}} файла", +} +export const ja = { files_other: "{{count}} ファイル" } diff --git a/scripts/validate-plural-forms.js b/scripts/validate-plural-forms.js new file mode 100755 index 0000000000..d6c9e45fd4 --- /dev/null +++ b/scripts/validate-plural-forms.js @@ -0,0 +1,245 @@ +/** + * Script to validate i18next plural keys against the CLDR plural rules of every locale, English included + * + * Usage: + * node scripts/validate-plural-forms.js [options] + * + * Options: + * --locale= Only check a specific locale (e.g. --locale=ru or --locale=en) + * --file= Only check a specific file (e.g. --file=chat.json) + * --area= Only check a specific area (core, webview, or all) + * --help Show this help message + */ + +const path = require("path") +const fs = require("fs") +const { PLURAL_FORMS, findPluralBases, requiredPluralForms } = require("./lib/plural-forms") + +// Process command line arguments +const args = process.argv.slice(2).reduce( + (acc, arg) => { + if (arg === "--help") { + acc.help = true + } else if (arg.startsWith("--locale=")) { + acc.locale = arg.split("=")[1] + } else if (arg.startsWith("--file=")) { + acc.file = arg.split("=")[1] + } else if (arg.startsWith("--area=")) { + acc.area = arg.split("=")[1] + if (!["core", "webview", "all"].includes(acc.area)) { + console.error(`Error: Invalid area '${acc.area}'. Must be 'core', 'webview', or 'all'.`) + process.exit(1) + } + } + return acc + }, + { area: "all" }, +) + +if (args.help) { + console.log(` +Validate Plural Forms + +Checks that every plural key has exactly the CLDR plural forms of each locale, English included: + - no missing form (ru needs one, few, many, other; ja needs only other) + - {{count}} in every form except "zero" (ru "one" also covers 21, fr "one" also covers 0) + - no form the locale does not have (no _one in ja) + - no bare key next to the plural forms (i18next uses it in place of a missing form) + +The English plural keys decide which keys are plural. Missing locale files are reported +by find-missing-translations.js, so this script skips them. + +Usage: + node scripts/validate-plural-forms.js [options] + +Options: + --locale= Only check a specific locale (e.g. --locale=ru or --locale=en) + --file= Only check a specific file (e.g. --file=chat.json) + --area= Only check a specific area (core, webview, or all) + 'core' = Backend (src/i18n/locales) + 'webview' = Frontend UI (webview-ui/src/i18n/locales) + 'all' = Check all areas (default) + --help Show this help message + `) + process.exit(0) +} + +const LOCALES_DIRS = { + core: path.join(__dirname, "../src/i18n/locales"), + webview: path.join(__dirname, "../webview-ui/src/i18n/locales"), +} + +// { a: { b: "x" } } -> Map { "a.b" => "x" } +function flatten(obj, parentKey = "", values = new Map()) { + for (const [key, value] of Object.entries(obj)) { + const currentKey = parentKey ? `${parentKey}.${key}` : key + if (typeof value === "object" && value !== null) { + flatten(value, currentKey, values) + } else { + values.set(currentKey, value) + } + } + return values +} + +function readJson(filePath) { + if (!fs.existsSync(filePath)) return null + try { + return JSON.parse(fs.readFileSync(filePath, "utf8")) + } catch (error) { + console.error(`Error parsing JSON file '${filePath}': ${error.message}`) + process.exit(1) + } +} + +// {{count}}, {{count, number}} and {{- count}} +const COUNT_PLACEHOLDER = /\{\{-?\s*count\s*(,[^}]*)?\}\}/ + +// Each English plural key must have exactly the locale's forms, each with {{count}} (except the "zero" override), +// and no bare key next to them +function validatePluralForms(locale, values, pluralBases) { + const problems = [] + + for (const [base, entry] of pluralBases) { + const required = requiredPluralForms(locale, entry) + + for (const form of required) { + const value = values.get(`${base}_${form}`) + if (value === undefined) { + problems.push({ type: "missing", key: `${base}_${form}`, problem: `missing the "${form}" plural form` }) + } else if (form !== "zero" && typeof value === "string" && !COUNT_PLACEHOLDER.test(value)) { + // "_one" also covers 21 in ru and 0 in fr, so a hardcoded "1" shows the wrong number + problems.push({ + type: "nocount", + key: `${base}_${form}`, + problem: `the "${form}" form has no {{count}} placeholder`, + }) + } + } + + for (const form of PLURAL_FORMS) { + if (!required.includes(form) && values.has(`${base}_${form}`)) { + problems.push({ + type: "extra", + key: `${base}_${form}`, + problem: `"${form}" is not a CLDR plural form for ${locale}; remove it`, + }) + } + } + + if (typeof values.get(base) === "string") { + problems.push({ type: "bare", key: base, problem: "bare key next to plural forms; remove it" }) + } + } + + return problems +} + +function validateArea(area) { + const localesDir = LOCALES_DIRS[area] + const allLocales = fs + .readdirSync(localesDir) + .filter((item) => fs.statSync(path.join(localesDir, item)).isDirectory()) + .sort() + const locales = args.locale ? allLocales.filter((locale) => locale === args.locale) : allLocales + + if (args.locale && locales.length === 0) { + console.error(`Error: Locale '${args.locale}' not found in ${localesDir}`) + process.exit(1) + } + + const englishDir = path.join(localesDir, "en") + let englishFiles = fs.readdirSync(englishDir).filter((file) => file.endsWith(".json") && !file.startsWith(".")) + + if (args.file) { + if (!englishFiles.includes(args.file)) { + // With --area=all the file is in one of the areas; the caller fails if it is in none + if (args.area === "all") return null + console.error(`Error: File '${args.file}' not found in ${englishDir}`) + process.exit(1) + } + englishFiles = englishFiles.filter((file) => file === args.file) + } + + const title = area === "core" ? "BACKEND" : "FRONTEND" + console.log(`\n${title} - Checking plural forms in ${locales.length} locale(s): ${locales.join(", ")}\n`) + + const pluralBases = new Map( + englishFiles.map((file) => [file, findPluralBases(flatten(readJson(path.join(englishDir, file))))]), + ) + const report = [] + + for (const locale of locales) { + const problemsByFile = [] + + for (const file of englishFiles) { + const content = readJson(path.join(localesDir, locale, file)) + if (!content) continue + + const problems = validatePluralForms(locale, flatten(content), pluralBases.get(file)) + if (problems.length > 0) problemsByFile.push({ file, problems }) + } + + if (problemsByFile.length === 0) { + console.log(`✅ ${locale}: Plural forms are correct`) + continue + } + + console.log(`📝 ${locale}:`) + for (const { file, problems } of problemsByFile) { + console.log(` - ${file}: ${problems.length} plural form problem(s)`) + for (const { key, problem } of problems) { + console.log(` ${key}: ${problem}`) + } + report.push({ area, locale, file, problems }) + } + console.log("") + } + + return report +} + +// Counts the problems of every checked area by type +function printStatistics(report) { + const problems = report.flatMap((entry) => entry.problems) + const count = (type) => problems.filter((problem) => problem.type === type).length + const locales = new Set(report.map((entry) => entry.locale)) + + console.log("\nPlural Forms Statistics:\n") + console.log(` Missing plural forms: ${count("missing")}`) + console.log(` Forms without {{count}}: ${count("nocount")}`) + console.log(` Forms that are not CLDR plural forms: ${count("extra")}`) + console.log(` Bare keys next to plural forms: ${count("bare")}`) + console.log(` Total problems: ${problems.length}`) + console.log(` Locale files with problems: ${report.length}`) + console.log(` Locales with problems: ${locales.size}`) +} + +const areas = args.area === "all" ? ["core", "webview"] : [args.area] +const reports = areas.map(validateArea).filter((areaReport) => areaReport !== null) + +if (reports.length === 0) { + console.error( + `Error: File '${args.file}' not found in ${areas.map((area) => LOCALES_DIRS[area] + "/en").join(" or ")}`, + ) + process.exit(1) +} + +const report = reports.flat() + +if (report.length > 0) { + printStatistics(report) + console.log("\n✏️ To fix the plural form problems:") + console.log( + "1. List the plural forms of a locale with: node -p 'new Intl.PluralRules(\"\").resolvedOptions().pluralCategories'", + ) + console.log( + "2. Synchronize the plural forms of each key with that list: add each missing form, translated from the English plural key, and remove each form that is not in the list", + ) + console.log('3. Put {{count}} in every form, including "one", instead of a hardcoded number') + console.log("4. Remove each bare key that is next to plural forms") + console.log("5. Run this script again to verify that all plural forms are correct") + process.exit(1) +} + +console.log("\n✅ All plural forms follow the CLDR rules of their locales!") diff --git a/scripts/validate-plural-forms.test.mjs b/scripts/validate-plural-forms.test.mjs new file mode 100644 index 0000000000..217c22a774 --- /dev/null +++ b/scripts/validate-plural-forms.test.mjs @@ -0,0 +1,232 @@ +import assert from "node:assert/strict" +import { describe, it } from "node:test" + +import { commonFiles, en, ja, locales, ru, runScript } from "./lib/translation-fixture.mjs" + +const run = (files, args) => runScript("validate-plural-forms.js", files, args) +const validate = (byLocale, args = []) => run(commonFiles(byLocale), ["--area=core", ...args]) + +describe("validate-plural-forms", () => { + it("accepts exactly the CLDR forms in every locale, English included", () => { + const { status, output } = validate({ en, ru, ja, fr: { ...en, files_many: "{{count}} fichiers" } }) + assert.equal(status, 0, output) + for (const locale of ["en", "fr", "ja", "ru"]) { + assert.match(output, new RegExp(`✅ ${locale}: Plural forms are correct`)) + } + }) + + it("accepts a zero override when every locale has it", () => { + const { status, output } = validate({ + en: { ...en, files_zero: "No files" }, + ru: { ...ru, files_zero: "Нет файлов" }, + }) + assert.equal(status, 0, output) + }) + + it("accepts formatted and unescaped {{count}} placeholders", () => { + const { status, output } = validate({ + en: { files_one: "{{count, number}} file", files_other: "{{- count}} files" }, + ja: { files_other: "{{ count }} ファイル" }, + }) + assert.equal(status, 0, output) + }) + + it("lists missing forms from zero to other", () => { + const { status, output } = validate({ en: { ...en, files_zero: "No files" }, fr: {}, ru: {} }) + assert.equal(status, 1, output) + const forms = (locale) => + [ + ...output + .split(`📝 ${locale}:`)[1] + .split("📝")[0] + .matchAll(/files_(\w+): missing/g), + ].map(([, form]) => form) + assert.deepEqual(forms("fr"), ["zero", "one", "many", "other"]) + assert.deepEqual(forms("ru"), ["zero", "one", "few", "many", "other"]) + }) + + it("prints statistics by problem type and the steps to fix them", () => { + const { status, output } = validate({ + en, + ru: { ...ru, files_one: "1 файл", files_few: undefined, files: "{{count}} файл" }, + ja: { ...ja, files_one: "1 ファイル" }, + }) + assert.equal(status, 1, output) + assert.match(output, /Missing plural forms: +1\n/) + assert.match(output, /Forms without \{\{count\}\}: +1\n/) + assert.match(output, /Forms that are not CLDR plural forms: +1\n/) + assert.match(output, /Bare keys next to plural forms: +1\n/) + assert.match(output, /Total problems: +4\n/) + assert.match(output, /Locale files with problems: +2\n/) + assert.match(output, /Locales with problems: +2\n/) + const steps = [...output.split("To fix the plural form problems:")[1].matchAll(/^(\d)\. /gm)].map(([, n]) => n) + assert.deepEqual(steps, ["1", "2", "3", "4", "5"]) + }) + + it("prints no statistics when every plural form is correct", () => { + const { status, output } = validate({ en, ru, ja }) + assert.equal(status, 0, output) + assert.doesNotMatch(output, /Plural Forms Statistics|To fix the plural form problems/) + }) + + it("ignores keys that are not plural", () => { + const { status, output } = validate({ en: { ...en, title: "Files" }, ja }) + assert.equal(status, 0, output) + }) + + for (const [name, byLocale, locale, expected] of [ + [ + "a missing CLDR form", + { en, ru: { ...ru, files_few: undefined } }, + "ru", + /files_few: missing the "few" plural form/, + ], + ["a missing many form in fr", { en, fr: en }, "fr", /files_many: missing the "many" plural form/], + [ + "a form the locale does not have", + { en, ja: { ...ja, files_one: "1 ファイル" } }, + "ja", + /files_one: "one" is not a CLDR plural form for ja; remove it/, + ], + [ + "a bare key next to plural forms", + { en, ru: { ...ru, files: "{{count}} файл" } }, + "ru", + /files: bare key next to plural forms; remove it/, + ], + [ + "a missing zero override that English has", + { en: { ...en, files_zero: "No files" }, ru }, + "ru", + /files_zero: missing the "zero" plural form/, + ], + ["English with only _other", { en: { files_other: en.files_other }, ja }, "en", /files_one: missing the "one"/], + [ + "a form English does not have", + { en: { ...en, files_few: "{{count}} files" }, ja }, + "en", + /files_few: "few" is not a CLDR plural form for en/, + ], + [ + "a bare key next to plural forms in English", + { en: { ...en, files: "{{count}} file" }, ja }, + "en", + /files: bare key next to plural forms/, + ], + [ + "a bare key in place of the plural forms", + { en, ru: { files: "{{count}} файлов" } }, + "ru", + /files_few: missing the "few" plural form/, + ], + [ + "a hardcoded number in place of {{count}}", + { en, ru: { ...ru, files_one: "1 файл" } }, + "ru", + /files_one: the "one" form has no \{\{count\}\} placeholder/, + ], + [ + "an English form without {{count}}", + { en: { ...en, files_one: "One file" }, ja }, + "en", + /files_one: the "one" form has no \{\{count\}\} placeholder/, + ], + ]) { + it(`rejects ${name}`, () => { + const { status, output } = validate(byLocale) + assert.equal(status, 1, output) + assert.match(output, new RegExp(`📝 ${locale}:`)) + assert.match(output, expected) + }) + } + + it("skips a locale file that is missing, which find-missing-translations.js reports", () => { + const files = locales("core", { en: { "common.json": en, "chat.json": en }, ja: { "common.json": ja } }) + const { status, output } = run(files, ["--area=core"]) + assert.equal(status, 0, output) + }) + + it("checks the webview locales with --area=webview", () => { + const files = locales("webview", { en: { "chat.json": en }, ja: { "chat.json": { ...ja, files_one: "1" } } }) + const { status, output } = run(files, ["--area=webview"]) + assert.equal(status, 1, output) + assert.match(output, /FRONTEND - Checking plural forms/) + assert.match(output, /files_one: "one" is not a CLDR plural form for ja/) + }) +}) + +describe("validate-plural-forms options", () => { + const fixture = commonFiles({ en: { files_other: en.files_other }, ja: { ...ja, files_one: "1" } }) + + it("--locale=en checks only English", () => { + const { status, output } = run(fixture, ["--area=core", "--locale=en"]) + assert.equal(status, 1, output) + assert.match(output, /📝 en:/) + assert.doesNotMatch(output, /ja/) + }) + + it("--locale checks only that locale", () => { + const { status, output } = run(fixture, ["--area=core", "--locale=ja"]) + assert.equal(status, 1, output) + assert.match(output, /📝 ja:/) + assert.doesNotMatch(output, /en:/) + }) + + it("--file checks only that file", () => { + const files = locales("core", { + en: { "common.json": en, "chat.json": en }, + ja: { "common.json": ja, "chat.json": { ...ja, files_one: "1" } }, + }) + const { status, output } = run(files, ["--area=core", "--file=common.json"]) + assert.equal(status, 0, output) + }) + + const webviewOnlyFile = (jaChat) => ({ + ...commonFiles({ en, ja }), + ...locales("webview", { en: { "chat.json": en }, ja: { "chat.json": jaChat } }), + }) + + it("--file without --area checks the area that has the file", () => { + const accepted = run(webviewOnlyFile(ja), ["--file=chat.json"]) + assert.equal(accepted.status, 0, accepted.output) + assert.match(accepted.output, /FRONTEND - Checking plural forms/) + assert.doesNotMatch(accepted.output, /BACKEND/) + + const rejected = run(webviewOnlyFile({ ...ja, files_one: "1" }), ["--file=chat.json"]) + assert.equal(rejected.status, 1, rejected.output) + assert.match(rejected.output, /files_one: "one" is not a CLDR plural form for ja/) + }) + + it("--file without --area fails when no area has the file", () => { + const { status, output } = run(webviewOnlyFile(ja), ["--file=missing.json"]) + assert.equal(status, 1, output) + assert.match(output, /File 'missing\.json' not found/) + }) + + for (const [name, args, expected] of [ + ["an unknown locale", ["--area=core", "--locale=xx"], /Locale 'xx' not found/], + ["an unknown file", ["--area=core", "--file=missing.json"], /File 'missing\.json' not found/], + ["an unknown area", ["--area=package-nls"], /Invalid area 'package-nls'/], + ]) { + it(`fails on ${name}`, () => { + const { status, output } = run(fixture, args) + assert.equal(status, 1, output) + assert.match(output, expected) + }) + } + + it("fails on a locale file that is not valid JSON", () => { + const { status, output } = run({ ...commonFiles({ en }), "src/i18n/locales/ru/common.json": "{ not json" }, [ + "--area=core", + ]) + assert.equal(status, 1, output) + assert.match(output, /Error parsing JSON file .*ru.*common\.json/) + }) + + it("--help prints usage without checking", () => { + const { status, output } = run({}, ["--help"]) + assert.equal(status, 0, output) + assert.match(output, /Usage:/) + assert.doesNotMatch(output, /Checking plural forms/) + }) +}) diff --git a/src/i18n/locales/ca/common.json b/src/i18n/locales/ca/common.json index d414d697f2..d61f6861c9 100644 --- a/src/i18n/locales/ca/common.json +++ b/src/i18n/locales/ca/common.json @@ -130,6 +130,7 @@ "rooHistoryImport": { "nothingFound": "No s'ha trobat historial de tasques de Roo Code per importar de {{domain}}.", "alreadyImported_one": "Tot l'historial de tasca de Roo Code ({{count}}) ja s'ha importat a Zoo Code.", + "alreadyImported_many": "Tots els {{count}} historials de tasques de Roo Code ja s'han importat a Zoo Code.", "alreadyImported_other": "Tots els {{count}} historials de tasques de Roo Code ja s'han importat a Zoo Code." } }, @@ -148,6 +149,7 @@ }, "rooHistoryImport": { "success_one": "S'ha importat {{count}} historial de tasca de Roo Code a Zoo Code.", + "success_many": "S'han importat {{count}} historials de tasques de Roo Code a Zoo Code.", "success_other": "S'han importat {{count}} historials de tasques de Roo Code a Zoo Code." } }, diff --git a/src/i18n/locales/ca/mcp.json b/src/i18n/locales/ca/mcp.json index 8e7e94ee6c..2bfbec328b 100644 --- a/src/i18n/locales/ca/mcp.json +++ b/src/i18n/locales/ca/mcp.json @@ -7,7 +7,9 @@ "invalidJsonArgument": "Zoo ha intentat utilitzar {{toolName}} amb un argument JSON no vàlid. Tornant a intentar...", "refresh_after_disable": "Ha fallat l'actualització de les connexions MCP després de desactivar", "refresh_after_enable": "Ha fallat l'actualització de les connexions MCP després d'activar", - "disconnect_servers_partial": "Ha fallat la desconnexió de {{count}} servidor(s) MCP. Comprova la sortida per més detalls.", + "disconnect_servers_partial_one": "Ha fallat la desconnexió de {{count}} servidor MCP. Comprova la sortida per més detalls.", + "disconnect_servers_partial_many": "Ha fallat la desconnexió de {{count}} servidors MCP. Comprova la sortida per més detalls.", + "disconnect_servers_partial_other": "Ha fallat la desconnexió de {{count}} servidors MCP. Comprova la sortida per més detalls.", "toolNotFound": "L'eina '{{toolName}}' no existeix al servidor '{{serverName}}'. Eines disponibles: {{availableTools}}", "serverNotFound": "El servidor MCP '{{serverName}}' no està configurat. Servidors disponibles: {{availableServers}}", "toolDisabled": "L'eina '{{toolName}}' del servidor '{{serverName}}' està desactivada. Eines activades disponibles: {{availableTools}}" diff --git a/src/i18n/locales/de/mcp.json b/src/i18n/locales/de/mcp.json index 167d93e3b6..be492a0268 100644 --- a/src/i18n/locales/de/mcp.json +++ b/src/i18n/locales/de/mcp.json @@ -7,7 +7,8 @@ "invalidJsonArgument": "Zoo hat versucht, {{toolName}} mit einem ungültigen JSON-Argument zu verwenden. Wiederhole...", "refresh_after_disable": "Fehler beim Aktualisieren der MCP-Verbindungen nach dem Deaktivieren", "refresh_after_enable": "Fehler beim Aktualisieren der MCP-Verbindungen nach dem Aktivieren", - "disconnect_servers_partial": "Fehler beim Trennen von {{count}} MCP-Server(n). Überprüfe die Ausgabe für Details.", + "disconnect_servers_partial_one": "Fehler beim Trennen von {{count}} MCP-Server. Überprüfe die Ausgabe für Details.", + "disconnect_servers_partial_other": "Fehler beim Trennen von {{count}} MCP-Servern. Überprüfe die Ausgabe für Details.", "toolNotFound": "Tool '{{toolName}}' existiert nicht auf Server '{{serverName}}'. Verfügbare Tools: {{availableTools}}", "serverNotFound": "MCP-Server '{{serverName}}' ist nicht konfiguriert. Verfügbare Server: {{availableServers}}", "toolDisabled": "Tool '{{toolName}}' auf Server '{{serverName}}' ist deaktiviert. Verfügbare aktivierte Tools: {{availableTools}}" diff --git a/src/i18n/locales/en/mcp.json b/src/i18n/locales/en/mcp.json index bd09dbd081..e309bbd7b8 100644 --- a/src/i18n/locales/en/mcp.json +++ b/src/i18n/locales/en/mcp.json @@ -7,7 +7,8 @@ "invalidJsonArgument": "Zoo tried to use {{toolName}} with an invalid JSON argument. Retrying...", "refresh_after_disable": "Failed to refresh MCP connections after disabling", "refresh_after_enable": "Failed to refresh MCP connections after enabling", - "disconnect_servers_partial": "Failed to disconnect {{count}} MCP server(s). Check the output for details.", + "disconnect_servers_partial_one": "Failed to disconnect {{count}} MCP server. Check the output for details.", + "disconnect_servers_partial_other": "Failed to disconnect {{count}} MCP servers. Check the output for details.", "toolNotFound": "Tool '{{toolName}}' does not exist on server '{{serverName}}'. Available tools: {{availableTools}}", "serverNotFound": "MCP server '{{serverName}}' is not configured. Available servers: {{availableServers}}", "toolDisabled": "Tool '{{toolName}}' on server '{{serverName}}' is disabled. Available enabled tools: {{availableTools}}" diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json index 5b959f6e2f..851b078187 100644 --- a/src/i18n/locales/es/common.json +++ b/src/i18n/locales/es/common.json @@ -126,6 +126,7 @@ "rooHistoryImport": { "nothingFound": "No se encontró historial de tareas de Roo Code para importar desde {{domain}}.", "alreadyImported_one": "El historial de {{count}} tarea de Roo Code ya ha sido importado en Zoo Code.", + "alreadyImported_many": "Los {{count}} historiales de tareas de Roo Code ya han sido importados en Zoo Code.", "alreadyImported_other": "Los {{count}} historiales de tareas de Roo Code ya han sido importados en Zoo Code." } }, @@ -144,6 +145,7 @@ }, "rooHistoryImport": { "success_one": "Se importó {{count}} historial de tarea de Roo Code en Zoo Code.", + "success_many": "Se importaron {{count}} historiales de tareas de Roo Code en Zoo Code.", "success_other": "Se importaron {{count}} historiales de tareas de Roo Code en Zoo Code." } }, diff --git a/src/i18n/locales/es/mcp.json b/src/i18n/locales/es/mcp.json index 24caac50a5..a65d37a500 100644 --- a/src/i18n/locales/es/mcp.json +++ b/src/i18n/locales/es/mcp.json @@ -7,7 +7,9 @@ "invalidJsonArgument": "Zoo intentó usar {{toolName}} con un argumento JSON no válido. Reintentando...", "refresh_after_disable": "Error al actualizar las conexiones MCP después de desactivar", "refresh_after_enable": "Error al actualizar las conexiones MCP después de activar", - "disconnect_servers_partial": "Error al desconectar {{count}} servidor(es) MCP. Revisa la salida para más detalles.", + "disconnect_servers_partial_one": "Error al desconectar {{count}} servidor MCP. Revisa la salida para más detalles.", + "disconnect_servers_partial_many": "Error al desconectar {{count}} servidores MCP. Revisa la salida para más detalles.", + "disconnect_servers_partial_other": "Error al desconectar {{count}} servidores MCP. Revisa la salida para más detalles.", "toolNotFound": "La herramienta '{{toolName}}' no existe en el servidor '{{serverName}}'. Herramientas disponibles: {{availableTools}}", "serverNotFound": "El servidor MCP '{{serverName}}' no está configurado. Servidores disponibles: {{availableServers}}", "toolDisabled": "La herramienta '{{toolName}}' del servidor '{{serverName}}' está desactivada. Herramientas activadas disponibles: {{availableTools}}" diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json index 03e911de49..2fbbda3db3 100644 --- a/src/i18n/locales/fr/common.json +++ b/src/i18n/locales/fr/common.json @@ -126,6 +126,7 @@ "rooHistoryImport": { "nothingFound": "Aucun historique de tâches Roo Code trouvé à importer depuis {{domain}}.", "alreadyImported_one": "L'historique de {{count}} tâche Roo Code a déjà été importé dans Zoo Code.", + "alreadyImported_many": "Les {{count}} historiques de tâches Roo Code ont déjà été importés dans Zoo Code.", "alreadyImported_other": "Les {{count}} historiques de tâches Roo Code ont déjà été importés dans Zoo Code." } }, @@ -144,6 +145,7 @@ }, "rooHistoryImport": { "success_one": "{{count}} historique de tâche Roo Code importé dans Zoo Code.", + "success_many": "{{count}} historiques de tâches Roo Code importés dans Zoo Code.", "success_other": "{{count}} historiques de tâches Roo Code importés dans Zoo Code." } }, diff --git a/src/i18n/locales/fr/mcp.json b/src/i18n/locales/fr/mcp.json index 6672f1541b..ba05cc0e9c 100644 --- a/src/i18n/locales/fr/mcp.json +++ b/src/i18n/locales/fr/mcp.json @@ -7,7 +7,9 @@ "invalidJsonArgument": "Zoo a essayé d'utiliser {{toolName}} avec un argument JSON invalide. Nouvelle tentative...", "refresh_after_disable": "Échec du rafraîchissement des connexions MCP après désactivation", "refresh_after_enable": "Échec du rafraîchissement des connexions MCP après activation", - "disconnect_servers_partial": "Échec de la déconnexion de {{count}} serveur(s) MCP. Vérifiez la sortie pour plus de détails.", + "disconnect_servers_partial_one": "Échec de la déconnexion de {{count}} serveur MCP. Vérifiez la sortie pour plus de détails.", + "disconnect_servers_partial_many": "Échec de la déconnexion de {{count}} serveurs MCP. Vérifiez la sortie pour plus de détails.", + "disconnect_servers_partial_other": "Échec de la déconnexion de {{count}} serveurs MCP. Vérifiez la sortie pour plus de détails.", "toolNotFound": "L'outil '{{toolName}}' n'existe pas sur le serveur '{{serverName}}'. Outils disponibles : {{availableTools}}", "serverNotFound": "Le serveur MCP '{{serverName}}' n'est pas configuré. Serveurs disponibles : {{availableServers}}", "toolDisabled": "L'outil '{{toolName}}' sur le serveur '{{serverName}}' est désactivé. Outils activés disponibles : {{availableTools}}" diff --git a/src/i18n/locales/hi/mcp.json b/src/i18n/locales/hi/mcp.json index d7df6ab681..2536e79922 100644 --- a/src/i18n/locales/hi/mcp.json +++ b/src/i18n/locales/hi/mcp.json @@ -7,7 +7,8 @@ "invalidJsonArgument": "Zoo ने {{toolName}} को अमान्य JSON आर्गुमेंट के साथ उपयोग करने की कोशिश की। फिर से कोशिश कर रहा है...", "refresh_after_disable": "अक्षम करने के बाद MCP कनेक्शन रीफ्रेश करने में विफल", "refresh_after_enable": "सक्षम करने के बाद MCP कनेक्शन रीफ्रेश करने में विफल", - "disconnect_servers_partial": "{{count}} MCP सर्वर डिस्कनेक्ट करने में विफल। विवरण के लिए आउटपुट देखें।", + "disconnect_servers_partial_one": "{{count}} MCP सर्वर डिस्कनेक्ट करने में विफल। विवरण के लिए आउटपुट देखें।", + "disconnect_servers_partial_other": "{{count}} MCP सर्वर डिस्कनेक्ट करने में विफल। विवरण के लिए आउटपुट देखें।", "toolNotFound": "टूल '{{toolName}}' सर्वर '{{serverName}}' पर मौजूद नहीं है। उपलब्ध टूल: {{availableTools}}", "serverNotFound": "MCP सर्वर '{{serverName}}' कॉन्फ़िगर नहीं है। उपलब्ध सर्वर: {{availableServers}}", "toolDisabled": "सर्वर '{{serverName}}' पर टूल '{{toolName}}' अक्षम है। उपलब्ध सक्षम टूल: {{availableTools}}" diff --git a/src/i18n/locales/id/common.json b/src/i18n/locales/id/common.json index d047cf3cbf..d6bcb23542 100644 --- a/src/i18n/locales/id/common.json +++ b/src/i18n/locales/id/common.json @@ -125,7 +125,6 @@ "auto_import_failed": "Gagal mengimpor pengaturan ZooCode secara otomatis: {{error}}", "rooHistoryImport": { "nothingFound": "Tidak ada riwayat tugas Roo Code yang ditemukan untuk diimpor dari {{domain}}.", - "alreadyImported_one": "Semua {{count}} riwayat tugas Roo Code sudah diimpor ke Zoo Code.", "alreadyImported_other": "Semua {{count}} riwayat tugas Roo Code sudah diimpor ke Zoo Code." } }, @@ -143,7 +142,6 @@ "signInUnavailable": "Masuk ke Roo Code Cloud saat ini tidak tersedia. Konfigurasikan penyedia lain untuk melanjutkan." }, "rooHistoryImport": { - "success_one": "{{count}} riwayat tugas Roo Code berhasil diimpor ke Zoo Code.", "success_other": "{{count}} riwayat tugas Roo Code berhasil diimpor ke Zoo Code." } }, diff --git a/src/i18n/locales/id/mcp.json b/src/i18n/locales/id/mcp.json index 39121cfdfd..cd9e0c3b36 100644 --- a/src/i18n/locales/id/mcp.json +++ b/src/i18n/locales/id/mcp.json @@ -7,7 +7,7 @@ "invalidJsonArgument": "Zoo mencoba menggunakan {{toolName}} dengan argumen JSON yang tidak valid. Mencoba lagi...", "refresh_after_disable": "Gagal me-refresh koneksi MCP setelah menonaktifkan", "refresh_after_enable": "Gagal me-refresh koneksi MCP setelah mengaktifkan", - "disconnect_servers_partial": "Gagal memutus koneksi {{count}} server MCP. Periksa output untuk detailnya.", + "disconnect_servers_partial_other": "Gagal memutus koneksi {{count}} server MCP. Periksa output untuk detailnya.", "toolNotFound": "Tool '{{toolName}}' tidak ada di server '{{serverName}}'. Tool yang tersedia: {{availableTools}}", "serverNotFound": "Server MCP '{{serverName}}' tidak dikonfigurasi. Server yang tersedia: {{availableServers}}", "toolDisabled": "Tool '{{toolName}}' di server '{{serverName}}' dinonaktifkan. Tool aktif yang tersedia: {{availableTools}}" diff --git a/src/i18n/locales/it/common.json b/src/i18n/locales/it/common.json index ecdf443a3d..744ffd5e42 100644 --- a/src/i18n/locales/it/common.json +++ b/src/i18n/locales/it/common.json @@ -126,6 +126,7 @@ "rooHistoryImport": { "nothingFound": "Nessuna cronologia di attività Roo Code trovata da importare da {{domain}}.", "alreadyImported_one": "La cronologia di {{count}} attività Roo Code è già stata importata in Zoo Code.", + "alreadyImported_many": "Tutte le {{count}} cronologie di attività Roo Code sono già state importate in Zoo Code.", "alreadyImported_other": "Tutte le {{count}} cronologie di attività Roo Code sono già state importate in Zoo Code." } }, @@ -144,6 +145,7 @@ }, "rooHistoryImport": { "success_one": "Importata {{count}} cronologia di attività Roo Code in Zoo Code.", + "success_many": "Importate {{count}} cronologie di attività Roo Code in Zoo Code.", "success_other": "Importate {{count}} cronologie di attività Roo Code in Zoo Code." } }, diff --git a/src/i18n/locales/it/mcp.json b/src/i18n/locales/it/mcp.json index 968e9f5148..7927818cb3 100644 --- a/src/i18n/locales/it/mcp.json +++ b/src/i18n/locales/it/mcp.json @@ -7,7 +7,9 @@ "invalidJsonArgument": "Zoo ha tentato di usare {{toolName}} con un argomento JSON non valido. Riprovo...", "refresh_after_disable": "Impossibile aggiornare le connessioni MCP dopo la disattivazione", "refresh_after_enable": "Impossibile aggiornare le connessioni MCP dopo l'attivazione", - "disconnect_servers_partial": "Impossibile disconnettere {{count}} server MCP. Controlla l'output per i dettagli.", + "disconnect_servers_partial_one": "Impossibile disconnettere {{count}} server MCP. Controlla l'output per i dettagli.", + "disconnect_servers_partial_many": "Impossibile disconnettere {{count}} server MCP. Controlla l'output per i dettagli.", + "disconnect_servers_partial_other": "Impossibile disconnettere {{count}} server MCP. Controlla l'output per i dettagli.", "toolNotFound": "Lo strumento '{{toolName}}' non esiste sul server '{{serverName}}'. Strumenti disponibili: {{availableTools}}", "serverNotFound": "Il server MCP '{{serverName}}' non è configurato. Server disponibili: {{availableServers}}", "toolDisabled": "Lo strumento '{{toolName}}' sul server '{{serverName}}' è disabilitato. Strumenti abilitati disponibili: {{availableTools}}" diff --git a/src/i18n/locales/ja/common.json b/src/i18n/locales/ja/common.json index 2220a608d6..ba429a08bc 100644 --- a/src/i18n/locales/ja/common.json +++ b/src/i18n/locales/ja/common.json @@ -125,7 +125,6 @@ "auto_import_failed": "ZooCode設定の自動インポートに失敗しました:{{error}}", "rooHistoryImport": { "nothingFound": "{{domain}}からインポートするRoo Codeのタスク履歴が見つかりませんでした。", - "alreadyImported_one": "{{count}}件のRoo Codeタスク履歴はすでにZoo Codeにインポート済みです。", "alreadyImported_other": "{{count}}件のRoo Codeタスク履歴はすでにZoo Codeにインポート済みです。" } }, @@ -143,7 +142,6 @@ "signInUnavailable": "Roo Code Cloud へのサインインは現在利用できません。続行するには別のプロバイダーを設定してください。" }, "rooHistoryImport": { - "success_one": "{{count}}件のRoo CodeタスクをZoo Codeにインポートしました。", "success_other": "{{count}}件のRoo CodeタスクをZoo Codeにインポートしました。" } }, diff --git a/src/i18n/locales/ja/mcp.json b/src/i18n/locales/ja/mcp.json index 68d0806329..e7850e6640 100644 --- a/src/i18n/locales/ja/mcp.json +++ b/src/i18n/locales/ja/mcp.json @@ -7,7 +7,7 @@ "invalidJsonArgument": "Zooが無効なJSON引数で{{toolName}}を使用しようとしました。再試行中...", "refresh_after_disable": "無効化後にMCP接続の更新に失敗しました", "refresh_after_enable": "有効化後にMCP接続の更新に失敗しました", - "disconnect_servers_partial": "{{count}}個のMCPサーバーの切断に失敗しました。詳細は出力を確認してください。", + "disconnect_servers_partial_other": "{{count}}個のMCPサーバーの切断に失敗しました。詳細は出力を確認してください。", "toolNotFound": "ツール '{{toolName}}' はサーバー '{{serverName}}' に存在しません。利用可能なツール: {{availableTools}}", "serverNotFound": "MCPサーバー '{{serverName}}' は設定されていません。利用可能なサーバー: {{availableServers}}", "toolDisabled": "サーバー '{{serverName}}' のツール '{{toolName}}' は無効です。利用可能な有効なツール: {{availableTools}}" diff --git a/src/i18n/locales/ko/common.json b/src/i18n/locales/ko/common.json index b462dc8056..bb8e9c0f13 100644 --- a/src/i18n/locales/ko/common.json +++ b/src/i18n/locales/ko/common.json @@ -125,7 +125,6 @@ "auto_import_failed": "ZooCode 설정 자동 가져오기 실패: {{error}}", "rooHistoryImport": { "nothingFound": "{{domain}}에서 가져올 Roo Code 작업 기록을 찾을 수 없습니다.", - "alreadyImported_one": "{{count}}개의 Roo Code 작업 기록이 이미 Zoo Code로 가져와졌습니다.", "alreadyImported_other": "{{count}}개의 Roo Code 작업 기록이 이미 Zoo Code로 가져와졌습니다." } }, @@ -143,7 +142,6 @@ "signInUnavailable": "Roo Code Cloud 로그인은 현재 사용할 수 없습니다. 계속하려면 다른 제공업체를 구성하세요." }, "rooHistoryImport": { - "success_one": "Roo Code 작업 기록 {{count}}개를 Zoo Code로 가져왔습니다.", "success_other": "Roo Code 작업 기록 {{count}}개를 Zoo Code로 가져왔습니다." } }, diff --git a/src/i18n/locales/ko/mcp.json b/src/i18n/locales/ko/mcp.json index 43f2d5d10f..5422f14506 100644 --- a/src/i18n/locales/ko/mcp.json +++ b/src/i18n/locales/ko/mcp.json @@ -7,7 +7,7 @@ "invalidJsonArgument": "Zoo가 유효하지 않은 JSON 인자로 {{toolName}}을(를) 사용하려고 했습니다. 다시 시도 중...", "refresh_after_disable": "비활성화 후 MCP 연결 새로 고침 실패", "refresh_after_enable": "활성화 후 MCP 연결 새로 고침 실패", - "disconnect_servers_partial": "{{count}}개의 MCP 서버 연결 해제 실패. 자세한 내용은 출력을 확인하세요.", + "disconnect_servers_partial_other": "{{count}}개의 MCP 서버 연결 해제 실패. 자세한 내용은 출력을 확인하세요.", "toolNotFound": "도구 '{{toolName}}'이(가) 서버 '{{serverName}}'에 존재하지 않습니다. 사용 가능한 도구: {{availableTools}}", "serverNotFound": "MCP 서버 '{{serverName}}'이(가) 구성되지 않았습니다. 사용 가능한 서버: {{availableServers}}", "toolDisabled": "서버 '{{serverName}}'의 도구 '{{toolName}}'이(가) 비활성화되었습니다. 사용 가능한 활성화된 도구: {{availableTools}}" diff --git a/src/i18n/locales/nl/mcp.json b/src/i18n/locales/nl/mcp.json index a1c148eafd..a0898b3139 100644 --- a/src/i18n/locales/nl/mcp.json +++ b/src/i18n/locales/nl/mcp.json @@ -7,7 +7,8 @@ "invalidJsonArgument": "Zoo probeerde {{toolName}} te gebruiken met een ongeldig JSON-argument. Opnieuw proberen...", "refresh_after_disable": "Vernieuwen van MCP-verbindingen na uitschakelen mislukt", "refresh_after_enable": "Vernieuwen van MCP-verbindingen na inschakelen mislukt", - "disconnect_servers_partial": "Loskoppelen van {{count}} MCP-server(s) mislukt. Controleer de uitvoer voor details.", + "disconnect_servers_partial_one": "Loskoppelen van {{count}} MCP-server mislukt. Controleer de uitvoer voor details.", + "disconnect_servers_partial_other": "Loskoppelen van {{count}} MCP-servers mislukt. Controleer de uitvoer voor details.", "toolNotFound": "Tool '{{toolName}}' bestaat niet op server '{{serverName}}'. Beschikbare tools: {{availableTools}}", "serverNotFound": "MCP-server '{{serverName}}' is niet geconfigureerd. Beschikbare servers: {{availableServers}}", "toolDisabled": "Tool '{{toolName}}' op server '{{serverName}}' is uitgeschakeld. Beschikbare ingeschakelde tools: {{availableTools}}" diff --git a/src/i18n/locales/pl/common.json b/src/i18n/locales/pl/common.json index d2b6412257..dafc5e6580 100644 --- a/src/i18n/locales/pl/common.json +++ b/src/i18n/locales/pl/common.json @@ -125,7 +125,9 @@ "auto_import_failed": "Nie udało się automatycznie zaimportować ustawień ZooCode: {{error}}", "rooHistoryImport": { "nothingFound": "Nie znaleziono historii zadań Roo Code do zaimportowania z {{domain}}.", - "alreadyImported_one": "Cała {{count}} historia zadań Roo Code została już zaimportowana do Zoo Code.", + "alreadyImported_one": "{{count}} historia zadań Roo Code została już zaimportowana do Zoo Code.", + "alreadyImported_few": "Wszystkie {{count}} historie zadań Roo Code zostały już zaimportowane do Zoo Code.", + "alreadyImported_many": "Wszystkie {{count}} historii zadań Roo Code zostały już zaimportowane do Zoo Code.", "alreadyImported_other": "Wszystkie {{count}} historii zadań Roo Code zostały już zaimportowane do Zoo Code." } }, @@ -144,6 +146,8 @@ }, "rooHistoryImport": { "success_one": "Zaimportowano {{count}} historię zadania Roo Code do Zoo Code.", + "success_few": "Zaimportowano {{count}} historie zadań Roo Code do Zoo Code.", + "success_many": "Zaimportowano {{count}} historii zadań Roo Code do Zoo Code.", "success_other": "Zaimportowano {{count}} historii zadań Roo Code do Zoo Code." } }, diff --git a/src/i18n/locales/pl/mcp.json b/src/i18n/locales/pl/mcp.json index 388a81962f..44242522ad 100644 --- a/src/i18n/locales/pl/mcp.json +++ b/src/i18n/locales/pl/mcp.json @@ -7,7 +7,10 @@ "invalidJsonArgument": "Zoo próbował użyć {{toolName}} z nieprawidłowym argumentem JSON. Ponawianie...", "refresh_after_disable": "Nie udało się odświeżyć połączeń MCP po wyłączeniu", "refresh_after_enable": "Nie udało się odświeżyć połączeń MCP po włączeniu", - "disconnect_servers_partial": "Nie udało się odłączyć {{count}} serwera(ów) MCP. Sprawdź dane wyjściowe, aby uzyskać szczegóły.", + "disconnect_servers_partial_one": "Nie udało się odłączyć {{count}} serwera MCP. Sprawdź dane wyjściowe, aby uzyskać szczegóły.", + "disconnect_servers_partial_few": "Nie udało się odłączyć {{count}} serwerów MCP. Sprawdź dane wyjściowe, aby uzyskać szczegóły.", + "disconnect_servers_partial_many": "Nie udało się odłączyć {{count}} serwerów MCP. Sprawdź dane wyjściowe, aby uzyskać szczegóły.", + "disconnect_servers_partial_other": "Nie udało się odłączyć {{count}} serwera MCP. Sprawdź dane wyjściowe, aby uzyskać szczegóły.", "toolNotFound": "Narzędzie '{{toolName}}' nie istnieje na serwerze '{{serverName}}'. Dostępne narzędzia: {{availableTools}}", "serverNotFound": "Serwer MCP '{{serverName}}' nie jest skonfigurowany. Dostępne serwery: {{availableServers}}", "toolDisabled": "Narzędzie '{{toolName}}' na serwerze '{{serverName}}' jest wyłączone. Dostępne włączone narzędzia: {{availableTools}}" diff --git a/src/i18n/locales/pt-BR/common.json b/src/i18n/locales/pt-BR/common.json index 02e65d5ab9..4cb22aba2d 100644 --- a/src/i18n/locales/pt-BR/common.json +++ b/src/i18n/locales/pt-BR/common.json @@ -130,6 +130,7 @@ "rooHistoryImport": { "nothingFound": "Nenhum histórico de tarefas do Roo Code encontrado para importar de {{domain}}.", "alreadyImported_one": "O histórico de {{count}} tarefa do Roo Code já foi importado para o Zoo Code.", + "alreadyImported_many": "Todos os {{count}} históricos de tarefas do Roo Code já foram importados para o Zoo Code.", "alreadyImported_other": "Todos os {{count}} históricos de tarefas do Roo Code já foram importados para o Zoo Code." } }, @@ -148,6 +149,7 @@ }, "rooHistoryImport": { "success_one": "{{count}} histórico de tarefa do Roo Code importado para o Zoo Code.", + "success_many": "{{count}} históricos de tarefas do Roo Code importados para o Zoo Code.", "success_other": "{{count}} históricos de tarefas do Roo Code importados para o Zoo Code." } }, diff --git a/src/i18n/locales/pt-BR/mcp.json b/src/i18n/locales/pt-BR/mcp.json index 5abf5ac030..ff019a6a40 100644 --- a/src/i18n/locales/pt-BR/mcp.json +++ b/src/i18n/locales/pt-BR/mcp.json @@ -7,7 +7,9 @@ "invalidJsonArgument": "Zoo tentou usar {{toolName}} com um argumento JSON inválido. Tentando novamente...", "refresh_after_disable": "Falha ao atualizar as conexões MCP após desativar", "refresh_after_enable": "Falha ao atualizar as conexões MCP após ativar", - "disconnect_servers_partial": "Falha ao desconectar {{count}} servidor(es) MCP. Verifique a saída para detalhes.", + "disconnect_servers_partial_one": "Falha ao desconectar {{count}} servidor MCP. Verifique a saída para detalhes.", + "disconnect_servers_partial_many": "Falha ao desconectar {{count}} servidores MCP. Verifique a saída para detalhes.", + "disconnect_servers_partial_other": "Falha ao desconectar {{count}} servidores MCP. Verifique a saída para detalhes.", "toolNotFound": "A ferramenta '{{toolName}}' não existe no servidor '{{serverName}}'. Ferramentas disponíveis: {{availableTools}}", "serverNotFound": "O servidor MCP '{{serverName}}' não está configurado. Servidores disponíveis: {{availableServers}}", "toolDisabled": "A ferramenta '{{toolName}}' no servidor '{{serverName}}' está desabilitada. Ferramentas habilitadas disponíveis: {{availableTools}}" diff --git a/src/i18n/locales/ru/common.json b/src/i18n/locales/ru/common.json index 64e60ab2ff..cc73596ce3 100644 --- a/src/i18n/locales/ru/common.json +++ b/src/i18n/locales/ru/common.json @@ -126,6 +126,8 @@ "rooHistoryImport": { "nothingFound": "История задач Roo Code для импорта из {{domain}} не найдена.", "alreadyImported_one": "{{count}} история задач Roo Code уже импортирована в Zoo Code.", + "alreadyImported_few": "Все {{count}} истории задач Roo Code уже импортированы в Zoo Code.", + "alreadyImported_many": "Все {{count}} историй задач Roo Code уже импортированы в Zoo Code.", "alreadyImported_other": "Все {{count}} истории задач Roo Code уже импортированы в Zoo Code." } }, @@ -144,7 +146,9 @@ }, "rooHistoryImport": { "success_one": "{{count}} история задач Roo Code импортирована в Zoo Code.", - "success_other": "{{count}} историй задач Roo Code импортировано в Zoo Code." + "success_few": "{{count}} истории задач Roo Code импортированы в Zoo Code.", + "success_many": "{{count}} историй задач Roo Code импортировано в Zoo Code.", + "success_other": "{{count}} истории задач Roo Code импортировано в Zoo Code." } }, "answers": { diff --git a/src/i18n/locales/ru/mcp.json b/src/i18n/locales/ru/mcp.json index 075a8e274c..b1296fcbb8 100644 --- a/src/i18n/locales/ru/mcp.json +++ b/src/i18n/locales/ru/mcp.json @@ -7,7 +7,10 @@ "invalidJsonArgument": "Zoo попытался использовать {{toolName}} с недопустимым JSON-аргументом. Повторная попытка...", "refresh_after_disable": "Не удалось обновить соединения MCP после отключения", "refresh_after_enable": "Не удалось обновить соединения MCP после включения", - "disconnect_servers_partial": "Не удалось отключить {{count}} MCP сервер(ов). Проверьте вывод для получения подробностей.", + "disconnect_servers_partial_one": "Не удалось отключить {{count}} MCP сервер. Проверьте вывод для получения подробностей.", + "disconnect_servers_partial_few": "Не удалось отключить {{count}} MCP сервера. Проверьте вывод для получения подробностей.", + "disconnect_servers_partial_many": "Не удалось отключить {{count}} MCP серверов. Проверьте вывод для получения подробностей.", + "disconnect_servers_partial_other": "Не удалось отключить {{count}} MCP сервера. Проверьте вывод для получения подробностей.", "toolNotFound": "Инструмент '{{toolName}}' не существует на сервере '{{serverName}}'. Доступные инструменты: {{availableTools}}", "serverNotFound": "MCP сервер '{{serverName}}' не настроен. Доступные серверы: {{availableServers}}", "toolDisabled": "Инструмент '{{toolName}}' на сервере '{{serverName}}' отключен. Доступные включенные инструменты: {{availableTools}}" diff --git a/src/i18n/locales/tr/mcp.json b/src/i18n/locales/tr/mcp.json index ea6fd2c05e..f753324d3c 100644 --- a/src/i18n/locales/tr/mcp.json +++ b/src/i18n/locales/tr/mcp.json @@ -7,7 +7,8 @@ "invalidJsonArgument": "Zoo, {{toolName}} aracını geçersiz bir JSON argümanıyla kullanmaya çalıştı. Tekrar deneniyor...", "refresh_after_disable": "Devre dışı bıraktıktan sonra MCP bağlantıları yenilenemedi", "refresh_after_enable": "Etkinleştirdikten sonra MCP bağlantıları yenilenemedi", - "disconnect_servers_partial": "{{count}} MCP sunucusu bağlantısı kesilemedi. Ayrıntılar için çıktıyı kontrol edin.", + "disconnect_servers_partial_one": "{{count}} MCP sunucusu bağlantısı kesilemedi. Ayrıntılar için çıktıyı kontrol edin.", + "disconnect_servers_partial_other": "{{count}} MCP sunucusu bağlantısı kesilemedi. Ayrıntılar için çıktıyı kontrol edin.", "toolNotFound": "Araç '{{toolName}}' sunucu '{{serverName}}' üzerinde mevcut değil. Mevcut araçlar: {{availableTools}}", "serverNotFound": "MCP sunucusu '{{serverName}}' yapılandırılmamış. Mevcut sunucular: {{availableServers}}", "toolDisabled": "Sunucu '{{serverName}}' üzerindeki araç '{{toolName}}' devre dışı. Mevcut etkin araçlar: {{availableTools}}" diff --git a/src/i18n/locales/vi/common.json b/src/i18n/locales/vi/common.json index 94c61bdaae..a057ee21a4 100644 --- a/src/i18n/locales/vi/common.json +++ b/src/i18n/locales/vi/common.json @@ -125,7 +125,6 @@ "auto_import_failed": "Không thể tự động nhập cài đặt ZooCode: {{error}}", "rooHistoryImport": { "nothingFound": "Không tìm thấy lịch sử nhiệm vụ Roo Code nào để nhập từ {{domain}}.", - "alreadyImported_one": "{{count}} lịch sử nhiệm vụ Roo Code đã được nhập vào Zoo Code.", "alreadyImported_other": "Tất cả {{count}} lịch sử nhiệm vụ Roo Code đã được nhập vào Zoo Code." } }, @@ -143,7 +142,6 @@ "signInUnavailable": "Đăng nhập Roo Code Cloud hiện không khả dụng. Hãy cấu hình nhà cung cấp khác để tiếp tục." }, "rooHistoryImport": { - "success_one": "Đã nhập {{count}} lịch sử nhiệm vụ Roo Code vào Zoo Code.", "success_other": "Đã nhập {{count}} lịch sử nhiệm vụ Roo Code vào Zoo Code." } }, diff --git a/src/i18n/locales/vi/mcp.json b/src/i18n/locales/vi/mcp.json index 7f6b6ad0d2..ca67e58fd2 100644 --- a/src/i18n/locales/vi/mcp.json +++ b/src/i18n/locales/vi/mcp.json @@ -7,7 +7,7 @@ "invalidJsonArgument": "Zoo đã cố gắng sử dụng {{toolName}} với tham số JSON không hợp lệ. Đang thử lại...", "refresh_after_disable": "Không thể làm mới kết nối MCP sau khi vô hiệu hóa", "refresh_after_enable": "Không thể làm mới kết nối MCP sau khi kích hoạt", - "disconnect_servers_partial": "Không thể ngắt kết nối {{count}} máy chủ MCP. Kiểm tra đầu ra để biết chi tiết.", + "disconnect_servers_partial_other": "Không thể ngắt kết nối {{count}} máy chủ MCP. Kiểm tra đầu ra để biết chi tiết.", "toolNotFound": "Công cụ '{{toolName}}' không tồn tại trên máy chủ '{{serverName}}'. Công cụ có sẵn: {{availableTools}}", "serverNotFound": "Máy chủ MCP '{{serverName}}' chưa được cấu hình. Máy chủ có sẵn: {{availableServers}}", "toolDisabled": "Công cụ '{{toolName}}' trên máy chủ '{{serverName}}' đã bị vô hiệu hóa. Công cụ đã kích hoạt có sẵn: {{availableTools}}" diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json index 2c39a92571..b8e94cf275 100644 --- a/src/i18n/locales/zh-CN/common.json +++ b/src/i18n/locales/zh-CN/common.json @@ -130,7 +130,6 @@ "auto_import_failed": "自动导入 ZooCode 设置失败:{{error}}", "rooHistoryImport": { "nothingFound": "未找到可从 {{domain}} 导入的 Roo Code 任务历史记录。", - "alreadyImported_one": "全部 {{count}} 条 Roo Code 任务历史记录已导入 Zoo Code。", "alreadyImported_other": "全部 {{count}} 条 Roo Code 任务历史记录已导入 Zoo Code。" } }, @@ -148,7 +147,6 @@ "signInUnavailable": "Roo Code Cloud 登录当前不可用。请配置其他提供商以继续。" }, "rooHistoryImport": { - "success_one": "已将 {{count}} 条 Roo Code 任务历史记录导入 Zoo Code。", "success_other": "已将 {{count}} 条 Roo Code 任务历史记录导入 Zoo Code。" } }, diff --git a/src/i18n/locales/zh-CN/mcp.json b/src/i18n/locales/zh-CN/mcp.json index e2d1cbff82..0fba9e23c8 100644 --- a/src/i18n/locales/zh-CN/mcp.json +++ b/src/i18n/locales/zh-CN/mcp.json @@ -7,7 +7,7 @@ "invalidJsonArgument": "Zoo 尝试使用无效的 JSON 参数调用 {{toolName}}。正在重试...", "refresh_after_disable": "禁用后刷新 MCP 连接失败", "refresh_after_enable": "启用后刷新 MCP 连接失败", - "disconnect_servers_partial": "断开 {{count}} 个 MCP 服务器失败。请查看输出了解详情。", + "disconnect_servers_partial_other": "断开 {{count}} 个 MCP 服务器失败。请查看输出了解详情。", "toolNotFound": "工具 '{{toolName}}' 在服务器 '{{serverName}}' 上不存在。可用工具: {{availableTools}}", "serverNotFound": "MCP 服务器 '{{serverName}}' 未配置。可用服务器: {{availableServers}}", "toolDisabled": "服务器 '{{serverName}}' 上的工具 '{{toolName}}' 已禁用。可用的已启用工具: {{availableTools}}" diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json index a96493284b..e04b97d5bc 100644 --- a/src/i18n/locales/zh-TW/common.json +++ b/src/i18n/locales/zh-TW/common.json @@ -125,7 +125,6 @@ "auto_import_failed": "自動匯入 ZooCode 設定失敗:{{error}}", "rooHistoryImport": { "nothingFound": "未找到可從 {{domain}} 匯入的 Roo Code 工作歷史記錄。", - "alreadyImported_one": "全部 {{count}} 筆 Roo Code 工作歷史記錄已匯入 Zoo Code。", "alreadyImported_other": "全部 {{count}} 筆 Roo Code 工作歷史記錄已匯入 Zoo Code。" } }, @@ -143,7 +142,6 @@ "signInUnavailable": "Roo Code Cloud 登入目前無法使用。請設定其他提供者以繼續。" }, "rooHistoryImport": { - "success_one": "已將 {{count}} 筆 Roo Code 工作歷史記錄匯入 Zoo Code。", "success_other": "已將 {{count}} 筆 Roo Code 工作歷史記錄匯入 Zoo Code。" } }, diff --git a/src/i18n/locales/zh-TW/mcp.json b/src/i18n/locales/zh-TW/mcp.json index c259d5fe76..b5468882d1 100644 --- a/src/i18n/locales/zh-TW/mcp.json +++ b/src/i18n/locales/zh-TW/mcp.json @@ -7,7 +7,7 @@ "invalidJsonArgument": "Zoo 嘗試使用無效的 JSON 參數呼叫 {{toolName}}。正在重試...", "refresh_after_disable": "停用後重新整理 MCP 連線失敗", "refresh_after_enable": "啟用後重新整理 MCP 連線失敗", - "disconnect_servers_partial": "斷開 {{count}} 個 MCP 伺服器失敗。請查看輸出了解詳情。", + "disconnect_servers_partial_other": "斷開 {{count}} 個 MCP 伺服器失敗。請查看輸出了解詳情。", "toolNotFound": "工具 '{{toolName}}' 在伺服器 '{{serverName}}' 上不存在。可用工具: {{availableTools}}", "serverNotFound": "MCP 伺服器 '{{serverName}}' 未設定。可用伺服器: {{availableServers}}", "toolDisabled": "伺服器 '{{serverName}}' 上的工具 '{{toolName}}' 已停用。可用的已啟用工具: {{availableTools}}" diff --git a/webview-ui/src/i18n/__tests__/plurals.spec.ts b/webview-ui/src/i18n/__tests__/plurals.spec.ts new file mode 100644 index 0000000000..5b9535b00b --- /dev/null +++ b/webview-ui/src/i18n/__tests__/plurals.spec.ts @@ -0,0 +1,51 @@ +// npx vitest src/i18n/__tests__/plurals.spec.ts +// +// Renders plural strings from the real locale bundles with i18next, so a +// missing CLDR form shows up as the wrong text or as the English fallback. + +import i18next from "i18next" + +import enChat from "../locales/en/chat.json" +import enCommon from "../locales/en/common.json" +import enHistory from "../locales/en/history.json" +import frChat from "../locales/fr/chat.json" +import plHistory from "../locales/pl/history.json" +import ruChat from "../locales/ru/chat.json" +import ruCommon from "../locales/ru/common.json" +import ruHistory from "../locales/ru/history.json" + +async function translator(language: string) { + const instance = i18next.createInstance() + await instance.init({ + lng: language, + fallbackLng: "en", + resources: { + en: { chat: enChat, common: enCommon, history: enHistory }, + fr: { chat: frChat }, + pl: { history: plHistory }, + ru: { chat: ruChat, common: ruCommon, history: ruHistory }, + }, + }) + return instance.t +} + +describe("plural forms", () => { + it.each([ + ["ru", "chat:autoApprove.triggerLabel", 0, "0 авто-утвержденных"], + ["ru", "chat:autoApprove.triggerLabel", 1, "1 авто-утвержденное"], + ["ru", "chat:autoApprove.triggerLabel", 2, "2 авто-утвержденных"], + ["ru", "chat:autoApprove.triggerLabel", 5, "5 авто-утвержденных"], + ["ru", "common:time_ago.seconds_ago", 31, "31 секунду назад"], + ["ru", "common:time_ago.seconds_ago", 32, "32 секунды назад"], + ["ru", "common:time_ago.seconds_ago", 45, "45 секунд назад"], + ["ru", "chat:contextManagement.truncation.messagesRemoved", 2, "2 сообщения удалено"], + ["ru", "history:subtasks", 3, "3 подзадачи"], + ["pl", "history:subtasks", 22, "22 podzadania"], + ["fr", "chat:codebaseSearch.didSearch", 0, "0 résultat trouvé"], + ["fr", "chat:codebaseSearch.didSearch", 1000000, "1000000 résultats trouvés"], + ["en", "history:deleteItems", 1, "Delete 1 Item"], + ])("%s %s with count %d renders %j", async (language, key, count, expected) => { + const t = await translator(language) + expect(t(key, { count })).toBe(expected) + }) +}) diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index 612fcec1f9..9160b1f9b0 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -20,7 +20,9 @@ "unpin": "Desfixar", "pin": "Fixar", "fileChangesInConversation": { - "header": "{{count}} fitxer(s) canviat(s) en aquesta conversa" + "header_one": "{{count}} fitxer canviat en aquesta conversa", + "header_many": "{{count}} fitxers canviats en aquesta conversa", + "header_other": "{{count}} fitxers canviats en aquesta conversa" }, "tokenProgress": { "availableSpace": "Espai disponible: {{amount}} tokens", @@ -287,7 +289,8 @@ "triggerLabelOff": "Aprovació automàtica desactivada", "triggerLabelOffShort": "Off", "triggerLabel_zero": "0 aprovacions automàtiques", - "triggerLabel_one": "1 aprovació automàtica", + "triggerLabel_one": "{{count}} aprovació automàtica", + "triggerLabel_many": "{{count}} aprovacions automàtiques", "triggerLabel_other": "{{count}} aprovacions automàtiques", "triggerLabelAll": "BRRR" }, @@ -305,7 +308,8 @@ "truncation": { "title": "Context truncat", "inProgress": "Truncant context...", - "messagesRemoved": "{{count}} missatge eliminat", + "messagesRemoved_one": "{{count}} missatge eliminat", + "messagesRemoved_many": "{{count}} missatges eliminats", "messagesRemoved_other": "{{count}} missatges eliminats", "description": "S'han eliminat missatges més antics de la conversa per mantenir-se dins del límit de la finestra de context. Aquest és un enfocament ràpid però menys conservador del context en comparació amb la condensació." } @@ -349,7 +353,9 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "S'ha arribat al límit de sol·licituds aprovades automàticament", - "description": "Zoo ha arribat al límit aprovat automàticament de {{count}} sol·licitud(s) d'API. Vols reiniciar el comptador i continuar amb la tasca?", + "description_one": "Zoo ha arribat al límit aprovat automàticament de {{count}} sol·licitud d'API. Vols reiniciar el comptador i continuar amb la tasca?", + "description_many": "Zoo ha arribat al límit aprovat automàticament de {{count}} sol·licituds d'API. Vols reiniciar el comptador i continuar amb la tasca?", + "description_other": "Zoo ha arribat al límit aprovat automàticament de {{count}} sol·licituds d'API. Vols reiniciar el comptador i continuar amb la tasca?", "button": "Reiniciar i continuar" }, "autoApprovedCostLimitReached": { @@ -361,7 +367,8 @@ "codebaseSearch": { "wantsToSearch": "Zoo vol cercar a la base de codi {{query}}", "wantsToSearchWithPath": "Zoo vol cercar a la base de codi {{query}} a {{path}}", - "didSearch_one": "S'ha trobat 1 resultat", + "didSearch_one": "S'ha trobat {{count}} resultat", + "didSearch_many": "S'han trobat {{count}} resultats", "didSearch_other": "S'han trobat {{count}} resultats", "resultTooltip": "Puntuació de similitud: {{score}} (fes clic per obrir el fitxer)" }, @@ -433,8 +440,10 @@ "tooManyTools": { "title": "Massa eines habilitades", "toolsPart_one": "{{count}} eina", + "toolsPart_many": "{{count}} eines", "toolsPart_other": "{{count}} eines", "serversPart_one": "{{count}} servidor MCP", + "serversPart_many": "{{count}} servidors MCP", "serversPart_other": "{{count}} servidors MCP", "messageTemplate": "Tens {{tools}} habilitades via {{servers}}. Un nombre tant alt pot confondre el model i portar a errors. Intenta mantenir-lo per sota de {{threshold}}.", "openMcpSettings": "Obrir configuració de MCP" diff --git a/webview-ui/src/i18n/locales/ca/common.json b/webview-ui/src/i18n/locales/ca/common.json index 4cbe89dad2..4c3e1bb76e 100644 --- a/webview-ui/src/i18n/locales/ca/common.json +++ b/webview-ui/src/i18n/locales/ca/common.json @@ -57,19 +57,33 @@ }, "time_ago": { "just_now": "ara mateix", - "seconds_ago": "fa {{count}} segons", + "seconds_ago_one": "fa {{count}} segon", + "seconds_ago_many": "fa {{count}} segons", + "seconds_ago_other": "fa {{count}} segons", "minute_ago": "fa un minut", - "minutes_ago": "fa {{count}} minuts", + "minutes_ago_one": "fa {{count}} minut", + "minutes_ago_many": "fa {{count}} minuts", + "minutes_ago_other": "fa {{count}} minuts", "hour_ago": "fa una hora", - "hours_ago": "fa {{count}} hores", + "hours_ago_one": "fa {{count}} hora", + "hours_ago_many": "fa {{count}} hores", + "hours_ago_other": "fa {{count}} hores", "day_ago": "fa un dia", - "days_ago": "fa {{count}} dies", + "days_ago_one": "fa {{count}} dia", + "days_ago_many": "fa {{count}} dies", + "days_ago_other": "fa {{count}} dies", "week_ago": "fa una setmana", - "weeks_ago": "fa {{count}} setmanes", + "weeks_ago_one": "fa {{count}} setmana", + "weeks_ago_many": "fa {{count}} setmanes", + "weeks_ago_other": "fa {{count}} setmanes", "month_ago": "fa un mes", - "months_ago": "fa {{count}} mesos", + "months_ago_one": "fa {{count}} mes", + "months_ago_many": "fa {{count}} mesos", + "months_ago_other": "fa {{count}} mesos", "year_ago": "fa un any", - "years_ago": "fa {{count}} anys" + "years_ago_one": "fa {{count}} any", + "years_ago_many": "fa {{count}} anys", + "years_ago_other": "fa {{count}} anys" }, "errors": { "wait_checkpoint_long_time": "Has esperat {{timeout}} segons per inicialitzar el punt de control. Si no necessites aquesta funció, desactiva-la a la configuració del punt de control.", diff --git a/webview-ui/src/i18n/locales/ca/history.json b/webview-ui/src/i18n/locales/ca/history.json index 9277538d30..6eab0e078c 100644 --- a/webview-ui/src/i18n/locales/ca/history.json +++ b/webview-ui/src/i18n/locales/ca/history.json @@ -33,9 +33,13 @@ "clearSelection": "Netejar selecció", "deleteSelected": "Eliminar seleccionats", "deleteTasks": "Eliminar tasques", - "confirmDeleteTasks": "Estàs segur que vols eliminar {{count}} tasques?", + "confirmDeleteTasks_one": "Estàs segur que vols eliminar {{count}} tasca?", + "confirmDeleteTasks_many": "Estàs segur que vols eliminar {{count}} tasques?", + "confirmDeleteTasks_other": "Estàs segur que vols eliminar {{count}} tasques?", "deleteTasksWarning": "Les tasques eliminades no es poden recuperar. Si us plau, assegura't que vols continuar.", - "deleteItems": "Eliminar {{count}} elements", + "deleteItems_one": "Eliminar {{count}} element", + "deleteItems_many": "Eliminar {{count}} elements", + "deleteItems_other": "Eliminar {{count}} elements", "workspace": { "prefix": "Espai de treball:", "current": "Actual", @@ -51,9 +55,12 @@ }, "viewAllHistory": "Veure-ho tot", "subtasks_one": "{{count}} subtasca", + "subtasks_many": "{{count}} subtasques", "subtasks_other": "{{count}} subtasques", "subtaskTag": "Subtasca", - "deleteWithSubtasks": "Això també eliminarà {{count}} subtasca(s). Estàs segur?", + "deleteWithSubtasks_one": "Això també eliminarà {{count}} subtasca. Estàs segur?", + "deleteWithSubtasks_many": "Això també eliminarà {{count}} subtasques. Estàs segur?", + "deleteWithSubtasks_other": "Això també eliminarà {{count}} subtasques. Estàs segur?", "expandSubtasks": "Expandir subtasques", "collapseSubtasks": "Contreure subtasques", "delegatedTag": "Esperant subtasca", diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 41bbcc4b0f..551782a3fd 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -77,6 +77,7 @@ "summaryCopied": "S'han copiat {{copied}} de {{total}} fitxers", "detailFailed": "Inicia un nou intent d'importació per tornar-ho a provar.", "detailTasksImported_one": "S'ha importat {{count}} de {{total}} historial de tasques.", + "detailTasksImported_many": "S'han importat {{count}} de {{total}} historials de tasques.", "detailTasksImported_other": "S'han importat {{count}} de {{total}} historials de tasques.", "detailPreparing": "Preparant la importació de l'historial de Roo Code.", "progressAriaLabel": "Progrés de la importació de l'historial de Roo Code" @@ -951,7 +952,9 @@ "useAzure": "Utilitzar Azure", "azureApiVersion": "Establir versió de l'API d'Azure", "gemini": { - "freeRequests": "* Gratuït fins a {{count}} sol·licituds per minut. Després d'això, la facturació depèn de la mida del prompt.", + "freeRequests_one": "* Gratuït fins a {{count}} sol·licitud per minut. Després d'això, la facturació depèn de la mida del prompt.", + "freeRequests_many": "* Gratuït fins a {{count}} sol·licituds per minut. Després d'això, la facturació depèn de la mida del prompt.", + "freeRequests_other": "* Gratuït fins a {{count}} sol·licituds per minut. Després d'això, la facturació depèn de la mida del prompt.", "pricingDetails": "Per a més informació, consulteu els detalls de preus.", "billingEstimate": "* La facturació és una estimació - el cost exacte depèn de la mida del prompt." } diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index 4cda6a70d1..8e2908299b 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -20,7 +20,8 @@ "unpin": "Lösen von oben", "pin": "Anheften", "fileChangesInConversation": { - "header": "{{count}} Datei(en) in dieser Unterhaltung geändert" + "header_one": "{{count}} Datei in dieser Unterhaltung geändert", + "header_other": "{{count}} Dateien in dieser Unterhaltung geändert" }, "tokenProgress": { "availableSpace": "Verfügbarer Speicher: {{amount}} Tokens", @@ -287,7 +288,7 @@ "triggerLabelOff": "Automatische Genehmigung aus", "triggerLabelOffShort": "Aus", "triggerLabel_zero": "0 automatisch genehmigt", - "triggerLabel_one": "1 automatisch genehmigt", + "triggerLabel_one": "{{count}} automatisch genehmigt", "triggerLabel_other": "{{count}} automatisch genehmigt", "triggerLabelAll": "BRRR" }, @@ -305,7 +306,7 @@ "truncation": { "title": "Kontext gekürzt", "inProgress": "Kontext wird gekürzt...", - "messagesRemoved": "{{count}} Nachricht entfernt", + "messagesRemoved_one": "{{count}} Nachricht entfernt", "messagesRemoved_other": "{{count}} Nachrichten entfernt", "description": "Ältere Nachrichten wurden aus der Konversation entfernt, um innerhalb des Kontextfenster-Limits zu bleiben. Dies ist ein schnellerer, aber weniger kontexterhaltender Ansatz im Vergleich zur Komprimierung." } @@ -349,7 +350,8 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Limit für automatisch genehmigte Anfragen erreicht", - "description": "Zoo hat das automatisch genehmigte Limit von {{count}} API-Anfrage(n) erreicht. Möchtest du den Zähler zurücksetzen und mit der Aufgabe fortfahren?", + "description_one": "Zoo hat das automatisch genehmigte Limit von {{count}} API-Anfrage erreicht. Möchtest du den Zähler zurücksetzen und mit der Aufgabe fortfahren?", + "description_other": "Zoo hat das automatisch genehmigte Limit von {{count}} API-Anfragen erreicht. Möchtest du den Zähler zurücksetzen und mit der Aufgabe fortfahren?", "button": "Zurücksetzen und fortfahren" }, "autoApprovedCostLimitReached": { @@ -361,7 +363,7 @@ "codebaseSearch": { "wantsToSearch": "Zoo möchte den Codebase nach {{query}} durchsuchen", "wantsToSearchWithPath": "Zoo möchte den Codebase nach {{query}} in {{path}} durchsuchen", - "didSearch_one": "1 Ergebnis gefunden", + "didSearch_one": "{{count}} Ergebnis gefunden", "didSearch_other": "{{count}} Ergebnisse gefunden", "resultTooltip": "Ähnlichkeitswert: {{score}} (klicken zum Öffnen der Datei)" }, diff --git a/webview-ui/src/i18n/locales/de/common.json b/webview-ui/src/i18n/locales/de/common.json index b03a465f36..026c5e10a9 100644 --- a/webview-ui/src/i18n/locales/de/common.json +++ b/webview-ui/src/i18n/locales/de/common.json @@ -57,19 +57,26 @@ }, "time_ago": { "just_now": "gerade eben", - "seconds_ago": "vor {{count}} Sekunden", + "seconds_ago_one": "vor {{count}} Sekunde", + "seconds_ago_other": "vor {{count}} Sekunden", "minute_ago": "vor einer Minute", - "minutes_ago": "vor {{count}} Minuten", + "minutes_ago_one": "vor {{count}} Minute", + "minutes_ago_other": "vor {{count}} Minuten", "hour_ago": "vor einer Stunde", - "hours_ago": "vor {{count}} Stunden", + "hours_ago_one": "vor {{count}} Stunde", + "hours_ago_other": "vor {{count}} Stunden", "day_ago": "vor einem Tag", - "days_ago": "vor {{count}} Tagen", + "days_ago_one": "vor {{count}} Tag", + "days_ago_other": "vor {{count}} Tagen", "week_ago": "vor einer Woche", - "weeks_ago": "vor {{count}} Wochen", + "weeks_ago_one": "vor {{count}} Woche", + "weeks_ago_other": "vor {{count}} Wochen", "month_ago": "vor einem Monat", - "months_ago": "vor {{count}} Monaten", + "months_ago_one": "vor {{count}} Monat", + "months_ago_other": "vor {{count}} Monaten", "year_ago": "vor einem Jahr", - "years_ago": "vor {{count}} Jahren" + "years_ago_one": "vor {{count}} Jahr", + "years_ago_other": "vor {{count}} Jahren" }, "errors": { "wait_checkpoint_long_time": "Du hast {{timeout}} Sekunden auf die Initialisierung des Checkpoints gewartet. Wenn du die Checkpoint-Funktion nicht brauchst, kannst du sie in den Checkpoint-Einstellungen ausschalten.", diff --git a/webview-ui/src/i18n/locales/de/history.json b/webview-ui/src/i18n/locales/de/history.json index 89917ce251..65c4d6eb10 100644 --- a/webview-ui/src/i18n/locales/de/history.json +++ b/webview-ui/src/i18n/locales/de/history.json @@ -33,9 +33,11 @@ "clearSelection": "Auswahl aufheben", "deleteSelected": "Ausgewählte löschen", "deleteTasks": "Aufgaben löschen", - "confirmDeleteTasks": "Bist du sicher, dass du {{count}} Aufgaben löschen möchtest?", + "confirmDeleteTasks_one": "Bist du sicher, dass du {{count}} Aufgabe löschen möchtest?", + "confirmDeleteTasks_other": "Bist du sicher, dass du {{count}} Aufgaben löschen möchtest?", "deleteTasksWarning": "Gelöschte Aufgaben können nicht wiederhergestellt werden. Bitte vergewissere dich, dass du fortfahren möchtest.", - "deleteItems": "{{count}} Elemente löschen", + "deleteItems_one": "{{count}} Element löschen", + "deleteItems_other": "{{count}} Elemente löschen", "workspace": { "prefix": "Arbeitsbereich:", "current": "Aktuell", @@ -53,7 +55,8 @@ "subtasks_one": "{{count}} Teilaufgabe", "subtasks_other": "{{count}} Teilaufgaben", "subtaskTag": "Teilaufgabe", - "deleteWithSubtasks": "Dies löscht auch {{count}} Teilaufgabe(n). Bist du sicher?", + "deleteWithSubtasks_one": "Dies löscht auch {{count}} Teilaufgabe. Bist du sicher?", + "deleteWithSubtasks_other": "Dies löscht auch {{count}} Teilaufgaben. Bist du sicher?", "expandSubtasks": "Teilaufgaben erweitern", "collapseSubtasks": "Teilaufgaben einklappen", "delegatedTag": "Wartet auf Unteraufgabe", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index a4a8b8c606..4d320d4968 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -951,7 +951,8 @@ "useAzure": "Azure verwenden", "azureApiVersion": "Azure API-Version festlegen", "gemini": { - "freeRequests": "* Kostenlos bis zu {{count}} Anfragen pro Minute. Danach hängt die Abrechnung von der Prompt-Größe ab.", + "freeRequests_one": "* Kostenlos bis zu {{count}} Anfrage pro Minute. Danach hängt die Abrechnung von der Prompt-Größe ab.", + "freeRequests_other": "* Kostenlos bis zu {{count}} Anfragen pro Minute. Danach hängt die Abrechnung von der Prompt-Größe ab.", "pricingDetails": "Weitere Informationen finden Sie unter Preisdetails.", "billingEstimate": "* Die Abrechnung ist eine Schätzung - die genauen Kosten hängen von der Prompt-Größe ab." } diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index c9a6fd765b..5ed830a662 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -20,7 +20,8 @@ "unpin": "Unpin", "pin": "Pin", "fileChangesInConversation": { - "header": "{{count}} file(s) changed in this conversation" + "header_one": "{{count}} file changed in this conversation", + "header_other": "{{count}} files changed in this conversation" }, "retry": { "title": "Retry", @@ -217,7 +218,7 @@ "truncation": { "title": "Context Truncated", "inProgress": "Truncating context...", - "messagesRemoved": "{{count}} message removed", + "messagesRemoved_one": "{{count}} message removed", "messagesRemoved_other": "{{count}} messages removed", "description": "Older messages were removed from the conversation to stay within the context window limit. This is a fast but less context-preserving approach compared to condensation." } @@ -260,7 +261,7 @@ "codebaseSearch": { "wantsToSearch": "Zoo wants to search the codebase for {{query}}", "wantsToSearchWithPath": "Zoo wants to search the codebase for {{query}} in {{path}}", - "didSearch_one": "Found 1 result", + "didSearch_one": "Found {{count}} result", "didSearch_other": "Found {{count}} results", "resultTooltip": "Similarity score: {{score}} (click to open file)" }, @@ -333,7 +334,7 @@ "triggerLabelOff": "Auto-approve off", "triggerLabelOffShort": "Off", "triggerLabel_zero": "0 auto-approve", - "triggerLabel_one": "1 auto-approved", + "triggerLabel_one": "{{count}} auto-approved", "triggerLabel_other": "{{count}} auto-approved", "triggerLabelAll": "BRRR" }, @@ -376,7 +377,8 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Auto-Approved Request Limit Reached", - "description": "Zoo has reached the auto-approved limit of {{count}} API request(s). Would you like to reset the count and proceed with the task?", + "description_one": "Zoo has reached the auto-approved limit of {{count}} API request. Would you like to reset the count and proceed with the task?", + "description_other": "Zoo has reached the auto-approved limit of {{count}} API requests. Would you like to reset the count and proceed with the task?", "button": "Reset and Continue" }, "autoApprovedCostLimitReached": { diff --git a/webview-ui/src/i18n/locales/en/common.json b/webview-ui/src/i18n/locales/en/common.json index 3253152cd4..f81e72ba4f 100644 --- a/webview-ui/src/i18n/locales/en/common.json +++ b/webview-ui/src/i18n/locales/en/common.json @@ -57,19 +57,26 @@ }, "time_ago": { "just_now": "just now", - "seconds_ago": "{{count}} seconds ago", + "seconds_ago_one": "{{count}} second ago", + "seconds_ago_other": "{{count}} seconds ago", "minute_ago": "a minute ago", - "minutes_ago": "{{count}} minutes ago", + "minutes_ago_one": "{{count}} minute ago", + "minutes_ago_other": "{{count}} minutes ago", "hour_ago": "an hour ago", - "hours_ago": "{{count}} hours ago", + "hours_ago_one": "{{count}} hour ago", + "hours_ago_other": "{{count}} hours ago", "day_ago": "a day ago", - "days_ago": "{{count}} days ago", + "days_ago_one": "{{count}} day ago", + "days_ago_other": "{{count}} days ago", "week_ago": "a week ago", - "weeks_ago": "{{count}} weeks ago", + "weeks_ago_one": "{{count}} week ago", + "weeks_ago_other": "{{count}} weeks ago", "month_ago": "a month ago", - "months_ago": "{{count}} months ago", + "months_ago_one": "{{count}} month ago", + "months_ago_other": "{{count}} months ago", "year_ago": "a year ago", - "years_ago": "{{count}} years ago" + "years_ago_one": "{{count}} year ago", + "years_ago_other": "{{count}} years ago" }, "errors": { "wait_checkpoint_long_time": "Waited {{timeout}} seconds for checkpoint initialization. If you don't need the checkpoint feature, please turn it off in the checkpoint settings.", diff --git a/webview-ui/src/i18n/locales/en/history.json b/webview-ui/src/i18n/locales/en/history.json index 0eb7ea53ec..f45b7d2be6 100644 --- a/webview-ui/src/i18n/locales/en/history.json +++ b/webview-ui/src/i18n/locales/en/history.json @@ -26,9 +26,11 @@ "clearSelection": "Clear Selection", "deleteSelected": "Delete Selected", "deleteTasks": "Delete Tasks", - "confirmDeleteTasks": "Are you sure you want to delete {{count}} tasks?", + "confirmDeleteTasks_one": "Are you sure you want to delete {{count}} task?", + "confirmDeleteTasks_other": "Are you sure you want to delete {{count}} tasks?", "deleteTasksWarning": "Deleted tasks cannot be recovered. Please make sure you want to proceed.", - "deleteItems": "Delete {{count}} Items", + "deleteItems_one": "Delete {{count}} Item", + "deleteItems_other": "Delete {{count}} Items", "workspace": { "prefix": "Workspace:", "current": "Current", @@ -46,7 +48,8 @@ "subtasks_one": "{{count}} subtask", "subtasks_other": "{{count}} subtasks", "subtaskTag": "Subtask", - "deleteWithSubtasks": "This will also delete {{count}} subtask(s). Are you sure?", + "deleteWithSubtasks_one": "This will also delete {{count}} subtask. Are you sure?", + "deleteWithSubtasks_other": "This will also delete {{count}} subtasks. Are you sure?", "expandSubtasks": "Expand subtasks", "collapseSubtasks": "Collapse subtasks", "delegatedTag": "Waiting on subtask", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index a5cd604aed..4655ed7fbe 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -1024,7 +1024,8 @@ "useAzure": "Use Azure", "azureApiVersion": "Set Azure API version", "gemini": { - "freeRequests": "* Free up to {{count}} requests per minute. After that, billing depends on prompt size.", + "freeRequests_one": "* Free up to {{count}} request per minute. After that, billing depends on prompt size.", + "freeRequests_other": "* Free up to {{count}} requests per minute. After that, billing depends on prompt size.", "pricingDetails": "For more info, see pricing details.", "billingEstimate": "* Billing is an estimate - exact cost depends on prompt size." } diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index c9f18174c6..118d809aae 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -20,7 +20,9 @@ "unpin": "Desfijar", "pin": "Fijar", "fileChangesInConversation": { - "header": "{{count}} archivo(s) modificado(s) en esta conversación" + "header_one": "{{count}} archivo modificado en esta conversación", + "header_many": "{{count}} archivos modificados en esta conversación", + "header_other": "{{count}} archivos modificados en esta conversación" }, "retry": { "title": "Reintentar", @@ -287,7 +289,8 @@ "triggerLabelOff": "Aprobación automática desactivada", "triggerLabelOffShort": "Desactivado", "triggerLabel_zero": "0 aprobaciones automáticas", - "triggerLabel_one": "1 aprobación automática", + "triggerLabel_one": "{{count}} aprobación automática", + "triggerLabel_many": "{{count}} aprobaciones automáticas", "triggerLabel_other": "{{count}} aprobaciones automáticas", "triggerLabelAll": "BRRR" }, @@ -305,7 +308,8 @@ "truncation": { "title": "Contexto truncado", "inProgress": "Truncando contexto...", - "messagesRemoved": "{{count}} mensaje eliminado", + "messagesRemoved_one": "{{count}} mensaje eliminado", + "messagesRemoved_many": "{{count}} mensajes eliminados", "messagesRemoved_other": "{{count}} mensajes eliminados", "description": "Se eliminaron mensajes más antiguos de la conversación para mantenerse dentro del límite de la ventana de contexto. Este es un enfoque rápido pero menos conservador del contexto en comparación con la condensación." } @@ -349,7 +353,9 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Límite de Solicitudes Auto-aprobadas Alcanzado", - "description": "Zoo ha alcanzado el límite auto-aprobado de {{count}} solicitud(es) API. ¿Deseas reiniciar el contador y continuar con la tarea?", + "description_one": "Zoo ha alcanzado el límite auto-aprobado de {{count}} solicitud API. ¿Deseas reiniciar el contador y continuar con la tarea?", + "description_many": "Zoo ha alcanzado el límite auto-aprobado de {{count}} solicitudes API. ¿Deseas reiniciar el contador y continuar con la tarea?", + "description_other": "Zoo ha alcanzado el límite auto-aprobado de {{count}} solicitudes API. ¿Deseas reiniciar el contador y continuar con la tarea?", "button": "Reiniciar y Continuar" }, "autoApprovedCostLimitReached": { @@ -361,7 +367,8 @@ "codebaseSearch": { "wantsToSearch": "Zoo quiere buscar en la base de código {{query}}", "wantsToSearchWithPath": "Zoo quiere buscar en la base de código {{query}} en {{path}}", - "didSearch_one": "Se encontró 1 resultado", + "didSearch_one": "Se encontró {{count}} resultado", + "didSearch_many": "Se encontraron {{count}} resultados", "didSearch_other": "Se encontraron {{count}} resultados", "resultTooltip": "Puntuación de similitud: {{score}} (haz clic para abrir el archivo)" }, @@ -433,8 +440,10 @@ "tooManyTools": { "title": "Demasiadas herramientas habilitadas", "toolsPart_one": "{{count}} herramienta", + "toolsPart_many": "{{count}} herramientas", "toolsPart_other": "{{count}} herramientas", "serversPart_one": "{{count}} servidor MCP", + "serversPart_many": "{{count}} servidores MCP", "serversPart_other": "{{count}} servidores MCP", "messageTemplate": "Tienes {{tools}} habilitadas a través de {{servers}}. Un número tan alto puede confundir al modelo y llevar a errores. Intenta mantenerlo por debajo de {{threshold}}.", "openMcpSettings": "Abrir configuración de MCP" diff --git a/webview-ui/src/i18n/locales/es/common.json b/webview-ui/src/i18n/locales/es/common.json index a6488c1be5..cb9af18b65 100644 --- a/webview-ui/src/i18n/locales/es/common.json +++ b/webview-ui/src/i18n/locales/es/common.json @@ -57,19 +57,33 @@ }, "time_ago": { "just_now": "ahora mismo", - "seconds_ago": "hace {{count}} segundos", + "seconds_ago_one": "hace {{count}} segundo", + "seconds_ago_many": "hace {{count}} segundos", + "seconds_ago_other": "hace {{count}} segundos", "minute_ago": "hace un minuto", - "minutes_ago": "hace {{count}} minutos", + "minutes_ago_one": "hace {{count}} minuto", + "minutes_ago_many": "hace {{count}} minutos", + "minutes_ago_other": "hace {{count}} minutos", "hour_ago": "hace una hora", - "hours_ago": "hace {{count}} horas", + "hours_ago_one": "hace {{count}} hora", + "hours_ago_many": "hace {{count}} horas", + "hours_ago_other": "hace {{count}} horas", "day_ago": "hace un día", - "days_ago": "hace {{count}} días", + "days_ago_one": "hace {{count}} día", + "days_ago_many": "hace {{count}} días", + "days_ago_other": "hace {{count}} días", "week_ago": "hace una semana", - "weeks_ago": "hace {{count}} semanas", + "weeks_ago_one": "hace {{count}} semana", + "weeks_ago_many": "hace {{count}} semanas", + "weeks_ago_other": "hace {{count}} semanas", "month_ago": "hace un mes", - "months_ago": "hace {{count}} meses", + "months_ago_one": "hace {{count}} mes", + "months_ago_many": "hace {{count}} meses", + "months_ago_other": "hace {{count}} meses", "year_ago": "hace un año", - "years_ago": "hace {{count}} años" + "years_ago_one": "hace {{count}} año", + "years_ago_many": "hace {{count}} años", + "years_ago_other": "hace {{count}} años" }, "errors": { "wait_checkpoint_long_time": "Has esperado {{timeout}} segundos para la inicialización del punto de control. Si no necesitas esta función, desactívala en la configuración del punto de control.", diff --git a/webview-ui/src/i18n/locales/es/history.json b/webview-ui/src/i18n/locales/es/history.json index a555ca5e73..1ce125d723 100644 --- a/webview-ui/src/i18n/locales/es/history.json +++ b/webview-ui/src/i18n/locales/es/history.json @@ -33,9 +33,13 @@ "clearSelection": "Limpiar selección", "deleteSelected": "Eliminar seleccionados", "deleteTasks": "Eliminar tareas", - "confirmDeleteTasks": "¿Estás seguro de que quieres eliminar {{count}} tareas?", + "confirmDeleteTasks_one": "¿Estás seguro de que quieres eliminar {{count}} tarea?", + "confirmDeleteTasks_many": "¿Estás seguro de que quieres eliminar {{count}} tareas?", + "confirmDeleteTasks_other": "¿Estás seguro de que quieres eliminar {{count}} tareas?", "deleteTasksWarning": "Las tareas eliminadas no se pueden recuperar. Por favor, asegúrate de que quieres continuar.", - "deleteItems": "Eliminar {{count}} elementos", + "deleteItems_one": "Eliminar {{count}} elemento", + "deleteItems_many": "Eliminar {{count}} elementos", + "deleteItems_other": "Eliminar {{count}} elementos", "workspace": { "prefix": "Espacio de trabajo:", "current": "Actual", @@ -51,9 +55,12 @@ }, "viewAllHistory": "Ver todo", "subtasks_one": "{{count}} subtarea", + "subtasks_many": "{{count}} subtareas", "subtasks_other": "{{count}} subtareas", "subtaskTag": "Subtarea", - "deleteWithSubtasks": "Esto también eliminará {{count}} subtarea(s). ¿Estás seguro?", + "deleteWithSubtasks_one": "Esto también eliminará {{count}} subtarea. ¿Estás seguro?", + "deleteWithSubtasks_many": "Esto también eliminará {{count}} subtareas. ¿Estás seguro?", + "deleteWithSubtasks_other": "Esto también eliminará {{count}} subtareas. ¿Estás seguro?", "expandSubtasks": "Expandir subtareas", "collapseSubtasks": "Contraer subtareas", "delegatedTag": "Esperando subtarea", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index a100b767f9..27623532b0 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -77,6 +77,7 @@ "summaryCopied": "{{copied}} de {{total}} archivos copiados", "detailFailed": "Inicia un nuevo intento de importación para volver a intentarlo.", "detailTasksImported_one": "Importado {{count}} de {{total}} historial de tareas.", + "detailTasksImported_many": "Importados {{count}} de {{total}} historiales de tareas.", "detailTasksImported_other": "Importados {{count}} de {{total}} historiales de tareas.", "detailPreparing": "Preparando la importación del historial de Roo Code.", "progressAriaLabel": "Progreso de importación del historial de Roo Code" @@ -951,7 +952,9 @@ "useAzure": "Usar Azure", "azureApiVersion": "Establecer versión de API de Azure", "gemini": { - "freeRequests": "* Gratis hasta {{count}} solicitudes por minuto. Después de eso, la facturación depende del tamaño del prompt.", + "freeRequests_one": "* Gratis hasta {{count}} solicitud por minuto. Después de eso, la facturación depende del tamaño del prompt.", + "freeRequests_many": "* Gratis hasta {{count}} solicitudes por minuto. Después de eso, la facturación depende del tamaño del prompt.", + "freeRequests_other": "* Gratis hasta {{count}} solicitudes por minuto. Después de eso, la facturación depende del tamaño del prompt.", "pricingDetails": "Para más información, consulte los detalles de precios.", "billingEstimate": "* La facturación es una estimación - el costo exacto depende del tamaño del prompt." } diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index ca203d2ee3..f5f452b687 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -20,7 +20,9 @@ "unpin": "Désépingler", "pin": "Épingler", "fileChangesInConversation": { - "header": "{{count}} fichier(s) modifié(s) dans cette conversation" + "header_one": "{{count}} fichier modifié dans cette conversation", + "header_many": "{{count}} fichiers modifiés dans cette conversation", + "header_other": "{{count}} fichiers modifiés dans cette conversation" }, "tokenProgress": { "availableSpace": "Espace disponible : {{amount}} tokens", @@ -287,7 +289,8 @@ "triggerLabelOff": "Approbation automatique désactivée", "triggerLabelOffShort": "Désactivé", "triggerLabel_zero": "0 approuvé automatiquement", - "triggerLabel_one": "1 approuvé automatiquement", + "triggerLabel_one": "{{count}} approuvé automatiquement", + "triggerLabel_many": "{{count}} approuvés automatiquement", "triggerLabel_other": "{{count}} approuvés automatiquement", "triggerLabelAll": "BRRR" }, @@ -305,7 +308,8 @@ "truncation": { "title": "Contexte tronqué", "inProgress": "Troncature du contexte...", - "messagesRemoved": "{{count}} message supprimé", + "messagesRemoved_one": "{{count}} message supprimé", + "messagesRemoved_many": "{{count}} messages supprimés", "messagesRemoved_other": "{{count}} messages supprimés", "description": "Les messages plus anciens ont été supprimés de la conversation pour rester dans la limite de la fenêtre de contexte. C'est une approche rapide mais moins conservatrice du contexte par rapport à la condensation." } @@ -349,7 +353,9 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Limite de requêtes auto-approuvées atteinte", - "description": "Zoo a atteint la limite auto-approuvée de {{count}} requête(s) API. Souhaitez-vous réinitialiser le compteur et poursuivre la tâche ?", + "description_one": "Zoo a atteint la limite auto-approuvée de {{count}} requête API. Souhaitez-vous réinitialiser le compteur et poursuivre la tâche ?", + "description_many": "Zoo a atteint la limite auto-approuvée de {{count}} requêtes API. Souhaitez-vous réinitialiser le compteur et poursuivre la tâche ?", + "description_other": "Zoo a atteint la limite auto-approuvée de {{count}} requêtes API. Souhaitez-vous réinitialiser le compteur et poursuivre la tâche ?", "button": "Réinitialiser et continuer" }, "autoApprovedCostLimitReached": { @@ -361,7 +367,8 @@ "codebaseSearch": { "wantsToSearch": "Zoo veut rechercher dans la base de code {{query}}", "wantsToSearchWithPath": "Zoo veut rechercher dans la base de code {{query}} dans {{path}}", - "didSearch_one": "1 résultat trouvé", + "didSearch_one": "{{count}} résultat trouvé", + "didSearch_many": "{{count}} résultats trouvés", "didSearch_other": "{{count}} résultats trouvés", "resultTooltip": "Score de similarité : {{score}} (cliquer pour ouvrir le fichier)" }, @@ -433,8 +440,10 @@ "tooManyTools": { "title": "Trop d'outils activés", "toolsPart_one": "{{count}} outil", + "toolsPart_many": "{{count}} outils", "toolsPart_other": "{{count}} outils", "serversPart_one": "{{count}} serveur MCP", + "serversPart_many": "{{count}} serveurs MCP", "serversPart_other": "{{count}} serveurs MCP", "messageTemplate": "Tu as {{tools}} activés via {{servers}}. Un nombre aussi élevé peut confondre le modèle et entraîner des erreurs. Essaie de le maintenir en dessous de {{threshold}}.", "openMcpSettings": "Ouvrir les paramètres MCP" diff --git a/webview-ui/src/i18n/locales/fr/common.json b/webview-ui/src/i18n/locales/fr/common.json index d03ab75ae0..42a8ab8351 100644 --- a/webview-ui/src/i18n/locales/fr/common.json +++ b/webview-ui/src/i18n/locales/fr/common.json @@ -57,19 +57,33 @@ }, "time_ago": { "just_now": "à l'instant", - "seconds_ago": "il y a {{count}} secondes", + "seconds_ago_one": "il y a {{count}} seconde", + "seconds_ago_many": "il y a {{count}} secondes", + "seconds_ago_other": "il y a {{count}} secondes", "minute_ago": "il y a une minute", - "minutes_ago": "il y a {{count}} minutes", + "minutes_ago_one": "il y a {{count}} minute", + "minutes_ago_many": "il y a {{count}} minutes", + "minutes_ago_other": "il y a {{count}} minutes", "hour_ago": "il y a une heure", - "hours_ago": "il y a {{count}} heures", + "hours_ago_one": "il y a {{count}} heure", + "hours_ago_many": "il y a {{count}} heures", + "hours_ago_other": "il y a {{count}} heures", "day_ago": "il y a un jour", - "days_ago": "il y a {{count}} jours", + "days_ago_one": "il y a {{count}} jour", + "days_ago_many": "il y a {{count}} jours", + "days_ago_other": "il y a {{count}} jours", "week_ago": "il y a une semaine", - "weeks_ago": "il y a {{count}} semaines", + "weeks_ago_one": "il y a {{count}} semaine", + "weeks_ago_many": "il y a {{count}} semaines", + "weeks_ago_other": "il y a {{count}} semaines", "month_ago": "il y a un mois", - "months_ago": "il y a {{count}} mois", + "months_ago_one": "il y a {{count}} mois", + "months_ago_many": "il y a {{count}} mois", + "months_ago_other": "il y a {{count}} mois", "year_ago": "il y a un an", - "years_ago": "il y a {{count}} ans" + "years_ago_one": "il y a {{count}} an", + "years_ago_many": "il y a {{count}} ans", + "years_ago_other": "il y a {{count}} ans" }, "errors": { "wait_checkpoint_long_time": "Tu as attendu {{timeout}} secondes pour l'initialisation du checkpoint. Si tu n'as pas besoin de cette fonction, désactive-la dans les paramètres du checkpoint.", diff --git a/webview-ui/src/i18n/locales/fr/history.json b/webview-ui/src/i18n/locales/fr/history.json index a240602dba..d3e508547d 100644 --- a/webview-ui/src/i18n/locales/fr/history.json +++ b/webview-ui/src/i18n/locales/fr/history.json @@ -33,9 +33,13 @@ "clearSelection": "Effacer la sélection", "deleteSelected": "Supprimer les éléments sélectionnés", "deleteTasks": "Supprimer les tâches", - "confirmDeleteTasks": "Êtes-vous sûr de vouloir supprimer {{count}} tâches ?", + "confirmDeleteTasks_one": "Êtes-vous sûr de vouloir supprimer {{count}} tâche ?", + "confirmDeleteTasks_many": "Êtes-vous sûr de vouloir supprimer {{count}} tâches ?", + "confirmDeleteTasks_other": "Êtes-vous sûr de vouloir supprimer {{count}} tâches ?", "deleteTasksWarning": "Les tâches supprimées ne peuvent pas être récupérées. Veuillez confirmer que vous souhaitez continuer.", - "deleteItems": "Supprimer {{count}} éléments", + "deleteItems_one": "Supprimer {{count}} élément", + "deleteItems_many": "Supprimer {{count}} éléments", + "deleteItems_other": "Supprimer {{count}} éléments", "workspace": { "prefix": "Espace de travail :", "current": "Actuel", @@ -51,9 +55,12 @@ }, "viewAllHistory": "Voir tout", "subtasks_one": "{{count}} sous-tâche", + "subtasks_many": "{{count}} sous-tâches", "subtasks_other": "{{count}} sous-tâches", "subtaskTag": "Sous-tâche", - "deleteWithSubtasks": "Cela supprimera aussi {{count}} sous-tâche(s). Êtes-vous sûr ?", + "deleteWithSubtasks_one": "Cela supprimera aussi {{count}} sous-tâche. Êtes-vous sûr ?", + "deleteWithSubtasks_many": "Cela supprimera aussi {{count}} sous-tâches. Êtes-vous sûr ?", + "deleteWithSubtasks_other": "Cela supprimera aussi {{count}} sous-tâches. Êtes-vous sûr ?", "expandSubtasks": "Développer les sous-tâches", "collapseSubtasks": "Réduire les sous-tâches", "delegatedTag": "En attente de sous-tâche", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index aba006610b..0efde01694 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -77,6 +77,7 @@ "summaryCopied": "{{copied}} sur {{total}} fichiers copiés", "detailFailed": "Démarre une nouvelle tentative d'importation pour réessayer.", "detailTasksImported_one": "{{count}} sur {{total}} historique de tâche importé.", + "detailTasksImported_many": "{{count}} sur {{total}} historiques de tâches importés.", "detailTasksImported_other": "{{count}} sur {{total}} historiques de tâches importés.", "detailPreparing": "Préparation de l'importation de l'historique Roo Code.", "progressAriaLabel": "Progression de l'importation de l'historique Roo Code" @@ -951,7 +952,9 @@ "useAzure": "Utiliser Azure", "azureApiVersion": "Définir la version de l'API Azure", "gemini": { - "freeRequests": "* Gratuit jusqu'à {{count}} requêtes par minute. Après cela, la facturation dépend de la taille du prompt.", + "freeRequests_one": "* Gratuit jusqu'à {{count}} requête par minute. Après cela, la facturation dépend de la taille du prompt.", + "freeRequests_many": "* Gratuit jusqu'à {{count}} requêtes par minute. Après cela, la facturation dépend de la taille du prompt.", + "freeRequests_other": "* Gratuit jusqu'à {{count}} requêtes par minute. Après cela, la facturation dépend de la taille du prompt.", "pricingDetails": "Pour plus d'informations, voir les détails de tarification.", "billingEstimate": "* La facturation est une estimation - le coût exact dépend de la taille du prompt." } diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 8b11224966..695fc50172 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -20,7 +20,8 @@ "unpin": "पिन करें", "pin": "अवपिन करें", "fileChangesInConversation": { - "header": "इस वार्तालाप में {{count}} फ़ाइल(ें) बदली गईं" + "header_one": "इस वार्तालाप में {{count}} फ़ाइल बदली गई", + "header_other": "इस वार्तालाप में {{count}} फ़ाइलें बदली गईं" }, "tokenProgress": { "availableSpace": "उपलब्ध स्थान: {{amount}} tokens", @@ -287,7 +288,7 @@ "triggerLabelOff": "स्वतः-अनुमोदन बंद", "triggerLabelOffShort": "बंद", "triggerLabel_zero": "0 स्वतः-अनुमोदन", - "triggerLabel_one": "1 स्वतः-अनुमोदित", + "triggerLabel_one": "{{count}} स्वतः-अनुमोदित", "triggerLabel_other": "{{count}} स्वतः-अनुमोदित", "triggerLabelAll": "BRRR" }, @@ -305,7 +306,7 @@ "truncation": { "title": "संदर्भ छोटा किया गया", "inProgress": "संदर्भ छोटा कर रहा है...", - "messagesRemoved": "{{count}} संदेश हटाया गया", + "messagesRemoved_one": "{{count}} संदेश हटाया गया", "messagesRemoved_other": "{{count}} संदेश हटाए गए", "description": "संदर्भ विंडो सीमा के भीतर रहने के लिए बातचीत से पुराने संदेश हटा दिए गए। संघनन की तुलना में यह एक तेज़ लेकिन कम संदर्भ-संरक्षित दृष्टिकोण है।" } @@ -349,7 +350,8 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "स्वत:-स्वीकृत अनुरोध सीमा पहुंची", - "description": "Zoo {{count}} API अनुरोध(धों) की स्वत:-स्वीकृत सीमा तक पहुंच गया है। क्या आप गणना को रीसेट करके कार्य जारी रखना चाहते हैं?", + "description_one": "Zoo {{count}} API अनुरोध की स्वत:-स्वीकृत सीमा तक पहुंच गया है। क्या आप गणना को रीसेट करके कार्य जारी रखना चाहते हैं?", + "description_other": "Zoo {{count}} API अनुरोधों की स्वत:-स्वीकृत सीमा तक पहुंच गया है। क्या आप गणना को रीसेट करके कार्य जारी रखना चाहते हैं?", "button": "रीसेट करें और जारी रखें" }, "autoApprovedCostLimitReached": { @@ -361,7 +363,7 @@ "codebaseSearch": { "wantsToSearch": "Zoo कोडबेस में {{query}} खोजना चाहता है", "wantsToSearchWithPath": "Zoo {{path}} में कोडबेस में {{query}} खोजना चाहता है", - "didSearch_one": "1 परिणाम मिला", + "didSearch_one": "{{count}} परिणाम मिला", "didSearch_other": "{{count}} परिणाम मिले", "resultTooltip": "समानता स्कोर: {{score}} (फ़ाइल खोलने के लिए क्लिक करें)" }, diff --git a/webview-ui/src/i18n/locales/hi/common.json b/webview-ui/src/i18n/locales/hi/common.json index ce60d4715e..d370163b23 100644 --- a/webview-ui/src/i18n/locales/hi/common.json +++ b/webview-ui/src/i18n/locales/hi/common.json @@ -57,19 +57,26 @@ }, "time_ago": { "just_now": "अभी", - "seconds_ago": "{{count}} सेकंड पहले", + "seconds_ago_one": "{{count}} सेकंड पहले", + "seconds_ago_other": "{{count}} सेकंड पहले", "minute_ago": "एक मिनट पहले", - "minutes_ago": "{{count}} मिनट पहले", + "minutes_ago_one": "{{count}} मिनट पहले", + "minutes_ago_other": "{{count}} मिनट पहले", "hour_ago": "एक घंटे पहले", - "hours_ago": "{{count}} घंटे पहले", + "hours_ago_one": "{{count}} घंटे पहले", + "hours_ago_other": "{{count}} घंटे पहले", "day_ago": "एक दिन पहले", - "days_ago": "{{count}} दिन पहले", + "days_ago_one": "{{count}} दिन पहले", + "days_ago_other": "{{count}} दिन पहले", "week_ago": "एक सप्ताह पहले", - "weeks_ago": "{{count}} सप्ताह पहले", + "weeks_ago_one": "{{count}} सप्ताह पहले", + "weeks_ago_other": "{{count}} सप्ताह पहले", "month_ago": "एक महीने पहले", - "months_ago": "{{count}} महीने पहले", + "months_ago_one": "{{count}} महीने पहले", + "months_ago_other": "{{count}} महीने पहले", "year_ago": "एक साल पहले", - "years_ago": "{{count}} साल पहले" + "years_ago_one": "{{count}} साल पहले", + "years_ago_other": "{{count}} साल पहले" }, "errors": { "wait_checkpoint_long_time": "तुमने {{timeout}} सेकंड तक चेकपॉइंट इनिशियलाइज़ेशन का इंतजार किया। अगर तुम्हें यह फ़ीचर नहीं चाहिए, तो चेकपॉइंट सेटिंग्स में बंद कर दो।", diff --git a/webview-ui/src/i18n/locales/hi/history.json b/webview-ui/src/i18n/locales/hi/history.json index c3a6dc7526..a2414917d9 100644 --- a/webview-ui/src/i18n/locales/hi/history.json +++ b/webview-ui/src/i18n/locales/hi/history.json @@ -26,9 +26,11 @@ "clearSelection": "चयन साफ़ करें", "deleteSelected": "चयनित हटाएं", "deleteTasks": "कार्य हटाएं", - "confirmDeleteTasks": "क्या आप वाकई {{count}} कार्य हटाना चाहते हैं?", + "confirmDeleteTasks_one": "क्या आप वाकई {{count}} कार्य हटाना चाहते हैं?", + "confirmDeleteTasks_other": "क्या आप वाकई {{count}} कार्य हटाना चाहते हैं?", "deleteTasksWarning": "हटाए गए कार्य पुनर्प्राप्त नहीं किए जा सकते। कृपया सुनिश्चित करें कि आप आगे बढ़ना चाहते हैं।", - "deleteItems": "{{count}} आइटम हटाएं", + "deleteItems_one": "{{count}} आइटम हटाएं", + "deleteItems_other": "{{count}} आइटम हटाएं", "workspace": { "prefix": "कार्यस्थान:", "current": "वर्तमान", @@ -46,7 +48,8 @@ "subtasks_one": "{{count}} उप-कार्य", "subtasks_other": "{{count}} उप-कार्य", "subtaskTag": "उप-कार्य", - "deleteWithSubtasks": "यह {{count}} उप-कार्य(कों) को भी हटा देगा। क्या आप निश्चित हैं?", + "deleteWithSubtasks_one": "यह {{count}} उप-कार्य को भी हटा देगा। क्या आप निश्चित हैं?", + "deleteWithSubtasks_other": "यह {{count}} उप-कार्यों को भी हटा देगा। क्या आप निश्चित हैं?", "expandSubtasks": "उप-कार्य विस्तारित करें", "collapseSubtasks": "उप-कार्य संपीड़ित करें", "delegatedTag": "उपकार्य की प्रतीक्षा", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 274d0b4217..c0101cd92e 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -951,7 +951,8 @@ "useAzure": "Azure का उपयोग करें", "azureApiVersion": "Azure API संस्करण सेट करें", "gemini": { - "freeRequests": "* प्रति मिनट {{count}} अनुरोधों तक मुफ्त। उसके बाद, बिलिंग प्रॉम्प्ट आकार पर निर्भर करती है।", + "freeRequests_one": "* प्रति मिनट {{count}} अनुरोध तक मुफ्त। उसके बाद, बिलिंग प्रॉम्प्ट आकार पर निर्भर करती है।", + "freeRequests_other": "* प्रति मिनट {{count}} अनुरोधों तक मुफ्त। उसके बाद, बिलिंग प्रॉम्प्ट आकार पर निर्भर करती है।", "pricingDetails": "अधिक जानकारी के लिए, मूल्य निर्धारण विवरण देखें।", "billingEstimate": "* बिलिंग एक अनुमान है - सटीक लागत प्रॉम्प्ट आकार पर निर्भर करती है।" } diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index 9f844381cd..685d5f8a0b 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -23,7 +23,7 @@ "unpin": "Lepas Pin", "pin": "Pin", "fileChangesInConversation": { - "header": "{{count}} file diubah dalam percakapan ini" + "header_other": "{{count}} file diubah dalam percakapan ini" }, "retry": { "title": "Coba Lagi", @@ -220,7 +220,6 @@ "truncation": { "title": "Konteks Dipotong", "inProgress": "Memotong konteks...", - "messagesRemoved": "{{count}} pesan dihapus", "messagesRemoved_other": "{{count}} pesan dihapus", "description": "Pesan lama telah dihapus dari percakapan untuk tetap dalam batas jendela konteks. Ini adalah pendekatan yang cepat tetapi kurang mempertahankan konteks dibandingkan dengan kondensasi." } @@ -268,7 +267,6 @@ "codebaseSearch": { "wantsToSearch": "Zoo ingin mencari codebase untuk {{query}}", "wantsToSearchWithPath": "Zoo ingin mencari codebase untuk {{query}} di {{path}}", - "didSearch_one": "Ditemukan 1 hasil", "didSearch_other": "Ditemukan {{count}} hasil", "resultTooltip": "Skor kemiripan: {{score}} (klik untuk membuka file)" }, @@ -343,7 +341,6 @@ "triggerLabelOff": "Persetujuan otomatis mati", "triggerLabelOffShort": "Mati", "triggerLabel_zero": "0 disetujui otomatis", - "triggerLabel_one": "1 disetujui otomatis", "triggerLabel_other": "{{count}} disetujui otomatis", "triggerLabelAll": "BRRR" }, @@ -386,7 +383,7 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Batas Permintaan yang Disetujui Otomatis Tercapai", - "description": "Zoo telah mencapai batas {{count}} permintaan API yang disetujui otomatis. Apakah Anda ingin mengatur ulang hitungan dan melanjutkan tugas?", + "description_other": "Zoo telah mencapai batas {{count}} permintaan API yang disetujui otomatis. Apakah Anda ingin mengatur ulang hitungan dan melanjutkan tugas?", "button": "Setel Ulang dan Lanjutkan" }, "autoApprovedCostLimitReached": { @@ -438,9 +435,7 @@ }, "tooManyTools": { "title": "Terlalu banyak alat diaktifkan", - "toolsPart_one": "{{count}} alat", "toolsPart_other": "{{count}} alat", - "serversPart_one": "{{count}} server MCP", "serversPart_other": "{{count}} server MCP", "messageTemplate": "Anda memiliki {{tools}} diaktifkan melalui {{servers}}. Jumlah yang begitu besar dapat membingungkan model dan menyebabkan kesalahan. Cobalah untuk menjaganya di bawah {{threshold}}.", "openMcpSettings": "Buka Pengaturan MCP" diff --git a/webview-ui/src/i18n/locales/id/common.json b/webview-ui/src/i18n/locales/id/common.json index 0d6dbd224f..86d5fa8a49 100644 --- a/webview-ui/src/i18n/locales/id/common.json +++ b/webview-ui/src/i18n/locales/id/common.json @@ -57,19 +57,19 @@ }, "time_ago": { "just_now": "baru saja", - "seconds_ago": "{{count}} detik yang lalu", + "seconds_ago_other": "{{count}} detik yang lalu", "minute_ago": "satu menit yang lalu", - "minutes_ago": "{{count}} menit yang lalu", + "minutes_ago_other": "{{count}} menit yang lalu", "hour_ago": "satu jam yang lalu", - "hours_ago": "{{count}} jam yang lalu", + "hours_ago_other": "{{count}} jam yang lalu", "day_ago": "satu hari yang lalu", - "days_ago": "{{count}} hari yang lalu", + "days_ago_other": "{{count}} hari yang lalu", "week_ago": "satu minggu yang lalu", - "weeks_ago": "{{count}} minggu yang lalu", + "weeks_ago_other": "{{count}} minggu yang lalu", "month_ago": "satu bulan yang lalu", - "months_ago": "{{count}} bulan yang lalu", + "months_ago_other": "{{count}} bulan yang lalu", "year_ago": "satu tahun yang lalu", - "years_ago": "{{count}} tahun yang lalu" + "years_ago_other": "{{count}} tahun yang lalu" }, "errors": { "wait_checkpoint_long_time": "Kamu sudah menunggu {{timeout}} detik untuk inisialisasi checkpoint. Kalau tidak butuh fitur ini, matikan saja di pengaturan checkpoint.", diff --git a/webview-ui/src/i18n/locales/id/history.json b/webview-ui/src/i18n/locales/id/history.json index 4cc3503970..1e0fbad88b 100644 --- a/webview-ui/src/i18n/locales/id/history.json +++ b/webview-ui/src/i18n/locales/id/history.json @@ -33,11 +33,11 @@ "clearSelection": "Hapus Seleksi", "deleteSelected": "Hapus yang Dipilih", "deleteTasks": "Hapus Tugas", - "confirmDeleteTasks": "Apakah kamu yakin ingin menghapus {{count}} tugas?", + "confirmDeleteTasks_other": "Apakah kamu yakin ingin menghapus {{count}} tugas?", "deleteTasksWarning": "Tugas yang dihapus tidak dapat dipulihkan. Pastikan kamu ingin melanjutkan.", "deleteTaskFavoritedWarning": "Tugas ini telah ditandai sebagai favorit. Apakah kamu yakin ingin menghapusnya?", "deleteTasksFavoritedWarning": "{{count}} tugas yang dipilih telah ditandai sebagai favorit. Apakah kamu yakin ingin menghapusnya?", - "deleteItems": "Hapus {{count}} Item", + "deleteItems_other": "Hapus {{count}} Item", "workspace": { "prefix": "Ruang Kerja:", "current": "Saat Ini", @@ -52,10 +52,9 @@ "mostRelevant": "Paling Relevan" }, "viewAllHistory": "Lihat semua", - "subtasks_one": "{{count}} subtask", "subtasks_other": "{{count}} subtask", "subtaskTag": "Subtask", - "deleteWithSubtasks": "Ini juga akan menghapus {{count}} subtask. Apakah Anda yakin?", + "deleteWithSubtasks_other": "Ini juga akan menghapus {{count}} subtask. Apakah Anda yakin?", "expandSubtasks": "Perluas subtask", "collapseSubtasks": "Tutup subtask", "delegatedTag": "Menunggu subtugas", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index f88ddf8500..060629cfb9 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -76,7 +76,6 @@ "summaryFailedNoFiles": "Impor berhenti sebelum file apa pun disalin.", "summaryCopied": "{{copied}} dari {{total}} file disalin", "detailFailed": "Mulai percobaan impor baru untuk mencoba lagi.", - "detailTasksImported_one": "{{count}} dari {{total}} riwayat tugas diimpor.", "detailTasksImported_other": "{{count}} dari {{total}} riwayat tugas diimpor.", "detailPreparing": "Mempersiapkan impor riwayat Roo Code.", "progressAriaLabel": "Progres impor riwayat Roo Code" @@ -951,7 +950,7 @@ "useAzure": "Gunakan Azure", "azureApiVersion": "Atur versi API Azure", "gemini": { - "freeRequests": "* Gratis hingga {{count}} permintaan per menit. Setelah itu, penagihan tergantung pada ukuran prompt.", + "freeRequests_other": "* Gratis hingga {{count}} permintaan per menit. Setelah itu, penagihan tergantung pada ukuran prompt.", "pricingDetails": "Untuk info lebih lanjut, lihat detail harga.", "billingEstimate": "* Penagihan adalah estimasi - biaya sebenarnya tergantung pada ukuran prompt." } diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index eeaba17976..564745eb29 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -20,7 +20,9 @@ "unpin": "Rilascia", "pin": "Fissa", "fileChangesInConversation": { - "header": "{{count}} file modificati in questa conversazione" + "header_one": "{{count}} file modificato in questa conversazione", + "header_many": "{{count}} file modificati in questa conversazione", + "header_other": "{{count}} file modificati in questa conversazione" }, "tokenProgress": { "availableSpace": "Spazio disponibile: {{amount}} tokens", @@ -287,7 +289,8 @@ "triggerLabelOff": "Approvazione automatica disattivata", "triggerLabelOffShort": "Disattivata", "triggerLabel_zero": "0 approvati automaticamente", - "triggerLabel_one": "1 approvato automaticamente", + "triggerLabel_one": "{{count}} approvato automaticamente", + "triggerLabel_many": "{{count}} approvati automaticamente", "triggerLabel_other": "{{count}} approvati automaticamente", "triggerLabelAll": "BRRR" }, @@ -305,7 +308,8 @@ "truncation": { "title": "Contesto troncato", "inProgress": "Troncamento del contesto...", - "messagesRemoved": "{{count}} messaggio rimosso", + "messagesRemoved_one": "{{count}} messaggio rimosso", + "messagesRemoved_many": "{{count}} messaggi rimossi", "messagesRemoved_other": "{{count}} messaggi rimossi", "description": "I messaggi più vecchi sono stati rimossi dalla conversazione per rimanere entro il limite della finestra di contesto. Questo è un approccio veloce ma meno conservativo del contesto rispetto alla condensazione." } @@ -349,7 +353,9 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Limite di Richieste Auto-approvate Raggiunto", - "description": "Zoo ha raggiunto il limite auto-approvato di {{count}} richiesta/e API. Vuoi reimpostare il contatore e procedere con l'attività?", + "description_one": "Zoo ha raggiunto il limite auto-approvato di {{count}} richiesta API. Vuoi reimpostare il contatore e procedere con l'attività?", + "description_many": "Zoo ha raggiunto il limite auto-approvato di {{count}} richieste API. Vuoi reimpostare il contatore e procedere con l'attività?", + "description_other": "Zoo ha raggiunto il limite auto-approvato di {{count}} richieste API. Vuoi reimpostare il contatore e procedere con l'attività?", "button": "Reimposta e Continua" }, "autoApprovedCostLimitReached": { @@ -361,7 +367,8 @@ "codebaseSearch": { "wantsToSearch": "Zoo vuole cercare nella base di codice {{query}}", "wantsToSearchWithPath": "Zoo vuole cercare nella base di codice {{query}} in {{path}}", - "didSearch_one": "Trovato 1 risultato", + "didSearch_one": "Trovato {{count}} risultato", + "didSearch_many": "Trovati {{count}} risultati", "didSearch_other": "Trovati {{count}} risultati", "resultTooltip": "Punteggio di somiglianza: {{score}} (clicca per aprire il file)" }, @@ -433,8 +440,10 @@ "tooManyTools": { "title": "Troppi strumenti abilitati", "toolsPart_one": "{{count}} strumento", + "toolsPart_many": "{{count}} strumenti", "toolsPart_other": "{{count}} strumenti", "serversPart_one": "{{count}} server MCP", + "serversPart_many": "{{count}} server MCP", "serversPart_other": "{{count}} server MCP", "messageTemplate": "Hai {{tools}} abilitate via {{servers}}. Un numero così alto può confondere il modello e portare a errori. Prova a mantenerlo sotto {{threshold}}.", "openMcpSettings": "Apri impostazioni MCP" diff --git a/webview-ui/src/i18n/locales/it/common.json b/webview-ui/src/i18n/locales/it/common.json index 2cdc309c11..d1d92f085b 100644 --- a/webview-ui/src/i18n/locales/it/common.json +++ b/webview-ui/src/i18n/locales/it/common.json @@ -57,19 +57,33 @@ }, "time_ago": { "just_now": "proprio ora", - "seconds_ago": "{{count}} secondi fa", + "seconds_ago_one": "{{count}} secondo fa", + "seconds_ago_many": "{{count}} secondi fa", + "seconds_ago_other": "{{count}} secondi fa", "minute_ago": "un minuto fa", - "minutes_ago": "{{count}} minuti fa", + "minutes_ago_one": "{{count}} minuto fa", + "minutes_ago_many": "{{count}} minuti fa", + "minutes_ago_other": "{{count}} minuti fa", "hour_ago": "un'ora fa", - "hours_ago": "{{count}} ore fa", + "hours_ago_one": "{{count}} ora fa", + "hours_ago_many": "{{count}} ore fa", + "hours_ago_other": "{{count}} ore fa", "day_ago": "un giorno fa", - "days_ago": "{{count}} giorni fa", + "days_ago_one": "{{count}} giorno fa", + "days_ago_many": "{{count}} giorni fa", + "days_ago_other": "{{count}} giorni fa", "week_ago": "una settimana fa", - "weeks_ago": "{{count}} settimane fa", + "weeks_ago_one": "{{count}} settimana fa", + "weeks_ago_many": "{{count}} settimane fa", + "weeks_ago_other": "{{count}} settimane fa", "month_ago": "un mese fa", - "months_ago": "{{count}} mesi fa", + "months_ago_one": "{{count}} mese fa", + "months_ago_many": "{{count}} mesi fa", + "months_ago_other": "{{count}} mesi fa", "year_ago": "un anno fa", - "years_ago": "{{count}} anni fa" + "years_ago_one": "{{count}} anno fa", + "years_ago_many": "{{count}} anni fa", + "years_ago_other": "{{count}} anni fa" }, "errors": { "wait_checkpoint_long_time": "Hai aspettato {{timeout}} secondi per l'inizializzazione del checkpoint. Se non ti serve questa funzione, disattivala nelle impostazioni del checkpoint.", diff --git a/webview-ui/src/i18n/locales/it/history.json b/webview-ui/src/i18n/locales/it/history.json index 5719dc3cb9..4b9eee91d9 100644 --- a/webview-ui/src/i18n/locales/it/history.json +++ b/webview-ui/src/i18n/locales/it/history.json @@ -26,9 +26,13 @@ "clearSelection": "Cancella selezione", "deleteSelected": "Elimina selezionati", "deleteTasks": "Elimina attività", - "confirmDeleteTasks": "Sei sicuro di voler eliminare {{count}} attività?", + "confirmDeleteTasks_one": "Sei sicuro di voler eliminare {{count}} attività?", + "confirmDeleteTasks_many": "Sei sicuro di voler eliminare {{count}} attività?", + "confirmDeleteTasks_other": "Sei sicuro di voler eliminare {{count}} attività?", "deleteTasksWarning": "Le attività eliminate non possono essere recuperate. Assicurati di voler continuare.", - "deleteItems": "Elimina {{count}} elementi", + "deleteItems_one": "Elimina {{count}} elemento", + "deleteItems_many": "Elimina {{count}} elementi", + "deleteItems_other": "Elimina {{count}} elementi", "workspace": { "prefix": "Spazio di lavoro:", "current": "Attuale", @@ -44,9 +48,12 @@ }, "viewAllHistory": "Visualizza tutto", "subtasks_one": "{{count}} sottoattività", + "subtasks_many": "{{count}} sottoattività", "subtasks_other": "{{count}} sottoattività", "subtaskTag": "Sottoattività", - "deleteWithSubtasks": "Questo eliminerà anche {{count}} sottoattività. Sei sicuro?", + "deleteWithSubtasks_one": "Questo eliminerà anche {{count}} sottoattività. Sei sicuro?", + "deleteWithSubtasks_many": "Questo eliminerà anche {{count}} sottoattività. Sei sicuro?", + "deleteWithSubtasks_other": "Questo eliminerà anche {{count}} sottoattività. Sei sicuro?", "expandSubtasks": "Espandi sottoattività", "collapseSubtasks": "Comprimi sottoattività", "delegatedTag": "In attesa di sottoattività", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index ee1b282786..4c8cc0fbec 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -77,6 +77,7 @@ "summaryCopied": "{{copied}} di {{total}} file copiati", "detailFailed": "Avvia un nuovo tentativo di importazione per riprovare.", "detailTasksImported_one": "Importato {{count}} di {{total}} cronologia attività.", + "detailTasksImported_many": "Importati {{count}} di {{total}} cronologie attività.", "detailTasksImported_other": "Importati {{count}} di {{total}} cronologie attività.", "detailPreparing": "Preparazione dell'importazione della cronologia Roo Code.", "progressAriaLabel": "Avanzamento importazione cronologia Roo Code" @@ -951,7 +952,9 @@ "useAzure": "Usa Azure", "azureApiVersion": "Imposta versione API Azure", "gemini": { - "freeRequests": "* Gratuito fino a {{count}} richieste al minuto. Dopo, la fatturazione dipende dalla dimensione del prompt.", + "freeRequests_one": "* Gratuito fino a {{count}} richiesta al minuto. Dopo, la fatturazione dipende dalla dimensione del prompt.", + "freeRequests_many": "* Gratuito fino a {{count}} richieste al minuto. Dopo, la fatturazione dipende dalla dimensione del prompt.", + "freeRequests_other": "* Gratuito fino a {{count}} richieste al minuto. Dopo, la fatturazione dipende dalla dimensione del prompt.", "pricingDetails": "Per maggiori informazioni, vedi i dettagli sui prezzi.", "billingEstimate": "* La fatturazione è una stima - il costo esatto dipende dalle dimensioni del prompt." } diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index 9547109171..bbc5699c74 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -20,7 +20,7 @@ "unpin": "ピン留めを解除", "pin": "ピン留め", "fileChangesInConversation": { - "header": "この会話で {{count}} 個のファイルが変更されました" + "header_other": "この会話で {{count}} 個のファイルが変更されました" }, "tokenProgress": { "availableSpace": "利用可能な空き容量: {{amount}} トークン", @@ -287,7 +287,6 @@ "triggerLabelOff": "自動承認オフ", "triggerLabelOffShort": "オフ", "triggerLabel_zero": "0個の自動承認", - "triggerLabel_one": "1個の自動承認済み", "triggerLabel_other": "{{count}}個の自動承認済み", "triggerLabelAll": "BRRR" }, @@ -305,7 +304,6 @@ "truncation": { "title": "コンテキスト切り詰め", "inProgress": "コンテキストを切り詰め中...", - "messagesRemoved": "{{count}}件のメッセージを削除", "messagesRemoved_other": "{{count}}件のメッセージを削除", "description": "コンテキストウィンドウの制限内に収めるため、古いメッセージが会話から削除されました。これは圧縮と比較して高速ですが、コンテキストの保持性が低いアプローチです。" } @@ -349,7 +347,7 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "自動承認リクエスト制限に達しました", - "description": "Zooは{{count}}件のAPI自動承認リクエスト制限に達しました。カウントをリセットしてタスクを続行しますか?", + "description_other": "Zooは{{count}}件のAPI自動承認リクエスト制限に達しました。カウントをリセットしてタスクを続行しますか?", "button": "リセットして続行" }, "autoApprovedCostLimitReached": { @@ -361,7 +359,6 @@ "codebaseSearch": { "wantsToSearch": "Zooはコードベースで {{query}} を検索したい", "wantsToSearchWithPath": "Zooは {{path}} 内のコードベースで {{query}} を検索したい", - "didSearch_one": "1件の結果が見つかりました", "didSearch_other": "{{count}}件の結果が見つかりました", "resultTooltip": "類似度スコア: {{score}} (クリックしてファイルを開く)" }, @@ -432,9 +429,7 @@ }, "tooManyTools": { "title": "有効になっているツールが多すぎます", - "toolsPart_one": "{{count}} ツール", "toolsPart_other": "{{count}} ツール", - "serversPart_one": "{{count}} MCP サーバー", "serversPart_other": "{{count}} MCP サーバー", "messageTemplate": "{{servers}}経由で{{tools}}が有効になっています。このような高い数は、モデルを混乱させてエラーを引き起こす可能性があります。{{threshold}}以下に保つようにしてください。", "openMcpSettings": "MCP 設定を開く" diff --git a/webview-ui/src/i18n/locales/ja/common.json b/webview-ui/src/i18n/locales/ja/common.json index e009c69b07..4a70faf68e 100644 --- a/webview-ui/src/i18n/locales/ja/common.json +++ b/webview-ui/src/i18n/locales/ja/common.json @@ -57,19 +57,19 @@ }, "time_ago": { "just_now": "たった今", - "seconds_ago": "{{count}}秒前", + "seconds_ago_other": "{{count}}秒前", "minute_ago": "1分前", - "minutes_ago": "{{count}}分前", + "minutes_ago_other": "{{count}}分前", "hour_ago": "1時間前", - "hours_ago": "{{count}}時間前", + "hours_ago_other": "{{count}}時間前", "day_ago": "1日前", - "days_ago": "{{count}}日前", + "days_ago_other": "{{count}}日前", "week_ago": "1週間前", - "weeks_ago": "{{count}}週間前", + "weeks_ago_other": "{{count}}週間前", "month_ago": "1ヶ月前", - "months_ago": "{{count}}ヶ月前", + "months_ago_other": "{{count}}ヶ月前", "year_ago": "1年前", - "years_ago": "{{count}}年前" + "years_ago_other": "{{count}}年前" }, "errors": { "wait_checkpoint_long_time": "{{timeout}} 秒間チェックポイントの初期化を待機しました。チェックポイント機能が不要な場合は、チェックポイント設定でオフにしてください。", diff --git a/webview-ui/src/i18n/locales/ja/history.json b/webview-ui/src/i18n/locales/ja/history.json index 1f635dfb54..9910fb923c 100644 --- a/webview-ui/src/i18n/locales/ja/history.json +++ b/webview-ui/src/i18n/locales/ja/history.json @@ -26,9 +26,9 @@ "clearSelection": "選択をクリア", "deleteSelected": "選択した項目を削除", "deleteTasks": "タスクを削除", - "confirmDeleteTasks": "{{count}} 件のタスクを削除してもよろしいですか?", + "confirmDeleteTasks_other": "{{count}} 件のタスクを削除してもよろしいですか?", "deleteTasksWarning": "削除されたタスクは復元できません。続行してもよろしいですか?", - "deleteItems": "{{count}} 項目を削除", + "deleteItems_other": "{{count}} 項目を削除", "workspace": { "prefix": "ワークスペース:", "current": "現在", @@ -43,10 +43,9 @@ "mostRelevant": "最も関連性の高い" }, "viewAllHistory": "すべて表示", - "subtasks_one": "{{count}} サブタスク", "subtasks_other": "{{count}} サブタスク", "subtaskTag": "サブタスク", - "deleteWithSubtasks": "これにより {{count}} サブタスクも削除されます。よろしいですか?", + "deleteWithSubtasks_other": "これにより {{count}} サブタスクも削除されます。よろしいですか?", "expandSubtasks": "サブタスクを展開", "collapseSubtasks": "サブタスクを折りたたむ", "delegatedTag": "サブタスク待ち", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index a277b5485c..25e9c126aa 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -76,7 +76,6 @@ "summaryFailedNoFiles": "ファイルがコピーされる前にインポートが停止しました。", "summaryCopied": "{{total}} 件中 {{copied}} 件のファイルをコピー済み", "detailFailed": "新しいインポートを開始して再試行してください。", - "detailTasksImported_one": "{{total}} 件中 {{count}} 件のタスク履歴をインポートしました。", "detailTasksImported_other": "{{total}} 件中 {{count}} 件のタスク履歴をインポートしました。", "detailPreparing": "Roo Code の履歴インポートを準備中です。", "progressAriaLabel": "Roo Code の履歴インポートの進行状況" @@ -951,7 +950,7 @@ "useAzure": "Azureを使用", "azureApiVersion": "Azure APIバージョンを設定", "gemini": { - "freeRequests": "* 1分間あたり{{count}}リクエストまで無料。それ以降は、プロンプトサイズに応じて課金されます。", + "freeRequests_other": "* 1分間あたり{{count}}リクエストまで無料。それ以降は、プロンプトサイズに応じて課金されます。", "pricingDetails": "詳細は価格情報をご覧ください。", "billingEstimate": "* 課金は見積もりです - 正確な費用はプロンプトのサイズによって異なります。" } diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 5fd9f15839..e160ac1423 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -20,7 +20,7 @@ "unpin": "고정 해제하기", "pin": "고정하기", "fileChangesInConversation": { - "header": "이 대화에서 {{count}}개 파일이 변경됨" + "header_other": "이 대화에서 {{count}}개 파일이 변경됨" }, "tokenProgress": { "availableSpace": "사용 가능한 공간: {{amount}} 토큰", @@ -287,7 +287,6 @@ "triggerLabelOff": "자동 승인 꺼짐", "triggerLabelOffShort": "꺼짐", "triggerLabel_zero": "0개 자동 승인됨", - "triggerLabel_one": "1개 자동 승인됨", "triggerLabel_other": "{{count}}개 자동 승인됨", "triggerLabelAll": "BRRR" }, @@ -305,7 +304,6 @@ "truncation": { "title": "컨텍스트 잘림", "inProgress": "컨텍스트 자르는 중...", - "messagesRemoved": "{{count}}개 메시지 제거됨", "messagesRemoved_other": "{{count}}개 메시지 제거됨", "description": "컨텍스트 윈도우 제한 내에 유지하기 위해 대화에서 오래된 메시지가 제거되었습니다. 이것은 압축에 비해 빠르지만 컨텍스트 보존 능력이 낮은 접근 방식입니다." } @@ -349,7 +347,7 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "자동 승인 요청 한도 도달", - "description": "Zoo가 {{count}}개의 API 요청(들)에 대한 자동 승인 한도에 도달했습니다. 카운트를 재설정하고 작업을 계속하시겠습니까?", + "description_other": "Zoo가 {{count}}개의 API 요청에 대한 자동 승인 한도에 도달했습니다. 카운트를 재설정하고 작업을 계속하시겠습니까?", "button": "재설정 후 계속" }, "autoApprovedCostLimitReached": { @@ -361,7 +359,6 @@ "codebaseSearch": { "wantsToSearch": "Zoo가 코드베이스에서 {{query}}을(를) 검색하고 싶어합니다", "wantsToSearchWithPath": "Zoo가 {{path}}에서 {{query}}을(를) 검색하고 싶어합니다", - "didSearch_one": "1개의 결과를 찾았습니다", "didSearch_other": "{{count}}개의 결과를 찾았습니다", "resultTooltip": "유사도 점수: {{score}} (클릭하여 파일 열기)" }, @@ -432,9 +429,7 @@ }, "tooManyTools": { "title": "활성화된 도구가 너무 많습니다", - "toolsPart_one": "{{count}}개 도구", "toolsPart_other": "{{count}}개 도구", - "serversPart_one": "{{count}}개 MCP 서버", "serversPart_other": "{{count}}개 MCP 서버", "messageTemplate": "{{servers}}를 통해 {{tools}}가 활성화되어 있습니다. 이렇게 많은 수의 도구는 모델을 혼동시키고 오류를 유발할 수 있습니다. {{threshold}} 이하로 유지하도록 노력하세요.", "openMcpSettings": "MCP 설정 열기" diff --git a/webview-ui/src/i18n/locales/ko/common.json b/webview-ui/src/i18n/locales/ko/common.json index 0a4550b934..5e0843da7a 100644 --- a/webview-ui/src/i18n/locales/ko/common.json +++ b/webview-ui/src/i18n/locales/ko/common.json @@ -57,19 +57,19 @@ }, "time_ago": { "just_now": "방금", - "seconds_ago": "{{count}}초 전", + "seconds_ago_other": "{{count}}초 전", "minute_ago": "1분 전", - "minutes_ago": "{{count}}분 전", + "minutes_ago_other": "{{count}}분 전", "hour_ago": "1시간 전", - "hours_ago": "{{count}}시간 전", + "hours_ago_other": "{{count}}시간 전", "day_ago": "1일 전", - "days_ago": "{{count}}일 전", + "days_ago_other": "{{count}}일 전", "week_ago": "1주일 전", - "weeks_ago": "{{count}}주일 전", + "weeks_ago_other": "{{count}}주일 전", "month_ago": "1개월 전", - "months_ago": "{{count}}개월 전", + "months_ago_other": "{{count}}개월 전", "year_ago": "1년 전", - "years_ago": "{{count}}년 전" + "years_ago_other": "{{count}}년 전" }, "errors": { "wait_checkpoint_long_time": "{{timeout}}초 동안 체크포인트 초기화를 기다렸어. 체크포인트 기능이 필요 없다면 체크포인트 설정에서 꺼 줘.", diff --git a/webview-ui/src/i18n/locales/ko/history.json b/webview-ui/src/i18n/locales/ko/history.json index b5a204b7bf..3c998d4317 100644 --- a/webview-ui/src/i18n/locales/ko/history.json +++ b/webview-ui/src/i18n/locales/ko/history.json @@ -26,9 +26,9 @@ "clearSelection": "선택 초기화", "deleteSelected": "선택 항목 삭제", "deleteTasks": "작업 삭제", - "confirmDeleteTasks": "{{count}}개의 작업을 삭제하시겠습니까?", + "confirmDeleteTasks_other": "{{count}}개의 작업을 삭제하시겠습니까?", "deleteTasksWarning": "삭제된 작업은 복구할 수 없습니다. 계속 진행하시겠습니까?", - "deleteItems": "{{count}}개 항목 삭제", + "deleteItems_other": "{{count}}개 항목 삭제", "workspace": { "prefix": "워크스페이스:", "current": "현재", @@ -43,10 +43,9 @@ "mostRelevant": "관련성 높은순" }, "viewAllHistory": "모두 보기", - "subtasks_one": "{{count}} 부분작업", "subtasks_other": "{{count}} 부분작업", "subtaskTag": "부분작업", - "deleteWithSubtasks": "이는 {{count}} 부분작업도 삭제합니다. 확실하십니까?", + "deleteWithSubtasks_other": "이는 {{count}} 부분작업도 삭제합니다. 확실하십니까?", "expandSubtasks": "부분작업 확장", "collapseSubtasks": "부분작업 축소", "delegatedTag": "하위 작업 대기 중", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 87bd718210..2e28bc3526 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -76,7 +76,6 @@ "summaryFailedNoFiles": "파일이 복사되기 전에 가져오기가 중단되었습니다.", "summaryCopied": "{{total}}개 중 {{copied}}개 파일 복사됨", "detailFailed": "다시 시도하려면 새 가져오기를 시작하세요.", - "detailTasksImported_one": "{{total}}개 중 {{count}}개의 작업 기록을 가져왔습니다.", "detailTasksImported_other": "{{total}}개 중 {{count}}개의 작업 기록을 가져왔습니다.", "detailPreparing": "Roo Code 기록 가져오기를 준비 중입니다.", "progressAriaLabel": "Roo Code 기록 가져오기 진행률" @@ -951,7 +950,7 @@ "useAzure": "Azure 사용", "azureApiVersion": "Azure API 버전 설정", "gemini": { - "freeRequests": "* 분당 {{count}}개의 요청까지 무료. 이후에는 프롬프트 크기에 따라 요금이 부과됩니다.", + "freeRequests_other": "* 분당 {{count}}개의 요청까지 무료. 이후에는 프롬프트 크기에 따라 요금이 부과됩니다.", "pricingDetails": "자세한 내용은 가격 정보를 참조하세요.", "billingEstimate": "* 요금은 추정치입니다 - 정확한 비용은 프롬프트 크기에 따라 달라집니다." } diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index 876c4051e9..0a39ed7138 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -20,7 +20,8 @@ "unpin": "Losmaken", "pin": "Vastmaken", "fileChangesInConversation": { - "header": "{{count}} bestand(en) gewijzigd in dit gesprek" + "header_one": "{{count}} bestand gewijzigd in dit gesprek", + "header_other": "{{count}} bestanden gewijzigd in dit gesprek" }, "retry": { "title": "Opnieuw proberen", @@ -287,7 +288,7 @@ "triggerLabelOff": "Automatisch goedkeuren uit", "triggerLabelOffShort": "Uit", "triggerLabel_zero": "0 automatisch goedgekeurd", - "triggerLabel_one": "1 automatisch goedgekeurd", + "triggerLabel_one": "{{count}} automatisch goedgekeurd", "triggerLabel_other": "{{count}} automatisch goedgekeurd", "triggerLabelAll": "BRRR" }, @@ -315,7 +316,7 @@ "truncation": { "title": "Context ingekort", "inProgress": "Context aan het inkorten...", - "messagesRemoved": "{{count}} bericht verwijderd", + "messagesRemoved_one": "{{count}} bericht verwijderd", "messagesRemoved_other": "{{count}} berichten verwijderd", "description": "Oudere berichten zijn uit het gesprek verwijderd om binnen de limiet van het contextvenster te blijven. Dit is een snelle maar minder contextbehoudende aanpak in vergelijking met samenvoeging." } @@ -349,7 +350,8 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Limiet voor automatisch goedgekeurde verzoeken bereikt", - "description": "Zoo heeft de automatisch goedgekeurde limiet van {{count}} API-verzoek(en) bereikt. Wil je de teller resetten en doorgaan met de taak?", + "description_one": "Zoo heeft de automatisch goedgekeurde limiet van {{count}} API-verzoek bereikt. Wil je de teller resetten en doorgaan met de taak?", + "description_other": "Zoo heeft de automatisch goedgekeurde limiet van {{count}} API-verzoeken bereikt. Wil je de teller resetten en doorgaan met de taak?", "button": "Resetten en doorgaan" }, "autoApprovedCostLimitReached": { @@ -361,7 +363,7 @@ "codebaseSearch": { "wantsToSearch": "Zoo wil de codebase doorzoeken op {{query}}", "wantsToSearchWithPath": "Zoo wil de codebase doorzoeken op {{query}} in {{path}}", - "didSearch_one": "1 resultaat gevonden", + "didSearch_one": "{{count}} resultaat gevonden", "didSearch_other": "{{count}} resultaten gevonden", "resultTooltip": "Gelijkenisscore: {{score}} (klik om bestand te openen)" }, diff --git a/webview-ui/src/i18n/locales/nl/common.json b/webview-ui/src/i18n/locales/nl/common.json index 88250bf190..111a1c0e80 100644 --- a/webview-ui/src/i18n/locales/nl/common.json +++ b/webview-ui/src/i18n/locales/nl/common.json @@ -57,19 +57,26 @@ }, "time_ago": { "just_now": "zojuist", - "seconds_ago": "{{count}} seconden geleden", + "seconds_ago_one": "{{count}} seconde geleden", + "seconds_ago_other": "{{count}} seconden geleden", "minute_ago": "een minuut geleden", - "minutes_ago": "{{count}} minuten geleden", + "minutes_ago_one": "{{count}} minuut geleden", + "minutes_ago_other": "{{count}} minuten geleden", "hour_ago": "een uur geleden", - "hours_ago": "{{count}} uur geleden", + "hours_ago_one": "{{count}} uur geleden", + "hours_ago_other": "{{count}} uur geleden", "day_ago": "een dag geleden", - "days_ago": "{{count}} dagen geleden", + "days_ago_one": "{{count}} dag geleden", + "days_ago_other": "{{count}} dagen geleden", "week_ago": "een week geleden", - "weeks_ago": "{{count}} weken geleden", + "weeks_ago_one": "{{count}} week geleden", + "weeks_ago_other": "{{count}} weken geleden", "month_ago": "een maand geleden", - "months_ago": "{{count}} maanden geleden", + "months_ago_one": "{{count}} maand geleden", + "months_ago_other": "{{count}} maanden geleden", "year_ago": "een jaar geleden", - "years_ago": "{{count}} jaar geleden" + "years_ago_one": "{{count}} jaar geleden", + "years_ago_other": "{{count}} jaar geleden" }, "errors": { "wait_checkpoint_long_time": "Je hebt {{timeout}} seconden gewacht op de initialisatie van de checkpoint. Als je deze functie niet nodig hebt, schakel hem dan uit in de checkpoint-instellingen.", diff --git a/webview-ui/src/i18n/locales/nl/history.json b/webview-ui/src/i18n/locales/nl/history.json index 2a72b0bfe8..2c70f69ff6 100644 --- a/webview-ui/src/i18n/locales/nl/history.json +++ b/webview-ui/src/i18n/locales/nl/history.json @@ -26,9 +26,11 @@ "clearSelection": "Selectie wissen", "deleteSelected": "Geselecteerde verwijderen", "deleteTasks": "Taken verwijderen", - "confirmDeleteTasks": "Weet je zeker dat je {{count}} taken wilt verwijderen?", + "confirmDeleteTasks_one": "Weet je zeker dat je {{count}} taak wilt verwijderen?", + "confirmDeleteTasks_other": "Weet je zeker dat je {{count}} taken wilt verwijderen?", "deleteTasksWarning": "Verwijderde taken kunnen niet worden hersteld. Zorg ervoor dat je wilt doorgaan.", - "deleteItems": "Verwijder {{count}} items", + "deleteItems_one": "Verwijder {{count}} item", + "deleteItems_other": "Verwijder {{count}} items", "workspace": { "prefix": "Werkruimte:", "current": "Huidig", @@ -46,7 +48,8 @@ "subtasks_one": "{{count}} subtaak", "subtasks_other": "{{count}} subtaken", "subtaskTag": "Subtaak", - "deleteWithSubtasks": "Dit zal ook {{count}} subtaak(en) verwijderen. Weet je het zeker?", + "deleteWithSubtasks_one": "Dit zal ook {{count}} subtaak verwijderen. Weet je het zeker?", + "deleteWithSubtasks_other": "Dit zal ook {{count}} subtaken verwijderen. Weet je het zeker?", "expandSubtasks": "Subtaken uitvouwen", "collapseSubtasks": "Subtaken samenvouwen", "delegatedTag": "Wacht op subtaak", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 9185cd1ba8..76c0880328 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -951,7 +951,8 @@ "useAzure": "Azure gebruiken", "azureApiVersion": "Azure API-versie instellen", "gemini": { - "freeRequests": "* Gratis tot {{count}} verzoeken per minuut. Daarna is de prijs afhankelijk van de promptgrootte.", + "freeRequests_one": "* Gratis tot {{count}} verzoek per minuut. Daarna is de prijs afhankelijk van de promptgrootte.", + "freeRequests_other": "* Gratis tot {{count}} verzoeken per minuut. Daarna is de prijs afhankelijk van de promptgrootte.", "pricingDetails": "Zie prijsdetails voor meer info.", "billingEstimate": "* Facturering is een schatting - de exacte kosten hangen af van de promptgrootte." } diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index e4b536b4c8..52d73ccc77 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -20,7 +20,10 @@ "unpin": "Odepnij", "pin": "Przypnij", "fileChangesInConversation": { - "header": "{{count}} plik(ów) zmienionych w tej rozmowie" + "header_one": "{{count}} plik zmieniony w tej rozmowie", + "header_few": "{{count}} pliki zmienione w tej rozmowie", + "header_many": "{{count}} plików zmienionych w tej rozmowie", + "header_other": "{{count}} pliku zmienionego w tej rozmowie" }, "tokenProgress": { "availableSpace": "Dostępne miejsce: {{amount}} tokenów", @@ -286,9 +289,11 @@ "description": "Wykonuj te działania bez pytania o zgodę. Włącz tę opcję tylko dla działań, którym w pełni ufasz.", "triggerLabelOff": "Automatyczne zatwierdzanie wyłączone", "triggerLabelOffShort": "Wyłączone", - "triggerLabel_zero": "0 automatycznie zatwierdzone", - "triggerLabel_one": "1 automatycznie zatwierdzony", - "triggerLabel_other": "{{count}} automatycznie zatwierdzonych", + "triggerLabel_zero": "0 automatycznie zatwierdzonych", + "triggerLabel_one": "{{count}} automatycznie zatwierdzony", + "triggerLabel_few": "{{count}} automatycznie zatwierdzone", + "triggerLabel_many": "{{count}} automatycznie zatwierdzonych", + "triggerLabel_other": "{{count}} automatycznie zatwierdzonego", "triggerLabelAll": "BRRR" }, "reasoning": { @@ -305,8 +310,10 @@ "truncation": { "title": "Kontekst obcięty", "inProgress": "Obcinanie kontekstu...", - "messagesRemoved": "{{count}} wiadomość usunięta", - "messagesRemoved_other": "{{count}} wiadomości usunięte", + "messagesRemoved_one": "Usunięto {{count}} wiadomość", + "messagesRemoved_few": "Usunięto {{count}} wiadomości", + "messagesRemoved_many": "Usunięto {{count}} wiadomości", + "messagesRemoved_other": "Usunięto {{count}} wiadomości", "description": "Starsze wiadomości zostały usunięte z konwersacji, aby pozostać w granicach okna kontekstu. To szybsze, ale mniej zachowujące kontekst podejście w porównaniu z kondensacją." } }, @@ -349,7 +356,10 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Osiągnięto limit automatycznie zatwierdzonych żądań", - "description": "Zoo osiągnął automatycznie zatwierdzony limit {{count}} żądania/żądań API. Czy chcesz zresetować licznik i kontynuować zadanie?", + "description_one": "Zoo osiągnął automatycznie zatwierdzony limit {{count}} żądania API. Czy chcesz zresetować licznik i kontynuować zadanie?", + "description_few": "Zoo osiągnął automatycznie zatwierdzony limit {{count}} żądań API. Czy chcesz zresetować licznik i kontynuować zadanie?", + "description_many": "Zoo osiągnął automatycznie zatwierdzony limit {{count}} żądań API. Czy chcesz zresetować licznik i kontynuować zadanie?", + "description_other": "Zoo osiągnął automatycznie zatwierdzony limit {{count}} żądania API. Czy chcesz zresetować licznik i kontynuować zadanie?", "button": "Zresetuj i kontynuuj" }, "autoApprovedCostLimitReached": { @@ -361,8 +371,10 @@ "codebaseSearch": { "wantsToSearch": "Zoo chce przeszukać bazę kodu w poszukiwaniu {{query}}", "wantsToSearchWithPath": "Zoo chce przeszukać bazę kodu w poszukiwaniu {{query}} w {{path}}", - "didSearch_one": "Znaleziono 1 wynik", - "didSearch_other": "Znaleziono {{count}} wyników", + "didSearch_one": "Znaleziono {{count}} wynik", + "didSearch_few": "Znaleziono {{count}} wyniki", + "didSearch_many": "Znaleziono {{count}} wyników", + "didSearch_other": "Znaleziono {{count}} wyniku", "resultTooltip": "Wynik podobieństwa: {{score}} (kliknij, aby otworzyć plik)" }, "read-batch": { @@ -433,9 +445,13 @@ "tooManyTools": { "title": "Włączono zbyt wiele narzędzi", "toolsPart_one": "{{count}} narzędzie", - "toolsPart_other": "{{count}} narzędzi", + "toolsPart_few": "{{count}} narzędzia", + "toolsPart_many": "{{count}} narzędzi", + "toolsPart_other": "{{count}} narzędzia", "serversPart_one": "{{count}} serwer MCP", - "serversPart_other": "{{count}} serwerów MCP", + "serversPart_few": "{{count}} serwery MCP", + "serversPart_many": "{{count}} serwerów MCP", + "serversPart_other": "{{count}} serwera MCP", "messageTemplate": "Masz {{tools}} włączonych przez {{servers}}. Taka duża liczba może zamieszać model i prowadzić do błędów. Staraj się, aby była poniżej {{threshold}}.", "openMcpSettings": "Otwórz ustawienia MCP" }, diff --git a/webview-ui/src/i18n/locales/pl/common.json b/webview-ui/src/i18n/locales/pl/common.json index 5dc55d2ffb..df63ca9368 100644 --- a/webview-ui/src/i18n/locales/pl/common.json +++ b/webview-ui/src/i18n/locales/pl/common.json @@ -57,19 +57,40 @@ }, "time_ago": { "just_now": "przed chwilą", - "seconds_ago": "{{count}} sekund temu", + "seconds_ago_one": "{{count}} sekundę temu", + "seconds_ago_few": "{{count}} sekundy temu", + "seconds_ago_many": "{{count}} sekund temu", + "seconds_ago_other": "{{count}} sekundy temu", "minute_ago": "minutę temu", - "minutes_ago": "{{count}} minut temu", + "minutes_ago_one": "{{count}} minutę temu", + "minutes_ago_few": "{{count}} minuty temu", + "minutes_ago_many": "{{count}} minut temu", + "minutes_ago_other": "{{count}} minuty temu", "hour_ago": "godzinę temu", - "hours_ago": "{{count}} godzin temu", + "hours_ago_one": "{{count}} godzinę temu", + "hours_ago_few": "{{count}} godziny temu", + "hours_ago_many": "{{count}} godzin temu", + "hours_ago_other": "{{count}} godziny temu", "day_ago": "dzień temu", - "days_ago": "{{count}} dni temu", + "days_ago_one": "{{count}} dzień temu", + "days_ago_few": "{{count}} dni temu", + "days_ago_many": "{{count}} dni temu", + "days_ago_other": "{{count}} dnia temu", "week_ago": "tydzień temu", - "weeks_ago": "{{count}} tygodni temu", + "weeks_ago_one": "{{count}} tydzień temu", + "weeks_ago_few": "{{count}} tygodnie temu", + "weeks_ago_many": "{{count}} tygodni temu", + "weeks_ago_other": "{{count}} tygodnia temu", "month_ago": "miesiąc temu", - "months_ago": "{{count}} miesięcy temu", + "months_ago_one": "{{count}} miesiąc temu", + "months_ago_few": "{{count}} miesiące temu", + "months_ago_many": "{{count}} miesięcy temu", + "months_ago_other": "{{count}} miesiąca temu", "year_ago": "rok temu", - "years_ago": "{{count}} lat temu" + "years_ago_one": "{{count}} rok temu", + "years_ago_few": "{{count}} lata temu", + "years_ago_many": "{{count}} lat temu", + "years_ago_other": "{{count}} roku temu" }, "errors": { "wait_checkpoint_long_time": "Czekałeś {{timeout}} sekund na inicjalizację punktu kontrolnego. Jeśli nie potrzebujesz tej funkcji, wyłącz ją w ustawieniach punktu kontrolnego.", diff --git a/webview-ui/src/i18n/locales/pl/history.json b/webview-ui/src/i18n/locales/pl/history.json index 229f28030f..8a2fe7615a 100644 --- a/webview-ui/src/i18n/locales/pl/history.json +++ b/webview-ui/src/i18n/locales/pl/history.json @@ -26,9 +26,15 @@ "clearSelection": "Wyczyść wybór", "deleteSelected": "Usuń wybrane", "deleteTasks": "Usuń zadania", - "confirmDeleteTasks": "Czy na pewno chcesz usunąć {{count}} zadań?", + "confirmDeleteTasks_one": "Czy na pewno chcesz usunąć {{count}} zadanie?", + "confirmDeleteTasks_few": "Czy na pewno chcesz usunąć {{count}} zadania?", + "confirmDeleteTasks_many": "Czy na pewno chcesz usunąć {{count}} zadań?", + "confirmDeleteTasks_other": "Czy na pewno chcesz usunąć {{count}} zadania?", "deleteTasksWarning": "Usuniętych zadań nie można przywrócić. Upewnij się, że chcesz kontynuować.", - "deleteItems": "Usuń {{count}} elementów", + "deleteItems_one": "Usuń {{count}} element", + "deleteItems_few": "Usuń {{count}} elementy", + "deleteItems_many": "Usuń {{count}} elementów", + "deleteItems_other": "Usuń {{count}} elementu", "workspace": { "prefix": "Obszar roboczy:", "current": "Bieżący", @@ -44,9 +50,14 @@ }, "viewAllHistory": "Zobacz wszystko", "subtasks_one": "{{count}} podzadanie", - "subtasks_other": "{{count}} podzadań", + "subtasks_few": "{{count}} podzadania", + "subtasks_many": "{{count}} podzadań", + "subtasks_other": "{{count}} podzadania", "subtaskTag": "Podzadanie", - "deleteWithSubtasks": "Spowoduje to usunięcie {{count}} podzadania(ń). Jesteś pewny?", + "deleteWithSubtasks_one": "Spowoduje to usunięcie {{count}} podzadania. Jesteś pewny?", + "deleteWithSubtasks_few": "Spowoduje to usunięcie {{count}} podzadań. Jesteś pewny?", + "deleteWithSubtasks_many": "Spowoduje to usunięcie {{count}} podzadań. Jesteś pewny?", + "deleteWithSubtasks_other": "Spowoduje to usunięcie {{count}} podzadania. Jesteś pewny?", "expandSubtasks": "Rozwiń podzadania", "collapseSubtasks": "Zwiń podzadania", "delegatedTag": "Oczekuje na podzadanie", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index a3dee217d0..fd09d548c5 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -76,8 +76,10 @@ "summaryFailedNoFiles": "Import zatrzymał się przed skopiowaniem jakichkolwiek plików.", "summaryCopied": "Skopiowano {{copied}} z {{total}} plików", "detailFailed": "Rozpocznij nową próbę importu, aby spróbować ponownie.", - "detailTasksImported_one": "Zaimportowano {{count}} z {{total}} historię zadań.", - "detailTasksImported_other": "Zaimportowano {{count}} z {{total}} historii zadań.", + "detailTasksImported_one": "Zaimportowano historii zadań: {{count}} z {{total}}.", + "detailTasksImported_few": "Zaimportowano historii zadań: {{count}} z {{total}}.", + "detailTasksImported_many": "Zaimportowano historii zadań: {{count}} z {{total}}.", + "detailTasksImported_other": "Zaimportowano historii zadań: {{count}} z {{total}}.", "detailPreparing": "Przygotowywanie importu historii Roo Code.", "progressAriaLabel": "Postęp importu historii Roo Code" } @@ -951,7 +953,10 @@ "useAzure": "Użyj Azure", "azureApiVersion": "Ustaw wersję API Azure", "gemini": { - "freeRequests": "* Darmowe do {{count}} zapytań na minutę. Po tym, rozliczanie zależy od rozmiaru podpowiedzi.", + "freeRequests_one": "* Darmowe do {{count}} zapytania na minutę. Po tym, rozliczanie zależy od rozmiaru podpowiedzi.", + "freeRequests_few": "* Darmowe do {{count}} zapytań na minutę. Po tym, rozliczanie zależy od rozmiaru podpowiedzi.", + "freeRequests_many": "* Darmowe do {{count}} zapytań na minutę. Po tym, rozliczanie zależy od rozmiaru podpowiedzi.", + "freeRequests_other": "* Darmowe do {{count}} zapytania na minutę. Po tym, rozliczanie zależy od rozmiaru podpowiedzi.", "pricingDetails": "Więcej informacji znajdziesz w szczegółach cennika.", "billingEstimate": "* Rozliczenie jest szacunkowe - dokładny koszt zależy od rozmiaru podpowiedzi." } diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index fdcfa99c7d..52391043ed 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -20,7 +20,9 @@ "unpin": "Desfixar", "pin": "Fixar", "fileChangesInConversation": { - "header": "{{count}} arquivo(s) alterado(s) nesta conversa" + "header_one": "{{count}} arquivo alterado nesta conversa", + "header_many": "{{count}} arquivos alterados nesta conversa", + "header_other": "{{count}} arquivos alterados nesta conversa" }, "tokenProgress": { "availableSpace": "Espaço disponível: {{amount}} tokens", @@ -287,7 +289,8 @@ "triggerLabelOff": "Aprovação automática desativada", "triggerLabelOffShort": "Desativada", "triggerLabel_zero": "0 aprovados automaticamente", - "triggerLabel_one": "1 aprovado automaticamente", + "triggerLabel_one": "{{count}} aprovado automaticamente", + "triggerLabel_many": "{{count}} aprovados automaticamente", "triggerLabel_other": "{{count}} aprovados automaticamente", "triggerLabelAll": "BRRR" }, @@ -305,7 +308,8 @@ "truncation": { "title": "Contexto truncado", "inProgress": "Truncando contexto...", - "messagesRemoved": "{{count}} mensagem removida", + "messagesRemoved_one": "{{count}} mensagem removida", + "messagesRemoved_many": "{{count}} mensagens removidas", "messagesRemoved_other": "{{count}} mensagens removidas", "description": "Mensagens mais antigas foram removidas da conversa para permanecer dentro do limite da janela de contexto. Esta é uma abordagem rápida, mas menos preservadora de contexto em comparação com a condensação." } @@ -349,7 +353,9 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Limite de Solicitações Auto-aprovadas Atingido", - "description": "Zoo atingiu o limite auto-aprovado de {{count}} solicitação(ões) de API. Deseja redefinir a contagem e prosseguir com a tarefa?", + "description_one": "Zoo atingiu o limite auto-aprovado de {{count}} solicitação de API. Deseja redefinir a contagem e prosseguir com a tarefa?", + "description_many": "Zoo atingiu o limite auto-aprovado de {{count}} solicitações de API. Deseja redefinir a contagem e prosseguir com a tarefa?", + "description_other": "Zoo atingiu o limite auto-aprovado de {{count}} solicitações de API. Deseja redefinir a contagem e prosseguir com a tarefa?", "button": "Redefinir e Continuar" }, "autoApprovedCostLimitReached": { @@ -361,7 +367,8 @@ "codebaseSearch": { "wantsToSearch": "Zoo quer pesquisar na base de código por {{query}}", "wantsToSearchWithPath": "Zoo quer pesquisar na base de código por {{query}} em {{path}}", - "didSearch_one": "Encontrado 1 resultado", + "didSearch_one": "Encontrado {{count}} resultado", + "didSearch_many": "Encontrados {{count}} resultados", "didSearch_other": "Encontrados {{count}} resultados", "resultTooltip": "Pontuação de similaridade: {{score}} (clique para abrir o arquivo)" }, @@ -433,8 +440,10 @@ "tooManyTools": { "title": "Muitas ferramentas habilitadas", "toolsPart_one": "{{count}} ferramenta", + "toolsPart_many": "{{count}} ferramentas", "toolsPart_other": "{{count}} ferramentas", "serversPart_one": "{{count}} servidor MCP", + "serversPart_many": "{{count}} servidores MCP", "serversPart_other": "{{count}} servidores MCP", "messageTemplate": "Você tem {{tools}} habilitadas via {{servers}}. Um número tão alto pode confundir o modelo e levar a erros. Tente mantê-lo abaixo de {{threshold}}.", "openMcpSettings": "Abrir Configurações MCP" diff --git a/webview-ui/src/i18n/locales/pt-BR/common.json b/webview-ui/src/i18n/locales/pt-BR/common.json index 16791fd00c..679301340b 100644 --- a/webview-ui/src/i18n/locales/pt-BR/common.json +++ b/webview-ui/src/i18n/locales/pt-BR/common.json @@ -57,19 +57,33 @@ }, "time_ago": { "just_now": "agora mesmo", - "seconds_ago": "há {{count}} segundos", + "seconds_ago_one": "há {{count}} segundo", + "seconds_ago_many": "há {{count}} segundos", + "seconds_ago_other": "há {{count}} segundos", "minute_ago": "há um minuto", - "minutes_ago": "há {{count}} minutos", + "minutes_ago_one": "há {{count}} minuto", + "minutes_ago_many": "há {{count}} minutos", + "minutes_ago_other": "há {{count}} minutos", "hour_ago": "há uma hora", - "hours_ago": "há {{count}} horas", + "hours_ago_one": "há {{count}} hora", + "hours_ago_many": "há {{count}} horas", + "hours_ago_other": "há {{count}} horas", "day_ago": "há um dia", - "days_ago": "há {{count}} dias", + "days_ago_one": "há {{count}} dia", + "days_ago_many": "há {{count}} dias", + "days_ago_other": "há {{count}} dias", "week_ago": "há uma semana", - "weeks_ago": "há {{count}} semanas", + "weeks_ago_one": "há {{count}} semana", + "weeks_ago_many": "há {{count}} semanas", + "weeks_ago_other": "há {{count}} semanas", "month_ago": "há um mês", - "months_ago": "há {{count}} meses", + "months_ago_one": "há {{count}} mês", + "months_ago_many": "há {{count}} meses", + "months_ago_other": "há {{count}} meses", "year_ago": "há um ano", - "years_ago": "há {{count}} anos" + "years_ago_one": "há {{count}} ano", + "years_ago_many": "há {{count}} anos", + "years_ago_other": "há {{count}} anos" }, "errors": { "wait_checkpoint_long_time": "Você esperou {{timeout}} segundos para inicializar o checkpoint. Se não precisa dessa função, desative nas configurações do checkpoint.", diff --git a/webview-ui/src/i18n/locales/pt-BR/history.json b/webview-ui/src/i18n/locales/pt-BR/history.json index c9b2848ee6..124ee5ff60 100644 --- a/webview-ui/src/i18n/locales/pt-BR/history.json +++ b/webview-ui/src/i18n/locales/pt-BR/history.json @@ -26,9 +26,13 @@ "clearSelection": "Limpar seleção", "deleteSelected": "Excluir selecionados", "deleteTasks": "Excluir tarefas", - "confirmDeleteTasks": "Tem certeza que deseja excluir {{count}} tarefas?", + "confirmDeleteTasks_one": "Tem certeza que deseja excluir {{count}} tarefa?", + "confirmDeleteTasks_many": "Tem certeza que deseja excluir {{count}} tarefas?", + "confirmDeleteTasks_other": "Tem certeza que deseja excluir {{count}} tarefas?", "deleteTasksWarning": "As tarefas excluídas não podem ser recuperadas. Por favor, certifique-se de que deseja prosseguir.", - "deleteItems": "Excluir {{count}} itens", + "deleteItems_one": "Excluir {{count}} item", + "deleteItems_many": "Excluir {{count}} itens", + "deleteItems_other": "Excluir {{count}} itens", "workspace": { "prefix": "Espaço de trabalho:", "current": "Atual", @@ -44,9 +48,12 @@ }, "viewAllHistory": "Ver tudo", "subtasks_one": "{{count}} subtarefa", + "subtasks_many": "{{count}} subtarefas", "subtasks_other": "{{count}} subtarefas", "subtaskTag": "Subtarefa", - "deleteWithSubtasks": "Isso também excluirá {{count}} subtarefa(s). Tem certeza?", + "deleteWithSubtasks_one": "Isso também excluirá {{count}} subtarefa. Tem certeza?", + "deleteWithSubtasks_many": "Isso também excluirá {{count}} subtarefas. Tem certeza?", + "deleteWithSubtasks_other": "Isso também excluirá {{count}} subtarefas. Tem certeza?", "expandSubtasks": "Expandir subtarefas", "collapseSubtasks": "Recolher subtarefas", "delegatedTag": "Aguardando subtarefa", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index c5e103eec0..47256c7d6b 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -77,6 +77,7 @@ "summaryCopied": "{{copied}} de {{total}} arquivos copiados", "detailFailed": "Inicie uma nova tentativa de importação para tentar novamente.", "detailTasksImported_one": "{{count}} de {{total}} histórico de tarefa importado.", + "detailTasksImported_many": "{{count}} de {{total}} históricos de tarefas importados.", "detailTasksImported_other": "{{count}} de {{total}} históricos de tarefas importados.", "detailPreparing": "Preparando a importação do histórico do Roo Code.", "progressAriaLabel": "Progresso da importação do histórico do Roo Code" @@ -951,7 +952,9 @@ "useAzure": "Usar Azure", "azureApiVersion": "Definir versão da API Azure", "gemini": { - "freeRequests": "* Gratuito até {{count}} requisições por minuto. Depois disso, a cobrança depende do tamanho do prompt.", + "freeRequests_one": "* Gratuito até {{count}} requisição por minuto. Depois disso, a cobrança depende do tamanho do prompt.", + "freeRequests_many": "* Gratuito até {{count}} requisições por minuto. Depois disso, a cobrança depende do tamanho do prompt.", + "freeRequests_other": "* Gratuito até {{count}} requisições por minuto. Depois disso, a cobrança depende do tamanho do prompt.", "pricingDetails": "Para mais informações, consulte os detalhes de preços.", "billingEstimate": "* A cobrança é uma estimativa - o custo exato depende do tamanho do prompt." } diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index c2017d1789..3c7c59860f 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -20,7 +20,10 @@ "unpin": "Открепить", "pin": "Закрепить", "fileChangesInConversation": { - "header": "{{count}} файл(ов) изменено в этом разговоре" + "header_one": "{{count}} файл изменен в этом разговоре", + "header_few": "{{count}} файла изменено в этом разговоре", + "header_many": "{{count}} файлов изменено в этом разговоре", + "header_other": "{{count}} файла изменено в этом разговоре" }, "retry": { "title": "Повторить", @@ -288,7 +291,9 @@ "triggerLabelOff": "Авто-утверждение выкл", "triggerLabelOffShort": "Выкл", "triggerLabel_zero": "0 авто-утвержденных", - "triggerLabel_one": "1 авто-утвержден", + "triggerLabel_one": "{{count}} авто-утвержденное", + "triggerLabel_few": "{{count}} авто-утвержденных", + "triggerLabel_many": "{{count}} авто-утвержденных", "triggerLabel_other": "{{count}} авто-утвержденных", "triggerLabelAll": "BRRR" }, @@ -316,8 +321,10 @@ "truncation": { "title": "Контекст усечён", "inProgress": "Усечение контекста...", - "messagesRemoved": "{{count}} сообщение удалено", - "messagesRemoved_other": "{{count}} сообщений удалено", + "messagesRemoved_one": "{{count}} сообщение удалено", + "messagesRemoved_few": "{{count}} сообщения удалено", + "messagesRemoved_many": "{{count}} сообщений удалено", + "messagesRemoved_other": "{{count}} сообщения удалено", "description": "Более старые сообщения были удалены из разговора, чтобы остаться в пределах контекстного окна. Это быстрый, но менее сохраняющий контекст подход по сравнению со сжатием." } }, @@ -350,7 +357,10 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Достигнут лимит автоматически одобренных запросов", - "description": "Zoo достиг автоматически одобренного лимита в {{count}} API-запрос(ов). Хотите сбросить счетчик и продолжить задачу?", + "description_one": "Zoo достиг автоматически одобренного лимита в {{count}} API-запрос. Хотите сбросить счетчик и продолжить задачу?", + "description_few": "Zoo достиг автоматически одобренного лимита в {{count}} API-запроса. Хотите сбросить счетчик и продолжить задачу?", + "description_many": "Zoo достиг автоматически одобренного лимита в {{count}} API-запросов. Хотите сбросить счетчик и продолжить задачу?", + "description_other": "Zoo достиг автоматически одобренного лимита в {{count}} API-запроса. Хотите сбросить счетчик и продолжить задачу?", "button": "Сбросить и продолжить" }, "autoApprovedCostLimitReached": { @@ -362,8 +372,10 @@ "codebaseSearch": { "wantsToSearch": "Zoo хочет выполнить поиск в кодовой базе по {{query}}", "wantsToSearchWithPath": "Zoo хочет выполнить поиск в кодовой базе по {{query}} в {{path}}", - "didSearch_one": "Найден 1 результат", - "didSearch_other": "Найдено {{count}} результатов", + "didSearch_one": "Найден {{count}} результат", + "didSearch_few": "Найдено {{count}} результата", + "didSearch_many": "Найдено {{count}} результатов", + "didSearch_other": "Найдено {{count}} результата", "resultTooltip": "Оценка схожести: {{score}} (нажмите, чтобы открыть файл)" }, "read-batch": { @@ -434,9 +446,13 @@ "tooManyTools": { "title": "Включено слишком много инструментов", "toolsPart_one": "{{count}} инструмент", - "toolsPart_other": "{{count}} инструментов", + "toolsPart_few": "{{count}} инструмента", + "toolsPart_many": "{{count}} инструментов", + "toolsPart_other": "{{count}} инструмента", "serversPart_one": "{{count}} сервер MCP", - "serversPart_other": "{{count}} серверов MCP", + "serversPart_few": "{{count}} сервера MCP", + "serversPart_many": "{{count}} серверов MCP", + "serversPart_other": "{{count}} сервера MCP", "messageTemplate": "У тебя включено {{tools}} через {{servers}}. Такое большое количество может сбить модель с толку и привести к ошибкам. Постарайся держать это ниже {{threshold}}.", "openMcpSettings": "Открыть настройки MCP" }, diff --git a/webview-ui/src/i18n/locales/ru/common.json b/webview-ui/src/i18n/locales/ru/common.json index dbac914ad5..d03708d290 100644 --- a/webview-ui/src/i18n/locales/ru/common.json +++ b/webview-ui/src/i18n/locales/ru/common.json @@ -57,19 +57,40 @@ }, "time_ago": { "just_now": "только что", - "seconds_ago": "{{count}} секунд назад", + "seconds_ago_one": "{{count}} секунду назад", + "seconds_ago_few": "{{count}} секунды назад", + "seconds_ago_many": "{{count}} секунд назад", + "seconds_ago_other": "{{count}} секунды назад", "minute_ago": "минуту назад", - "minutes_ago": "{{count}} минут назад", + "minutes_ago_one": "{{count}} минуту назад", + "minutes_ago_few": "{{count}} минуты назад", + "minutes_ago_many": "{{count}} минут назад", + "minutes_ago_other": "{{count}} минуты назад", "hour_ago": "час назад", - "hours_ago": "{{count}} часов назад", + "hours_ago_one": "{{count}} час назад", + "hours_ago_few": "{{count}} часа назад", + "hours_ago_many": "{{count}} часов назад", + "hours_ago_other": "{{count}} часа назад", "day_ago": "день назад", - "days_ago": "{{count}} дней назад", + "days_ago_one": "{{count}} день назад", + "days_ago_few": "{{count}} дня назад", + "days_ago_many": "{{count}} дней назад", + "days_ago_other": "{{count}} дня назад", "week_ago": "неделю назад", - "weeks_ago": "{{count}} недель назад", + "weeks_ago_one": "{{count}} неделю назад", + "weeks_ago_few": "{{count}} недели назад", + "weeks_ago_many": "{{count}} недель назад", + "weeks_ago_other": "{{count}} недели назад", "month_ago": "месяц назад", - "months_ago": "{{count}} месяцев назад", + "months_ago_one": "{{count}} месяц назад", + "months_ago_few": "{{count}} месяца назад", + "months_ago_many": "{{count}} месяцев назад", + "months_ago_other": "{{count}} месяца назад", "year_ago": "год назад", - "years_ago": "{{count}} лет назад" + "years_ago_one": "{{count}} год назад", + "years_ago_few": "{{count}} года назад", + "years_ago_many": "{{count}} лет назад", + "years_ago_other": "{{count}} года назад" }, "errors": { "wait_checkpoint_long_time": "Ожидание инициализации контрольной точки заняло {{timeout}} секунд. Если тебе не нужна эта функция, отключи её в настройках контрольных точек.", diff --git a/webview-ui/src/i18n/locales/ru/history.json b/webview-ui/src/i18n/locales/ru/history.json index 482b8453ad..be05809520 100644 --- a/webview-ui/src/i18n/locales/ru/history.json +++ b/webview-ui/src/i18n/locales/ru/history.json @@ -26,9 +26,15 @@ "clearSelection": "Очистить выбор", "deleteSelected": "Удалить выбранные", "deleteTasks": "Удалить задачи", - "confirmDeleteTasks": "Вы уверены, что хотите удалить {{count}} задач?", + "confirmDeleteTasks_one": "Вы уверены, что хотите удалить {{count}} задачу?", + "confirmDeleteTasks_few": "Вы уверены, что хотите удалить {{count}} задачи?", + "confirmDeleteTasks_many": "Вы уверены, что хотите удалить {{count}} задач?", + "confirmDeleteTasks_other": "Вы уверены, что хотите удалить {{count}} задачи?", "deleteTasksWarning": "Удалённые задачи не могут быть восстановлены. Пожалуйста, убедитесь, что хотите продолжить.", - "deleteItems": "Удалить {{count}} элементов", + "deleteItems_one": "Удалить {{count}} элемент", + "deleteItems_few": "Удалить {{count}} элемента", + "deleteItems_many": "Удалить {{count}} элементов", + "deleteItems_other": "Удалить {{count}} элемента", "workspace": { "prefix": "Рабочая область:", "current": "Текущая", @@ -44,9 +50,14 @@ }, "viewAllHistory": "Посмотреть все", "subtasks_one": "{{count}} подзадача", - "subtasks_other": "{{count}} подзадач", + "subtasks_few": "{{count}} подзадачи", + "subtasks_many": "{{count}} подзадач", + "subtasks_other": "{{count}} подзадачи", "subtaskTag": "Подзадача", - "deleteWithSubtasks": "Это также удалит {{count}} подзадачу(и). Вы уверены?", + "deleteWithSubtasks_one": "Это также удалит {{count}} подзадачу. Вы уверены?", + "deleteWithSubtasks_few": "Это также удалит {{count}} подзадачи. Вы уверены?", + "deleteWithSubtasks_many": "Это также удалит {{count}} подзадач. Вы уверены?", + "deleteWithSubtasks_other": "Это также удалит {{count}} подзадачи. Вы уверены?", "expandSubtasks": "Развернуть подзадачи", "collapseSubtasks": "Свернуть подзадачи", "delegatedTag": "Ожидание подзадачи", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 8c944f3797..7bd2cd6c3e 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -76,8 +76,10 @@ "summaryFailedNoFiles": "Импорт остановился до копирования каких-либо файлов.", "summaryCopied": "Скопировано {{copied}} из {{total}} файлов", "detailFailed": "Начни новую попытку импорта, чтобы повторить.", - "detailTasksImported_one": "Импортирована {{count}} из {{total}} история задач.", - "detailTasksImported_other": "Импортировано {{count}} из {{total}} историй задач.", + "detailTasksImported_one": "Импортировано историй задач: {{count}} из {{total}}.", + "detailTasksImported_few": "Импортировано историй задач: {{count}} из {{total}}.", + "detailTasksImported_many": "Импортировано историй задач: {{count}} из {{total}}.", + "detailTasksImported_other": "Импортировано историй задач: {{count}} из {{total}}.", "detailPreparing": "Подготовка импорта истории Roo Code.", "progressAriaLabel": "Ход импорта истории Roo Code" } @@ -951,7 +953,10 @@ "useAzure": "Использовать Azure", "azureApiVersion": "Установить версию API Azure", "gemini": { - "freeRequests": "* Бесплатно до {{count}} запросов в минуту. Далее тарификация зависит от размера подсказки.", + "freeRequests_one": "* Бесплатно до {{count}} запроса в минуту. Далее тарификация зависит от размера подсказки.", + "freeRequests_few": "* Бесплатно до {{count}} запросов в минуту. Далее тарификация зависит от размера подсказки.", + "freeRequests_many": "* Бесплатно до {{count}} запросов в минуту. Далее тарификация зависит от размера подсказки.", + "freeRequests_other": "* Бесплатно до {{count}} запроса в минуту. Далее тарификация зависит от размера подсказки.", "pricingDetails": "Подробнее о ценах.", "billingEstimate": "* Счёт — приблизительный, точная стоимость зависит от размера подсказки." } diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 73b96161bf..f1abda010e 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -20,7 +20,8 @@ "unpin": "Sabitlemeyi iptal et", "pin": "Sabitle", "fileChangesInConversation": { - "header": "Bu sohbette {{count}} dosya değiştirildi" + "header_one": "Bu sohbette {{count}} dosya değiştirildi", + "header_other": "Bu sohbette {{count}} dosya değiştirildi" }, "tokenProgress": { "availableSpace": "Kullanılabilir alan: {{amount}} token", @@ -288,7 +289,7 @@ "triggerLabelOff": "Otomatik onay kapalı", "triggerLabelOffShort": "Kapalı", "triggerLabel_zero": "0 otomatik onaylandı", - "triggerLabel_one": "1 otomatik onaylandı", + "triggerLabel_one": "{{count}} otomatik onaylandı", "triggerLabel_other": "{{count}} otomatik onaylandı", "triggerLabelAll": "BRRR" }, @@ -306,7 +307,7 @@ "truncation": { "title": "Bağlam Kısaltıldı", "inProgress": "Bağlam kısaltılıyor...", - "messagesRemoved": "{{count}} mesaj kaldırıldı", + "messagesRemoved_one": "{{count}} mesaj kaldırıldı", "messagesRemoved_other": "{{count}} mesaj kaldırıldı", "description": "Bağlam penceresi sınırında kalmak için eski mesajlar konuşmadan kaldırıldı. Bu, yoğunlaştırmaya kıyasla hızlı ancak daha az bağlam koruyucu bir yaklaşımdır." } @@ -350,7 +351,8 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Otomatik Onaylanan İstek Limiti Aşıldı", - "description": "Zoo, {{count}} API isteği/istekleri için otomatik onaylanan limite ulaştı. Sayacı sıfırlamak ve göreve devam etmek istiyor musunuz?", + "description_one": "Zoo, {{count}} API isteği için otomatik onaylanan limite ulaştı. Sayacı sıfırlamak ve göreve devam etmek istiyor musunuz?", + "description_other": "Zoo, {{count}} API isteği için otomatik onaylanan limite ulaştı. Sayacı sıfırlamak ve göreve devam etmek istiyor musunuz?", "button": "Sıfırla ve Devam Et" }, "autoApprovedCostLimitReached": { @@ -362,7 +364,7 @@ "codebaseSearch": { "wantsToSearch": "Zoo kod tabanında {{query}} aramak istiyor", "wantsToSearchWithPath": "Zoo {{path}} içinde kod tabanında {{query}} aramak istiyor", - "didSearch_one": "1 sonuç bulundu", + "didSearch_one": "{{count}} sonuç bulundu", "didSearch_other": "{{count}} sonuç bulundu", "resultTooltip": "Benzerlik puanı: {{score}} (dosyayı açmak için tıklayın)" }, diff --git a/webview-ui/src/i18n/locales/tr/common.json b/webview-ui/src/i18n/locales/tr/common.json index b89728d2cb..0a7fb07217 100644 --- a/webview-ui/src/i18n/locales/tr/common.json +++ b/webview-ui/src/i18n/locales/tr/common.json @@ -57,19 +57,26 @@ }, "time_ago": { "just_now": "şimdi", - "seconds_ago": "{{count}} saniye önce", + "seconds_ago_one": "{{count}} saniye önce", + "seconds_ago_other": "{{count}} saniye önce", "minute_ago": "bir dakika önce", - "minutes_ago": "{{count}} dakika önce", + "minutes_ago_one": "{{count}} dakika önce", + "minutes_ago_other": "{{count}} dakika önce", "hour_ago": "bir saat önce", - "hours_ago": "{{count}} saat önce", + "hours_ago_one": "{{count}} saat önce", + "hours_ago_other": "{{count}} saat önce", "day_ago": "bir gün önce", - "days_ago": "{{count}} gün önce", + "days_ago_one": "{{count}} gün önce", + "days_ago_other": "{{count}} gün önce", "week_ago": "bir hafta önce", - "weeks_ago": "{{count}} hafta önce", + "weeks_ago_one": "{{count}} hafta önce", + "weeks_ago_other": "{{count}} hafta önce", "month_ago": "bir ay önce", - "months_ago": "{{count}} ay önce", + "months_ago_one": "{{count}} ay önce", + "months_ago_other": "{{count}} ay önce", "year_ago": "bir yıl önce", - "years_ago": "{{count}} yıl önce" + "years_ago_one": "{{count}} yıl önce", + "years_ago_other": "{{count}} yıl önce" }, "errors": { "wait_checkpoint_long_time": "{{timeout}} saniye boyunca kontrol noktası başlatılması beklendi. Bu özelliğe ihtiyacın yoksa kontrol noktası ayarlarından kapatabilirsin.", diff --git a/webview-ui/src/i18n/locales/tr/history.json b/webview-ui/src/i18n/locales/tr/history.json index 10b7e82362..4bdafc76e3 100644 --- a/webview-ui/src/i18n/locales/tr/history.json +++ b/webview-ui/src/i18n/locales/tr/history.json @@ -26,9 +26,11 @@ "clearSelection": "Seçimi Temizle", "deleteSelected": "Seçilenleri Sil", "deleteTasks": "Görevleri Sil", - "confirmDeleteTasks": "{{count}} görevi silmek istediğinizden emin misiniz?", + "confirmDeleteTasks_one": "{{count}} görevi silmek istediğinizden emin misiniz?", + "confirmDeleteTasks_other": "{{count}} görevi silmek istediğinizden emin misiniz?", "deleteTasksWarning": "Silinen görevler geri alınamaz. Lütfen devam etmek istediğinizden emin olun.", - "deleteItems": "{{count}} Öğeyi Sil", + "deleteItems_one": "{{count}} Öğeyi Sil", + "deleteItems_other": "{{count}} Öğeyi Sil", "workspace": { "prefix": "Çalışma Alanı:", "current": "Mevcut", @@ -46,7 +48,8 @@ "subtasks_one": "{{count}} alt görev", "subtasks_other": "{{count}} alt görev", "subtaskTag": "Alt görev", - "deleteWithSubtasks": "Bu, {{count}} alt görev(i) de silecektir. Emin misiniz?", + "deleteWithSubtasks_one": "Bu, {{count}} alt görevi de silecektir. Emin misiniz?", + "deleteWithSubtasks_other": "Bu, {{count}} alt görevi de silecektir. Emin misiniz?", "expandSubtasks": "Alt görevleri genişlet", "collapseSubtasks": "Alt görevleri daralt", "delegatedTag": "Alt görev bekleniyor", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 2872f7f9f3..3cc4b0f554 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -951,7 +951,8 @@ "useAzure": "Azure kullan", "azureApiVersion": "Azure API sürümünü ayarla", "gemini": { - "freeRequests": "* Dakikada {{count}} isteğe kadar ücretsiz. Bundan sonra, ücretlendirme istem boyutuna bağlıdır.", + "freeRequests_one": "* Dakikada {{count}} isteğe kadar ücretsiz. Bundan sonra, ücretlendirme istem boyutuna bağlıdır.", + "freeRequests_other": "* Dakikada {{count}} isteğe kadar ücretsiz. Bundan sonra, ücretlendirme istem boyutuna bağlıdır.", "pricingDetails": "Daha fazla bilgi için fiyatlandırma ayrıntılarına bakın.", "billingEstimate": "* Ücretlendirme bir tahmindir - kesin maliyet istem boyutuna bağlıdır." } diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index 40c5749f8b..2237ca1dbd 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -20,7 +20,7 @@ "unpin": "Bỏ ghim khỏi đầu", "pin": "Ghim lên đầu", "fileChangesInConversation": { - "header": "{{count}} tệp đã thay đổi trong cuộc hội thoại này" + "header_other": "{{count}} tệp đã thay đổi trong cuộc hội thoại này" }, "tokenProgress": { "availableSpace": "Không gian khả dụng: {{amount}} tokens", @@ -288,7 +288,6 @@ "triggerLabelOff": "Tự động phê duyệt tắt", "triggerLabelOffShort": "Tắt", "triggerLabel_zero": "0 được tự động phê duyệt", - "triggerLabel_one": "1 được tự động phê duyệt", "triggerLabel_other": "{{count}} được tự động phê duyệt", "triggerLabelAll": "BRRR" }, @@ -306,7 +305,6 @@ "truncation": { "title": "Ngữ cảnh đã cắt bớt", "inProgress": "Đang cắt bớt ngữ cảnh...", - "messagesRemoved": "{{count}} tin nhắn đã xóa", "messagesRemoved_other": "{{count}} tin nhắn đã xóa", "description": "Các tin nhắn cũ hơn đã bị xóa khỏi cuộc trò chuyện để giữ trong giới hạn cửa sổ ngữ cảnh. Đây là cách tiếp cận nhanh nhưng ít bảo toàn ngữ cảnh hơn so với cô đọng." } @@ -350,7 +348,7 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "Đã Đạt Giới Hạn Yêu Cầu Tự Động Phê Duyệt", - "description": "Zoo đã đạt đến giới hạn tự động phê duyệt là {{count}} yêu cầu API. Bạn có muốn đặt lại bộ đếm và tiếp tục nhiệm vụ không?", + "description_other": "Zoo đã đạt đến giới hạn tự động phê duyệt là {{count}} yêu cầu API. Bạn có muốn đặt lại bộ đếm và tiếp tục nhiệm vụ không?", "button": "Đặt lại và Tiếp tục" }, "autoApprovedCostLimitReached": { @@ -362,7 +360,6 @@ "codebaseSearch": { "wantsToSearch": "Zoo muốn tìm kiếm trong cơ sở mã cho {{query}}", "wantsToSearchWithPath": "Zoo muốn tìm kiếm trong cơ sở mã cho {{query}} trong {{path}}", - "didSearch_one": "Đã tìm thấy 1 kết quả", "didSearch_other": "Đã tìm thấy {{count}} kết quả", "resultTooltip": "Điểm tương tự: {{score}} (nhấp để mở tệp)" }, @@ -433,9 +430,7 @@ }, "tooManyTools": { "title": "Đã bật quá nhiều công cụ", - "toolsPart_one": "{{count}} công cụ", "toolsPart_other": "{{count}} công cụ", - "serversPart_one": "{{count}} máy chủ MCP", "serversPart_other": "{{count}} máy chủ MCP", "messageTemplate": "Bạn đã bật {{tools}} qua {{servers}}. Số lượng lớn như vậy có thể khiến mô hình bối rối và dẫn đến lỗi. Cố gắng giữ nó dưới {{threshold}}.", "openMcpSettings": "Mở cài đặt MCP" diff --git a/webview-ui/src/i18n/locales/vi/common.json b/webview-ui/src/i18n/locales/vi/common.json index 5bebfbcd05..ccae866d37 100644 --- a/webview-ui/src/i18n/locales/vi/common.json +++ b/webview-ui/src/i18n/locales/vi/common.json @@ -57,19 +57,19 @@ }, "time_ago": { "just_now": "vừa xong", - "seconds_ago": "{{count}} giây trước", + "seconds_ago_other": "{{count}} giây trước", "minute_ago": "một phút trước", - "minutes_ago": "{{count}} phút trước", + "minutes_ago_other": "{{count}} phút trước", "hour_ago": "một giờ trước", - "hours_ago": "{{count}} giờ trước", + "hours_ago_other": "{{count}} giờ trước", "day_ago": "một ngày trước", - "days_ago": "{{count}} ngày trước", + "days_ago_other": "{{count}} ngày trước", "week_ago": "một tuần trước", - "weeks_ago": "{{count}} tuần trước", + "weeks_ago_other": "{{count}} tuần trước", "month_ago": "một tháng trước", - "months_ago": "{{count}} tháng trước", + "months_ago_other": "{{count}} tháng trước", "year_ago": "một năm trước", - "years_ago": "{{count}} năm trước" + "years_ago_other": "{{count}} năm trước" }, "errors": { "wait_checkpoint_long_time": "Bạn đã chờ {{timeout}} giây để khởi tạo điểm kiểm tra. Nếu không cần chức năng này, hãy tắt nó trong cài đặt điểm kiểm tra.", diff --git a/webview-ui/src/i18n/locales/vi/history.json b/webview-ui/src/i18n/locales/vi/history.json index 48ec3a00a4..f5fe374702 100644 --- a/webview-ui/src/i18n/locales/vi/history.json +++ b/webview-ui/src/i18n/locales/vi/history.json @@ -26,9 +26,9 @@ "clearSelection": "Xóa chọn", "deleteSelected": "Xóa các mục đã chọn", "deleteTasks": "Xóa nhiệm vụ", - "confirmDeleteTasks": "Bạn có chắc chắn muốn xóa {{count}} nhiệm vụ không?", + "confirmDeleteTasks_other": "Bạn có chắc chắn muốn xóa {{count}} nhiệm vụ không?", "deleteTasksWarning": "Các nhiệm vụ đã xóa không thể khôi phục. Vui lòng chắc chắn bạn muốn tiếp tục.", - "deleteItems": "Xóa {{count}} mục", + "deleteItems_other": "Xóa {{count}} mục", "workspace": { "prefix": "Không gian làm việc:", "current": "Hiện tại", @@ -43,10 +43,9 @@ "mostRelevant": "Liên quan nhất" }, "viewAllHistory": "Xem tất cả", - "subtasks_one": "{{count}} tác vụ con", "subtasks_other": "{{count}} tác vụ con", "subtaskTag": "Tác vụ con", - "deleteWithSubtasks": "Điều này cũng sẽ xóa {{count}} tác vụ con. Bạn có chắc không?", + "deleteWithSubtasks_other": "Điều này cũng sẽ xóa {{count}} tác vụ con. Bạn có chắc không?", "expandSubtasks": "Mở rộng tác vụ con", "collapseSubtasks": "Thu gọn tác vụ con", "delegatedTag": "Đang chờ nhiệm vụ con", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index b8c769f584..462778d282 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -76,7 +76,6 @@ "summaryFailedNoFiles": "Quá trình nhập đã dừng trước khi bất kỳ tệp nào được sao chép.", "summaryCopied": "Đã sao chép {{copied}} trong {{total}} tệp", "detailFailed": "Bắt đầu một lần thử nhập mới để thử lại.", - "detailTasksImported_one": "Đã nhập {{count}} trong {{total}} lịch sử nhiệm vụ.", "detailTasksImported_other": "Đã nhập {{count}} trong {{total}} lịch sử nhiệm vụ.", "detailPreparing": "Đang chuẩn bị nhập lịch sử Roo Code.", "progressAriaLabel": "Tiến trình nhập lịch sử Roo Code" @@ -951,7 +950,7 @@ "useAzure": "Sử dụng Azure", "azureApiVersion": "Đặt phiên bản API Azure", "gemini": { - "freeRequests": "* Miễn phí đến {{count}} yêu cầu mỗi phút. Sau đó, thanh toán phụ thuộc vào kích thước lời nhắc.", + "freeRequests_other": "* Miễn phí đến {{count}} yêu cầu mỗi phút. Sau đó, thanh toán phụ thuộc vào kích thước lời nhắc.", "pricingDetails": "Để biết thêm thông tin, xem chi tiết giá.", "billingEstimate": "* Thanh toán là ước tính - chi phí chính xác phụ thuộc vào kích thước lời nhắc." } diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index 97dd6d620f..8671156b11 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -20,7 +20,7 @@ "unpin": "取消置顶", "pin": "置顶", "fileChangesInConversation": { - "header": "此对话中已更改 {{count}} 个文件" + "header_other": "此对话中已更改 {{count}} 个文件" }, "tokenProgress": { "availableSpace": "可用: {{amount}}", @@ -288,7 +288,6 @@ "triggerLabelOff": "自动批准已关闭", "triggerLabelOffShort": "关闭", "triggerLabel_zero": "0 个自动批准", - "triggerLabel_one": "1 个自动批准", "triggerLabel_other": "{{count}} 个自动批准", "triggerLabelAll": "BRRR" }, @@ -306,7 +305,6 @@ "truncation": { "title": "上下文已截断", "inProgress": "正在截断上下文...", - "messagesRemoved": "已移除 {{count}} 条消息", "messagesRemoved_other": "已移除 {{count}} 条消息", "description": "为保持在上下文窗口限制内,已从对话中移除较旧的消息。与压缩相比,这是一种快速但上下文保留较少的方法。" } @@ -350,7 +348,7 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "已达自动批准请求限制", - "description": "Zoo 已达到 {{count}} 次 API 请求的自动批准限制。您想重置计数并继续任务吗?", + "description_other": "Zoo 已达到 {{count}} 次 API 请求的自动批准限制。您想重置计数并继续任务吗?", "button": "重置并继续" }, "autoApprovedCostLimitReached": { @@ -362,7 +360,6 @@ "codebaseSearch": { "wantsToSearch": "Zoo 需要搜索代码库: {{query}}", "wantsToSearchWithPath": "Zoo 需要在 {{path}} 中搜索: {{query}}", - "didSearch_one": "找到 1 个结果", "didSearch_other": "找到 {{count}} 个结果", "resultTooltip": "相似度评分: {{score}} (点击打开文件)" }, @@ -433,9 +430,7 @@ }, "tooManyTools": { "title": "启用的工具过多", - "toolsPart_one": "{{count}} 个工具", "toolsPart_other": "{{count}} 个工具", - "serversPart_one": "{{count}} 个 MCP 服务", "serversPart_other": "{{count}} 个 MCP 服务", "messageTemplate": "你通过 {{servers}} 启用了 {{tools}}。这么多数量会混淆模型并导致错误。建议将其保持在 {{threshold}} 以下。", "openMcpSettings": "打开 MCP 设置" diff --git a/webview-ui/src/i18n/locales/zh-CN/common.json b/webview-ui/src/i18n/locales/zh-CN/common.json index bab7a26881..7bc88f69a8 100644 --- a/webview-ui/src/i18n/locales/zh-CN/common.json +++ b/webview-ui/src/i18n/locales/zh-CN/common.json @@ -57,19 +57,19 @@ }, "time_ago": { "just_now": "刚刚", - "seconds_ago": "{{count}}秒前", + "seconds_ago_other": "{{count}}秒前", "minute_ago": "1分钟前", - "minutes_ago": "{{count}}分钟前", + "minutes_ago_other": "{{count}}分钟前", "hour_ago": "1小时前", - "hours_ago": "{{count}}小时前", + "hours_ago_other": "{{count}}小时前", "day_ago": "1天前", - "days_ago": "{{count}}天前", + "days_ago_other": "{{count}}天前", "week_ago": "1周前", - "weeks_ago": "{{count}}周前", + "weeks_ago_other": "{{count}}周前", "month_ago": "1个月前", - "months_ago": "{{count}}个月前", + "months_ago_other": "{{count}}个月前", "year_ago": "1年前", - "years_ago": "{{count}}年前" + "years_ago_other": "{{count}}年前" }, "errors": { "wait_checkpoint_long_time": "初始化存档点已等待 {{timeout}} 秒。如果你不需要存档点功能,请在存档点设置中关闭。", diff --git a/webview-ui/src/i18n/locales/zh-CN/history.json b/webview-ui/src/i18n/locales/zh-CN/history.json index 2c97a23067..f5542d9948 100644 --- a/webview-ui/src/i18n/locales/zh-CN/history.json +++ b/webview-ui/src/i18n/locales/zh-CN/history.json @@ -26,9 +26,9 @@ "clearSelection": "清除选择", "deleteSelected": "删除选中项", "deleteTasks": "删除任务", - "confirmDeleteTasks": "确认删除 {{count}} 项任务?", + "confirmDeleteTasks_other": "确认删除 {{count}} 项任务?", "deleteTasksWarning": "删除后将无法恢复,请谨慎操作。", - "deleteItems": "删除 {{count}} 项", + "deleteItems_other": "删除 {{count}} 项", "workspace": { "prefix": "工作区:", "current": "当前", @@ -43,10 +43,9 @@ "mostRelevant": "最相关" }, "viewAllHistory": "查看全部", - "subtasks_one": "{{count}} 子任务", "subtasks_other": "{{count}} 子任务", "subtaskTag": "子任务", - "deleteWithSubtasks": "这也将删除 {{count}} 个子任务。您确定吗?", + "deleteWithSubtasks_other": "这也将删除 {{count}} 个子任务。您确定吗?", "expandSubtasks": "展开子任务", "collapseSubtasks": "收起子任务", "delegatedTag": "等待子任务", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 01c6cf7948..7da9f157f0 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -76,7 +76,6 @@ "summaryFailedNoFiles": "导入在复制任何文件之前已停止。", "summaryCopied": "已复制 {{total}} 个文件中的 {{copied}} 个", "detailFailed": "开始新的导入尝试以重试。", - "detailTasksImported_one": "已导入 {{total}} 个任务历史记录中的 {{count}} 个。", "detailTasksImported_other": "已导入 {{total}} 个任务历史记录中的 {{count}} 个。", "detailPreparing": "正在准备导入 Roo Code 历史记录。", "progressAriaLabel": "Roo Code 历史记录导入进度" @@ -951,7 +950,7 @@ "useAzure": "使用 Azure 服务", "azureApiVersion": "设置 Azure API 版本", "gemini": { - "freeRequests": "* 每分钟免费 {{count}} 个请求。之后,计费取决于提示大小。", + "freeRequests_other": "* 每分钟免费 {{count}} 个请求。之后,计费取决于提示大小。", "pricingDetails": "有关更多信息,请参阅定价详情。", "billingEstimate": "* 计费为估计值 - 具体费用取决于提示大小。" } diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index d3f7690981..71b5ed700b 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -20,7 +20,7 @@ "unpin": "取消釘選", "pin": "釘選", "fileChangesInConversation": { - "header": "此對話中已變更 {{count}} 個檔案" + "header_other": "此對話中已變更 {{count}} 個檔案" }, "retry": { "title": "重試", @@ -217,7 +217,6 @@ "truncation": { "title": "上下文已截斷", "inProgress": "正在截斷上下文...", - "messagesRemoved": "已移除 {{count}} 則訊息", "messagesRemoved_other": "已移除 {{count}} 則訊息", "description": "為保持在上下文視窗限制內,已從對話中移除較舊的訊息。與壓縮相比,這是一種快速但上下文保留較少的方法。" } @@ -263,7 +262,6 @@ "codebaseSearch": { "wantsToSearch": "Zoo 想要在程式碼庫中搜尋 {{query}}", "wantsToSearchWithPath": "Zoo 想要在 {{path}} 中搜尋程式碼庫 {{query}}", - "didSearch_one": "找到 1 個結果", "didSearch_other": "找到 {{count}} 個結果", "resultTooltip": "相似度評分:{{score}}(點選以開啟檔案)" }, @@ -336,7 +334,6 @@ "triggerLabelOff": "自動核准已關閉", "triggerLabelOffShort": "關閉", "triggerLabel_zero": "0 個自動核准", - "triggerLabel_one": "1 個自動核准", "triggerLabel_other": "{{count}} 個自動核准", "triggerLabelAll": "BRRR" }, @@ -379,7 +376,7 @@ "ask": { "autoApprovedRequestLimitReached": { "title": "已達自動核准請求上限", - "description": "Zoo 已達到 {{count}} 次 API 請求的自動核准上限。您想重設計數並繼續工作嗎?", + "description_other": "Zoo 已達到 {{count}} 次 API 請求的自動核准上限。您想重設計數並繼續工作嗎?", "button": "重設並繼續" }, "autoApprovedCostLimitReached": { @@ -423,9 +420,7 @@ }, "tooManyTools": { "title": "啟用的工具過多", - "toolsPart_one": "{{count}} 個工具", "toolsPart_other": "{{count}} 個工具", - "serversPart_one": "{{count}} 個 MCP 伺服器", "serversPart_other": "{{count}} 個 MCP 伺服器", "messageTemplate": "您已啟用 {{tools}}(透過 {{servers}})。這麼多的工具可能會混淆模型並導致錯誤。請嘗試保持在 {{threshold}} 以下。", "openMcpSettings": "開啟 MCP 設定" diff --git a/webview-ui/src/i18n/locales/zh-TW/common.json b/webview-ui/src/i18n/locales/zh-TW/common.json index b8f1ba20b8..b2fca75771 100644 --- a/webview-ui/src/i18n/locales/zh-TW/common.json +++ b/webview-ui/src/i18n/locales/zh-TW/common.json @@ -57,19 +57,19 @@ }, "time_ago": { "just_now": "剛剛", - "seconds_ago": "{{count}} 秒前", + "seconds_ago_other": "{{count}} 秒前", "minute_ago": "1 分鐘前", - "minutes_ago": "{{count}} 分鐘前", + "minutes_ago_other": "{{count}} 分鐘前", "hour_ago": "1 小時前", - "hours_ago": "{{count}} 小時前", + "hours_ago_other": "{{count}} 小時前", "day_ago": "1 天前", - "days_ago": "{{count}} 天前", + "days_ago_other": "{{count}} 天前", "week_ago": "1 週前", - "weeks_ago": "{{count}} 週前", + "weeks_ago_other": "{{count}} 週前", "month_ago": "1 個月前", - "months_ago": "{{count}} 個月前", + "months_ago_other": "{{count}} 個月前", "year_ago": "1 年前", - "years_ago": "{{count}} 年前" + "years_ago_other": "{{count}} 年前" }, "errors": { "wait_checkpoint_long_time": "初始化檢查點已等待 {{timeout}} 秒。若不需要檢查點功能,請在 [檢查點設定] 中關閉。", diff --git a/webview-ui/src/i18n/locales/zh-TW/history.json b/webview-ui/src/i18n/locales/zh-TW/history.json index 01bb30014b..50db9834a4 100644 --- a/webview-ui/src/i18n/locales/zh-TW/history.json +++ b/webview-ui/src/i18n/locales/zh-TW/history.json @@ -26,9 +26,9 @@ "clearSelection": "清除選擇", "deleteSelected": "刪除所選", "deleteTasks": "刪除工作", - "confirmDeleteTasks": "確定要刪除 {{count}} 個工作嗎?", + "confirmDeleteTasks_other": "確定要刪除 {{count}} 個工作嗎?", "deleteTasksWarning": "已刪除的工作無法復原,請確認是否要繼續。", - "deleteItems": "刪除 {{count}} 筆記錄", + "deleteItems_other": "刪除 {{count}} 筆記錄", "workspace": { "prefix": "工作區:", "current": "目前", @@ -43,10 +43,9 @@ "mostRelevant": "最相關" }, "viewAllHistory": "檢視全部", - "subtasks_one": "{{count}} 子工作", "subtasks_other": "{{count}} 子工作", "subtaskTag": "子工作", - "deleteWithSubtasks": "這也將刪除 {{count}} 個子工作。您確定嗎?", + "deleteWithSubtasks_other": "這也將刪除 {{count}} 個子工作。您確定嗎?", "expandSubtasks": "展開子工作", "collapseSubtasks": "收起子工作", "delegatedTag": "等待子任務", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index ceda034bf6..948577e63b 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -76,7 +76,6 @@ "summaryFailedNoFiles": "匯入在複製任何檔案之前已停止。", "summaryCopied": "已複製 {{total}} 個檔案中的 {{copied}} 個", "detailFailed": "開始新的匯入嘗試以重試。", - "detailTasksImported_one": "已匯入 {{total}} 個工作歷史記錄中的 {{count}} 個。", "detailTasksImported_other": "已匯入 {{total}} 個工作歷史記錄中的 {{count}} 個。", "detailPreparing": "正在準備匯入 Roo Code 歷史記錄。", "progressAriaLabel": "Roo Code 歷史記錄匯入進度" @@ -978,7 +977,7 @@ "useAzure": "使用 Azure", "azureApiVersion": "設定 Azure API 版本", "gemini": { - "freeRequests": "* 每分鐘可免費使用 {{count}} 次請求,超過後將依提示詞大小計費。", + "freeRequests_other": "* 每分鐘可免費使用 {{count}} 次請求,超過後將依提示詞大小計費。", "pricingDetails": "詳細資訊請參閱定價說明。", "billingEstimate": "* 費用為估算值 - 實際費用取決於提示大小。" }