diff --git a/frontend/src/pages/xray/routing/RuleCardList.tsx b/frontend/src/pages/xray/routing/RuleCardList.tsx index ffa43c267..50f2e925c 100644 --- a/frontend/src/pages/xray/routing/RuleCardList.tsx +++ b/frontend/src/pages/xray/routing/RuleCardList.tsx @@ -152,9 +152,7 @@ export default function RuleCardList({ →
- {rule.balancerTag - ? t('pages.xray.balancer') || 'Balancer' - : t('pages.xray.Outbounds')} + {rule.balancerTag ? t('pages.xray.rules.balancer') : t('pages.xray.Outbounds')} {rule.outboundTag ? ( diff --git a/frontend/src/test/i18n-dead-keys.test.ts b/frontend/src/test/i18n-dead-keys.test.ts index a8b595f64..002849c57 100644 --- a/frontend/src/test/i18n-dead-keys.test.ts +++ b/frontend/src/test/i18n-dead-keys.test.ts @@ -5,7 +5,7 @@ import { join, resolve } from 'node:path'; import { describe, expect, it } from 'vitest'; /* - * Guards the 14-locale translation set two ways: every key in en-US must be + * Guards the 14-locale translation set: every key in en-US must be * referenced somewhere in the frontend or Go sources (dead keys accumulate * silently — this test deleted over two hundred of them when it was * introduced), and every locale must carry exactly the en-US key set @@ -82,6 +82,17 @@ 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}.`))); + expect( + objectKeys, + `t() keys naming a group, rendered as "key '…' returned an object instead of string.":\n ${objectKeys.join('\n ')}`, + ).toEqual([]); + }); + it('every locale carries exactly the en-US key set', () => { const enSet = new Set(enKeys); for (const file of readdirSync(translationDir)) {