fix(i18n): replace raw translation keys on panel screens (#7057)

Use valid translation keys on six panel screens, add the missing copy-failure and empty-value strings across all locales, and reject unresolved literal translation keys in the regression test.
This commit is contained in:
Cheng Ho Ming, Eric
2026-11-06 01:10:09 +08:00
committed by GitHub
parent f4030c889c
commit b54325dcc9
20 changed files with 42 additions and 13 deletions
@@ -95,7 +95,7 @@ export default function ClientBulkAdjustModal({
<Modal
open={open}
title={t('pages.clients.bulkAdjustTitle', { count })}
okText={t('apply')}
okText={t('confirm')}
cancelText={t('cancel')}
confirmLoading={submitting}
onOk={handleOk}
+2 -2
View File
@@ -128,7 +128,7 @@ export default function FilterDrawer({
/>
</Form.Item>
<Form.Item label={t('inbounds')} htmlFor={`${uid}-inbounds`}>
<Form.Item label={t('pages.clients.attachedInbounds')} htmlFor={`${uid}-inbounds`}>
<Select
id={`${uid}-inbounds`}
mode="multiple"
@@ -136,7 +136,7 @@ export default function FilterDrawer({
value={filters.inboundIds}
onChange={(v) => patch('inboundIds', v as number[])}
options={inboundOptions}
placeholder={t('inbounds')}
placeholder={t('pages.clients.attachedInbounds')}
allowClear
showSearch={{ optionFilterProp: 'label' }}
listHeight={220}
@@ -69,7 +69,7 @@ export default function TuicFields() {
if (obj.webKeyFile) {
setValue('settings.server.private_key', obj.webKeyFile);
}
messageApi.success(t('pages.inbounds.setSuccess'));
messageApi.success(t('success'));
} catch {
messageApi.error(t('somethingWentWrong'));
} finally {
+1 -1
View File
@@ -169,7 +169,7 @@ export default function SecurityTab({ allSetting, updateSetting, saveSetting }:
if (!token) return;
const ok = await ClipboardManager.copyText(token);
if (ok) messageApi.success(t('copySuccess'));
else messageApi.error(t('copyFail') ?? 'Copy failed');
else messageApi.error(t('copyFail'));
}
function openCreateModal() {
@@ -291,7 +291,7 @@ export default function WarpModal({
interval: methods.getValues('updateInterval'),
});
if (msg?.success) {
messageApi.success(t('pages.setting.toasts.saveSuccess', 'Settings saved successfully'));
messageApi.success(t('pages.settings.toasts.modifySettings'));
}
} finally {
setLoading(false);
+8 -7
View File
@@ -82,14 +82,15 @@ describe('i18n keys', () => {
);
});
it('no literal t() key resolves to an object', () => {
const objectKeys = Array.from(
blob.matchAll(/\bt\(\s*(['"`])([\w.-]+)\1\s*[,)]/g),
(m) => m[2],
).filter((key) => enKeys.some((leaf) => leaf.startsWith(`${key}.`)));
it('every literal t() key is an en-US string', () => {
const leaves = new Set(enKeys);
const literalKeys = new Set(
Array.from(blob.matchAll(/\bt\(\s*(['"`])([\w.-]+)\1\s*[,)]/g), (m) => m[2]),
);
const unresolved = [...literalKeys].filter((key) => !leaves.has(key));
expect(
objectKeys,
`t() keys naming a group, rendered as "key '…' returned an object instead of string.":\n ${objectKeys.join('\n ')}`,
unresolved,
`t() keys that are not an en-US string (a missing key renders raw, a group renders "key '…' returned an object instead of string."):\n ${unresolved.join('\n ')}`,
).toEqual([]);
});
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "غير محدد",
"unlimited": "غير محدود",
"none": "لا شيء",
"empty": "فارغ",
"qrCode": "كود QR",
"info": "معلومات أكتر",
"edit": "تحرير",
@@ -47,6 +48,7 @@
"reset": "إعادة تعيين",
"noData": "لا توجد بيانات.",
"copySuccess": "اتنسخ بنجاح",
"copyFail": "فشل النسخ",
"sure": "متأكد؟",
"encryption": "تشفير",
"transmission": "نقل",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "Indefinite",
"unlimited": "Unlimited",
"none": "None",
"empty": "Empty",
"qrCode": "QR Code",
"info": "More Information",
"edit": "Edit",
@@ -47,6 +48,7 @@
"reset": "Reset",
"noData": "Nothing here yet",
"copySuccess": "Copied successfully",
"copyFail": "Copy failed",
"sure": "Sure",
"encryption": "Encryption",
"transmission": "Transmission",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "Indefinido",
"unlimited": "Ilimitado",
"none": "Ninguno",
"empty": "Vacío",
"qrCode": "Código QR",
"info": "Más Información",
"edit": "Editar",
@@ -47,6 +48,7 @@
"reset": "Restablecer",
"noData": "Sin datos",
"copySuccess": "Copiado exitosamente",
"copyFail": "Error al copiar",
"sure": "Seguro",
"encryption": "Encriptación",
"transmission": "Transmisión",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "نامحدود",
"unlimited": "نامحدود",
"none": "هیچ",
"empty": "خالی",
"qrCode": "QRکد",
"info": "اطلاعات بیشتر",
"edit": "ویرایش",
@@ -47,6 +48,7 @@
"reset": "بازنشانی",
"noData": "داده‌ای وجود ندارد.",
"copySuccess": "باموفقیت کپی‌شد",
"copyFail": "کپی ناموفق بود",
"sure": "مطمئن",
"encryption": "رمزگذاری",
"transmission": "راه‌اتصال",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "Tak Terbatas",
"unlimited": "Tanpa Batas",
"none": "Tidak ada",
"empty": "Kosong",
"qrCode": "Kode QR",
"info": "Informasi Lebih Lanjut",
"edit": "Edit",
@@ -47,6 +48,7 @@
"reset": "Reset",
"noData": "Tidak ada data.",
"copySuccess": "Berhasil Disalin",
"copyFail": "Gagal Menyalin",
"sure": "Yakin",
"encryption": "Enkripsi",
"transmission": "Transmisi",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "無期限",
"unlimited": "無制限",
"none": "なし",
"empty": "空欄",
"qrCode": "QRコード",
"info": "詳細情報",
"edit": "編集",
@@ -47,6 +48,7 @@
"reset": "リセット",
"noData": "データなし。",
"copySuccess": "コピー成功",
"copyFail": "コピー失敗",
"sure": "確定",
"encryption": "暗号化",
"transmission": "伝送",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "Indeterminado",
"unlimited": "Ilimitado",
"none": "Nenhum",
"empty": "Vazio",
"qrCode": "Código QR",
"info": "Mais Informações",
"edit": "Editar",
@@ -47,6 +48,7 @@
"reset": "Redefinir",
"noData": "Sem dados.",
"copySuccess": "Copiado com Sucesso",
"copyFail": "Falha ao Copiar",
"sure": "Certo",
"encryption": "Criptografia",
"transmission": "Transmissão",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "Бесконечно",
"unlimited": "Безлимит",
"none": "Нет",
"empty": "Пусто",
"qrCode": "QR-код",
"info": "Информация",
"edit": "Изменить",
@@ -47,6 +48,7 @@
"reset": "Сброс",
"noData": "Нет данных.",
"copySuccess": "Скопировано",
"copyFail": "Не удалось скопировать",
"sure": "Да",
"encryption": "Шифрование",
"transmission": "Транспорт",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "Bez časového obmedzenia",
"unlimited": "Bez obmedzenia",
"none": "Žiadne",
"empty": "Prázdne",
"qrCode": "QR kód",
"info": "Ďalšie informácie",
"edit": "Upraviť",
@@ -47,6 +48,7 @@
"reset": "Vynulovať",
"noData": "Zatiaľ tu nič nie je",
"copySuccess": "Úspešne skopírované",
"copyFail": "Kopírovanie zlyhalo",
"sure": "Áno",
"encryption": "Šifrovanie",
"transmission": "Prenos",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "Belirsiz",
"unlimited": "Sınırsız",
"none": "Yok",
"empty": "Boş",
"qrCode": "QR Kod",
"info": "Daha Fazla Bilgi",
"edit": "Düzenle",
@@ -47,6 +48,7 @@
"reset": "Sıfırla",
"noData": "Veri yok.",
"copySuccess": "Başarıyla kopyalandı",
"copyFail": "Kopyalama başarısız",
"sure": "Emin misiniz?",
"encryption": "Şifreleme",
"transmission": "İletim",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "Безстроково",
"unlimited": "Безлімітний",
"none": "Немає",
"empty": "Порожньо",
"qrCode": "QR-Код",
"info": "Більше інформації",
"edit": "Змінити",
@@ -47,6 +48,7 @@
"reset": "Скидання",
"noData": "Немає даних.",
"copySuccess": "Скопійовано успішно",
"copyFail": "Не вдалося скопіювати",
"sure": "Звичайно",
"encryption": "Шифрування",
"transmission": "Протокол передачи",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "Không xác định",
"unlimited": "Không giới hạn",
"none": "Không",
"empty": "Trống",
"qrCode": "Mã QR",
"info": "Thông tin thêm",
"edit": "Sửa",
@@ -47,6 +48,7 @@
"reset": "Đặt lại",
"noData": "Không có dữ liệu.",
"copySuccess": "Đã sao chép thành công",
"copyFail": "Sao chép thất bại",
"sure": "Chắc chắn",
"encryption": "Mã hóa",
"transmission": "Truyền tải",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "无限期",
"unlimited": "无限制",
"none": "无",
"empty": "空",
"qrCode": "二维码",
"info": "更多信息",
"edit": "编辑",
@@ -47,6 +48,7 @@
"reset": "重置",
"noData": "无数据。",
"copySuccess": "复制成功",
"copyFail": "复制失败",
"sure": "确定",
"encryption": "加密",
"transmission": "传输",
+2
View File
@@ -40,6 +40,7 @@
"indefinite": "無限期",
"unlimited": "無限制",
"none": "無",
"empty": "空",
"qrCode": "二維碼",
"info": "更多資訊",
"edit": "編輯",
@@ -47,6 +48,7 @@
"reset": "重置",
"noData": "無數據。",
"copySuccess": "複製成功",
"copyFail": "複製失敗",
"sure": "確定",
"encryption": "加密",
"transmission": "傳輸",