Zum Hauptinhalt springen

Locale-Dateien

Alle Strings einer Lösung liegen in genau einem Skript: ou.sp.<PREFIX>.installer.step.globalPropertiesLocales.ts. Dort werden sie als verschachtelte JavaScript-Objekte definiert, bei der Installation in das Properties-Format transformiert und als Globale Eigenschaft gespeichert.

Aufbau der Datei​

Die Referenzsprache wird mit as const definiert, daraus wird der Struktur-Typ abgeleitet, und dieser erzwingt Vollständigkeit in allen weiteren Sprachen.

import { installLocales, type LocaleShape } from "@one-unity/library/ou.sp.I18n";
import type { InstallStepInputOptions } from "@one-unity/library/ou.sp.Package";

const de = {
folder: {
importFile: "Dateiimport",
importFileError: {
label: "Fehlerhaft",
action: { start: "Verarbeitung starten" },
},
},
importFile: {
transform: {
error: { overall: "{{count}} Dokumente mit Fehlern" },
},
},
} as const;

export type Locales = LocaleShape<typeof de>;

const en: Locales = {
folder: {
importFile: "File import",
importFileError: {
label: "Faulty",
action: { start: "Start processing" },
},
},
importFile: {
transform: {
error: { overall: "{{count}} documents with errors" },
},
},
};

export const locales = { de, en };

export function install(options: InstallStepInputOptions): void {
installLocales({ baseName: "ou.sp.ImportFiles", locales }, options);
}

Fehlt in en ein Key oder ist er falsch verschachtelt, ist das ein Compile-Fehler — nicht ein Laufzeitproblem, das erst in der zweiten Sprache auffällt.

Warum diese Struktur
  • Typ-Fehler bei fehlenden Übersetzungen.
  • Auto-Completion an jeder Aufrufstelle über Selektor-Funktionen (siehe Übersetzen).
  • Eine neue Sprache ist eine weitere Konstante plus ein Eintrag in locales.

installLocales​

Erzeugt pro Sprache eine Globale Eigenschaft nach der Namenskonvention <baseName>_<sprache> und gibt die erzeugten Namen zurück. Signatur und alle Optionen siehe installLocales und InstallLocalesOptions.

Zwei Punkte, die sich aus der Signatur allein nicht ergeben: baseName ist der Name ohne Sprachsuffix — ou.sp.ImportFiles erzeugt ou.sp.ImportFiles_de und ou.sp.ImportFiles_en. Und wird der zweite Parameter mit den Installer-Step-Options belegt, meldet jede erzeugte Eigenschaft sich selbst über appendToResultSuccess.

Für den Sonderfall, dass ein Name nicht der Konvention folgen soll, gibt es installLocale für eine einzelne Sprache.

Erzeugtes Format​

Aus dem Objekt oben wird für de folgender Inhalt gespeichert:

$PROPERTIES_ENCODING=UTF-8
folder.importFile=Dateiimport
folder.importFileError.label=Fehlerhaft
folder.importFileError.action.start=Verarbeitung starten
importFile.transform.error.overall={{count}} Dokumente mit Fehlern

Konventionen für Keys​

Abschnitte nach Zuständigkeit​

Die oberste Ebene trennt Beschriftungen, die bei der Installation gesetzt werden, von Meldungen, die zur Laufzeit entstehen.

AbschnittZweckBeispiel
outbarBeschriftungen von Outbar-Einträgenoutbar.ptpInvoice → "Rechnungen"
folderNamen der angelegten Ordnerfolder.importFile → "Dateiimport"
filetypeFeldbeschriftungen, Registernamen und Action-Buttons am Mappentypfiletype.importFile.filePath → "Pfad"
workflowAufgabennamen, Entscheidungskommentare und Action-Buttons im Workflowworkflow.ptpInvoice.action.restart → "Erneute Prüfung"
<entity>Laufzeitmeldungen der VerarbeitungimportFile.transform.error.overall → "{{count}} Dokumente mit Fehlern"

outbar, folder, filetype und workflow decken die Installationszeit ab. Alles andere ist ein paketspezifischer Abschnitt für Laufzeitmeldungen, benannt nach seiner Entität.

Beispielpfade aus invoice (ou.sp.ptpINV.installer.step.globalPropertiesLocales.ts):

# Installationszeit
outbar.ptpInvoice Outbar-Eintrag
folder.ptpInvoice Ordnername
filetype.ptpInvoice.MultiLangLabel Anzeigename des Mappentyps (PascalCase, Documents-Attribut)
filetype.ptpInvoice.Title AutoTitle-Präfix (PascalCase, Documents-Attribut)
filetype.ptpInvoice.eInvoiceType.label Feldbeschriftung mit Enum-Kindern
filetype.ptpInvoice.eInvoiceType.XRechnung Enum-Wert
folder.statusCodeConfig.form.table.column.statusCode.label Spaltenüberschrift
folder.statusCodeConfig.form.table.column.statusCode.tooltip Tooltip
workflow.ptpInvoice.Description Workflow-Beschreibung
workflow.ptpInvoice.task.validateData Aufgabenname
workflow.ptpInvoice.decisioncomment.validData.ok Entscheidungskommentar
workflow.ptpInvoice.action.restart Action-Button im Workflow

# Laufzeitmeldungen
goodsReceiptCheck.status.timeout.summary Aktionstext eines Statuseintrags
goodsReceiptCheck.status.timeout.description Kommentar dazu, mit {{days}}
ptpInvoice.exportToExtract.notification.title Titel einer Benachrichtigung
ptpInvoice.exportToExtract.notification.message Text dazu

Benennung​

  • label bei Knoten mit Doppelrolle — ist ein Knoten gleichzeitig Wert und Elternknoten, bekommt der Wert den Key label:

    fileType: {
    label: "Dateityp",
    singleFiles: "Einzeldatei",
    sid3: "SID3",
    }
  • Platzhalter immer in doppelten geschweiften Klammern ({{count}}). Einfache Klammern werden zur Laufzeit nicht ersetzt.

  • Nach Domänen-Substantiv gruppieren, dann error bzw. action — Laufzeitabschnitte folgen dem Muster <entity>.error.* und <entity>.action.*.

Punkt-Notation nicht mischen

Ein Key darf entweder verschachtelt oder in Punkt-Notation geschrieben werden, aber nicht beides parallel für denselben Pfad — sonst kollidieren zwei Einträge im erzeugten Properties-Inhalt und einer überschreibt den anderen. Der Testhelfer expectLocalesConsistent erkennt solche Kollisionen.

Bei Upgrades​

Damit geänderte Strings auch in bestehenden Installationen ankommen, muss die exportierte install-Funktion als Erstes im Upgrade-Schritt in ou.sp.<PREFIX>.installer.update.next.ts aufgerufen werden.