wip
fix: docs
This commit is contained in:
@@ -18,9 +18,20 @@ import type { ModelsSectionInjected } from './ModelsSection.tsx'
|
||||
import { DeepSeekOnboardingDialog } from './DeepSeekOnboardingDialog.tsx'
|
||||
import type { DeepSeekOnboardingInjected } from './DeepSeekOnboardingDialog.tsx'
|
||||
import { ModelsSettingsStore } from './store.ts'
|
||||
import { en, zh } from './locales.ts'
|
||||
import { en, zh, type ModelsKey } from './locales.ts'
|
||||
|
||||
export type { ModelsSectionInjected, ModelsSectionProps } from './ModelsSection.tsx'
|
||||
export type { ModelsKey } from './locales.ts'
|
||||
|
||||
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
||||
interface LocaleNamespaceMap {
|
||||
/** The Models page + onboarding overlay copy. */
|
||||
'settings.models': ModelsKey
|
||||
}
|
||||
}
|
||||
|
||||
/** Dictionary namespace owned by this plugin. */
|
||||
const NS = 'settings.models'
|
||||
export type { ModelsSettingsState, ProviderRow } from './store.ts'
|
||||
|
||||
/**
|
||||
@@ -47,18 +58,14 @@ export const inject = ['slots', 'locale', 'connection']
|
||||
* @param ctx - client root context.
|
||||
*/
|
||||
export function apply(ctx: ClientContext): void {
|
||||
ctx.effect(() => {
|
||||
const disposers = [
|
||||
ctx.locale.register('settings.models', 'zh', zh),
|
||||
ctx.locale.register('settings.models', 'en', en),
|
||||
]
|
||||
return () => { for (const dispose of disposers) dispose() }
|
||||
}, 'ui-models: copy dictionaries')
|
||||
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'ui-models: copy dictionaries')
|
||||
|
||||
const connection = ctx.get('connection') as ConnectionHandle
|
||||
const controller = new ModelsSettingsStore(connection.api)
|
||||
const useSnapshot = bindSnapshotSelector(controller.store)
|
||||
const t = ctx.locale.bind('settings.models') as ModelsSectionInjected['t']
|
||||
// Registration-time text (the nav label thunk) and the inject faces share
|
||||
// one bound translate; copy freshness rides the locale revision.
|
||||
const t = ctx.locale.bind(NS) as ModelsSectionInjected['t']
|
||||
const injected = (): ModelsSectionInjected => ({
|
||||
controller,
|
||||
useSnapshot,
|
||||
@@ -90,7 +97,7 @@ export function apply(ctx: ClientContext): void {
|
||||
name: 'settings.section',
|
||||
id: 'models',
|
||||
order: 10,
|
||||
label: t('nav'),
|
||||
label: () => t('nav'),
|
||||
inject: injected,
|
||||
}, ModelsSection))
|
||||
const onboarding = deferRegistration(
|
||||
@@ -104,14 +111,7 @@ export function apply(ctx: ClientContext): void {
|
||||
inject: onboardingInjected,
|
||||
}, DeepSeekOnboardingDialog),
|
||||
)
|
||||
// Nav labels are registrant-localized: refresh on locale change so the
|
||||
// ledger carries fresh text (the version bump re-renders the shell).
|
||||
const offLocale = ctx.on('locale/change', () => {
|
||||
section.refresh()
|
||||
onboarding.refresh()
|
||||
})
|
||||
return () => {
|
||||
offLocale()
|
||||
section.dispose()
|
||||
onboarding.dispose()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** Copy dictionaries for the Models settings section. */
|
||||
|
||||
/** English strings. */
|
||||
/** English strings (the key-set source of truth for this pair). */
|
||||
export const en = {
|
||||
nav: 'Models',
|
||||
title: 'Models',
|
||||
@@ -34,6 +34,9 @@ export const en = {
|
||||
onboardingLater: 'Configure later',
|
||||
}
|
||||
|
||||
/** The settings.models namespace key union. */
|
||||
export type ModelsKey = keyof typeof en
|
||||
|
||||
/** Chinese strings (same keys as {@link en}). */
|
||||
export const zh: typeof en = {
|
||||
nav: '模型',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** Models section registration: declaration-aware deferral, locale re-registration, and HMR recovery. */
|
||||
/** Models section registration: declaration-aware deferral, the locale-following label thunk, and HMR recovery. */
|
||||
import { Context } from 'cordis'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { resolveSlotLabel } from '@deepseek-ai/dsh-client-ui-slots'
|
||||
import { SlotsService } from '@deepseek-ai/dsh-client-runtime/client'
|
||||
import { LocaleService } from '@deepseek-ai/dsh-client-locale/client'
|
||||
import { apply, inject, refreshIfLoaded } from '@deepseek-ai/dsh-client-ui-models/client'
|
||||
@@ -42,7 +43,9 @@ describe('ui-models apply', () => {
|
||||
await before.ctx.plugin({ inject: [...inject], apply }).await()
|
||||
const entry = before.slots.entries('settings.section')[0]!
|
||||
expect(entry.component).toBe(ModelsSection)
|
||||
expect(entry.options).toMatchObject({ id: 'models', order: 10, label: '模型' })
|
||||
expect(entry.options).toMatchObject({ id: 'models', order: 10 })
|
||||
// The nav label is a locale-following thunk; owners resolve at read time.
|
||||
expect(resolveSlotLabel(entry.options.label)).toBe('模型')
|
||||
const injected = (entry.inject as unknown as () => import('../src/client/ModelsSection.tsx').ModelsSectionInjected)()
|
||||
expect(injected.t('nav')).toBe('模型')
|
||||
expect(typeof injected.controller.load).toBe('function')
|
||||
@@ -64,14 +67,14 @@ describe('ui-models apply', () => {
|
||||
expect(after.slots.entries('settings.section')).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('re-registers with fresh label text on locale change', async () => {
|
||||
it('the label thunk follows the active locale without re-registration', async () => {
|
||||
const b = await bench()
|
||||
declare(b.slots)
|
||||
await b.ctx.plugin({ inject: [...inject], apply }).await()
|
||||
b.locale.setLocale('en')
|
||||
expect(b.slots.entries('settings.section')[0]!.options.label).toBe('Models')
|
||||
expect(resolveSlotLabel(b.slots.entries('settings.section')[0]!.options.label)).toBe('Models')
|
||||
b.locale.setLocale('zh')
|
||||
expect(b.slots.entries('settings.section')[0]!.options.label).toBe('模型')
|
||||
expect(resolveSlotLabel(b.slots.entries('settings.section')[0]!.options.label)).toBe('模型')
|
||||
})
|
||||
|
||||
it('locale change while the slot is undeclared stays a no-op', async () => {
|
||||
@@ -98,7 +101,7 @@ describe('ui-models apply', () => {
|
||||
expect(b.slots.entries('settings.onboarding')[0]!.component).toBe(DeepSeekOnboardingDialog)
|
||||
// The locale path also recovers through the same ledger re-check.
|
||||
b.locale.setLocale('en')
|
||||
expect(b.slots.entries('settings.section')[0]!.options.label).toBe('Models')
|
||||
expect(resolveSlotLabel(b.slots.entries('settings.section')[0]!.options.label)).toBe('Models')
|
||||
b.locale.setLocale('zh')
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user