import { afterEach, describe, expect, it } from 'vitest' import i18n from '../../src/i18n' import { APP_LANGUAGES } from '../../src/i18n/detectLocale' import { translateIpcError } from '../../src/i18n/format' /** User-visible keys added or changed in this round. Must resolve in every locale. */ const ROUND_KEYS = [ 'errors:native.taskJoin', 'errors:native.invalidBase64', 'errors:native.knownHostsPath', 'errors:native.invalidHostKeyDecision', 'errors:connection.unexpectedDropped', 'errors:connection.shellExited', 'errors:connection.shellReadFailed', 'common:error.bodyPane', 'common:error.retryPane', 'terminal:overlay.disconnectedKeepalive', 'settings:ssh.sessionPolicyHint', 'sftp:connection.autoReconnecting', 'desktop:toolbar.reconnect', 'desktop:status.reconnecting', 'common:tab.menu.reconnect', 'sessions:dialog.displayNamePlaceholderVnc', 'sessions:importExport.exportFilterOxs', 'sessions:importExport.importFilterOxs', 'settings:nav.aboutDesc', 'settings:about.wechat', 'settings:about.copyWechat', 'settings:about.resources', 'settings:ai.apiKey', 'ai:confirm.reject', 'ai:confirm.once', 'ai:confirm.always', 'ai:confirm.hint', 'ai:error.noProvider', 'ai:error.execFailed', ] as const describe('new copy resolves in every locale', () => { afterEach(async () => { await i18n.changeLanguage('zh-CN') }) it.each(APP_LANGUAGES)('%s returns real text, not the key', async (language) => { await i18n.changeLanguage(language) for (const key of ROUND_KEYS) { const text = i18n.t(key) expect(text.trim().length, key).toBeGreaterThan(0) expect(text).not.toBe(key) expect(text).not.toBe(key.replace(/^[a-z]+:/, '')) } }) it.each(APP_LANGUAGES.filter((language) => language !== 'en'))( '%s does not leave English copy for native errors and pane fallback', async (language) => { await i18n.changeLanguage('en') const english = Object.fromEntries(ROUND_KEYS.map((key) => [key, i18n.t(key)])) await i18n.changeLanguage(language) for (const key of [ 'errors:native.taskJoin', 'errors:native.invalidBase64', 'errors:native.knownHostsPath', 'errors:native.invalidHostKeyDecision', 'errors:connection.unexpectedDropped', 'terminal:overlay.disconnectedKeepalive', 'settings:ssh.sessionPolicyHint', 'common:error.bodyPane', 'common:error.retryPane', 'sessions:dialog.displayNamePlaceholderVnc', 'settings:nav.aboutDesc', 'settings:about.copyWechat', 'settings:ai.apiKey', 'ai:confirm.once', 'ai:error.noProvider', 'ai:error.execFailed', ] as const) { expect(i18n.t(key), key).not.toBe(english[key]) } } ) it.each(APP_LANGUAGES)('%s maps native.taskJoin through translateIpcError', async (language) => { await i18n.changeLanguage(language) expect(translateIpcError('ignored', 'native.taskJoin')).toBe(i18n.t('errors:native.taskJoin')) expect(translateIpcError('native.knownHostsPath')).toBe(i18n.t('errors:native.knownHostsPath')) }) })