cc-haha/desktop/src/i18n/index.ts
程序员阿江(Relakkes) f57f163604 fix: prevent session inspector context stalls
Session inspection was coupling quick status and usage rendering to live context control requests, so a slow get_context_usage path could leave the desktop inspector stuck on a loading state. The desktop panel now loads basic inspection data first, renders a transcript-based context estimate immediately, and only asks for live context details as a background refinement.

The translation hook now returns a stable function per locale so effects that depend on translation do not reset and re-fetch after every render.

Constraint: Third-party provider sessions may not expose reliable live context capabilities through the control request path.
Rejected: Keep waiting on live get_context_usage for the context tab | it recreates the user-visible loading stall.
Rejected: Hardcode provider-specific context windows | provider capabilities are not always known from the desktop session record.
Confidence: high
Scope-risk: moderate
Directive: Do not make the inspector first render depend on live CLI control requests without a transcript or cached fallback.
Tested: bun test src/server/__tests__/conversations.test.ts -t "structured session inspection|Sonnet 4.6 transcript usage"
Tested: cd desktop && bun run test -- --run src/i18n/index.test.tsx
Tested: cd desktop && bun run build
Tested: git diff --check
Tested: agent-browser verified /context renders transcript estimate without Loading context data
Not-tested: Provider-specific true context-window discovery for every third-party vendor
2026-04-28 22:52:18 +08:00

59 lines
1.7 KiB
TypeScript

import { useCallback } from 'react'
import { useSettingsStore } from '../stores/settingsStore'
import { en, type TranslationKey } from './locales/en'
import { zh } from './locales/zh'
export type Locale = 'en' | 'zh'
const translations: Record<Locale, Record<string, string>> = { en, zh }
/**
* Translate a key with optional interpolation params.
* Falls back to the key itself if no translation is found.
*
* @example
* translate('en', 'settings.providers.connected', { latency: '42' })
* // => "Connected (42ms)"
*/
export function translate(
locale: Locale,
key: TranslationKey,
params?: Record<string, string | number>,
): string {
let text = translations[locale]?.[key] ?? translations.en[key] ?? key
if (params) {
for (const [k, v] of Object.entries(params)) {
text = text.replace(new RegExp(`\\{${k}\\}`, 'g'), String(v))
}
}
return text
}
/**
* React hook that returns a `t()` function bound to the current locale.
* Re-renders when the locale changes.
*
* @example
* const t = useTranslation()
* t('sidebar.newSession') // => "New session" or "新建会话"
*/
export function useTranslation() {
const locale = useSettingsStore((s) => s.locale)
return useCallback(
(key: TranslationKey, params?: Record<string, string | number>) =>
translate(locale, key, params),
[locale],
)
}
/**
* Get a translation outside of React (e.g. in stores).
* Reads the current locale from the Zustand store directly.
*/
export function t(key: TranslationKey, params?: Record<string, string | number>): string {
const locale = useSettingsStore.getState().locale
return translate(locale, key, params)
}
export type { TranslationKey }