diff --git a/src/renderer/src/components/native-chat/background-task-words-text.ts b/src/renderer/src/components/native-chat/background-task-words-text.ts index 701ac7836b3..c4e5bfc142a 100644 --- a/src/renderer/src/components/native-chat/background-task-words-text.ts +++ b/src/renderer/src/components/native-chat/background-task-words-text.ts @@ -21,91 +21,179 @@ const PIECES: Record translate('components.native-chat.backgroundTasks.task', COPY.task), detailsUnavailable: () => translate('components.native-chat.backgroundTasks.detailsUnavailable', COPY.detailsUnavailable), - countAgentsOne: () => - translate('components.native-chat.backgroundTasks.countAgentsOne', COPY.countAgentsOne), - countAgentsMany: (values) => - translate( - 'components.native-chat.backgroundTasks.countAgentsMany', - COPY.countAgentsMany, - values - ), - countShellOne: () => - translate('components.native-chat.backgroundTasks.countShellOne', COPY.countShellOne), - countShellMany: (values) => - translate('components.native-chat.backgroundTasks.countShellMany', COPY.countShellMany, values), + countAgents: (values) => + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.countAgents_one', + COPY.countAgents.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.countAgents_other', + COPY.countAgents.other, + values + ), + countShell: (values) => + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.countShell_one', + COPY.countShell.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.countShell_other', + COPY.countShell.other, + values + ), countShellCommandOne: () => translate( 'components.native-chat.backgroundTasks.countShellCommandOne', COPY.countShellCommandOne ), - countMonitorsOne: () => - translate('components.native-chat.backgroundTasks.countMonitorsOne', COPY.countMonitorsOne), - countMonitorsMany: (values) => - translate( - 'components.native-chat.backgroundTasks.countMonitorsMany', - COPY.countMonitorsMany, - values - ), - countWorkflowsOne: () => - translate('components.native-chat.backgroundTasks.countWorkflowsOne', COPY.countWorkflowsOne), - countWorkflowsMany: (values) => - translate( - 'components.native-chat.backgroundTasks.countWorkflowsMany', - COPY.countWorkflowsMany, - values - ), - countTasksOne: () => - translate('components.native-chat.backgroundTasks.countTasksOne', COPY.countTasksOne), - countTasksMany: (values) => - translate('components.native-chat.backgroundTasks.countTasksMany', COPY.countTasksMany, values), + countMonitors: (values) => + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.countMonitors_one', + COPY.countMonitors.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.countMonitors_other', + COPY.countMonitors.other, + values + ), + countWorkflows: (values) => + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.countWorkflows_one', + COPY.countWorkflows.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.countWorkflows_other', + COPY.countWorkflows.other, + values + ), + countTasks: (values) => + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.countTasks_one', + COPY.countTasks.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.countTasks_other', + COPY.countTasks.other, + values + ), headerTotal: (values) => - translate('components.native-chat.backgroundTasks.headerTotal', COPY.headerTotal, values), + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.headerTotal_one', + COPY.headerTotal.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.headerTotal_other', + COPY.headerTotal.other, + values + ), stateWorking: () => translate('components.native-chat.backgroundTasks.stateWorking', COPY.stateWorking), stateWorkingCount: (values) => - translate( - 'components.native-chat.backgroundTasks.stateWorkingCount', - COPY.stateWorkingCount, - values - ), + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.stateWorkingCount_one', + COPY.stateWorkingCount.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.stateWorkingCount_other', + COPY.stateWorkingCount.other, + values + ), stateMonitoring: () => translate('components.native-chat.backgroundTasks.stateMonitoring', COPY.stateMonitoring), stateMonitoringCount: (values) => - translate( - 'components.native-chat.backgroundTasks.stateMonitoringCount', - COPY.stateMonitoringCount, - values - ), + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.stateMonitoringCount_one', + COPY.stateMonitoringCount.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.stateMonitoringCount_other', + COPY.stateMonitoringCount.other, + values + ), stateWaiting: () => translate('components.native-chat.backgroundTasks.stateWaiting', COPY.stateWaiting), stateWaitingCount: (values) => - translate( - 'components.native-chat.backgroundTasks.stateWaitingCount', - COPY.stateWaitingCount, - values - ), + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.stateWaitingCount_one', + COPY.stateWaitingCount.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.stateWaitingCount_other', + COPY.stateWaitingCount.other, + values + ), stateBlocked: () => translate('components.native-chat.backgroundTasks.stateBlocked', COPY.stateBlocked), stateBlockedCount: (values) => - translate( - 'components.native-chat.backgroundTasks.stateBlockedCount', - COPY.stateBlockedCount, - values - ), + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.stateBlockedCount_one', + COPY.stateBlockedCount.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.stateBlockedCount_other', + COPY.stateBlockedCount.other, + values + ), stateDone: () => translate('components.native-chat.backgroundTasks.stateDone', COPY.stateDone), stateDoneCount: (values) => - translate('components.native-chat.backgroundTasks.stateDoneCount', COPY.stateDoneCount, values), + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.stateDoneCount_one', + COPY.stateDoneCount.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.stateDoneCount_other', + COPY.stateDoneCount.other, + values + ), stateIdle: () => translate('components.native-chat.backgroundTasks.stateIdle', COPY.stateIdle), stateIdleCount: (values) => - translate('components.native-chat.backgroundTasks.stateIdleCount', COPY.stateIdleCount, values), + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.stateIdleCount_one', + COPY.stateIdleCount.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.stateIdleCount_other', + COPY.stateIdleCount.other, + values + ), stateUnverifiable: () => translate('components.native-chat.backgroundTasks.stateUnverifiable', COPY.stateUnverifiable), stateUnverifiableCount: (values) => - translate( - 'components.native-chat.backgroundTasks.stateUnverifiableCount', - COPY.stateUnverifiableCount, - values - ), + values?.count === 1 + ? translate( + 'components.native-chat.backgroundTasks.stateUnverifiableCount_one', + COPY.stateUnverifiableCount.one, + values + ) + : translate( + 'components.native-chat.backgroundTasks.stateUnverifiableCount_other', + COPY.stateUnverifiableCount.other, + values + ), reasonWaiting: () => translate('components.native-chat.backgroundTasks.reasonWaiting', COPY.reasonWaiting), reasonBlocked: () => diff --git a/src/renderer/src/components/native-chat/counted-roster-words-text.test.ts b/src/renderer/src/components/native-chat/counted-roster-words-text.test.ts new file mode 100644 index 00000000000..a2308fe041b --- /dev/null +++ b/src/renderer/src/components/native-chat/counted-roster-words-text.test.ts @@ -0,0 +1,25 @@ +import { afterEach, expect, it } from 'vitest' +import { i18n } from '@/i18n/i18n' +import { sayBackgroundTaskTranslated } from './background-task-words-text' +import { sayNativeChatSubagentGroupTranslated } from './native-chat-subagent-group-words-text' + +afterEach(async () => { + await i18n.changeLanguage('en') +}) + +it('picks each Russian plural form for counted roster phrases', async () => { + await i18n.changeLanguage('ru') + const counts = [1, 3, 5, 21] + expect(counts.map((count) => sayBackgroundTaskTranslated('countAgents', { count }))).toEqual([ + '1 агент', + '3 агента', + '5 агентов', + '21 агент' + ]) + expect(counts.map((count) => sayNativeChatSubagentGroupTranslated('ran', { count }))).toEqual([ + 'Работал 1 дочерний агент', + 'Работали 3 дочерних агента', + 'Работали 5 дочерних агентов', + 'Работал 21 дочерний агент' + ]) +}) diff --git a/src/renderer/src/components/native-chat/native-chat-subagent-group-words-text.ts b/src/renderer/src/components/native-chat/native-chat-subagent-group-words-text.ts index a3af687666a..74155dad40b 100644 --- a/src/renderer/src/components/native-chat/native-chat-subagent-group-words-text.ts +++ b/src/renderer/src/components/native-chat/native-chat-subagent-group-words-text.ts @@ -6,11 +6,9 @@ import { type NativeChatSubagentGroupCopyId, type NativeChatSubagentGroupSay } from '../../../../shared/native-chat/transcript/native-chat-subagent-group-header' +import type { CopyValues } from '../../../../shared/counted-copy-english' -const PIECES: Record< - NativeChatSubagentGroupCopyId, - (values?: { value0: string | number }) => string -> = { +const PIECES: Record string> = { stateCompleted: () => translate('components.native-chat.subagents.state.completed', COPY.stateCompleted), stateWorking: () => @@ -22,32 +20,73 @@ const PIECES: Record< stateUnverifiable: () => translate('components.native-chat.subagents.state.unverifiable', COPY.stateUnverifiable), stateWorkingCount: (values) => - translate( - 'components.native-chat.subagents.state.workingCount', - COPY.stateWorkingCount, - values - ), + values?.count === 1 + ? translate( + 'components.native-chat.subagents.state.workingCount_one', + COPY.stateWorkingCount.one, + values + ) + : translate( + 'components.native-chat.subagents.state.workingCount_other', + COPY.stateWorkingCount.other, + values + ), stateIdleCount: (values) => - translate('components.native-chat.subagents.state.idleCount', COPY.stateIdleCount, values), + values?.count === 1 + ? translate( + 'components.native-chat.subagents.state.idleCount_one', + COPY.stateIdleCount.one, + values + ) + : translate( + 'components.native-chat.subagents.state.idleCount_other', + COPY.stateIdleCount.other, + values + ), stateFailedCount: (values) => - translate('components.native-chat.subagents.state.failedCount', COPY.stateFailedCount, values), + values?.count === 1 + ? translate( + 'components.native-chat.subagents.state.failedCount_one', + COPY.stateFailedCount.one, + values + ) + : translate( + 'components.native-chat.subagents.state.failedCount_other', + COPY.stateFailedCount.other, + values + ), stateStoppedCount: (values) => - translate( - 'components.native-chat.subagents.state.stoppedCount', - COPY.stateStoppedCount, - values - ), + values?.count === 1 + ? translate( + 'components.native-chat.subagents.state.stoppedCount_one', + COPY.stateStoppedCount.one, + values + ) + : translate( + 'components.native-chat.subagents.state.stoppedCount_other', + COPY.stateStoppedCount.other, + values + ), stateUnverifiableCount: (values) => - translate( - 'components.native-chat.subagents.state.unverifiableCount', - COPY.stateUnverifiableCount, - values - ), - startedOne: () => translate('components.native-chat.subagents.startedOne', COPY.startedOne), - startedN: (values) => - translate('components.native-chat.subagents.startedN', COPY.startedN, values), - ranOne: () => translate('components.native-chat.subagents.ranOne', COPY.ranOne), - ranN: (values) => translate('components.native-chat.subagents.ranN', COPY.ranN, values), + values?.count === 1 + ? translate( + 'components.native-chat.subagents.state.unverifiableCount_one', + COPY.stateUnverifiableCount.one, + values + ) + : translate( + 'components.native-chat.subagents.state.unverifiableCount_other', + COPY.stateUnverifiableCount.other, + values + ), + started: (values) => + values?.count === 1 + ? translate('components.native-chat.subagents.started_one', COPY.started.one, values) + : translate('components.native-chat.subagents.started_other', COPY.started.other, values), + ran: (values) => + values?.count === 1 + ? translate('components.native-chat.subagents.ran_one', COPY.ran.one, values) + : translate('components.native-chat.subagents.ran_other', COPY.ran.other, values), tokens: (values) => translate('components.native-chat.subagents.tokens', COPY.tokens, values) } diff --git a/src/renderer/src/i18n/en-runtime-required.json b/src/renderer/src/i18n/en-runtime-required.json index 45fd9aa3ae6..74f1f84ee85 100644 --- a/src/renderer/src/i18n/en-runtime-required.json +++ b/src/renderer/src/i18n/en-runtime-required.json @@ -1190,42 +1190,50 @@ "backgroundTasks": { "agent": "Background agent", "command": "Background command", - "countAgentsMany": "{{value0}} agents", - "countAgentsOne": "1 agent", - "countMonitorsMany": "{{value0}} monitors", - "countMonitorsOne": "1 monitor", + "countAgents_one": "{{count}} agent", + "countAgents_other": "{{count}} agents", + "countMonitors_one": "{{count}} monitor", + "countMonitors_other": "{{count}} monitors", "countShellCommandOne": "1 shell command", - "countShellMany": "{{value0}} shells", - "countShellOne": "1 shell", - "countTasksMany": "{{value0}} tasks", - "countTasksOne": "1 task", - "countWorkflowsMany": "{{value0}} workflows", - "countWorkflowsOne": "1 workflow", + "countShell_one": "{{count}} shell", + "countShell_other": "{{count}} shells", + "countTasks_one": "{{count}} task", + "countTasks_other": "{{count}} tasks", + "countWorkflows_one": "{{count}} workflow", + "countWorkflows_other": "{{count}} workflows", "detailsUnavailable": "Task details are unavailable for this session.", "groupAgents": "Agents", "groupMonitors": "Monitors", "groupShell": "Shell", "groupTasks": "Tasks", "groupWorkflows": "Workflows", - "headerTotal": "{{value0}} background tasks", + "headerTotal_one": "{{count}} background task", + "headerTotal_other": "{{count}} background tasks", "monitor": "Background monitor", "monitoring": "Monitoring background tasks", "reasonBlocked": "failed", "reasonWaiting": "needs approval", "stateBlocked": "blocked", - "stateBlockedCount": "{{value0}} blocked", + "stateBlockedCount_one": "{{value0}} blocked", + "stateBlockedCount_other": "{{value0}} blocked", "stateDone": "done", - "stateDoneCount": "{{value0}} done", + "stateDoneCount_one": "{{value0}} done", + "stateDoneCount_other": "{{value0}} done", "stateIdle": "stopped", - "stateIdleCount": "{{value0}} stopped", + "stateIdleCount_one": "{{value0}} stopped", + "stateIdleCount_other": "{{value0}} stopped", "stateMonitoring": "monitoring", - "stateMonitoringCount": "{{value0}} monitoring", + "stateMonitoringCount_one": "{{value0}} monitoring", + "stateMonitoringCount_other": "{{value0}} monitoring", "stateUnverifiable": "status unavailable", - "stateUnverifiableCount": "{{value0}} with status unavailable", + "stateUnverifiableCount_one": "{{value0}} with status unavailable", + "stateUnverifiableCount_other": "{{value0}} with status unavailable", "stateWaiting": "waiting", - "stateWaitingCount": "{{value0}} waiting", + "stateWaitingCount_one": "{{value0}} waiting", + "stateWaitingCount_other": "{{value0}} waiting", "stateWorking": "working", - "stateWorkingCount": "{{value0}} working", + "stateWorkingCount_one": "{{value0}} working", + "stateWorkingCount_other": "{{value0}} working", "stop": "Stop", "stopAll": "Stop background tasks", "stopTask": "Stop {{value0}}", @@ -1418,22 +1426,27 @@ "workingFor": "Working for {{value0}}" }, "subagents": { - "ranN": "Ran {{value0}} subagents", - "ranOne": "Ran 1 subagent", - "startedN": "Kicked off {{value0}} subagents", - "startedOne": "Kicked off 1 subagent", + "ran_one": "Ran {{count}} subagent", + "ran_other": "Ran {{count}} subagents", + "started_one": "Kicked off {{count}} subagent", + "started_other": "Kicked off {{count}} subagents", "state": { "completed": "completed", "failed": "failed", - "failedCount": "{{value0}} failed", + "failedCount_one": "{{count}} failed", + "failedCount_other": "{{count}} failed", "idle": "idle", - "idleCount": "{{value0}} idle", + "idleCount_one": "{{count}} idle", + "idleCount_other": "{{count}} idle", "stopped": "stopped", - "stoppedCount": "{{value0}} stopped", + "stoppedCount_one": "{{count}} stopped", + "stoppedCount_other": "{{count}} stopped", "unverifiable": "status unavailable", - "unverifiableCount": "{{value0}} with status unavailable", + "unverifiableCount_one": "{{count}} with status unavailable", + "unverifiableCount_other": "{{count}} with status unavailable", "working": "working", - "workingCount": "{{value0}} working" + "workingCount_one": "{{count}} working", + "workingCount_other": "{{count}} working" }, "tokens": "{{value0}} tokens" }, diff --git a/src/renderer/src/i18n/locales/de.json b/src/renderer/src/i18n/locales/de.json index 1f66468e935..0e6bc685d12 100644 --- a/src/renderer/src/i18n/locales/de.json +++ b/src/renderer/src/i18n/locales/de.json @@ -18900,39 +18900,47 @@ "task": "Hintergrundaufgabe", "outputFile": "Ausgabe: {{value0}}", "detailsUnavailable": "Aufgabendetails sind für diese Sitzung nicht verfügbar.", - "countAgentsOne": "1 Agent", - "countAgentsMany": "{{value0}} Agenten", - "countShellOne": "1 Shell", - "countShellMany": "{{value0}} Shells", "countShellCommandOne": "1 Shell-Befehl", - "countMonitorsOne": "1 Überwachung", - "countMonitorsMany": "{{value0}} Überwachungen", - "countWorkflowsOne": "1 Arbeitsablauf", - "countWorkflowsMany": "{{value0}} Arbeitsabläufe", - "countTasksOne": "1 Aufgabe", - "countTasksMany": "{{value0}} Aufgaben", - "headerTotal": "{{value0}} Hintergrundaufgaben", "stateWorking": "in Bearbeitung", - "stateWorkingCount": "{{value0}} in Bearbeitung", "stateMonitoring": "Überwachung aktiv", - "stateMonitoringCount": "{{value0}} mit aktiver Überwachung", "stateWaiting": "wartend", - "stateWaitingCount": "{{value0}} wartend", "stateBlocked": "blockiert", - "stateBlockedCount": "{{value0}} blockiert", "stateDone": "erledigt", - "stateDoneCount": "{{value0}} erledigt", "stateIdle": "gestoppt", - "stateIdleCount": "{{value0}} gestoppt", "stateUnverifiable": "Status nicht verfügbar", - "stateUnverifiableCount": "{{value0}} mit nicht verfügbarem Status", "reasonWaiting": "Genehmigung erforderlich", "reasonBlocked": "fehlgeschlagen", "groupAgents": "Agenten", "groupShell": "Shell", "groupMonitors": "Überwachungen", "groupWorkflows": "Arbeitsabläufe", - "groupTasks": "Aufgaben" + "groupTasks": "Aufgaben", + "countAgents_one": "{{count}} Agent", + "countAgents_other": "{{count}} Agenten", + "countShell_one": "{{count}} Shell", + "countShell_other": "{{count}} Shells", + "countMonitors_one": "{{count}} Überwachung", + "countMonitors_other": "{{count}} Überwachungen", + "countWorkflows_one": "{{count}} Arbeitsablauf", + "countWorkflows_other": "{{count}} Arbeitsabläufe", + "countTasks_one": "{{count}} Aufgabe", + "countTasks_other": "{{count}} Aufgaben", + "headerTotal_one": "{{count}} Hintergrundaufgabe", + "headerTotal_other": "{{count}} Hintergrundaufgaben", + "stateWorkingCount_one": "{{value0}} in Bearbeitung", + "stateWorkingCount_other": "{{value0}} in Bearbeitung", + "stateMonitoringCount_one": "{{value0}} mit aktiver Überwachung", + "stateMonitoringCount_other": "{{value0}} mit aktiver Überwachung", + "stateWaitingCount_one": "{{value0}} wartend", + "stateWaitingCount_other": "{{value0}} wartend", + "stateBlockedCount_one": "{{value0}} blockiert", + "stateBlockedCount_other": "{{value0}} blockiert", + "stateDoneCount_one": "{{value0}} erledigt", + "stateDoneCount_other": "{{value0}} erledigt", + "stateIdleCount_one": "{{value0}} gestoppt", + "stateIdleCount_other": "{{value0}} gestoppt", + "stateUnverifiableCount_one": "{{value0}} mit nicht verfügbarem Status", + "stateUnverifiableCount_other": "{{value0}} mit nicht verfügbarem Status" }, "jumpToLatest": "Zur neuesten Nachricht springen", "newRowsAnnouncement": "Während der Abwesenheit sind neue Nachrichten eingegangen", @@ -19031,18 +19039,23 @@ "failed": "Fehlgeschlagen", "stopped": "Gestoppt", "unverifiable": "Status nicht verfügbar", - "workingCount": "{{value0}} arbeiten", - "idleCount": "{{value0}} inaktiv", - "failedCount": "{{value0}} fehlgeschlagen", - "stoppedCount": "{{value0}} gestoppt", - "unverifiableCount": "{{value0}} mit nicht verfügbarem Status" + "workingCount_one": "{{count}} arbeitet", + "workingCount_other": "{{count}} arbeiten", + "idleCount_one": "{{count}} inaktiv", + "idleCount_other": "{{count}} inaktiv", + "failedCount_one": "{{count}} fehlgeschlagen", + "failedCount_other": "{{count}} fehlgeschlagen", + "stoppedCount_one": "{{count}} gestoppt", + "stoppedCount_other": "{{count}} gestoppt", + "unverifiableCount_one": "{{count}} mit nicht verfügbarem Status", + "unverifiableCount_other": "{{count}} mit nicht verfügbarem Status" }, - "startedOne": "1 Unteragent gestartet", - "startedN": "{{value0}} Unteragenten gestartet", - "ranOne": "1 Unteragent ausgeführt", - "ranN": "{{value0}} Unteragenten ausgeführt", "tokens": "{{value0}} Token", - "unnamed": "Unteragent" + "unnamed": "Unteragent", + "started_one": "{{count}} Unteragent gestartet", + "started_other": "{{count}} Unteragenten gestartet", + "ran_one": "{{count}} Unteragent ausgeführt", + "ran_other": "{{count}} Unteragenten ausgeführt" }, "rewind": { "unsupported": "Dieser Chat kann nicht zu einer früheren Nachricht zurückgesetzt werden.", diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json index 6151a8d7894..6ec536d19eb 100644 --- a/src/renderer/src/i18n/locales/en.json +++ b/src/renderer/src/i18n/locales/en.json @@ -18941,39 +18941,47 @@ "task": "Background task", "outputFile": "Output: {{value0}}", "detailsUnavailable": "Task details are unavailable for this session.", - "countAgentsOne": "1 agent", - "countAgentsMany": "{{value0}} agents", - "countShellOne": "1 shell", - "countShellMany": "{{value0}} shells", "countShellCommandOne": "1 shell command", - "countMonitorsOne": "1 monitor", - "countMonitorsMany": "{{value0}} monitors", - "countWorkflowsOne": "1 workflow", - "countWorkflowsMany": "{{value0}} workflows", - "countTasksOne": "1 task", - "countTasksMany": "{{value0}} tasks", - "headerTotal": "{{value0}} background tasks", "stateWorking": "working", - "stateWorkingCount": "{{value0}} working", "stateMonitoring": "monitoring", - "stateMonitoringCount": "{{value0}} monitoring", "stateWaiting": "waiting", - "stateWaitingCount": "{{value0}} waiting", "stateBlocked": "blocked", - "stateBlockedCount": "{{value0}} blocked", "stateDone": "done", - "stateDoneCount": "{{value0}} done", "stateIdle": "stopped", - "stateIdleCount": "{{value0}} stopped", "stateUnverifiable": "status unavailable", - "stateUnverifiableCount": "{{value0}} with status unavailable", "reasonWaiting": "needs approval", "reasonBlocked": "failed", "groupAgents": "Agents", "groupShell": "Shell", "groupMonitors": "Monitors", "groupWorkflows": "Workflows", - "groupTasks": "Tasks" + "groupTasks": "Tasks", + "countAgents_one": "{{count}} agent", + "countAgents_other": "{{count}} agents", + "countShell_one": "{{count}} shell", + "countShell_other": "{{count}} shells", + "countMonitors_one": "{{count}} monitor", + "countMonitors_other": "{{count}} monitors", + "countWorkflows_one": "{{count}} workflow", + "countWorkflows_other": "{{count}} workflows", + "countTasks_one": "{{count}} task", + "countTasks_other": "{{count}} tasks", + "headerTotal_one": "{{count}} background task", + "headerTotal_other": "{{count}} background tasks", + "stateWorkingCount_one": "{{value0}} working", + "stateWorkingCount_other": "{{value0}} working", + "stateMonitoringCount_one": "{{value0}} monitoring", + "stateMonitoringCount_other": "{{value0}} monitoring", + "stateWaitingCount_one": "{{value0}} waiting", + "stateWaitingCount_other": "{{value0}} waiting", + "stateBlockedCount_one": "{{value0}} blocked", + "stateBlockedCount_other": "{{value0}} blocked", + "stateDoneCount_one": "{{value0}} done", + "stateDoneCount_other": "{{value0}} done", + "stateIdleCount_one": "{{value0}} stopped", + "stateIdleCount_other": "{{value0}} stopped", + "stateUnverifiableCount_one": "{{value0}} with status unavailable", + "stateUnverifiableCount_other": "{{value0}} with status unavailable" }, "jumpToLatest": "Jump to latest", "newRowsAnnouncement": "New messages arrived while you were away", @@ -19072,18 +19080,23 @@ "failed": "failed", "stopped": "stopped", "unverifiable": "status unavailable", - "workingCount": "{{value0}} working", - "idleCount": "{{value0}} idle", - "failedCount": "{{value0}} failed", - "stoppedCount": "{{value0}} stopped", - "unverifiableCount": "{{value0}} with status unavailable" + "workingCount_one": "{{count}} working", + "workingCount_other": "{{count}} working", + "idleCount_one": "{{count}} idle", + "idleCount_other": "{{count}} idle", + "failedCount_one": "{{count}} failed", + "failedCount_other": "{{count}} failed", + "stoppedCount_one": "{{count}} stopped", + "stoppedCount_other": "{{count}} stopped", + "unverifiableCount_one": "{{count}} with status unavailable", + "unverifiableCount_other": "{{count}} with status unavailable" }, - "startedOne": "Kicked off 1 subagent", - "startedN": "Kicked off {{value0}} subagents", - "ranOne": "Ran 1 subagent", - "ranN": "Ran {{value0}} subagents", "tokens": "{{value0}} tokens", - "unnamed": "Subagent" + "unnamed": "Subagent", + "started_one": "Kicked off {{count}} subagent", + "started_other": "Kicked off {{count}} subagents", + "ran_one": "Ran {{count}} subagent", + "ran_other": "Ran {{count}} subagents" }, "rewind": { "unsupported": "This chat can't go back to an earlier message.", diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json index 782a76535b8..c45d9b6bd1e 100644 --- a/src/renderer/src/i18n/locales/es.json +++ b/src/renderer/src/i18n/locales/es.json @@ -18606,23 +18606,28 @@ "subagents": { "unnamed": "Subagente", "state": { - "failedCount": "{{value0}} con error", "working": "trabajando", "failed": "falló", "stopped": "detenido", "unverifiable": "estado no disponible", - "unverifiableCount": "{{value0}} con estado no disponible", "completed": "completado", "idle": "inactivo", - "workingCount": "{{value0}} trabajando", - "idleCount": "{{value0}} inactivo(s)", - "stoppedCount": "{{value0}} detenido(s)" + "workingCount_one": "{{count}} trabajando", + "workingCount_other": "{{count}} trabajando", + "idleCount_one": "{{count}} inactivo", + "idleCount_other": "{{count}} inactivos", + "failedCount_one": "{{count}} con error", + "failedCount_other": "{{count}} con error", + "stoppedCount_one": "{{count}} detenido", + "stoppedCount_other": "{{count}} detenidos", + "unverifiableCount_one": "{{count}} con estado no disponible", + "unverifiableCount_other": "{{count}} con estado no disponible" }, - "startedOne": "Inició 1 subagente", - "startedN": "Inició {{value0}} subagentes", - "ranOne": "Ejecutó 1 subagente", - "ranN": "Ejecutó {{value0}} subagentes", - "tokens": "{{value0}} tokens" + "tokens": "{{value0}} tokens", + "started_one": "Inició {{count}} subagente", + "started_other": "Inició {{count}} subagentes", + "ran_one": "Ejecutó {{count}} subagente", + "ran_other": "Ejecutó {{count}} subagentes" }, "queuedMessages": { "alreadySent": "Este mensaje ya se envió.", @@ -18687,37 +18692,45 @@ "task": "Tarea en segundo plano", "outputFile": "Salida: {{value0}}", "detailsUnavailable": "Los detalles de la tarea no están disponibles para esta sesión.", - "countAgentsOne": "1 agente", - "countAgentsMany": "{{value0}} agentes", - "countShellOne": "1 shell", - "countShellMany": "{{value0}} shells", "countShellCommandOne": "1 comando de shell", - "countMonitorsOne": "1 monitor", - "countMonitorsMany": "{{value0}} monitores", - "countWorkflowsOne": "1 flujo de trabajo", - "countWorkflowsMany": "{{value0}} flujos de trabajo", - "countTasksOne": "1 tarea", - "countTasksMany": "{{value0}} tareas", - "headerTotal": "{{value0}} tareas en segundo plano", "stateWorking": "trabajando", - "stateWorkingCount": "{{value0}} trabajando", "stateMonitoring": "supervisando", - "stateMonitoringCount": "{{value0}} supervisando", "stateWaiting": "esperando", - "stateWaitingCount": "{{value0}} esperando", "stateBlocked": "bloqueado", - "stateBlockedCount": "{{value0}} en estado bloqueado", "stateDone": "terminado", - "stateDoneCount": "{{value0}} en estado terminado", "stateIdle": "detenido", - "stateIdleCount": "{{value0}} en estado detenido", "stateUnverifiable": "estado no disponible", - "stateUnverifiableCount": "{{value0}} con estado no disponible", "reasonWaiting": "aprobación pendiente", "reasonBlocked": "con error", "groupShell": "Shell", "groupMonitors": "Monitores", - "groupWorkflows": "Flujos de trabajo" + "groupWorkflows": "Flujos de trabajo", + "countAgents_one": "{{count}} agente", + "countAgents_other": "{{count}} agentes", + "countShell_one": "{{count}} shell", + "countShell_other": "{{count}} shells", + "countMonitors_one": "{{count}} monitor", + "countMonitors_other": "{{count}} monitores", + "countWorkflows_one": "{{count}} flujo de trabajo", + "countWorkflows_other": "{{count}} flujos de trabajo", + "countTasks_one": "{{count}} tarea", + "countTasks_other": "{{count}} tareas", + "headerTotal_one": "{{count}} tarea en segundo plano", + "headerTotal_other": "{{count}} tareas en segundo plano", + "stateWorkingCount_one": "{{value0}} trabajando", + "stateWorkingCount_other": "{{value0}} trabajando", + "stateMonitoringCount_one": "{{value0}} supervisando", + "stateMonitoringCount_other": "{{value0}} supervisando", + "stateWaitingCount_one": "{{value0}} esperando", + "stateWaitingCount_other": "{{value0}} esperando", + "stateBlockedCount_one": "{{value0}} en estado bloqueado", + "stateBlockedCount_other": "{{value0}} en estado bloqueado", + "stateDoneCount_one": "{{value0}} en estado terminado", + "stateDoneCount_other": "{{value0}} en estado terminado", + "stateIdleCount_one": "{{value0}} en estado detenido", + "stateIdleCount_other": "{{value0}} en estado detenido", + "stateUnverifiableCount_one": "{{value0}} con estado no disponible", + "stateUnverifiableCount_other": "{{value0}} con estado no disponible" }, "taskList": { "title": "Tareas", diff --git a/src/renderer/src/i18n/locales/fr.json b/src/renderer/src/i18n/locales/fr.json index 969f7c98b9c..63226813e11 100644 --- a/src/renderer/src/i18n/locales/fr.json +++ b/src/renderer/src/i18n/locales/fr.json @@ -18833,39 +18833,47 @@ "task": "Tâche en arrière-plan", "outputFile": "Sortie : {{value0}}", "detailsUnavailable": "Les détails des tâches ne sont pas disponibles pour cette session.", - "countAgentsOne": "1 mandataire", - "countAgentsMany": "Agents {{value0}}", - "countShellOne": "1 coquille", - "countShellMany": "Coquilles {{value0}}", "countShellCommandOne": "1 commande shell", - "countMonitorsOne": "1 moniteur", - "countMonitorsMany": "Moniteurs {{value0}}", - "countWorkflowsOne": "1 flux de travail", - "countWorkflowsMany": "Flux de travail {{value0}}", - "countTasksOne": "1 tâche", - "countTasksMany": "{{value0}} tâches", - "headerTotal": "{{value0}} tâches en arrière-plan", "stateWorking": "fonctionnement", - "stateWorkingCount": "{{value0}} en cours", "stateMonitoring": "surveillance", - "stateMonitoringCount": "{{value0}} en surveillance", "stateWaiting": "en attendant", - "stateWaitingCount": "{{value0}} en attente", "stateBlocked": "bloqué", - "stateBlockedCount": "{{value0}} à l'état bloqué", "stateDone": "fait", - "stateDoneCount": "{{value0}} à l'état terminé", "stateIdle": "arrêté", - "stateIdleCount": "{{value0}} à l'état arrêté", "stateUnverifiable": "statut indisponible", - "stateUnverifiableCount": "{{value0}} au statut indisponible", "reasonWaiting": "a besoin d'approbation", "reasonBlocked": "échoué", "groupAgents": "Agents", "groupShell": "Coquille", "groupMonitors": "Moniteurs", "groupWorkflows": "Flux de travail", - "groupTasks": "Tâches" + "groupTasks": "Tâches", + "countAgents_one": "{{count}} agent", + "countAgents_other": "{{count}} agents", + "countShell_one": "{{count}} shell", + "countShell_other": "{{count}} shells", + "countMonitors_one": "{{count}} moniteur", + "countMonitors_other": "{{count}} moniteurs", + "countWorkflows_one": "{{count}} flux de travail", + "countWorkflows_other": "{{count}} flux de travail", + "countTasks_one": "{{count}} tâche", + "countTasks_other": "{{count}} tâches", + "headerTotal_one": "{{count}} tâche en arrière-plan", + "headerTotal_other": "{{count}} tâches en arrière-plan", + "stateWorkingCount_one": "{{value0}} en cours", + "stateWorkingCount_other": "{{value0}} en cours", + "stateMonitoringCount_one": "{{value0}} en surveillance", + "stateMonitoringCount_other": "{{value0}} en surveillance", + "stateWaitingCount_one": "{{value0}} en attente", + "stateWaitingCount_other": "{{value0}} en attente", + "stateBlockedCount_one": "{{value0}} à l'état bloqué", + "stateBlockedCount_other": "{{value0}} à l'état bloqué", + "stateDoneCount_one": "{{value0}} à l'état terminé", + "stateDoneCount_other": "{{value0}} à l'état terminé", + "stateIdleCount_one": "{{value0}} à l'état arrêté", + "stateIdleCount_other": "{{value0}} à l'état arrêté", + "stateUnverifiableCount_one": "{{value0}} au statut indisponible", + "stateUnverifiableCount_other": "{{value0}} au statut indisponible" }, "railLabel": "Vos messages", "railImageMessage": "Image jointe", @@ -18885,18 +18893,23 @@ "failed": "échoué", "stopped": "arrêté", "unverifiable": "statut indisponible", - "workingCount": "{{value0}} fonctionne", - "idleCount": "{{value0}} inactif", - "failedCount": "{{value0}} a échoué", - "stoppedCount": "{{value0}} arrêté", - "unverifiableCount": "{{value0}} au statut indisponible" + "workingCount_one": "{{count}} en cours", + "workingCount_other": "{{count}} en cours", + "idleCount_one": "{{count}} inactif", + "idleCount_other": "{{count}} inactifs", + "failedCount_one": "{{count}} en échec", + "failedCount_other": "{{count}} en échec", + "stoppedCount_one": "{{count}} arrêté", + "stoppedCount_other": "{{count}} arrêtés", + "unverifiableCount_one": "{{count}} au statut indisponible", + "unverifiableCount_other": "{{count}} au statut indisponible" }, - "startedOne": "A lancé 1 sous-agent", - "startedN": "A lancé {{value0}} sous-agents", - "ranOne": "A exécuté 1 sous-agent", - "ranN": "A exécuté {{value0}} sous-agents", "tokens": "Jetons {{value0}}", - "unnamed": "Sous-agent" + "unnamed": "Sous-agent", + "started_one": "A lancé {{count}} sous-agent", + "started_other": "A lancé {{count}} sous-agents", + "ran_one": "A exécuté {{count}} sous-agent", + "ran_other": "A exécuté {{count}} sous-agents" }, "drop": { "messageTitle": "Déposez pour joindre à ce message", diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json index 09d25252812..e6b52972341 100644 --- a/src/renderer/src/i18n/locales/ja.json +++ b/src/renderer/src/i18n/locales/ja.json @@ -18470,39 +18470,34 @@ "task": "バックグラウンドタスク", "outputFile": "出力: {{value0}}", "detailsUnavailable": "このセッションではタスクの詳細は利用できません。", - "countAgentsOne": "Agent1名", - "countAgentsMany": "{{value0}} Agent", - "countShellOne": "1 シェル", - "countShellMany": "{{value0}} シェル", "countShellCommandOne": "1 シェルコマンド", - "countMonitorsOne": "モニター1台", - "countMonitorsMany": "{{value0}} モニター", - "countWorkflowsOne": "1つのワークフロー", - "countWorkflowsMany": "{{value0}} ワークフロー", - "countTasksOne": "1タスク", - "countTasksMany": "{{value0}} タスク", - "headerTotal": "{{value0}} バックグラウンドタスク", "stateWorking": "実行中", - "stateWorkingCount": "{{value0}} 実行中", "stateMonitoring": "監視", - "stateMonitoringCount": "{{value0}} 監視", "stateWaiting": "待機中", - "stateWaitingCount": "{{value0}} 待機中", "stateBlocked": "ブロックされました", - "stateBlockedCount": "{{value0}} ブロックされました", "stateDone": "終わり", - "stateDoneCount": "{{value0}} 終わり", "stateIdle": "止まった", - "stateIdleCount": "{{value0}} 止まった", "stateUnverifiable": "状態を取得できません", - "stateUnverifiableCount": "{{value0}} は状態を取得できません", "reasonWaiting": "承認が必要です", "reasonBlocked": "失敗した", "groupAgents": "Agent", "groupShell": "シェル", "groupMonitors": "モニター", "groupWorkflows": "ワークフロー", - "groupTasks": "タスク" + "groupTasks": "タスク", + "countAgents_other": "{{count}} 個の Agent", + "countShell_other": "{{count}} 個のシェル", + "countMonitors_other": "{{count}} 件のモニター", + "countWorkflows_other": "{{count}} 件のワークフロー", + "countTasks_other": "{{count}} 件のタスク", + "headerTotal_other": "{{count}} 件のバックグラウンドタスク", + "stateWorkingCount_other": "実行中: {{value0}}", + "stateMonitoringCount_other": "監視中: {{value0}}", + "stateWaitingCount_other": "待機中: {{value0}}", + "stateBlockedCount_other": "ブロック中: {{value0}}", + "stateDoneCount_other": "完了: {{value0}}", + "stateIdleCount_other": "停止: {{value0}}", + "stateUnverifiableCount_other": "状態取得不可: {{value0}}" }, "railLabel": "あなたのメッセージ", "railImageMessage": "画像添付", @@ -18521,18 +18516,16 @@ "failed": "失敗した", "stopped": "止まった", "unverifiable": "状態を取得できません", - "workingCount": "{{value0}} は動作しています", - "idleCount": "{{value0}} アイドル状態", - "failedCount": "{{value0}} 件失敗", - "stoppedCount": "{{value0}} が停止しました", - "unverifiableCount": "{{value0}} 件は状態を取得できません" + "workingCount_other": "実行中 {{count}} 件", + "idleCount_other": "アイドル状態 {{count}} 件", + "failedCount_other": "失敗 {{count}} 件", + "stoppedCount_other": "停止 {{count}} 件", + "unverifiableCount_other": "状態取得不可 {{count}} 件" }, - "startedOne": "1 個のサブ Agent を起動しました", - "startedN": "{{value0}} 個のサブ Agent を起動しました", - "ranOne": "1 個のサブ Agent を実行しました", - "ranN": "{{value0}} 個のサブ Agent を実行しました", "tokens": "{{value0}} トークン", - "unnamed": "サブ Agent" + "unnamed": "サブ Agent", + "started_other": "{{count}} 個のサブ Agent を起動しました", + "ran_other": "{{count}} 個のサブ Agent を実行しました" }, "drop": { "messageTitle": "ドロップしてこのメッセージに添付", diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json index 896c9a5014f..bf71cca8b36 100644 --- a/src/renderer/src/i18n/locales/ko.json +++ b/src/renderer/src/i18n/locales/ko.json @@ -18470,39 +18470,34 @@ "task": "백그라운드 작업", "outputFile": "출력: {{value0}}", "detailsUnavailable": "이 세션에서는 작업 세부정보를 사용할 수 없습니다.", - "countAgentsOne": "에이전트 1명", - "countAgentsMany": "{{value0}} 에이전트", - "countShellOne": "셸 1개", - "countShellMany": "셸 {{value0}}개", "countShellCommandOne": "셸 명령 1개", - "countMonitorsOne": "모니터 1개", - "countMonitorsMany": "{{value0}} 모니터", - "countWorkflowsOne": "워크플로우 1개", - "countWorkflowsMany": "{{value0}} 워크플로", - "countTasksOne": "작업 1개", - "countTasksMany": "{{value0}} 작업", - "headerTotal": "{{value0}} 백그라운드 작업", "stateWorking": "작업 중", - "stateWorkingCount": "{{value0}} 작업 중", "stateMonitoring": "모니터링", - "stateMonitoringCount": "{{value0}} 모니터링", "stateWaiting": "대기 중", - "stateWaitingCount": "{{value0}} 대기 중", "stateBlocked": "막힌", - "stateBlockedCount": "{{value0}} 막힌", "stateDone": "완료", - "stateDoneCount": "{{value0}} 완료", "stateIdle": "중지됨", - "stateIdleCount": "{{value0}} 중지됨", "stateUnverifiable": "상태를 확인할 수 없음", - "stateUnverifiableCount": "{{value0}} 상태를 확인할 수 없음", "reasonWaiting": "승인이 필요합니다", "reasonBlocked": "실패한", "groupAgents": "에이전트", "groupShell": "셸", "groupMonitors": "모니터", "groupWorkflows": "워크플로", - "groupTasks": "작업" + "groupTasks": "작업", + "countAgents_other": "에이전트 {{count}}개", + "countShell_other": "셸 {{count}}개", + "countMonitors_other": "모니터 {{count}}개", + "countWorkflows_other": "워크플로 {{count}}개", + "countTasks_other": "작업 {{count}}개", + "headerTotal_other": "백그라운드 작업 {{count}}개", + "stateWorkingCount_other": "작업 중: {{value0}}", + "stateMonitoringCount_other": "모니터링 중: {{value0}}", + "stateWaitingCount_other": "대기 중: {{value0}}", + "stateBlockedCount_other": "차단됨: {{value0}}", + "stateDoneCount_other": "완료: {{value0}}", + "stateIdleCount_other": "중지됨: {{value0}}", + "stateUnverifiableCount_other": "상태 확인 불가: {{value0}}" }, "railLabel": "귀하의 메시지", "railImageMessage": "이미지 첨부", @@ -18521,18 +18516,16 @@ "failed": "실패한", "stopped": "중지됨", "unverifiable": "상태를 확인할 수 없음", - "workingCount": "{{value0}} 작업 중", - "idleCount": "{{value0}} 유휴", - "failedCount": "{{value0}} 실패", - "stoppedCount": "{{value0}} 중지됨", - "unverifiableCount": "{{value0}} 상태를 확인할 수 없음" + "workingCount_other": "{{count}}개 작업 중", + "idleCount_other": "{{count}}개 유휴", + "failedCount_other": "{{count}}개 실패", + "stoppedCount_other": "{{count}}개 중지됨", + "unverifiableCount_other": "{{count}}개 상태 확인 불가" }, - "startedOne": "하위 에이전트 1개가 시작되었습니다.", - "startedN": "{{value0}} 하위 에이전트가 시작되었습니다.", - "ranOne": "하위 에이전트 1개 실행", - "ranN": "{{value0}} 하위 에이전트를 실행했습니다.", "tokens": "{{value0}} 토큰", - "unnamed": "하위 에이전트" + "unnamed": "하위 에이전트", + "started_other": "하위 에이전트 {{count}}개 시작", + "ran_other": "하위 에이전트 {{count}}개 실행" }, "drop": { "messageTitle": "놓아서 이 메시지에 첨부", diff --git a/src/renderer/src/i18n/locales/pt.json b/src/renderer/src/i18n/locales/pt.json index e5fb6f24677..7963b9f6704 100644 --- a/src/renderer/src/i18n/locales/pt.json +++ b/src/renderer/src/i18n/locales/pt.json @@ -19088,18 +19088,7 @@ "task": "Tarefa em segundo plano", "outputFile": "Saída: {{value0}}", "detailsUnavailable": "Os detalhes da tarefa não estão disponíveis para esta sessão.", - "countAgentsOne": "1 agente", - "countAgentsMany": "{{value0}} agentes", - "countShellOne": "1 shell", - "countShellMany": "{{value0}} shells", "countShellCommandOne": "1 comando de shell", - "countMonitorsOne": "1 monitor", - "countMonitorsMany": "{{value0}} monitores", - "countWorkflowsOne": "1 fluxo de trabalho", - "countWorkflowsMany": "{{value0}} fluxos de trabalho", - "countTasksOne": "1 tarefa", - "countTasksMany": "{{value0}} tarefas", - "headerTotal": "{{value0}} tarefas em segundo plano", "stateWorking": "trabalhando", "stateMonitoring": "monitorando", "stateWaiting": "aguardando", @@ -19114,13 +19103,32 @@ "groupMonitors": "Monitores", "groupWorkflows": "Fluxos de trabalho", "groupTasks": "Tarefas", - "stateWorkingCount": "{{value0}} trabalhando", - "stateMonitoringCount": "{{value0}} monitorando", - "stateWaitingCount": "{{value0}} aguardando", - "stateBlockedCount": "{{value0}} bloqueados", - "stateDoneCount": "{{value0}} concluídos", - "stateIdleCount": "{{value0}} parados", - "stateUnverifiableCount": "{{value0}} com status indisponível" + "countAgents_one": "{{count}} agente", + "countAgents_other": "{{count}} agentes", + "countShell_one": "{{count}} shell", + "countShell_other": "{{count}} shells", + "countMonitors_one": "{{count}} monitor", + "countMonitors_other": "{{count}} monitores", + "countWorkflows_one": "{{count}} fluxo de trabalho", + "countWorkflows_other": "{{count}} fluxos de trabalho", + "countTasks_one": "{{count}} tarefa", + "countTasks_other": "{{count}} tarefas", + "headerTotal_one": "{{count}} tarefa em segundo plano", + "headerTotal_other": "{{count}} tarefas em segundo plano", + "stateWorkingCount_one": "Trabalhando: {{value0}}", + "stateWorkingCount_other": "Trabalhando: {{value0}}", + "stateMonitoringCount_one": "Monitorando: {{value0}}", + "stateMonitoringCount_other": "Monitorando: {{value0}}", + "stateWaitingCount_one": "Aguardando: {{value0}}", + "stateWaitingCount_other": "Aguardando: {{value0}}", + "stateBlockedCount_one": "Bloqueado: {{value0}}", + "stateBlockedCount_other": "Bloqueado: {{value0}}", + "stateDoneCount_one": "Concluído: {{value0}}", + "stateDoneCount_other": "Concluído: {{value0}}", + "stateIdleCount_one": "Parado: {{value0}}", + "stateIdleCount_other": "Parado: {{value0}}", + "stateUnverifiableCount_one": "Status indisponível: {{value0}}", + "stateUnverifiableCount_other": "Status indisponível: {{value0}}" }, "jumpToLatest": "Ir para o mais recente", "toggle": { @@ -19198,18 +19206,23 @@ "failed": "falhou", "stopped": "parado", "unverifiable": "não verificável", - "workingCount": "{{value0}} trabalhando", - "idleCount": "{{value0}} inativo(s)", - "failedCount": "{{value0}} com falha", - "stoppedCount": "{{value0}} parado(s)", - "unverifiableCount": "{{value0}} não verificável(is)" + "workingCount_one": "{{count}} trabalhando", + "workingCount_other": "{{count}} trabalhando", + "idleCount_one": "{{count}} inativo", + "idleCount_other": "{{count}} inativos", + "failedCount_one": "{{count}} com falha", + "failedCount_other": "{{count}} com falha", + "stoppedCount_one": "{{count}} parado", + "stoppedCount_other": "{{count}} parados", + "unverifiableCount_one": "{{count}} com status indisponível", + "unverifiableCount_other": "{{count}} com status indisponível" }, - "startedOne": "Iniciou 1 subagente", - "startedN": "Iniciou {{value0}} subagentes", - "ranOne": "Executou 1 subagente", - "ranN": "Executou {{value0}} subagentes", "tokens": "{{value0}} tokens", - "unnamed": "Subagente" + "unnamed": "Subagente", + "started_one": "Iniciou {{count}} subagente", + "started_other": "Iniciou {{count}} subagentes", + "ran_one": "Executou {{count}} subagente", + "ran_other": "Executou {{count}} subagentes" }, "drop": { "title": "Solte para anexar a este chat", diff --git a/src/renderer/src/i18n/locales/ru.json b/src/renderer/src/i18n/locales/ru.json index 95dfe5615d8..38af7582f20 100644 --- a/src/renderer/src/i18n/locales/ru.json +++ b/src/renderer/src/i18n/locales/ru.json @@ -19439,39 +19439,73 @@ "task": "Фоновая задача", "outputFile": "Вывод: {{value0}}", "detailsUnavailable": "Подробности задач в этой сессии недоступны.", - "countAgentsOne": "1 агент", - "countAgentsMany": "Агентов: {{value0}}", - "countShellOne": "1 оболочка", - "countShellMany": "Оболочек: {{value0}}", "countShellCommandOne": "1 команда оболочки", - "countMonitorsOne": "1 наблюдение", - "countMonitorsMany": "Наблюдений: {{value0}}", - "countWorkflowsOne": "1 процесс", - "countWorkflowsMany": "Процессов: {{value0}}", - "countTasksOne": "1 задача", - "countTasksMany": "Задач: {{value0}}", - "headerTotal": "Фоновых задач: {{value0}}", "stateWorking": "в работе", - "stateWorkingCount": "В работе: {{value0}}", "stateMonitoring": "наблюдает", - "stateMonitoringCount": "Наблюдают: {{value0}}", "stateWaiting": "ожидает", - "stateWaitingCount": "Ожидают: {{value0}}", "stateBlocked": "заблокировано", - "stateBlockedCount": "Заблокировано: {{value0}}", "stateDone": "готово", - "stateDoneCount": "Готово: {{value0}}", "stateIdle": "остановлено", - "stateIdleCount": "Остановлено: {{value0}}", "stateUnverifiable": "статус недоступен", - "stateUnverifiableCount": "Статус недоступен: {{value0}}", "reasonWaiting": "нужно разрешение", "reasonBlocked": "ошибка", "groupAgents": "Агенты", "groupShell": "Оболочка", "groupMonitors": "Наблюдения", "groupWorkflows": "Процессы", - "groupTasks": "Задачи" + "groupTasks": "Задачи", + "countAgents_one": "{{count}} агент", + "countAgents_other": "{{count}} агента", + "countShell_one": "{{count}} оболочка", + "countShell_other": "{{count}} оболочки", + "countMonitors_one": "{{count}} наблюдение", + "countMonitors_other": "{{count}} наблюдения", + "countWorkflows_one": "{{count}} процесс", + "countWorkflows_other": "{{count}} процесса", + "countTasks_one": "{{count}} задача", + "countTasks_other": "{{count}} задачи", + "headerTotal_one": "{{count}} фоновая задача", + "headerTotal_other": "{{count}} фоновой задачи", + "stateWorkingCount_one": "В работе: {{value0}}", + "stateWorkingCount_other": "В работе: {{value0}}", + "stateMonitoringCount_one": "Наблюдение: {{value0}}", + "stateMonitoringCount_other": "Наблюдение: {{value0}}", + "stateWaitingCount_one": "В ожидании: {{value0}}", + "stateWaitingCount_other": "В ожидании: {{value0}}", + "stateBlockedCount_one": "Заблокировано: {{value0}}", + "stateBlockedCount_other": "Заблокировано: {{value0}}", + "stateDoneCount_one": "Готово: {{value0}}", + "stateDoneCount_other": "Готово: {{value0}}", + "stateIdleCount_one": "Остановлено: {{value0}}", + "stateIdleCount_other": "Остановлено: {{value0}}", + "stateUnverifiableCount_one": "Статус недоступен: {{value0}}", + "stateUnverifiableCount_other": "Статус недоступен: {{value0}}", + "countAgents_few": "{{count}} агента", + "countAgents_many": "{{count}} агентов", + "countShell_few": "{{count}} оболочки", + "countShell_many": "{{count}} оболочек", + "countMonitors_few": "{{count}} наблюдения", + "countMonitors_many": "{{count}} наблюдений", + "countWorkflows_few": "{{count}} процесса", + "countWorkflows_many": "{{count}} процессов", + "countTasks_few": "{{count}} задачи", + "countTasks_many": "{{count}} задач", + "headerTotal_few": "{{count}} фоновые задачи", + "headerTotal_many": "{{count}} фоновых задач", + "stateWorkingCount_few": "В работе: {{value0}}", + "stateWorkingCount_many": "В работе: {{value0}}", + "stateMonitoringCount_few": "Наблюдение: {{value0}}", + "stateMonitoringCount_many": "Наблюдение: {{value0}}", + "stateWaitingCount_few": "В ожидании: {{value0}}", + "stateWaitingCount_many": "В ожидании: {{value0}}", + "stateBlockedCount_few": "Заблокировано: {{value0}}", + "stateBlockedCount_many": "Заблокировано: {{value0}}", + "stateDoneCount_few": "Готово: {{value0}}", + "stateDoneCount_many": "Готово: {{value0}}", + "stateIdleCount_few": "Остановлено: {{value0}}", + "stateIdleCount_many": "Остановлено: {{value0}}", + "stateUnverifiableCount_few": "Статус недоступен: {{value0}}", + "stateUnverifiableCount_many": "Статус недоступен: {{value0}}" }, "jumpToLatest": "К последним сообщениям", "newRowsAnnouncement": "Пока вас не было, появились новые сообщения", @@ -19572,18 +19606,37 @@ "failed": "ошибка", "stopped": "остановлен", "unverifiable": "статус недоступен", - "workingCount": "Работают: {{value0}}", - "idleCount": "Бездействуют: {{value0}}", - "failedCount": "С ошибками: {{value0}}", - "stoppedCount": "Остановлены: {{value0}}", - "unverifiableCount": "Статус недоступен: {{value0}}" + "workingCount_one": "Работает: {{count}}", + "workingCount_other": "Работают: {{count}}", + "idleCount_one": "Бездействует: {{count}}", + "idleCount_other": "Бездействуют: {{count}}", + "failedCount_one": "С ошибками: {{count}}", + "failedCount_other": "С ошибками: {{count}}", + "stoppedCount_one": "Остановлен: {{count}}", + "stoppedCount_other": "Остановлены: {{count}}", + "unverifiableCount_one": "Статус недоступен: {{count}}", + "unverifiableCount_other": "Статус недоступен: {{count}}", + "workingCount_few": "Работают: {{count}}", + "workingCount_many": "Работают: {{count}}", + "idleCount_few": "Бездействуют: {{count}}", + "idleCount_many": "Бездействуют: {{count}}", + "failedCount_few": "С ошибками: {{count}}", + "failedCount_many": "С ошибками: {{count}}", + "stoppedCount_few": "Остановлены: {{count}}", + "stoppedCount_many": "Остановлены: {{count}}", + "unverifiableCount_few": "Статус недоступен: {{count}}", + "unverifiableCount_many": "Статус недоступен: {{count}}" }, - "startedOne": "Запущен 1 дочерний агент", - "startedN": "Запущено дочерних агентов: {{value0}}", - "ranOne": "Работал 1 дочерний агент", - "ranN": "Работало дочерних агентов: {{value0}}", "tokens": "Токенов: {{value0}}", - "unnamed": "Дочерний агент" + "unnamed": "Дочерний агент", + "started_one": "Запущен {{count}} дочерний агент", + "started_other": "Запущено {{count}} дочернего агента", + "ran_one": "Работал {{count}} дочерний агент", + "ran_other": "Работало {{count}} дочернего агента", + "started_few": "Запущено {{count}} дочерних агента", + "started_many": "Запущено {{count}} дочерних агентов", + "ran_few": "Работали {{count}} дочерних агента", + "ran_many": "Работали {{count}} дочерних агентов" }, "rewind": { "unsupported": "В этом чате нельзя вернуться к предыдущему сообщению.", diff --git a/src/renderer/src/i18n/locales/tr.json b/src/renderer/src/i18n/locales/tr.json index df7280d93d6..43b687ba3ce 100644 --- a/src/renderer/src/i18n/locales/tr.json +++ b/src/renderer/src/i18n/locales/tr.json @@ -18679,39 +18679,47 @@ "task": "Arka plan görevi", "outputFile": "Çıktı: {{value0}}", "detailsUnavailable": "Bu oturum için görev ayrıntıları kullanılamıyor.", - "countAgentsOne": "1 ajan", - "countAgentsMany": "{{value0}} ajan", - "countShellOne": "1 kabuk", - "countShellMany": "{{value0}} kabuk", "countShellCommandOne": "1 kabuk komutu", - "countMonitorsOne": "1 izleyici", - "countMonitorsMany": "{{value0}} izleyici", - "countWorkflowsOne": "1 iş akışı", - "countWorkflowsMany": "{{value0}} iş akışı", - "countTasksOne": "1 görev", - "countTasksMany": "{{value0}} görev", - "headerTotal": "{{value0}} arka plan görevi", "stateWorking": "çalışıyor", - "stateWorkingCount": "{{value0}} çalışıyor", "stateMonitoring": "izleniyor", - "stateMonitoringCount": "{{value0}} izliyor", "stateWaiting": "bekliyor", - "stateWaitingCount": "{{value0}} bekliyor", "stateBlocked": "engellendi", - "stateBlockedCount": "{{value0}} engellendi", "stateDone": "tamamlandı", - "stateDoneCount": "{{value0}} tamamlandı", "stateIdle": "durduruldu", - "stateIdleCount": "{{value0}} durdu", "stateUnverifiable": "durum bilgisi alınamıyor", - "stateUnverifiableCount": "{{value0}} tanesinin durum bilgisi alınamıyor", "reasonWaiting": "onay gerekiyor", "reasonBlocked": "başarısız oldu", "groupAgents": "Ajanlar", "groupShell": "Kabuk", "groupMonitors": "İzleyiciler", "groupWorkflows": "İş akışları", - "groupTasks": "Görevler" + "groupTasks": "Görevler", + "countAgents_one": "{{count}} ajan", + "countAgents_other": "{{count}} ajan", + "countShell_one": "{{count}} kabuk", + "countShell_other": "{{count}} kabuk", + "countMonitors_one": "{{count}} izleyici", + "countMonitors_other": "{{count}} izleyici", + "countWorkflows_one": "{{count}} iş akışı", + "countWorkflows_other": "{{count}} iş akışı", + "countTasks_one": "{{count}} görev", + "countTasks_other": "{{count}} görev", + "headerTotal_one": "{{count}} arka plan görevi", + "headerTotal_other": "{{count}} arka plan görevi", + "stateWorkingCount_one": "{{value0}} çalışıyor", + "stateWorkingCount_other": "{{value0}} çalışıyor", + "stateMonitoringCount_one": "{{value0}} izliyor", + "stateMonitoringCount_other": "{{value0}} izliyor", + "stateWaitingCount_one": "{{value0}} bekliyor", + "stateWaitingCount_other": "{{value0}} bekliyor", + "stateBlockedCount_one": "{{value0}} engellendi", + "stateBlockedCount_other": "{{value0}} engellendi", + "stateDoneCount_one": "{{value0}} tamamlandı", + "stateDoneCount_other": "{{value0}} tamamlandı", + "stateIdleCount_one": "{{value0}} durduruldu", + "stateIdleCount_other": "{{value0}} durduruldu", + "stateUnverifiableCount_one": "Durum bilgisi alınamıyor: {{value0}}", + "stateUnverifiableCount_other": "Durum bilgisi alınamıyor: {{value0}}" }, "jumpToLatest": "En son öğeye git", "newRowsAnnouncement": "Siz yokken yeni mesajlar geldi", @@ -18809,18 +18817,23 @@ "failed": "başarısız", "stopped": "durduruldu", "unverifiable": "durum bilgisi alınamıyor", - "workingCount": "{{value0}} çalışıyor", - "idleCount": "{{value0}} boşta", - "failedCount": "{{value0}} başarısız", - "stoppedCount": "{{value0}} durduruldu", - "unverifiableCount": "{{value0}} tanesinin durum bilgisi alınamıyor" + "workingCount_one": "{{count}} çalışıyor", + "workingCount_other": "{{count}} çalışıyor", + "idleCount_one": "{{count}} boşta", + "idleCount_other": "{{count}} boşta", + "failedCount_one": "{{count}} başarısız", + "failedCount_other": "{{count}} başarısız", + "stoppedCount_one": "{{count}} durduruldu", + "stoppedCount_other": "{{count}} durduruldu", + "unverifiableCount_one": "Durum bilgisi alınamıyor: {{count}}", + "unverifiableCount_other": "Durum bilgisi alınamıyor: {{count}}" }, - "startedOne": "1 alt ajan başlatıldı", - "startedN": "{{value0}} alt ajan başlatıldı", - "ranOne": "1 alt ajan çalıştırıldı", - "ranN": "{{value0}} alt ajan çalıştırıldı", "tokens": "{{value0}} token", - "unnamed": "Alt ajan" + "unnamed": "Alt ajan", + "started_one": "{{count}} alt ajan başlatıldı", + "started_other": "{{count}} alt ajan başlatıldı", + "ran_one": "{{count}} alt ajan çalıştırıldı", + "ran_other": "{{count}} alt ajan çalıştırıldı" }, "rewind": { "unsupported": "Bu sohbette önceki bir mesaja dönülemiyor.", diff --git a/src/renderer/src/i18n/locales/zh-Hant.json b/src/renderer/src/i18n/locales/zh-Hant.json index 878a8adcb76..57ee5f4d962 100644 --- a/src/renderer/src/i18n/locales/zh-Hant.json +++ b/src/renderer/src/i18n/locales/zh-Hant.json @@ -18665,39 +18665,34 @@ "task": "背景任務", "outputFile": "輸出:{{value0}}", "detailsUnavailable": "無法取得此工作階段的任務詳細資訊。", - "countAgentsOne": "1 個代理程式", - "countAgentsMany": "{{value0}} 個代理程式", - "countShellOne": "1 個 Shell", - "countShellMany": "{{value0}} 個 Shell", "countShellCommandOne": "1 個 Shell 命令", - "countMonitorsOne": "1 個監控項目", - "countMonitorsMany": "{{value0}} 個監控項目", - "countWorkflowsOne": "1 個工作流程", - "countWorkflowsMany": "{{value0}} 個工作流程", - "countTasksOne": "1 個任務", - "countTasksMany": "{{value0}} 個任務", - "headerTotal": "{{value0}} 個背景任務", "stateWorking": "工作中", - "stateWorkingCount": "{{value0}} 處理中", "stateMonitoring": "監控中", - "stateMonitoringCount": "{{value0}} 監控", "stateWaiting": "等待", - "stateWaitingCount": "{{value0}} 等待", "stateBlocked": "已受阻", - "stateBlockedCount": "{{value0}} 個受阻", "stateDone": "完成", - "stateDoneCount": "{{value0}} 完畢", "stateIdle": "已停止", - "stateIdleCount": "{{value0}} 停止了", "stateUnverifiable": "狀態不可用", - "stateUnverifiableCount": "{{value0}} 狀態不可用", "reasonWaiting": "需要核准", "reasonBlocked": "失敗", "groupAgents": "代理程式", "groupShell": "shell", "groupMonitors": "監控項目", "groupWorkflows": "工作流程", - "groupTasks": "任務" + "groupTasks": "任務", + "countAgents_other": "{{count}} 個代理程式", + "countShell_other": "{{count}} 個 Shell", + "countMonitors_other": "{{count}} 個監控項目", + "countWorkflows_other": "{{count}} 個工作流程", + "countTasks_other": "{{count}} 個任務", + "headerTotal_other": "{{count}} 個背景任務", + "stateWorkingCount_other": "處理中:{{value0}}", + "stateMonitoringCount_other": "監控中:{{value0}}", + "stateWaitingCount_other": "等待中:{{value0}}", + "stateBlockedCount_other": "受阻:{{value0}}", + "stateDoneCount_other": "已完成:{{value0}}", + "stateIdleCount_other": "已停止:{{value0}}", + "stateUnverifiableCount_other": "狀態不可用:{{value0}}" }, "jumpToLatest": "跳到最新訊息", "newRowsAnnouncement": "你離開期間有新訊息", @@ -18795,18 +18790,16 @@ "failed": "失敗", "stopped": "已停止", "unverifiable": "狀態不可用", - "workingCount": "{{value0}} 個執行中", - "idleCount": "{{value0}} 個閒置", - "failedCount": "{{value0}} 失敗", - "stoppedCount": "{{value0}} 個已停止", - "unverifiableCount": "{{value0}} 狀態不可用" + "workingCount_other": "{{count}} 個執行中", + "idleCount_other": "{{count}} 個閒置", + "failedCount_other": "{{count}} 個失敗", + "stoppedCount_other": "{{count}} 個已停止", + "unverifiableCount_other": "{{count}} 個狀態不可用" }, - "startedOne": "已啟動 1 個子代理程式", - "startedN": "已啟動 {{value0}} 個子代理程式", - "ranOne": "已執行 1 個子代理程式", - "ranN": "已執行 {{value0}} 個子代理程式", "tokens": "{{value0}} token", - "unnamed": "子代理程式" + "unnamed": "子代理程式", + "started_other": "已啟動 {{count}} 個子代理程式", + "ran_other": "已執行 {{count}} 個子代理程式" }, "rewind": { "unsupported": "此聊天無法返回到更早的訊息。", diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json index 3e8095981af..4b4ab7406a8 100644 --- a/src/renderer/src/i18n/locales/zh.json +++ b/src/renderer/src/i18n/locales/zh.json @@ -18439,39 +18439,34 @@ "task": "后台任务", "outputFile": "输出:{{value0}}", "detailsUnavailable": "此会话的任务详细信息不可用。", - "countAgentsOne": "1 个智能体", - "countAgentsMany": "{{value0}} 个智能体", - "countShellOne": "1 个 shell", - "countShellMany": "{{value0}} 个 shell", "countShellCommandOne": "1 个 shell 命令", - "countMonitorsOne": "1 个监控任务", - "countMonitorsMany": "{{value0}} 个监控任务", - "countWorkflowsOne": "1 个工作流程", - "countWorkflowsMany": "{{value0}} 个工作流程", - "countTasksOne": "1 项任务", - "countTasksMany": "{{value0}} 项任务", - "headerTotal": "{{value0}} 个后台任务", "stateWorking": "处理中", - "stateWorkingCount": "{{value0}} 处理中", "stateMonitoring": "监控", - "stateMonitoringCount": "{{value0}} 监控", "stateWaiting": "等待", - "stateWaitingCount": "{{value0}} 等待", "stateBlocked": "被阻止", - "stateBlockedCount": "{{value0}} 被阻止", "stateDone": "完毕", - "stateDoneCount": "{{value0}} 完毕", "stateIdle": "已停止", - "stateIdleCount": "{{value0}} 已停止", "stateUnverifiable": "状态不可用", - "stateUnverifiableCount": "{{value0}} 状态不可用", "reasonWaiting": "需要批准", "reasonBlocked": "失败", "groupAgents": "智能体", "groupShell": "Shell", "groupMonitors": "监控", "groupWorkflows": "工作流程", - "groupTasks": "任务" + "groupTasks": "任务", + "countAgents_other": "{{count}} 个智能体", + "countShell_other": "{{count}} 个 shell", + "countMonitors_other": "{{count}} 个监控任务", + "countWorkflows_other": "{{count}} 个工作流程", + "countTasks_other": "{{count}} 项任务", + "headerTotal_other": "{{count}} 个后台任务", + "stateWorkingCount_other": "处理中:{{value0}}", + "stateMonitoringCount_other": "监控中:{{value0}}", + "stateWaitingCount_other": "等待中:{{value0}}", + "stateBlockedCount_other": "受阻:{{value0}}", + "stateDoneCount_other": "已完成:{{value0}}", + "stateIdleCount_other": "已停止:{{value0}}", + "stateUnverifiableCount_other": "状态不可用:{{value0}}" }, "railLabel": "您的留言", "railImageMessage": "图片附件", @@ -18490,18 +18485,16 @@ "failed": "失败的", "stopped": "停止了", "unverifiable": "状态不可用", - "workingCount": "{{value0}} 工作", - "idleCount": "{{value0}} 空闲", - "failedCount": "{{value0}} 失败", - "stoppedCount": "{{value0}} 已停止", - "unverifiableCount": "{{value0}} 状态不可用" + "workingCount_other": "{{count}} 个处理中", + "idleCount_other": "{{count}} 个空闲", + "failedCount_other": "{{count}} 个失败", + "stoppedCount_other": "{{count}} 个已停止", + "unverifiableCount_other": "{{count}} 个状态不可用" }, - "startedOne": "启动 1 个子智能体", - "startedN": "启动 {{value0}} 个子智能体", - "ranOne": "已运行 1 个子智能体", - "ranN": "已运行 {{value0}} 个子智能体", "tokens": "{{value0}} 代币", - "unnamed": "子智能体" + "unnamed": "子智能体", + "started_other": "已启动 {{count}} 个子智能体", + "ran_other": "已运行 {{count}} 个子智能体" }, "drop": { "messageTitle": "拖放以附加到此消息", diff --git a/src/shared/background-task-copy.ts b/src/shared/background-task-copy.ts index 7217d0fbf7c..66f736ec390 100644 --- a/src/shared/background-task-copy.ts +++ b/src/shared/background-task-copy.ts @@ -1,5 +1,7 @@ // Share whole English translation pieces for desktop/mobile roster wording. +import { englishCopyText, type CopyValues, type CountedCopy } from './counted-copy-english' + export const BACKGROUND_TASK_COPY = { monitoring: 'Monitoring background tasks', stop: 'Stop', @@ -11,34 +13,32 @@ export const BACKGROUND_TASK_COPY = { monitor: 'Background monitor', task: 'Background task', detailsUnavailable: 'Task details are unavailable for this session.', - countAgentsOne: '1 agent', - countAgentsMany: '{{value0}} agents', - countShellOne: '1 shell', - countShellMany: '{{value0}} shells', + countAgents: { one: '{{count}} agent', other: '{{count}} agents' }, + countShell: { one: '{{count}} shell', other: '{{count}} shells' }, countShellCommandOne: '1 shell command', - countMonitorsOne: '1 monitor', - countMonitorsMany: '{{value0}} monitors', - countWorkflowsOne: '1 workflow', - countWorkflowsMany: '{{value0}} workflows', - countTasksOne: '1 task', - countTasksMany: '{{value0}} tasks', - headerTotal: '{{value0}} background tasks', + countMonitors: { one: '{{count}} monitor', other: '{{count}} monitors' }, + countWorkflows: { one: '{{count}} workflow', other: '{{count}} workflows' }, + countTasks: { one: '{{count}} task', other: '{{count}} tasks' }, + headerTotal: { one: '{{count}} background task', other: '{{count}} background tasks' }, stateWorking: 'working', - stateWorkingCount: '{{value0}} working', + stateWorkingCount: { one: '{{value0}} working', other: '{{value0}} working' }, stateMonitoring: 'monitoring', - stateMonitoringCount: '{{value0}} monitoring', + stateMonitoringCount: { one: '{{value0}} monitoring', other: '{{value0}} monitoring' }, stateWaiting: 'waiting', - stateWaitingCount: '{{value0}} waiting', + stateWaitingCount: { one: '{{value0}} waiting', other: '{{value0}} waiting' }, stateBlocked: 'blocked', - stateBlockedCount: '{{value0}} blocked', + stateBlockedCount: { one: '{{value0}} blocked', other: '{{value0}} blocked' }, stateDone: 'done', - stateDoneCount: '{{value0}} done', + stateDoneCount: { one: '{{value0}} done', other: '{{value0}} done' }, stateIdle: 'stopped', - stateIdleCount: '{{value0}} stopped', + stateIdleCount: { one: '{{value0}} stopped', other: '{{value0}} stopped' }, // Settled unknown or out of contact: claims neither an exit nor a coming update. stateUnverifiable: 'status unavailable', // After a count, "status unavailable" needs a "with". - stateUnverifiableCount: '{{value0}} with status unavailable', + stateUnverifiableCount: { + one: '{{value0}} with status unavailable', + other: '{{value0}} with status unavailable' + }, reasonWaiting: 'needs approval', reasonBlocked: 'failed', groupAgents: 'Agents', @@ -46,14 +46,14 @@ export const BACKGROUND_TASK_COPY = { groupMonitors: 'Monitors', groupWorkflows: 'Workflows', groupTasks: 'Tasks' -} as const +} as const satisfies Record export type BackgroundTaskCopyId = keyof typeof BACKGROUND_TASK_COPY -/** What a piece's `{{value0}}` stands for: a count, or a phrase already said. */ -export type BackgroundTaskCopyValues = { value0: string | number } +/** Counted pieces need `count`; `value0` is the counted phrase or number the state describes. */ +export type BackgroundTaskCopyValues = CopyValues -/** One piece in the reader's language, its placeholder filled. */ +/** One piece in the reader's language, its placeholders filled. */ export type BackgroundTaskSay = ( id: BackgroundTaskCopyId, values?: BackgroundTaskCopyValues @@ -61,7 +61,4 @@ export type BackgroundTaskSay = ( /** Any surface without translations. */ export const sayBackgroundTaskEnglish: BackgroundTaskSay = (id, values) => - values === undefined - ? BACKGROUND_TASK_COPY[id] - : // A replacer function, so a task's own `$&` is never read as a pattern. - BACKGROUND_TASK_COPY[id].replaceAll('{{value0}}', () => String(values.value0)) + englishCopyText(BACKGROUND_TASK_COPY[id], values) diff --git a/src/shared/background-task-header-content.ts b/src/shared/background-task-header-content.ts index 6753a9efe02..f357f706e76 100644 --- a/src/shared/background-task-header-content.ts +++ b/src/shared/background-task-header-content.ts @@ -20,18 +20,17 @@ type RunState = AgentSessionBackgroundTaskRunState export const NARROW_BACKGROUND_TASKS_STRIP_REM = 24 function kindCountLabel(kind: TaskKind, count: number, say: BackgroundTaskSay): string { - const value = { value0: count } switch (kind) { case 'agent': - return count === 1 ? say('countAgentsOne') : say('countAgentsMany', value) + return say('countAgents', { count }) case 'command': - return count === 1 ? say('countShellOne') : say('countShellMany', value) + return say('countShell', { count }) case 'monitor': - return count === 1 ? say('countMonitorsOne') : say('countMonitorsMany', value) + return say('countMonitors', { count }) case 'workflow': - return count === 1 ? say('countWorkflowsOne') : say('countWorkflowsMany', value) + return say('countWorkflows', { count }) case 'unknown': - return count === 1 ? say('countTasksOne') : say('countTasksMany', value) + return say('countTasks', { count }) } } @@ -76,7 +75,7 @@ export function backgroundTasksHeaderContent( } if (groups.length > HEADER_SEGMENT_CAP || (options.narrow && groups.length > 1)) { return { - segments: [{ text: say('headerTotal', { value0: all.length }), kind: null }], + segments: [{ text: say('headerTotal', { count: all.length }), kind: null }], detail: null } } @@ -99,9 +98,10 @@ export function backgroundTasksHeaderContent( segments: [ { text: backgroundTaskCountedState( - kindCountLabel(group.kind, count, say), + count, uniformState, - say + say, + kindCountLabel(group.kind, count, say) ), kind: group.kind } diff --git a/src/shared/background-task-roster.test.ts b/src/shared/background-task-roster.test.ts index 57a9095b0dc..50deed85ea3 100644 --- a/src/shared/background-task-roster.test.ts +++ b/src/shared/background-task-roster.test.ts @@ -20,9 +20,10 @@ const buildBackgroundTaskGroups = ( settled: AgentSessionBackgroundTask[] ) => buildGroups(tasks, settled, say) const backgroundTaskCountedState = ( - counted: string | number, - state: Parameters[1] -) => countedState(counted, state, say) + count: number, + state: Parameters[1], + subject?: string +) => countedState(count, state, say, subject) const resolveBackgroundTaskName = (task: AgentSessionBackgroundTask) => resolveName(task, say) const backgroundTasksHeaderContent = ( groups: BackgroundTaskGroup[], @@ -218,11 +219,11 @@ describe('buildBackgroundTaskGroups', () => { describe('backgroundTaskCountedState', () => { it('words a count with each state as one sentence', () => { - expect(backgroundTaskCountedState('2 agents', 'working')).toBe('2 agents working') - expect(backgroundTaskCountedState('2 agents', 'monitoring')).toBe('2 agents monitoring') - expect(backgroundTaskCountedState('2 agents', 'waiting')).toBe('2 agents waiting') - expect(backgroundTaskCountedState('2 agents', 'blocked')).toBe('2 agents blocked') - expect(backgroundTaskCountedState('2 agents', 'done')).toBe('2 agents done') + expect(backgroundTaskCountedState(2, 'working', '2 agents')).toBe('2 agents working') + expect(backgroundTaskCountedState(2, 'monitoring', '2 agents')).toBe('2 agents monitoring') + expect(backgroundTaskCountedState(2, 'waiting', '2 agents')).toBe('2 agents waiting') + expect(backgroundTaskCountedState(2, 'blocked', '2 agents')).toBe('2 agents blocked') + expect(backgroundTaskCountedState(2, 'done', '2 agents')).toBe('2 agents done') expect(backgroundTaskCountedState(3, 'idle')).toBe('3 stopped') expect(backgroundTaskCountedState(3, 'unverifiable')).toBe('3 with status unavailable') }) diff --git a/src/shared/background-task-roster.ts b/src/shared/background-task-roster.ts index c4434df92de..0120c995061 100644 --- a/src/shared/background-task-roster.ts +++ b/src/shared/background-task-roster.ts @@ -142,13 +142,14 @@ export function backgroundTaskStateReason(state: RunState, say: BackgroundTaskSa } } -/** Translate count/state as a whole sentence so languages can agree their forms. */ +/** Translate count/state as a whole sentence so languages can agree their forms; `subject` ("2 agents") stands in for the bare count. */ export function backgroundTaskCountedState( - counted: string | number, + count: number, state: RunState, - say: BackgroundTaskSay + say: BackgroundTaskSay, + subject?: string ): string { - const value = { value0: counted } + const value = { count, value0: subject ?? count } switch (state) { case 'working': return say('stateWorkingCount', value) diff --git a/src/shared/counted-copy-english.ts b/src/shared/counted-copy-english.ts new file mode 100644 index 00000000000..4a25a877bd3 --- /dev/null +++ b/src/shared/counted-copy-english.ts @@ -0,0 +1,19 @@ +// English rendering of shared copy tables whose counted phrases carry one/other forms. + +/** A counted phrase; translated surfaces pick the reader's CLDR form from `count`. */ +export type CountedCopy = { readonly one: string; readonly other: string } + +/** `{{value0}}` is a phrase already said or a number; `{{count}}` selects and fills the plural form. */ +export type CopyValues = { value0?: string | number; count?: number } + +export function englishCopyText(entry: string | CountedCopy, values?: CopyValues): string { + const text = typeof entry === 'string' ? entry : values?.count === 1 ? entry.one : entry.other + if (values === undefined) { + return text + } + // A replacer function, so a task's own `$&` is never read as a pattern. + return text.replaceAll(/\{\{(value0|count)\}\}/g, (placeholder, name) => { + const value = name === 'count' ? values.count : values.value0 + return value === undefined ? placeholder : String(value) + }) +} diff --git a/src/shared/native-chat/transcript/native-chat-subagent-group-header.ts b/src/shared/native-chat/transcript/native-chat-subagent-group-header.ts index d6cee1c2bd6..6fba63590a0 100644 --- a/src/shared/native-chat/transcript/native-chat-subagent-group-header.ts +++ b/src/shared/native-chat/transcript/native-chat-subagent-group-header.ts @@ -2,6 +2,7 @@ import { normalizeSubagentState, summarizeSubagentGroup } from './native-chat-subagent-summary' import type { NativeChatSubagentEntry, NativeChatSubagentState } from '../../native-chat-types' +import { englishCopyText, type CopyValues, type CountedCopy } from '../../counted-copy-english' export const NATIVE_CHAT_SUBAGENT_GROUP_COPY = { stateCompleted: 'completed', @@ -10,30 +11,30 @@ export const NATIVE_CHAT_SUBAGENT_GROUP_COPY = { stateFailed: 'failed', stateStopped: 'stopped', stateUnverifiable: 'status unavailable', - stateWorkingCount: '{{value0}} working', - stateIdleCount: '{{value0}} idle', - stateFailedCount: '{{value0}} failed', - stateStoppedCount: '{{value0}} stopped', - stateUnverifiableCount: '{{value0}} with status unavailable', - startedOne: 'Kicked off 1 subagent', - startedN: 'Kicked off {{value0}} subagents', - ranOne: 'Ran 1 subagent', - ranN: 'Ran {{value0}} subagents', + stateWorkingCount: { one: '{{count}} working', other: '{{count}} working' }, + stateIdleCount: { one: '{{count}} idle', other: '{{count}} idle' }, + stateFailedCount: { one: '{{count}} failed', other: '{{count}} failed' }, + stateStoppedCount: { one: '{{count}} stopped', other: '{{count}} stopped' }, + stateUnverifiableCount: { + one: '{{count}} with status unavailable', + other: '{{count}} with status unavailable' + }, + started: { one: 'Kicked off {{count}} subagent', other: 'Kicked off {{count}} subagents' }, + ran: { one: 'Ran {{count}} subagent', other: 'Ran {{count}} subagents' }, tokens: '{{value0}} tokens' -} as const +} as const satisfies Record export type NativeChatSubagentGroupCopyId = keyof typeof NATIVE_CHAT_SUBAGENT_GROUP_COPY +/** Counted pieces need `count`; `tokens` takes its formatted amount as `value0`. */ export type NativeChatSubagentGroupSay = ( id: NativeChatSubagentGroupCopyId, - values?: { value0: string | number } + values?: CopyValues ) => string /** Any surface without translations. */ export const sayNativeChatSubagentGroupEnglish: NativeChatSubagentGroupSay = (id, values) => - values === undefined - ? NATIVE_CHAT_SUBAGENT_GROUP_COPY[id] - : NATIVE_CHAT_SUBAGENT_GROUP_COPY[id].replaceAll('{{value0}}', () => String(values.value0)) + englishCopyText(NATIVE_CHAT_SUBAGENT_GROUP_COPY[id], values) /** Compact token counts: the row shows scale, not an exact ledger. */ export function formatSubagentTokens(tokens: number): string { @@ -69,7 +70,7 @@ export function subagentStateLabel( return say('stateUnverifiable') } } - const value = { value0: count } + const value = { count } switch (state) { case 'working': return say('stateWorkingCount', value) @@ -107,13 +108,7 @@ export function nativeChatSubagentGroupHeader( ): NativeChatSubagentGroupHeader { const summary = summarizeSubagentGroup(agents) const working = summary.working > 0 - const headline = working - ? summary.total === 1 - ? say('startedOne') - : say('startedN', { value0: summary.total }) - : summary.total === 1 - ? say('ranOne') - : say('ranN', { value0: summary.total }) + const headline = say(working ? 'started' : 'ran', { count: summary.total }) const verdictState: NativeChatSubagentState = working ? 'working' : (summary.settledState ?? 'idle')