chronolizer 0.1.0 → 0.3.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.
Files changed (62) hide show
  1. package/README.md +184 -119
  2. package/dist/ast/constructors.d.mts +135 -0
  3. package/dist/ast/constructors.mjs +25 -0
  4. package/dist/ast/fold.d.mts +13 -0
  5. package/dist/ast/fold.mjs +58 -0
  6. package/dist/ast/normalize.d.mts +42 -0
  7. package/dist/ast/normalize.mjs +34 -0
  8. package/dist/ast/schemas.d.mts +80 -0
  9. package/dist/ast/schemas.mjs +65 -0
  10. package/dist/filter/codec.d.mts +92 -0
  11. package/dist/filter/codec.mjs +48 -0
  12. package/dist/filter/errors.d.mts +14 -0
  13. package/dist/filter/errors.mjs +10 -0
  14. package/dist/filter/expression.d.mts +8 -0
  15. package/dist/filter/expression.mjs +76 -0
  16. package/dist/filter/schema.d.mts +13 -0
  17. package/dist/filter/schema.mjs +11 -0
  18. package/dist/filter/transformation.d.mts +37 -0
  19. package/dist/filter/transformation.mjs +20 -0
  20. package/dist/index.d.mts +22 -969
  21. package/dist/index.mjs +22 -2305
  22. package/dist/language/errors.d.mts +38 -0
  23. package/dist/language/errors.mjs +30 -0
  24. package/dist/language/model.d.mts +239 -0
  25. package/dist/language/model.mjs +50 -0
  26. package/dist/language/registry.d.mts +17 -0
  27. package/dist/language/registry.mjs +116 -0
  28. package/dist/locales/cs.d.mts +10 -0
  29. package/dist/locales/cs.mjs +746 -0
  30. package/dist/locales/de.d.mts +10 -0
  31. package/dist/locales/de.mjs +1039 -0
  32. package/dist/locales/en.d.mts +10 -0
  33. package/dist/locales/en.mjs +598 -0
  34. package/dist/locales/es.d.mts +10 -0
  35. package/dist/locales/es.mjs +908 -0
  36. package/dist/locales/fr.d.mts +10 -0
  37. package/dist/locales/fr.mjs +901 -0
  38. package/dist/locales/nl.d.mts +10 -0
  39. package/dist/locales/nl.mjs +791 -0
  40. package/dist/locales/pl.d.mts +10 -0
  41. package/dist/locales/pl.mjs +885 -0
  42. package/dist/locales/shared.mjs +395 -0
  43. package/dist/locales/tr.d.mts +10 -0
  44. package/dist/locales/tr.mjs +725 -0
  45. package/dist/natural/correction.d.mts +13 -0
  46. package/dist/natural/correction.mjs +73 -0
  47. package/dist/natural/format.d.mts +47 -0
  48. package/dist/natural/format.mjs +14 -0
  49. package/dist/natural/parse.d.mts +99 -0
  50. package/dist/natural/parse.mjs +66 -0
  51. package/dist/natural/policy.mjs +6 -0
  52. package/dist/natural/suggest.d.mts +53 -0
  53. package/dist/natural/suggest.mjs +24 -0
  54. package/dist/natural/suggestion.d.mts +4 -0
  55. package/dist/natural/suggestion.mjs +79 -0
  56. package/dist/natural/text.d.mts +5 -0
  57. package/dist/natural/text.mjs +5 -0
  58. package/dist/resolve/resolve.d.mts +79 -0
  59. package/dist/resolve/resolve.mjs +58 -0
  60. package/dist/resolve/schema.d.mts +59 -0
  61. package/dist/resolve/schema.mjs +28 -0
  62. package/package.json +15 -3
@@ -0,0 +1,1039 @@
1
+ import { isIsoDate } from "../ast/schemas.mjs";
2
+ import { BaseLanguageContribution } from "../language/model.mjs";
3
+ import { normalizeNaturalText } from "../natural/text.mjs";
4
+ import { defineLanguagePlugin, languagePluginsLayer } from "../language/registry.mjs";
5
+ import { correctWhitespaceSeparatedText } from "../natural/correction.mjs";
6
+ import { completeNaturalPhrases, fixedCalendarPeriodPhrases, naturalCount, prefixNaturalPhrases } from "../natural/suggestion.mjs";
7
+ import { absoluteDatePeriod, calendarPeriodOffset, candidate, currentYearDatePeriods, datedPeriods, datedQuarterPeriods, fixedDatePeriod, fixedMonthPeriod, fixedQuarterPeriod, fixedYearPeriod, fromNowRange, futurePeriod, futureRange, isoDate, joinedNowCandidate, joinedPeriodCandidate, monthOfRelativeYear, namedCurrentYearDatePeriod, namedDatePeriod, openBoundaryCandidate, parseTrailingCount, periodBoundaryCandidate, periodEndDay, periodRange, periodStartDay, periodToDateRange, periodsFromPhrases, quarterOfRelativeYear, relativePeriod, relativeWeekend, remainingPeriodRange, renderPeriodRange, textAt, trailingPeriod, trailingRange, untilNowRange, validYear } from "./shared.mjs";
8
+ import { Effect, Option, String as String$1 } from "effect";
9
+ //#region src/locales/de.ts
10
+ const months = [
11
+ "januar",
12
+ "februar",
13
+ "märz",
14
+ "april",
15
+ "mai",
16
+ "juni",
17
+ "juli",
18
+ "august",
19
+ "september",
20
+ "oktober",
21
+ "november",
22
+ "dezember"
23
+ ];
24
+ const monthAbbreviations = [
25
+ ["jan"],
26
+ ["feb"],
27
+ ["mär", "mrz"],
28
+ ["apr"],
29
+ ["mai"],
30
+ ["jun"],
31
+ ["jul"],
32
+ ["aug"],
33
+ ["sep", "sept"],
34
+ ["okt"],
35
+ ["nov"],
36
+ ["dez"]
37
+ ];
38
+ const unitPhrases = [
39
+ {
40
+ unit: "day",
41
+ noun: "tag",
42
+ plural: "tage",
43
+ current: "heute",
44
+ previous: "gestern",
45
+ next: "morgen",
46
+ compound: "tages",
47
+ currentGenitive: "dieses tages",
48
+ previousGenitive: "letzten tages",
49
+ nextGenitive: "nächsten tages",
50
+ indefiniteDative: "einem tag",
51
+ indefiniteGenitive: "eines tages",
52
+ dative: "tagen",
53
+ genitive: "des tages"
54
+ },
55
+ {
56
+ unit: "week",
57
+ noun: "woche",
58
+ plural: "wochen",
59
+ current: "diese woche",
60
+ previous: "letzte woche",
61
+ next: "nächste woche",
62
+ compound: "wochen",
63
+ currentGenitive: "dieser woche",
64
+ previousGenitive: "letzter woche",
65
+ nextGenitive: "nächster woche",
66
+ indefiniteDative: "einer woche",
67
+ indefiniteGenitive: "einer woche",
68
+ dative: "wochen",
69
+ genitive: "der woche"
70
+ },
71
+ {
72
+ unit: "month",
73
+ noun: "monat",
74
+ plural: "monate",
75
+ current: "dieser monat",
76
+ previous: "letzter monat",
77
+ next: "nächster monat",
78
+ compound: "monats",
79
+ currentGenitive: "dieses monats",
80
+ previousGenitive: "letzten monats",
81
+ nextGenitive: "nächsten monats",
82
+ indefiniteDative: "einem monat",
83
+ indefiniteGenitive: "eines monats",
84
+ dative: "monaten",
85
+ genitive: "des monats"
86
+ },
87
+ {
88
+ unit: "quarter",
89
+ noun: "quartal",
90
+ plural: "quartale",
91
+ current: "dieses quartal",
92
+ previous: "letztes quartal",
93
+ next: "nächstes quartal",
94
+ compound: "quartals",
95
+ currentGenitive: "dieses quartals",
96
+ previousGenitive: "letzten quartals",
97
+ nextGenitive: "nächsten quartals",
98
+ indefiniteDative: "einem quartal",
99
+ indefiniteGenitive: "eines quartals",
100
+ dative: "quartalen",
101
+ genitive: "des quartals"
102
+ },
103
+ {
104
+ unit: "year",
105
+ noun: "jahr",
106
+ plural: "jahre",
107
+ current: "dieses jahr",
108
+ previous: "letztes jahr",
109
+ next: "nächstes jahr",
110
+ compound: "jahres",
111
+ currentGenitive: "dieses jahres",
112
+ previousGenitive: "letzten jahres",
113
+ nextGenitive: "nächsten jahres",
114
+ indefiniteDative: "einem jahr",
115
+ indefiniteGenitive: "eines jahres",
116
+ dative: "jahren",
117
+ genitive: "des jahres"
118
+ }
119
+ ];
120
+ const title = (value) => `${value.slice(0, 1).toLocaleUpperCase("de")}${value.slice(1)}`;
121
+ const canonicalToDate = (entry) => `seit ${title(entry.compound)}beginn`;
122
+ const canonicalRelative = (value) => {
123
+ const separator = value.lastIndexOf(" ");
124
+ if (separator === -1) return value;
125
+ return `${value.slice(0, separator + 1)}${title(value.slice(separator + 1))}`;
126
+ };
127
+ const remainingPeriodPhrases = unitPhrases.flatMap((entry) => [`rest ${entry.genitive}`, `rest ${entry.currentGenitive}`].map((phrase) => ({
128
+ entry,
129
+ phrase
130
+ })));
131
+ const toDatePhrases = unitPhrases.flatMap((entry) => [
132
+ `seit ${entry.compound}beginn`,
133
+ `seit ${entry.compound}anfang`,
134
+ `seit beginn ${entry.genitive}`,
135
+ `seit anfang ${entry.genitive}`,
136
+ `seit beginn ${entry.currentGenitive}`,
137
+ `seit anfang ${entry.currentGenitive}`,
138
+ `vom ${entry.compound}beginn bis heute`,
139
+ `vom ${entry.compound}anfang bis heute`,
140
+ `vom beginn ${entry.genitive} bis heute`,
141
+ `vom anfang ${entry.genitive} bis heute`,
142
+ `vom beginn ${entry.currentGenitive} bis heute`,
143
+ `vom anfang ${entry.currentGenitive} bis heute`,
144
+ `${entry.noun} bis heute`,
145
+ `${entry.current} bisher`,
146
+ `bisher ${entry.current}`
147
+ ].map((phrase) => ({
148
+ entry,
149
+ phrase
150
+ })));
151
+ const currentBoundaryPhrases = unitPhrases.flatMap((entry) => [
152
+ [`vor ${entry.compound}beginn`, "before"],
153
+ [`vor ${entry.compound}anfang`, "before"],
154
+ [`bis ${entry.compound}beginn`, "before"],
155
+ [`bis ${entry.compound}anfang`, "before"],
156
+ [`bis ${entry.compound}ende`, "through"],
157
+ [`nach ${entry.compound}ende`, "after"],
158
+ [`ab ${entry.compound}ende`, "after"]
159
+ ].map(([phrase, boundary]) => ({
160
+ boundary,
161
+ entry,
162
+ phrase
163
+ })));
164
+ const declinedBoundaryPeriods = [
165
+ [
166
+ "diese woche",
167
+ "week",
168
+ 0,
169
+ "dieser woche",
170
+ "diese woche"
171
+ ],
172
+ [
173
+ "letzte woche",
174
+ "week",
175
+ -1,
176
+ "letzter woche",
177
+ "letzte woche"
178
+ ],
179
+ [
180
+ "nächste woche",
181
+ "week",
182
+ 1,
183
+ "nächster woche",
184
+ "nächste woche"
185
+ ],
186
+ [
187
+ "dieser monat",
188
+ "month",
189
+ 0,
190
+ "diesem monat",
191
+ "diesen monat"
192
+ ],
193
+ [
194
+ "letzter monat",
195
+ "month",
196
+ -1,
197
+ "letztem monat",
198
+ "letzten monat"
199
+ ],
200
+ [
201
+ "nächster monat",
202
+ "month",
203
+ 1,
204
+ "nächstem monat",
205
+ "nächsten monat"
206
+ ],
207
+ [
208
+ "dieses quartal",
209
+ "quarter",
210
+ 0,
211
+ "diesem quartal",
212
+ "dieses quartal"
213
+ ],
214
+ [
215
+ "letztes quartal",
216
+ "quarter",
217
+ -1,
218
+ "letztem quartal",
219
+ "letztes quartal"
220
+ ],
221
+ [
222
+ "nächstes quartal",
223
+ "quarter",
224
+ 1,
225
+ "nächstem quartal",
226
+ "nächstes quartal"
227
+ ],
228
+ [
229
+ "dieses jahr",
230
+ "year",
231
+ 0,
232
+ "diesem jahr",
233
+ "dieses jahr"
234
+ ],
235
+ [
236
+ "letztes jahr",
237
+ "year",
238
+ -1,
239
+ "letztem jahr",
240
+ "letztes jahr"
241
+ ],
242
+ [
243
+ "nächstes jahr",
244
+ "year",
245
+ 1,
246
+ "nächstem jahr",
247
+ "nächstes jahr"
248
+ ]
249
+ ];
250
+ const relativeAliases = [
251
+ ...unitPhrases.flatMap((entry) => [
252
+ [
253
+ entry.currentGenitive,
254
+ entry.unit,
255
+ 0,
256
+ entry.current
257
+ ],
258
+ [
259
+ entry.previousGenitive,
260
+ entry.unit,
261
+ -1,
262
+ entry.previous
263
+ ],
264
+ [
265
+ entry.nextGenitive,
266
+ entry.unit,
267
+ 1,
268
+ entry.next
269
+ ]
270
+ ]),
271
+ ...declinedBoundaryPeriods.map(([canonical, unit, direction, dative]) => [
272
+ dative,
273
+ unit,
274
+ direction,
275
+ canonical
276
+ ]),
277
+ [
278
+ "vorgestern",
279
+ "day",
280
+ -2,
281
+ "vorgestern"
282
+ ],
283
+ [
284
+ "vorletzten tag",
285
+ "day",
286
+ -2,
287
+ "vorletzter tag"
288
+ ],
289
+ [
290
+ "übernächsten tag",
291
+ "day",
292
+ 2,
293
+ "übernächster tag"
294
+ ],
295
+ [
296
+ "vorletzte woche",
297
+ "week",
298
+ -2,
299
+ "vorletzte woche"
300
+ ],
301
+ [
302
+ "übernächste woche",
303
+ "week",
304
+ 2,
305
+ "übernächste woche"
306
+ ],
307
+ [
308
+ "vorletzten monat",
309
+ "month",
310
+ -2,
311
+ "vorletzter monat"
312
+ ],
313
+ [
314
+ "übernächsten monat",
315
+ "month",
316
+ 2,
317
+ "übernächster monat"
318
+ ],
319
+ [
320
+ "vorletztes quartal",
321
+ "quarter",
322
+ -2,
323
+ "vorletztes quartal"
324
+ ],
325
+ [
326
+ "übernächstes quartal",
327
+ "quarter",
328
+ 2,
329
+ "übernächstes quartal"
330
+ ],
331
+ [
332
+ "vorletztes jahr",
333
+ "year",
334
+ -2,
335
+ "vorletztes jahr"
336
+ ],
337
+ [
338
+ "übernächstes jahr",
339
+ "year",
340
+ 2,
341
+ "übernächstes jahr"
342
+ ],
343
+ [
344
+ "letzten tag",
345
+ "day",
346
+ -1,
347
+ "gestern"
348
+ ],
349
+ [
350
+ "vergangenen tag",
351
+ "day",
352
+ -1,
353
+ "gestern"
354
+ ],
355
+ [
356
+ "vorherigen tag",
357
+ "day",
358
+ -1,
359
+ "gestern"
360
+ ],
361
+ [
362
+ "diesen tag",
363
+ "day",
364
+ 0,
365
+ "heute"
366
+ ],
367
+ [
368
+ "heutigen tag",
369
+ "day",
370
+ 0,
371
+ "heute"
372
+ ],
373
+ [
374
+ "nächsten tag",
375
+ "day",
376
+ 1,
377
+ "morgen"
378
+ ],
379
+ [
380
+ "kommenden tag",
381
+ "day",
382
+ 1,
383
+ "morgen"
384
+ ],
385
+ [
386
+ "vergangene woche",
387
+ "week",
388
+ -1,
389
+ "letzte woche"
390
+ ],
391
+ [
392
+ "vorherige woche",
393
+ "week",
394
+ -1,
395
+ "letzte woche"
396
+ ],
397
+ [
398
+ "aktuelle woche",
399
+ "week",
400
+ 0,
401
+ "diese woche"
402
+ ],
403
+ [
404
+ "laufende woche",
405
+ "week",
406
+ 0,
407
+ "diese woche"
408
+ ],
409
+ [
410
+ "kommende woche",
411
+ "week",
412
+ 1,
413
+ "nächste woche"
414
+ ],
415
+ [
416
+ "folgende woche",
417
+ "week",
418
+ 1,
419
+ "nächste woche"
420
+ ],
421
+ [
422
+ "letzten monat",
423
+ "month",
424
+ -1,
425
+ "letzter monat"
426
+ ],
427
+ [
428
+ "vergangenen monat",
429
+ "month",
430
+ -1,
431
+ "letzter monat"
432
+ ],
433
+ [
434
+ "vorherigen monat",
435
+ "month",
436
+ -1,
437
+ "letzter monat"
438
+ ],
439
+ [
440
+ "diesen monat",
441
+ "month",
442
+ 0,
443
+ "dieser monat"
444
+ ],
445
+ [
446
+ "aktuellen monat",
447
+ "month",
448
+ 0,
449
+ "dieser monat"
450
+ ],
451
+ [
452
+ "laufenden monat",
453
+ "month",
454
+ 0,
455
+ "dieser monat"
456
+ ],
457
+ [
458
+ "nächsten monat",
459
+ "month",
460
+ 1,
461
+ "nächster monat"
462
+ ],
463
+ [
464
+ "kommenden monat",
465
+ "month",
466
+ 1,
467
+ "nächster monat"
468
+ ],
469
+ [
470
+ "folgenden monat",
471
+ "month",
472
+ 1,
473
+ "nächster monat"
474
+ ],
475
+ [
476
+ "vergangenes quartal",
477
+ "quarter",
478
+ -1,
479
+ "letztes quartal"
480
+ ],
481
+ [
482
+ "vorheriges quartal",
483
+ "quarter",
484
+ -1,
485
+ "letztes quartal"
486
+ ],
487
+ [
488
+ "aktuelles quartal",
489
+ "quarter",
490
+ 0,
491
+ "dieses quartal"
492
+ ],
493
+ [
494
+ "laufendes quartal",
495
+ "quarter",
496
+ 0,
497
+ "dieses quartal"
498
+ ],
499
+ [
500
+ "kommendes quartal",
501
+ "quarter",
502
+ 1,
503
+ "nächstes quartal"
504
+ ],
505
+ [
506
+ "folgendes quartal",
507
+ "quarter",
508
+ 1,
509
+ "nächstes quartal"
510
+ ],
511
+ [
512
+ "vergangenes jahr",
513
+ "year",
514
+ -1,
515
+ "letztes jahr"
516
+ ],
517
+ [
518
+ "vorheriges jahr",
519
+ "year",
520
+ -1,
521
+ "letztes jahr"
522
+ ],
523
+ [
524
+ "aktuelles jahr",
525
+ "year",
526
+ 0,
527
+ "dieses jahr"
528
+ ],
529
+ [
530
+ "laufendes jahr",
531
+ "year",
532
+ 0,
533
+ "dieses jahr"
534
+ ],
535
+ [
536
+ "kommendes jahr",
537
+ "year",
538
+ 1,
539
+ "nächstes jahr"
540
+ ],
541
+ [
542
+ "folgendes jahr",
543
+ "year",
544
+ 1,
545
+ "nächstes jahr"
546
+ ]
547
+ ];
548
+ const monthNumber = (value) => {
549
+ const normalized = value.endsWith(".") ? value.slice(0, -1) : value;
550
+ const fullIndex = months.findIndex((month) => month === normalized);
551
+ if (fullIndex !== -1) return fullIndex + 1;
552
+ const shortIndex = monthAbbreviations.findIndex((aliases) => aliases.some((alias) => alias === normalized));
553
+ return shortIndex === -1 ? void 0 : shortIndex + 1;
554
+ };
555
+ const currentDateLabel = (day, month) => `${day}. ${title(textAt(months, month - 1))}`;
556
+ const withRelativeCase = (canonical, grammaticalCase) => {
557
+ const period = declinedBoundaryPeriods.find((entry) => canonical === canonicalRelative(entry[0]));
558
+ if (period === void 0) return canonical;
559
+ return canonicalRelative(period[grammaticalCase === "dative" ? 3 : 4]);
560
+ };
561
+ const withRelativeGenitive = (canonical) => {
562
+ for (const entry of unitPhrases) {
563
+ if (canonical === canonicalRelative(entry.current)) return canonicalRelative(entry.currentGenitive);
564
+ if (canonical === canonicalRelative(entry.previous)) return canonicalRelative(entry.previousGenitive);
565
+ if (canonical === canonicalRelative(entry.next)) return canonicalRelative(entry.nextGenitive);
566
+ }
567
+ return canonical;
568
+ };
569
+ const parseNamedDate = (input) => {
570
+ const named = String$1.match(/^([0-3]?\d)\.? ([a-zäöüß]+\.?) (\d{4})$/u)(input);
571
+ if (Option.isSome(named)) return namedDatePeriod(textAt(named.value, 3), textAt(named.value, 2), textAt(named.value, 1), monthNumber, (day, month, year) => `${day}. ${title(textAt(months, month - 1))} ${year}`);
572
+ const numeric = String$1.match(/^([0-3]?\d)\.([01]?\d)\.(\d{4})$/u)(input);
573
+ if (Option.isSome(numeric)) {
574
+ const year = validYear(textAt(numeric.value, 3));
575
+ const day = Number(textAt(numeric.value, 1));
576
+ const month = Number(textAt(numeric.value, 2));
577
+ if (year !== void 0 && month >= 1 && month <= 12) {
578
+ const value = isoDate(year, month, day);
579
+ if (isIsoDate(value) && value !== "9999-12-31") return Option.some(fixedDatePeriod(value, `${day}. ${title(textAt(months, month - 1))} ${year}`));
580
+ }
581
+ }
582
+ const current = String$1.match(/^([0-3]?\d)\.? ([a-zäöüß]+\.?)$/u)(input);
583
+ return Option.isSome(current) ? namedCurrentYearDatePeriod(textAt(current.value, 2), textAt(current.value, 1), monthNumber, currentDateLabel) : Option.none();
584
+ };
585
+ const quarterNames = [
586
+ "erstes",
587
+ "zweites",
588
+ "drittes",
589
+ "viertes"
590
+ ];
591
+ const quarterNumber = (value) => {
592
+ if (value.startsWith("q")) return Number(value.slice(1));
593
+ if (value.endsWith(".")) return Number(value.slice(0, -1));
594
+ const index = quarterNames.findIndex((name) => name === value);
595
+ return index === -1 ? void 0 : index + 1;
596
+ };
597
+ const relativeDirection = (value) => {
598
+ if (value === "letzten") return -1;
599
+ if (value === "nächsten") return 1;
600
+ return 0;
601
+ };
602
+ const parseQuarter = (input) => {
603
+ const fixed = String$1.match(/^(q[1-4]|[1-4]\.|erstes|zweites|drittes|viertes)(?: quartal)? (\d{4})$/u)(input);
604
+ const reversed = String$1.match(/^(\d{4}) (q[1-4])$/u)(input);
605
+ const relative = String$1.match(/^(q[1-4]|[1-4]\.|erstes|zweites|drittes|viertes)(?: quartal)? (letzten|dieses|nächsten) jahres$/u)(input);
606
+ const standalone = String$1.match(/^(q[1-4]|[1-4]\.|erstes|zweites|drittes|viertes)(?: quartal)?$/u)(input);
607
+ const fixedMatch = Option.firstSomeOf([fixed, reversed]);
608
+ if (Option.isSome(fixedMatch)) {
609
+ const quarterText = textAt(fixedMatch.value, Option.isSome(reversed) ? 2 : 1);
610
+ const yearText = textAt(fixedMatch.value, Option.isSome(reversed) ? 1 : 2);
611
+ const quarter = quarterNumber(quarterText);
612
+ const year = validYear(yearText);
613
+ if (quarter !== void 0 && year !== void 0) return Option.some(fixedQuarterPeriod(year, quarter, `Q${quarter} ${year}`));
614
+ }
615
+ if (Option.isSome(relative)) {
616
+ const directionText = textAt(relative.value, 2);
617
+ const quarter = quarterNumber(textAt(relative.value, 1));
618
+ if (quarter !== void 0) {
619
+ const direction = relativeDirection(directionText);
620
+ return Option.some(quarterOfRelativeYear(quarter, direction, `Q${quarter} ${directionText} Jahres`));
621
+ }
622
+ }
623
+ if (Option.isNone(standalone)) return Option.none();
624
+ const quarter = quarterNumber(textAt(standalone.value, 1));
625
+ return quarter === void 0 ? Option.none() : Option.some(quarterOfRelativeYear(quarter, 0, `Q${quarter}`));
626
+ };
627
+ const parseBasePeriod = (input) => {
628
+ const absoluteDate = absoluteDatePeriod(input, "de");
629
+ if (Option.isSome(absoluteDate)) return absoluteDate;
630
+ const namedDate = parseNamedDate(input);
631
+ if (Option.isSome(namedDate)) return namedDate;
632
+ const quarter = parseQuarter(input);
633
+ if (Option.isSome(quarter)) return quarter;
634
+ const yearMatch = String$1.match(/^(?:(?:das )?(?:kalender)?jahr )?(\d{4})$/u)(input);
635
+ if (Option.isSome(yearMatch)) {
636
+ const year = validYear(textAt(yearMatch.value, 1));
637
+ if (year !== void 0) return Option.some(fixedYearPeriod(year, String(year)));
638
+ }
639
+ const monthYear = String$1.match(/^([a-zäöüß]+\.?) (\d{4})$/u)(input);
640
+ if (Option.isSome(monthYear)) {
641
+ const month = monthNumber(textAt(monthYear.value, 1));
642
+ const year = validYear(textAt(monthYear.value, 2));
643
+ if (month !== void 0 && year !== void 0) return Option.some(fixedMonthPeriod(year, month, `${title(textAt(months, month - 1))} ${year}`));
644
+ }
645
+ const relativeMonth = String$1.match(/^([a-zäöüß]+\.?) (letzten|dieses|nächsten) jahres$/u)(input);
646
+ if (Option.isSome(relativeMonth)) {
647
+ const directionText = textAt(relativeMonth.value, 2);
648
+ const month = monthNumber(textAt(relativeMonth.value, 1));
649
+ const direction = relativeDirection(directionText);
650
+ if (month !== void 0) return Option.some(monthOfRelativeYear(month, direction, `${title(textAt(months, month - 1))} ${directionText} Jahres`));
651
+ }
652
+ const standaloneMonth = monthNumber(input);
653
+ if (standaloneMonth !== void 0) return Option.some(monthOfRelativeYear(standaloneMonth, 0, title(textAt(months, standaloneMonth - 1))));
654
+ if (input === "wochenende" || input === "dieses wochenende" || input === "am wochenende") return Option.some(relativeWeekend(0, "dieses Wochenende"));
655
+ if (input === "letztes wochenende" || input === "vergangenes wochenende") return Option.some(relativeWeekend(-1, "letztes Wochenende"));
656
+ if (input === "nächstes wochenende" || input === "kommendes wochenende") return Option.some(relativeWeekend(1, "nächstes Wochenende"));
657
+ if (input === "vorletztes wochenende") return Option.some(relativeWeekend(-2, "vorletztes Wochenende"));
658
+ if (input === "übernächstes wochenende") return Option.some(relativeWeekend(2, "übernächstes Wochenende"));
659
+ const relative = unitPhrases.find((entry) => entry.current === input || entry.previous === input || entry.next === input);
660
+ if (relative !== void 0) {
661
+ let direction = 0;
662
+ if (input === relative.previous) direction = -1;
663
+ if (input === relative.next) direction = 1;
664
+ return Option.some(relativePeriod(relative.unit, direction, canonicalRelative(input)));
665
+ }
666
+ const alias = relativeAliases.find((entry) => entry[0] === input);
667
+ if (alias !== void 0) return Option.some(relativePeriod(alias[1], alias[2], canonicalRelative(alias[3])));
668
+ return Option.none();
669
+ };
670
+ const parsePeriod = (input) => {
671
+ const edge = String$1.match(/^(anfang|beginn|ende) (.+)$/u)(input);
672
+ if (Option.isSome(edge)) {
673
+ const edgeName = textAt(edge.value, 1);
674
+ const period = parseBasePeriod(textAt(edge.value, 2));
675
+ if (Option.isSome(period)) {
676
+ const canonical = `${edgeName === "ende" ? "Ende" : "Anfang"} ${withRelativeGenitive(period.value.canonical)}`;
677
+ return Option.some(edgeName === "ende" ? periodEndDay(period.value, canonical) : periodStartDay(period.value, canonical));
678
+ }
679
+ }
680
+ const wrapper = [
681
+ "im ",
682
+ "am ",
683
+ "für ",
684
+ "während "
685
+ ].find((prefix) => input.startsWith(prefix));
686
+ return parseBasePeriod(wrapper === void 0 ? input : input.slice(wrapper.length));
687
+ };
688
+ const currentBoundaryCandidate = (input) => {
689
+ const match = currentBoundaryPhrases.find((entry) => entry.phrase === input);
690
+ if (match === void 0) return Option.none();
691
+ const period = relativePeriod(match.entry.unit, 0, match.entry.current);
692
+ return Option.some(periodBoundaryCandidate(period, match.boundary, canonicalRelative(match.phrase)));
693
+ };
694
+ const boundaryCandidate = (input) => Option.map(openBoundaryCandidate(input, [
695
+ ["seit dem beginn von ", "since"],
696
+ ["seit dem anfang von ", "since"],
697
+ ["seit dem jahr ", "since"],
698
+ ["ab dem jahr ", "since"],
699
+ ["bis zum beginn von ", "before"],
700
+ ["bis zum anfang von ", "before"],
701
+ ["bis zum jahr ", "before"],
702
+ ["bis zum ende von ", "through"],
703
+ ["nach dem ende von ", "after"],
704
+ ["bis einschließlich ", "through"],
705
+ ["seit beginn ", "since"],
706
+ ["seit anfang ", "since"],
707
+ ["ab beginn ", "since"],
708
+ ["ab anfang ", "since"],
709
+ ["vor beginn ", "before"],
710
+ ["vor anfang ", "before"],
711
+ ["bis beginn ", "before"],
712
+ ["bis anfang ", "before"],
713
+ ["bis ende ", "through"],
714
+ ["nach ende ", "after"],
715
+ ["ab ende ", "after"],
716
+ ["seit ", "since"],
717
+ ["vor ", "before"],
718
+ ["nach ", "after"],
719
+ ["bis ", "before"],
720
+ ["ab ", "since"]
721
+ ], parsePeriod), (result) => candidate(result.range, canonicalRelative(input)));
722
+ const countedUnit = (value, amount, dative = false) => unitPhrases.find((entry) => {
723
+ if (amount === 1) return value === entry.noun;
724
+ return value === (dative ? entry.dative : entry.plural);
725
+ });
726
+ const parseCalendarOffset = (input) => {
727
+ const singular = String$1.match(/^(vor|in) (einem tag|einer woche|einem monat|einem quartal|einem jahr)$/u)(input);
728
+ if (Option.isSome(singular)) {
729
+ const entry = unitPhrases.find((unit) => unit.indefiniteDative === textAt(singular.value, 2));
730
+ if (entry !== void 0) {
731
+ const isPast = textAt(singular.value, 1) === "vor";
732
+ const direction = isPast ? -1 : 1;
733
+ const canonical = `${isPast ? "vor" : "in"} ${canonicalRelative(entry.indefiniteDative)}`;
734
+ return Option.some(candidate(periodRange(relativePeriod(entry.unit, direction, canonical)), canonical));
735
+ }
736
+ }
737
+ const prefixed = String$1.match(/^(vor|in) ([1-9]\d*) (tag|tagen|woche|wochen|monat|monaten|quartal|quartalen|jahr|jahren)$/u)(input);
738
+ const prior = String$1.match(/^([1-9]\d*) (tag|tage|woche|wochen|monat|monate|quartal|quartale|jahr|jahre) zuvor$/u)(input);
739
+ const match = Option.firstSomeOf([prefixed, prior]);
740
+ if (Option.isNone(match)) return Option.none();
741
+ const amountText = textAt(match.value, Option.isSome(prefixed) ? 2 : 1);
742
+ const unitText = textAt(match.value, Option.isSome(prefixed) ? 3 : 2);
743
+ const amount = parseTrailingCount(amountText);
744
+ if (Option.isNone(amount)) return Option.none();
745
+ const entry = countedUnit(unitText, amount.value, Option.isSome(prefixed));
746
+ if (entry === void 0) return Option.none();
747
+ const isPast = Option.isSome(prior) || Option.isSome(prefixed) && textAt(match.value, 1) === "vor";
748
+ const direction = isPast ? -amount.value : amount.value;
749
+ const directionName = isPast ? "vor" : "in";
750
+ const noun = amount.value === 1 ? entry.noun : entry.dative;
751
+ const canonical = `${directionName} ${amount.value} ${title(noun)}`;
752
+ return Option.some(candidate(periodRange(relativePeriod(entry.unit, direction, canonical)), canonical));
753
+ };
754
+ const parseRollingPeriod = (input) => {
755
+ const past = String$1.match(/^(?:(?:die letzten|letzten|letzte|vergangene|vorherige) )?([1-9]\d*) (tag|tage|woche|wochen|monat|monate|quartal|quartale|jahr|jahre)$/u)(input);
756
+ const pastDative = String$1.match(/^(?:(?:in den letzten|in den vergangenen|in den vorherigen) |seit )([1-9]\d*) (tag|tagen|woche|wochen|monat|monaten|quartal|quartalen|jahr|jahren)$/u)(input);
757
+ const singularSince = String$1.match(/^seit (einem tag|einer woche|einem monat|einem quartal|einem jahr)$/u)(input);
758
+ const pastGenitive = String$1.match(/^während der letzten ([1-9]\d*) (tag|tage|woche|wochen|monat|monate|quartal|quartale|jahr|jahre)$/u)(input);
759
+ const future = String$1.match(/^(?:die nächsten|nächsten|nächste|kommende) ([1-9]\d*) (tag|tage|woche|wochen|monat|monate|quartal|quartale|jahr|jahre)$/u)(input);
760
+ const futureDative = String$1.match(/^(?:in den nächsten|in den kommenden|innerhalb von) ([1-9]\d*) (tag|tagen|woche|wochen|monat|monaten|quartal|quartalen|jahr|jahren)$/u)(input);
761
+ const singularFuture = String$1.match(/^innerhalb (eines tages|einer woche|eines monats|eines quartals|eines jahres)$/u)(input);
762
+ const futureGenitive = String$1.match(/^innerhalb der nächsten ([1-9]\d*) (tag|tage|woche|wochen|monat|monate|quartal|quartale|jahr|jahre)$/u)(input);
763
+ const match = Option.firstSomeOf([
764
+ past,
765
+ pastDative,
766
+ singularSince,
767
+ pastGenitive,
768
+ future,
769
+ futureDative,
770
+ singularFuture,
771
+ futureGenitive
772
+ ]);
773
+ if (Option.isNone(match)) return Option.none();
774
+ const isSingular = Option.isSome(singularSince) || Option.isSome(singularFuture);
775
+ const amount = parseTrailingCount(isSingular ? "1" : textAt(match.value, 1));
776
+ if (Option.isNone(amount)) return Option.none();
777
+ const usesDative = Option.isSome(pastDative) || Option.isSome(singularSince) || Option.isSome(futureDative);
778
+ const sinceEntry = Option.isSome(singularSince) ? unitPhrases.find((unit) => unit.indefiniteDative === textAt(match.value, 1)) : void 0;
779
+ const futureEntry = Option.isSome(singularFuture) ? unitPhrases.find((unit) => unit.indefiniteGenitive === textAt(match.value, 1)) : void 0;
780
+ const countedEntry = isSingular ? void 0 : countedUnit(textAt(match.value, 2), amount.value, usesDative);
781
+ const entry = sinceEntry ?? futureEntry ?? countedEntry;
782
+ if (entry === void 0) return Option.none();
783
+ const isFuture = Option.isSome(future) || Option.isSome(futureDative) || Option.isSome(singularFuture) || Option.isSome(futureGenitive);
784
+ const range = isFuture ? futureRange(amount.value, entry.unit) : trailingRange(amount.value, entry.unit);
785
+ if (amount.value === 1) {
786
+ const phrase = isFuture ? `innerhalb ${canonicalRelative(entry.indefiniteGenitive)}` : `seit ${canonicalRelative(entry.indefiniteDative)}`;
787
+ return Option.some(candidate(range, phrase));
788
+ }
789
+ const direction = isFuture ? "nächste" : "letzte";
790
+ return Option.some(candidate(range, `${direction} ${amount.value} ${title(entry.plural)}`));
791
+ };
792
+ const parseElidedDateRange = (input) => {
793
+ const match = String$1.match(/^(?:vom )?([0-3]?\d)\.(?: bis |[–—-])(?:zum )?([0-3]?\d)\.? ([a-zäöüß]+\.?)(?: (\d{4}))?$/u)(input);
794
+ if (Option.isNone(match)) return Option.none();
795
+ const lowerDay = textAt(match.value, 1);
796
+ const upperDay = textAt(match.value, 2);
797
+ const month = textAt(match.value, 3);
798
+ const year = textAt(match.value, 4);
799
+ const suffix = year.length === 0 ? "" : ` ${year}`;
800
+ return joinedPeriodCandidate(`von ${lowerDay}. ${month}${suffix} bis ${upperDay}. ${month}${suffix}`, [["von ", " bis "]], parsePeriod, (lower, upper) => `von ${lower} bis ${upper}`);
801
+ };
802
+ const parseGerman = (input) => {
803
+ const remaining = remainingPeriodPhrases.find((entry) => entry.phrase === input);
804
+ if (remaining !== void 0) return Option.some(candidate(remainingPeriodRange(remaining.entry.unit), `Rest ${canonicalRelative(remaining.entry.genitive)}`));
805
+ if (["bis heute", "bis jetzt"].includes(input)) return Option.some(candidate(untilNowRange(), "bis heute"));
806
+ if (["ab jetzt", "von jetzt an"].includes(input)) return Option.some(candidate(fromNowRange(), "ab jetzt"));
807
+ const offset = parseCalendarOffset(input);
808
+ if (Option.isSome(offset)) return offset;
809
+ const rolling = parseRollingPeriod(input);
810
+ if (Option.isSome(rolling)) return rolling;
811
+ const toDate = toDatePhrases.find((entry) => entry.phrase === input);
812
+ if (toDate !== void 0) return Option.some(candidate(periodToDateRange(toDate.entry.unit), canonicalToDate(toDate.entry)));
813
+ const currentBoundary = currentBoundaryCandidate(input);
814
+ if (Option.isSome(currentBoundary)) return currentBoundary;
815
+ const elided = parseElidedDateRange(input);
816
+ if (Option.isSome(elided)) return elided;
817
+ const nowBounded = joinedNowCandidate(input, [
818
+ ["von ", " bis heute"],
819
+ ["vom ", " bis heute"],
820
+ ["zwischen ", " und heute"]
821
+ ], ["von heute bis ", "zwischen heute und "], parsePeriod, (period) => `von ${period} bis heute`, (period) => `von heute bis ${period}`);
822
+ if (Option.isSome(nowBounded)) return nowBounded;
823
+ const bounded = joinedPeriodCandidate(input, [
824
+ ["von ", " bis einschließlich "],
825
+ ["vom ", " bis einschließlich "],
826
+ ["von ", " bis zum "],
827
+ ["vom ", " bis zum "],
828
+ ["von ", " bis "],
829
+ ["vom ", " bis "],
830
+ ["zwischen ", " und "],
831
+ ["", " bis einschließlich "],
832
+ ["", " bis "],
833
+ ["", " - "],
834
+ ["", " – "],
835
+ ["", " — "],
836
+ ["zwischen ", "-"],
837
+ ["", "-"],
838
+ ["zwischen ", "–"],
839
+ ["", "–"],
840
+ ["zwischen ", "—"],
841
+ ["", "—"],
842
+ ["zwischen ", "~"],
843
+ ["", "~"]
844
+ ], parsePeriod, (lower, upper) => `von ${lower} bis ${upper}`);
845
+ if (Option.isSome(bounded)) return bounded;
846
+ const boundary = boundaryCandidate(input);
847
+ if (Option.isSome(boundary)) return boundary;
848
+ return parsePeriod(input).pipe(Option.map((period) => candidate(periodRange(period), period.canonical)));
849
+ };
850
+ const staticPeriodPhrases = [
851
+ "vorgestern",
852
+ "dieses wochenende",
853
+ "letztes wochenende",
854
+ "nächstes wochenende",
855
+ "vorletztes wochenende",
856
+ "übernächstes wochenende",
857
+ ...unitPhrases.flatMap((entry) => [
858
+ entry.current,
859
+ entry.previous,
860
+ entry.next,
861
+ `anfang ${entry.currentGenitive}`,
862
+ `ende ${entry.currentGenitive}`,
863
+ `anfang ${entry.previousGenitive}`,
864
+ `ende ${entry.previousGenitive}`,
865
+ `anfang ${entry.nextGenitive}`,
866
+ `ende ${entry.nextGenitive}`
867
+ ]),
868
+ ...[
869
+ 1,
870
+ 2,
871
+ 3,
872
+ 4
873
+ ].flatMap((quarter) => [
874
+ `q${quarter}`,
875
+ `q${quarter} letzten jahres`,
876
+ `q${quarter} nächsten jahres`
877
+ ]),
878
+ ...months.flatMap((month) => [
879
+ month,
880
+ `${month} letzten jahres`,
881
+ `${month} nächsten jahres`
882
+ ])
883
+ ];
884
+ const staticPeriods = periodsFromPhrases(staticPeriodPhrases, parsePeriod);
885
+ const boundaryPrefixes = [
886
+ "seit ",
887
+ "vor ",
888
+ "bis einschließlich ",
889
+ "nach "
890
+ ];
891
+ const countedSuggestions = (input) => {
892
+ const amount = naturalCount(input);
893
+ if (amount === void 0) return [];
894
+ return unitPhrases.flatMap((entry) => {
895
+ const noun = amount === 1 ? entry.noun : entry.plural;
896
+ const dative = amount === 1 ? entry.noun : entry.dative;
897
+ return [
898
+ ...amount === 1 ? [`${amount} ${noun}`] : [
899
+ `letzte ${amount} ${noun}`,
900
+ `${amount} ${noun}`,
901
+ `nächste ${amount} ${noun}`
902
+ ],
903
+ `vor ${amount} ${dative}`,
904
+ `in ${amount} ${dative}`
905
+ ];
906
+ });
907
+ };
908
+ const germanSuggestionPhrases = [
909
+ ...unitPhrases.map(canonicalToDate),
910
+ ...unitPhrases.map((entry) => `rest ${entry.genitive}`),
911
+ ...unitPhrases.flatMap((entry) => [
912
+ `seit ${entry.indefiniteDative}`,
913
+ `innerhalb ${entry.indefiniteGenitive}`,
914
+ `vor ${entry.indefiniteDative}`,
915
+ `in ${entry.indefiniteDative}`
916
+ ]),
917
+ ...staticPeriodPhrases,
918
+ ...currentBoundaryPhrases.map((entry) => entry.phrase),
919
+ ...declinedBoundaryPeriods.flatMap(([, , , dative, accusative]) => [
920
+ `seit ${dative}`,
921
+ `vor ${dative}`,
922
+ `bis einschließlich ${accusative}`,
923
+ `nach ${dative}`
924
+ ]),
925
+ ...prefixNaturalPhrases(months, boundaryPrefixes),
926
+ "bis heute",
927
+ "ab jetzt"
928
+ ].map((phrase) => normalizeNaturalText(phrase, "de"));
929
+ const suggestGerman = (input, limit) => {
930
+ const fixed = fixedCalendarPeriodPhrases(input, months);
931
+ return completeNaturalPhrases(input, [
932
+ ...germanSuggestionPhrases,
933
+ ...fixed,
934
+ ...prefixNaturalPhrases(fixed, boundaryPrefixes),
935
+ ...countedSuggestions(input)
936
+ ], limit);
937
+ };
938
+ const renderGerman = (range) => {
939
+ const offset = calendarPeriodOffset(range);
940
+ if (Option.isSome(offset) && Math.abs(offset.value.amount) > 1) {
941
+ const entry = unitPhrases.find((unit) => unit.unit === offset.value.unit);
942
+ if (entry !== void 0) return Option.some(`${offset.value.amount < 0 ? "vor" : "in"} ${Math.abs(offset.value.amount)} ${title(Math.abs(offset.value.amount) === 1 ? entry.noun : entry.dative)}`);
943
+ }
944
+ const future = futurePeriod(range);
945
+ if (Option.isSome(future)) {
946
+ const entry = unitPhrases.find((unit) => unit.unit === future.value.unit);
947
+ if (entry !== void 0) return Option.some(future.value.amount === 1 ? `innerhalb ${canonicalRelative(entry.indefiniteGenitive)}` : `nächste ${future.value.amount} ${title(entry.plural)}`);
948
+ }
949
+ const trailing = trailingPeriod(range);
950
+ if (Option.isSome(trailing)) {
951
+ const entry = unitPhrases.find((unit) => unit.unit === trailing.value.unit);
952
+ if (entry !== void 0) return Option.some(trailing.value.amount === 1 ? `seit ${canonicalRelative(entry.indefiniteDative)}` : `letzte ${trailing.value.amount} ${title(entry.plural)}`);
953
+ }
954
+ const dated = [...datedPeriods(range, months), ...datedQuarterPeriods(range)];
955
+ const periods = [
956
+ ...staticPeriods,
957
+ ...currentYearDatePeriods(range, currentDateLabel),
958
+ ...periodsFromPhrases([...dated, ...dated.flatMap((phrase) => [`anfang ${phrase}`, `ende ${phrase}`])], parsePeriod)
959
+ ];
960
+ return renderPeriodRange(range, [...unitPhrases.map((entry) => candidate(periodToDateRange(entry.unit), canonicalToDate(entry))), ...unitPhrases.map((entry) => candidate(remainingPeriodRange(entry.unit), `Rest ${canonicalRelative(entry.genitive)}`))], periods, (period) => `seit ${withRelativeCase(period, "dative")}`, (period) => `vor ${withRelativeCase(period, "dative")}`, (period) => `bis einschließlich ${withRelativeCase(period, "accusative")}`, (period) => `nach ${withRelativeCase(period, "dative")}`, (lower, upper) => `von ${lower} bis ${upper}`, (period) => `von ${period} bis heute`, (period) => `von heute bis ${period}`, () => "bis heute", () => "ab jetzt");
961
+ };
962
+ const GermanContribution = new BaseLanguageContribution({
963
+ locale: "de",
964
+ vocabulary: [
965
+ ...months,
966
+ ...quarterNames,
967
+ "q1",
968
+ "q2",
969
+ "q3",
970
+ "q4",
971
+ ...monthAbbreviations.flatMap((aliases) => aliases),
972
+ ...toDatePhrases.flatMap((entry) => entry.phrase.split(" ")),
973
+ ...remainingPeriodPhrases.flatMap((entry) => entry.phrase.split(" ")),
974
+ ...currentBoundaryPhrases.flatMap((entry) => entry.phrase.split(" ")),
975
+ ...relativeAliases.flatMap((entry) => entry[0].split(" ")),
976
+ ...unitPhrases.flatMap((entry) => [
977
+ entry.noun,
978
+ entry.plural,
979
+ entry.dative,
980
+ ...entry.indefiniteDative.split(" "),
981
+ ...entry.indefiniteGenitive.split(" "),
982
+ ...entry.currentGenitive.split(" "),
983
+ ...entry.previousGenitive.split(" "),
984
+ ...entry.nextGenitive.split(" "),
985
+ ...entry.current.split(" "),
986
+ ...entry.previous.split(" "),
987
+ ...entry.next.split(" ")
988
+ ]),
989
+ "ab",
990
+ "an",
991
+ "anfang",
992
+ "beginn",
993
+ "bisher",
994
+ "bis",
995
+ "dem",
996
+ "den",
997
+ "die",
998
+ "dieses",
999
+ "einschließlich",
1000
+ "ende",
1001
+ "für",
1002
+ "im",
1003
+ "innerhalb",
1004
+ "jetzt",
1005
+ "kalenderjahr",
1006
+ "jahres",
1007
+ "kommende",
1008
+ "kommenden",
1009
+ "letzte",
1010
+ "letzten",
1011
+ "nach",
1012
+ "nächste",
1013
+ "nächsten",
1014
+ "seit",
1015
+ "vor",
1016
+ "vorherige",
1017
+ "vorherigen",
1018
+ "vergangene",
1019
+ "vergangenen",
1020
+ "vom",
1021
+ "von",
1022
+ "während",
1023
+ "wochenende",
1024
+ "zwischen",
1025
+ "zuvor"
1026
+ ],
1027
+ normalize: normalizeNaturalText,
1028
+ correct: correctWhitespaceSeparatedText,
1029
+ parseExact: parseGerman,
1030
+ suggest: suggestGerman,
1031
+ render: renderGerman
1032
+ });
1033
+ const GermanLanguage = defineLanguagePlugin({
1034
+ id: "chronolizer/language-de",
1035
+ effect: (context) => Effect.asVoid(context.register("chronolizer/language-de", GermanContribution))
1036
+ });
1037
+ const GermanLanguageLayer = languagePluginsLayer([GermanLanguage]);
1038
+ //#endregion
1039
+ export { GermanContribution, GermanLanguage, GermanLanguageLayer };