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([]);
});