docs(arts): A2 ES->EN — prefs (full translation)

Full Spanish -> English translation of prefs/README.md (faithful; all code /
text blocks and the `prefs::*` error strings kept verbatim). Carries the A1
signature fixes already landed (applyBrowserEnvironment/watchBrowserEnvironment,
createPrefsStorageBridge `engine`).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
menubar-v4-safe
dev 3 months ago
parent 65c6ae4559
commit 6e13790a73

@ -1,78 +1,80 @@
# Prefs
`prefs` es el artefacto activo de preferencias. Su trabajo es resolver, de
forma generica, la relacion entre intencion de usuario, entorno detectado y
valor efectivo para un esquema declarado por la app.
No traduce, no formatea, no persiste por si mismo y no escribe el DOM salvo
cuando el composition root cablea explicitamente `createActivePrefsDomProjection(...)`.
## Estado 2026-05-14
Decisiones vigentes:
- `prefs.language` alimenta `langs`.
- `prefs.locale` alimenta `format`.
- `prefs.direction` resuelve direccion efectiva.
- `prefs.motion`, `prefs.sound` y `prefs.haptic` son preferencias
transversales de percepcion/interaccion.
- `createActivePrefsDomProjection(...)` proyecta solo `dir`,
`data-motion`, `data-sound` y `data-haptic`.
- `theme`, `mode` y `density` visuales pertenecen a `ActiveEidos`, no al
preset core de `prefs`, `ActiveApp` ni `ActiveUix`.
- No hay `themeDimension(...)` ni `densityDimension(...)` en el catalogo
publico de prefs: si una app necesita dimensiones custom, usa las
primitivas genericas (`enumDimension`, `stringDimension`, etc.) o una
`PrefsDimension` propia.
`prefs` is the active preferences artifact. Its job is to resolve, generically,
the relationship between user intent, detected environment and effective value
for a schema declared by the app.
It does not translate, does not format, does not persist by itself, and does not
write the DOM except when the composition root explicitly wires
`createActivePrefsDomProjection(...)`.
## Status 2026-05-14
Current decisions:
- `prefs.language` feeds `langs`.
- `prefs.locale` feeds `format`.
- `prefs.direction` resolves the effective direction.
- `prefs.motion`, `prefs.sound` and `prefs.haptic` are cross-cutting
perception/interaction preferences.
- `createActivePrefsDomProjection(...)` projects only `dir`, `data-motion`,
`data-sound` and `data-haptic`.
- Visual `theme`, `mode` and `density` belong to `ActiveEidos`, not to the core
preset of `prefs`, `ActiveApp` or `ActiveUix`.
- There is no `themeDimension(...)` or `densityDimension(...)` in the public
prefs catalog: if an app needs custom dimensions, it uses the generic
primitives (`enumDimension`, `stringDimension`, etc.) or its own
`PrefsDimension`.
## Composition Rule
Solo los composition roots crean `ActivePrefs`:
Only composition roots create `ActivePrefs`:
- `ActiveApp` crea o recibe `prefs`.
- `createActiveUix(...)` crea `prefs` cuando UIX arranca standalone.
- `attachActiveUix(app)` reutiliza `app.prefs`.
- `ActiveApp` creates or receives `prefs`.
- `createActiveUix(...)` creates `prefs` when UIX boots standalone.
- `attachActiveUix(app)` reuses `app.prefs`.
Las capas consumidoras leen slots concretos o reciben vistas acotadas. No
deben crear otra instancia compensatoria de preferencias.
Consuming layers read specific slots or receive scoped views. They must not
create another compensatory preferences instance.
```text
ActiveApp/createActiveUix -> ActivePrefs
langs -> prefs.language
format -> prefs.locale, currency, timezone, unitSystem
ActivePrefsDomProjection -> direction, motion, sound, haptic
ActiveEidos -> theme/mode/density visuales propios
ActiveEidos -> its own visual theme/mode/density
```
## Schema Model
La implementacion actual es schema-based:
The current implementation is schema-based:
```ts
type PrefsSchema = Record<string, PrefsDimension<TIntent, TEffective>>;
```
Cada dimension declara:
Each dimension declares:
- `defaultValue`: valor de fallback.
- `validate(value)`: valida intencion de usuario.
- `resolve(intent, env)`: opcional; convierte intencion + entorno en valor
efectivo.
- `catalog()`: opcional; lista de valores seleccionables.
- `defaultValue`: fallback value.
- `validate(value)`: validates user intent.
- `resolve(intent, env)`: optional; turns intent + environment into the
effective value.
- `catalog()`: optional; list of selectable values.
El motor mantiene tres planos:
The engine keeps three planes:
```text
intent = lo que el usuario eligio explicitamente
environment = lo que servidor/browser/sistema sugieren
effective = valor total que leen los consumidores
intent = what the user explicitly chose
environment = what the server/browser/system suggest
effective = the final value consumers read
```
Solo `intent` se persiste. `environment` se recalcula y `effective` se deriva.
Only `intent` is persisted. `environment` is recomputed and `effective` is
derived.
## Standard Preset
`standardPrefsDimensions(catalog)` compone el preset transversal:
`standardPrefsDimensions(catalog)` composes the cross-cutting preset:
```ts
const schema = {
@ -90,7 +92,7 @@ const schema = {
};
```
Incluye:
Includes:
```text
language
@ -104,7 +106,7 @@ haptic
direction
```
No incluye:
Does not include:
```text
theme
@ -112,13 +114,13 @@ mode
density
```
Esos valores son visuales en UIX. Una shell debe pasarlos a `ActiveEidos`
mediante `theme`, `modeSource` y `densitySource`.
Those values are visual in UIX. A shell must pass them to `ActiveEidos` via
`theme`, `modeSource` and `densitySource`.
## Active Surface
`createActivePrefs({ schema })` devuelve una superficie reactiva con un slot
por dimension:
`createActivePrefs({ schema })` returns a reactive surface with one slot per
dimension:
```ts
const prefs = createActivePrefs({ schema });
@ -130,7 +132,7 @@ prefs.locale.onChange((locale) => {});
prefs.locale.catalog();
```
Tambien expone metodos genericos para adaptadores:
It also exposes generic methods for adapters:
```ts
prefs.setIntent('locale', 'en-US');
@ -142,30 +144,31 @@ prefs.subscribe((event) => {});
prefs.dispose();
```
Los servicios que reciben un `ActivePrefs` abierto y no conocen su schema en
tiempo de compilacion deben leer defensivamente:
Services that receive an open `ActivePrefs` and do not know its schema at
compile time should read defensively:
```ts
const slot = readActivePrefsSlot<Locale>(prefs, 'locale');
const locale = slot?.get();
```
Si el slot no existe, el consumidor decide si puede degradar o debe lanzar su
propio error de configuracion.
If the slot does not exist, the consumer decides whether it can degrade or must
throw its own configuration error.
## Environment
El entorno entra por adaptadores. Ninguna dimension lee `window`, cookies,
headers, `localStorage` o DOM directamente.
The environment comes in through adapters. No dimension reads `window`, cookies,
headers, `localStorage` or the DOM directly.
Adaptadores disponibles:
Available adapters:
- `detectServerEnvironment(input)`
- `detectBrowserEnvironment(overrides?)`
- `applyBrowserEnvironment(engine, overrides?)`
- `watchBrowserEnvironment(apply, overrides?)` — `apply` recibe el patch de entorno (`(patch) => void`); `overrides` solo `{ matchMedia }`
- `watchBrowserEnvironment(apply, overrides?)` — `apply` receives the environment
patch (`(patch) => void`); `overrides` is only `{ matchMedia }`
Ejemplos de entorno:
Environment examples:
```text
Accept-Language -> language/locale candidates
@ -174,14 +177,14 @@ matchMedia -> reducedMotion/colorScheme
navigator -> languages, reduced sound/haptics when available
```
`colorScheme` puede existir en el entorno porque el browser lo expone, pero
UIX no lo convierte en `prefs.theme`; `ActiveEidos` puede leer el sistema por
su propia `modeSource`.
`colorScheme` can exist in the environment because the browser exposes it, but
UIX does not turn it into `prefs.theme`; `ActiveEidos` can read the system
through its own `modeSource`.
## DOM Projection
`ActivePrefs` no escribe el DOM por si mismo. Si la app quiere atributos
globales, cablea el proyector:
`ActivePrefs` does not write the DOM by itself. If the app wants global
attributes, it wires the projector:
```ts
const prefsProjection = createActivePrefsDomProjection({
@ -190,10 +193,10 @@ const prefsProjection = createActivePrefsDomProjection({
});
```
El proyector es idempotente, se suscribe a los slots disponibles y limpia los
atributos que gestiono en `dispose()`.
The projector is idempotent, subscribes to the available slots and clears the
attributes it manages on `dispose()`.
Contrato de atributos:
Attribute contract:
```text
prefs.direction -> dir
@ -202,11 +205,11 @@ prefs.sound -> data-sound
prefs.haptic -> data-haptic
```
No proyecta `data-theme`, `data-mode` ni `data-density`.
It does not project `data-theme`, `data-mode` or `data-density`.
## Eidos Boundary
Para una shell visual:
For a visual shell:
```ts
const uix = createActiveUix({ langs, prefs: { schema } });
@ -223,55 +226,55 @@ const eidos = ActiveEidos.create({
});
```
Regla practica:
Practical rule:
```text
NO: uix.prefs.setIntent('theme', 'dark')
SI: modeSource notifica 'dark' a ActiveEidos
YES: modeSource notifies 'dark' to ActiveEidos
```
Si una app no UIX decide declarar una dimension visual propia en `prefs`, es
un contrato local de esa app. No debe filtrarse a `ActiveUix`, Soma, Sema ni
If a non-UIX app decides to declare its own visual dimension in `prefs`, that is
a local contract of that app. It must not leak into `ActiveUix`, Soma, Sema or
Morfo.
## Storage
`createPrefsStorageBridge(...)` persiste intenciones, no valores efectivos:
`createPrefsStorageBridge(...)` persists intents, not effective values:
```ts
const bridge = createPrefsStorageBridge({
engine, // EnginePrefs
storage, // PrefsIntentStorage
onError: (error, op) => report(error, op), // opcional
skipHydrate: false // opcional (default false)
onError: (error, op) => report(error, op), // optional
skipHydrate: false // optional (default false)
});
```
Reglas:
Rules:
- Persistir solo `intent`.
- No persistir `environment`.
- No persistir `effective`.
- No escribir durante hydrate salvo configuracion explicita.
- Un fallo de storage no debe corromper preferencias en memoria.
- Persist only `intent`.
- Do not persist `environment`.
- Do not persist `effective`.
- Do not write during hydrate unless explicitly configured.
- A storage failure must not corrupt in-memory preferences.
## Errors
Los errores publicos usan la familia `prefs::*`:
Public errors use the `prefs::*` family:
- `prefs::unknown_dimension`
- `prefs::intent_invalid`
- `prefs::reserved_key`
- `prefs::disposed`
Ejemplo conocido:
Known example:
```text
prefs::unknown_dimension: [prefs] no such dimension in schema: theme
```
En UIX ese error normalmente significa que una shell intento escribir
`prefs.theme`. La correccion es pasar el modo visual a `ActiveEidos`.
In UIX that error usually means a shell tried to write `prefs.theme`. The fix is
to pass the visual mode to `ActiveEidos`.
## Tests

Loading…
Cancel
Save

Powered by TurnKey Linux.