From 42693d2a21f129d431bf216393cc4945ffa2ed62 Mon Sep 17 00:00:00 2001 From: Neonforge <48338160+Neonforge98@users.noreply.github.com> Date: Wed, 29 Jul 2026 23:24:10 -0700 Subject: [PATCH 1/5] fix(team-inbox): register orphaned IPC commands team_inbox_list_page/unread_count/mark_read/mark_all_read/mark_unread have existed in the project-management crate and been invoked by the frontend since the feature was re-added after the #521 revert, but the handler_list.inc registration never came back with it. Every Team Inbox IPC call has been rejecting at the Tauri boundary as an unknown command. --- src-tauri/src/commands/handler_list.inc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src-tauri/src/commands/handler_list.inc b/src-tauri/src/commands/handler_list.inc index facae3a5f..7663db9c8 100644 --- a/src-tauri/src/commands/handler_list.inc +++ b/src-tauri/src/commands/handler_list.inc @@ -594,6 +594,12 @@ project_management::projects::commands::project_allocate_work_item_id, project_management::projects::commands::work_item_allocate_standalone_id, project_management::projects::commands::project_batch_delete_work_items, project_management::projects::commands::project_batch_update_work_items, +// Team Inbox read model (viewer member IDs are explicit at the IPC boundary). +project_management::team_inbox::commands::team_inbox_list_page, +project_management::team_inbox::commands::team_inbox_unread_count, +project_management::team_inbox::commands::team_inbox_mark_read, +project_management::team_inbox::commands::team_inbox_mark_all_read, +project_management::team_inbox::commands::team_inbox_mark_unread, project_management::projects::commands::project_list_routines, project_management::projects::commands::project_read_routine, project_management::projects::commands::project_upsert_routine, From 0ae010560206b0b293175b6dd5a8813e0ebd45f0 Mon Sep 17 00:00:00 2001 From: Neonforge <48338160+Neonforge98@users.noreply.github.com> Date: Wed, 29 Jul 2026 23:26:51 -0700 Subject: [PATCH 2/5] fix(team-inbox): guard read-state idempotency in the coordinator The readAt check before calling markRead/markUnread lived only in TeamInboxView, so any other caller could double-fire a mutation on an item that's already in the target state. The coordinator's own optimistic patch already recomputes unread deltas from live cache state on each call, so client-side counts stayed safe, but a redundant call still meant an unnecessary local/cloud round trip on every double click. Move the guard into setReadState, checked against the live cache rather than the caller's (possibly stale) item snapshot, so it holds regardless of caller. --- .../MainApp/TeamInbox/teamInboxCoordinator.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/modules/MainApp/TeamInbox/teamInboxCoordinator.ts b/src/modules/MainApp/TeamInbox/teamInboxCoordinator.ts index adc50adbb..f854932da 100644 --- a/src/modules/MainApp/TeamInbox/teamInboxCoordinator.ts +++ b/src/modules/MainApp/TeamInbox/teamInboxCoordinator.ts @@ -606,6 +606,18 @@ export class TeamInboxCoordinator { ): Promise { const runtime = this.ensureScope(store, scope.key); const itemKey = getTeamInboxItemKey(item); + // Idempotency lives here, not just at the call site, so any caller — + // including future ones — can't double-fire a read/unread mutation and + // send a redundant network round-trip that risks drifting unreadCount. + // Check the live cache rather than the passed-in `item`, which may be a + // stale snapshot from the caller's render. + const currentItem = store + .get(teamInboxCacheAtom) + .items.find((candidate) => getTeamInboxItemKey(candidate) === itemKey); + const currentlyRead = (currentItem ?? item).readAt !== null; + if (currentlyRead === read) { + return Promise.resolve(); + } const epoch = ++runtime.mutationEpoch; runtime.mutationEpochByItem.set(itemKey, epoch); this.patchReadState( From 2ea445c127e11e4dd93c414e983c6cd81030e422 Mon Sep 17 00:00:00 2001 From: Neonforge <48338160+Neonforge98@users.noreply.github.com> Date: Wed, 29 Jul 2026 23:29:28 -0700 Subject: [PATCH 3/5] fix(team-inbox): revert and resync optimistic read state on failure The coordinator already reverts an item's own optimistic readAt on a failed mutation, but nothing forced a resync against server truth afterwards, so a failure racing with another concurrent update could leave the list or badge quietly drifted. Extract the success/failure/resync orchestration out of TeamInboxView into a pure, framework-free helper (repo policy is no .tsx unit tests) and wire handleSelect/handleMarkRead/handleMarkUnread through it. Covers the success path, failure with revert already handled by the coordinator plus resync trigger, and resync failure not masking the original mutation error. --- .../MainApp/TeamInbox/TeamInboxView.tsx | 49 ++++++---- .../teamInboxReadTransitions.test.ts | 92 +++++++++++++++++++ .../TeamInbox/teamInboxReadTransitions.ts | 53 +++++++++++ 3 files changed, 176 insertions(+), 18 deletions(-) create mode 100644 src/modules/MainApp/TeamInbox/__tests__/teamInboxReadTransitions.test.ts create mode 100644 src/modules/MainApp/TeamInbox/teamInboxReadTransitions.ts diff --git a/src/modules/MainApp/TeamInbox/TeamInboxView.tsx b/src/modules/MainApp/TeamInbox/TeamInboxView.tsx index 40fc601e9..c40028c79 100644 --- a/src/modules/MainApp/TeamInbox/TeamInboxView.tsx +++ b/src/modules/MainApp/TeamInbox/TeamInboxView.tsx @@ -30,6 +30,7 @@ import { selectTeamInboxItems, toTeamInboxNavigationIntent, } from "./domain"; +import { performTeamInboxReadTransition } from "./teamInboxReadTransitions"; export interface TeamInboxViewProps { dataSource?: TeamInboxDataSource; @@ -210,32 +211,44 @@ const TeamInboxView: React.FC = ({ const handleSelect = (item: TeamInboxItem) => { setRequestedItemId(getTeamInboxItemKey(item)); if (item.readAt !== null) return; - void dataSource.markRead?.(item).catch(() => { - setLoadState({ - status: "error", - message: t("teamInbox.errors.markRead"), - }); - }); + void performTeamInboxReadTransition("read", item, dataSource).then( + (result) => { + if (!result.ok) { + setLoadState({ + status: "error", + message: t("teamInbox.errors.markRead"), + }); + } + } + ); }; const handleMarkRead = (item: TeamInboxItem) => { if (item.readAt !== null) return; - void dataSource.markRead?.(item).catch(() => { - setLoadState({ - status: "error", - message: t("teamInbox.errors.markRead"), - }); - }); + void performTeamInboxReadTransition("read", item, dataSource).then( + (result) => { + if (!result.ok) { + setLoadState({ + status: "error", + message: t("teamInbox.errors.markRead"), + }); + } + } + ); }; const handleMarkUnread = (item: TeamInboxItem) => { if (item.readAt === null) return; - void dataSource.markUnread?.(item).catch(() => { - setLoadState({ - status: "error", - message: t("teamInbox.errors.markUnread"), - }); - }); + void performTeamInboxReadTransition("unread", item, dataSource).then( + (result) => { + if (!result.ok) { + setLoadState({ + status: "error", + message: t("teamInbox.errors.markUnread"), + }); + } + } + ); }; const handleMarkAllRead = () => { diff --git a/src/modules/MainApp/TeamInbox/__tests__/teamInboxReadTransitions.test.ts b/src/modules/MainApp/TeamInbox/__tests__/teamInboxReadTransitions.test.ts new file mode 100644 index 000000000..339e9ddf4 --- /dev/null +++ b/src/modules/MainApp/TeamInbox/__tests__/teamInboxReadTransitions.test.ts @@ -0,0 +1,92 @@ +import { describe, expect, it, vi } from "vitest"; + +import type { TeamInboxItem } from "../domain"; +import { performTeamInboxReadTransition } from "../teamInboxReadTransitions"; + +function assignedItem(readAt: string | null): TeamInboxItem { + return { + kind: "assigned_work_item", + id: "wi-1", + occurredAt: "2026-07-29T00:00:00.000Z", + readAt, + workItem: { + id: "wi-1", + title: "Ship the thing", + status: "todo", + priority: "medium", + }, + } as unknown as TeamInboxItem; +} + +describe("performTeamInboxReadTransition", () => { + it("resolves ok without touching refresh on the success path", async () => { + const markRead = vi.fn().mockResolvedValue(undefined); + const refresh = vi.fn().mockResolvedValue(undefined); + + const result = await performTeamInboxReadTransition( + "read", + assignedItem(null), + { markRead, refresh } + ); + + expect(result).toEqual({ ok: true, resyncStarted: false }); + expect(markRead).toHaveBeenCalledTimes(1); + expect(refresh).not.toHaveBeenCalled(); + }); + + it("triggers a data source refresh when the mutation rejects", async () => { + const markRead = vi.fn().mockRejectedValue(new Error("network down")); + const refresh = vi.fn().mockResolvedValue(undefined); + + const result = await performTeamInboxReadTransition( + "read", + assignedItem(null), + { markRead, refresh } + ); + + expect(result).toEqual({ ok: false, resyncStarted: true }); + expect(refresh).toHaveBeenCalledTimes(1); + }); + + it("still reports resyncStarted even if the refresh itself fails", async () => { + const markUnread = vi + .fn() + .mockRejectedValue(new Error("no longer visible")); + const refresh = vi.fn().mockRejectedValue(new Error("offline")); + + const result = await performTeamInboxReadTransition( + "unread", + assignedItem("2026-07-28T00:00:00.000Z"), + { markUnread, refresh } + ); + + expect(result).toEqual({ ok: false, resyncStarted: true }); + expect(markUnread).toHaveBeenCalledTimes(1); + expect(refresh).toHaveBeenCalledTimes(1); + }); + + it("does not attempt a resync when the data source has no refresh", async () => { + const markRead = vi.fn().mockRejectedValue(new Error("boom")); + + const result = await performTeamInboxReadTransition( + "read", + assignedItem(null), + { markRead } + ); + + expect(result).toEqual({ ok: false, resyncStarted: false }); + }); + + it("is a no-op when the data source has no mutator for the requested kind", async () => { + const refresh = vi.fn(); + + const result = await performTeamInboxReadTransition( + "unread", + assignedItem(null), + { refresh } + ); + + expect(result).toEqual({ ok: true, resyncStarted: false }); + expect(refresh).not.toHaveBeenCalled(); + }); +}); diff --git a/src/modules/MainApp/TeamInbox/teamInboxReadTransitions.ts b/src/modules/MainApp/TeamInbox/teamInboxReadTransitions.ts new file mode 100644 index 000000000..4194bc25e --- /dev/null +++ b/src/modules/MainApp/TeamInbox/teamInboxReadTransitions.ts @@ -0,0 +1,53 @@ +import type { TeamInboxDataSource, TeamInboxItem } from "./domain"; + +export type TeamInboxReadTransitionKind = "read" | "unread"; + +export interface TeamInboxReadTransitionResult { + ok: boolean; + /** + * Only meaningful when `ok` is false. `true` means a resync against the + * data source's server-truth state was kicked off after the failed + * optimistic mutation (regardless of whether that resync itself + * succeeded) so the caller knows a follow-up render is coming. + */ + resyncStarted: boolean; +} + +/** + * Drives a single Team Inbox mark-read / mark-unread mutation. + * + * The data source (`teamInboxCoordinator`) already reverts its own + * optimistic item mutation when the underlying local/cloud call rejects. + * This helper adds the second half of that contract: it also triggers a + * `refresh()` on failure so the list and unread badge resync against + * server truth instead of relying solely on the coordinator's local + * revert, which guards against drift if the revert races with another + * concurrent update (e.g. a mutation from another client). It is kept + * framework-free (no React) so it can be unit tested directly — repo + * policy is not to unit test `.tsx` files. + */ +export async function performTeamInboxReadTransition( + kind: TeamInboxReadTransitionKind, + item: TeamInboxItem, + dataSource: Pick +): Promise { + const mutate = kind === "read" ? dataSource.markRead : dataSource.markUnread; + if (!mutate) return { ok: true, resyncStarted: false }; + + try { + await mutate(item); + return { ok: true, resyncStarted: false }; + } catch { + if (!dataSource.refresh) return { ok: false, resyncStarted: false }; + // Best-effort: the resync's own outcome doesn't change the fact that + // the mutation itself failed and the caller still needs to surface an + // error — it only affects whether a follow-up render is coming. + try { + await dataSource.refresh(); + } catch { + // Swallow: the refresh failure is secondary to the mutation failure + // already being reported via `ok: false`. + } + return { ok: false, resyncStarted: true }; + } +} From fc2600262e26705b895193aad699788e079caf09 Mon Sep 17 00:00:00 2001 From: Neonforge <48338160+Neonforge98@users.noreply.github.com> Date: Wed, 29 Jul 2026 23:32:07 -0700 Subject: [PATCH 4/5] fix(team-inbox): translate the unread sidebar badge aria-label The unread-count badge's aria-label was a hardcoded English template literal, so screen reader users on every non-English locale heard English. Thread the existing teamInbox.unreadCount translation (it was already in common.json, just unused here) down through usePinnedMenuItems into buildPinnedMenuItems, with the old string kept only as a fallback for callers that don't supply it. --- .../sidebarMenuCollections.ts | 9 +++++ .../workstationSidebarMenuItems.test.ts | 40 +++++++++++++++++++ .../workstationSidebarMenuItems.tsx | 6 ++- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/scaffold/NavigationSidebar/connectors/WorkstationSidebarConnector/sidebarMenuCollections.ts b/src/scaffold/NavigationSidebar/connectors/WorkstationSidebarConnector/sidebarMenuCollections.ts index 21dd54714..e1c6ca6af 100644 --- a/src/scaffold/NavigationSidebar/connectors/WorkstationSidebarConnector/sidebarMenuCollections.ts +++ b/src/scaffold/NavigationSidebar/connectors/WorkstationSidebarConnector/sidebarMenuCollections.ts @@ -51,6 +51,13 @@ export function usePinnedMenuItems({ workItemDestinations, t, }: UsePinnedMenuItemsParams): UsePinnedMenuItemsResult { + const teamInboxUnreadAriaLabel = useMemo( + () => + teamInboxUnreadCount + ? t("common:teamInbox.unreadCount", { count: teamInboxUnreadCount }) + : undefined, + [t, teamInboxUnreadCount] + ); const sessionPinnedMenuItems = useMemo( () => buildPinnedMenuItems({ @@ -63,6 +70,7 @@ export function usePinnedMenuItems({ runtimeLabel, teamInboxLabel, teamInboxUnreadCount, + teamInboxUnreadAriaLabel, }), [ kanbanLabel, @@ -70,6 +78,7 @@ export function usePinnedMenuItems({ runtimeLabel, teamInboxLabel, teamInboxUnreadCount, + teamInboxUnreadAriaLabel, workItemDestinations, t, ] diff --git a/src/scaffold/NavigationSidebar/connectors/workstationSidebarMenuItems.test.ts b/src/scaffold/NavigationSidebar/connectors/workstationSidebarMenuItems.test.ts index d65b85290..af28a7a2a 100644 --- a/src/scaffold/NavigationSidebar/connectors/workstationSidebarMenuItems.test.ts +++ b/src/scaffold/NavigationSidebar/connectors/workstationSidebarMenuItems.test.ts @@ -1,3 +1,4 @@ +import type React from "react"; import { describe, expect, it } from "vitest"; import { @@ -53,6 +54,45 @@ describe("buildPinnedMenuItems", () => { expect(items[0]?.openContextMenuOnSelectedClick).toBeUndefined(); }); + it("translates the unread badge aria-label when one is supplied", () => { + const items = buildPinnedMenuItems({ + newSessionLabel: "New Session", + newSessionShortcut: "⌘N", + workItemsLabel: "Work Items", + workItemDestinations: [], + kanbanLabel: "Kanban", + kanbanShortcut: "⌘O", + runtimeLabel: "Runtime", + teamInboxLabel: "Team Inbox", + teamInboxUnreadCount: 3, + teamInboxUnreadAriaLabel: "3 no leídos", + }); + + const badge = items[3]?.trailingElement as React.ReactElement<{ + "aria-label"?: string; + }>; + expect(badge?.props["aria-label"]).toBe("3 no leídos"); + }); + + it("falls back to an English badge aria-label when none is supplied", () => { + const items = buildPinnedMenuItems({ + newSessionLabel: "New Session", + newSessionShortcut: "⌘N", + workItemsLabel: "Work Items", + workItemDestinations: [], + kanbanLabel: "Kanban", + kanbanShortcut: "⌘O", + runtimeLabel: "Runtime", + teamInboxLabel: "Team Inbox", + teamInboxUnreadCount: 5, + }); + + const badge = items[3]?.trailingElement as React.ReactElement<{ + "aria-label"?: string; + }>; + expect(badge?.props["aria-label"]).toBe("5 unread"); + }); + it("keeps destination navigation available inside the Work Items layer", () => { const items = buildProjectsPinnedMenuItems({ createProjectLabel: "Create Project", diff --git a/src/scaffold/NavigationSidebar/connectors/workstationSidebarMenuItems.tsx b/src/scaffold/NavigationSidebar/connectors/workstationSidebarMenuItems.tsx index afb89c26d..7ec57ad16 100644 --- a/src/scaffold/NavigationSidebar/connectors/workstationSidebarMenuItems.tsx +++ b/src/scaffold/NavigationSidebar/connectors/workstationSidebarMenuItems.tsx @@ -38,6 +38,7 @@ interface BuildPinnedMenuItemsParams { runtimeLabel: string; teamInboxLabel: string; teamInboxUnreadCount?: number; + teamInboxUnreadAriaLabel?: string; } interface BuildProjectsPinnedMenuItemsParams { @@ -57,6 +58,7 @@ export function buildPinnedMenuItems({ runtimeLabel, teamInboxLabel, teamInboxUnreadCount = 0, + teamInboxUnreadAriaLabel, }: BuildPinnedMenuItemsParams): NavigationMenuItem[] { return [ { @@ -94,7 +96,9 @@ export function buildPinnedMenuItems({ trailingElement: teamInboxUnreadCount > 0 ? ( {teamInboxUnreadCount > 99 ? "99+" : teamInboxUnreadCount} From 110519b89532fddbfeb3796fcd9b1da0e382e7b8 Mon Sep 17 00:00:00 2001 From: Neonforge <48338160+Neonforge98@users.noreply.github.com> Date: Wed, 29 Jul 2026 23:35:40 -0700 Subject: [PATCH 5/5] feat(team-inbox): add teamInbox namespace to remaining locales teamInbox only existed in en and zh common.json; every other shipped locale (de, es, fr, ja, ko, pl, pt, ru, tr, vi, zh-Hant) fell back to raw English for the whole feature. Add the namespace to all 11, mirroring en's key structure exactly (including the _one/_other plural key pairs, per this file's existing convention across other namespaces). --- src/i18n/locales/de/common.json | 158 ++++++++++++++++++++++++++ src/i18n/locales/es/common.json | 158 ++++++++++++++++++++++++++ src/i18n/locales/fr/common.json | 158 ++++++++++++++++++++++++++ src/i18n/locales/ja/common.json | 156 ++++++++++++++++++++++++++ src/i18n/locales/ko/common.json | 156 ++++++++++++++++++++++++++ src/i18n/locales/pl/common.json | 162 +++++++++++++++++++++++++++ src/i18n/locales/pt/common.json | 158 ++++++++++++++++++++++++++ src/i18n/locales/ru/common.json | 162 +++++++++++++++++++++++++++ src/i18n/locales/tr/common.json | 158 ++++++++++++++++++++++++++ src/i18n/locales/vi/common.json | 156 ++++++++++++++++++++++++++ src/i18n/locales/zh-Hant/common.json | 156 ++++++++++++++++++++++++++ 11 files changed, 1738 insertions(+) diff --git a/src/i18n/locales/de/common.json b/src/i18n/locales/de/common.json index 07ec56f99..c30d9c64c 100644 --- a/src/i18n/locales/de/common.json +++ b/src/i18n/locales/de/common.json @@ -1,4 +1,162 @@ { + "teamInbox": { + "title": "Team-Posteingang", + "listLabel": "Liste des Team-Posteingangs", + "itemsLabel": "Einträge im Team-Posteingang", + "unreadCount": "{{count}} ungelesen", + "allRead": "Alles gelesen", + "loadMore": "Mehr laden", + "filters": { + "all": "Alle", + "mentions": "Erwähnungen", + "assigned": "Zugewiesen" + }, + "status": { + "read": "Gelesen", + "unread": "Ungelesen" + }, + "row": { + "assignedSummary": "{{status}} · {{priority}}", + "ariaLabel": "{{title}}, {{status}}" + }, + "search": { + "placeholder": "Posteingang durchsuchen", + "ariaLabel": "Team-Posteingang durchsuchen" + }, + "groups": { + "today": "Heute", + "yesterday": "Gestern", + "thisWeek": "Diese Woche", + "earlier": "Früher" + }, + "empty": { + "title": "Noch nichts hier", + "subtitle": "Erwähnungen und zugewiesene Arbeitselemente werden hier angezeigt.", + "selectTitle": "Ein Element auswählen", + "selectSubtitle": "Kommentarkontext oder Details des Arbeitselements ansehen.", + "mentions": { + "title": "Keine Erwähnungen", + "subtitle": "Wenn dich ein Teammitglied in einem Kommentar mit @ erwähnt, erscheint es hier." + }, + "assigned": { + "title": "Dir ist nichts zugewiesen", + "subtitle": "Dir zugewiesene Arbeitselemente werden hier angezeigt." + }, + "noResults": { + "title": "Keine Treffer", + "subtitle": "Keine Elemente entsprechen „{{query}}“." + } + }, + "loading": "Team-Posteingang wird geladen…", + "drop": { + "title": "Zum Erstellen eines Arbeitselements hier ablegen", + "subtitle": "Prüfe den Sitzungs-Schnappschuss und erstelle oder übergib dann das Arbeitselement.", + "processing": "Arbeitselement wird aus „{{title}}“ erstellt…", + "processingHint": "Sitzung wird gelesen und Projektmitglieder werden aufgelöst.", + "success": "Arbeitselement erstellt", + "reused": "Vorhandenes Arbeitselement aktualisiert", + "failed": "Arbeitselement konnte nicht erstellt werden", + "error": "Aus dieser Sitzung kann kein Arbeitselement erstellt werden.", + "open": "Öffnen", + "dismiss": "Verwerfen" + }, + "handoff": { + "title": "Aus Sitzung erstellen", + "createFromSession": "Team-Arbeitselement erstellen…", + "project": "Zielprojekt", + "chooseProject": "Projekt auswählen", + "recipientSelf": "{{name}} (ich)", + "chooseRecipient": "Empfänger auswählen", + "todoCount_one": "{{count}} Aufgabe", + "todoCount_other": "{{count}} Aufgaben", + "workItemTitle": "Titel des Arbeitselements", + "assignTo": "Zuweisen an", + "note": "Übergabehinweis", + "notePlaceholder": "Teile mit, was fertig ist, was offen ist und was als Nächstes passieren sollte.", + "selfHint": "Wenn du dir dies selbst zuweist, entsteht ein normales Arbeitselement ohne Übergabeanfrage.", + "submitHandoff": "Erstellen & übergeben", + "submitCreate": "Arbeitselement erstellen", + "preparing": "„{{title}}“ wird vorbereitet…", + "preparationError": { + "session_unavailable": "Diese Sitzung ist nicht mehr verfügbar. Öffne sie erneut und versuche es noch einmal.", + "project_unavailable": "Das Projekt dieser Sitzung ist nicht mehr verfügbar.", + "identity_unavailable": "Deine Identität ist kein Mitglied dieses Sitzungsprojekts.", + "no_project": "Kein geeignetes Projekt verfügbar. Erstelle oder tritt einem Projekt bei und versuche es erneut.", + "unknown": "Diese Sitzung kann nicht vorbereitet werden. Aktualisiere den Team-Posteingang und versuche es erneut." + }, + "submitError": "Das Arbeitselement konnte nicht erstellt werden. Überprüfe den Empfänger und versuche es erneut.", + "pendingTitle": "Übergabe von {{name}}", + "acceptedTitle": "Angenommen von {{name}}", + "returnedTitle": "Zurückgegeben von {{name}}", + "noNote": "Kein Übergabehinweis.", + "statusLabel": "Übergabe des Arbeitselements", + "return": "Zurückgeben", + "accept": "Annehmen", + "returnTitle": "Diese Übergabe zurückgeben?", + "confirmReturn": "An Absender zurückgeben", + "returnHint": "Teile {{name}} mit, was geklärt oder nachgebessert werden muss. Das Arbeitselement wird erneut zugewiesen.", + "returnPlaceholder": "Was muss sich vor der nächsten Übergabe ändern?", + "responseError": "Die Antwort auf die Übergabe konnte nicht gespeichert werden. Versuche es erneut.", + "identityUnavailable": "Deine Teamidentität konnte nicht bestätigt werden. Prüfe dein Projektprofil, bevor du antwortest.", + "rowPending": "Von {{name}} · Antwort ausstehend", + "rowAccepted": "Übergabe angenommen · {{status}} · {{priority}}", + "rowReturned": "Zurückgegeben von {{name}} · {{status}} · {{priority}}" + }, + "errors": { + "loadTitle": "Team-Posteingang konnte nicht geladen werden", + "load": "Team-Posteingang konnte nicht geladen werden", + "loadMore": "Weitere Einträge im Team-Posteingang konnten nicht geladen werden. Versuche es erneut.", + "refresh": "Team-Posteingang konnte nicht aktualisiert werden", + "markRead": "Dieses Element konnte nicht als gelesen markiert werden. Versuche es erneut.", + "markUnread": "Dieses Element konnte nicht als ungelesen markiert werden. Versuche es erneut.", + "markAllRead": "Alle Elemente konnten nicht als gelesen markiert werden. Versuche es erneut.", + "identity": "Dein Konto konnte keinem Projektmitglied zugeordnet werden. Überprüfe die E-Mail-Adresse in deinem Projektprofil.", + "partialLoad": "Einige Quellen des Team-Posteingangs konnten nicht aktualisiert werden. Verfügbare Elemente werden weiterhin angezeigt.", + "workItemContext": "Einiger Projektkontext ist nicht verfügbar. Das Arbeitselement bleibt nutzbar.", + "workItemLoad": "Dieses Arbeitselement konnte nicht geladen werden. Versuche es erneut.", + "workItemUpdate": "Die letzte Änderung am Arbeitselement konnte nicht gespeichert werden. Versuche es erneut." + }, + "detail": { + "assignedSubtitle": "Zugewiesenes Arbeitselement", + "standaloneProject": "Eigenständig", + "mentionSubtitle": "In einem Kommentar erwähnt", + "mentionedYou": "hat dich erwähnt", + "threadComments_one": "{{count}} Kommentar in diesem Thread", + "threadComments_other": "{{count}} Kommentare in diesem Thread" + }, + "actions": { + "markRead": "Als gelesen markieren", + "markUnread": "Als ungelesen markieren", + "openWorkItem": "Arbeitselement öffnen", + "openSession": "Sitzung öffnen" + }, + "fields": { + "status": "Status", + "priority": "Priorität", + "assignee": "Zugewiesen an", + "workItemId": "Arbeitselement-ID", + "session": "Sitzung", + "comments": "Kommentare", + "threadId": "Thread-ID", + "commentId": "Kommentar-ID" + }, + "workItemStatus": { + "backlog": "Backlog", + "todo": "Zu erledigen", + "in_progress": "In Bearbeitung", + "in_review": "In Prüfung", + "blocked": "Blockiert", + "done": "Erledigt", + "cancelled": "Abgebrochen" + }, + "priority": { + "none": "Keine Priorität", + "low": "Niedrig", + "medium": "Mittel", + "high": "Hoch", + "urgent": "Dringend" + } + }, "toasts": { "replyEmpty": "Antwort darf nicht leer sein", "sessionNotFound": "Sitzung nicht gefunden", diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json index dea676221..b1e69ff93 100644 --- a/src/i18n/locales/es/common.json +++ b/src/i18n/locales/es/common.json @@ -1,4 +1,162 @@ { + "teamInbox": { + "title": "Bandeja del equipo", + "listLabel": "Lista de la bandeja del equipo", + "itemsLabel": "Elementos de la bandeja del equipo", + "unreadCount": "{{count}} sin leer", + "allRead": "Todo al día", + "loadMore": "Cargar más", + "filters": { + "all": "Todos", + "mentions": "Menciones", + "assigned": "Asignados" + }, + "status": { + "read": "Leído", + "unread": "Sin leer" + }, + "row": { + "assignedSummary": "{{status}} · {{priority}}", + "ariaLabel": "{{title}}, {{status}}" + }, + "search": { + "placeholder": "Buscar en la bandeja", + "ariaLabel": "Buscar en la bandeja del equipo" + }, + "groups": { + "today": "Hoy", + "yesterday": "Ayer", + "thisWeek": "Esta semana", + "earlier": "Anteriores" + }, + "empty": { + "title": "Todavía no hay nada aquí", + "subtitle": "Las menciones y los elementos de trabajo asignados aparecerán aquí.", + "selectTitle": "Selecciona un elemento", + "selectSubtitle": "Consulta el contexto del comentario o los detalles del elemento de trabajo.", + "mentions": { + "title": "Sin menciones", + "subtitle": "Cuando un compañero te mencione con @ en un comentario, aparecerá aquí." + }, + "assigned": { + "title": "No tienes nada asignado", + "subtitle": "Los elementos de trabajo asignados a ti aparecerán aquí." + }, + "noResults": { + "title": "Sin coincidencias", + "subtitle": "Ningún elemento coincide con «{{query}}»." + } + }, + "loading": "Cargando la bandeja del equipo…", + "drop": { + "title": "Suelta aquí para crear un elemento de trabajo", + "subtitle": "Revisa la instantánea de la sesión y luego crea o transfiere el elemento de trabajo.", + "processing": "Creando un elemento de trabajo a partir de «{{title}}»…", + "processingHint": "Leyendo la sesión y resolviendo los miembros del proyecto.", + "success": "Elemento de trabajo creado", + "reused": "Elemento de trabajo existente actualizado", + "failed": "No se pudo crear el elemento de trabajo", + "error": "No se puede crear un elemento de trabajo a partir de esta sesión.", + "open": "Abrir", + "dismiss": "Descartar" + }, + "handoff": { + "title": "Crear desde la sesión", + "createFromSession": "Crear elemento de trabajo del equipo…", + "project": "Proyecto de destino", + "chooseProject": "Elegir un proyecto", + "recipientSelf": "{{name}} (yo)", + "chooseRecipient": "Elegir un destinatario", + "todoCount_one": "{{count}} pendiente", + "todoCount_other": "{{count}} pendientes", + "workItemTitle": "Título del elemento de trabajo", + "assignTo": "Asignar a", + "note": "Nota de traspaso", + "notePlaceholder": "Indica qué está listo, qué queda pendiente y qué debería ocurrir a continuación.", + "selfHint": "Asignarte esto a ti mismo crea un elemento de trabajo normal, sin solicitud de traspaso.", + "submitHandoff": "Crear y traspasar", + "submitCreate": "Crear elemento de trabajo", + "preparing": "Preparando «{{title}}»…", + "preparationError": { + "session_unavailable": "Esta sesión ya no está disponible. Vuelve a abrirla e inténtalo de nuevo.", + "project_unavailable": "El proyecto de esta sesión ya no está disponible.", + "identity_unavailable": "Tu identidad no es miembro del proyecto de esta sesión.", + "no_project": "No hay ningún proyecto elegible disponible. Crea o únete a un proyecto e inténtalo de nuevo.", + "unknown": "No se puede preparar esta sesión. Actualiza la bandeja del equipo e inténtalo de nuevo." + }, + "submitError": "No se pudo crear el elemento de trabajo. Revisa el destinatario e inténtalo de nuevo.", + "pendingTitle": "Traspaso de {{name}}", + "acceptedTitle": "Aceptado por {{name}}", + "returnedTitle": "Devuelto por {{name}}", + "noNote": "Sin nota de traspaso.", + "statusLabel": "Traspaso del elemento de trabajo", + "return": "Devolver", + "accept": "Aceptar", + "returnTitle": "¿Devolver este traspaso?", + "confirmReturn": "Devolver al remitente", + "returnHint": "Indica a {{name}} qué necesita aclaración o seguimiento. El elemento de trabajo se le reasignará.", + "returnPlaceholder": "¿Qué debe cambiar antes de poder traspasarlo?", + "responseError": "No se pudo guardar la respuesta del traspaso. Inténtalo de nuevo.", + "identityUnavailable": "No se pudo verificar tu identidad de equipo. Revisa tu perfil de proyecto antes de responder.", + "rowPending": "De {{name}} · Esperando respuesta", + "rowAccepted": "Traspaso aceptado · {{status}} · {{priority}}", + "rowReturned": "Devuelto por {{name}} · {{status}} · {{priority}}" + }, + "errors": { + "loadTitle": "No se pudo cargar la bandeja del equipo", + "load": "No se pudo cargar la bandeja del equipo", + "loadMore": "No se pudieron cargar más elementos de la bandeja del equipo. Inténtalo de nuevo.", + "refresh": "No se pudo actualizar la bandeja del equipo", + "markRead": "No se pudo marcar este elemento como leído. Inténtalo de nuevo.", + "markUnread": "No se pudo marcar este elemento como no leído. Inténtalo de nuevo.", + "markAllRead": "No se pudieron marcar todos los elementos como leídos. Inténtalo de nuevo.", + "identity": "Tu cuenta no se pudo asociar a ningún miembro del proyecto. Revisa el correo electrónico de tu perfil de proyecto.", + "partialLoad": "Algunas fuentes de la bandeja del equipo no se pudieron actualizar. Los elementos disponibles se siguen mostrando.", + "workItemContext": "Parte del contexto del proyecto no está disponible. El elemento de trabajo sigue siendo utilizable.", + "workItemLoad": "No se pudo cargar este elemento de trabajo. Inténtalo de nuevo.", + "workItemUpdate": "No se pudo guardar el último cambio del elemento de trabajo. Inténtalo de nuevo." + }, + "detail": { + "assignedSubtitle": "Elemento de trabajo asignado", + "standaloneProject": "Independiente", + "mentionSubtitle": "Mencionado en un comentario", + "mentionedYou": "te mencionó", + "threadComments_one": "{{count}} comentario en este hilo", + "threadComments_other": "{{count}} comentarios en este hilo" + }, + "actions": { + "markRead": "Marcar como leído", + "markUnread": "Marcar como no leído", + "openWorkItem": "Abrir elemento de trabajo", + "openSession": "Abrir sesión" + }, + "fields": { + "status": "Estado", + "priority": "Prioridad", + "assignee": "Responsable", + "workItemId": "ID del elemento de trabajo", + "session": "Sesión", + "comments": "Comentarios", + "threadId": "ID del hilo", + "commentId": "ID del comentario" + }, + "workItemStatus": { + "backlog": "Pendiente", + "todo": "Por hacer", + "in_progress": "En curso", + "in_review": "En revisión", + "blocked": "Bloqueado", + "done": "Hecho", + "cancelled": "Cancelado" + }, + "priority": { + "none": "Sin prioridad", + "low": "Baja", + "medium": "Media", + "high": "Alta", + "urgent": "Urgente" + } + }, "toasts": { "replyEmpty": "La respuesta no puede estar vacía", "sessionNotFound": "Sesión no encontrada", diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json index 35ebae47a..9d12abd3e 100644 --- a/src/i18n/locales/fr/common.json +++ b/src/i18n/locales/fr/common.json @@ -1,4 +1,162 @@ { + "teamInbox": { + "title": "Boîte de réception d’équipe", + "listLabel": "Liste de la boîte de réception d’équipe", + "itemsLabel": "Éléments de la boîte de réception d’équipe", + "unreadCount": "{{count}} non lu(s)", + "allRead": "Tout est à jour", + "loadMore": "Charger plus", + "filters": { + "all": "Tous", + "mentions": "Mentions", + "assigned": "Assignés" + }, + "status": { + "read": "Lu", + "unread": "Non lu" + }, + "row": { + "assignedSummary": "{{status}} · {{priority}}", + "ariaLabel": "{{title}}, {{status}}" + }, + "search": { + "placeholder": "Rechercher dans la boîte de réception", + "ariaLabel": "Rechercher dans la boîte de réception d’équipe" + }, + "groups": { + "today": "Aujourd’hui", + "yesterday": "Hier", + "thisWeek": "Cette semaine", + "earlier": "Plus tôt" + }, + "empty": { + "title": "Rien ici pour l’instant", + "subtitle": "Les mentions et les éléments de travail assignés apparaîtront ici.", + "selectTitle": "Sélectionner un élément", + "selectSubtitle": "Voir le contexte du commentaire ou les détails de l’élément de travail.", + "mentions": { + "title": "Aucune mention", + "subtitle": "Lorsqu’un coéquipier vous mentionne avec @ dans un commentaire, cela apparaît ici." + }, + "assigned": { + "title": "Rien ne vous est assigné", + "subtitle": "Les éléments de travail qui vous sont assignés apparaîtront ici." + }, + "noResults": { + "title": "Aucun résultat", + "subtitle": "Aucun élément ne correspond à « {{query}} »." + } + }, + "loading": "Chargement de la boîte de réception d’équipe…", + "drop": { + "title": "Déposer ici pour créer un élément de travail", + "subtitle": "Vérifiez l’aperçu de la session, puis créez ou transférez l’élément de travail.", + "processing": "Création d’un élément de travail à partir de « {{title}} »…", + "processingHint": "Lecture de la session et résolution des membres du projet.", + "success": "Élément de travail créé", + "reused": "Élément de travail existant mis à jour", + "failed": "Impossible de créer l’élément de travail", + "error": "Impossible de créer un élément de travail à partir de cette session.", + "open": "Ouvrir", + "dismiss": "Ignorer" + }, + "handoff": { + "title": "Créer depuis la session", + "createFromSession": "Créer un élément de travail d’équipe…", + "project": "Projet de destination", + "chooseProject": "Choisir un projet", + "recipientSelf": "{{name}} (moi)", + "chooseRecipient": "Choisir un destinataire", + "todoCount_one": "{{count}} tâche", + "todoCount_other": "{{count}} tâches", + "workItemTitle": "Titre de l’élément de travail", + "assignTo": "Assigner à", + "note": "Note de transfert", + "notePlaceholder": "Indiquez ce qui est prêt, ce qui reste en suspens et ce qui devrait suivre.", + "selfHint": "Vous l’assigner à vous-même crée un élément de travail normal, sans demande de transfert.", + "submitHandoff": "Créer et transférer", + "submitCreate": "Créer l’élément de travail", + "preparing": "Préparation de « {{title}} »…", + "preparationError": { + "session_unavailable": "Cette session n’est plus disponible. Rouvrez-la et réessayez.", + "project_unavailable": "Le projet de cette session n’est plus disponible.", + "identity_unavailable": "Votre identité n’est pas membre du projet de cette session.", + "no_project": "Aucun projet éligible disponible. Créez ou rejoignez un projet, puis réessayez.", + "unknown": "Impossible de préparer cette session. Actualisez la boîte de réception d’équipe et réessayez." + }, + "submitError": "L’élément de travail n’a pas pu être créé. Vérifiez le destinataire et réessayez.", + "pendingTitle": "Transfert de {{name}}", + "acceptedTitle": "Accepté par {{name}}", + "returnedTitle": "Renvoyé par {{name}}", + "noNote": "Aucune note de transfert.", + "statusLabel": "Transfert de l’élément de travail", + "return": "Renvoyer", + "accept": "Accepter", + "returnTitle": "Renvoyer ce transfert ?", + "confirmReturn": "Renvoyer à l’expéditeur", + "returnHint": "Indiquez à {{name}} ce qui doit être clarifié ou complété. L’élément de travail lui sera réassigné.", + "returnPlaceholder": "Que faut-il changer avant un nouveau transfert ?", + "responseError": "La réponse au transfert n’a pas pu être enregistrée. Réessayez.", + "identityUnavailable": "Votre identité d’équipe n’a pas pu être vérifiée. Vérifiez votre profil de projet avant de répondre.", + "rowPending": "De {{name}} · En attente de réponse", + "rowAccepted": "Transfert accepté · {{status}} · {{priority}}", + "rowReturned": "Renvoyé par {{name}} · {{status}} · {{priority}}" + }, + "errors": { + "loadTitle": "Impossible de charger la boîte de réception d’équipe", + "load": "Impossible de charger la boîte de réception d’équipe", + "loadMore": "Impossible de charger d’autres éléments de la boîte de réception d’équipe. Réessayez.", + "refresh": "Impossible d’actualiser la boîte de réception d’équipe", + "markRead": "Impossible de marquer cet élément comme lu. Réessayez.", + "markUnread": "Impossible de marquer cet élément comme non lu. Réessayez.", + "markAllRead": "Impossible de marquer tous les éléments comme lus. Réessayez.", + "identity": "Votre compte n’a pas pu être associé à un membre du projet. Vérifiez l’e-mail de votre profil de projet.", + "partialLoad": "Certaines sources de la boîte de réception d’équipe n’ont pas pu être actualisées. Les éléments disponibles restent affichés.", + "workItemContext": "Une partie du contexte du projet n’est pas disponible. L’élément de travail reste utilisable.", + "workItemLoad": "Impossible de charger cet élément de travail. Réessayez.", + "workItemUpdate": "Impossible d’enregistrer la dernière modification de l’élément de travail. Réessayez." + }, + "detail": { + "assignedSubtitle": "Élément de travail assigné", + "standaloneProject": "Autonome", + "mentionSubtitle": "Mentionné dans un commentaire", + "mentionedYou": "vous a mentionné", + "threadComments_one": "{{count}} commentaire dans ce fil", + "threadComments_other": "{{count}} commentaires dans ce fil" + }, + "actions": { + "markRead": "Marquer comme lu", + "markUnread": "Marquer comme non lu", + "openWorkItem": "Ouvrir l’élément de travail", + "openSession": "Ouvrir la session" + }, + "fields": { + "status": "Statut", + "priority": "Priorité", + "assignee": "Assigné à", + "workItemId": "ID de l’élément de travail", + "session": "Session", + "comments": "Commentaires", + "threadId": "ID du fil", + "commentId": "ID du commentaire" + }, + "workItemStatus": { + "backlog": "Backlog", + "todo": "À faire", + "in_progress": "En cours", + "in_review": "En revue", + "blocked": "Bloqué", + "done": "Terminé", + "cancelled": "Annulé" + }, + "priority": { + "none": "Aucune priorité", + "low": "Basse", + "medium": "Moyenne", + "high": "Haute", + "urgent": "Urgente" + } + }, "toasts": { "replyEmpty": "La réponse ne peut pas être vide", "sessionNotFound": "Session introuvable", diff --git a/src/i18n/locales/ja/common.json b/src/i18n/locales/ja/common.json index 38bec2b1b..d42326d06 100644 --- a/src/i18n/locales/ja/common.json +++ b/src/i18n/locales/ja/common.json @@ -1,4 +1,160 @@ { + "teamInbox": { + "title": "チームの受信トレイ", + "listLabel": "チーム受信トレイの一覧", + "itemsLabel": "チーム受信トレイの項目", + "unreadCount": "未読 {{count}} 件", + "allRead": "すべて確認済み", + "loadMore": "さらに読み込む", + "filters": { + "all": "すべて", + "mentions": "メンション", + "assigned": "自分の担当" + }, + "status": { + "read": "既読", + "unread": "未読" + }, + "row": { + "assignedSummary": "{{status}} · {{priority}}", + "ariaLabel": "{{title}}、{{status}}" + }, + "search": { + "placeholder": "受信トレイを検索", + "ariaLabel": "チーム受信トレイを検索" + }, + "groups": { + "today": "今日", + "yesterday": "昨日", + "thisWeek": "今週", + "earlier": "それ以前" + }, + "empty": { + "title": "まだ何もありません", + "subtitle": "メンションや割り当てられた作業項目がここに表示されます。", + "selectTitle": "項目を選択してください", + "selectSubtitle": "コメントの文脈や作業項目の詳細を確認できます。", + "mentions": { + "title": "メンションはありません", + "subtitle": "チームメンバーがコメントで @ メンションすると、ここに表示されます。" + }, + "assigned": { + "title": "自分に割り当てられた項目はありません", + "subtitle": "自分に割り当てられた作業項目がここに表示されます。" + }, + "noResults": { + "title": "一致する項目がありません", + "subtitle": "「{{query}}」に一致する項目はありません。" + } + }, + "loading": "チーム受信トレイを読み込んでいます…", + "drop": { + "title": "ここにドロップして作業項目を作成", + "subtitle": "セッションのスナップショットを確認してから、作業項目を作成または引き継いでください。", + "processing": "「{{title}}」から作業項目を作成しています…", + "processingHint": "セッションを読み込み、プロジェクトメンバーを解決しています。", + "success": "作業項目を作成しました", + "reused": "既存の作業項目を更新しました", + "failed": "作業項目を作成できませんでした", + "error": "このセッションから作業項目を作成できません。", + "open": "開く", + "dismiss": "閉じる" + }, + "handoff": { + "title": "セッションから作成", + "createFromSession": "チーム作業項目を作成…", + "project": "移動先プロジェクト", + "chooseProject": "プロジェクトを選択", + "recipientSelf": "{{name}}(自分)", + "chooseRecipient": "受信者を選択", + "todoCount_other": "To-do {{count}} 件", + "workItemTitle": "作業項目のタイトル", + "assignTo": "担当者", + "note": "引き継ぎメモ", + "notePlaceholder": "完了していること、未解決の点、次に行うべきことを共有してください。", + "selfHint": "自分自身に割り当てると、引き継ぎ依頼のない通常の作業項目が作成されます。", + "submitHandoff": "作成して引き継ぐ", + "submitCreate": "作業項目を作成", + "preparing": "「{{title}}」を準備しています…", + "preparationError": { + "session_unavailable": "このセッションは利用できなくなりました。再度開いてやり直してください。", + "project_unavailable": "このセッションのプロジェクトは利用できなくなりました。", + "identity_unavailable": "あなたはこのセッションのプロジェクトのメンバーではありません。", + "no_project": "利用可能なプロジェクトがありません。プロジェクトを作成または参加してから再試行してください。", + "unknown": "このセッションを準備できません。チーム受信トレイを更新してから再試行してください。" + }, + "submitError": "作業項目を作成できませんでした。受信者を確認してから再試行してください。", + "pendingTitle": "{{name}} からの引き継ぎ", + "acceptedTitle": "{{name}} が受諾しました", + "returnedTitle": "{{name}} が差し戻しました", + "noNote": "引き継ぎメモはありません。", + "statusLabel": "作業項目の引き継ぎ", + "return": "差し戻す", + "accept": "受諾する", + "returnTitle": "この引き継ぎを差し戻しますか?", + "confirmReturn": "送信者に差し戻す", + "returnHint": "確認や対応が必要な内容を {{name}} に伝えてください。作業項目は {{name}} に再割り当てされます。", + "returnPlaceholder": "次に引き継ぐ前に何を変更する必要がありますか?", + "responseError": "引き継ぎへの返信を保存できませんでした。再試行してください。", + "identityUnavailable": "チームでの本人確認ができませんでした。返信する前にプロジェクトのプロフィールを確認してください。", + "rowPending": "{{name}} から · 返信待ち", + "rowAccepted": "引き継ぎ受諾済み · {{status}} · {{priority}}", + "rowReturned": "{{name}} が差し戻し · {{status}} · {{priority}}" + }, + "errors": { + "loadTitle": "チーム受信トレイを読み込めませんでした", + "load": "チーム受信トレイを読み込めませんでした", + "loadMore": "チーム受信トレイの項目をこれ以上読み込めませんでした。再試行してください。", + "refresh": "チーム受信トレイを更新できませんでした", + "markRead": "この項目を既読にできませんでした。再試行してください。", + "markUnread": "この項目を未読にできませんでした。再試行してください。", + "markAllRead": "すべての項目を既読にできませんでした。再試行してください。", + "identity": "アカウントをプロジェクトメンバーに一致させられませんでした。プロジェクトのプロフィールのメールアドレスを確認してください。", + "partialLoad": "一部のチーム受信トレイのソースを更新できませんでした。利用可能な項目は引き続き表示されます。", + "workItemContext": "一部のプロジェクト情報が利用できません。作業項目は引き続き使用できます。", + "workItemLoad": "この作業項目を読み込めませんでした。再試行してください。", + "workItemUpdate": "作業項目への最新の変更を保存できませんでした。再試行してください。" + }, + "detail": { + "assignedSubtitle": "割り当てられた作業項目", + "standaloneProject": "単独", + "mentionSubtitle": "コメントでメンションされました", + "mentionedYou": "があなたをメンションしました", + "threadComments_other": "このスレッドには {{count}} 件のコメントがあります" + }, + "actions": { + "markRead": "既読にする", + "markUnread": "未読にする", + "openWorkItem": "作業項目を開く", + "openSession": "セッションを開く" + }, + "fields": { + "status": "ステータス", + "priority": "優先度", + "assignee": "担当者", + "workItemId": "作業項目 ID", + "session": "セッション", + "comments": "コメント", + "threadId": "スレッド ID", + "commentId": "コメント ID" + }, + "workItemStatus": { + "backlog": "バックログ", + "todo": "未着手", + "in_progress": "進行中", + "in_review": "レビュー中", + "blocked": "ブロック中", + "done": "完了", + "cancelled": "キャンセル" + }, + "priority": { + "none": "優先度なし", + "low": "低", + "medium": "中", + "high": "高", + "urgent": "緊急" + } + }, "toasts": { "replyEmpty": "返信を入力してください", "sessionNotFound": "セッションが見つかりません", diff --git a/src/i18n/locales/ko/common.json b/src/i18n/locales/ko/common.json index 490b02ff0..971bf1e0e 100644 --- a/src/i18n/locales/ko/common.json +++ b/src/i18n/locales/ko/common.json @@ -1,4 +1,160 @@ { + "teamInbox": { + "title": "팀 수신함", + "listLabel": "팀 수신함 목록", + "itemsLabel": "팀 수신함 항목", + "unreadCount": "읽지 않음 {{count}}건", + "allRead": "모두 확인했습니다", + "loadMore": "더 불러오기", + "filters": { + "all": "전체", + "mentions": "멘션", + "assigned": "할당됨" + }, + "status": { + "read": "읽음", + "unread": "읽지 않음" + }, + "row": { + "assignedSummary": "{{status}} · {{priority}}", + "ariaLabel": "{{title}}, {{status}}" + }, + "search": { + "placeholder": "수신함 검색", + "ariaLabel": "팀 수신함 검색" + }, + "groups": { + "today": "오늘", + "yesterday": "어제", + "thisWeek": "이번 주", + "earlier": "이전" + }, + "empty": { + "title": "아직 항목이 없습니다", + "subtitle": "멘션과 할당된 작업 항목이 여기에 표시됩니다.", + "selectTitle": "항목을 선택하세요", + "selectSubtitle": "댓글 맥락이나 작업 항목 세부 정보를 확인하세요.", + "mentions": { + "title": "멘션이 없습니다", + "subtitle": "팀원이 댓글에서 @로 멘션하면 여기에 표시됩니다." + }, + "assigned": { + "title": "할당된 항목이 없습니다", + "subtitle": "나에게 할당된 작업 항목이 여기에 표시됩니다." + }, + "noResults": { + "title": "일치하는 항목이 없습니다", + "subtitle": "“{{query}}”와(과) 일치하는 항목이 없습니다." + } + }, + "loading": "팀 수신함을 불러오는 중…", + "drop": { + "title": "여기로 끌어다 놓아 작업 항목 만들기", + "subtitle": "세션 스냅샷을 확인한 다음 작업 항목을 만들거나 인계하세요.", + "processing": "“{{title}}”에서 작업 항목을 만드는 중…", + "processingHint": "세션을 읽고 프로젝트 구성원을 확인하는 중입니다.", + "success": "작업 항목을 만들었습니다", + "reused": "기존 작업 항목을 업데이트했습니다", + "failed": "작업 항목을 만들지 못했습니다", + "error": "이 세션에서 작업 항목을 만들 수 없습니다.", + "open": "열기", + "dismiss": "닫기" + }, + "handoff": { + "title": "세션에서 만들기", + "createFromSession": "팀 작업 항목 만들기…", + "project": "대상 프로젝트", + "chooseProject": "프로젝트 선택", + "recipientSelf": "{{name}}(나)", + "chooseRecipient": "받는 사람 선택", + "todoCount_other": "할 일 {{count}}개", + "workItemTitle": "작업 항목 제목", + "assignTo": "담당자", + "note": "인계 메모", + "notePlaceholder": "완료된 사항, 남은 미해결 사항, 다음에 해야 할 일을 알려주세요.", + "selfHint": "자신에게 할당하면 인계 요청 없이 일반 작업 항목이 생성됩니다.", + "submitHandoff": "만들고 인계하기", + "submitCreate": "작업 항목 만들기", + "preparing": "“{{title}}” 준비하는 중…", + "preparationError": { + "session_unavailable": "이 세션을 더 이상 사용할 수 없습니다. 다시 열어서 시도해 주세요.", + "project_unavailable": "이 세션의 프로젝트를 더 이상 사용할 수 없습니다.", + "identity_unavailable": "회원님은 이 세션 프로젝트의 구성원이 아닙니다.", + "no_project": "사용 가능한 프로젝트가 없습니다. 프로젝트를 만들거나 참여한 후 다시 시도해 주세요.", + "unknown": "이 세션을 준비할 수 없습니다. 팀 수신함을 새로 고친 후 다시 시도해 주세요." + }, + "submitError": "작업 항목을 만들지 못했습니다. 받는 사람을 확인한 후 다시 시도해 주세요.", + "pendingTitle": "{{name}} 님의 인계", + "acceptedTitle": "{{name}} 님이 수락함", + "returnedTitle": "{{name}} 님이 반려함", + "noNote": "인계 메모가 없습니다.", + "statusLabel": "작업 항목 인계", + "return": "반려", + "accept": "수락", + "returnTitle": "이 인계를 반려하시겠어요?", + "confirmReturn": "보낸 사람에게 반려", + "returnHint": "{{name}} 님에게 확인이나 후속 조치가 필요한 내용을 알려주세요. 작업 항목이 다시 할당됩니다.", + "returnPlaceholder": "다시 인계하기 전에 무엇을 변경해야 하나요?", + "responseError": "인계 응답을 저장하지 못했습니다. 다시 시도해 주세요.", + "identityUnavailable": "팀 신원을 확인할 수 없습니다. 응답하기 전에 프로젝트 프로필을 확인하세요.", + "rowPending": "{{name}} 님으로부터 · 응답 대기 중", + "rowAccepted": "인계 수락됨 · {{status}} · {{priority}}", + "rowReturned": "{{name}} 님이 반려함 · {{status}} · {{priority}}" + }, + "errors": { + "loadTitle": "팀 수신함을 불러올 수 없습니다", + "load": "팀 수신함을 불러올 수 없습니다", + "loadMore": "팀 수신함 항목을 더 불러올 수 없습니다. 다시 시도해 주세요.", + "refresh": "팀 수신함을 새로 고칠 수 없습니다", + "markRead": "이 항목을 읽음으로 표시할 수 없습니다. 다시 시도해 주세요.", + "markUnread": "이 항목을 읽지 않음으로 표시할 수 없습니다. 다시 시도해 주세요.", + "markAllRead": "모든 항목을 읽음으로 표시할 수 없습니다. 다시 시도해 주세요.", + "identity": "계정을 프로젝트 구성원과 일치시킬 수 없습니다. 프로젝트 프로필의 이메일을 확인하세요.", + "partialLoad": "일부 팀 수신함 소스를 새로 고칠 수 없습니다. 사용 가능한 항목은 계속 표시됩니다.", + "workItemContext": "일부 프로젝트 정보를 사용할 수 없습니다. 작업 항목은 계속 사용할 수 있습니다.", + "workItemLoad": "이 작업 항목을 불러올 수 없습니다. 다시 시도해 주세요.", + "workItemUpdate": "작업 항목의 최신 변경 사항을 저장할 수 없습니다. 다시 시도해 주세요." + }, + "detail": { + "assignedSubtitle": "할당된 작업 항목", + "standaloneProject": "독립 항목", + "mentionSubtitle": "댓글에서 멘션됨", + "mentionedYou": "님이 회원님을 멘션했습니다", + "threadComments_other": "이 스레드에 댓글 {{count}}개가 있습니다" + }, + "actions": { + "markRead": "읽음으로 표시", + "markUnread": "읽지 않음으로 표시", + "openWorkItem": "작업 항목 열기", + "openSession": "세션 열기" + }, + "fields": { + "status": "상태", + "priority": "우선순위", + "assignee": "담당자", + "workItemId": "작업 항목 ID", + "session": "세션", + "comments": "댓글", + "threadId": "스레드 ID", + "commentId": "댓글 ID" + }, + "workItemStatus": { + "backlog": "백로그", + "todo": "할 일", + "in_progress": "진행 중", + "in_review": "검토 중", + "blocked": "차단됨", + "done": "완료", + "cancelled": "취소됨" + }, + "priority": { + "none": "우선순위 없음", + "low": "낮음", + "medium": "중간", + "high": "높음", + "urgent": "긴급" + } + }, "toasts": { "replyEmpty": "답장을 입력하세요", "sessionNotFound": "세션을 찾을 수 없습니다", diff --git a/src/i18n/locales/pl/common.json b/src/i18n/locales/pl/common.json index bd10dff0f..6b849b912 100644 --- a/src/i18n/locales/pl/common.json +++ b/src/i18n/locales/pl/common.json @@ -1,4 +1,166 @@ { + "teamInbox": { + "title": "Skrzynka zespołu", + "listLabel": "Lista skrzynki zespołu", + "itemsLabel": "Elementy skrzynki zespołu", + "unreadCount": "Nieprzeczytane: {{count}}", + "allRead": "Wszystko przeczytane", + "loadMore": "Wczytaj więcej", + "filters": { + "all": "Wszystkie", + "mentions": "Wzmianki", + "assigned": "Przypisane" + }, + "status": { + "read": "Przeczytane", + "unread": "Nieprzeczytane" + }, + "row": { + "assignedSummary": "{{status}} · {{priority}}", + "ariaLabel": "{{title}}, {{status}}" + }, + "search": { + "placeholder": "Przeszukaj skrzynkę", + "ariaLabel": "Przeszukaj skrzynkę zespołu" + }, + "groups": { + "today": "Dzisiaj", + "yesterday": "Wczoraj", + "thisWeek": "W tym tygodniu", + "earlier": "Wcześniej" + }, + "empty": { + "title": "Nic tu jeszcze nie ma", + "subtitle": "Wzmianki i przypisane elementy pracy będą się tu pojawiać.", + "selectTitle": "Wybierz element", + "selectSubtitle": "Zobacz kontekst komentarza lub szczegóły elementu pracy.", + "mentions": { + "title": "Brak wzmianek", + "subtitle": "Gdy członek zespołu wspomni o Tobie za pomocą @ w komentarzu, pojawi się to tutaj." + }, + "assigned": { + "title": "Nic Ci nie przypisano", + "subtitle": "Przypisane do Ciebie elementy pracy pojawią się tutaj." + }, + "noResults": { + "title": "Brak wyników", + "subtitle": "Żaden element nie pasuje do „{{query}}”." + } + }, + "loading": "Wczytywanie skrzynki zespołu…", + "drop": { + "title": "Upuść tutaj, aby utworzyć element pracy", + "subtitle": "Sprawdź migawkę sesji, a następnie utwórz lub przekaż element pracy.", + "processing": "Tworzenie elementu pracy z „{{title}}”…", + "processingHint": "Odczytywanie sesji i ustalanie członków projektu.", + "success": "Utworzono element pracy", + "reused": "Zaktualizowano istniejący element pracy", + "failed": "Nie udało się utworzyć elementu pracy", + "error": "Nie można utworzyć elementu pracy na podstawie tej sesji.", + "open": "Otwórz", + "dismiss": "Odrzuć" + }, + "handoff": { + "title": "Utwórz z sesji", + "createFromSession": "Utwórz zespołowy element pracy…", + "project": "Projekt docelowy", + "chooseProject": "Wybierz projekt", + "recipientSelf": "{{name}} (ja)", + "chooseRecipient": "Wybierz odbiorcę", + "todoCount_one": "{{count}} zadanie", + "todoCount_few": "{{count}} zadania", + "todoCount_many": "{{count}} zadań", + "todoCount_other": "{{count}} zadania", + "workItemTitle": "Tytuł elementu pracy", + "assignTo": "Przypisz do", + "note": "Notatka przekazania", + "notePlaceholder": "Opisz, co jest gotowe, co pozostało nierozwiązane i co powinno się wydarzyć dalej.", + "selfHint": "Przypisanie tego do siebie tworzy zwykły element pracy bez żądania przekazania.", + "submitHandoff": "Utwórz i przekaż", + "submitCreate": "Utwórz element pracy", + "preparing": "Przygotowywanie „{{title}}”…", + "preparationError": { + "session_unavailable": "Ta sesja nie jest już dostępna. Otwórz ją ponownie i spróbuj jeszcze raz.", + "project_unavailable": "Projekt tej sesji nie jest już dostępny.", + "identity_unavailable": "Twoja tożsamość nie jest członkiem projektu tej sesji.", + "no_project": "Brak dostępnego kwalifikującego się projektu. Utwórz projekt lub dołącz do niego, a następnie spróbuj ponownie.", + "unknown": "Nie można przygotować tej sesji. Odśwież skrzynkę zespołu i spróbuj ponownie." + }, + "submitError": "Nie udało się utworzyć elementu pracy. Sprawdź odbiorcę i spróbuj ponownie.", + "pendingTitle": "Przekazanie od {{name}}", + "acceptedTitle": "Zaakceptowane przez {{name}}", + "returnedTitle": "Zwrócone przez {{name}}", + "noNote": "Brak notatki przekazania.", + "statusLabel": "Przekazanie elementu pracy", + "return": "Zwróć", + "accept": "Zaakceptuj", + "returnTitle": "Zwrócić to przekazanie?", + "confirmReturn": "Zwróć do nadawcy", + "returnHint": "Poinformuj {{name}}, co wymaga wyjaśnienia lub dalszych działań. Element pracy zostanie ponownie przypisany.", + "returnPlaceholder": "Co należy zmienić przed kolejnym przekazaniem?", + "responseError": "Nie udało się zapisać odpowiedzi na przekazanie. Spróbuj ponownie.", + "identityUnavailable": "Nie udało się zweryfikować Twojej tożsamości zespołowej. Sprawdź swój profil projektu przed odpowiedzią.", + "rowPending": "Od {{name}} · Oczekuje na odpowiedź", + "rowAccepted": "Przekazanie zaakceptowane · {{status}} · {{priority}}", + "rowReturned": "Zwrócone przez {{name}} · {{status}} · {{priority}}" + }, + "errors": { + "loadTitle": "Nie można wczytać skrzynki zespołu", + "load": "Nie można wczytać skrzynki zespołu", + "loadMore": "Nie można wczytać kolejnych elementów skrzynki zespołu. Spróbuj ponownie.", + "refresh": "Nie można odświeżyć skrzynki zespołu", + "markRead": "Nie można oznaczyć tego elementu jako przeczytanego. Spróbuj ponownie.", + "markUnread": "Nie można oznaczyć tego elementu jako nieprzeczytanego. Spróbuj ponownie.", + "markAllRead": "Nie można oznaczyć wszystkich elementów jako przeczytanych. Spróbuj ponownie.", + "identity": "Nie udało się dopasować Twojego konta do członka projektu. Sprawdź adres e-mail w profilu projektu.", + "partialLoad": "Nie udało się odświeżyć niektórych źródeł skrzynki zespołu. Dostępne elementy są nadal wyświetlane.", + "workItemContext": "Część kontekstu projektu jest niedostępna. Element pracy jest nadal użyteczny.", + "workItemLoad": "Nie można wczytać tego elementu pracy. Spróbuj ponownie.", + "workItemUpdate": "Nie można zapisać ostatniej zmiany elementu pracy. Spróbuj ponownie." + }, + "detail": { + "assignedSubtitle": "Przypisany element pracy", + "standaloneProject": "Samodzielny", + "mentionSubtitle": "Wspomniano w komentarzu", + "mentionedYou": "wspomniał(a) o Tobie", + "threadComments_one": "{{count}} komentarz w tym wątku", + "threadComments_few": "{{count}} komentarze w tym wątku", + "threadComments_many": "{{count}} komentarzy w tym wątku", + "threadComments_other": "{{count}} komentarza w tym wątku" + }, + "actions": { + "markRead": "Oznacz jako przeczytane", + "markUnread": "Oznacz jako nieprzeczytane", + "openWorkItem": "Otwórz element pracy", + "openSession": "Otwórz sesję" + }, + "fields": { + "status": "Status", + "priority": "Priorytet", + "assignee": "Przypisano do", + "workItemId": "ID elementu pracy", + "session": "Sesja", + "comments": "Komentarze", + "threadId": "ID wątku", + "commentId": "ID komentarza" + }, + "workItemStatus": { + "backlog": "Zaległości", + "todo": "Do zrobienia", + "in_progress": "W toku", + "in_review": "W recenzji", + "blocked": "Zablokowane", + "done": "Ukończone", + "cancelled": "Anulowane" + }, + "priority": { + "none": "Brak priorytetu", + "low": "Niski", + "medium": "Średni", + "high": "Wysoki", + "urgent": "Pilny" + } + }, "toasts": { "replyEmpty": "Odpowiedź nie może być pusta", "sessionNotFound": "Nie znaleziono sesji", diff --git a/src/i18n/locales/pt/common.json b/src/i18n/locales/pt/common.json index 6bed7b2a8..3b3c018b7 100644 --- a/src/i18n/locales/pt/common.json +++ b/src/i18n/locales/pt/common.json @@ -1,4 +1,162 @@ { + "teamInbox": { + "title": "Caixa de entrada da equipe", + "listLabel": "Lista da caixa de entrada da equipe", + "itemsLabel": "Itens da caixa de entrada da equipe", + "unreadCount": "{{count}} não lidas", + "allRead": "Tudo em dia", + "loadMore": "Carregar mais", + "filters": { + "all": "Todos", + "mentions": "Menções", + "assigned": "Atribuídos" + }, + "status": { + "read": "Lido", + "unread": "Não lido" + }, + "row": { + "assignedSummary": "{{status}} · {{priority}}", + "ariaLabel": "{{title}}, {{status}}" + }, + "search": { + "placeholder": "Pesquisar na caixa de entrada", + "ariaLabel": "Pesquisar na caixa de entrada da equipe" + }, + "groups": { + "today": "Hoje", + "yesterday": "Ontem", + "thisWeek": "Esta semana", + "earlier": "Anteriores" + }, + "empty": { + "title": "Ainda não há nada aqui", + "subtitle": "Menções e itens de trabalho atribuídos aparecerão aqui.", + "selectTitle": "Selecione um item", + "selectSubtitle": "Veja o contexto do comentário ou os detalhes do item de trabalho.", + "mentions": { + "title": "Nenhuma menção", + "subtitle": "Quando um colega de equipe mencionar você com @ em um comentário, isso aparecerá aqui." + }, + "assigned": { + "title": "Nada atribuído a você", + "subtitle": "Os itens de trabalho atribuídos a você aparecerão aqui." + }, + "noResults": { + "title": "Nenhuma correspondência", + "subtitle": "Nenhum item corresponde a “{{query}}”." + } + }, + "loading": "Carregando a caixa de entrada da equipe…", + "drop": { + "title": "Solte aqui para criar um item de trabalho", + "subtitle": "Revise o snapshot da sessão e, em seguida, crie ou repasse o item de trabalho.", + "processing": "Criando um item de trabalho a partir de “{{title}}”…", + "processingHint": "Lendo a sessão e resolvendo os membros do projeto.", + "success": "Item de trabalho criado", + "reused": "Item de trabalho existente atualizado", + "failed": "Não foi possível criar o item de trabalho", + "error": "Não é possível criar um item de trabalho a partir desta sessão.", + "open": "Abrir", + "dismiss": "Descartar" + }, + "handoff": { + "title": "Criar a partir da sessão", + "createFromSession": "Criar item de trabalho da equipe…", + "project": "Projeto de destino", + "chooseProject": "Escolher um projeto", + "recipientSelf": "{{name}} (eu)", + "chooseRecipient": "Escolher um destinatário", + "todoCount_one": "{{count}} tarefa", + "todoCount_other": "{{count}} tarefas", + "workItemTitle": "Título do item de trabalho", + "assignTo": "Atribuir a", + "note": "Nota de repasse", + "notePlaceholder": "Compartilhe o que está pronto, o que está pendente e o que deve acontecer a seguir.", + "selfHint": "Atribuir isto a você mesmo cria um item de trabalho normal, sem solicitação de repasse.", + "submitHandoff": "Criar e repassar", + "submitCreate": "Criar item de trabalho", + "preparing": "Preparando “{{title}}”…", + "preparationError": { + "session_unavailable": "Esta sessão não está mais disponível. Reabra-a e tente novamente.", + "project_unavailable": "O projeto desta sessão não está mais disponível.", + "identity_unavailable": "Sua identidade não é membro do projeto desta sessão.", + "no_project": "Nenhum projeto elegível disponível. Crie ou participe de um projeto e tente novamente.", + "unknown": "Não foi possível preparar esta sessão. Atualize a caixa de entrada da equipe e tente novamente." + }, + "submitError": "Não foi possível criar o item de trabalho. Verifique o destinatário e tente novamente.", + "pendingTitle": "Repasse de {{name}}", + "acceptedTitle": "Aceito por {{name}}", + "returnedTitle": "Devolvido por {{name}}", + "noNote": "Sem nota de repasse.", + "statusLabel": "Repasse do item de trabalho", + "return": "Devolver", + "accept": "Aceitar", + "returnTitle": "Devolver este repasse?", + "confirmReturn": "Devolver ao remetente", + "returnHint": "Informe a {{name}} o que precisa de esclarecimento ou acompanhamento. O item de trabalho será reatribuído a essa pessoa.", + "returnPlaceholder": "O que precisa mudar antes de um novo repasse?", + "responseError": "Não foi possível salvar a resposta do repasse. Tente novamente.", + "identityUnavailable": "Não foi possível verificar sua identidade de equipe. Confira seu perfil do projeto antes de responder.", + "rowPending": "De {{name}} · Aguardando resposta", + "rowAccepted": "Repasse aceito · {{status}} · {{priority}}", + "rowReturned": "Devolvido por {{name}} · {{status}} · {{priority}}" + }, + "errors": { + "loadTitle": "Não foi possível carregar a caixa de entrada da equipe", + "load": "Não foi possível carregar a caixa de entrada da equipe", + "loadMore": "Não foi possível carregar mais itens da caixa de entrada da equipe. Tente novamente.", + "refresh": "Não foi possível atualizar a caixa de entrada da equipe", + "markRead": "Não foi possível marcar este item como lido. Tente novamente.", + "markUnread": "Não foi possível marcar este item como não lido. Tente novamente.", + "markAllRead": "Não foi possível marcar todos os itens como lidos. Tente novamente.", + "identity": "Sua conta não pôde ser associada a um membro do projeto. Verifique o e-mail no seu perfil do projeto.", + "partialLoad": "Algumas fontes da caixa de entrada da equipe não puderam ser atualizadas. Os itens disponíveis continuam sendo exibidos.", + "workItemContext": "Parte do contexto do projeto não está disponível. O item de trabalho continua utilizável.", + "workItemLoad": "Não foi possível carregar este item de trabalho. Tente novamente.", + "workItemUpdate": "Não foi possível salvar a última alteração do item de trabalho. Tente novamente." + }, + "detail": { + "assignedSubtitle": "Item de trabalho atribuído", + "standaloneProject": "Independente", + "mentionSubtitle": "Mencionado em um comentário", + "mentionedYou": "mencionou você", + "threadComments_one": "{{count}} comentário nesta conversa", + "threadComments_other": "{{count}} comentários nesta conversa" + }, + "actions": { + "markRead": "Marcar como lido", + "markUnread": "Marcar como não lido", + "openWorkItem": "Abrir item de trabalho", + "openSession": "Abrir sessão" + }, + "fields": { + "status": "Status", + "priority": "Prioridade", + "assignee": "Responsável", + "workItemId": "ID do item de trabalho", + "session": "Sessão", + "comments": "Comentários", + "threadId": "ID da conversa", + "commentId": "ID do comentário" + }, + "workItemStatus": { + "backlog": "Backlog", + "todo": "A fazer", + "in_progress": "Em andamento", + "in_review": "Em revisão", + "blocked": "Bloqueado", + "done": "Concluído", + "cancelled": "Cancelado" + }, + "priority": { + "none": "Sem prioridade", + "low": "Baixa", + "medium": "Média", + "high": "Alta", + "urgent": "Urgente" + } + }, "toasts": { "replyEmpty": "A resposta não pode estar vazia", "sessionNotFound": "Sessão não encontrada", diff --git a/src/i18n/locales/ru/common.json b/src/i18n/locales/ru/common.json index 1adc60023..24f7146c0 100644 --- a/src/i18n/locales/ru/common.json +++ b/src/i18n/locales/ru/common.json @@ -1,4 +1,166 @@ { + "teamInbox": { + "title": "Общий почтовый ящик команды", + "listLabel": "Список общего почтового ящика команды", + "itemsLabel": "Элементы общего почтового ящика команды", + "unreadCount": "Непрочитанных: {{count}}", + "allRead": "Всё прочитано", + "loadMore": "Загрузить ещё", + "filters": { + "all": "Все", + "mentions": "Упоминания", + "assigned": "Назначенные" + }, + "status": { + "read": "Прочитано", + "unread": "Не прочитано" + }, + "row": { + "assignedSummary": "{{status}} · {{priority}}", + "ariaLabel": "{{title}}, {{status}}" + }, + "search": { + "placeholder": "Поиск в почтовом ящике", + "ariaLabel": "Поиск в почтовом ящике команды" + }, + "groups": { + "today": "Сегодня", + "yesterday": "Вчера", + "thisWeek": "На этой неделе", + "earlier": "Ранее" + }, + "empty": { + "title": "Здесь пока ничего нет", + "subtitle": "Упоминания и назначенные рабочие задачи будут отображаться здесь.", + "selectTitle": "Выберите элемент", + "selectSubtitle": "Просмотрите контекст комментария или детали рабочей задачи.", + "mentions": { + "title": "Нет упоминаний", + "subtitle": "Когда коллега упомянет вас через @ в комментарии, это появится здесь." + }, + "assigned": { + "title": "Вам ничего не назначено", + "subtitle": "Назначенные вам рабочие задачи будут отображаться здесь." + }, + "noResults": { + "title": "Совпадений нет", + "subtitle": "Нет элементов, соответствующих «{{query}}»." + } + }, + "loading": "Загрузка общего почтового ящика команды…", + "drop": { + "title": "Перетащите сюда, чтобы создать рабочую задачу", + "subtitle": "Просмотрите снимок сессии, затем создайте или передайте рабочую задачу.", + "processing": "Создание рабочей задачи из «{{title}}»…", + "processingHint": "Чтение сессии и определение участников проекта.", + "success": "Рабочая задача создана", + "reused": "Существующая рабочая задача обновлена", + "failed": "Не удалось создать рабочую задачу", + "error": "Невозможно создать рабочую задачу на основе этой сессии.", + "open": "Открыть", + "dismiss": "Скрыть" + }, + "handoff": { + "title": "Создать из сессии", + "createFromSession": "Создать командную рабочую задачу…", + "project": "Проект назначения", + "chooseProject": "Выбрать проект", + "recipientSelf": "{{name}} (я)", + "chooseRecipient": "Выбрать получателя", + "todoCount_one": "{{count}} задача", + "todoCount_few": "{{count}} задачи", + "todoCount_many": "{{count}} задач", + "todoCount_other": "{{count}} задачи", + "workItemTitle": "Название рабочей задачи", + "assignTo": "Назначить на", + "note": "Примечание к передаче", + "notePlaceholder": "Опишите, что готово, что осталось нерешённым и что должно произойти дальше.", + "selfHint": "Назначение этого себе создаёт обычную рабочую задачу без запроса на передачу.", + "submitHandoff": "Создать и передать", + "submitCreate": "Создать рабочую задачу", + "preparing": "Подготовка «{{title}}»…", + "preparationError": { + "session_unavailable": "Эта сессия больше недоступна. Откройте её заново и повторите попытку.", + "project_unavailable": "Проект этой сессии больше недоступен.", + "identity_unavailable": "Ваша учётная запись не является участником проекта этой сессии.", + "no_project": "Нет доступных подходящих проектов. Создайте проект или присоединитесь к нему и повторите попытку.", + "unknown": "Не удалось подготовить эту сессию. Обновите общий почтовый ящик команды и повторите попытку." + }, + "submitError": "Не удалось создать рабочую задачу. Проверьте получателя и повторите попытку.", + "pendingTitle": "Передача от {{name}}", + "acceptedTitle": "Принято пользователем {{name}}", + "returnedTitle": "Возвращено пользователем {{name}}", + "noNote": "Нет примечания к передаче.", + "statusLabel": "Передача рабочей задачи", + "return": "Вернуть", + "accept": "Принять", + "returnTitle": "Вернуть эту передачу?", + "confirmReturn": "Вернуть отправителю", + "returnHint": "Сообщите {{name}}, что требует уточнения или доработки. Рабочая задача будет переназначена этому человеку.", + "returnPlaceholder": "Что нужно изменить перед следующей передачей?", + "responseError": "Не удалось сохранить ответ на передачу. Повторите попытку.", + "identityUnavailable": "Не удалось подтвердить вашу командную учётную запись. Проверьте профиль проекта перед ответом.", + "rowPending": "От {{name}} · Ожидает ответа", + "rowAccepted": "Передача принята · {{status}} · {{priority}}", + "rowReturned": "Возвращено пользователем {{name}} · {{status}} · {{priority}}" + }, + "errors": { + "loadTitle": "Не удалось загрузить общий почтовый ящик команды", + "load": "Не удалось загрузить общий почтовый ящик команды", + "loadMore": "Не удалось загрузить дополнительные элементы общего почтового ящика команды. Повторите попытку.", + "refresh": "Не удалось обновить общий почтовый ящик команды", + "markRead": "Не удалось отметить этот элемент как прочитанный. Повторите попытку.", + "markUnread": "Не удалось отметить этот элемент как непрочитанный. Повторите попытку.", + "markAllRead": "Не удалось отметить все элементы как прочитанные. Повторите попытку.", + "identity": "Не удалось сопоставить вашу учётную запись с участником проекта. Проверьте адрес электронной почты в профиле проекта.", + "partialLoad": "Некоторые источники общего почтового ящика команды не удалось обновить. Доступные элементы по-прежнему отображаются.", + "workItemContext": "Часть контекста проекта недоступна. Рабочая задача остаётся доступной для использования.", + "workItemLoad": "Не удалось загрузить эту рабочую задачу. Повторите попытку.", + "workItemUpdate": "Не удалось сохранить последнее изменение рабочей задачи. Повторите попытку." + }, + "detail": { + "assignedSubtitle": "Назначенная рабочая задача", + "standaloneProject": "Отдельная", + "mentionSubtitle": "Упомянуто в комментарии", + "mentionedYou": "упомянул(а) вас", + "threadComments_one": "{{count}} комментарий в этой теме", + "threadComments_few": "{{count}} комментария в этой теме", + "threadComments_many": "{{count}} комментариев в этой теме", + "threadComments_other": "{{count}} комментария в этой теме" + }, + "actions": { + "markRead": "Отметить как прочитанное", + "markUnread": "Отметить как непрочитанное", + "openWorkItem": "Открыть рабочую задачу", + "openSession": "Открыть сессию" + }, + "fields": { + "status": "Статус", + "priority": "Приоритет", + "assignee": "Исполнитель", + "workItemId": "ID рабочей задачи", + "session": "Сессия", + "comments": "Комментарии", + "threadId": "ID темы", + "commentId": "ID комментария" + }, + "workItemStatus": { + "backlog": "Бэклог", + "todo": "К выполнению", + "in_progress": "В работе", + "in_review": "На проверке", + "blocked": "Заблокировано", + "done": "Готово", + "cancelled": "Отменено" + }, + "priority": { + "none": "Без приоритета", + "low": "Низкий", + "medium": "Средний", + "high": "Высокий", + "urgent": "Срочный" + } + }, "toasts": { "replyEmpty": "Ответ не может быть пустым", "sessionNotFound": "Сессия не найдена", diff --git a/src/i18n/locales/tr/common.json b/src/i18n/locales/tr/common.json index a196d2b79..3357b223c 100644 --- a/src/i18n/locales/tr/common.json +++ b/src/i18n/locales/tr/common.json @@ -1,4 +1,162 @@ { + "teamInbox": { + "title": "Ekip Gelen Kutusu", + "listLabel": "Ekip Gelen Kutusu listesi", + "itemsLabel": "Ekip Gelen Kutusu öğeleri", + "unreadCount": "{{count}} okunmadı", + "allRead": "Hepsi okundu", + "loadMore": "Daha fazla yükle", + "filters": { + "all": "Tümü", + "mentions": "Bahsedilenler", + "assigned": "Atananlar" + }, + "status": { + "read": "Okundu", + "unread": "Okunmadı" + }, + "row": { + "assignedSummary": "{{status}} · {{priority}}", + "ariaLabel": "{{title}}, {{status}}" + }, + "search": { + "placeholder": "Gelen kutusunda ara", + "ariaLabel": "Ekip Gelen Kutusunda ara" + }, + "groups": { + "today": "Bugün", + "yesterday": "Dün", + "thisWeek": "Bu hafta", + "earlier": "Daha önce" + }, + "empty": { + "title": "Henüz burada bir şey yok", + "subtitle": "Bahsetmeler ve atanan iş öğeleri burada görünecek.", + "selectTitle": "Bir öğe seçin", + "selectSubtitle": "Yorum bağlamını veya iş öğesi ayrıntılarını görüntüleyin.", + "mentions": { + "title": "Bahsetme yok", + "subtitle": "Bir takım arkadaşı bir yorumda sizden @ ile bahsettiğinde burada görünür." + }, + "assigned": { + "title": "Size atanan hiçbir şey yok", + "subtitle": "Size atanan iş öğeleri burada görünecek." + }, + "noResults": { + "title": "Eşleşme yok", + "subtitle": "“{{query}}” ile eşleşen öğe yok." + } + }, + "loading": "Ekip Gelen Kutusu yükleniyor…", + "drop": { + "title": "İş öğesi oluşturmak için buraya bırakın", + "subtitle": "Önce oturum anlık görüntüsünü inceleyin, ardından iş öğesini oluşturun veya devredin.", + "processing": "“{{title}}” içinden iş öğesi oluşturuluyor…", + "processingHint": "Oturum okunuyor ve proje üyeleri çözümleniyor.", + "success": "İş öğesi oluşturuldu", + "reused": "Mevcut iş öğesi güncellendi", + "failed": "İş öğesi oluşturulamadı", + "error": "Bu oturumdan bir iş öğesi oluşturulamıyor.", + "open": "Aç", + "dismiss": "Kapat" + }, + "handoff": { + "title": "Oturumdan oluştur", + "createFromSession": "Ekip iş öğesi oluştur…", + "project": "Hedef proje", + "chooseProject": "Proje seçin", + "recipientSelf": "{{name}} (ben)", + "chooseRecipient": "Alıcı seçin", + "todoCount_one": "{{count}} yapılacak", + "todoCount_other": "{{count}} yapılacak", + "workItemTitle": "İş öğesi başlığı", + "assignTo": "Şuna ata", + "note": "Devir notu", + "notePlaceholder": "Neyin hazır olduğunu, neyin çözülmediğini ve sonra ne olması gerektiğini paylaşın.", + "selfHint": "Bunu kendinize atamak, devir talebi olmayan normal bir iş öğesi oluşturur.", + "submitHandoff": "Oluştur ve devret", + "submitCreate": "İş öğesi oluştur", + "preparing": "“{{title}}” hazırlanıyor…", + "preparationError": { + "session_unavailable": "Bu oturum artık kullanılamıyor. Yeniden açıp tekrar deneyin.", + "project_unavailable": "Bu oturumun projesi artık kullanılamıyor.", + "identity_unavailable": "Kimliğiniz bu oturumun projesinin üyesi değil.", + "no_project": "Uygun bir proje yok. Bir proje oluşturun veya katılın, ardından tekrar deneyin.", + "unknown": "Bu oturum hazırlanamıyor. Ekip Gelen Kutusunu yenileyip tekrar deneyin." + }, + "submitError": "İş öğesi oluşturulamadı. Alıcıyı kontrol edip tekrar deneyin.", + "pendingTitle": "{{name}} kişisinden devir", + "acceptedTitle": "{{name}} tarafından kabul edildi", + "returnedTitle": "{{name}} tarafından iade edildi", + "noNote": "Devir notu yok.", + "statusLabel": "İş öğesi devri", + "return": "İade et", + "accept": "Kabul et", + "returnTitle": "Bu devir iade edilsin mi?", + "confirmReturn": "Gönderene iade et", + "returnHint": "{{name}} kişisine neyin netleştirilmesi veya takip edilmesi gerektiğini belirtin. İş öğesi kendisine yeniden atanacak.", + "returnPlaceholder": "Bir sonraki devirden önce neyin değişmesi gerekiyor?", + "responseError": "Devir yanıtı kaydedilemedi. Tekrar deneyin.", + "identityUnavailable": "Ekip kimliğiniz doğrulanamadı. Yanıtlamadan önce proje profilinizi kontrol edin.", + "rowPending": "{{name}} kişisinden · Yanıt bekleniyor", + "rowAccepted": "Devir kabul edildi · {{status}} · {{priority}}", + "rowReturned": "{{name}} tarafından iade edildi · {{status}} · {{priority}}" + }, + "errors": { + "loadTitle": "Ekip Gelen Kutusu yüklenemedi", + "load": "Ekip Gelen Kutusu yüklenemedi", + "loadMore": "Daha fazla Ekip Gelen Kutusu öğesi yüklenemedi. Tekrar deneyin.", + "refresh": "Ekip Gelen Kutusu yenilenemedi", + "markRead": "Bu öğe okundu olarak işaretlenemedi. Tekrar deneyin.", + "markUnread": "Bu öğe okunmadı olarak işaretlenemedi. Tekrar deneyin.", + "markAllRead": "Tüm öğeler okundu olarak işaretlenemedi. Tekrar deneyin.", + "identity": "Hesabınız bir proje üyesiyle eşleştirilemedi. Proje profilinizdeki e-postayı kontrol edin.", + "partialLoad": "Bazı Ekip Gelen Kutusu kaynakları yenilenemedi. Kullanılabilir öğeler gösterilmeye devam ediyor.", + "workItemContext": "Bazı proje bağlamı kullanılamıyor. İş öğesi kullanılabilir durumda kalır.", + "workItemLoad": "Bu iş öğesi yüklenemedi. Tekrar deneyin.", + "workItemUpdate": "İş öğesindeki son değişiklik kaydedilemedi. Tekrar deneyin." + }, + "detail": { + "assignedSubtitle": "Atanan iş öğesi", + "standaloneProject": "Bağımsız", + "mentionSubtitle": "Bir yorumda bahsedildi", + "mentionedYou": "sizden bahsetti", + "threadComments_one": "Bu konuda {{count}} yorum var", + "threadComments_other": "Bu konuda {{count}} yorum var" + }, + "actions": { + "markRead": "Okundu olarak işaretle", + "markUnread": "Okunmadı olarak işaretle", + "openWorkItem": "İş öğesini aç", + "openSession": "Oturumu aç" + }, + "fields": { + "status": "Durum", + "priority": "Öncelik", + "assignee": "Atanan kişi", + "workItemId": "İş öğesi kimliği", + "session": "Oturum", + "comments": "Yorumlar", + "threadId": "Konu kimliği", + "commentId": "Yorum kimliği" + }, + "workItemStatus": { + "backlog": "Birikmiş İşler", + "todo": "Yapılacak", + "in_progress": "Devam Ediyor", + "in_review": "İncelemede", + "blocked": "Engellendi", + "done": "Tamamlandı", + "cancelled": "İptal Edildi" + }, + "priority": { + "none": "Öncelik yok", + "low": "Düşük", + "medium": "Orta", + "high": "Yüksek", + "urgent": "Acil" + } + }, "toasts": { "replyEmpty": "Yanıt boş olamaz", "sessionNotFound": "Oturum bulunamadı", diff --git a/src/i18n/locales/vi/common.json b/src/i18n/locales/vi/common.json index 7ebb0b930..4c0129f49 100644 --- a/src/i18n/locales/vi/common.json +++ b/src/i18n/locales/vi/common.json @@ -1,4 +1,160 @@ { + "teamInbox": { + "title": "Hộp thư nhóm", + "listLabel": "Danh sách hộp thư nhóm", + "itemsLabel": "Mục trong hộp thư nhóm", + "unreadCount": "{{count}} chưa đọc", + "allRead": "Đã xem hết", + "loadMore": "Tải thêm", + "filters": { + "all": "Tất cả", + "mentions": "Được nhắc đến", + "assigned": "Được giao" + }, + "status": { + "read": "Đã đọc", + "unread": "Chưa đọc" + }, + "row": { + "assignedSummary": "{{status}} · {{priority}}", + "ariaLabel": "{{title}}, {{status}}" + }, + "search": { + "placeholder": "Tìm trong hộp thư", + "ariaLabel": "Tìm trong hộp thư nhóm" + }, + "groups": { + "today": "Hôm nay", + "yesterday": "Hôm qua", + "thisWeek": "Tuần này", + "earlier": "Trước đó" + }, + "empty": { + "title": "Chưa có gì ở đây", + "subtitle": "Các lượt nhắc đến và mục công việc được giao sẽ xuất hiện ở đây.", + "selectTitle": "Chọn một mục", + "selectSubtitle": "Xem ngữ cảnh bình luận hoặc chi tiết mục công việc.", + "mentions": { + "title": "Không có lượt nhắc đến nào", + "subtitle": "Khi đồng đội nhắc đến bạn bằng @ trong bình luận, mục đó sẽ xuất hiện ở đây." + }, + "assigned": { + "title": "Không có gì được giao cho bạn", + "subtitle": "Các mục công việc được giao cho bạn sẽ xuất hiện ở đây." + }, + "noResults": { + "title": "Không có kết quả phù hợp", + "subtitle": "Không có mục nào khớp với “{{query}}”." + } + }, + "loading": "Đang tải hộp thư nhóm…", + "drop": { + "title": "Thả vào đây để tạo mục công việc", + "subtitle": "Xem lại ảnh chụp phiên làm việc, sau đó tạo hoặc bàn giao mục công việc.", + "processing": "Đang tạo mục công việc từ “{{title}}”…", + "processingHint": "Đang đọc phiên làm việc và xác định thành viên dự án.", + "success": "Đã tạo mục công việc", + "reused": "Đã cập nhật mục công việc hiện có", + "failed": "Không thể tạo mục công việc", + "error": "Không thể tạo mục công việc từ phiên làm việc này.", + "open": "Mở", + "dismiss": "Bỏ qua" + }, + "handoff": { + "title": "Tạo từ phiên làm việc", + "createFromSession": "Tạo mục công việc của nhóm…", + "project": "Dự án đích", + "chooseProject": "Chọn dự án", + "recipientSelf": "{{name}} (tôi)", + "chooseRecipient": "Chọn người nhận", + "todoCount_other": "{{count}} việc cần làm", + "workItemTitle": "Tiêu đề mục công việc", + "assignTo": "Giao cho", + "note": "Ghi chú bàn giao", + "notePlaceholder": "Cho biết những gì đã sẵn sàng, những gì còn tồn đọng và bước tiếp theo nên là gì.", + "selfHint": "Giao việc này cho chính bạn sẽ tạo một mục công việc bình thường, không có yêu cầu bàn giao.", + "submitHandoff": "Tạo & bàn giao", + "submitCreate": "Tạo mục công việc", + "preparing": "Đang chuẩn bị “{{title}}”…", + "preparationError": { + "session_unavailable": "Phiên làm việc này không còn khả dụng. Hãy mở lại và thử lại.", + "project_unavailable": "Dự án của phiên làm việc này không còn khả dụng.", + "identity_unavailable": "Danh tính của bạn không phải là thành viên của dự án thuộc phiên làm việc này.", + "no_project": "Không có dự án phù hợp nào khả dụng. Hãy tạo hoặc tham gia một dự án rồi thử lại.", + "unknown": "Không thể chuẩn bị phiên làm việc này. Hãy làm mới hộp thư nhóm rồi thử lại." + }, + "submitError": "Không thể tạo mục công việc. Hãy kiểm tra người nhận rồi thử lại.", + "pendingTitle": "Bàn giao từ {{name}}", + "acceptedTitle": "Đã được {{name}} chấp nhận", + "returnedTitle": "Đã được {{name}} trả lại", + "noNote": "Không có ghi chú bàn giao.", + "statusLabel": "Bàn giao mục công việc", + "return": "Trả lại", + "accept": "Chấp nhận", + "returnTitle": "Trả lại lượt bàn giao này?", + "confirmReturn": "Trả lại cho người gửi", + "returnHint": "Cho {{name}} biết điều gì cần làm rõ hoặc theo dõi thêm. Mục công việc sẽ được giao lại cho họ.", + "returnPlaceholder": "Cần thay đổi điều gì trước khi bàn giao lại?", + "responseError": "Không thể lưu phản hồi bàn giao. Hãy thử lại.", + "identityUnavailable": "Không thể xác minh danh tính nhóm của bạn. Hãy kiểm tra hồ sơ dự án trước khi phản hồi.", + "rowPending": "Từ {{name}} · Đang chờ phản hồi", + "rowAccepted": "Đã chấp nhận bàn giao · {{status}} · {{priority}}", + "rowReturned": "Đã được {{name}} trả lại · {{status}} · {{priority}}" + }, + "errors": { + "loadTitle": "Không thể tải hộp thư nhóm", + "load": "Không thể tải hộp thư nhóm", + "loadMore": "Không thể tải thêm mục trong hộp thư nhóm. Hãy thử lại.", + "refresh": "Không thể làm mới hộp thư nhóm", + "markRead": "Không thể đánh dấu mục này là đã đọc. Hãy thử lại.", + "markUnread": "Không thể đánh dấu mục này là chưa đọc. Hãy thử lại.", + "markAllRead": "Không thể đánh dấu tất cả mục là đã đọc. Hãy thử lại.", + "identity": "Không thể khớp tài khoản của bạn với thành viên dự án. Hãy kiểm tra email trong hồ sơ dự án của bạn.", + "partialLoad": "Một số nguồn của hộp thư nhóm không thể làm mới. Các mục khả dụng vẫn được hiển thị.", + "workItemContext": "Một phần ngữ cảnh dự án không khả dụng. Mục công việc vẫn có thể sử dụng được.", + "workItemLoad": "Không thể tải mục công việc này. Hãy thử lại.", + "workItemUpdate": "Không thể lưu thay đổi mới nhất của mục công việc. Hãy thử lại." + }, + "detail": { + "assignedSubtitle": "Mục công việc được giao", + "standaloneProject": "Độc lập", + "mentionSubtitle": "Được nhắc đến trong một bình luận", + "mentionedYou": "đã nhắc đến bạn", + "threadComments_other": "{{count}} bình luận trong chuỗi này" + }, + "actions": { + "markRead": "Đánh dấu đã đọc", + "markUnread": "Đánh dấu chưa đọc", + "openWorkItem": "Mở mục công việc", + "openSession": "Mở phiên làm việc" + }, + "fields": { + "status": "Trạng thái", + "priority": "Mức độ ưu tiên", + "assignee": "Người phụ trách", + "workItemId": "ID mục công việc", + "session": "Phiên làm việc", + "comments": "Bình luận", + "threadId": "ID chuỗi", + "commentId": "ID bình luận" + }, + "workItemStatus": { + "backlog": "Tồn đọng", + "todo": "Cần làm", + "in_progress": "Đang thực hiện", + "in_review": "Đang xem xét", + "blocked": "Bị chặn", + "done": "Hoàn thành", + "cancelled": "Đã hủy" + }, + "priority": { + "none": "Không ưu tiên", + "low": "Thấp", + "medium": "Trung bình", + "high": "Cao", + "urgent": "Khẩn cấp" + } + }, "toasts": { "replyEmpty": "Câu trả lời không được để trống", "sessionNotFound": "Không tìm thấy phiên", diff --git a/src/i18n/locales/zh-Hant/common.json b/src/i18n/locales/zh-Hant/common.json index ccf142f07..e08976b3a 100644 --- a/src/i18n/locales/zh-Hant/common.json +++ b/src/i18n/locales/zh-Hant/common.json @@ -1,4 +1,160 @@ { + "teamInbox": { + "title": "團隊收件匣", + "listLabel": "團隊收件匣清單", + "itemsLabel": "團隊收件匣項目", + "unreadCount": "{{count}} 則未讀", + "allRead": "已全部閱讀", + "loadMore": "載入更多", + "filters": { + "all": "全部", + "mentions": "提及", + "assigned": "已指派給我" + }, + "status": { + "read": "已讀", + "unread": "未讀" + }, + "row": { + "assignedSummary": "{{status}} · {{priority}}", + "ariaLabel": "{{title}},{{status}}" + }, + "search": { + "placeholder": "搜尋收件匣", + "ariaLabel": "搜尋團隊收件匣" + }, + "groups": { + "today": "今天", + "yesterday": "昨天", + "thisWeek": "本週", + "earlier": "更早" + }, + "empty": { + "title": "目前尚無項目", + "subtitle": "新的提及與指派的工作項目會顯示在這裡。", + "selectTitle": "選擇一個項目", + "selectSubtitle": "查看留言脈絡或工作項目詳情。", + "mentions": { + "title": "尚無提及", + "subtitle": "當同事在留言中以 @ 提及你時,會顯示在這裡。" + }, + "assigned": { + "title": "尚無指派給你的項目", + "subtitle": "指派給你的工作項目會顯示在這裡。" + }, + "noResults": { + "title": "沒有相符結果", + "subtitle": "沒有與「{{query}}」相符的項目。" + } + }, + "loading": "正在載入團隊收件匣…", + "drop": { + "title": "拖曳到這裡以建立工作項目", + "subtitle": "先確認工作階段快照,再建立或交接工作項目。", + "processing": "正在從「{{title}}」建立工作項目…", + "processingHint": "正在讀取工作階段並解析專案成員。", + "success": "工作項目已建立", + "reused": "已更新現有工作項目", + "failed": "無法建立工作項目", + "error": "無法根據此工作階段建立工作項目。", + "open": "開啟", + "dismiss": "關閉" + }, + "handoff": { + "title": "從工作階段建立", + "createFromSession": "建立團隊工作項目…", + "project": "目標專案", + "chooseProject": "選擇專案", + "recipientSelf": "{{name}}(我)", + "chooseRecipient": "選擇接收人", + "todoCount_other": "{{count}} 項待辦", + "workItemTitle": "工作項目標題", + "assignTo": "指派給", + "note": "交接說明", + "notePlaceholder": "說明已完成的事項、尚未解決的部分,以及接下來該做什麼。", + "selfHint": "指派給自己會建立一般工作項目,不會發出交接請求。", + "submitHandoff": "建立並交接", + "submitCreate": "建立工作項目", + "preparing": "正在準備「{{title}}」…", + "preparationError": { + "session_unavailable": "此工作階段已無法使用,請重新開啟後再試一次。", + "project_unavailable": "此工作階段所屬的專案已無法使用。", + "identity_unavailable": "你的身分並非此工作階段所屬專案的成員。", + "no_project": "沒有可用的合適專案,請先建立或加入專案後再試一次。", + "unknown": "無法準備此工作階段,請重新整理團隊收件匣後再試一次。" + }, + "submitError": "無法建立工作項目,請檢查接收人後再試一次。", + "pendingTitle": "來自 {{name}} 的交接", + "acceptedTitle": "{{name}} 已接受", + "returnedTitle": "{{name}} 已退回", + "noNote": "沒有交接說明。", + "statusLabel": "工作項目交接", + "return": "退回", + "accept": "接受", + "returnTitle": "要退回這次交接嗎?", + "confirmReturn": "退回給發送者", + "returnHint": "告訴 {{name}} 需要釐清或補充的內容,工作項目將重新指派給對方。", + "returnPlaceholder": "在再次交接之前需要調整什麼?", + "responseError": "無法儲存交接回應,請再試一次。", + "identityUnavailable": "無法驗證你的團隊身分,請先檢查專案個人資料再回應。", + "rowPending": "來自 {{name}} · 等待回應", + "rowAccepted": "已接受交接 · {{status}} · {{priority}}", + "rowReturned": "{{name}} 已退回 · {{status}} · {{priority}}" + }, + "errors": { + "loadTitle": "無法載入團隊收件匣", + "load": "無法載入團隊收件匣", + "loadMore": "無法載入更多團隊收件匣項目,請再試一次。", + "refresh": "無法重新整理團隊收件匣", + "markRead": "無法將此項目標記為已讀,請再試一次。", + "markUnread": "無法將此項目標記為未讀,請再試一次。", + "markAllRead": "無法將所有項目標記為已讀,請再試一次。", + "identity": "無法將你的帳戶與專案成員配對,請檢查專案個人資料中的電子郵件。", + "partialLoad": "部分團隊收件匣來源無法重新整理,現有項目仍會繼續顯示。", + "workItemContext": "部分專案內容暫時無法使用,工作項目仍可繼續操作。", + "workItemLoad": "無法載入此工作項目,請再試一次。", + "workItemUpdate": "無法儲存工作項目的最新變更,請再試一次。" + }, + "detail": { + "assignedSubtitle": "已指派的工作項目", + "standaloneProject": "獨立項目", + "mentionSubtitle": "在留言中被提及", + "mentionedYou": "提及了你", + "threadComments_other": "此討論串中有 {{count}} 則留言" + }, + "actions": { + "markRead": "標記為已讀", + "markUnread": "標記為未讀", + "openWorkItem": "開啟工作項目", + "openSession": "開啟工作階段" + }, + "fields": { + "status": "狀態", + "priority": "優先順序", + "assignee": "負責人", + "workItemId": "工作項目 ID", + "session": "工作階段", + "comments": "留言", + "threadId": "討論串 ID", + "commentId": "留言 ID" + }, + "workItemStatus": { + "backlog": "待辦清單", + "todo": "待辦", + "in_progress": "進行中", + "in_review": "審核中", + "blocked": "受阻", + "done": "已完成", + "cancelled": "已取消" + }, + "priority": { + "none": "無優先順序", + "low": "低", + "medium": "中", + "high": "高", + "urgent": "緊急" + } + }, "toasts": { "replyEmpty": "回覆不能為空", "sessionNotFound": "找不到 Session",