@deepseek-ai/dsh-client-locale 0.0.1-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js ADDED
@@ -0,0 +1,26 @@
1
+ import { settingsNamespace } from "@deepseek-ai/dsh-settings";
2
+ import z from "@deepseek-ai/schemastery";
3
+ //#region lib/types/locale-settings.js
4
+ /** Locale preference stored in the Host user-settings document. */
5
+ /** Settings namespace owned by the locale plugin. */
6
+ const LOCALE_SETTINGS_NAMESPACE = "locale";
7
+ /** Field carrying an explicit locale selection; absence delegates to the browser. */
8
+ const LOCALE_PREFERENCE_FIELD = "preference";
9
+ /** Locale identifiers shipped by the browser client. */
10
+ const LOCALE_IDS = ["zh", "en"];
11
+ /** Durable locale schema; also the wire envelope the browser scope validates against. */
12
+ const LocaleSettingsSchema = z.object({ [LOCALE_PREFERENCE_FIELD]: z.union([...LOCALE_IDS]).required(false) });
13
+ //#endregion
14
+ //#region lib/types/index.js
15
+ /** Host registration for the browser locale preference. */
16
+ /**
17
+ * Register the durable locale section when a settings provider exists.
18
+ * @param ctx - Host context whose optional settings service owns the section.
19
+ */
20
+ function apply(ctx) {
21
+ ctx.inject(["settings"], (settingsCtx) => {
22
+ settingsCtx.settings.register(settingsNamespace(LOCALE_SETTINGS_NAMESPACE), LocaleSettingsSchema);
23
+ });
24
+ }
25
+ //#endregion
26
+ export { LOCALE_IDS, LOCALE_PREFERENCE_FIELD, LOCALE_SETTINGS_NAMESPACE, apply };
@@ -0,0 +1,25 @@
1
+ //#region lib/types/invariant.js
2
+ /**
3
+ * Package-owned invariant companion for `@deepseek-ai/dsh-client-locale`.
4
+ * @module @deepseek-ai/dsh-client-locale/invariant
5
+ */
6
+ const PACKAGE_NAME = "@deepseek-ai/dsh-client-locale";
7
+ /** Cordis companion plugin name. */
8
+ const name = "client-locale-invariant";
9
+ /** Service required before the companion can reserve package ownership. */
10
+ const inject = ["invariants"];
11
+ /**
12
+ * No runtime invariant: ns-by-locale dictionary registry with a stable
13
+ * bind(ns) surface — it emits no cordis events and owns no cross-plugin
14
+ * mutable relation; fallback-chain resolution and locale-store behavior are
15
+ * asserted directly by this package's behavior specs.
16
+ */
17
+ const install = () => {};
18
+ /**
19
+ * Register this package's invariant companion.
20
+ * @param ctx - Cordis context carrying the invariant service.
21
+ * @returns the installed registration's disposer after setup succeeds.
22
+ */
23
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
24
+ //#endregion
25
+ export { apply, inject, name };
@@ -0,0 +1,16 @@
1
+ import type { PropsLocale, PropsRuntime, PropsStore } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { createLanguageRowStore } from './settings-store.ts';
3
+ /** Injected business face: the preference write (t rides the standard locale seat). */
4
+ export interface LanguageRowInjected {
5
+ /** Switch the active locale (a registered locale id). */
6
+ setLocale: (id: string) => void;
7
+ }
8
+ /** Full component props: runtime share + store share + locale seat + injected face. */
9
+ export type LanguageRowComponentProps = PropsRuntime<'settings.general.item'> & PropsStore<ReturnType<typeof createLanguageRowStore>> & PropsLocale<'settings.locale'> & LanguageRowInjected;
10
+ /**
11
+ * Render the Language row.
12
+ * @param props - composed slot props.
13
+ * @returns the row element tree.
14
+ */
15
+ export declare function LanguageRow({ t, setLocale, useStore }: LanguageRowComponentProps): import("react").JSX.Element;
16
+ //# sourceMappingURL=LanguageRow.d.ts.map
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Browser-side locale registry. Bound translation functions retain stable
3
+ * identity for injected consumers. The plugin also registers the Language
4
+ * preference row into the settings General section — the locale feature owns
5
+ * its own settings surface.
6
+ */
7
+ import type { Context } from '@deepseek-ai/cordis';
8
+ import { type LocaleDictOf, type LocaleNamespaceMap, type Translate, type TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
9
+ import { type ClientContext, type SettingsScope } from '@deepseek-ai/dsh-client-runtime/client';
10
+ import { type LocaleId, type LocaleSettings } from '../locale-settings.ts';
11
+ import { type CommonKey } from '../locales/index.ts';
12
+ import { type SettingsLocaleKey } from '../locales/settings.ts';
13
+ export type { LanguageRowComponentProps, LanguageRowInjected } from './LanguageRow.tsx';
14
+ export type { LanguageOptionRow, LanguageRowState } from './settings-store.ts';
15
+ export type { SettingsGeneralItemOwnerProps } from './settings-contract.ts';
16
+ export type { CommonKey } from '../locales/index.ts';
17
+ export type { LocaleId, LocaleSettings } from '../locale-settings.ts';
18
+ export type { Translate, TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
19
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
20
+ interface LocaleNamespaceMap {
21
+ /** Shared cross-feature vocabulary, consulted by the lookup chain after the entry's own namespace misses. */
22
+ common: CommonKey;
23
+ /** This feature's own settings-row copy (the Language row). */
24
+ 'settings.locale': SettingsLocaleKey;
25
+ }
26
+ }
27
+ /** Locale dictionary: flat key to template string ({name} placeholders). */
28
+ export type LocaleDict = Record<string, string>;
29
+ /** One selectable locale: id plus its self-described display name. */
30
+ export interface LocaleDefinition {
31
+ /** Locale id (persisted; the setLocale argument). */
32
+ id: LocaleId;
33
+ /** Display name in its own language (中文 / English). */
34
+ label: string;
35
+ }
36
+ /** Immutable locale state published on every change. */
37
+ export interface LocaleSnapshot {
38
+ /** Active locale id. */
39
+ active: LocaleId;
40
+ /** Selectable locales in display order. */
41
+ locales: readonly LocaleDefinition[];
42
+ /** Monotonic change counter (registry or active changes). */
43
+ revision: number;
44
+ }
45
+ declare module '@deepseek-ai/cordis' {
46
+ interface Context {
47
+ locale: LocaleService;
48
+ }
49
+ interface Events {
50
+ /**
51
+ * The active locale switched. Dictionary registrations do NOT emit this
52
+ * event (listeners may re-register slots in response, and boot registers
53
+ * one namespace per package); continuous render refresh rides the
54
+ * LocaleFace revision instead.
55
+ * @param snapshot - Current immutable locale snapshot.
56
+ * @mode emit
57
+ */
58
+ 'locale/change'(snapshot: LocaleSnapshot): void;
59
+ }
60
+ }
61
+ /** Fallback locale consulted after the active locale misses (also the last-resort initial locale). */
62
+ export declare const FALLBACK_LOCALE: LocaleId;
63
+ /** Shared namespace for shell-level texts. */
64
+ export declare const COMMON_NS = "common";
65
+ /** Namespace owning this feature's settings-row copy. */
66
+ export declare const SETTINGS_NS = "settings.locale";
67
+ /**
68
+ * Dictionary registry plus locale preference. Lookup chain per key: the
69
+ * entry's namespace in the active locale -> that namespace's zh fallback ->
70
+ * the shared common namespace (active, then zh) -> the key itself (missing
71
+ * text stays visible, fail loud in the UI rather than blank). Reads go
72
+ * through {@link getLocale}; writes only through {@link setLocale};
73
+ * continuous sync through the `locale/change` event, or through the
74
+ * LocaleFace getSnapshot/subscribe pair the render machinery consumes
75
+ * (installed via `ctx.slots.installLocale`).
76
+ */
77
+ export declare class LocaleService {
78
+ private dicts;
79
+ private bound;
80
+ private snapshot;
81
+ private listeners;
82
+ private readonly ctx;
83
+ private readonly host;
84
+ /** Browser-derived locale standing wherever no explicit Host selection does. */
85
+ private readonly provisional;
86
+ /**
87
+ * @param ctx - owning context (change events are emitted on it; the scope
88
+ * listener is released through ctx.effect on dispose).
89
+ * @param host - durable preference scope owned by the providing plugin;
90
+ * absent compositions (standalone dictionary registries) stay process-local.
91
+ */
92
+ constructor(ctx: Context, host?: SettingsScope<LocaleSettings>);
93
+ /**
94
+ * Read the current immutable locale snapshot.
95
+ * @returns the current snapshot (stable reference until the next change).
96
+ */
97
+ getLocale(): LocaleSnapshot;
98
+ /**
99
+ * LocaleFace getSnapshot: the current snapshot (carries `revision`; stable
100
+ * reference between changes, uSES-safe).
101
+ * @returns the current snapshot.
102
+ */
103
+ getSnapshot(): LocaleSnapshot;
104
+ /**
105
+ * LocaleFace subscribe: notified on every snapshot change (locale switch
106
+ * or dictionary registration — registrations bump the revision so already
107
+ * rendered outlets pick up late-arriving dictionaries).
108
+ * @param fn - change callback.
109
+ * @returns unsubscribe.
110
+ */
111
+ subscribe(fn: () => void): () => void;
112
+ /**
113
+ * Switch the active locale — the only user preference write entry.
114
+ * @param id - a registered locale id; unknown ids throw.
115
+ */
116
+ setLocale(id: string): void;
117
+ /**
118
+ * Adopt the scope's accepted durable selection without writing it back; an
119
+ * absent selection returns to the browser-derived locale.
120
+ * @param host - the constructor-narrowed scope driving this adoption.
121
+ */
122
+ private adopt;
123
+ /**
124
+ * Register a declared namespace's dictionaries, all locales in one call —
125
+ * the typed form: each dictionary is checked against the namespace's
126
+ * {@link LocaleNamespaceMap} key union (a missing or extra key is a
127
+ * compile error), and every shipped locale is required (bilingual balance
128
+ * enforced at registration). Duplicate (ns, locale) throws (single occupant; a
129
+ * namespace's texts have one owner). Registration bumps the revision so
130
+ * mounted outlets pick up late-arriving dictionaries.
131
+ * @param ns - a namespace merged into LocaleNamespaceMap.
132
+ * @param dicts - complete dictionaries keyed by locale id.
133
+ * @returns disposer removing every locale registered by this call (idempotent).
134
+ */
135
+ register<N extends keyof LocaleNamespaceMap & string>(ns: N, dicts: Record<LocaleId, LocaleDictOf<N>>): () => void;
136
+ /**
137
+ * Single-locale untyped form for namespaces outside the merge table
138
+ * (dynamic composition, tests).
139
+ * @param ns - namespace.
140
+ * @param locale - locale tag.
141
+ * @param dict - dictionary.
142
+ * @returns disposer (idempotent).
143
+ */
144
+ register(ns: string, locale: string, dict: LocaleDict): () => void;
145
+ /**
146
+ * Bind a declared namespace to a translate function typed to its
147
+ * dictionary key union (plus the shared common vocabulary) — the same key
148
+ * domain the framework-injected `t` seat carries. The returned reference
149
+ * is stable per namespace (repeat binds return the same function), so it
150
+ * can ride inject surfaces without breaking memoization.
151
+ * @param ns - a namespace merged into LocaleNamespaceMap.
152
+ * @returns the typed translate function (reads the active locale at call time).
153
+ */
154
+ bind<N extends keyof LocaleNamespaceMap & string>(ns: N): TranslateNS<N>;
155
+ /**
156
+ * Untyped form for namespaces outside the merge table (dynamic
157
+ * composition, tests).
158
+ * @param ns - namespace.
159
+ * @returns the translate function.
160
+ */
161
+ bind(ns: string): Translate;
162
+ private translate;
163
+ private lookup;
164
+ /**
165
+ * Advance the snapshot revision and notify LocaleFace subscribers (render
166
+ * refresh). Only an active-locale switch additionally emits
167
+ * `locale/change` — dictionary registrations stay off the event so
168
+ * registration-heavy boot cannot storm event listeners (which may
169
+ * re-register slots in response).
170
+ */
171
+ private publish;
172
+ }
173
+ /** Required services: slot registration plus the settings transport. */
174
+ export declare const inject: string[];
175
+ /**
176
+ * Client plugin body: provide the locale service with base dictionaries and
177
+ * register the feature-owned Language preference row into the General
178
+ * section's item slot (a feature owns its settings surface).
179
+ * @param ctx - client cordis context.
180
+ */
181
+ export declare function apply(ctx: ClientContext): void;
182
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The `settings.general.item` slot type — one preference row inside the
3
+ * settings General section, contributed by the feature plugin that owns the
4
+ * preference (locale → Language, ui-theme → Appearance). Options: `id` (row
5
+ * key), `order` (row position). Rows draw their own internals (row layout,
6
+ * separators via CSS); the section column only stacks them.
7
+ *
8
+ * TYPE HOME RATIONALE: the slot is declared at runtime by
9
+ * ui-settings-general's General entry, but its type lives here — this
10
+ * package is the common dependency of every item registrant (any settings
11
+ * row carries copy, so every registrant already depends on locale), whereas
12
+ * the declarer's own contract is unreachable for locale/ui-theme without a
13
+ * reference cycle.
14
+ */
15
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
16
+ interface SlotMap {
17
+ /** One preference row inside the settings General section (see module JSDoc). */
18
+ 'settings.general.item': {
19
+ kind: 'list';
20
+ scope: 'root';
21
+ owner: SettingsGeneralItemOwnerProps;
22
+ };
23
+ }
24
+ }
25
+ /** Owner share of a General preference row (the section supplies nothing). */
26
+ export interface SettingsGeneralItemOwnerProps {
27
+ /** Marker field: item owner props are intentionally empty. */
28
+ children?: never;
29
+ }
30
+ //# sourceMappingURL=settings-contract.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Language row slot store: a mirror of the locale service snapshot. The
3
+ * plugin's apply-world change listener is the only writer; the row component
4
+ * reads via props.useStore.
5
+ */
6
+ import { type EngineStoreHandle } from '@deepseek-ai/dsh-client-runtime/client';
7
+ /** One selectable locale row (id + self-described label). */
8
+ export interface LanguageOptionRow {
9
+ /** Locale id (the setLocale argument). */
10
+ id: string;
11
+ /** Display name in its own language (中文 / English). */
12
+ label: string;
13
+ }
14
+ /** Store state mirrored from the locale snapshot. */
15
+ export interface LanguageRowState {
16
+ /** Active locale id. */
17
+ active: string;
18
+ /** Selectable locales in display order. */
19
+ options: LanguageOptionRow[];
20
+ /** Service revision; -1 until first sync so revision 0 lands as a change. */
21
+ revision: number;
22
+ }
23
+ /** Declared action shape giving the exported factory a stable return type. */
24
+ type LanguageRowActions = {
25
+ sync: (draft: LanguageRowState, active: string, options: LanguageOptionRow[], revision: number) => void;
26
+ };
27
+ /**
28
+ * Declares the Language row state and write surface.
29
+ * @returns the store handle.
30
+ */
31
+ export declare function createLanguageRowStore(): EngineStoreHandle<LanguageRowState, LanguageRowActions>;
32
+ export {};
33
+ //# sourceMappingURL=settings-store.d.ts.map
@@ -0,0 +1,9 @@
1
+ /** Host registration for the browser locale preference. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ export { LOCALE_IDS, LOCALE_PREFERENCE_FIELD, LOCALE_SETTINGS_NAMESPACE, type LocaleId, type LocaleSettings, } from './locale-settings.ts';
4
+ /**
5
+ * Register the durable locale section when a settings provider exists.
6
+ * @param ctx - Host context whose optional settings service owns the section.
7
+ */
8
+ export declare function apply(ctx: Context): void;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Package-owned invariant companion for `@deepseek-ai/dsh-client-locale`.
3
+ * @module @deepseek-ai/dsh-client-locale/invariant
4
+ */
5
+ import type { Context } from '@deepseek-ai/cordis';
6
+ /** Cordis companion plugin name. */
7
+ export declare const name = "client-locale-invariant";
8
+ /** Service required before the companion can reserve package ownership. */
9
+ export declare const inject: string[];
10
+ /**
11
+ * Register this package's invariant companion.
12
+ * @param ctx - Cordis context carrying the invariant service.
13
+ * @returns the installed registration's disposer after setup succeeds.
14
+ */
15
+ export declare const apply: (ctx: Context) => Promise<() => void>;
16
+ //# sourceMappingURL=invariant.d.ts.map
@@ -0,0 +1,18 @@
1
+ /** Locale preference stored in the Host user-settings document. */
2
+ import z from '@deepseek-ai/schemastery';
3
+ /** Settings namespace owned by the locale plugin. */
4
+ export declare const LOCALE_SETTINGS_NAMESPACE = "locale";
5
+ /** Field carrying an explicit locale selection; absence delegates to the browser. */
6
+ export declare const LOCALE_PREFERENCE_FIELD = "preference";
7
+ /** Locale identifiers shipped by the browser client. */
8
+ export declare const LOCALE_IDS: readonly ["zh", "en"];
9
+ /** Shipped locale identifier. */
10
+ export type LocaleId = typeof LOCALE_IDS[number];
11
+ /** Durable locale section shared by the Host schema and the browser scope. */
12
+ export interface LocaleSettings {
13
+ /** Explicit locale selection; absence delegates to the browser. */
14
+ preference?: LocaleId;
15
+ }
16
+ /** Durable locale schema; also the wire envelope the browser scope validates against. */
17
+ export declare const LocaleSettingsSchema: z<LocaleSettings>;
18
+ //# sourceMappingURL=locale-settings.d.ts.map
@@ -0,0 +1,28 @@
1
+ /** en base dictionary for the common namespace, checked complete against the zh key set. */
2
+ export declare const en: {
3
+ ok: string;
4
+ cancel: string;
5
+ close: string;
6
+ copy: string;
7
+ copied: string;
8
+ retry: string;
9
+ loading: string;
10
+ 'load.failed': string;
11
+ submit: string;
12
+ submitting: string;
13
+ next: string;
14
+ previous: string;
15
+ skip: string;
16
+ delete: string;
17
+ edit: string;
18
+ save: string;
19
+ search: string;
20
+ more: string;
21
+ collapse: string;
22
+ expand: string;
23
+ back: string;
24
+ unknown: string;
25
+ none: string;
26
+ truncated: string;
27
+ };
28
+ //# sourceMappingURL=en.d.ts.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The common-namespace dictionary pair. zh is the source of truth for the
3
+ * key set (Chinese-first repo convention); en is checked complete against it
4
+ * — a missing or extra en key is a compile error.
5
+ */
6
+ export { zh } from './zh.ts';
7
+ export { en } from './en.ts';
8
+ export type { CommonKey } from './zh.ts';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,12 @@
1
+ /** `settings.locale` namespace dictionaries (the Language row's copy). */
2
+ /** Simplified Chinese dictionary (the key-set source of truth). */
3
+ export declare const zh: {
4
+ 'language.title': string;
5
+ };
6
+ /** The settings.locale namespace key union. */
7
+ export type SettingsLocaleKey = keyof typeof zh;
8
+ /** English dictionary, checked complete against the zh key set. */
9
+ export declare const en: {
10
+ 'language.title': string;
11
+ };
12
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1,30 @@
1
+ /** zh base dictionary for the common namespace: cross-feature standard words. */
2
+ export declare const zh: {
3
+ ok: string;
4
+ cancel: string;
5
+ close: string;
6
+ copy: string;
7
+ copied: string;
8
+ retry: string;
9
+ loading: string;
10
+ 'load.failed': string;
11
+ submit: string;
12
+ submitting: string;
13
+ next: string;
14
+ previous: string;
15
+ skip: string;
16
+ delete: string;
17
+ edit: string;
18
+ save: string;
19
+ search: string;
20
+ more: string;
21
+ collapse: string;
22
+ expand: string;
23
+ back: string;
24
+ unknown: string;
25
+ none: string;
26
+ truncated: string;
27
+ };
28
+ /** The common vocabulary key union (zh is the key-set source of truth). */
29
+ export type CommonKey = keyof typeof zh;
30
+ //# sourceMappingURL=zh.d.ts.map
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@deepseek-ai/dsh-client-locale",
3
+ "description": "Locale plugin: Host-backed zh/en preference, browser-derived fallback, locale snapshots, and typed namespace dictionaries",
4
+ "version": "0.0.1-rc.1",
5
+ "publishConfig": {
6
+ "access": "restricted"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
11
+ "directory": "packages/client/locale"
12
+ },
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "types": "lib/types/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/types/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "./invariant": {
22
+ "types": "./lib/types/invariant.d.ts",
23
+ "default": "./lib/invariant.js"
24
+ },
25
+ "./client": {
26
+ "types": "./lib/types/client/index.d.ts",
27
+ "default": "./lib/client.js"
28
+ },
29
+ "./src/*": "./src/*",
30
+ "./package.json": "./package.json"
31
+ },
32
+ "dsh": {
33
+ "client": {
34
+ "inject": [
35
+ "@deepseek-ai/dsh-client-connection",
36
+ "@deepseek-ai/dsh-client-runtime"
37
+ ],
38
+ "platform": "web",
39
+ "immediately": true
40
+ }
41
+ },
42
+ "license": "BSD-3-Clause",
43
+ "peerDependencies": {
44
+ "react": "^18.2.0",
45
+ "@deepseek-ai/dsh-client-runtime": "^0.0.1-rc.1",
46
+ "@deepseek-ai/dsh-client-connection": "^0.0.1-rc.1",
47
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1-rc.1",
48
+ "@deepseek-ai/dsh-client-ui-slots": "^0.0.1-rc.1",
49
+ "@deepseek-ai/dsh-invariants": "^0.0.1-rc.1",
50
+ "@deepseek-ai/cordis": "^4.0.1-rc.1"
51
+ },
52
+ "devDependencies": {
53
+ "@types/react": "~18.3.1",
54
+ "react": "^18.2.0",
55
+ "@deepseek-ai/dsh-client-ui-slots": "^0.0.1-rc.1",
56
+ "@deepseek-ai/cordis": "^4.0.1-rc.1",
57
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1-rc.1",
58
+ "@deepseek-ai/dsh-client-runtime": "^0.0.1-rc.1",
59
+ "@deepseek-ai/dsh-invariants": "^0.0.1-rc.1"
60
+ },
61
+ "dependencies": {
62
+ "@deepseek-ai/schemastery": "^3.18.1-rc.1",
63
+ "@deepseek-ai/dsh-settings": "^0.0.1-rc.1"
64
+ },
65
+ "files": [
66
+ "lib/index.js",
67
+ "lib/invariant.js",
68
+ "lib/client.js",
69
+ "lib/types/**/*.d.ts"
70
+ ],
71
+ "scripts": {
72
+ "bundle": "tsdown",
73
+ "watch": "tsdown --watch"
74
+ }
75
+ }