chronolizer 0.3.0 → 0.4.1
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/README.md +50 -47
- package/dist/ast/fold.mjs +8 -10
- package/dist/ast/normalize.mjs +7 -16
- package/dist/filter/codec.mjs +5 -6
- package/dist/filter/expression.mjs +26 -21
- package/dist/language/model.mjs +1 -1
- package/dist/language/registry.mjs +34 -12
- package/dist/locales/cs.mjs +194 -36
- package/dist/locales/de.mjs +307 -490
- package/dist/locales/en.mjs +162 -46
- package/dist/locales/es.mjs +187 -37
- package/dist/locales/fr.mjs +168 -52
- package/dist/locales/nl.mjs +125 -37
- package/dist/locales/pl.mjs +163 -36
- package/dist/locales/shared.mjs +68 -5
- package/dist/locales/tr.mjs +144 -42
- package/dist/natural/correction.d.mts +1 -1
- package/dist/natural/correction.mjs +97 -28
- package/dist/natural/format.mjs +1 -1
- package/dist/natural/parse.mjs +6 -5
- package/dist/natural/suggest.mjs +27 -3
- package/dist/natural/suggestion.mjs +50 -26
- package/dist/resolve/resolve.mjs +2 -3
- package/package.json +2 -1
package/dist/locales/pl.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { isIsoDate } from "../ast/schemas.mjs";
|
|
2
1
|
import { BaseLanguageContribution } from "../language/model.mjs";
|
|
3
2
|
import { normalizeNaturalText } from "../natural/text.mjs";
|
|
4
3
|
import { defineLanguagePlugin, languagePluginsLayer } from "../language/registry.mjs";
|
|
5
4
|
import { correctWhitespaceSeparatedText } from "../natural/correction.mjs";
|
|
6
5
|
import { completeNaturalPhrases, fixedCalendarPeriodPhrases, naturalCount } from "../natural/suggestion.mjs";
|
|
7
|
-
import { absoluteDatePeriod, calendarPeriodOffset, candidate, currentYearDatePeriods, datedPeriods, datedQuarterPeriods,
|
|
6
|
+
import { absoluteDatePeriod, calendarPeriodOffset, candidate, compileCountAliasNormalizer, compoundCountAliases, countAliasVocabulary, currentYearDatePeriods, datedPeriods, datedQuarterPeriods, decimalTens, decomposeShiftedPeriodRange, fixedMonthPeriod, fixedQuarterPeriod, fixedYearPeriod, fromNowRange, futurePeriod, futureRange, joinedNowCandidate, joinedPeriodCandidate, monthOfRelativeYear, namedCurrentYearDatePeriod, namedDatePeriod, parseTrailingCount, periodBoundaryCandidate, periodEndDay, periodRange, periodStartDay, periodToDateRange, periodsFromPhrases, quarterOfRelativeYear, relativePeriod, relativeWeekday, relativeWeekend, remainingPeriodRange, renderPeriodRange, sequentialCountAliases, shiftPeriod, textAt, trailingPeriod, trailingRange, untilNowRange, validYear } from "./shared.mjs";
|
|
8
7
|
import { Effect, Option, String as String$1 } from "effect";
|
|
9
8
|
//#region src/locales/pl.ts
|
|
10
9
|
const months = [
|
|
@@ -21,6 +20,95 @@ const months = [
|
|
|
21
20
|
"listopad",
|
|
22
21
|
"grudzień"
|
|
23
22
|
];
|
|
23
|
+
const weekdays = [
|
|
24
|
+
"poniedziałek",
|
|
25
|
+
"wtorek",
|
|
26
|
+
"środa",
|
|
27
|
+
"czwartek",
|
|
28
|
+
"piątek",
|
|
29
|
+
"sobota",
|
|
30
|
+
"niedziela"
|
|
31
|
+
];
|
|
32
|
+
const weekdayGenitives = [
|
|
33
|
+
"poniedziałku",
|
|
34
|
+
"wtorku",
|
|
35
|
+
"środy",
|
|
36
|
+
"czwartku",
|
|
37
|
+
"piątku",
|
|
38
|
+
"soboty",
|
|
39
|
+
"niedzieli"
|
|
40
|
+
];
|
|
41
|
+
const nextWeekdays = weekdays.flatMap((weekday, day) => {
|
|
42
|
+
const feminine = day === 2 || day >= 5;
|
|
43
|
+
const canonical = `${feminine ? "następna" : "następny"} ${weekday}`;
|
|
44
|
+
return [{
|
|
45
|
+
phrase: canonical,
|
|
46
|
+
day,
|
|
47
|
+
canonical
|
|
48
|
+
}, {
|
|
49
|
+
phrase: `${feminine ? "następnej" : "następnego"} ${textAt(weekdayGenitives, day)}`,
|
|
50
|
+
day,
|
|
51
|
+
canonical
|
|
52
|
+
}];
|
|
53
|
+
});
|
|
54
|
+
const polishCountWords = [
|
|
55
|
+
[
|
|
56
|
+
"dwa",
|
|
57
|
+
"dwie",
|
|
58
|
+
"dwóch"
|
|
59
|
+
],
|
|
60
|
+
["trzy"],
|
|
61
|
+
["cztery"],
|
|
62
|
+
["pięć"],
|
|
63
|
+
["sześć"],
|
|
64
|
+
["siedem"],
|
|
65
|
+
["osiem"],
|
|
66
|
+
["dziewięć"],
|
|
67
|
+
["dziesięć"],
|
|
68
|
+
["jedenaście"],
|
|
69
|
+
["dwanaście"],
|
|
70
|
+
["trzynaście"],
|
|
71
|
+
["czternaście"],
|
|
72
|
+
["piętnaście"],
|
|
73
|
+
["szesnaście"],
|
|
74
|
+
["siedemnaście"],
|
|
75
|
+
["osiemnaście"],
|
|
76
|
+
["dziewiętnaście"],
|
|
77
|
+
["dwadzieścia"]
|
|
78
|
+
];
|
|
79
|
+
const polishCountOnes = [
|
|
80
|
+
[1, "jeden"],
|
|
81
|
+
[2, "dwa"],
|
|
82
|
+
[3, "trzy"],
|
|
83
|
+
[4, "cztery"],
|
|
84
|
+
[5, "pięć"],
|
|
85
|
+
[6, "sześć"],
|
|
86
|
+
[7, "siedem"],
|
|
87
|
+
[8, "osiem"],
|
|
88
|
+
[9, "dziewięć"]
|
|
89
|
+
];
|
|
90
|
+
const polishCountAliases = [
|
|
91
|
+
...sequentialCountAliases([[
|
|
92
|
+
"jeden",
|
|
93
|
+
"jedna",
|
|
94
|
+
"jedno"
|
|
95
|
+
]], 1),
|
|
96
|
+
...sequentialCountAliases(polishCountWords, 2),
|
|
97
|
+
...compoundCountAliases(decimalTens([
|
|
98
|
+
"dwadzieścia",
|
|
99
|
+
"trzydzieści",
|
|
100
|
+
"czterdzieści",
|
|
101
|
+
"pięćdziesiąt",
|
|
102
|
+
"sześćdziesiąt",
|
|
103
|
+
"siedemdziesiąt",
|
|
104
|
+
"osiemdziesiąt",
|
|
105
|
+
"dziewięćdziesiąt"
|
|
106
|
+
]), polishCountOnes, (ten, one) => [`${ten} ${one}`])
|
|
107
|
+
];
|
|
108
|
+
const normalizePolishCounts = compileCountAliasNormalizer(polishCountAliases);
|
|
109
|
+
const polishCountVocabulary = new Set(countAliasVocabulary(polishCountAliases));
|
|
110
|
+
const correctPolish = (input, vocabulary) => correctWhitespaceSeparatedText(input, vocabulary, polishCountVocabulary);
|
|
111
|
+
const normalizePolish = (input, locale) => normalizePolishCounts(normalizeNaturalText(input, locale));
|
|
24
112
|
const monthGenitives = [
|
|
25
113
|
"stycznia",
|
|
26
114
|
"lutego",
|
|
@@ -447,15 +535,7 @@ const parseNamedDate = (input) => {
|
|
|
447
535
|
const named = String$1.match(/^([0-3]?\d)\.?(?: )([a-ząćęłńóśźż]+\.?) (\d{4})$/u)(input);
|
|
448
536
|
if (Option.isSome(named)) return namedDatePeriod(textAt(named.value, 3), textAt(named.value, 2), textAt(named.value, 1), monthNumber, dateLabel);
|
|
449
537
|
const numeric = String$1.match(/^([0-3]?\d)(?:\. ?|[/-])([01]?\d)(?:\. ?|[/-])(\d{4})$/u)(input);
|
|
450
|
-
if (Option.isSome(numeric))
|
|
451
|
-
const year = validYear(textAt(numeric.value, 3));
|
|
452
|
-
const month = Number(textAt(numeric.value, 2));
|
|
453
|
-
const day = Number(textAt(numeric.value, 1));
|
|
454
|
-
if (year !== void 0 && month >= 1 && month <= 12) {
|
|
455
|
-
const value = isoDate(year, month, day);
|
|
456
|
-
if (isIsoDate(value) && value !== "9999-12-31") return Option.some(fixedDatePeriod(value, dateLabel(day, month, year)));
|
|
457
|
-
}
|
|
458
|
-
}
|
|
538
|
+
if (Option.isSome(numeric)) return namedDatePeriod(textAt(numeric.value, 3), textAt(numeric.value, 2), textAt(numeric.value, 1), Number, dateLabel);
|
|
459
539
|
const current = String$1.match(/^([0-3]?\d)\.? ([a-ząćęłńóśźż]+\.?)$/u)(input);
|
|
460
540
|
return Option.isSome(current) ? namedCurrentYearDatePeriod(textAt(current.value, 2), textAt(current.value, 1), monthNumber, currentDateLabel) : Option.none();
|
|
461
541
|
};
|
|
@@ -484,13 +564,13 @@ const parseQuarter = (input) => {
|
|
|
484
564
|
const quarter = quarterNumber(textAt(standalone.value, 1));
|
|
485
565
|
return quarter === void 0 ? Option.none() : Option.some(quarterOfRelativeYear(quarter, 0, `Q${quarter}`));
|
|
486
566
|
};
|
|
487
|
-
const
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
if (Option.isSome(
|
|
567
|
+
const parseDatedPeriod = (input) => {
|
|
568
|
+
const knownPeriod = Option.firstSomeOf([
|
|
569
|
+
absoluteDatePeriod(input, "pl"),
|
|
570
|
+
parseNamedDate(input),
|
|
571
|
+
parseQuarter(input)
|
|
572
|
+
]);
|
|
573
|
+
if (Option.isSome(knownPeriod)) return knownPeriod;
|
|
494
574
|
const yearMatch = String$1.match(/^(?:rok |roku )?(\d{4})$/u)(input);
|
|
495
575
|
if (Option.isSome(yearMatch)) {
|
|
496
576
|
const year = validYear(textAt(yearMatch.value, 1));
|
|
@@ -502,6 +582,20 @@ const parseBasePeriod = (input) => {
|
|
|
502
582
|
const year = validYear(textAt(monthYear.value, 2));
|
|
503
583
|
if (month !== void 0 && year !== void 0) return Option.some(fixedMonthPeriod(year, month, `${title(textAt(months, month - 1))} ${year}`));
|
|
504
584
|
}
|
|
585
|
+
return Option.none();
|
|
586
|
+
};
|
|
587
|
+
const parseBasePeriod = (input) => {
|
|
588
|
+
const datedPeriod = parseDatedPeriod(input);
|
|
589
|
+
if (Option.isSome(datedPeriod)) return datedPeriod;
|
|
590
|
+
const prefixedRelativeMonth = String$1.match(/^(poprzedni|ten|następny) ([a-ząćęłńóśźż]+\.?)$/u)(input);
|
|
591
|
+
if (Option.isSome(prefixedRelativeMonth)) {
|
|
592
|
+
const month = monthNumber(textAt(prefixedRelativeMonth.value, 2));
|
|
593
|
+
if (month !== void 0) {
|
|
594
|
+
const modifier = textAt(prefixedRelativeMonth.value, 1);
|
|
595
|
+
const direction = relativeYearDirection(modifier);
|
|
596
|
+
return Option.some(monthOfRelativeYear(month, direction, `${modifier} ${textAt(months, month - 1)}`));
|
|
597
|
+
}
|
|
598
|
+
}
|
|
505
599
|
const relativeMonth = String$1.match(/^([a-ząćęłńóśźż]+\.?) (poprzedniego roku|następnego roku|tego roku)$/u)(input);
|
|
506
600
|
const relativeMonthYearFirst = String$1.match(/^(poprzedniego roku|następnego roku|tego roku) ([a-ząćęłńóśźż]+\.?)$/u)(input);
|
|
507
601
|
const relativeMatch = Option.firstSomeOf([relativeMonth, relativeMonthYearFirst]);
|
|
@@ -522,12 +616,31 @@ const parseBasePeriod = (input) => {
|
|
|
522
616
|
if (["następny weekend", "przyszły weekend"].includes(input)) return Option.some(relativeWeekend(1, "następny weekend"));
|
|
523
617
|
if (input === "weekend przed poprzednim") return Option.some(relativeWeekend(-2, input));
|
|
524
618
|
if (input === "weekend po następnym") return Option.some(relativeWeekend(2, input));
|
|
525
|
-
|
|
619
|
+
const weekday = nextWeekdays.find((entry) => entry.phrase === input);
|
|
620
|
+
return weekday === void 0 ? Option.none() : Option.some(relativeWeekday(weekday.day, 1, weekday.canonical));
|
|
526
621
|
};
|
|
527
622
|
const parsePeriod = (input) => {
|
|
623
|
+
const shifted = String$1.match(/^(.+) (?:([1-9]\d*) (dzień|dni|tydzień|tygodnie|tygodni|miesiąc|miesiące|miesięcy|kwartał|kwartały|kwartałów|rok|lata|lat) (temu)|za ([1-9]\d*) (dzień|dni|tydzień|tygodnie|tygodni|miesiąc|miesiące|miesięcy|kwartał|kwartały|kwartałów|rok|lata|lat))$/u)(input);
|
|
624
|
+
if (Option.isSome(shifted)) {
|
|
625
|
+
const past = textAt(shifted.value, 4) === "temu";
|
|
626
|
+
const amount = parseTrailingCount(textAt(shifted.value, past ? 2 : 5));
|
|
627
|
+
const alias = unitAliases.find((unit) => unit[0] === textAt(shifted.value, past ? 3 : 6));
|
|
628
|
+
const entry = alias === void 0 ? void 0 : units.find((unit) => unit.unit === alias[1]);
|
|
629
|
+
const period = parsePeriod(textAt(shifted.value, 1));
|
|
630
|
+
if (Option.isSome(amount) && entry !== void 0 && Option.isSome(period)) {
|
|
631
|
+
const direction = past ? -amount.value : amount.value;
|
|
632
|
+
const noun = countNoun(amount.value, entry);
|
|
633
|
+
const canonical = past ? `${period.value.canonical} ${amount.value} ${noun} temu` : `${period.value.canonical} za ${amount.value} ${noun}`;
|
|
634
|
+
return Option.some(shiftPeriod(period.value, direction, entry.unit, canonical));
|
|
635
|
+
}
|
|
636
|
+
}
|
|
528
637
|
const edge = String$1.match(/^(początek|koniec) (.+)$/u)(input);
|
|
529
638
|
if (Option.isSome(edge)) {
|
|
530
|
-
const
|
|
639
|
+
const periodText = textAt(edge.value, 2);
|
|
640
|
+
const basePeriod = parseBasePeriod(periodText);
|
|
641
|
+
const implicitUnit = declinedUnits.find((entry) => entry[2] === periodText)?.[0];
|
|
642
|
+
const implicit = units.find((entry) => entry.unit === implicitUnit);
|
|
643
|
+
const period = Option.isSome(basePeriod) || implicit === void 0 ? basePeriod : Option.some(relativePeriod(implicit.unit, 0, implicit.current));
|
|
531
644
|
if (Option.isSome(period)) {
|
|
532
645
|
const isEnd = textAt(edge.value, 1) === "koniec";
|
|
533
646
|
const canonical = `${isEnd ? "koniec" : "początek"} ${withPeriodCase(period.value.canonical, "genitive")}`;
|
|
@@ -541,16 +654,15 @@ const parsePeriod = (input) => {
|
|
|
541
654
|
"cały ",
|
|
542
655
|
"całe "
|
|
543
656
|
].find((prefix) => input.startsWith(prefix));
|
|
544
|
-
|
|
657
|
+
const base = parseBasePeriod(wrapper === void 0 ? input : input.slice(wrapper.length));
|
|
658
|
+
return Option.isSome(base) ? base : parseCalendarOffset(input);
|
|
545
659
|
};
|
|
546
660
|
const countedUnit = (value) => unitAliases.find((entry) => entry[0] === value)?.[1];
|
|
547
|
-
const
|
|
548
|
-
const
|
|
549
|
-
const
|
|
550
|
-
const
|
|
551
|
-
const
|
|
552
|
-
const rollingFuturePatterns = [countedPattern("^(?:następny|następne|następnych|kolejny|kolejne|kolejnych) ([1-9]\\d*) (UNIT)$"), countedPattern("^w ciągu (?:najbliższego|najbliższych) ([1-9]\\d*) (UNIT)$")];
|
|
553
|
-
const rollingBarePattern = countedPattern("^([1-9]\\d*) (UNIT)$");
|
|
661
|
+
const calendarPastPattern = /^(?:dokładnie )?(?:([1-9]\d*) )?([^ ]+) temu$/u;
|
|
662
|
+
const calendarFuturePattern = /^za (?:([1-9]\d*) )?([^ ]+)$/u;
|
|
663
|
+
const rollingPastPatterns = [/^(?:ostatni|ostatnie|ostatnich|miniony|minione|minionych) ([1-9]\d*) ([^ ]+)$/u, /^w ciągu (?:ostatniego|ostatnich|minionego|minionych) ([1-9]\d*) ([^ ]+)$/u];
|
|
664
|
+
const rollingFuturePatterns = [/^(?:następny|następne|następnych|kolejny|kolejne|kolejnych) ([1-9]\d*) ([^ ]+)$/u, /^w ciągu (?:najbliższego|najbliższych) ([1-9]\d*) ([^ ]+)$/u];
|
|
665
|
+
const rollingBarePattern = /^([1-9]\d*) ([^ ]+)$/u;
|
|
554
666
|
const firstPatternMatch = (input, patterns) => Option.firstSomeOf(patterns.map((pattern) => String$1.match(pattern)(input)));
|
|
555
667
|
const countNoun = (amount, entry) => {
|
|
556
668
|
if (amount === 1) return entry.singular;
|
|
@@ -573,7 +685,7 @@ const parseCalendarOffset = (input) => {
|
|
|
573
685
|
const direction = Option.isSome(past) ? -amount.value : amount.value;
|
|
574
686
|
const noun = countNoun(amount.value, entry);
|
|
575
687
|
const canonical = direction < 0 ? `${amount.value} ${noun} temu` : `za ${amount.value} ${noun}`;
|
|
576
|
-
return Option.some(
|
|
688
|
+
return Option.some(relativePeriod(unit, direction, canonical));
|
|
577
689
|
};
|
|
578
690
|
const rollingModifier = (amount, future) => {
|
|
579
691
|
if (amount === 1) return future ? "następny" : "ostatni";
|
|
@@ -635,6 +747,7 @@ const boundaries = [
|
|
|
635
747
|
]
|
|
636
748
|
];
|
|
637
749
|
const boundaryCandidate = (input) => {
|
|
750
|
+
if (input.startsWith("do koniec ")) return Option.none();
|
|
638
751
|
const included = String$1.match(/^do (.+) włącznie$/u)(input);
|
|
639
752
|
if (Option.isSome(included)) return parsePeriod(textAt(included.value, 1)).pipe(Option.map((value) => periodBoundaryCandidate(value, "through", `do ${withPeriodCase(value.canonical, "genitive")} włącznie`)));
|
|
640
753
|
for (const [prefix, boundary, canonical] of boundaries) {
|
|
@@ -653,8 +766,6 @@ const parsePolish = (input) => {
|
|
|
653
766
|
"do teraz"
|
|
654
767
|
].includes(input)) return Option.some(candidate(untilNowRange(), "do dziś"));
|
|
655
768
|
if (["od teraz", "od dziś"].includes(input)) return Option.some(candidate(fromNowRange(), "od teraz"));
|
|
656
|
-
const offset = parseCalendarOffset(input);
|
|
657
|
-
if (Option.isSome(offset)) return offset;
|
|
658
769
|
const rolling = parseRollingPeriod(input);
|
|
659
770
|
if (Option.isSome(rolling)) return rolling;
|
|
660
771
|
const toDate = toDatePhrases.find((entry) => entry.phrase === input);
|
|
@@ -677,10 +788,11 @@ const parsePolish = (input) => {
|
|
|
677
788
|
], [
|
|
678
789
|
"od dziś do ",
|
|
679
790
|
"między dziś a ",
|
|
680
|
-
"pomiędzy dziś a "
|
|
791
|
+
"pomiędzy dziś a ",
|
|
792
|
+
"teraz do "
|
|
681
793
|
], parsePeriod, (period) => `od ${period} do dziś`, (period) => `od dziś do ${period}`);
|
|
682
794
|
if (Option.isSome(nowBounded)) return nowBounded;
|
|
683
|
-
const bounded = joinedPeriodCandidate(input, [
|
|
795
|
+
const bounded = joinedPeriodCandidate(input.replace(/ włącznie$/u, ""), [
|
|
684
796
|
["od ", " do "],
|
|
685
797
|
["między ", " a "],
|
|
686
798
|
["pomiędzy ", " a "],
|
|
@@ -731,9 +843,12 @@ const staticPeriodPhrases = [
|
|
|
731
843
|
]),
|
|
732
844
|
...months.flatMap((month) => [
|
|
733
845
|
month,
|
|
846
|
+
`poprzedni ${month}`,
|
|
847
|
+
`następny ${month}`,
|
|
734
848
|
`${month} poprzedniego roku`,
|
|
735
849
|
`${month} następnego roku`
|
|
736
|
-
])
|
|
850
|
+
]),
|
|
851
|
+
...nextWeekdays.map((entry) => entry.phrase)
|
|
737
852
|
];
|
|
738
853
|
const staticPeriods = periodsFromPhrases(staticPeriodPhrases, parsePeriod);
|
|
739
854
|
const monthBoundaryPhrases = months.flatMap((_, index) => {
|
|
@@ -800,6 +915,16 @@ const suggestPolish = (input, limit) => {
|
|
|
800
915
|
], limit);
|
|
801
916
|
};
|
|
802
917
|
const renderPolish = (range) => {
|
|
918
|
+
const shifted = decomposeShiftedPeriodRange(range);
|
|
919
|
+
if (Option.isSome(shifted)) {
|
|
920
|
+
const base = renderPolish(shifted.value.baseRange);
|
|
921
|
+
const entry = units.find((unit) => unit.unit === shifted.value.unit);
|
|
922
|
+
if (Option.isSome(base) && entry !== void 0) {
|
|
923
|
+
const amount = Math.abs(shifted.value.amount);
|
|
924
|
+
const noun = countNoun(amount, entry);
|
|
925
|
+
return Option.some(shifted.value.amount < 0 ? `${base.value} ${amount} ${noun} temu` : `${base.value} za ${amount} ${noun}`);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
803
928
|
const offset = calendarPeriodOffset(range);
|
|
804
929
|
if (Option.isSome(offset) && Math.abs(offset.value.amount) > 1) {
|
|
805
930
|
const entry = units.find((unit) => unit.unit === offset.value.unit);
|
|
@@ -830,6 +955,8 @@ const PolishContribution = new BaseLanguageContribution({
|
|
|
830
955
|
locale: "pl",
|
|
831
956
|
vocabulary: [
|
|
832
957
|
...months,
|
|
958
|
+
...weekdays,
|
|
959
|
+
...weekdayGenitives,
|
|
833
960
|
...monthGenitives,
|
|
834
961
|
...monthInstrumentals,
|
|
835
962
|
...monthLocatives,
|
|
@@ -870,8 +997,8 @@ const PolishContribution = new BaseLanguageContribution({
|
|
|
870
997
|
"we",
|
|
871
998
|
"za"
|
|
872
999
|
],
|
|
873
|
-
normalize:
|
|
874
|
-
correct:
|
|
1000
|
+
normalize: normalizePolish,
|
|
1001
|
+
correct: correctPolish,
|
|
875
1002
|
parseExact: parsePolish,
|
|
876
1003
|
suggest: suggestPolish,
|
|
877
1004
|
render: renderPolish
|
package/dist/locales/shared.mjs
CHANGED
|
@@ -6,6 +6,43 @@ import { NaturalCandidate } from "../language/model.mjs";
|
|
|
6
6
|
import { Match, Option, RegExp as RegExp$1, Schema, String as String$1 } from "effect";
|
|
7
7
|
//#region src/locales/shared.ts
|
|
8
8
|
const textAt = (values, index) => values[index] ?? "";
|
|
9
|
+
const sequentialCountAliases = (words, start) => words.flatMap((aliases, index) => aliases.map((phrase) => [phrase, start + index]));
|
|
10
|
+
const decimalTens = (words) => words.map((word, index) => [20 + index * 10, word]);
|
|
11
|
+
const compoundCountAliases = (tens, ones, join) => tens.flatMap(([tensAmount, tensWord]) => [[tensWord, tensAmount], ...ones.flatMap(([oneAmount, oneWord]) => {
|
|
12
|
+
const amount = tensAmount + oneAmount;
|
|
13
|
+
return join(tensWord, oneWord, amount).map((phrase) => [phrase, amount]);
|
|
14
|
+
})]);
|
|
15
|
+
const countAliasVocabulary = (aliases) => [...new Set(aliases.flatMap(([phrase]) => phrase.split(" ")))];
|
|
16
|
+
const compileCountAliasNormalizer = (aliases) => {
|
|
17
|
+
const distinct = /* @__PURE__ */ new Map();
|
|
18
|
+
for (const [phrase, amount] of aliases) if (!distinct.has(phrase)) distinct.set(phrase, amount);
|
|
19
|
+
const byFirstWord = /* @__PURE__ */ new Map();
|
|
20
|
+
for (const [phrase, amount] of distinct) {
|
|
21
|
+
const parts = phrase.split(" ");
|
|
22
|
+
const first = parts[0] ?? "";
|
|
23
|
+
const entries = byFirstWord.get(first) ?? [];
|
|
24
|
+
byFirstWord.set(first, [...entries, {
|
|
25
|
+
amount,
|
|
26
|
+
parts
|
|
27
|
+
}]);
|
|
28
|
+
}
|
|
29
|
+
for (const [first, entries] of byFirstWord) byFirstWord.set(first, [...entries].sort((left, right) => right.parts.length - left.parts.length));
|
|
30
|
+
return (input) => {
|
|
31
|
+
const words = input.split(" ");
|
|
32
|
+
const output = [];
|
|
33
|
+
for (let index = 0; index < words.length;) {
|
|
34
|
+
const alias = (byFirstWord.get(words[index] ?? "") ?? []).find((entry) => entry.parts.every((part, offset) => words[index + offset] === part));
|
|
35
|
+
if (alias === void 0) {
|
|
36
|
+
output.push(words[index] ?? "");
|
|
37
|
+
index += 1;
|
|
38
|
+
} else {
|
|
39
|
+
output.push(String(alias.amount));
|
|
40
|
+
index += alias.parts.length;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return output.join(" ");
|
|
44
|
+
};
|
|
45
|
+
};
|
|
9
46
|
const Period = Schema.Struct({
|
|
10
47
|
start: InstantExpr,
|
|
11
48
|
end: InstantExpr,
|
|
@@ -18,6 +55,22 @@ const isNow = Schema.is(Now);
|
|
|
18
55
|
const isShift = Schema.is(Shift);
|
|
19
56
|
const isStartOf = Schema.is(StartOf);
|
|
20
57
|
const periodRange = (period) => boundedRange(greaterThanOrEqual(period.start), lessThan(period.end));
|
|
58
|
+
const shiftPeriod = (period, amount, unit, canonical) => Period.make({
|
|
59
|
+
start: shift(period.start, amount, unit),
|
|
60
|
+
end: shift(period.end, amount, unit),
|
|
61
|
+
canonical
|
|
62
|
+
});
|
|
63
|
+
const decomposeShiftedPeriodRange = (range) => {
|
|
64
|
+
if (!isGreaterThanOrEqual(range.lower) || !isLessThan(range.upper)) return Option.none();
|
|
65
|
+
const start = range.lower.value;
|
|
66
|
+
const end = range.upper.value;
|
|
67
|
+
if (!isShift(start) || !isShift(end) || start.amount === 0 || start.amount !== end.amount || start.unit !== end.unit) return Option.none();
|
|
68
|
+
return Option.some({
|
|
69
|
+
amount: start.amount,
|
|
70
|
+
unit: start.unit,
|
|
71
|
+
baseRange: boundedRange(greaterThanOrEqual(start.base), lessThan(end.base))
|
|
72
|
+
});
|
|
73
|
+
};
|
|
21
74
|
const periodToDateRange = (unit) => boundedRange(greaterThanOrEqual(startOf(now(), unit)), lessThanOrEqual(now()));
|
|
22
75
|
const fromNowRange = () => lowerOpenRange(greaterThanOrEqual(now()));
|
|
23
76
|
const untilNowRange = () => upperOpenRange(lessThanOrEqual(now()));
|
|
@@ -40,7 +93,7 @@ const periodDay = (period, day, canonical) => {
|
|
|
40
93
|
const start = day === 1 ? period.start : shift(period.start, day - 1, "day");
|
|
41
94
|
return Option.some(Period.make({
|
|
42
95
|
start,
|
|
43
|
-
end: shift(start,
|
|
96
|
+
end: shift(period.start, day, "day"),
|
|
44
97
|
canonical
|
|
45
98
|
}));
|
|
46
99
|
};
|
|
@@ -49,13 +102,23 @@ const periodPreviousDay = (period, canonical) => Period.make({
|
|
|
49
102
|
end: period.start,
|
|
50
103
|
canonical
|
|
51
104
|
});
|
|
105
|
+
const relativeWeekday = (day, direction, canonical) => {
|
|
106
|
+
const weekBase = direction === 0 ? now() : shift(now(), direction, "week");
|
|
107
|
+
const weekStart = startOf(weekBase, "week");
|
|
108
|
+
const start = day === 0 ? weekStart : shift(weekStart, day, "day");
|
|
109
|
+
return Period.make({
|
|
110
|
+
start,
|
|
111
|
+
end: shift(weekStart, day + 1, "day"),
|
|
112
|
+
canonical
|
|
113
|
+
});
|
|
114
|
+
};
|
|
52
115
|
const relativeWeekend = (direction, canonical) => {
|
|
53
116
|
const weekBase = direction === 0 ? now() : shift(now(), direction, "week");
|
|
54
117
|
const weekStart = startOf(weekBase, "week");
|
|
55
118
|
const start = shift(weekStart, 5, "day");
|
|
56
119
|
return Period.make({
|
|
57
120
|
start,
|
|
58
|
-
end: shift(
|
|
121
|
+
end: shift(weekStart, 7, "day"),
|
|
59
122
|
canonical
|
|
60
123
|
});
|
|
61
124
|
};
|
|
@@ -191,7 +254,7 @@ const currentYearDatePeriod = (month, day, canonical) => {
|
|
|
191
254
|
const start = day === 1 ? monthStart : shift(monthStart, day - 1, "day");
|
|
192
255
|
return Period.make({
|
|
193
256
|
start,
|
|
194
|
-
end: shift(
|
|
257
|
+
end: shift(monthStart, day, "day"),
|
|
195
258
|
canonical
|
|
196
259
|
});
|
|
197
260
|
};
|
|
@@ -269,7 +332,7 @@ const monthOfRelativeYear = (month, direction, canonical) => {
|
|
|
269
332
|
const start = month === 1 ? yearStart : shift(yearStart, month - 1, "month");
|
|
270
333
|
return Period.make({
|
|
271
334
|
start,
|
|
272
|
-
end: shift(
|
|
335
|
+
end: shift(yearStart, month, "month"),
|
|
273
336
|
canonical
|
|
274
337
|
});
|
|
275
338
|
};
|
|
@@ -392,4 +455,4 @@ const renderPeriodRange = (range, toDate, periods, since, before, through, after
|
|
|
392
455
|
return Option.none();
|
|
393
456
|
};
|
|
394
457
|
//#endregion
|
|
395
|
-
export { Period, absoluteDatePeriod, calendarPeriodOffset, candidate, currentYearDatePeriods, datedPeriods, datedQuarterPeriods, fixedDatePeriod, fixedMonthPeriod, fixedQuarterPeriod, fixedYearPeriod, formatAbsoluteDate, fromNowRange, futurePeriod, futureRange, isoDate, joinedNowCandidate, joinedPeriodCandidate, monthOfRelativeYear, namedCurrentYearDatePeriod, namedDatePeriod, openBoundaryCandidate, parseTrailingCount, periodBoundaryCandidate, periodDay, periodEndDay, periodPreviousDay, periodRange, periodStartDay, periodToDateRange, periodsFromPhrases, quarterOfRelativeYear, relativePeriod, relativeWeekend, remainingPeriodRange, renderPeriodRange, textAt, trailingPeriod, trailingRange, untilNowRange, validYear };
|
|
458
|
+
export { Period, absoluteDatePeriod, calendarPeriodOffset, candidate, compileCountAliasNormalizer, compoundCountAliases, countAliasVocabulary, currentYearDatePeriods, datedPeriods, datedQuarterPeriods, decimalTens, decomposeShiftedPeriodRange, fixedDatePeriod, fixedMonthPeriod, fixedQuarterPeriod, fixedYearPeriod, formatAbsoluteDate, fromNowRange, futurePeriod, futureRange, isoDate, joinedNowCandidate, joinedPeriodCandidate, monthOfRelativeYear, namedCurrentYearDatePeriod, namedDatePeriod, openBoundaryCandidate, parseTrailingCount, periodBoundaryCandidate, periodDay, periodEndDay, periodPreviousDay, periodRange, periodStartDay, periodToDateRange, periodsFromPhrases, quarterOfRelativeYear, relativePeriod, relativeWeekday, relativeWeekend, remainingPeriodRange, renderPeriodRange, sequentialCountAliases, shiftPeriod, textAt, trailingPeriod, trailingRange, untilNowRange, validYear };
|