@cosmicdrift/kumiko-locale-de 0.414.0 → 0.415.0
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/package.json +2 -2
- package/src/__tests__/en-catalog.ts +2 -1
- package/src/__tests__/formal.test.ts +8 -7
- package/src/changes.json +6 -0
- package/src/formal.ts +23 -0
- package/src/strings.ts +16 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-locale-de",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.415.0",
|
|
4
4
|
"description": "German UI and mail copy for Kumiko framework screens. Opt in by mounting localeDe() + localeDeClient().",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
31
|
+
"@cosmicdrift/kumiko-framework": "0.415.0"
|
|
32
32
|
},
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"registry": "https://registry.npmjs.org",
|
|
@@ -994,7 +994,6 @@ export const frameworkEnCatalog: Readonly<Record<string, string>> = {
|
|
|
994
994
|
"kumiko.pager.pageSizeLabel": "Entries per page",
|
|
995
995
|
"kumiko.pager.previousPage": "Previous page",
|
|
996
996
|
"kumiko.pager.status": "{from}–{to} of {total}",
|
|
997
|
-
"kumiko.pager.status.noun": "{from}–{to} of {total} {noun}",
|
|
998
997
|
"kumiko.planCard.current": "Current plan",
|
|
999
998
|
"kumiko.planCard.priceUnavailable": "Price not available",
|
|
1000
999
|
"kumiko.reference.system-tenant": "System",
|
|
@@ -1057,6 +1056,8 @@ export const frameworkEnCatalog: Readonly<Record<string, string>> = {
|
|
|
1057
1056
|
"kumiko.widget.message-thread.showImages": "Load images",
|
|
1058
1057
|
"kumiko.widget.message-reader.mail": "Mail",
|
|
1059
1058
|
"kumiko.widget.step-list.progress": "{done} of {total} done",
|
|
1059
|
+
"kumiko.widget.step-list.total.one": "1 step",
|
|
1060
|
+
"kumiko.widget.step-list.total.other": "{count} steps",
|
|
1060
1061
|
"kumiko.widget.step-list.progressLabel": "Progress",
|
|
1061
1062
|
"kumiko.widget.step-list.moreSteps": "and {count} more steps",
|
|
1062
1063
|
"kumiko.widget.step-list.waitingFor": "Waiting for: {reason}",
|
|
@@ -18,19 +18,20 @@ const duFormRegex = /\b(du|dich|dir|dein\w*|Du|Dich|Dir|Dein\w*)\b/;
|
|
|
18
18
|
const informalImperativeRegex =
|
|
19
19
|
/(^|[.!?]\s+)(Gib|Wähle|Speichere|Klicke|Bestätige|Fordere|Scanne|Kopiere|Lege|Melde|Versuche|Prüfe|Öffne|Setze|Trage|Nutze|Verwende|Wende)(?![\p{L}])/u;
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
//
|
|
21
|
+
// The default bundle is du throughout; extend the allowlist only for genuine
|
|
22
|
+
// 3rd-person "Sie" referring to a noun.
|
|
23
23
|
const formalAddressRegex =
|
|
24
|
-
/\b(Ihr\w*|Ihnen|(Speichern|Nutzen|Laden|Wählen|Geben|Verwenden|Klicken|Prüfen|Legen|Fügen|Löschen|Bestätigen|Verwerfen|Bearbeiten|Öffnen|Setzen|Ziehen|Versuchen) Sie|Sie (sehen|können|müssen|haben|sind|werden|wollen|möchten|erhalten|benötigen))\b/;
|
|
24
|
+
/\b(Ihr\w*|Ihnen|(Speichern|Nutzen|Laden|Wählen|Geben|Verwenden|Klicken|Prüfen|Legen|Fügen|Löschen|Bestätigen|Verwerfen|Bearbeiten|Öffnen|Setzen|Ziehen|Versuchen|verwenden|ersetzen|ändern|prüfen|wählen|entfernen|schränken) Sie|Sie (sehen|können|müssen|haben|sind|werden|wollen|möchten|erhalten|benötigen))\b/;
|
|
25
25
|
|
|
26
|
-
const
|
|
26
|
+
const THIRD_PERSON_SIE_ALLOWLIST: ReadonlySet<string> = new Set<string>([
|
|
27
|
+
"auth.mfa.enable.recoveryHint",
|
|
28
|
+
]);
|
|
27
29
|
|
|
28
30
|
describe("locale-de formal overrides", () => {
|
|
29
|
-
test("informal bundle has no formal address
|
|
31
|
+
test("informal bundle has no formal address", () => {
|
|
30
32
|
const offenders = Object.entries(localeDeBundle)
|
|
31
|
-
.filter(([key]) => key.startsWith("documentDesigner."))
|
|
32
33
|
.filter(
|
|
33
|
-
([key, value]) => !
|
|
34
|
+
([key, value]) => !THIRD_PERSON_SIE_ALLOWLIST.has(key) && formalAddressRegex.test(value),
|
|
34
35
|
)
|
|
35
36
|
.map(([key]) => key);
|
|
36
37
|
expect(offenders).toEqual([]);
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.415.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "Informal German bundle says du throughout",
|
|
6
|
+
"detail": "Fourteen strings in the informal bundle addressed the user with Sie. They now say du. Apps with address formal keep the previous wording through the formal overrides."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.409.0",
|
|
4
10
|
"type": "improvement",
|
package/src/formal.ts
CHANGED
|
@@ -4,6 +4,29 @@ import { localeDeBundle } from "./strings";
|
|
|
4
4
|
export type GermanAddress = "informal" | "formal";
|
|
5
5
|
|
|
6
6
|
export const localeDeFormalOverrides: Readonly<Record<string, string>> = {
|
|
7
|
+
"admin-shell:overview.scope.notice":
|
|
8
|
+
"Sie sehen Daten aller Mandanten. Mandantenübergreifende Abfragen werden im Ereignisprotokoll vermerkt.",
|
|
9
|
+
"config.secret.channel-whatsapp.verify-token.hint":
|
|
10
|
+
"Beliebiger Text, den Sie auch in den Meta-Webhook-Einstellungen eintragen; beantwortet den Abonnement-Handshake von Meta.",
|
|
11
|
+
"kumiko.screen.forbidden": "Sie haben keinen Zugriff auf diese Seite.",
|
|
12
|
+
"managed-pages:body.lossy.warning":
|
|
13
|
+
"Diese Seite wurde in Markdown geschrieben. Bei der Umwandlung in den Editor gehen verloren: {features}. Prüfen Sie das Ergebnis vor dem Speichern.",
|
|
14
|
+
"template-resolver.editor.readOnly": "Nur lesbar. Ihre Rolle erlaubt hier keine Änderungen.",
|
|
15
|
+
"templateResolver.errors.patch.textAmbiguous":
|
|
16
|
+
"Der Text {find} kommt {count}-mal im Block vor; verwenden Sie einen längeren Text.",
|
|
17
|
+
"templateResolver.errors.patch.textSpansFormatting":
|
|
18
|
+
"Der Text {find} überspannt einen Formatwechsel im Block; ersetzen Sie jeden formatierten Teil einzeln.",
|
|
19
|
+
"templateResolver.errors.patch.placeholderNotReplaceable":
|
|
20
|
+
"Der Platzhalter {find} lässt sich nicht als Text ersetzen; ändern Sie den Text drumherum mit einer anderen Operation oder entfernen Sie den Block.",
|
|
21
|
+
"templateResolver.errors.collection.slugExists":
|
|
22
|
+
"Ein Eintrag mit dem Kürzel „{detail}“ existiert bereits. Wählen Sie ein anderes.",
|
|
23
|
+
"userDataRights.privacyCenter.subtitle":
|
|
24
|
+
"Laden Sie eine Kopie Ihrer Daten herunter (Art. 20), schränken Sie die Verarbeitung Ihres Kontos ein (Art. 18) oder löschen Sie es (Art. 17).",
|
|
25
|
+
"userDataRights.privacyCenter.subtitleWithoutDeletion":
|
|
26
|
+
"Laden Sie eine Kopie Ihrer Daten herunter (Art. 20) oder schränken Sie die Verarbeitung Ihres Kontos ein (Art. 18).",
|
|
27
|
+
"screen:my-mail-accounts.title": "Ihre Postfächer",
|
|
28
|
+
"inboundMail.accounts.reactivateOauth.confirm":
|
|
29
|
+
"Sie werden zur Anmeldeseite des Anbieters weitergeleitet. Nach der Anmeldung ruft das Postfach wieder Mails ab und behält seinen Verlauf.",
|
|
7
30
|
"documentDesigner.editor.mjmlNotice.tenant":
|
|
8
31
|
"Sie sehen das System-Layout. Speichern legt ein eigenes Layout für Ihren Mandanten an.",
|
|
9
32
|
"documentDesigner.editor.origin.system":
|
package/src/strings.ts
CHANGED
|
@@ -39,7 +39,7 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
39
39
|
"admin-shell:overview.range.7d": "7 Tage",
|
|
40
40
|
"admin-shell:overview.scope.badge": "Alle Mandanten",
|
|
41
41
|
"admin-shell:overview.scope.notice":
|
|
42
|
-
"
|
|
42
|
+
"Du siehst Daten aller Mandanten. Mandantenübergreifende Abfragen werden im Ereignisprotokoll vermerkt.",
|
|
43
43
|
"admin-shell:workspace.platform": "Plattform",
|
|
44
44
|
"admin-shell:workspace.tenant": "Administration",
|
|
45
45
|
"audit.errors.systemScopeRequiresSystemAdmin": "Nur SystemAdmin darf Systemereignisse lesen.",
|
|
@@ -475,7 +475,7 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
475
475
|
"App-Secret der Meta-App. Prüft die Signatur jedes eingehenden Webhooks.",
|
|
476
476
|
"config.secret.channel-whatsapp.app-secret.label": "WhatsApp-App-Secret",
|
|
477
477
|
"config.secret.channel-whatsapp.verify-token.hint":
|
|
478
|
-
"Beliebiger Text, den
|
|
478
|
+
"Beliebiger Text, den du auch in den Meta-Webhook-Einstellungen einträgst; beantwortet den Abonnement-Handshake von Meta.",
|
|
479
479
|
"config.secret.channel-whatsapp.verify-token.label": "WhatsApp-Verifizierungstoken",
|
|
480
480
|
"config.secret.file-provider-s3.s3-secret-access-key.hint":
|
|
481
481
|
"Privater Teil des S3-Schlüsselpaars. Hetzner nennt ihn „Secret Key“, AWS „Secret Access Key“.",
|
|
@@ -803,12 +803,12 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
803
803
|
"kumiko.error.reference": "Fehler-ID: {id}",
|
|
804
804
|
"kumiko.error.copyReference": "Kopieren",
|
|
805
805
|
"kumiko.error.referenceCopied": "Kopiert!",
|
|
806
|
-
"kumiko.screen-access-denied.title": "
|
|
806
|
+
"kumiko.screen-access-denied.title": "Du hast keinen Zugriff auf diese Seite.",
|
|
807
807
|
"kumiko.screen-missing.home": "Zur Startseite",
|
|
808
808
|
"kumiko.screen-missing.hint":
|
|
809
809
|
"Sie ist für dein Konto nicht freigeschaltet oder existiert nicht mehr.",
|
|
810
810
|
"kumiko.screen-missing.title": "Diese Seite ist nicht verfügbar",
|
|
811
|
-
"kumiko.screen.forbidden": "
|
|
811
|
+
"kumiko.screen.forbidden": "Du hast keinen Zugriff auf diese Seite.",
|
|
812
812
|
"kumiko.screen.notFound": "Diese Seite wurde nicht gefunden.",
|
|
813
813
|
"kumiko.screen.unavailable": "Diese Seite ist derzeit nicht verfügbar.",
|
|
814
814
|
"kumiko.dashboard.brush-end": "Fensterende",
|
|
@@ -1029,7 +1029,6 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
1029
1029
|
"kumiko.pager.pageSizeLabel": "Einträge pro Seite",
|
|
1030
1030
|
"kumiko.pager.previousPage": "Vorherige Seite",
|
|
1031
1031
|
"kumiko.pager.status": "{from}–{to} von {total}",
|
|
1032
|
-
"kumiko.pager.status.noun": "{from}–{to} von {total} {noun}",
|
|
1033
1032
|
"kumiko.planCard.current": "Aktueller Tarif",
|
|
1034
1033
|
"kumiko.planCard.priceUnavailable": "Preis nicht verfügbar",
|
|
1035
1034
|
"kumiko.reference.system-tenant": "System",
|
|
@@ -1092,6 +1091,8 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
1092
1091
|
"kumiko.widget.message-thread.showImages": "Bilder laden",
|
|
1093
1092
|
"kumiko.widget.message-reader.mail": "Mail",
|
|
1094
1093
|
"kumiko.widget.step-list.progress": "{done} von {total} erledigt",
|
|
1094
|
+
"kumiko.widget.step-list.total.one": "1 Schritt",
|
|
1095
|
+
"kumiko.widget.step-list.total.other": "{count} Schritte",
|
|
1095
1096
|
"kumiko.widget.step-list.progressLabel": "Fortschritt",
|
|
1096
1097
|
"kumiko.widget.step-list.moreSteps": "und {count} weitere Schritte",
|
|
1097
1098
|
"kumiko.widget.step-list.waitingFor": "Wartet auf: {reason}",
|
|
@@ -1139,7 +1140,7 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
1139
1140
|
"managed-pages:actions.edit": "Bearbeiten",
|
|
1140
1141
|
"managed-pages.errors.document.rejected": "Der Inhalt enthält nicht erlaubte Elemente: {detail}",
|
|
1141
1142
|
"managed-pages:body.lossy.warning":
|
|
1142
|
-
"Diese Seite wurde in Markdown geschrieben. Bei der Umwandlung in den Editor gehen verloren: {features}.
|
|
1143
|
+
"Diese Seite wurde in Markdown geschrieben. Bei der Umwandlung in den Editor gehen verloren: {features}. Prüfe das Ergebnis vor dem Speichern.",
|
|
1143
1144
|
"managed-pages:body.lossy.image": "externe Bilder",
|
|
1144
1145
|
"managed-pages:body.lossy.blockquote": "Zitate",
|
|
1145
1146
|
"managed-pages:body.lossy.code": "Code",
|
|
@@ -1460,7 +1461,7 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
1460
1461
|
"template-resolver.editor.networkError": "Netzwerkfehler beim Speichern.",
|
|
1461
1462
|
"template-resolver.editor.newEntry": "Neuer Eintrag",
|
|
1462
1463
|
"template-resolver.editor.newEntryTitle": "Neu: {label}",
|
|
1463
|
-
"template-resolver.editor.readOnly": "Nur lesbar.
|
|
1464
|
+
"template-resolver.editor.readOnly": "Nur lesbar. Deine Rolle erlaubt hier keine Änderungen.",
|
|
1464
1465
|
"template-resolver.editor.infoPreviewPlain":
|
|
1465
1466
|
"Vorschau des ungespeicherten Stands, so wie die Seite ihn zeigt. Kopf und Fuß der Website sind nicht enthalten.",
|
|
1466
1467
|
"template-resolver.preview.frameTitle": "Textvorschau",
|
|
@@ -1540,11 +1541,11 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
1540
1541
|
"Der Block {blockId} wurde von einem früheren Schritt bereits entfernt.",
|
|
1541
1542
|
"templateResolver.errors.patch.textNotFound": "Der Text {find} wurde im Block nicht gefunden.",
|
|
1542
1543
|
"templateResolver.errors.patch.textAmbiguous":
|
|
1543
|
-
"Der Text {find} kommt {count}-mal im Block vor;
|
|
1544
|
+
"Der Text {find} kommt {count}-mal im Block vor; verwende einen längeren Text.",
|
|
1544
1545
|
"templateResolver.errors.patch.textSpansFormatting":
|
|
1545
|
-
"Der Text {find} überspannt einen Formatwechsel im Block;
|
|
1546
|
+
"Der Text {find} überspannt einen Formatwechsel im Block; ersetze jeden formatierten Teil einzeln.",
|
|
1546
1547
|
"templateResolver.errors.patch.placeholderNotReplaceable":
|
|
1547
|
-
"Der Platzhalter {find} lässt sich nicht als Text ersetzen;
|
|
1548
|
+
"Der Platzhalter {find} lässt sich nicht als Text ersetzen; ändere den Text drumherum mit einer anderen Operation oder entferne den Block.",
|
|
1548
1549
|
"templateResolver.errors.patch.blockNotAllowed":
|
|
1549
1550
|
"Der Blocktyp {type} ist in {kind}-Vorlagen nicht verfügbar.",
|
|
1550
1551
|
"templateResolver.errors.patch.blockTypeMismatch":
|
|
@@ -1579,7 +1580,7 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
1579
1580
|
"templateResolver.errors.collection.kindNotAllowed":
|
|
1580
1581
|
"„{detail}“-Vorlagen werden im eigenen Editor gepflegt, nicht über eine Sammlung.",
|
|
1581
1582
|
"templateResolver.errors.collection.slugExists":
|
|
1582
|
-
"Ein Eintrag mit dem Kürzel „{detail}“ existiert bereits.
|
|
1583
|
+
"Ein Eintrag mit dem Kürzel „{detail}“ existiert bereits. Wähle ein anderes.",
|
|
1583
1584
|
"templateResolver.errors.noSystemTemplate":
|
|
1584
1585
|
"Es gibt keine aktive Systemvorlage, auf die zurückgesetzt werden könnte.",
|
|
1585
1586
|
"templateResolver.errors.noDraft": "Es gibt keinen Entwurf, der verworfen werden könnte.",
|
|
@@ -1793,9 +1794,9 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
1793
1794
|
"userDataRights.privacyCenter.restriction.restrict": "Konto einschränken",
|
|
1794
1795
|
"userDataRights.privacyCenter.restriction.title": "Verarbeitung einschränken · Art. 18",
|
|
1795
1796
|
"userDataRights.privacyCenter.subtitle":
|
|
1796
|
-
"
|
|
1797
|
+
"Lade eine Kopie deiner Daten herunter (Art. 20), schränke die Verarbeitung deines Kontos ein (Art. 18) oder lösche es (Art. 17).",
|
|
1797
1798
|
"userDataRights.privacyCenter.subtitleWithoutDeletion":
|
|
1798
|
-
"
|
|
1799
|
+
"Lade eine Kopie deiner Daten herunter (Art. 20) oder schränke die Verarbeitung deines Kontos ein (Art. 18).",
|
|
1799
1800
|
"admin-shell.screen.platform-overview.subtitle":
|
|
1800
1801
|
"Zustand von Mandanten, Benutzern, Jobs und Zustellungen der gesamten Installation.",
|
|
1801
1802
|
"admin-shell.screen.tenant-overview.subtitle":
|
|
@@ -2202,7 +2203,7 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
2202
2203
|
"mail-transport-smtp.from.description":
|
|
2203
2204
|
"Von dieser Adresse kommen die Mails, zum Beispiel status@example.com. Dein Anbieter muss sie erlauben.",
|
|
2204
2205
|
"screen:mail-accounts.title": "Postfächer",
|
|
2205
|
-
"screen:my-mail-accounts.title": "
|
|
2206
|
+
"screen:my-mail-accounts.title": "Deine Postfächer",
|
|
2206
2207
|
"screen:mail-account-edit.title": "Postfach bearbeiten",
|
|
2207
2208
|
"screen:mail-account-sender-check.title": "Absenderprüfung",
|
|
2208
2209
|
"inboundMail.accounts.col.name": "Name",
|
|
@@ -2265,7 +2266,7 @@ export const localeDeBundle: Readonly<Record<string, string>> = {
|
|
|
2265
2266
|
"inboundMail.accounts.connectImap": "Postfach verbinden",
|
|
2266
2267
|
"screen:mail-account-connect-imap.title": "Postfach verbinden",
|
|
2267
2268
|
"inboundMail.accounts.reactivateOauth.confirm":
|
|
2268
|
-
"
|
|
2269
|
+
"Du wirst zur Anmeldeseite des Anbieters weitergeleitet. Nach der Anmeldung ruft das Postfach wieder Mails ab und behält seinen Verlauf.",
|
|
2269
2270
|
"inboundMail.accounts.reconnect.invalidRow":
|
|
2270
2271
|
"Dieses Postfach lässt sich hier nicht reaktivieren.",
|
|
2271
2272
|
"screen:mail-account-reconnect-imap.title": "Postfach neu verbinden",
|