From b7c8be408143e00f88f5756e874729232d28c68f Mon Sep 17 00:00:00 2001
From: "paseo-bot[bot]" <266920839+paseo-bot[bot]@users.noreply.github.com>
Date: Tue, 6 Oct 2026 12:55:44 +0200
Subject: [PATCH] Show the PR panel's Activity and Add to chat labels in the
app language (#6208)
* fix(app): show PR panel activity and add-to-chat labels in the app language
The PR panel's Activity header, its empty state, every "Add to chat"
button, "Add all to chat", "Adding...", and the comment and thread menu
labels were written in the components, so they stayed English in every
other language. The sidebar status group rows also appended an English
" group" to their accessibility label. They now come from the
translation files, with copy for all nine supported languages.
Closes #6203
* test(app): check the new PR panel labels are translated in every language
---------
Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
---
.../sidebar/sidebar-status-list.tsx | 3 +-
.../git/pull-request-panel/checks-section.tsx | 5 +-
.../app/src/git/pull-request-panel/pane.tsx | 22 +++++----
packages/app/src/i18n/resources.test.ts | 46 +++++++++++++++++++
packages/app/src/i18n/resources/ar.ts | 8 ++++
packages/app/src/i18n/resources/en.ts | 8 ++++
packages/app/src/i18n/resources/es.ts | 8 ++++
packages/app/src/i18n/resources/fr.ts | 8 ++++
packages/app/src/i18n/resources/ja.ts | 8 ++++
packages/app/src/i18n/resources/ko.ts | 8 ++++
packages/app/src/i18n/resources/pt-BR.ts | 8 ++++
packages/app/src/i18n/resources/ru.ts | 8 ++++
packages/app/src/i18n/resources/zh-CN.ts | 8 ++++
13 files changed, 136 insertions(+), 12 deletions(-)
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: "失败",