Sprachen und Darstellung in einer App
Eine App übersetzt ihre Texte selbst: Der Desktop gibt ihr Sprache, Formate und Zeitzone des Benutzers in app.context und sagt, wenn sie sich ändern. @pithyx/sdk/i18n ist ein optionaler Helfer für Texte in ICU MessageFormat, dem Format, das auch der Desktop nutzt, und app.format formatiert Daten, Zahlen, Größen und Listen. Das Aussehen kommt als CSS-Eigenschaften --pithyx-*, die das SDK auf der Seite setzt und aktuell hält; einfaches CSS folgt so Hell und Dunkel, der Akzentfarbe und der Dichte.
Beispiel
Abschnitt betitelt „Beispiel“Die Texte liegen in einer JSON-Datei pro Sprache:
{ "files": { "title": "Files", "count": "{count, plural, one {# file} other {# files}}", "changed": "Changed {when}" }}{ "files": { "title": "Dateien", "count": "{count, plural, one {# Datei} other {# Dateien}}", "changed": "Geändert {when}" }}// Texts in the user's language, dates and sizes in the user's formats, and colors from the desktop's theme.import { connect, type PithyxApp } from '@pithyx/sdk';import { createI18n } from '@pithyx/sdk/i18n';// ICU MessageFormat, like the desktop's own texts; English is the fallback for keys a language lacks.import de from './i18n/de.json';import en from './i18n/en.json';
const app: PithyxApp = await connect();const i18n = createI18n(app, { en, de });
interface Row { name: string; size: number; modified: string;}
function render(rows: Row[]) { document.title = i18n.t('files.title'); const heading = document.createElement('h1'); heading.textContent = `${i18n.t('files.title')} (${i18n.t('files.count', { count: rows.length })})`; const list = document.createElement('ul'); for (const row of rows) { const item = document.createElement('li'); // Dates arrive as UTC; app.format shows them in the user's time zone and locale. item.textContent = `${row.name}, ${app.format.bytes(row.size)}, ${i18n.t('files.changed', { when: app.format.relative(row.modified), })}`; list.append(item); } document.body.replaceChildren(heading, list);}
const rows: Row[] = [ { name: 'report.pdf', size: 1_234_567, modified: new Date(Date.now() - 3_600_000).toISOString() },];
render(rows);// The SDK already set the new lang attribute and theme properties when these handlers run.app.on('localeChange', () => { render(rows);});app.on('themeChange', (theme) => { // CSS with var(--pithyx-...) follows by itself; only canvas drawings and the like need the values. document.body.dataset.scheme = theme.scheme;});Und das CSS, das der Darstellung folgt:
body { margin: 0; background: var(--pithyx-color-background); color: var(--pithyx-color-text); font: var(--pithyx-font-size) var(--pithyx-font-ui);}button { height: var(--pithyx-control-height); padding: 0 calc(var(--pithyx-space) * 2); border: 1px solid var(--pithyx-color-border); border-radius: var(--pithyx-radius); background: var(--pithyx-color-accent); color: var(--pithyx-color-accent-text);}button:focus-visible { outline: 2px solid var(--pithyx-color-focus);}Sprache und Formate
Abschnitt betitelt „Sprache und Formate“context.languageist die Sprache des Benutzers für Texte, zum Beispielde.context.localeist diese Sprache mit der Region der Formate der Box, zum Beispielde-AT; das SDK setzt sie alslangauf das Wurzelelement.context.timeZoneist eine IANA-Zone wieEurope/Berlin.createI18n(app, { en, de, ... })brauchten. Es nimmt die Texte der genauen Locale, dann ihrer Grundsprache (defürde-AT), dannen, und liestcontext.localebei jedem Aufruf; so folgt eslocaleChangevon selbst. Ein Schlüssel, der einer Sprache fehlt, fällt auf den englischen Text zurück; ein Schlüssel, den keine Sprache hat, kommt als der Schlüssel selbst zurück. Schlüssel sind Pfade mit Punkten in verschachtelte Objekte.- Texte sind ICU MessageFormat:
{count, plural, one {# Datei} other {# Dateien}},{name},{kind, select, ...}. Jeder Text wird einmal pro Locale kompiliert. app.formathatdate,time,dateTime,relative,number,bytes(dezimale Einheiten, wie der Desktop Größen zeigt) undlist. Sie nutzen die aktuelle Locale und Zeitzone. Daten kommen über die API als UTC-Text in ISO 8601; gib sie so weiter, wie sie sind.- Zeichne bei
localeChangeneu. Wenn dein Handler läuft, hat das SDK den Kontext undlangschon aktualisiert. - Jede andere i18n-Bibliothek geht auch; das SDK gibt nur die Locale weiter.
Darstellung
Abschnitt betitelt „Darstellung“Das SDK setzt diese Eigenschaften auf document.documentElement (oder auf themeRoot, das du connect mitgibst, null zum Auslassen):
- Farben:
--pithyx-color-background,-surface,-surface-raised,-hover,-selected,-text,-text-muted,-border,-accent,-accent-text,-focus,-success,-warning,-danger, - Schrift und Form:
--pithyx-font-ui,--pithyx-font-mono,--pithyx-font-size,--pithyx-radius,--pithyx-space,--pithyx-control-height.
Außerdem setzt es color-scheme, data-theme und data-pithyx-theme (beide light oder dark) und data-pithyx-density (comfortable oder compact; compact verkleinert --pithyx-space und --pithyx-control-height schon). Bei themeChange ändern sich die Eigenschaften, bevor dein Handler läuft; CSS folgt ohne Code, auch wenn dein Bundler light-dark() für ältere Browser übersetzt hat (Vite tut das: Das übersetzte CSS folgt data-theme und der Einstellung des Browsers, nicht einem per Skript gesetzten color-scheme, entferne data-theme also nicht). Nur Zeichnungen in einem Canvas oder mit WebGL brauchen die Werte aus theme.tokens.
Fertige Komponenten im Aussehen des Desktops findest du in @pithyx/ui; sie folgen demselben Theme von selbst, sobald das SDK verbunden ist.
Sonderfälle
Abschnitt betitelt „Sonderfälle“- Schriften. Die Schrift-Eigenschaften nennen die Schriften des Desktops, aber die Seite der App teilt die Schriften nicht, die der Desktop geladen hat, und darf Schriften nur aus eigenen Dateien oder
data:-URLs laden (font-src 'self' data:). Liefere die Schriftdateien mit deinem Frontend aus, wenn du dich auf sie verlässt; sonst weicht der Browser auf eine andere Schrift aus. - Unbekannte Werte. Ein Token-Wert mit
;,{,},<oder>wird nie gesetzt, damit vom Host kein CSS eingeschleust werden kann. - Mock-Desktop.
pithyx devschaltet Darstellung, Akzent, Locale (en-US,en-GB,de-DE,de-AT,fr-FR,ja-JP), Zeitzone und Größenklasse im Panel um. Seine Dichte ist immercomfortable.
Grenzen
Abschnitt betitelt „Grenzen“Die Namen der --pithyx-*-Eigenschaften sind ein stabiler Vertrag: Neue Namen sind eine kleine Änderung, einen umzubenennen oder zu entfernen eine große. Rohe Farben gehören nie dazu; nutze die Namen nach ihrem Zweck.