diff --git a/packages/app/src/components/sidebar/sidebar-status-list.tsx b/packages/app/src/components/sidebar/sidebar-status-list.tsx index 051121fd3f..c299d07987 100644 --- a/packages/app/src/components/sidebar/sidebar-status-list.tsx +++ b/packages/app/src/components/sidebar/sidebar-status-list.tsx @@ -408,6 +408,7 @@ function StatusGroupHeader({ group: SidebarWorkspaceGroup; collapsed: boolean; }) { + const { t } = useTranslation(); const [isHovered, setIsHovered] = useState(false); const toggleWorkspaceGroupCollapsed = useSidebarCollapsedSectionsStore( (state) => state.toggleWorkspaceGroupCollapsed, @@ -431,7 +432,7 @@ function StatusGroupHeader({ void; }) { + const { t } = useTranslation(); const handlePress = useCallback(() => { void openExternalUrl(check.url); }, [check.url]); @@ -220,7 +221,9 @@ function CheckRow({ onPress={handleAddLogsToChat} style={styles.addButton} > - {isAddingLogsToChat ? "Adding..." : "Add to chat"} + {isAddingLogsToChat + ? t("workspace.git.pr.actions.addingToChat") + : t("workspace.git.pr.actions.addToChat")} ) : null} {check.timing && {check.timing}} diff --git a/packages/app/src/git/pull-request-panel/pane.tsx b/packages/app/src/git/pull-request-panel/pane.tsx index b7c0890c3a..4b468e14e2 100644 --- a/packages/app/src/git/pull-request-panel/pane.tsx +++ b/packages/app/src/git/pull-request-panel/pane.tsx @@ -568,7 +568,7 @@ export function PullRequestPane({
- Add all to chat + {t("workspace.git.pr.actions.addAllToChat")} ) : null} {activityLoading ? : null} {!activityLoading && visibleEntries.length === 0 ? ( - No activity yet + {t("workspace.git.pr.empty.noActivity")} ) : null} {!activityLoading ? visibleEntries.map(({ entry, collapsed }) => ( @@ -702,14 +702,14 @@ function ActivityKebab({ {renderKebabTriggerIcon} {attachEnabled && canAddPullRequestActivityToChat(activity) ? ( - Add to chat + {t("workspace.git.pr.actions.addToChat")} ) : null} {activity.body.trim() !== "" ? ( @@ -815,6 +815,7 @@ function SingleActivityCard({ entry: Extract; collapsed: boolean; }) { + const { t } = useTranslation(); const { activity } = entry; const { actionsVisible, handlePointerEnter, handlePointerLeave, setMenuOpen } = useRevealOnHover(); @@ -884,7 +885,7 @@ function SingleActivityCard({ leftIcon={MessageSquarePlus} onPress={handleAddToChat} > - Add to chat + {t("workspace.git.pr.actions.addToChat")} ) : null} @@ -935,6 +936,7 @@ function ReviewCard({ collapsed: boolean; collapsedEntryIds: ReadonlySet; }) { + const { t } = useTranslation(); const { review, threads } = entry; const { actionsVisible, handlePointerEnter, handlePointerLeave, setMenuOpen } = useRevealOnHover(); @@ -961,7 +963,7 @@ function ReviewCard({ onPress={handleAddToChat} style={styles.checkAddButton} > - Add to chat + {t("workspace.git.pr.actions.addToChat")} ) : null} {collapsed ? ( @@ -995,7 +997,7 @@ function ReviewCard({ leftIcon={MessageSquarePlus} onPress={handleAddToChat} > - Add to chat + {t("workspace.git.pr.actions.addToChat")} ) : null} @@ -1080,7 +1082,7 @@ function ThreadBlock({ {renderKebabTriggerIcon} @@ -1124,7 +1126,7 @@ function ThreadBlock({ leftIcon={MessageSquarePlus} onPress={handleAddThreadToChat} > - Add to chat + {t("workspace.git.pr.actions.addToChat")} ) : null} diff --git a/packages/app/src/i18n/resources.test.ts b/packages/app/src/i18n/resources.test.ts index 2b83055774..039242710e 100644 --- a/packages/app/src/i18n/resources.test.ts +++ b/packages/app/src/i18n/resources.test.ts @@ -74,6 +74,34 @@ const untranslatedLocalFallbacks = [ "Unable to save desktop settings.", ] as const; +const pullRequestPanelSources = [ + "git/pull-request-panel/pane.tsx", + "git/pull-request-panel/checks-section.tsx", + "components/sidebar/sidebar-status-list.tsx", +] as const; +const untranslatedPullRequestPanelLabels = [ + "Activity", + "No activity yet", + "Add all to chat", + "Add to chat", + "Adding...", + "Comment actions", + "Thread actions", +] as const; + +function findUntranslatedPullRequestPanelLabels(): string[] { + return pullRequestPanelSources.flatMap((source) => { + const contents = readFileSync(join(appSourceRoot, source), "utf8"); + const matches: string[] = untranslatedPullRequestPanelLabels.filter( + (text) => contents.includes(`"${text}"`) || new RegExp(`>\\s*${text}\\s*<`).test(contents), + ); + if (contents.includes("} group`")) { + matches.push("group"); + } + return matches.length === 0 ? [] : [`${source}: ${matches.join(", ")}`]; + }); +} + function collectSourceFiles(directory: string): string[] { return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => { const path = join(directory, entry.name); @@ -204,6 +232,24 @@ describe("translation resources", () => { expect(en.workspace.fileActions.addToChat).toBe("Add to chat"); }); + it("keeps pull request panel and sidebar status group labels translated", () => { + expect(findUntranslatedPullRequestPanelLabels()).toEqual([]); + for (const resource of [ar, es, fr, ja, ko, ptBR, ru, zhCN]) { + const pr = resource.workspace.git.pr; + const englishPr = en.workspace.git.pr; + expect(pr.sections.activity).not.toBe(englishPr.sections.activity); + expect(pr.empty.noActivity).not.toBe(englishPr.empty.noActivity); + expect(pr.actions.addToChat).not.toBe(englishPr.actions.addToChat); + expect(pr.actions.addAllToChat).not.toBe(englishPr.actions.addAllToChat); + expect(pr.actions.addingToChat).not.toBe(englishPr.actions.addingToChat); + expect(pr.accessibility.commentActions).not.toBe(englishPr.accessibility.commentActions); + expect(pr.accessibility.threadActions).not.toBe(englishPr.accessibility.threadActions); + expect(resource.sidebar.statusGroupAccessibility).not.toBe( + en.sidebar.statusGroupAccessibility, + ); + } + }); + it("keeps local connection fallback errors translated", () => { expect(findUntranslatedConnectionErrors()).toEqual([]); }); diff --git a/packages/app/src/i18n/resources/ar.ts b/packages/app/src/i18n/resources/ar.ts index 8a6338fe1e..5b684c4545 100644 --- a/packages/app/src/i18n/resources/ar.ts +++ b/packages/app/src/i18n/resources/ar.ts @@ -973,6 +973,9 @@ export const ar: TranslationResources = { actions: { viewPullRequest: "عرض", openOn: "فتح على {{brand}}", + addToChat: "إضافة إلى الدردشة", + addAllToChat: "إضافة الكل إلى الدردشة", + addingToChat: "جارٍ الإضافة...", }, checksOverview: { headline: { @@ -1024,17 +1027,21 @@ export const ar: TranslationResources = { checks: "الشيكات", pipeline: "خط المعالجة", reviews: "التعليقات", + activity: "النشاط", }, empty: { noJobs: "لا توجد مهام", loadingPipeline: "جارٍ تحميل خط المعالجة...", pipelineJobsLoadFailed: "تعذر تحميل مهام خط المعالجة", allowedToFail: "مسموح بالفشل", + noActivity: "لا يوجد نشاط بعد", }, approvals: "{{given}} من {{required}} موافقات", accessibility: { pullRequest: "سحب الطلب #{{number}}", pullRequest_mr: "طلب دمج !{{number}}", + commentActions: "إجراءات التعليق", + threadActions: "إجراءات سلسلة النقاش", checkStatus: { passed: "ناجح", failed: "فاشل", @@ -1129,6 +1136,7 @@ export const ar: TranslationResources = { }, }, sidebar: { + statusGroupAccessibility: "مجموعة {{label}}", statusBucket: { needsInput: "تحتاج إدخالاً", failed: "فشل", diff --git a/packages/app/src/i18n/resources/en.ts b/packages/app/src/i18n/resources/en.ts index 5ae4bc29cd..35230d4aaa 100644 --- a/packages/app/src/i18n/resources/en.ts +++ b/packages/app/src/i18n/resources/en.ts @@ -981,6 +981,9 @@ export const en = { actions: { viewPullRequest: "View", openOn: "Open on {{brand}}", + addToChat: "Add to chat", + addAllToChat: "Add all to chat", + addingToChat: "Adding...", }, checksOverview: { headline: { @@ -1032,17 +1035,21 @@ export const en = { checks: "Checks", pipeline: "Pipeline", reviews: "Reviews", + activity: "Activity", }, empty: { noJobs: "No jobs", loadingPipeline: "Loading pipeline…", pipelineJobsLoadFailed: "Could not load pipeline jobs", allowedToFail: "allowed to fail", + noActivity: "No activity yet", }, approvals: "{{given}} of {{required}} approvals", accessibility: { pullRequest: "Pull request #{{number}}", pullRequest_mr: "Merge request !{{number}}", + commentActions: "Comment actions", + threadActions: "Thread actions", checkStatus: { passed: "Passed", failed: "Failed", @@ -1137,6 +1144,7 @@ export const en = { }, }, sidebar: { + statusGroupAccessibility: "{{label}} group", statusBucket: { needsInput: "Needs input", failed: "Failed", diff --git a/packages/app/src/i18n/resources/es.ts b/packages/app/src/i18n/resources/es.ts index 1c34d7f5b6..18346ad126 100644 --- a/packages/app/src/i18n/resources/es.ts +++ b/packages/app/src/i18n/resources/es.ts @@ -1006,6 +1006,9 @@ export const es: TranslationResources = { actions: { viewPullRequest: "Ver", openOn: "Abrir en {{brand}}", + addToChat: "Añadir al chat", + addAllToChat: "Añadir todo al chat", + addingToChat: "Añadiendo...", }, checksOverview: { headline: { @@ -1057,17 +1060,21 @@ export const es: TranslationResources = { checks: "cheques", pipeline: "Pipeline", reviews: "Reseñas", + activity: "Actividad", }, empty: { noJobs: "Sin trabajos", loadingPipeline: "Cargando pipeline...", pipelineJobsLoadFailed: "No se pudieron cargar los trabajos del pipeline", allowedToFail: "permitido fallar", + noActivity: "Aún no hay actividad", }, approvals: "{{given}} de {{required}} aprobaciones", accessibility: { pullRequest: "Solicitud de extracción n.°{{number}}", pullRequest_mr: "Solicitud de fusión !{{number}}", + commentActions: "Acciones del comentario", + threadActions: "Acciones del hilo", checkStatus: { passed: "Superado", failed: "Fallido", @@ -1165,6 +1172,7 @@ export const es: TranslationResources = { }, }, sidebar: { + statusGroupAccessibility: "Grupo {{label}}", statusBucket: { needsInput: "Necesita datos", failed: "Con error", diff --git a/packages/app/src/i18n/resources/fr.ts b/packages/app/src/i18n/resources/fr.ts index c682d05baf..6f21c9ad90 100644 --- a/packages/app/src/i18n/resources/fr.ts +++ b/packages/app/src/i18n/resources/fr.ts @@ -997,6 +997,9 @@ export const fr: TranslationResources = { actions: { viewPullRequest: "Voir", openOn: "Ouvrir sur {{brand}}", + addToChat: "Ajouter à la conversation", + addAllToChat: "Tout ajouter à la conversation", + addingToChat: "Ajout…", }, checksOverview: { headline: { @@ -1048,17 +1051,21 @@ export const fr: TranslationResources = { checks: "Vérifications", pipeline: "Pipeline", reviews: "Revues", + activity: "Activité", }, empty: { noJobs: "Aucun job", loadingPipeline: "Chargement du pipeline…", pipelineJobsLoadFailed: "Impossible de charger les jobs du pipeline", allowedToFail: "échec autorisé", + noActivity: "Aucune activité pour le moment", }, approvals: "{{given}} sur {{required}} approbations", accessibility: { pullRequest: "Pull request #{{number}}", pullRequest_mr: "Merge request !{{number}}", + commentActions: "Actions du commentaire", + threadActions: "Actions du fil", checkStatus: { passed: "Réussie", failed: "Échec", @@ -1156,6 +1163,7 @@ export const fr: TranslationResources = { }, }, sidebar: { + statusGroupAccessibility: "Groupe {{label}}", statusBucket: { needsInput: "Attend une réponse", failed: "Échec", diff --git a/packages/app/src/i18n/resources/ja.ts b/packages/app/src/i18n/resources/ja.ts index 7d562247b2..14fc6f2f69 100644 --- a/packages/app/src/i18n/resources/ja.ts +++ b/packages/app/src/i18n/resources/ja.ts @@ -986,6 +986,9 @@ export const ja: TranslationResources = { actions: { viewPullRequest: "表示", openOn: "{{brand}}で開く", + addToChat: "チャットに追加", + addAllToChat: "すべてチャットに追加", + addingToChat: "追加中...", }, checksOverview: { headline: { @@ -1037,17 +1040,21 @@ export const ja: TranslationResources = { checks: "チェック", pipeline: "パイプライン", reviews: "レビュー", + activity: "アクティビティ", }, empty: { noJobs: "ジョブなし", loadingPipeline: "パイプラインを読み込み中...", pipelineJobsLoadFailed: "パイプラインのジョブを読み込めませんでした", allowedToFail: "失敗を許可", + noActivity: "まだアクティビティはありません", }, approvals: "{{given}} / {{required}} 承認", accessibility: { pullRequest: "プルリクエスト#{{number}}", pullRequest_mr: "マージリクエスト !{{number}}", + commentActions: "コメントの操作", + threadActions: "スレッドの操作", checkStatus: { passed: "成功", failed: "失敗", @@ -1142,6 +1149,7 @@ export const ja: TranslationResources = { }, }, sidebar: { + statusGroupAccessibility: "{{label}} グループ", statusBucket: { needsInput: "入力待ち", failed: "失敗", diff --git a/packages/app/src/i18n/resources/ko.ts b/packages/app/src/i18n/resources/ko.ts index 5b325a5be6..95ac1e2bbd 100644 --- a/packages/app/src/i18n/resources/ko.ts +++ b/packages/app/src/i18n/resources/ko.ts @@ -980,6 +980,9 @@ export const ko: TranslationResources = { actions: { viewPullRequest: "보기", openOn: "{{brand}}에서 열기", + addToChat: "채팅에 추가", + addAllToChat: "모두 채팅에 추가", + addingToChat: "추가 중...", }, checksOverview: { headline: { @@ -1031,17 +1034,21 @@ export const ko: TranslationResources = { checks: "검사", pipeline: "파이프라인", reviews: "리뷰", + activity: "활동", }, empty: { noJobs: "작업 없음", loadingPipeline: "파이프라인 로드 중…", pipelineJobsLoadFailed: "파이프라인 작업을 로드할 수 없습니다.", allowedToFail: "실패가 허용됨", + noActivity: "아직 활동이 없습니다", }, approvals: "{{required}} 중 {{given}} 승인", accessibility: { pullRequest: "풀 리퀘스트 #{{number}}", pullRequest_mr: "병합 요청 !{{number}}", + commentActions: "댓글 작업", + threadActions: "스레드 작업", checkStatus: { passed: "통과", failed: "실패", @@ -1136,6 +1143,7 @@ export const ko: TranslationResources = { }, }, sidebar: { + statusGroupAccessibility: "{{label}} 그룹", statusBucket: { needsInput: "입력 필요", failed: "실패", diff --git a/packages/app/src/i18n/resources/pt-BR.ts b/packages/app/src/i18n/resources/pt-BR.ts index d86b0f58d3..626dec1e3c 100644 --- a/packages/app/src/i18n/resources/pt-BR.ts +++ b/packages/app/src/i18n/resources/pt-BR.ts @@ -996,6 +996,9 @@ export const ptBR: TranslationResources = { actions: { viewPullRequest: "Ver", openOn: "Abrir no {{brand}}", + addToChat: "Adicionar ao chat", + addAllToChat: "Adicionar tudo ao chat", + addingToChat: "Adicionando...", }, checksOverview: { headline: { @@ -1047,17 +1050,21 @@ export const ptBR: TranslationResources = { checks: "Verificações", pipeline: "Pipeline", reviews: "Revisões", + activity: "Atividade", }, empty: { noJobs: "Sem jobs", loadingPipeline: "Carregando pipeline...", pipelineJobsLoadFailed: "Não foi possível carregar os jobs do pipeline", allowedToFail: "permitido falhar", + noActivity: "Nenhuma atividade ainda", }, approvals: "{{given}} de {{required}} aprovações", accessibility: { pullRequest: "Pull request #{{number}}", pullRequest_mr: "Merge request !{{number}}", + commentActions: "Ações do comentário", + threadActions: "Ações da conversa", checkStatus: { passed: "Aprovado", failed: "Falhou", @@ -1155,6 +1162,7 @@ export const ptBR: TranslationResources = { }, }, sidebar: { + statusGroupAccessibility: "Grupo {{label}}", statusBucket: { needsInput: "Precisa de resposta", failed: "Com falha", diff --git a/packages/app/src/i18n/resources/ru.ts b/packages/app/src/i18n/resources/ru.ts index ac5ab8d2e0..59562e626b 100644 --- a/packages/app/src/i18n/resources/ru.ts +++ b/packages/app/src/i18n/resources/ru.ts @@ -990,6 +990,9 @@ export const ru: TranslationResources = { actions: { viewPullRequest: "Просмотреть", openOn: "Открыть на {{brand}}", + addToChat: "Добавить в чат", + addAllToChat: "Добавить всё в чат", + addingToChat: "Добавление...", }, checksOverview: { headline: { @@ -1041,17 +1044,21 @@ export const ru: TranslationResources = { checks: "Проверки", pipeline: "Пайплайн", reviews: "Ревью", + activity: "Активность", }, empty: { noJobs: "Нет заданий", loadingPipeline: "Загрузка пайплайна...", pipelineJobsLoadFailed: "Не удалось загрузить задания пайплайна", allowedToFail: "допускается сбой", + noActivity: "Активности пока нет", }, approvals: "Одобрено: {{given}} из {{required}}", accessibility: { pullRequest: "PR #{{number}}", pullRequest_mr: "MR !{{number}}", + commentActions: "Действия с комментарием", + threadActions: "Действия с обсуждением", checkStatus: { passed: "Успешно", failed: "Ошибка", @@ -1146,6 +1153,7 @@ export const ru: TranslationResources = { }, }, sidebar: { + statusGroupAccessibility: "Группа «{{label}}»", statusBucket: { needsInput: "Ожидает ввода", failed: "Ошибка", diff --git a/packages/app/src/i18n/resources/zh-CN.ts b/packages/app/src/i18n/resources/zh-CN.ts index 7120b7d80e..deb75a2a92 100644 --- a/packages/app/src/i18n/resources/zh-CN.ts +++ b/packages/app/src/i18n/resources/zh-CN.ts @@ -965,6 +965,9 @@ export const zhCN: TranslationResources = { actions: { viewPullRequest: "查看", openOn: "在 {{brand}} 上打开", + addToChat: "添加到聊天", + addAllToChat: "全部添加到聊天", + addingToChat: "正在添加...", }, checksOverview: { headline: { @@ -1016,17 +1019,21 @@ export const zhCN: TranslationResources = { checks: "Checks", pipeline: "流水线", reviews: "Reviews", + activity: "动态", }, empty: { noJobs: "无作业", loadingPipeline: "正在加载流水线...", pipelineJobsLoadFailed: "无法加载流水线作业", allowedToFail: "允许失败", + noActivity: "暂无动态", }, approvals: "{{given}} / {{required}} 批准", accessibility: { pullRequest: "Pull request #{{number}}", pullRequest_mr: "合并请求 !{{number}}", + commentActions: "评论操作", + threadActions: "讨论串操作", checkStatus: { passed: "成功", failed: "失败", @@ -1121,6 +1128,7 @@ export const zhCN: TranslationResources = { }, }, sidebar: { + statusGroupAccessibility: "{{label}} 分组", statusBucket: { needsInput: "需要输入", failed: "失败",