1"""Provides internationalization for arrow in over 60 languages and dialects."""
2
3import sys
4from math import trunc
5from typing import (
6    Any,
7    ClassVar,
8    Dict,
9    List,
10    Mapping,
11    Optional,
12    Sequence,
13    Tuple,
14    Type,
15    Union,
16    cast,
17)
18
19if sys.version_info < (3, 8):  # pragma: no cover
20    from typing_extensions import Literal
21else:
22    from typing import Literal  # pragma: no cover
23
24TimeFrameLiteral = Literal[
25    "now",
26    "second",
27    "seconds",
28    "minute",
29    "minutes",
30    "hour",
31    "hours",
32    "day",
33    "days",
34    "week",
35    "weeks",
36    "month",
37    "months",
38    "quarter",
39    "quarters",
40    "year",
41    "years",
42]
43
44_TimeFrameElements = Union[
45    str, Sequence[str], Mapping[str, str], Mapping[str, Sequence[str]]
46]
47
48
49_locale_map: Dict[str, Type["Locale"]] = dict()
50
51
52def get_locale(name: str) -> "Locale":
53    """Returns an appropriate :class:`Locale <arrow.locales.Locale>`
54    corresponding to an input locale name.
55
56    :param name: the name of the locale.
57
58    """
59
60    normalized_locale_name = name.lower().replace("_", "-")
61    locale_cls = _locale_map.get(normalized_locale_name)
62
63    if locale_cls is None:
64        raise ValueError(f"Unsupported locale {normalized_locale_name!r}.")
65
66    return locale_cls()
67
68
69def get_locale_by_class_name(name: str) -> "Locale":
70    """Returns an appropriate :class:`Locale <arrow.locales.Locale>`
71    corresponding to an locale class name.
72
73    :param name: the name of the locale class.
74
75    """
76    locale_cls: Optional[Type[Locale]] = globals().get(name)
77
78    if locale_cls is None:
79        raise ValueError(f"Unsupported locale {name!r}.")
80
81    return locale_cls()
82
83
84class Locale:
85    """Represents locale-specific data and functionality."""
86
87    names: ClassVar[List[str]] = []
88
89    timeframes: ClassVar[Mapping[TimeFrameLiteral, _TimeFrameElements]] = {
90        "now": "",
91        "second": "",
92        "seconds": "",
93        "minute": "",
94        "minutes": "",
95        "hour": "",
96        "hours": "",
97        "day": "",
98        "days": "",
99        "week": "",
100        "weeks": "",
101        "month": "",
102        "months": "",
103        "quarter": "",
104        "quarters": "",
105        "year": "",
106        "years": "",
107    }
108
109    meridians: ClassVar[Dict[str, str]] = {"am": "", "pm": "", "AM": "", "PM": ""}
110
111    past: ClassVar[str]
112    future: ClassVar[str]
113    and_word: ClassVar[Optional[str]] = None
114
115    month_names: ClassVar[List[str]] = []
116    month_abbreviations: ClassVar[List[str]] = []
117
118    day_names: ClassVar[List[str]] = []
119    day_abbreviations: ClassVar[List[str]] = []
120
121    ordinal_day_re: ClassVar[str] = r"(\d+)"
122
123    _month_name_to_ordinal: Optional[Dict[str, int]]
124
125    def __init_subclass__(cls, **kwargs: Any) -> None:
126        for locale_name in cls.names:
127            if locale_name in _locale_map:
128                raise LookupError(f"Duplicated locale name: {locale_name}")
129
130            _locale_map[locale_name.lower().replace("_", "-")] = cls
131
132    def __init__(self) -> None:
133
134        self._month_name_to_ordinal = None
135
136    def describe(
137        self,
138        timeframe: TimeFrameLiteral,
139        delta: Union[float, int] = 0,
140        only_distance: bool = False,
141    ) -> str:
142        """Describes a delta within a timeframe in plain language.
143
144        :param timeframe: a string representing a timeframe.
145        :param delta: a quantity representing a delta in a timeframe.
146        :param only_distance: return only distance eg: "11 seconds" without "in" or "ago" keywords
147        """
148
149        humanized = self._format_timeframe(timeframe, trunc(delta))
150        if not only_distance:
151            humanized = self._format_relative(humanized, timeframe, delta)
152
153        return humanized
154
155    def describe_multi(
156        self,
157        timeframes: Sequence[Tuple[TimeFrameLiteral, Union[int, float]]],
158        only_distance: bool = False,
159    ) -> str:
160        """Describes a delta within multiple timeframes in plain language.
161
162        :param timeframes: a list of string, quantity pairs each representing a timeframe and delta.
163        :param only_distance: return only distance eg: "2 hours and 11 seconds" without "in" or "ago" keywords
164        """
165
166        parts = [
167            self._format_timeframe(timeframe, trunc(delta))
168            for timeframe, delta in timeframes
169        ]
170        if self.and_word:
171            parts.insert(-1, self.and_word)
172        humanized = " ".join(parts)
173
174        if not only_distance:
175            humanized = self._format_relative(humanized, *timeframes[-1])
176
177        return humanized
178
179    def day_name(self, day: int) -> str:
180        """Returns the day name for a specified day of the week.
181
182        :param day: the ``int`` day of the week (1-7).
183
184        """
185
186        return self.day_names[day]
187
188    def day_abbreviation(self, day: int) -> str:
189        """Returns the day abbreviation for a specified day of the week.
190
191        :param day: the ``int`` day of the week (1-7).
192
193        """
194
195        return self.day_abbreviations[day]
196
197    def month_name(self, month: int) -> str:
198        """Returns the month name for a specified month of the year.
199
200        :param month: the ``int`` month of the year (1-12).
201
202        """
203
204        return self.month_names[month]
205
206    def month_abbreviation(self, month: int) -> str:
207        """Returns the month abbreviation for a specified month of the year.
208
209        :param month: the ``int`` month of the year (1-12).
210
211        """
212
213        return self.month_abbreviations[month]
214
215    def month_number(self, name: str) -> Optional[int]:
216        """Returns the month number for a month specified by name or abbreviation.
217
218        :param name: the month name or abbreviation.
219
220        """
221
222        if self._month_name_to_ordinal is None:
223            self._month_name_to_ordinal = self._name_to_ordinal(self.month_names)
224            self._month_name_to_ordinal.update(
225                self._name_to_ordinal(self.month_abbreviations)
226            )
227
228        return self._month_name_to_ordinal.get(name)
229
230    def year_full(self, year: int) -> str:
231        """Returns the year for specific locale if available
232
233        :param year: the ``int`` year (4-digit)
234        """
235        return f"{year:04d}"
236
237    def year_abbreviation(self, year: int) -> str:
238        """Returns the year for specific locale if available
239
240        :param year: the ``int`` year (4-digit)
241        """
242        return f"{year:04d}"[2:]
243
244    def meridian(self, hour: int, token: Any) -> Optional[str]:
245        """Returns the meridian indicator for a specified hour and format token.
246
247        :param hour: the ``int`` hour of the day.
248        :param token: the format token.
249        """
250
251        if token == "a":
252            return self.meridians["am"] if hour < 12 else self.meridians["pm"]
253        if token == "A":
254            return self.meridians["AM"] if hour < 12 else self.meridians["PM"]
255        return None
256
257    def ordinal_number(self, n: int) -> str:
258        """Returns the ordinal format of a given integer
259
260        :param n: an integer
261        """
262        return self._ordinal_number(n)
263
264    def _ordinal_number(self, n: int) -> str:
265        return f"{n}"
266
267    def _name_to_ordinal(self, lst: Sequence[str]) -> Dict[str, int]:
268        return {elem.lower(): i for i, elem in enumerate(lst[1:], 1)}
269
270    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
271        # TODO: remove cast
272        return cast(str, self.timeframes[timeframe]).format(trunc(abs(delta)))
273
274    def _format_relative(
275        self,
276        humanized: str,
277        timeframe: TimeFrameLiteral,
278        delta: Union[float, int],
279    ) -> str:
280
281        if timeframe == "now":
282            return humanized
283
284        direction = self.past if delta < 0 else self.future
285
286        return direction.format(humanized)
287
288
289class EnglishLocale(Locale):
290
291    names = [
292        "en",
293        "en-us",
294        "en-gb",
295        "en-au",
296        "en-be",
297        "en-jp",
298        "en-za",
299        "en-ca",
300        "en-ph",
301    ]
302
303    past = "{0} ago"
304    future = "in {0}"
305    and_word = "and"
306
307    timeframes = {
308        "now": "just now",
309        "second": "a second",
310        "seconds": "{0} seconds",
311        "minute": "a minute",
312        "minutes": "{0} minutes",
313        "hour": "an hour",
314        "hours": "{0} hours",
315        "day": "a day",
316        "days": "{0} days",
317        "week": "a week",
318        "weeks": "{0} weeks",
319        "month": "a month",
320        "months": "{0} months",
321        "quarter": "a quarter",
322        "quarters": "{0} quarters",
323        "year": "a year",
324        "years": "{0} years",
325    }
326
327    meridians = {"am": "am", "pm": "pm", "AM": "AM", "PM": "PM"}
328
329    month_names = [
330        "",
331        "January",
332        "February",
333        "March",
334        "April",
335        "May",
336        "June",
337        "July",
338        "August",
339        "September",
340        "October",
341        "November",
342        "December",
343    ]
344    month_abbreviations = [
345        "",
346        "Jan",
347        "Feb",
348        "Mar",
349        "Apr",
350        "May",
351        "Jun",
352        "Jul",
353        "Aug",
354        "Sep",
355        "Oct",
356        "Nov",
357        "Dec",
358    ]
359
360    day_names = [
361        "",
362        "Monday",
363        "Tuesday",
364        "Wednesday",
365        "Thursday",
366        "Friday",
367        "Saturday",
368        "Sunday",
369    ]
370    day_abbreviations = ["", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
371
372    ordinal_day_re = r"((?P<value>[2-3]?1(?=st)|[2-3]?2(?=nd)|[2-3]?3(?=rd)|[1-3]?[04-9](?=th)|1[1-3](?=th))(st|nd|rd|th))"
373
374    def _ordinal_number(self, n: int) -> str:
375        if n % 100 not in (11, 12, 13):
376            remainder = abs(n) % 10
377            if remainder == 1:
378                return f"{n}st"
379            elif remainder == 2:
380                return f"{n}nd"
381            elif remainder == 3:
382                return f"{n}rd"
383        return f"{n}th"
384
385    def describe(
386        self,
387        timeframe: TimeFrameLiteral,
388        delta: Union[int, float] = 0,
389        only_distance: bool = False,
390    ) -> str:
391        """Describes a delta within a timeframe in plain language.
392
393        :param timeframe: a string representing a timeframe.
394        :param delta: a quantity representing a delta in a timeframe.
395        :param only_distance: return only distance eg: "11 seconds" without "in" or "ago" keywords
396        """
397
398        humanized = super().describe(timeframe, delta, only_distance)
399        if only_distance and timeframe == "now":
400            humanized = "instantly"
401
402        return humanized
403
404
405class ItalianLocale(Locale):
406    names = ["it", "it-it"]
407    past = "{0} fa"
408    future = "tra {0}"
409    and_word = "e"
410
411    timeframes = {
412        "now": "adesso",
413        "second": "un secondo",
414        "seconds": "{0} qualche secondo",
415        "minute": "un minuto",
416        "minutes": "{0} minuti",
417        "hour": "un'ora",
418        "hours": "{0} ore",
419        "day": "un giorno",
420        "days": "{0} giorni",
421        "week": "una settimana,",
422        "weeks": "{0} settimane",
423        "month": "un mese",
424        "months": "{0} mesi",
425        "year": "un anno",
426        "years": "{0} anni",
427    }
428
429    month_names = [
430        "",
431        "gennaio",
432        "febbraio",
433        "marzo",
434        "aprile",
435        "maggio",
436        "giugno",
437        "luglio",
438        "agosto",
439        "settembre",
440        "ottobre",
441        "novembre",
442        "dicembre",
443    ]
444    month_abbreviations = [
445        "",
446        "gen",
447        "feb",
448        "mar",
449        "apr",
450        "mag",
451        "giu",
452        "lug",
453        "ago",
454        "set",
455        "ott",
456        "nov",
457        "dic",
458    ]
459
460    day_names = [
461        "",
462        "lunedì",
463        "martedì",
464        "mercoledì",
465        "giovedì",
466        "venerdì",
467        "sabato",
468        "domenica",
469    ]
470    day_abbreviations = ["", "lun", "mar", "mer", "gio", "ven", "sab", "dom"]
471
472    ordinal_day_re = r"((?P<value>[1-3]?[0-9](?=[ºª]))[ºª])"
473
474    def _ordinal_number(self, n: int) -> str:
475        return f"{n}º"
476
477
478class SpanishLocale(Locale):
479    names = ["es", "es-es"]
480    past = "hace {0}"
481    future = "en {0}"
482    and_word = "y"
483
484    timeframes = {
485        "now": "ahora",
486        "second": "un segundo",
487        "seconds": "{0} segundos",
488        "minute": "un minuto",
489        "minutes": "{0} minutos",
490        "hour": "una hora",
491        "hours": "{0} horas",
492        "day": "un día",
493        "days": "{0} días",
494        "week": "una semana",
495        "weeks": "{0} semanas",
496        "month": "un mes",
497        "months": "{0} meses",
498        "year": "un año",
499        "years": "{0} años",
500    }
501
502    meridians = {"am": "am", "pm": "pm", "AM": "AM", "PM": "PM"}
503
504    month_names = [
505        "",
506        "enero",
507        "febrero",
508        "marzo",
509        "abril",
510        "mayo",
511        "junio",
512        "julio",
513        "agosto",
514        "septiembre",
515        "octubre",
516        "noviembre",
517        "diciembre",
518    ]
519    month_abbreviations = [
520        "",
521        "ene",
522        "feb",
523        "mar",
524        "abr",
525        "may",
526        "jun",
527        "jul",
528        "ago",
529        "sep",
530        "oct",
531        "nov",
532        "dic",
533    ]
534
535    day_names = [
536        "",
537        "lunes",
538        "martes",
539        "miércoles",
540        "jueves",
541        "viernes",
542        "sábado",
543        "domingo",
544    ]
545    day_abbreviations = ["", "lun", "mar", "mie", "jue", "vie", "sab", "dom"]
546
547    ordinal_day_re = r"((?P<value>[1-3]?[0-9](?=[ºª]))[ºª])"
548
549    def _ordinal_number(self, n: int) -> str:
550        return f"{n}º"
551
552
553class FrenchBaseLocale(Locale):
554
555    past = "il y a {0}"
556    future = "dans {0}"
557    and_word = "et"
558
559    timeframes = {
560        "now": "maintenant",
561        "second": "une seconde",
562        "seconds": "{0} secondes",
563        "minute": "une minute",
564        "minutes": "{0} minutes",
565        "hour": "une heure",
566        "hours": "{0} heures",
567        "day": "un jour",
568        "days": "{0} jours",
569        "week": "une semaine",
570        "weeks": "{0} semaines",
571        "month": "un mois",
572        "months": "{0} mois",
573        "year": "un an",
574        "years": "{0} ans",
575    }
576
577    month_names = [
578        "",
579        "janvier",
580        "février",
581        "mars",
582        "avril",
583        "mai",
584        "juin",
585        "juillet",
586        "août",
587        "septembre",
588        "octobre",
589        "novembre",
590        "décembre",
591    ]
592
593    day_names = [
594        "",
595        "lundi",
596        "mardi",
597        "mercredi",
598        "jeudi",
599        "vendredi",
600        "samedi",
601        "dimanche",
602    ]
603    day_abbreviations = ["", "lun", "mar", "mer", "jeu", "ven", "sam", "dim"]
604
605    ordinal_day_re = (
606        r"((?P<value>\b1(?=er\b)|[1-3]?[02-9](?=e\b)|[1-3]1(?=e\b))(er|e)\b)"
607    )
608
609    def _ordinal_number(self, n: int) -> str:
610        if abs(n) == 1:
611            return f"{n}er"
612        return f"{n}e"
613
614
615class FrenchLocale(FrenchBaseLocale, Locale):
616
617    names = ["fr", "fr-fr"]
618
619    month_abbreviations = [
620        "",
621        "janv",
622        "févr",
623        "mars",
624        "avr",
625        "mai",
626        "juin",
627        "juil",
628        "août",
629        "sept",
630        "oct",
631        "nov",
632        "déc",
633    ]
634
635
636class FrenchCanadianLocale(FrenchBaseLocale, Locale):
637
638    names = ["fr-ca"]
639
640    month_abbreviations = [
641        "",
642        "janv",
643        "févr",
644        "mars",
645        "avr",
646        "mai",
647        "juin",
648        "juill",
649        "août",
650        "sept",
651        "oct",
652        "nov",
653        "déc",
654    ]
655
656
657class GreekLocale(Locale):
658
659    names = ["el", "el-gr"]
660
661    past = "{0} πριν"
662    future = "σε {0}"
663    and_word = "και"
664
665    timeframes = {
666        "now": "τώρα",
667        "second": "ένα δεύτερο",
668        "seconds": "{0} δευτερόλεπτα",
669        "minute": "ένα λεπτό",
670        "minutes": "{0} λεπτά",
671        "hour": "μία ώρα",
672        "hours": "{0} ώρες",
673        "day": "μία μέρα",
674        "days": "{0} μέρες",
675        "week": "μία εβδομάδα",
676        "weeks": "{0} εβδομάδες",
677        "month": "ένα μήνα",
678        "months": "{0} μήνες",
679        "year": "ένα χρόνο",
680        "years": "{0} χρόνια",
681    }
682
683    month_names = [
684        "",
685        "Ιανουαρίου",
686        "Φεβρουαρίου",
687        "Μαρτίου",
688        "Απριλίου",
689        "Μαΐου",
690        "Ιουνίου",
691        "Ιουλίου",
692        "Αυγούστου",
693        "Σεπτεμβρίου",
694        "Οκτωβρίου",
695        "Νοεμβρίου",
696        "Δεκεμβρίου",
697    ]
698    month_abbreviations = [
699        "",
700        "Ιαν",
701        "Φεβ",
702        "Μαρ",
703        "Απρ",
704        "Μαϊ",
705        "Ιον",
706        "Ιολ",
707        "Αυγ",
708        "Σεπ",
709        "Οκτ",
710        "Νοε",
711        "Δεκ",
712    ]
713
714    day_names = [
715        "",
716        "Δευτέρα",
717        "Τρίτη",
718        "Τετάρτη",
719        "Πέμπτη",
720        "Παρασκευή",
721        "Σάββατο",
722        "Κυριακή",
723    ]
724    day_abbreviations = ["", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ", "Κυρ"]
725
726
727class JapaneseLocale(Locale):
728
729    names = ["ja", "ja-jp"]
730
731    past = "{0}前"
732    future = "{0}後"
733    and_word = ""
734
735    timeframes = {
736        "now": "現在",
737        "second": "1秒",
738        "seconds": "{0}秒",
739        "minute": "1分",
740        "minutes": "{0}分",
741        "hour": "1時間",
742        "hours": "{0}時間",
743        "day": "1日",
744        "days": "{0}日",
745        "week": "1週間",
746        "weeks": "{0}週間",
747        "month": "1ヶ月",
748        "months": "{0}ヶ月",
749        "year": "1年",
750        "years": "{0}年",
751    }
752
753    month_names = [
754        "",
755        "1月",
756        "2月",
757        "3月",
758        "4月",
759        "5月",
760        "6月",
761        "7月",
762        "8月",
763        "9月",
764        "10月",
765        "11月",
766        "12月",
767    ]
768    month_abbreviations = [
769        "",
770        " 1",
771        " 2",
772        " 3",
773        " 4",
774        " 5",
775        " 6",
776        " 7",
777        " 8",
778        " 9",
779        "10",
780        "11",
781        "12",
782    ]
783
784    day_names = ["", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日", "日曜日"]
785    day_abbreviations = ["", "月", "火", "水", "木", "金", "土", "日"]
786
787
788class SwedishLocale(Locale):
789
790    names = ["sv", "sv-se"]
791
792    past = "för {0} sen"
793    future = "om {0}"
794    and_word = "och"
795
796    timeframes = {
797        "now": "just nu",
798        "second": "en sekund",
799        "seconds": "{0} sekunder",
800        "minute": "en minut",
801        "minutes": "{0} minuter",
802        "hour": "en timme",
803        "hours": "{0} timmar",
804        "day": "en dag",
805        "days": "{0} dagar",
806        "week": "en vecka",
807        "weeks": "{0} veckor",
808        "month": "en månad",
809        "months": "{0} månader",
810        "year": "ett år",
811        "years": "{0} år",
812    }
813
814    month_names = [
815        "",
816        "januari",
817        "februari",
818        "mars",
819        "april",
820        "maj",
821        "juni",
822        "juli",
823        "augusti",
824        "september",
825        "oktober",
826        "november",
827        "december",
828    ]
829    month_abbreviations = [
830        "",
831        "jan",
832        "feb",
833        "mar",
834        "apr",
835        "maj",
836        "jun",
837        "jul",
838        "aug",
839        "sep",
840        "okt",
841        "nov",
842        "dec",
843    ]
844
845    day_names = [
846        "",
847        "måndag",
848        "tisdag",
849        "onsdag",
850        "torsdag",
851        "fredag",
852        "lördag",
853        "söndag",
854    ]
855    day_abbreviations = ["", "mån", "tis", "ons", "tor", "fre", "lör", "sön"]
856
857
858class FinnishLocale(Locale):
859
860    names = ["fi", "fi-fi"]
861
862    # The finnish grammar is very complex, and its hard to convert
863    # 1-to-1 to something like English.
864
865    past = "{0} sitten"
866    future = "{0} kuluttua"
867
868    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
869        "now": "juuri nyt",
870        "second": "sekunti",
871        "seconds": {"past": "{0} muutama sekunti", "future": "{0} muutaman sekunnin"},
872        "minute": {"past": "minuutti", "future": "minuutin"},
873        "minutes": {"past": "{0} minuuttia", "future": "{0} minuutin"},
874        "hour": {"past": "tunti", "future": "tunnin"},
875        "hours": {"past": "{0} tuntia", "future": "{0} tunnin"},
876        "day": "päivä",
877        "days": {"past": "{0} päivää", "future": "{0} päivän"},
878        "month": {"past": "kuukausi", "future": "kuukauden"},
879        "months": {"past": "{0} kuukautta", "future": "{0} kuukauden"},
880        "year": {"past": "vuosi", "future": "vuoden"},
881        "years": {"past": "{0} vuotta", "future": "{0} vuoden"},
882    }
883
884    # Months and days are lowercase in Finnish
885    month_names = [
886        "",
887        "tammikuu",
888        "helmikuu",
889        "maaliskuu",
890        "huhtikuu",
891        "toukokuu",
892        "kesäkuu",
893        "heinäkuu",
894        "elokuu",
895        "syyskuu",
896        "lokakuu",
897        "marraskuu",
898        "joulukuu",
899    ]
900
901    month_abbreviations = [
902        "",
903        "tammi",
904        "helmi",
905        "maalis",
906        "huhti",
907        "touko",
908        "kesä",
909        "heinä",
910        "elo",
911        "syys",
912        "loka",
913        "marras",
914        "joulu",
915    ]
916
917    day_names = [
918        "",
919        "maanantai",
920        "tiistai",
921        "keskiviikko",
922        "torstai",
923        "perjantai",
924        "lauantai",
925        "sunnuntai",
926    ]
927
928    day_abbreviations = ["", "ma", "ti", "ke", "to", "pe", "la", "su"]
929
930    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
931        form = self.timeframes[timeframe]
932
933        if isinstance(form, Mapping):
934            if delta < 0:
935                form = form["past"]
936            else:
937                form = form["future"]
938
939        return form.format(abs(delta))
940
941    def _ordinal_number(self, n: int) -> str:
942        return f"{n}."
943
944
945class ChineseCNLocale(Locale):
946
947    names = ["zh", "zh-cn"]
948
949    past = "{0}前"
950    future = "{0}后"
951
952    timeframes = {
953        "now": "刚才",
954        "second": "一秒",
955        "seconds": "{0}秒",
956        "minute": "1分钟",
957        "minutes": "{0}分钟",
958        "hour": "1小时",
959        "hours": "{0}小时",
960        "day": "1天",
961        "days": "{0}天",
962        "week": "一周",
963        "weeks": "{0}周",
964        "month": "1个月",
965        "months": "{0}个月",
966        "year": "1年",
967        "years": "{0}年",
968    }
969
970    month_names = [
971        "",
972        "一月",
973        "二月",
974        "三月",
975        "四月",
976        "五月",
977        "六月",
978        "七月",
979        "八月",
980        "九月",
981        "十月",
982        "十一月",
983        "十二月",
984    ]
985    month_abbreviations = [
986        "",
987        " 1",
988        " 2",
989        " 3",
990        " 4",
991        " 5",
992        " 6",
993        " 7",
994        " 8",
995        " 9",
996        "10",
997        "11",
998        "12",
999    ]
1000
1001    day_names = ["", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]
1002    day_abbreviations = ["", "一", "二", "三", "四", "五", "六", "日"]
1003
1004
1005class ChineseTWLocale(Locale):
1006
1007    names = ["zh-tw"]
1008
1009    past = "{0}前"
1010    future = "{0}後"
1011    and_word = "和"
1012
1013    timeframes = {
1014        "now": "剛才",
1015        "second": "1秒",
1016        "seconds": "{0}秒",
1017        "minute": "1分鐘",
1018        "minutes": "{0}分鐘",
1019        "hour": "1小時",
1020        "hours": "{0}小時",
1021        "day": "1天",
1022        "days": "{0}天",
1023        "week": "1週",
1024        "weeks": "{0}週",
1025        "month": "1個月",
1026        "months": "{0}個月",
1027        "year": "1年",
1028        "years": "{0}年",
1029    }
1030
1031    month_names = [
1032        "",
1033        "1月",
1034        "2月",
1035        "3月",
1036        "4月",
1037        "5月",
1038        "6月",
1039        "7月",
1040        "8月",
1041        "9月",
1042        "10月",
1043        "11月",
1044        "12月",
1045    ]
1046    month_abbreviations = [
1047        "",
1048        " 1",
1049        " 2",
1050        " 3",
1051        " 4",
1052        " 5",
1053        " 6",
1054        " 7",
1055        " 8",
1056        " 9",
1057        "10",
1058        "11",
1059        "12",
1060    ]
1061
1062    day_names = ["", "週一", "週二", "週三", "週四", "週五", "週六", "週日"]
1063    day_abbreviations = ["", "一", "二", "三", "四", "五", "六", "日"]
1064
1065
1066class HongKongLocale(Locale):
1067
1068    names = ["zh-hk"]
1069
1070    past = "{0}前"
1071    future = "{0}後"
1072
1073    timeframes = {
1074        "now": "剛才",
1075        "second": "1秒",
1076        "seconds": "{0}秒",
1077        "minute": "1分鐘",
1078        "minutes": "{0}分鐘",
1079        "hour": "1小時",
1080        "hours": "{0}小時",
1081        "day": "1天",
1082        "days": "{0}天",
1083        "week": "1星期",
1084        "weeks": "{0}星期",
1085        "month": "1個月",
1086        "months": "{0}個月",
1087        "year": "1年",
1088        "years": "{0}年",
1089    }
1090
1091    month_names = [
1092        "",
1093        "1月",
1094        "2月",
1095        "3月",
1096        "4月",
1097        "5月",
1098        "6月",
1099        "7月",
1100        "8月",
1101        "9月",
1102        "10月",
1103        "11月",
1104        "12月",
1105    ]
1106    month_abbreviations = [
1107        "",
1108        " 1",
1109        " 2",
1110        " 3",
1111        " 4",
1112        " 5",
1113        " 6",
1114        " 7",
1115        " 8",
1116        " 9",
1117        "10",
1118        "11",
1119        "12",
1120    ]
1121
1122    day_names = ["", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]
1123    day_abbreviations = ["", "一", "二", "三", "四", "五", "六", "日"]
1124
1125
1126class KoreanLocale(Locale):
1127
1128    names = ["ko", "ko-kr"]
1129
1130    past = "{0} 전"
1131    future = "{0} 후"
1132
1133    timeframes = {
1134        "now": "지금",
1135        "second": "1초",
1136        "seconds": "{0}초",
1137        "minute": "1분",
1138        "minutes": "{0}분",
1139        "hour": "한시간",
1140        "hours": "{0}시간",
1141        "day": "하루",
1142        "days": "{0}일",
1143        "week": "1주",
1144        "weeks": "{0}주",
1145        "month": "한달",
1146        "months": "{0}개월",
1147        "year": "1년",
1148        "years": "{0}년",
1149    }
1150
1151    special_dayframes = {
1152        -3: "그끄제",
1153        -2: "그제",
1154        -1: "어제",
1155        1: "내일",
1156        2: "모레",
1157        3: "글피",
1158        4: "그글피",
1159    }
1160
1161    special_yearframes = {-2: "제작년", -1: "작년", 1: "내년", 2: "내후년"}
1162
1163    month_names = [
1164        "",
1165        "1월",
1166        "2월",
1167        "3월",
1168        "4월",
1169        "5월",
1170        "6월",
1171        "7월",
1172        "8월",
1173        "9월",
1174        "10월",
1175        "11월",
1176        "12월",
1177    ]
1178    month_abbreviations = [
1179        "",
1180        " 1",
1181        " 2",
1182        " 3",
1183        " 4",
1184        " 5",
1185        " 6",
1186        " 7",
1187        " 8",
1188        " 9",
1189        "10",
1190        "11",
1191        "12",
1192    ]
1193
1194    day_names = ["", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일", "일요일"]
1195    day_abbreviations = ["", "월", "화", "수", "목", "금", "토", "일"]
1196
1197    def _ordinal_number(self, n: int) -> str:
1198        ordinals = ["0", "첫", "두", "세", "네", "다섯", "여섯", "일곱", "여덟", "아홉", "열"]
1199        if n < len(ordinals):
1200            return f"{ordinals[n]}번째"
1201        return f"{n}번째"
1202
1203    def _format_relative(
1204        self,
1205        humanized: str,
1206        timeframe: TimeFrameLiteral,
1207        delta: Union[float, int],
1208    ) -> str:
1209        if timeframe in ("day", "days"):
1210            special = self.special_dayframes.get(int(delta))
1211            if special:
1212                return special
1213        elif timeframe in ("year", "years"):
1214            special = self.special_yearframes.get(int(delta))
1215            if special:
1216                return special
1217
1218        return super()._format_relative(humanized, timeframe, delta)
1219
1220
1221# derived locale types & implementations.
1222class DutchLocale(Locale):
1223
1224    names = ["nl", "nl-nl"]
1225
1226    past = "{0} geleden"
1227    future = "over {0}"
1228
1229    timeframes = {
1230        "now": "nu",
1231        "second": "een seconde",
1232        "seconds": "{0} seconden",
1233        "minute": "een minuut",
1234        "minutes": "{0} minuten",
1235        "hour": "een uur",
1236        "hours": "{0} uur",
1237        "day": "een dag",
1238        "days": "{0} dagen",
1239        "week": "een week",
1240        "weeks": "{0} weken",
1241        "month": "een maand",
1242        "months": "{0} maanden",
1243        "year": "een jaar",
1244        "years": "{0} jaar",
1245    }
1246
1247    # In Dutch names of months and days are not starting with a capital letter
1248    # like in the English language.
1249    month_names = [
1250        "",
1251        "januari",
1252        "februari",
1253        "maart",
1254        "april",
1255        "mei",
1256        "juni",
1257        "juli",
1258        "augustus",
1259        "september",
1260        "oktober",
1261        "november",
1262        "december",
1263    ]
1264    month_abbreviations = [
1265        "",
1266        "jan",
1267        "feb",
1268        "mrt",
1269        "apr",
1270        "mei",
1271        "jun",
1272        "jul",
1273        "aug",
1274        "sep",
1275        "okt",
1276        "nov",
1277        "dec",
1278    ]
1279
1280    day_names = [
1281        "",
1282        "maandag",
1283        "dinsdag",
1284        "woensdag",
1285        "donderdag",
1286        "vrijdag",
1287        "zaterdag",
1288        "zondag",
1289    ]
1290    day_abbreviations = ["", "ma", "di", "wo", "do", "vr", "za", "zo"]
1291
1292
1293class SlavicBaseLocale(Locale):
1294    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]]
1295
1296    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
1297        form = self.timeframes[timeframe]
1298        delta = abs(delta)
1299
1300        if isinstance(form, Mapping):
1301            if delta % 10 == 1 and delta % 100 != 11:
1302                form = form["singular"]
1303            elif 2 <= delta % 10 <= 4 and (delta % 100 < 10 or delta % 100 >= 20):
1304                form = form["dual"]
1305            else:
1306                form = form["plural"]
1307
1308        return form.format(delta)
1309
1310
1311class BelarusianLocale(SlavicBaseLocale):
1312
1313    names = ["be", "be-by"]
1314
1315    past = "{0} таму"
1316    future = "праз {0}"
1317
1318    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
1319        "now": "зараз",
1320        "second": "секунду",
1321        "seconds": "{0} некалькі секунд",
1322        "minute": "хвіліну",
1323        "minutes": {
1324            "singular": "{0} хвіліну",
1325            "dual": "{0} хвіліны",
1326            "plural": "{0} хвілін",
1327        },
1328        "hour": "гадзіну",
1329        "hours": {
1330            "singular": "{0} гадзіну",
1331            "dual": "{0} гадзіны",
1332            "plural": "{0} гадзін",
1333        },
1334        "day": "дзень",
1335        "days": {"singular": "{0} дзень", "dual": "{0} дні", "plural": "{0} дзён"},
1336        "month": "месяц",
1337        "months": {
1338            "singular": "{0} месяц",
1339            "dual": "{0} месяцы",
1340            "plural": "{0} месяцаў",
1341        },
1342        "year": "год",
1343        "years": {"singular": "{0} год", "dual": "{0} гады", "plural": "{0} гадоў"},
1344    }
1345
1346    month_names = [
1347        "",
1348        "студзеня",
1349        "лютага",
1350        "сакавіка",
1351        "красавіка",
1352        "траўня",
1353        "чэрвеня",
1354        "ліпеня",
1355        "жніўня",
1356        "верасня",
1357        "кастрычніка",
1358        "лістапада",
1359        "снежня",
1360    ]
1361    month_abbreviations = [
1362        "",
1363        "студ",
1364        "лют",
1365        "сак",
1366        "крас",
1367        "трав",
1368        "чэрв",
1369        "ліп",
1370        "жнів",
1371        "вер",
1372        "каст",
1373        "ліст",
1374        "снеж",
1375    ]
1376
1377    day_names = [
1378        "",
1379        "панядзелак",
1380        "аўторак",
1381        "серада",
1382        "чацвер",
1383        "пятніца",
1384        "субота",
1385        "нядзеля",
1386    ]
1387    day_abbreviations = ["", "пн", "ат", "ср", "чц", "пт", "сб", "нд"]
1388
1389
1390class PolishLocale(SlavicBaseLocale):
1391
1392    names = ["pl", "pl-pl"]
1393
1394    past = "{0} temu"
1395    future = "za {0}"
1396
1397    # The nouns should be in genitive case (Polish: "dopełniacz")
1398    # in order to correctly form `past` & `future` expressions.
1399    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
1400        "now": "teraz",
1401        "second": "sekundę",
1402        "seconds": {
1403            "singular": "{0} sekund",
1404            "dual": "{0} sekundy",
1405            "plural": "{0} sekund",
1406        },
1407        "minute": "minutę",
1408        "minutes": {
1409            "singular": "{0} minut",
1410            "dual": "{0} minuty",
1411            "plural": "{0} minut",
1412        },
1413        "hour": "godzinę",
1414        "hours": {
1415            "singular": "{0} godzin",
1416            "dual": "{0} godziny",
1417            "plural": "{0} godzin",
1418        },
1419        "day": "dzień",
1420        "days": "{0} dni",
1421        "week": "tydzień",
1422        "weeks": {
1423            "singular": "{0} tygodni",
1424            "dual": "{0} tygodnie",
1425            "plural": "{0} tygodni",
1426        },
1427        "month": "miesiąc",
1428        "months": {
1429            "singular": "{0} miesięcy",
1430            "dual": "{0} miesiące",
1431            "plural": "{0} miesięcy",
1432        },
1433        "year": "rok",
1434        "years": {"singular": "{0} lat", "dual": "{0} lata", "plural": "{0} lat"},
1435    }
1436
1437    month_names = [
1438        "",
1439        "styczeń",
1440        "luty",
1441        "marzec",
1442        "kwiecień",
1443        "maj",
1444        "czerwiec",
1445        "lipiec",
1446        "sierpień",
1447        "wrzesień",
1448        "październik",
1449        "listopad",
1450        "grudzień",
1451    ]
1452    month_abbreviations = [
1453        "",
1454        "sty",
1455        "lut",
1456        "mar",
1457        "kwi",
1458        "maj",
1459        "cze",
1460        "lip",
1461        "sie",
1462        "wrz",
1463        "paź",
1464        "lis",
1465        "gru",
1466    ]
1467
1468    day_names = [
1469        "",
1470        "poniedziałek",
1471        "wtorek",
1472        "środa",
1473        "czwartek",
1474        "piątek",
1475        "sobota",
1476        "niedziela",
1477    ]
1478    day_abbreviations = ["", "Pn", "Wt", "Śr", "Czw", "Pt", "So", "Nd"]
1479
1480
1481class RussianLocale(SlavicBaseLocale):
1482
1483    names = ["ru", "ru-ru"]
1484
1485    past = "{0} назад"
1486    future = "через {0}"
1487
1488    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
1489        "now": "сейчас",
1490        "second": "Второй",
1491        "seconds": "{0} несколько секунд",
1492        "minute": "минуту",
1493        "minutes": {
1494            "singular": "{0} минуту",
1495            "dual": "{0} минуты",
1496            "plural": "{0} минут",
1497        },
1498        "hour": "час",
1499        "hours": {"singular": "{0} час", "dual": "{0} часа", "plural": "{0} часов"},
1500        "day": "день",
1501        "days": {"singular": "{0} день", "dual": "{0} дня", "plural": "{0} дней"},
1502        "week": "неделю",
1503        "weeks": {
1504            "singular": "{0} неделю",
1505            "dual": "{0} недели",
1506            "plural": "{0} недель",
1507        },
1508        "month": "месяц",
1509        "months": {
1510            "singular": "{0} месяц",
1511            "dual": "{0} месяца",
1512            "plural": "{0} месяцев",
1513        },
1514        "year": "год",
1515        "years": {"singular": "{0} год", "dual": "{0} года", "plural": "{0} лет"},
1516    }
1517
1518    month_names = [
1519        "",
1520        "января",
1521        "февраля",
1522        "марта",
1523        "апреля",
1524        "мая",
1525        "июня",
1526        "июля",
1527        "августа",
1528        "сентября",
1529        "октября",
1530        "ноября",
1531        "декабря",
1532    ]
1533    month_abbreviations = [
1534        "",
1535        "янв",
1536        "фев",
1537        "мар",
1538        "апр",
1539        "май",
1540        "июн",
1541        "июл",
1542        "авг",
1543        "сен",
1544        "окт",
1545        "ноя",
1546        "дек",
1547    ]
1548
1549    day_names = [
1550        "",
1551        "понедельник",
1552        "вторник",
1553        "среда",
1554        "четверг",
1555        "пятница",
1556        "суббота",
1557        "воскресенье",
1558    ]
1559    day_abbreviations = ["", "пн", "вт", "ср", "чт", "пт", "сб", "вс"]
1560
1561
1562class AfrikaansLocale(Locale):
1563
1564    names = ["af", "af-nl"]
1565
1566    past = "{0} gelede"
1567    future = "in {0}"
1568
1569    timeframes = {
1570        "now": "nou",
1571        "second": "n sekonde",
1572        "seconds": "{0} sekondes",
1573        "minute": "minuut",
1574        "minutes": "{0} minute",
1575        "hour": "uur",
1576        "hours": "{0} ure",
1577        "day": "een dag",
1578        "days": "{0} dae",
1579        "month": "een maand",
1580        "months": "{0} maande",
1581        "year": "een jaar",
1582        "years": "{0} jaar",
1583    }
1584
1585    month_names = [
1586        "",
1587        "Januarie",
1588        "Februarie",
1589        "Maart",
1590        "April",
1591        "Mei",
1592        "Junie",
1593        "Julie",
1594        "Augustus",
1595        "September",
1596        "Oktober",
1597        "November",
1598        "Desember",
1599    ]
1600    month_abbreviations = [
1601        "",
1602        "Jan",
1603        "Feb",
1604        "Mrt",
1605        "Apr",
1606        "Mei",
1607        "Jun",
1608        "Jul",
1609        "Aug",
1610        "Sep",
1611        "Okt",
1612        "Nov",
1613        "Des",
1614    ]
1615
1616    day_names = [
1617        "",
1618        "Maandag",
1619        "Dinsdag",
1620        "Woensdag",
1621        "Donderdag",
1622        "Vrydag",
1623        "Saterdag",
1624        "Sondag",
1625    ]
1626    day_abbreviations = ["", "Ma", "Di", "Wo", "Do", "Vr", "Za", "So"]
1627
1628
1629class BulgarianLocale(SlavicBaseLocale):
1630
1631    names = ["bg", "bg-bg"]
1632
1633    past = "{0} назад"
1634    future = "напред {0}"
1635
1636    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
1637        "now": "сега",
1638        "second": "секунда",
1639        "seconds": "{0} няколко секунди",
1640        "minute": "минута",
1641        "minutes": {
1642            "singular": "{0} минута",
1643            "dual": "{0} минути",
1644            "plural": "{0} минути",
1645        },
1646        "hour": "час",
1647        "hours": {"singular": "{0} час", "dual": "{0} часа", "plural": "{0} часа"},
1648        "day": "ден",
1649        "days": {"singular": "{0} ден", "dual": "{0} дни", "plural": "{0} дни"},
1650        "month": "месец",
1651        "months": {
1652            "singular": "{0} месец",
1653            "dual": "{0} месеца",
1654            "plural": "{0} месеца",
1655        },
1656        "year": "година",
1657        "years": {
1658            "singular": "{0} година",
1659            "dual": "{0} години",
1660            "plural": "{0} години",
1661        },
1662    }
1663
1664    month_names = [
1665        "",
1666        "януари",
1667        "февруари",
1668        "март",
1669        "април",
1670        "май",
1671        "юни",
1672        "юли",
1673        "август",
1674        "септември",
1675        "октомври",
1676        "ноември",
1677        "декември",
1678    ]
1679    month_abbreviations = [
1680        "",
1681        "ян",
1682        "февр",
1683        "март",
1684        "апр",
1685        "май",
1686        "юни",
1687        "юли",
1688        "авг",
1689        "септ",
1690        "окт",
1691        "ноем",
1692        "дек",
1693    ]
1694
1695    day_names = [
1696        "",
1697        "понеделник",
1698        "вторник",
1699        "сряда",
1700        "четвъртък",
1701        "петък",
1702        "събота",
1703        "неделя",
1704    ]
1705    day_abbreviations = ["", "пон", "вт", "ср", "четв", "пет", "съб", "нед"]
1706
1707
1708class UkrainianLocale(SlavicBaseLocale):
1709
1710    names = ["ua", "uk", "uk-ua"]
1711
1712    past = "{0} тому"
1713    future = "за {0}"
1714
1715    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
1716        "now": "зараз",
1717        "second": "секунда",
1718        "seconds": "{0} кілька секунд",
1719        "minute": "хвилину",
1720        "minutes": {
1721            "singular": "{0} хвилину",
1722            "dual": "{0} хвилини",
1723            "plural": "{0} хвилин",
1724        },
1725        "hour": "годину",
1726        "hours": {
1727            "singular": "{0} годину",
1728            "dual": "{0} години",
1729            "plural": "{0} годин",
1730        },
1731        "day": "день",
1732        "days": {"singular": "{0} день", "dual": "{0} дні", "plural": "{0} днів"},
1733        "month": "місяць",
1734        "months": {
1735            "singular": "{0} місяць",
1736            "dual": "{0} місяці",
1737            "plural": "{0} місяців",
1738        },
1739        "year": "рік",
1740        "years": {"singular": "{0} рік", "dual": "{0} роки", "plural": "{0} років"},
1741    }
1742
1743    month_names = [
1744        "",
1745        "січня",
1746        "лютого",
1747        "березня",
1748        "квітня",
1749        "травня",
1750        "червня",
1751        "липня",
1752        "серпня",
1753        "вересня",
1754        "жовтня",
1755        "листопада",
1756        "грудня",
1757    ]
1758    month_abbreviations = [
1759        "",
1760        "січ",
1761        "лют",
1762        "бер",
1763        "квіт",
1764        "трав",
1765        "черв",
1766        "лип",
1767        "серп",
1768        "вер",
1769        "жовт",
1770        "лист",
1771        "груд",
1772    ]
1773
1774    day_names = [
1775        "",
1776        "понеділок",
1777        "вівторок",
1778        "середа",
1779        "четвер",
1780        "п’ятниця",
1781        "субота",
1782        "неділя",
1783    ]
1784    day_abbreviations = ["", "пн", "вт", "ср", "чт", "пт", "сб", "нд"]
1785
1786
1787class MacedonianLocale(SlavicBaseLocale):
1788    names = ["mk", "mk-mk"]
1789
1790    past = "пред {0}"
1791    future = "за {0}"
1792
1793    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
1794        "now": "сега",
1795        "second": "една секунда",
1796        "seconds": {
1797            "singular": "{0} секунда",
1798            "dual": "{0} секунди",
1799            "plural": "{0} секунди",
1800        },
1801        "minute": "една минута",
1802        "minutes": {
1803            "singular": "{0} минута",
1804            "dual": "{0} минути",
1805            "plural": "{0} минути",
1806        },
1807        "hour": "еден саат",
1808        "hours": {"singular": "{0} саат", "dual": "{0} саати", "plural": "{0} саати"},
1809        "day": "еден ден",
1810        "days": {"singular": "{0} ден", "dual": "{0} дена", "plural": "{0} дена"},
1811        "week": "една недела",
1812        "weeks": {
1813            "singular": "{0} недела",
1814            "dual": "{0} недели",
1815            "plural": "{0} недели",
1816        },
1817        "month": "еден месец",
1818        "months": {
1819            "singular": "{0} месец",
1820            "dual": "{0} месеци",
1821            "plural": "{0} месеци",
1822        },
1823        "year": "една година",
1824        "years": {
1825            "singular": "{0} година",
1826            "dual": "{0} години",
1827            "plural": "{0} години",
1828        },
1829    }
1830
1831    meridians = {"am": "дп", "pm": "пп", "AM": "претпладне", "PM": "попладне"}
1832
1833    month_names = [
1834        "",
1835        "Јануари",
1836        "Февруари",
1837        "Март",
1838        "Април",
1839        "Мај",
1840        "Јуни",
1841        "Јули",
1842        "Август",
1843        "Септември",
1844        "Октомври",
1845        "Ноември",
1846        "Декември",
1847    ]
1848    month_abbreviations = [
1849        "",
1850        "Јан",
1851        "Фев",
1852        "Мар",
1853        "Апр",
1854        "Мај",
1855        "Јун",
1856        "Јул",
1857        "Авг",
1858        "Септ",
1859        "Окт",
1860        "Ноем",
1861        "Декем",
1862    ]
1863
1864    day_names = [
1865        "",
1866        "Понеделник",
1867        "Вторник",
1868        "Среда",
1869        "Четврток",
1870        "Петок",
1871        "Сабота",
1872        "Недела",
1873    ]
1874    day_abbreviations = [
1875        "",
1876        "Пон",
1877        "Вт",
1878        "Сре",
1879        "Чет",
1880        "Пет",
1881        "Саб",
1882        "Нед",
1883    ]
1884
1885
1886class GermanBaseLocale(Locale):
1887
1888    past = "vor {0}"
1889    future = "in {0}"
1890    and_word = "und"
1891
1892    timeframes = {
1893        "now": "gerade eben",
1894        "second": "einer Sekunde",
1895        "seconds": "{0} Sekunden",
1896        "minute": "einer Minute",
1897        "minutes": "{0} Minuten",
1898        "hour": "einer Stunde",
1899        "hours": "{0} Stunden",
1900        "day": "einem Tag",
1901        "days": "{0} Tagen",
1902        "week": "einer Woche",
1903        "weeks": "{0} Wochen",
1904        "month": "einem Monat",
1905        "months": "{0} Monaten",
1906        "year": "einem Jahr",
1907        "years": "{0} Jahren",
1908    }
1909
1910    timeframes_only_distance = timeframes.copy()
1911    timeframes_only_distance["second"] = "eine Sekunde"
1912    timeframes_only_distance["minute"] = "eine Minute"
1913    timeframes_only_distance["hour"] = "eine Stunde"
1914    timeframes_only_distance["day"] = "ein Tag"
1915    timeframes_only_distance["days"] = "{0} Tage"
1916    timeframes_only_distance["week"] = "eine Woche"
1917    timeframes_only_distance["month"] = "ein Monat"
1918    timeframes_only_distance["months"] = "{0} Monate"
1919    timeframes_only_distance["year"] = "ein Jahr"
1920    timeframes_only_distance["years"] = "{0} Jahre"
1921
1922    month_names = [
1923        "",
1924        "Januar",
1925        "Februar",
1926        "März",
1927        "April",
1928        "Mai",
1929        "Juni",
1930        "Juli",
1931        "August",
1932        "September",
1933        "Oktober",
1934        "November",
1935        "Dezember",
1936    ]
1937
1938    month_abbreviations = [
1939        "",
1940        "Jan",
1941        "Feb",
1942        "Mär",
1943        "Apr",
1944        "Mai",
1945        "Jun",
1946        "Jul",
1947        "Aug",
1948        "Sep",
1949        "Okt",
1950        "Nov",
1951        "Dez",
1952    ]
1953
1954    day_names = [
1955        "",
1956        "Montag",
1957        "Dienstag",
1958        "Mittwoch",
1959        "Donnerstag",
1960        "Freitag",
1961        "Samstag",
1962        "Sonntag",
1963    ]
1964
1965    day_abbreviations = ["", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"]
1966
1967    def _ordinal_number(self, n: int) -> str:
1968        return f"{n}."
1969
1970    def describe(
1971        self,
1972        timeframe: TimeFrameLiteral,
1973        delta: Union[int, float] = 0,
1974        only_distance: bool = False,
1975    ) -> str:
1976        """Describes a delta within a timeframe in plain language.
1977
1978        :param timeframe: a string representing a timeframe.
1979        :param delta: a quantity representing a delta in a timeframe.
1980        :param only_distance: return only distance eg: "11 seconds" without "in" or "ago" keywords
1981        """
1982
1983        if not only_distance:
1984            return super().describe(timeframe, delta, only_distance)
1985
1986        # German uses a different case without 'in' or 'ago'
1987        humanized = self.timeframes_only_distance[timeframe].format(trunc(abs(delta)))
1988
1989        return humanized
1990
1991
1992class GermanLocale(GermanBaseLocale, Locale):
1993
1994    names = ["de", "de-de"]
1995
1996
1997class SwissLocale(GermanBaseLocale, Locale):
1998
1999    names = ["de-ch"]
2000
2001
2002class AustrianLocale(GermanBaseLocale, Locale):
2003
2004    names = ["de-at"]
2005
2006    month_names = [
2007        "",
2008        "Jänner",
2009        "Februar",
2010        "März",
2011        "April",
2012        "Mai",
2013        "Juni",
2014        "Juli",
2015        "August",
2016        "September",
2017        "Oktober",
2018        "November",
2019        "Dezember",
2020    ]
2021
2022
2023class NorwegianLocale(Locale):
2024
2025    names = ["nb", "nb-no"]
2026
2027    past = "for {0} siden"
2028    future = "om {0}"
2029
2030    timeframes = {
2031        "now": "nå nettopp",
2032        "second": "ett sekund",
2033        "seconds": "{0} sekunder",
2034        "minute": "ett minutt",
2035        "minutes": "{0} minutter",
2036        "hour": "en time",
2037        "hours": "{0} timer",
2038        "day": "en dag",
2039        "days": "{0} dager",
2040        "month": "en måned",
2041        "months": "{0} måneder",
2042        "year": "ett år",
2043        "years": "{0} år",
2044    }
2045
2046    month_names = [
2047        "",
2048        "januar",
2049        "februar",
2050        "mars",
2051        "april",
2052        "mai",
2053        "juni",
2054        "juli",
2055        "august",
2056        "september",
2057        "oktober",
2058        "november",
2059        "desember",
2060    ]
2061    month_abbreviations = [
2062        "",
2063        "jan",
2064        "feb",
2065        "mar",
2066        "apr",
2067        "mai",
2068        "jun",
2069        "jul",
2070        "aug",
2071        "sep",
2072        "okt",
2073        "nov",
2074        "des",
2075    ]
2076
2077    day_names = [
2078        "",
2079        "mandag",
2080        "tirsdag",
2081        "onsdag",
2082        "torsdag",
2083        "fredag",
2084        "lørdag",
2085        "søndag",
2086    ]
2087    day_abbreviations = ["", "ma", "ti", "on", "to", "fr", "lø", "sø"]
2088
2089
2090class NewNorwegianLocale(Locale):
2091
2092    names = ["nn", "nn-no"]
2093
2094    past = "for {0} sidan"
2095    future = "om {0}"
2096
2097    timeframes = {
2098        "now": "no nettopp",
2099        "second": "eitt sekund",
2100        "seconds": "{0} sekund",
2101        "minute": "eitt minutt",
2102        "minutes": "{0} minutt",
2103        "hour": "ein time",
2104        "hours": "{0} timar",
2105        "day": "ein dag",
2106        "days": "{0} dagar",
2107        "month": "en månad",
2108        "months": "{0} månader",
2109        "year": "eitt år",
2110        "years": "{0} år",
2111    }
2112
2113    month_names = [
2114        "",
2115        "januar",
2116        "februar",
2117        "mars",
2118        "april",
2119        "mai",
2120        "juni",
2121        "juli",
2122        "august",
2123        "september",
2124        "oktober",
2125        "november",
2126        "desember",
2127    ]
2128    month_abbreviations = [
2129        "",
2130        "jan",
2131        "feb",
2132        "mar",
2133        "apr",
2134        "mai",
2135        "jun",
2136        "jul",
2137        "aug",
2138        "sep",
2139        "okt",
2140        "nov",
2141        "des",
2142    ]
2143
2144    day_names = [
2145        "",
2146        "måndag",
2147        "tysdag",
2148        "onsdag",
2149        "torsdag",
2150        "fredag",
2151        "laurdag",
2152        "sundag",
2153    ]
2154    day_abbreviations = ["", "må", "ty", "on", "to", "fr", "la", "su"]
2155
2156
2157class PortugueseLocale(Locale):
2158    names = ["pt", "pt-pt"]
2159
2160    past = "há {0}"
2161    future = "em {0}"
2162    and_word = "e"
2163
2164    timeframes = {
2165        "now": "agora",
2166        "second": "um segundo",
2167        "seconds": "{0} segundos",
2168        "minute": "um minuto",
2169        "minutes": "{0} minutos",
2170        "hour": "uma hora",
2171        "hours": "{0} horas",
2172        "day": "um dia",
2173        "days": "{0} dias",
2174        "week": "uma semana",
2175        "weeks": "{0} semanas",
2176        "month": "um mês",
2177        "months": "{0} meses",
2178        "year": "um ano",
2179        "years": "{0} anos",
2180    }
2181
2182    month_names = [
2183        "",
2184        "Janeiro",
2185        "Fevereiro",
2186        "Março",
2187        "Abril",
2188        "Maio",
2189        "Junho",
2190        "Julho",
2191        "Agosto",
2192        "Setembro",
2193        "Outubro",
2194        "Novembro",
2195        "Dezembro",
2196    ]
2197    month_abbreviations = [
2198        "",
2199        "Jan",
2200        "Fev",
2201        "Mar",
2202        "Abr",
2203        "Mai",
2204        "Jun",
2205        "Jul",
2206        "Ago",
2207        "Set",
2208        "Out",
2209        "Nov",
2210        "Dez",
2211    ]
2212
2213    day_names = [
2214        "",
2215        "Segunda-feira",
2216        "Terça-feira",
2217        "Quarta-feira",
2218        "Quinta-feira",
2219        "Sexta-feira",
2220        "Sábado",
2221        "Domingo",
2222    ]
2223    day_abbreviations = ["", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab", "Dom"]
2224
2225
2226class BrazilianPortugueseLocale(PortugueseLocale):
2227    names = ["pt-br"]
2228
2229    past = "faz {0}"
2230
2231
2232class TagalogLocale(Locale):
2233
2234    names = ["tl", "tl-ph"]
2235
2236    past = "nakaraang {0}"
2237    future = "{0} mula ngayon"
2238
2239    timeframes = {
2240        "now": "ngayon lang",
2241        "second": "isang segundo",
2242        "seconds": "{0} segundo",
2243        "minute": "isang minuto",
2244        "minutes": "{0} minuto",
2245        "hour": "isang oras",
2246        "hours": "{0} oras",
2247        "day": "isang araw",
2248        "days": "{0} araw",
2249        "week": "isang linggo",
2250        "weeks": "{0} linggo",
2251        "month": "isang buwan",
2252        "months": "{0} buwan",
2253        "year": "isang taon",
2254        "years": "{0} taon",
2255    }
2256
2257    month_names = [
2258        "",
2259        "Enero",
2260        "Pebrero",
2261        "Marso",
2262        "Abril",
2263        "Mayo",
2264        "Hunyo",
2265        "Hulyo",
2266        "Agosto",
2267        "Setyembre",
2268        "Oktubre",
2269        "Nobyembre",
2270        "Disyembre",
2271    ]
2272    month_abbreviations = [
2273        "",
2274        "Ene",
2275        "Peb",
2276        "Mar",
2277        "Abr",
2278        "May",
2279        "Hun",
2280        "Hul",
2281        "Ago",
2282        "Set",
2283        "Okt",
2284        "Nob",
2285        "Dis",
2286    ]
2287
2288    day_names = [
2289        "",
2290        "Lunes",
2291        "Martes",
2292        "Miyerkules",
2293        "Huwebes",
2294        "Biyernes",
2295        "Sabado",
2296        "Linggo",
2297    ]
2298    day_abbreviations = ["", "Lun", "Mar", "Miy", "Huw", "Biy", "Sab", "Lin"]
2299
2300    meridians = {"am": "nu", "pm": "nh", "AM": "ng umaga", "PM": "ng hapon"}
2301
2302    def _ordinal_number(self, n: int) -> str:
2303        return f"ika-{n}"
2304
2305
2306class VietnameseLocale(Locale):
2307
2308    names = ["vi", "vi-vn"]
2309
2310    past = "{0} trước"
2311    future = "{0} nữa"
2312
2313    timeframes = {
2314        "now": "hiện tại",
2315        "second": "một giây",
2316        "seconds": "{0} giây",
2317        "minute": "một phút",
2318        "minutes": "{0} phút",
2319        "hour": "một giờ",
2320        "hours": "{0} giờ",
2321        "day": "một ngày",
2322        "days": "{0} ngày",
2323        "week": "một tuần",
2324        "weeks": "{0} tuần",
2325        "month": "một tháng",
2326        "months": "{0} tháng",
2327        "year": "một năm",
2328        "years": "{0} năm",
2329    }
2330
2331    month_names = [
2332        "",
2333        "Tháng Một",
2334        "Tháng Hai",
2335        "Tháng Ba",
2336        "Tháng Tư",
2337        "Tháng Năm",
2338        "Tháng Sáu",
2339        "Tháng Bảy",
2340        "Tháng Tám",
2341        "Tháng Chín",
2342        "Tháng Mười",
2343        "Tháng Mười Một",
2344        "Tháng Mười Hai",
2345    ]
2346    month_abbreviations = [
2347        "",
2348        "Tháng 1",
2349        "Tháng 2",
2350        "Tháng 3",
2351        "Tháng 4",
2352        "Tháng 5",
2353        "Tháng 6",
2354        "Tháng 7",
2355        "Tháng 8",
2356        "Tháng 9",
2357        "Tháng 10",
2358        "Tháng 11",
2359        "Tháng 12",
2360    ]
2361
2362    day_names = [
2363        "",
2364        "Thứ Hai",
2365        "Thứ Ba",
2366        "Thứ Tư",
2367        "Thứ Năm",
2368        "Thứ Sáu",
2369        "Thứ Bảy",
2370        "Chủ Nhật",
2371    ]
2372    day_abbreviations = ["", "Thứ 2", "Thứ 3", "Thứ 4", "Thứ 5", "Thứ 6", "Thứ 7", "CN"]
2373
2374
2375class TurkishLocale(Locale):
2376
2377    names = ["tr", "tr-tr"]
2378
2379    past = "{0} önce"
2380    future = "{0} sonra"
2381    and_word = "ve"
2382
2383    timeframes = {
2384        "now": "şimdi",
2385        "second": "bir saniye",
2386        "seconds": "{0} saniye",
2387        "minute": "bir dakika",
2388        "minutes": "{0} dakika",
2389        "hour": "bir saat",
2390        "hours": "{0} saat",
2391        "day": "bir gün",
2392        "days": "{0} gün",
2393        "week": "bir hafta",
2394        "weeks": "{0} hafta",
2395        "month": "bir ay",
2396        "months": "{0} ay",
2397        "year": "bir yıl",
2398        "years": "{0} yıl",
2399    }
2400
2401    meridians = {"am": "öö", "pm": "ös", "AM": "ÖÖ", "PM": "ÖS"}
2402
2403    month_names = [
2404        "",
2405        "Ocak",
2406        "Şubat",
2407        "Mart",
2408        "Nisan",
2409        "Mayıs",
2410        "Haziran",
2411        "Temmuz",
2412        "Ağustos",
2413        "Eylül",
2414        "Ekim",
2415        "Kasım",
2416        "Aralık",
2417    ]
2418    month_abbreviations = [
2419        "",
2420        "Oca",
2421        "Şub",
2422        "Mar",
2423        "Nis",
2424        "May",
2425        "Haz",
2426        "Tem",
2427        "Ağu",
2428        "Eyl",
2429        "Eki",
2430        "Kas",
2431        "Ara",
2432    ]
2433
2434    day_names = [
2435        "",
2436        "Pazartesi",
2437        "Salı",
2438        "Çarşamba",
2439        "Perşembe",
2440        "Cuma",
2441        "Cumartesi",
2442        "Pazar",
2443    ]
2444    day_abbreviations = ["", "Pzt", "Sal", "Çar", "Per", "Cum", "Cmt", "Paz"]
2445
2446
2447class AzerbaijaniLocale(Locale):
2448
2449    names = ["az", "az-az"]
2450
2451    past = "{0} əvvəl"
2452    future = "{0} sonra"
2453
2454    timeframes = {
2455        "now": "indi",
2456        "second": "bir saniyə",
2457        "seconds": "{0} saniyə",
2458        "minute": "bir dəqiqə",
2459        "minutes": "{0} dəqiqə",
2460        "hour": "bir saat",
2461        "hours": "{0} saat",
2462        "day": "bir gün",
2463        "days": "{0} gün",
2464        "week": "bir həftə",
2465        "weeks": "{0} həftə",
2466        "month": "bir ay",
2467        "months": "{0} ay",
2468        "year": "bir il",
2469        "years": "{0} il",
2470    }
2471
2472    month_names = [
2473        "",
2474        "Yanvar",
2475        "Fevral",
2476        "Mart",
2477        "Aprel",
2478        "May",
2479        "İyun",
2480        "İyul",
2481        "Avqust",
2482        "Sentyabr",
2483        "Oktyabr",
2484        "Noyabr",
2485        "Dekabr",
2486    ]
2487    month_abbreviations = [
2488        "",
2489        "Yan",
2490        "Fev",
2491        "Mar",
2492        "Apr",
2493        "May",
2494        "İyn",
2495        "İyl",
2496        "Avq",
2497        "Sen",
2498        "Okt",
2499        "Noy",
2500        "Dek",
2501    ]
2502
2503    day_names = [
2504        "",
2505        "Bazar ertəsi",
2506        "Çərşənbə axşamı",
2507        "Çərşənbə",
2508        "Cümə axşamı",
2509        "Cümə",
2510        "Şənbə",
2511        "Bazar",
2512    ]
2513    day_abbreviations = ["", "Ber", "Çax", "Çər", "Cax", "Cüm", "Şnb", "Bzr"]
2514
2515
2516class ArabicLocale(Locale):
2517    names = [
2518        "ar",
2519        "ar-ae",
2520        "ar-bh",
2521        "ar-dj",
2522        "ar-eg",
2523        "ar-eh",
2524        "ar-er",
2525        "ar-km",
2526        "ar-kw",
2527        "ar-ly",
2528        "ar-om",
2529        "ar-qa",
2530        "ar-sa",
2531        "ar-sd",
2532        "ar-so",
2533        "ar-ss",
2534        "ar-td",
2535        "ar-ye",
2536    ]
2537
2538    past = "منذ {0}"
2539    future = "خلال {0}"
2540
2541    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
2542        "now": "الآن",
2543        "second": "ثانية",
2544        "seconds": {"2": "ثانيتين", "ten": "{0} ثوان", "higher": "{0} ثانية"},
2545        "minute": "دقيقة",
2546        "minutes": {"2": "دقيقتين", "ten": "{0} دقائق", "higher": "{0} دقيقة"},
2547        "hour": "ساعة",
2548        "hours": {"2": "ساعتين", "ten": "{0} ساعات", "higher": "{0} ساعة"},
2549        "day": "يوم",
2550        "days": {"2": "يومين", "ten": "{0} أيام", "higher": "{0} يوم"},
2551        "month": "شهر",
2552        "months": {"2": "شهرين", "ten": "{0} أشهر", "higher": "{0} شهر"},
2553        "year": "سنة",
2554        "years": {"2": "سنتين", "ten": "{0} سنوات", "higher": "{0} سنة"},
2555    }
2556
2557    month_names = [
2558        "",
2559        "يناير",
2560        "فبراير",
2561        "مارس",
2562        "أبريل",
2563        "مايو",
2564        "يونيو",
2565        "يوليو",
2566        "أغسطس",
2567        "سبتمبر",
2568        "أكتوبر",
2569        "نوفمبر",
2570        "ديسمبر",
2571    ]
2572    month_abbreviations = [
2573        "",
2574        "يناير",
2575        "فبراير",
2576        "مارس",
2577        "أبريل",
2578        "مايو",
2579        "يونيو",
2580        "يوليو",
2581        "أغسطس",
2582        "سبتمبر",
2583        "أكتوبر",
2584        "نوفمبر",
2585        "ديسمبر",
2586    ]
2587
2588    day_names = [
2589        "",
2590        "الإثنين",
2591        "الثلاثاء",
2592        "الأربعاء",
2593        "الخميس",
2594        "الجمعة",
2595        "السبت",
2596        "الأحد",
2597    ]
2598    day_abbreviations = ["", "إثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"]
2599
2600    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
2601        form = self.timeframes[timeframe]
2602        delta = abs(delta)
2603        if isinstance(form, Mapping):
2604            if delta == 2:
2605                form = form["2"]
2606            elif 2 < delta <= 10:
2607                form = form["ten"]
2608            else:
2609                form = form["higher"]
2610
2611        return form.format(delta)
2612
2613
2614class LevantArabicLocale(ArabicLocale):
2615    names = ["ar-iq", "ar-jo", "ar-lb", "ar-ps", "ar-sy"]
2616    month_names = [
2617        "",
2618        "كانون الثاني",
2619        "شباط",
2620        "آذار",
2621        "نيسان",
2622        "أيار",
2623        "حزيران",
2624        "تموز",
2625        "آب",
2626        "أيلول",
2627        "تشرين الأول",
2628        "تشرين الثاني",
2629        "كانون الأول",
2630    ]
2631    month_abbreviations = [
2632        "",
2633        "كانون الثاني",
2634        "شباط",
2635        "آذار",
2636        "نيسان",
2637        "أيار",
2638        "حزيران",
2639        "تموز",
2640        "آب",
2641        "أيلول",
2642        "تشرين الأول",
2643        "تشرين الثاني",
2644        "كانون الأول",
2645    ]
2646
2647
2648class AlgeriaTunisiaArabicLocale(ArabicLocale):
2649    names = ["ar-tn", "ar-dz"]
2650    month_names = [
2651        "",
2652        "جانفي",
2653        "فيفري",
2654        "مارس",
2655        "أفريل",
2656        "ماي",
2657        "جوان",
2658        "جويلية",
2659        "أوت",
2660        "سبتمبر",
2661        "أكتوبر",
2662        "نوفمبر",
2663        "ديسمبر",
2664    ]
2665    month_abbreviations = [
2666        "",
2667        "جانفي",
2668        "فيفري",
2669        "مارس",
2670        "أفريل",
2671        "ماي",
2672        "جوان",
2673        "جويلية",
2674        "أوت",
2675        "سبتمبر",
2676        "أكتوبر",
2677        "نوفمبر",
2678        "ديسمبر",
2679    ]
2680
2681
2682class MauritaniaArabicLocale(ArabicLocale):
2683    names = ["ar-mr"]
2684    month_names = [
2685        "",
2686        "يناير",
2687        "فبراير",
2688        "مارس",
2689        "إبريل",
2690        "مايو",
2691        "يونيو",
2692        "يوليو",
2693        "أغشت",
2694        "شتمبر",
2695        "أكتوبر",
2696        "نوفمبر",
2697        "دجمبر",
2698    ]
2699    month_abbreviations = [
2700        "",
2701        "يناير",
2702        "فبراير",
2703        "مارس",
2704        "إبريل",
2705        "مايو",
2706        "يونيو",
2707        "يوليو",
2708        "أغشت",
2709        "شتمبر",
2710        "أكتوبر",
2711        "نوفمبر",
2712        "دجمبر",
2713    ]
2714
2715
2716class MoroccoArabicLocale(ArabicLocale):
2717    names = ["ar-ma"]
2718    month_names = [
2719        "",
2720        "يناير",
2721        "فبراير",
2722        "مارس",
2723        "أبريل",
2724        "ماي",
2725        "يونيو",
2726        "يوليوز",
2727        "غشت",
2728        "شتنبر",
2729        "أكتوبر",
2730        "نونبر",
2731        "دجنبر",
2732    ]
2733    month_abbreviations = [
2734        "",
2735        "يناير",
2736        "فبراير",
2737        "مارس",
2738        "أبريل",
2739        "ماي",
2740        "يونيو",
2741        "يوليوز",
2742        "غشت",
2743        "شتنبر",
2744        "أكتوبر",
2745        "نونبر",
2746        "دجنبر",
2747    ]
2748
2749
2750class IcelandicLocale(Locale):
2751    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
2752        form = self.timeframes[timeframe]
2753
2754        if isinstance(form, Mapping):
2755            if delta < 0:
2756                form = form["past"]
2757            elif delta > 0:
2758                form = form["future"]
2759            else:
2760                raise ValueError(
2761                    "Icelandic Locale does not support units with a delta of zero. "
2762                    "Please consider making a contribution to fix this issue."
2763                )
2764                # FIXME: handle when delta is 0
2765
2766        return form.format(abs(delta))
2767
2768    names = ["is", "is-is"]
2769
2770    past = "fyrir {0} síðan"
2771    future = "eftir {0}"
2772
2773    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
2774        "now": "rétt í þessu",
2775        "second": {"past": "sekúndu", "future": "sekúndu"},
2776        "seconds": {"past": "{0} nokkrum sekúndum", "future": "nokkrar sekúndur"},
2777        "minute": {"past": "einni mínútu", "future": "eina mínútu"},
2778        "minutes": {"past": "{0} mínútum", "future": "{0} mínútur"},
2779        "hour": {"past": "einum tíma", "future": "einn tíma"},
2780        "hours": {"past": "{0} tímum", "future": "{0} tíma"},
2781        "day": {"past": "einum degi", "future": "einn dag"},
2782        "days": {"past": "{0} dögum", "future": "{0} daga"},
2783        "month": {"past": "einum mánuði", "future": "einn mánuð"},
2784        "months": {"past": "{0} mánuðum", "future": "{0} mánuði"},
2785        "year": {"past": "einu ári", "future": "eitt ár"},
2786        "years": {"past": "{0} árum", "future": "{0} ár"},
2787    }
2788
2789    meridians = {"am": "f.h.", "pm": "e.h.", "AM": "f.h.", "PM": "e.h."}
2790
2791    month_names = [
2792        "",
2793        "janúar",
2794        "febrúar",
2795        "mars",
2796        "apríl",
2797        "maí",
2798        "júní",
2799        "júlí",
2800        "ágúst",
2801        "september",
2802        "október",
2803        "nóvember",
2804        "desember",
2805    ]
2806    month_abbreviations = [
2807        "",
2808        "jan",
2809        "feb",
2810        "mar",
2811        "apr",
2812        "maí",
2813        "jún",
2814        "júl",
2815        "ágú",
2816        "sep",
2817        "okt",
2818        "nóv",
2819        "des",
2820    ]
2821
2822    day_names = [
2823        "",
2824        "mánudagur",
2825        "þriðjudagur",
2826        "miðvikudagur",
2827        "fimmtudagur",
2828        "föstudagur",
2829        "laugardagur",
2830        "sunnudagur",
2831    ]
2832    day_abbreviations = ["", "mán", "þri", "mið", "fim", "fös", "lau", "sun"]
2833
2834
2835class DanishLocale(Locale):
2836
2837    names = ["da", "da-dk"]
2838
2839    past = "for {0} siden"
2840    future = "efter {0}"
2841    and_word = "og"
2842
2843    timeframes = {
2844        "now": "lige nu",
2845        "second": "et sekund",
2846        "seconds": "{0} et par sekunder",
2847        "minute": "et minut",
2848        "minutes": "{0} minutter",
2849        "hour": "en time",
2850        "hours": "{0} timer",
2851        "day": "en dag",
2852        "days": "{0} dage",
2853        "month": "en måned",
2854        "months": "{0} måneder",
2855        "year": "et år",
2856        "years": "{0} år",
2857    }
2858
2859    month_names = [
2860        "",
2861        "januar",
2862        "februar",
2863        "marts",
2864        "april",
2865        "maj",
2866        "juni",
2867        "juli",
2868        "august",
2869        "september",
2870        "oktober",
2871        "november",
2872        "december",
2873    ]
2874    month_abbreviations = [
2875        "",
2876        "jan",
2877        "feb",
2878        "mar",
2879        "apr",
2880        "maj",
2881        "jun",
2882        "jul",
2883        "aug",
2884        "sep",
2885        "okt",
2886        "nov",
2887        "dec",
2888    ]
2889
2890    day_names = [
2891        "",
2892        "mandag",
2893        "tirsdag",
2894        "onsdag",
2895        "torsdag",
2896        "fredag",
2897        "lørdag",
2898        "søndag",
2899    ]
2900    day_abbreviations = ["", "man", "tir", "ons", "tor", "fre", "lør", "søn"]
2901
2902
2903class MalayalamLocale(Locale):
2904
2905    names = ["ml"]
2906
2907    past = "{0} മുമ്പ്"
2908    future = "{0} ശേഷം"
2909
2910    timeframes = {
2911        "now": "ഇപ്പോൾ",
2912        "second": "ഒരു നിമിഷം",
2913        "seconds": "{0} സെക്കന്റ്‌",
2914        "minute": "ഒരു മിനിറ്റ്",
2915        "minutes": "{0} മിനിറ്റ്",
2916        "hour": "ഒരു മണിക്കൂർ",
2917        "hours": "{0} മണിക്കൂർ",
2918        "day": "ഒരു ദിവസം ",
2919        "days": "{0} ദിവസം ",
2920        "month": "ഒരു മാസം ",
2921        "months": "{0} മാസം ",
2922        "year": "ഒരു വർഷം ",
2923        "years": "{0} വർഷം ",
2924    }
2925
2926    meridians = {
2927        "am": "രാവിലെ",
2928        "pm": "ഉച്ചക്ക് ശേഷം",
2929        "AM": "രാവിലെ",
2930        "PM": "ഉച്ചക്ക് ശേഷം",
2931    }
2932
2933    month_names = [
2934        "",
2935        "ജനുവരി",
2936        "ഫെബ്രുവരി",
2937        "മാർച്ച്‌",
2938        "ഏപ്രിൽ ",
2939        "മെയ്‌ ",
2940        "ജൂണ്‍",
2941        "ജൂലൈ",
2942        "ഓഗസ്റ്റ്‌",
2943        "സെപ്റ്റംബർ",
2944        "ഒക്ടോബർ",
2945        "നവംബർ",
2946        "ഡിസംബർ",
2947    ]
2948    month_abbreviations = [
2949        "",
2950        "ജനു",
2951        "ഫെബ് ",
2952        "മാർ",
2953        "ഏപ്രിൽ",
2954        "മേയ്",
2955        "ജൂണ്‍",
2956        "ജൂലൈ",
2957        "ഓഗസ്റ",
2958        "സെപ്റ്റ",
2959        "ഒക്ടോ",
2960        "നവം",
2961        "ഡിസം",
2962    ]
2963
2964    day_names = ["", "തിങ്കള്‍", "ചൊവ്വ", "ബുധന്‍", "വ്യാഴം", "വെള്ളി", "ശനി", "ഞായര്‍"]
2965    day_abbreviations = [
2966        "",
2967        "തിങ്കള്‍",
2968        "ചൊവ്വ",
2969        "ബുധന്‍",
2970        "വ്യാഴം",
2971        "വെള്ളി",
2972        "ശനി",
2973        "ഞായര്‍",
2974    ]
2975
2976
2977class HindiLocale(Locale):
2978
2979    names = ["hi", "hi-in"]
2980
2981    past = "{0} पहले"
2982    future = "{0} बाद"
2983
2984    timeframes = {
2985        "now": "अभी",
2986        "second": "एक पल",
2987        "seconds": "{0} सेकंड्",
2988        "minute": "एक मिनट ",
2989        "minutes": "{0} मिनट ",
2990        "hour": "एक घंटा",
2991        "hours": "{0} घंटे",
2992        "day": "एक दिन",
2993        "days": "{0} दिन",
2994        "month": "एक माह ",
2995        "months": "{0} महीने ",
2996        "year": "एक वर्ष ",
2997        "years": "{0} साल ",
2998    }
2999
3000    meridians = {"am": "सुबह", "pm": "शाम", "AM": "सुबह", "PM": "शाम"}
3001
3002    month_names = [
3003        "",
3004        "जनवरी",
3005        "फरवरी",
3006        "मार्च",
3007        "अप्रैल ",
3008        "मई",
3009        "जून",
3010        "जुलाई",
3011        "अगस्त",
3012        "सितंबर",
3013        "अक्टूबर",
3014        "नवंबर",
3015        "दिसंबर",
3016    ]
3017    month_abbreviations = [
3018        "",
3019        "जन",
3020        "फ़र",
3021        "मार्च",
3022        "अप्रै",
3023        "मई",
3024        "जून",
3025        "जुलाई",
3026        "आग",
3027        "सित",
3028        "अकत",
3029        "नवे",
3030        "दिस",
3031    ]
3032
3033    day_names = [
3034        "",
3035        "सोमवार",
3036        "मंगलवार",
3037        "बुधवार",
3038        "गुरुवार",
3039        "शुक्रवार",
3040        "शनिवार",
3041        "रविवार",
3042    ]
3043    day_abbreviations = ["", "सोम", "मंगल", "बुध", "गुरुवार", "शुक्र", "शनि", "रवि"]
3044
3045
3046class CzechLocale(Locale):
3047    names = ["cs", "cs-cz"]
3048
3049    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
3050        "now": "Teď",
3051        "second": {"past": "vteřina", "future": "vteřina", "zero": "vteřina"},
3052        "seconds": {
3053            "past": "{0} sekundami",
3054            "future-singular": "{0} sekundy",
3055            "future-paucal": "{0} sekund",
3056        },
3057        "minute": {"past": "minutou", "future": "minutu", "zero": "{0} minut"},
3058        "minutes": {
3059            "past": "{0} minutami",
3060            "future-singular": "{0} minuty",
3061            "future-paucal": "{0} minut",
3062        },
3063        "hour": {"past": "hodinou", "future": "hodinu", "zero": "{0} hodin"},
3064        "hours": {
3065            "past": "{0} hodinami",
3066            "future-singular": "{0} hodiny",
3067            "future-paucal": "{0} hodin",
3068        },
3069        "day": {"past": "dnem", "future": "den", "zero": "{0} dnů"},
3070        "days": {
3071            "past": "{0} dny",
3072            "future-singular": "{0} dny",
3073            "future-paucal": "{0} dnů",
3074        },
3075        "week": {"past": "týdnem", "future": "týden", "zero": "{0} týdnů"},
3076        "weeks": {
3077            "past": "{0} týdny",
3078            "future-singular": "{0} týdny",
3079            "future-paucal": "{0} týdnů",
3080        },
3081        "month": {"past": "měsícem", "future": "měsíc", "zero": "{0} měsíců"},
3082        "months": {
3083            "past": "{0} měsíci",
3084            "future-singular": "{0} měsíce",
3085            "future-paucal": "{0} měsíců",
3086        },
3087        "year": {"past": "rokem", "future": "rok", "zero": "{0} let"},
3088        "years": {
3089            "past": "{0} lety",
3090            "future-singular": "{0} roky",
3091            "future-paucal": "{0} let",
3092        },
3093    }
3094
3095    past = "Před {0}"
3096    future = "Za {0}"
3097
3098    month_names = [
3099        "",
3100        "leden",
3101        "únor",
3102        "březen",
3103        "duben",
3104        "květen",
3105        "červen",
3106        "červenec",
3107        "srpen",
3108        "září",
3109        "říjen",
3110        "listopad",
3111        "prosinec",
3112    ]
3113    month_abbreviations = [
3114        "",
3115        "led",
3116        "úno",
3117        "bře",
3118        "dub",
3119        "kvě",
3120        "čvn",
3121        "čvc",
3122        "srp",
3123        "zář",
3124        "říj",
3125        "lis",
3126        "pro",
3127    ]
3128
3129    day_names = [
3130        "",
3131        "pondělí",
3132        "úterý",
3133        "středa",
3134        "čtvrtek",
3135        "pátek",
3136        "sobota",
3137        "neděle",
3138    ]
3139    day_abbreviations = ["", "po", "út", "st", "čt", "pá", "so", "ne"]
3140
3141    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
3142        """Czech aware time frame format function, takes into account
3143        the differences between past and future forms."""
3144        abs_delta = abs(delta)
3145        form = self.timeframes[timeframe]
3146
3147        if isinstance(form, str):
3148            return form.format(abs_delta)
3149
3150        if delta == 0:
3151            key = "zero"  # And *never* use 0 in the singular!
3152        elif delta < 0:
3153            key = "past"
3154        else:
3155            # Needed since both regular future and future-singular and future-paucal cases
3156            if "future-singular" not in form:
3157                key = "future"
3158            elif 2 <= abs_delta % 10 <= 4 and (
3159                abs_delta % 100 < 10 or abs_delta % 100 >= 20
3160            ):
3161                key = "future-singular"
3162            else:
3163                key = "future-paucal"
3164
3165        form: str = form[key]
3166        return form.format(abs_delta)
3167
3168
3169class SlovakLocale(Locale):
3170    names = ["sk", "sk-sk"]
3171
3172    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
3173        "now": "Teraz",
3174        "second": {"past": "sekundou", "future": "sekundu", "zero": "{0} sekúnd"},
3175        "seconds": {
3176            "past": "{0} sekundami",
3177            "future-singular": "{0} sekundy",
3178            "future-paucal": "{0} sekúnd",
3179        },
3180        "minute": {"past": "minútou", "future": "minútu", "zero": "{0} minút"},
3181        "minutes": {
3182            "past": "{0} minútami",
3183            "future-singular": "{0} minúty",
3184            "future-paucal": "{0} minút",
3185        },
3186        "hour": {"past": "hodinou", "future": "hodinu", "zero": "{0} hodín"},
3187        "hours": {
3188            "past": "{0} hodinami",
3189            "future-singular": "{0} hodiny",
3190            "future-paucal": "{0} hodín",
3191        },
3192        "day": {"past": "dňom", "future": "deň", "zero": "{0} dní"},
3193        "days": {
3194            "past": "{0} dňami",
3195            "future-singular": "{0} dni",
3196            "future-paucal": "{0} dní",
3197        },
3198        "week": {"past": "týždňom", "future": "týždeň", "zero": "{0} týždňov"},
3199        "weeks": {
3200            "past": "{0} týždňami",
3201            "future-singular": "{0} týždne",
3202            "future-paucal": "{0} týždňov",
3203        },
3204        "month": {"past": "mesiacom", "future": "mesiac", "zero": "{0} mesiacov"},
3205        "months": {
3206            "past": "{0} mesiacmi",
3207            "future-singular": "{0} mesiace",
3208            "future-paucal": "{0} mesiacov",
3209        },
3210        "year": {"past": "rokom", "future": "rok", "zero": "{0} rokov"},
3211        "years": {
3212            "past": "{0} rokmi",
3213            "future-singular": "{0} roky",
3214            "future-paucal": "{0} rokov",
3215        },
3216    }
3217
3218    past = "Pred {0}"
3219    future = "O {0}"
3220    and_word = "a"
3221
3222    month_names = [
3223        "",
3224        "január",
3225        "február",
3226        "marec",
3227        "apríl",
3228        "máj",
3229        "jún",
3230        "júl",
3231        "august",
3232        "september",
3233        "október",
3234        "november",
3235        "december",
3236    ]
3237    month_abbreviations = [
3238        "",
3239        "jan",
3240        "feb",
3241        "mar",
3242        "apr",
3243        "máj",
3244        "jún",
3245        "júl",
3246        "aug",
3247        "sep",
3248        "okt",
3249        "nov",
3250        "dec",
3251    ]
3252
3253    day_names = [
3254        "",
3255        "pondelok",
3256        "utorok",
3257        "streda",
3258        "štvrtok",
3259        "piatok",
3260        "sobota",
3261        "nedeľa",
3262    ]
3263    day_abbreviations = ["", "po", "ut", "st", "št", "pi", "so", "ne"]
3264
3265    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
3266        """Slovak aware time frame format function, takes into account
3267        the differences between past and future forms."""
3268        abs_delta = abs(delta)
3269        form = self.timeframes[timeframe]
3270
3271        if isinstance(form, str):
3272            return form.format(abs_delta)
3273
3274        if delta == 0:
3275            key = "zero"  # And *never* use 0 in the singular!
3276        elif delta < 0:
3277            key = "past"
3278        else:
3279            if "future-singular" not in form:
3280                key = "future"
3281            elif 2 <= abs_delta % 10 <= 4 and (
3282                abs_delta % 100 < 10 or abs_delta % 100 >= 20
3283            ):
3284                key = "future-singular"
3285            else:
3286                key = "future-paucal"
3287
3288        form: str = form[key]
3289        return form.format(abs_delta)
3290
3291
3292class FarsiLocale(Locale):
3293
3294    names = ["fa", "fa-ir"]
3295
3296    past = "{0} قبل"
3297    future = "در {0}"
3298
3299    timeframes = {
3300        "now": "اکنون",
3301        "second": "یک لحظه",
3302        "seconds": "{0} ثانیه",
3303        "minute": "یک دقیقه",
3304        "minutes": "{0} دقیقه",
3305        "hour": "یک ساعت",
3306        "hours": "{0} ساعت",
3307        "day": "یک روز",
3308        "days": "{0} روز",
3309        "month": "یک ماه",
3310        "months": "{0} ماه",
3311        "year": "یک سال",
3312        "years": "{0} سال",
3313    }
3314
3315    meridians = {
3316        "am": "قبل از ظهر",
3317        "pm": "بعد از ظهر",
3318        "AM": "قبل از ظهر",
3319        "PM": "بعد از ظهر",
3320    }
3321
3322    month_names = [
3323        "",
3324        "January",
3325        "February",
3326        "March",
3327        "April",
3328        "May",
3329        "June",
3330        "July",
3331        "August",
3332        "September",
3333        "October",
3334        "November",
3335        "December",
3336    ]
3337    month_abbreviations = [
3338        "",
3339        "Jan",
3340        "Feb",
3341        "Mar",
3342        "Apr",
3343        "May",
3344        "Jun",
3345        "Jul",
3346        "Aug",
3347        "Sep",
3348        "Oct",
3349        "Nov",
3350        "Dec",
3351    ]
3352
3353    day_names = [
3354        "",
3355        "دو شنبه",
3356        "سه شنبه",
3357        "چهارشنبه",
3358        "پنجشنبه",
3359        "جمعه",
3360        "شنبه",
3361        "یکشنبه",
3362    ]
3363    day_abbreviations = ["", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
3364
3365
3366class HebrewLocale(Locale):
3367
3368    names = ["he", "he-il"]
3369
3370    past = "לפני {0}"
3371    future = "בעוד {0}"
3372    and_word = "ו"
3373
3374    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
3375        "now": "הרגע",
3376        "second": "שנייה",
3377        "seconds": "{0} שניות",
3378        "minute": "דקה",
3379        "minutes": "{0} דקות",
3380        "hour": "שעה",
3381        "hours": {"2": "שעתיים", "ten": "{0} שעות", "higher": "{0} שעות"},
3382        "day": "יום",
3383        "days": {"2": "יומיים", "ten": "{0} ימים", "higher": "{0} יום"},
3384        "week": "שבוע",
3385        "weeks": {"2": "שבועיים", "ten": "{0} שבועות", "higher": "{0} שבועות"},
3386        "month": "חודש",
3387        "months": {"2": "חודשיים", "ten": "{0} חודשים", "higher": "{0} חודשים"},
3388        "year": "שנה",
3389        "years": {"2": "שנתיים", "ten": "{0} שנים", "higher": "{0} שנה"},
3390    }
3391
3392    meridians = {
3393        "am": 'לפנ"צ',
3394        "pm": 'אחר"צ',
3395        "AM": "לפני הצהריים",
3396        "PM": "אחרי הצהריים",
3397    }
3398
3399    month_names = [
3400        "",
3401        "ינואר",
3402        "פברואר",
3403        "מרץ",
3404        "אפריל",
3405        "מאי",
3406        "יוני",
3407        "יולי",
3408        "אוגוסט",
3409        "ספטמבר",
3410        "אוקטובר",
3411        "נובמבר",
3412        "דצמבר",
3413    ]
3414    month_abbreviations = [
3415        "",
3416        "ינו׳",
3417        "פבר׳",
3418        "מרץ",
3419        "אפר׳",
3420        "מאי",
3421        "יוני",
3422        "יולי",
3423        "אוג׳",
3424        "ספט׳",
3425        "אוק׳",
3426        "נוב׳",
3427        "דצמ׳",
3428    ]
3429
3430    day_names = ["", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת", "ראשון"]
3431    day_abbreviations = ["", "ב׳", "ג׳", "ד׳", "ה׳", "ו׳", "ש׳", "א׳"]
3432
3433    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
3434        form = self.timeframes[timeframe]
3435        delta = abs(delta)
3436        if isinstance(form, Mapping):
3437            if delta == 2:
3438                form = form["2"]
3439            elif delta == 0 or 2 < delta <= 10:
3440                form = form["ten"]
3441            else:
3442                form = form["higher"]
3443
3444        return form.format(delta)
3445
3446    def describe_multi(
3447        self,
3448        timeframes: Sequence[Tuple[TimeFrameLiteral, Union[int, float]]],
3449        only_distance: bool = False,
3450    ) -> str:
3451        """Describes a delta within multiple timeframes in plain language.
3452        In Hebrew, the and word behaves a bit differently.
3453
3454        :param timeframes: a list of string, quantity pairs each representing a timeframe and delta.
3455        :param only_distance: return only distance eg: "2 hours and 11 seconds" without "in" or "ago" keywords
3456        """
3457
3458        humanized = ""
3459        for index, (timeframe, delta) in enumerate(timeframes):
3460            last_humanized = self._format_timeframe(timeframe, trunc(delta))
3461            if index == 0:
3462                humanized = last_humanized
3463            elif index == len(timeframes) - 1:  # Must have at least 2 items
3464                humanized += " " + self.and_word
3465                if last_humanized[0].isdecimal():
3466                    humanized += "־"
3467                humanized += last_humanized
3468            else:  # Don't add for the last one
3469                humanized += ", " + last_humanized
3470
3471        if not only_distance:
3472            humanized = self._format_relative(humanized, timeframe, trunc(delta))
3473
3474        return humanized
3475
3476
3477class MarathiLocale(Locale):
3478
3479    names = ["mr"]
3480
3481    past = "{0} आधी"
3482    future = "{0} नंतर"
3483
3484    timeframes = {
3485        "now": "सद्य",
3486        "second": "एक सेकंद",
3487        "seconds": "{0} सेकंद",
3488        "minute": "एक मिनिट ",
3489        "minutes": "{0} मिनिट ",
3490        "hour": "एक तास",
3491        "hours": "{0} तास",
3492        "day": "एक दिवस",
3493        "days": "{0} दिवस",
3494        "month": "एक महिना ",
3495        "months": "{0} महिने ",
3496        "year": "एक वर्ष ",
3497        "years": "{0} वर्ष ",
3498    }
3499
3500    meridians = {"am": "सकाळ", "pm": "संध्याकाळ", "AM": "सकाळ", "PM": "संध्याकाळ"}
3501
3502    month_names = [
3503        "",
3504        "जानेवारी",
3505        "फेब्रुवारी",
3506        "मार्च",
3507        "एप्रिल",
3508        "मे",
3509        "जून",
3510        "जुलै",
3511        "अॉगस्ट",
3512        "सप्टेंबर",
3513        "अॉक्टोबर",
3514        "नोव्हेंबर",
3515        "डिसेंबर",
3516    ]
3517    month_abbreviations = [
3518        "",
3519        "जान",
3520        "फेब्रु",
3521        "मार्च",
3522        "एप्रि",
3523        "मे",
3524        "जून",
3525        "जुलै",
3526        "अॉग",
3527        "सप्टें",
3528        "अॉक्टो",
3529        "नोव्हें",
3530        "डिसें",
3531    ]
3532
3533    day_names = [
3534        "",
3535        "सोमवार",
3536        "मंगळवार",
3537        "बुधवार",
3538        "गुरुवार",
3539        "शुक्रवार",
3540        "शनिवार",
3541        "रविवार",
3542    ]
3543    day_abbreviations = ["", "सोम", "मंगळ", "बुध", "गुरु", "शुक्र", "शनि", "रवि"]
3544
3545
3546class CatalanLocale(Locale):
3547    names = ["ca", "ca-es", "ca-ad", "ca-fr", "ca-it"]
3548    past = "Fa {0}"
3549    future = "En {0}"
3550    and_word = "i"
3551
3552    timeframes = {
3553        "now": "Ara mateix",
3554        "second": "un segon",
3555        "seconds": "{0} segons",
3556        "minute": "un minut",
3557        "minutes": "{0} minuts",
3558        "hour": "una hora",
3559        "hours": "{0} hores",
3560        "day": "un dia",
3561        "days": "{0} dies",
3562        "month": "un mes",
3563        "months": "{0} mesos",
3564        "year": "un any",
3565        "years": "{0} anys",
3566    }
3567
3568    month_names = [
3569        "",
3570        "gener",
3571        "febrer",
3572        "març",
3573        "abril",
3574        "maig",
3575        "juny",
3576        "juliol",
3577        "agost",
3578        "setembre",
3579        "octubre",
3580        "novembre",
3581        "desembre",
3582    ]
3583    month_abbreviations = [
3584        "",
3585        "gen.",
3586        "febr.",
3587        "març",
3588        "abr.",
3589        "maig",
3590        "juny",
3591        "jul.",
3592        "ag.",
3593        "set.",
3594        "oct.",
3595        "nov.",
3596        "des.",
3597    ]
3598    day_names = [
3599        "",
3600        "dilluns",
3601        "dimarts",
3602        "dimecres",
3603        "dijous",
3604        "divendres",
3605        "dissabte",
3606        "diumenge",
3607    ]
3608    day_abbreviations = [
3609        "",
3610        "dl.",
3611        "dt.",
3612        "dc.",
3613        "dj.",
3614        "dv.",
3615        "ds.",
3616        "dg.",
3617    ]
3618
3619
3620class BasqueLocale(Locale):
3621    names = ["eu", "eu-eu"]
3622    past = "duela {0}"
3623    future = "{0}"  # I don't know what's the right phrase in Basque for the future.
3624
3625    timeframes = {
3626        "now": "Orain",
3627        "second": "segundo bat",
3628        "seconds": "{0} segundu",
3629        "minute": "minutu bat",
3630        "minutes": "{0} minutu",
3631        "hour": "ordu bat",
3632        "hours": "{0} ordu",
3633        "day": "egun bat",
3634        "days": "{0} egun",
3635        "month": "hilabete bat",
3636        "months": "{0} hilabet",
3637        "year": "urte bat",
3638        "years": "{0} urte",
3639    }
3640
3641    month_names = [
3642        "",
3643        "urtarrilak",
3644        "otsailak",
3645        "martxoak",
3646        "apirilak",
3647        "maiatzak",
3648        "ekainak",
3649        "uztailak",
3650        "abuztuak",
3651        "irailak",
3652        "urriak",
3653        "azaroak",
3654        "abenduak",
3655    ]
3656    month_abbreviations = [
3657        "",
3658        "urt",
3659        "ots",
3660        "mar",
3661        "api",
3662        "mai",
3663        "eka",
3664        "uzt",
3665        "abu",
3666        "ira",
3667        "urr",
3668        "aza",
3669        "abe",
3670    ]
3671    day_names = [
3672        "",
3673        "astelehena",
3674        "asteartea",
3675        "asteazkena",
3676        "osteguna",
3677        "ostirala",
3678        "larunbata",
3679        "igandea",
3680    ]
3681    day_abbreviations = ["", "al", "ar", "az", "og", "ol", "lr", "ig"]
3682
3683
3684class HungarianLocale(Locale):
3685
3686    names = ["hu", "hu-hu"]
3687
3688    past = "{0} ezelőtt"
3689    future = "{0} múlva"
3690
3691    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
3692        "now": "éppen most",
3693        "second": {"past": "egy második", "future": "egy második"},
3694        "seconds": {"past": "{0} másodpercekkel", "future": "{0} pár másodperc"},
3695        "minute": {"past": "egy perccel", "future": "egy perc"},
3696        "minutes": {"past": "{0} perccel", "future": "{0} perc"},
3697        "hour": {"past": "egy órával", "future": "egy óra"},
3698        "hours": {"past": "{0} órával", "future": "{0} óra"},
3699        "day": {"past": "egy nappal", "future": "egy nap"},
3700        "days": {"past": "{0} nappal", "future": "{0} nap"},
3701        "month": {"past": "egy hónappal", "future": "egy hónap"},
3702        "months": {"past": "{0} hónappal", "future": "{0} hónap"},
3703        "year": {"past": "egy évvel", "future": "egy év"},
3704        "years": {"past": "{0} évvel", "future": "{0} év"},
3705    }
3706
3707    month_names = [
3708        "",
3709        "január",
3710        "február",
3711        "március",
3712        "április",
3713        "május",
3714        "június",
3715        "július",
3716        "augusztus",
3717        "szeptember",
3718        "október",
3719        "november",
3720        "december",
3721    ]
3722    month_abbreviations = [
3723        "",
3724        "jan",
3725        "febr",
3726        "márc",
3727        "ápr",
3728        "máj",
3729        "jún",
3730        "júl",
3731        "aug",
3732        "szept",
3733        "okt",
3734        "nov",
3735        "dec",
3736    ]
3737
3738    day_names = [
3739        "",
3740        "hétfő",
3741        "kedd",
3742        "szerda",
3743        "csütörtök",
3744        "péntek",
3745        "szombat",
3746        "vasárnap",
3747    ]
3748    day_abbreviations = ["", "hét", "kedd", "szer", "csüt", "pént", "szom", "vas"]
3749
3750    meridians = {"am": "de", "pm": "du", "AM": "DE", "PM": "DU"}
3751
3752    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
3753        form = self.timeframes[timeframe]
3754
3755        if isinstance(form, Mapping):
3756            if delta > 0:
3757                form = form["future"]
3758            else:
3759                form = form["past"]
3760
3761        return form.format(abs(delta))
3762
3763
3764class EsperantoLocale(Locale):
3765    names = ["eo", "eo-xx"]
3766    past = "antaŭ {0}"
3767    future = "post {0}"
3768
3769    timeframes = {
3770        "now": "nun",
3771        "second": "sekundo",
3772        "seconds": "{0} kelkaj sekundoj",
3773        "minute": "unu minuto",
3774        "minutes": "{0} minutoj",
3775        "hour": "un horo",
3776        "hours": "{0} horoj",
3777        "day": "unu tago",
3778        "days": "{0} tagoj",
3779        "month": "unu monato",
3780        "months": "{0} monatoj",
3781        "year": "unu jaro",
3782        "years": "{0} jaroj",
3783    }
3784
3785    month_names = [
3786        "",
3787        "januaro",
3788        "februaro",
3789        "marto",
3790        "aprilo",
3791        "majo",
3792        "junio",
3793        "julio",
3794        "aŭgusto",
3795        "septembro",
3796        "oktobro",
3797        "novembro",
3798        "decembro",
3799    ]
3800    month_abbreviations = [
3801        "",
3802        "jan",
3803        "feb",
3804        "mar",
3805        "apr",
3806        "maj",
3807        "jun",
3808        "jul",
3809        "aŭg",
3810        "sep",
3811        "okt",
3812        "nov",
3813        "dec",
3814    ]
3815
3816    day_names = [
3817        "",
3818        "lundo",
3819        "mardo",
3820        "merkredo",
3821        "ĵaŭdo",
3822        "vendredo",
3823        "sabato",
3824        "dimanĉo",
3825    ]
3826    day_abbreviations = ["", "lun", "mar", "mer", "ĵaŭ", "ven", "sab", "dim"]
3827
3828    meridians = {"am": "atm", "pm": "ptm", "AM": "ATM", "PM": "PTM"}
3829
3830    ordinal_day_re = r"((?P<value>[1-3]?[0-9](?=a))a)"
3831
3832    def _ordinal_number(self, n: int) -> str:
3833        return f"{n}a"
3834
3835
3836class ThaiLocale(Locale):
3837
3838    names = ["th", "th-th"]
3839
3840    past = "{0} ที่ผ่านมา"
3841    future = "ในอีก {0}"
3842
3843    timeframes = {
3844        "now": "ขณะนี้",
3845        "second": "วินาที",
3846        "seconds": "{0} ไม่กี่วินาที",
3847        "minute": "1 นาที",
3848        "minutes": "{0} นาที",
3849        "hour": "1 ชั่วโมง",
3850        "hours": "{0} ชั่วโมง",
3851        "day": "1 วัน",
3852        "days": "{0} วัน",
3853        "month": "1 เดือน",
3854        "months": "{0} เดือน",
3855        "year": "1 ปี",
3856        "years": "{0} ปี",
3857    }
3858
3859    month_names = [
3860        "",
3861        "มกราคม",
3862        "กุมภาพันธ์",
3863        "มีนาคม",
3864        "เมษายน",
3865        "พฤษภาคม",
3866        "มิถุนายน",
3867        "กรกฎาคม",
3868        "สิงหาคม",
3869        "กันยายน",
3870        "ตุลาคม",
3871        "พฤศจิกายน",
3872        "ธันวาคม",
3873    ]
3874    month_abbreviations = [
3875        "",
3876        "ม.ค.",
3877        "ก.พ.",
3878        "มี.ค.",
3879        "เม.ย.",
3880        "พ.ค.",
3881        "มิ.ย.",
3882        "ก.ค.",
3883        "ส.ค.",
3884        "ก.ย.",
3885        "ต.ค.",
3886        "พ.ย.",
3887        "ธ.ค.",
3888    ]
3889
3890    day_names = ["", "จันทร์", "อังคาร", "พุธ", "พฤหัสบดี", "ศุกร์", "เสาร์", "อาทิตย์"]
3891    day_abbreviations = ["", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"]
3892
3893    meridians = {"am": "am", "pm": "pm", "AM": "AM", "PM": "PM"}
3894
3895    BE_OFFSET = 543
3896
3897    def year_full(self, year: int) -> str:
3898        """Thai always use Buddhist Era (BE) which is CE + 543"""
3899        year += self.BE_OFFSET
3900        return f"{year:04d}"
3901
3902    def year_abbreviation(self, year: int) -> str:
3903        """Thai always use Buddhist Era (BE) which is CE + 543"""
3904        year += self.BE_OFFSET
3905        return f"{year:04d}"[2:]
3906
3907    def _format_relative(
3908        self,
3909        humanized: str,
3910        timeframe: TimeFrameLiteral,
3911        delta: Union[float, int],
3912    ) -> str:
3913        """Thai normally doesn't have any space between words"""
3914        if timeframe == "now":
3915            return humanized
3916
3917        direction = self.past if delta < 0 else self.future
3918        relative_string = direction.format(humanized)
3919
3920        if timeframe == "seconds":
3921            relative_string = relative_string.replace(" ", "")
3922
3923        return relative_string
3924
3925
3926class BengaliLocale(Locale):
3927
3928    names = ["bn", "bn-bd", "bn-in"]
3929
3930    past = "{0} আগে"
3931    future = "{0} পরে"
3932
3933    timeframes = {
3934        "now": "এখন",
3935        "second": "একটি দ্বিতীয়",
3936        "seconds": "{0} সেকেন্ড",
3937        "minute": "এক মিনিট",
3938        "minutes": "{0} মিনিট",
3939        "hour": "এক ঘণ্টা",
3940        "hours": "{0} ঘণ্টা",
3941        "day": "এক দিন",
3942        "days": "{0} দিন",
3943        "month": "এক মাস",
3944        "months": "{0} মাস ",
3945        "year": "এক বছর",
3946        "years": "{0} বছর",
3947    }
3948
3949    meridians = {"am": "সকাল", "pm": "বিকাল", "AM": "সকাল", "PM": "বিকাল"}
3950
3951    month_names = [
3952        "",
3953        "জানুয়ারি",
3954        "ফেব্রুয়ারি",
3955        "মার্চ",
3956        "এপ্রিল",
3957        "মে",
3958        "জুন",
3959        "জুলাই",
3960        "আগস্ট",
3961        "সেপ্টেম্বর",
3962        "অক্টোবর",
3963        "নভেম্বর",
3964        "ডিসেম্বর",
3965    ]
3966    month_abbreviations = [
3967        "",
3968        "জানু",
3969        "ফেব",
3970        "মার্চ",
3971        "এপ্রি",
3972        "মে",
3973        "জুন",
3974        "জুল",
3975        "অগা",
3976        "সেপ্ট",
3977        "অক্টো",
3978        "নভে",
3979        "ডিসে",
3980    ]
3981
3982    day_names = [
3983        "",
3984        "সোমবার",
3985        "মঙ্গলবার",
3986        "বুধবার",
3987        "বৃহস্পতিবার",
3988        "শুক্রবার",
3989        "শনিবার",
3990        "রবিবার",
3991    ]
3992    day_abbreviations = ["", "সোম", "মঙ্গল", "বুধ", "বৃহঃ", "শুক্র", "শনি", "রবি"]
3993
3994    def _ordinal_number(self, n: int) -> str:
3995        if n > 10 or n == 0:
3996            return f"{n}তম"
3997        if n in [1, 5, 7, 8, 9, 10]:
3998            return f"{n}ম"
3999        if n in [2, 3]:
4000            return f"{n}য়"
4001        if n == 4:
4002            return f"{n}র্থ"
4003        if n == 6:
4004            return f"{n}ষ্ঠ"
4005
4006
4007class RomanshLocale(Locale):
4008
4009    names = ["rm", "rm-ch"]
4010
4011    past = "avant {0}"
4012    future = "en {0}"
4013
4014    timeframes = {
4015        "now": "en quest mument",
4016        "second": "in secunda",
4017        "seconds": "{0} secundas",
4018        "minute": "ina minuta",
4019        "minutes": "{0} minutas",
4020        "hour": "in'ura",
4021        "hours": "{0} ura",
4022        "day": "in di",
4023        "days": "{0} dis",
4024        "month": "in mais",
4025        "months": "{0} mais",
4026        "year": "in onn",
4027        "years": "{0} onns",
4028    }
4029
4030    month_names = [
4031        "",
4032        "schaner",
4033        "favrer",
4034        "mars",
4035        "avrigl",
4036        "matg",
4037        "zercladur",
4038        "fanadur",
4039        "avust",
4040        "settember",
4041        "october",
4042        "november",
4043        "december",
4044    ]
4045
4046    month_abbreviations = [
4047        "",
4048        "schan",
4049        "fav",
4050        "mars",
4051        "avr",
4052        "matg",
4053        "zer",
4054        "fan",
4055        "avu",
4056        "set",
4057        "oct",
4058        "nov",
4059        "dec",
4060    ]
4061
4062    day_names = [
4063        "",
4064        "glindesdi",
4065        "mardi",
4066        "mesemna",
4067        "gievgia",
4068        "venderdi",
4069        "sonda",
4070        "dumengia",
4071    ]
4072
4073    day_abbreviations = ["", "gli", "ma", "me", "gie", "ve", "so", "du"]
4074
4075
4076class RomanianLocale(Locale):
4077    names = ["ro", "ro-ro"]
4078
4079    past = "{0} în urmă"
4080    future = "peste {0}"
4081    and_word = "și"
4082
4083    timeframes = {
4084        "now": "acum",
4085        "second": "o secunda",
4086        "seconds": "{0} câteva secunde",
4087        "minute": "un minut",
4088        "minutes": "{0} minute",
4089        "hour": "o oră",
4090        "hours": "{0} ore",
4091        "day": "o zi",
4092        "days": "{0} zile",
4093        "month": "o lună",
4094        "months": "{0} luni",
4095        "year": "un an",
4096        "years": "{0} ani",
4097    }
4098
4099    month_names = [
4100        "",
4101        "ianuarie",
4102        "februarie",
4103        "martie",
4104        "aprilie",
4105        "mai",
4106        "iunie",
4107        "iulie",
4108        "august",
4109        "septembrie",
4110        "octombrie",
4111        "noiembrie",
4112        "decembrie",
4113    ]
4114    month_abbreviations = [
4115        "",
4116        "ian",
4117        "febr",
4118        "mart",
4119        "apr",
4120        "mai",
4121        "iun",
4122        "iul",
4123        "aug",
4124        "sept",
4125        "oct",
4126        "nov",
4127        "dec",
4128    ]
4129
4130    day_names = [
4131        "",
4132        "luni",
4133        "marți",
4134        "miercuri",
4135        "joi",
4136        "vineri",
4137        "sâmbătă",
4138        "duminică",
4139    ]
4140    day_abbreviations = ["", "Lun", "Mar", "Mie", "Joi", "Vin", "Sâm", "Dum"]
4141
4142
4143class SlovenianLocale(Locale):
4144    names = ["sl", "sl-si"]
4145
4146    past = "pred {0}"
4147    future = "čez {0}"
4148    and_word = "in"
4149
4150    timeframes = {
4151        "now": "zdaj",
4152        "second": "sekundo",
4153        "seconds": "{0} sekund",
4154        "minute": "minuta",
4155        "minutes": "{0} minutami",
4156        "hour": "uro",
4157        "hours": "{0} ur",
4158        "day": "dan",
4159        "days": "{0} dni",
4160        "month": "mesec",
4161        "months": "{0} mesecev",
4162        "year": "leto",
4163        "years": "{0} let",
4164    }
4165
4166    meridians = {"am": "", "pm": "", "AM": "", "PM": ""}
4167
4168    month_names = [
4169        "",
4170        "Januar",
4171        "Februar",
4172        "Marec",
4173        "April",
4174        "Maj",
4175        "Junij",
4176        "Julij",
4177        "Avgust",
4178        "September",
4179        "Oktober",
4180        "November",
4181        "December",
4182    ]
4183
4184    month_abbreviations = [
4185        "",
4186        "Jan",
4187        "Feb",
4188        "Mar",
4189        "Apr",
4190        "Maj",
4191        "Jun",
4192        "Jul",
4193        "Avg",
4194        "Sep",
4195        "Okt",
4196        "Nov",
4197        "Dec",
4198    ]
4199
4200    day_names = [
4201        "",
4202        "Ponedeljek",
4203        "Torek",
4204        "Sreda",
4205        "Četrtek",
4206        "Petek",
4207        "Sobota",
4208        "Nedelja",
4209    ]
4210
4211    day_abbreviations = ["", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob", "Ned"]
4212
4213
4214class IndonesianLocale(Locale):
4215
4216    names = ["id", "id-id"]
4217
4218    past = "{0} yang lalu"
4219    future = "dalam {0}"
4220    and_word = "dan"
4221
4222    timeframes = {
4223        "now": "baru saja",
4224        "second": "1 sebentar",
4225        "seconds": "{0} detik",
4226        "minute": "1 menit",
4227        "minutes": "{0} menit",
4228        "hour": "1 jam",
4229        "hours": "{0} jam",
4230        "day": "1 hari",
4231        "days": "{0} hari",
4232        "month": "1 bulan",
4233        "months": "{0} bulan",
4234        "year": "1 tahun",
4235        "years": "{0} tahun",
4236    }
4237
4238    meridians = {"am": "", "pm": "", "AM": "", "PM": ""}
4239
4240    month_names = [
4241        "",
4242        "Januari",
4243        "Februari",
4244        "Maret",
4245        "April",
4246        "Mei",
4247        "Juni",
4248        "Juli",
4249        "Agustus",
4250        "September",
4251        "Oktober",
4252        "November",
4253        "Desember",
4254    ]
4255
4256    month_abbreviations = [
4257        "",
4258        "Jan",
4259        "Feb",
4260        "Mar",
4261        "Apr",
4262        "Mei",
4263        "Jun",
4264        "Jul",
4265        "Ags",
4266        "Sept",
4267        "Okt",
4268        "Nov",
4269        "Des",
4270    ]
4271
4272    day_names = ["", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"]
4273
4274    day_abbreviations = [
4275        "",
4276        "Senin",
4277        "Selasa",
4278        "Rabu",
4279        "Kamis",
4280        "Jumat",
4281        "Sabtu",
4282        "Minggu",
4283    ]
4284
4285
4286class NepaliLocale(Locale):
4287    names = ["ne", "ne-np"]
4288
4289    past = "{0} पहिले"
4290    future = "{0} पछी"
4291
4292    timeframes = {
4293        "now": "अहिले",
4294        "second": "एक सेकेन्ड",
4295        "seconds": "{0} सेकण्ड",
4296        "minute": "मिनेट",
4297        "minutes": "{0} मिनेट",
4298        "hour": "एक घण्टा",
4299        "hours": "{0} घण्टा",
4300        "day": "एक दिन",
4301        "days": "{0} दिन",
4302        "month": "एक महिना",
4303        "months": "{0} महिना",
4304        "year": "एक बर्ष",
4305        "years": "{0} बर्ष",
4306    }
4307
4308    meridians = {"am": "पूर्वाह्न", "pm": "अपरान्ह", "AM": "पूर्वाह्न", "PM": "अपरान्ह"}
4309
4310    month_names = [
4311        "",
4312        "जनवरी",
4313        "फेब्रुअरी",
4314        "मार्च",
4315        "एप्रील",
4316        "मे",
4317        "जुन",
4318        "जुलाई",
4319        "अगष्ट",
4320        "सेप्टेम्बर",
4321        "अक्टोबर",
4322        "नोवेम्बर",
4323        "डिसेम्बर",
4324    ]
4325    month_abbreviations = [
4326        "",
4327        "जन",
4328        "फेब",
4329        "मार्च",
4330        "एप्रील",
4331        "मे",
4332        "जुन",
4333        "जुलाई",
4334        "अग",
4335        "सेप",
4336        "अक्ट",
4337        "नोव",
4338        "डिस",
4339    ]
4340
4341    day_names = [
4342        "",
4343        "सोमवार",
4344        "मंगलवार",
4345        "बुधवार",
4346        "बिहिवार",
4347        "शुक्रवार",
4348        "शनिवार",
4349        "आइतवार",
4350    ]
4351
4352    day_abbreviations = ["", "सोम", "मंगल", "बुध", "बिहि", "शुक्र", "शनि", "आइत"]
4353
4354
4355class EstonianLocale(Locale):
4356    names = ["ee", "et"]
4357
4358    past = "{0} tagasi"
4359    future = "{0} pärast"
4360    and_word = "ja"
4361
4362    timeframes: ClassVar[Mapping[TimeFrameLiteral, Mapping[str, str]]] = {
4363        "now": {"past": "just nüüd", "future": "just nüüd"},
4364        "second": {"past": "üks sekund", "future": "ühe sekundi"},
4365        "seconds": {"past": "{0} sekundit", "future": "{0} sekundi"},
4366        "minute": {"past": "üks minut", "future": "ühe minuti"},
4367        "minutes": {"past": "{0} minutit", "future": "{0} minuti"},
4368        "hour": {"past": "tund aega", "future": "tunni aja"},
4369        "hours": {"past": "{0} tundi", "future": "{0} tunni"},
4370        "day": {"past": "üks päev", "future": "ühe päeva"},
4371        "days": {"past": "{0} päeva", "future": "{0} päeva"},
4372        "month": {"past": "üks kuu", "future": "ühe kuu"},
4373        "months": {"past": "{0} kuud", "future": "{0} kuu"},
4374        "year": {"past": "üks aasta", "future": "ühe aasta"},
4375        "years": {"past": "{0} aastat", "future": "{0} aasta"},
4376    }
4377
4378    month_names = [
4379        "",
4380        "Jaanuar",
4381        "Veebruar",
4382        "Märts",
4383        "Aprill",
4384        "Mai",
4385        "Juuni",
4386        "Juuli",
4387        "August",
4388        "September",
4389        "Oktoober",
4390        "November",
4391        "Detsember",
4392    ]
4393    month_abbreviations = [
4394        "",
4395        "Jan",
4396        "Veb",
4397        "Mär",
4398        "Apr",
4399        "Mai",
4400        "Jun",
4401        "Jul",
4402        "Aug",
4403        "Sep",
4404        "Okt",
4405        "Nov",
4406        "Dets",
4407    ]
4408
4409    day_names = [
4410        "",
4411        "Esmaspäev",
4412        "Teisipäev",
4413        "Kolmapäev",
4414        "Neljapäev",
4415        "Reede",
4416        "Laupäev",
4417        "Pühapäev",
4418    ]
4419    day_abbreviations = ["", "Esm", "Teis", "Kolm", "Nelj", "Re", "Lau", "Püh"]
4420
4421    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
4422        form = self.timeframes[timeframe]
4423        if delta > 0:
4424            _form = form["future"]
4425        else:
4426            _form = form["past"]
4427        return _form.format(abs(delta))
4428
4429
4430class LatvianLocale(Locale):
4431
4432    names = ["lv", "lv-lv"]
4433
4434    past = "pirms {0}"
4435    future = "pēc {0}"
4436    and_word = "un"
4437
4438    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
4439        "now": "tagad",
4440        "second": "sekundes",
4441        "seconds": "{0} sekundēm",
4442        "minute": "minūtes",
4443        "minutes": "{0} minūtēm",
4444        "hour": "stundas",
4445        "hours": "{0} stundām",
4446        "day": "dienas",
4447        "days": "{0} dienām",
4448        "week": "nedēļas",
4449        "weeks": "{0} nedēļām",
4450        "month": "mēneša",
4451        "months": "{0} mēnešiem",
4452        "year": "gada",
4453        "years": "{0} gadiem",
4454    }
4455
4456    month_names = [
4457        "",
4458        "janvāris",
4459        "februāris",
4460        "marts",
4461        "aprīlis",
4462        "maijs",
4463        "jūnijs",
4464        "jūlijs",
4465        "augusts",
4466        "septembris",
4467        "oktobris",
4468        "novembris",
4469        "decembris",
4470    ]
4471
4472    month_abbreviations = [
4473        "",
4474        "jan",
4475        "feb",
4476        "marts",
4477        "apr",
4478        "maijs",
4479        "jūnijs",
4480        "jūlijs",
4481        "aug",
4482        "sept",
4483        "okt",
4484        "nov",
4485        "dec",
4486    ]
4487
4488    day_names = [
4489        "",
4490        "pirmdiena",
4491        "otrdiena",
4492        "trešdiena",
4493        "ceturtdiena",
4494        "piektdiena",
4495        "sestdiena",
4496        "svētdiena",
4497    ]
4498
4499    day_abbreviations = [
4500        "",
4501        "pi",
4502        "ot",
4503        "tr",
4504        "ce",
4505        "pi",
4506        "se",
4507        "sv",
4508    ]
4509
4510
4511class SwahiliLocale(Locale):
4512
4513    names = [
4514        "sw",
4515        "sw-ke",
4516        "sw-tz",
4517    ]
4518
4519    past = "{0} iliyopita"
4520    future = "muda wa {0}"
4521    and_word = "na"
4522
4523    timeframes = {
4524        "now": "sasa hivi",
4525        "second": "sekunde",
4526        "seconds": "sekunde {0}",
4527        "minute": "dakika moja",
4528        "minutes": "dakika {0}",
4529        "hour": "saa moja",
4530        "hours": "saa {0}",
4531        "day": "siku moja",
4532        "days": "siku {0}",
4533        "week": "wiki moja",
4534        "weeks": "wiki {0}",
4535        "month": "mwezi moja",
4536        "months": "miezi {0}",
4537        "year": "mwaka moja",
4538        "years": "miaka {0}",
4539    }
4540
4541    meridians = {"am": "asu", "pm": "mch", "AM": "ASU", "PM": "MCH"}
4542
4543    month_names = [
4544        "",
4545        "Januari",
4546        "Februari",
4547        "Machi",
4548        "Aprili",
4549        "Mei",
4550        "Juni",
4551        "Julai",
4552        "Agosti",
4553        "Septemba",
4554        "Oktoba",
4555        "Novemba",
4556        "Desemba",
4557    ]
4558    month_abbreviations = [
4559        "",
4560        "Jan",
4561        "Feb",
4562        "Mac",
4563        "Apr",
4564        "Mei",
4565        "Jun",
4566        "Jul",
4567        "Ago",
4568        "Sep",
4569        "Okt",
4570        "Nov",
4571        "Des",
4572    ]
4573
4574    day_names = [
4575        "",
4576        "Jumatatu",
4577        "Jumanne",
4578        "Jumatano",
4579        "Alhamisi",
4580        "Ijumaa",
4581        "Jumamosi",
4582        "Jumapili",
4583    ]
4584    day_abbreviations = [
4585        "",
4586        "Jumatatu",
4587        "Jumanne",
4588        "Jumatano",
4589        "Alhamisi",
4590        "Ijumaa",
4591        "Jumamosi",
4592        "Jumapili",
4593    ]
4594
4595
4596class CroatianLocale(Locale):
4597
4598    names = ["hr", "hr-hr"]
4599
4600    past = "prije {0}"
4601    future = "za {0}"
4602    and_word = "i"
4603
4604    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
4605        "now": "upravo sad",
4606        "second": "sekundu",
4607        "seconds": {"double": "{0} sekunde", "higher": "{0} sekundi"},
4608        "minute": "minutu",
4609        "minutes": {"double": "{0} minute", "higher": "{0} minuta"},
4610        "hour": "sat",
4611        "hours": {"double": "{0} sata", "higher": "{0} sati"},
4612        "day": "jedan dan",
4613        "days": {"double": "{0} dana", "higher": "{0} dana"},
4614        "week": "tjedan",
4615        "weeks": {"double": "{0} tjedna", "higher": "{0} tjedana"},
4616        "month": "mjesec",
4617        "months": {"double": "{0} mjeseca", "higher": "{0} mjeseci"},
4618        "year": "godinu",
4619        "years": {"double": "{0} godine", "higher": "{0} godina"},
4620    }
4621
4622    month_names = [
4623        "",
4624        "siječanj",
4625        "veljača",
4626        "ožujak",
4627        "travanj",
4628        "svibanj",
4629        "lipanj",
4630        "srpanj",
4631        "kolovoz",
4632        "rujan",
4633        "listopad",
4634        "studeni",
4635        "prosinac",
4636    ]
4637
4638    month_abbreviations = [
4639        "",
4640        "siječ",
4641        "velj",
4642        "ožuj",
4643        "trav",
4644        "svib",
4645        "lip",
4646        "srp",
4647        "kol",
4648        "ruj",
4649        "list",
4650        "stud",
4651        "pros",
4652    ]
4653
4654    day_names = [
4655        "",
4656        "ponedjeljak",
4657        "utorak",
4658        "srijeda",
4659        "četvrtak",
4660        "petak",
4661        "subota",
4662        "nedjelja",
4663    ]
4664
4665    day_abbreviations = [
4666        "",
4667        "po",
4668        "ut",
4669        "sr",
4670        "če",
4671        "pe",
4672        "su",
4673        "ne",
4674    ]
4675
4676    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
4677        form = self.timeframes[timeframe]
4678        delta = abs(delta)
4679        if isinstance(form, Mapping):
4680            if 1 < delta <= 4:
4681                form = form["double"]
4682            else:
4683                form = form["higher"]
4684
4685        return form.format(delta)
4686
4687
4688class LatinLocale(Locale):
4689
4690    names = ["la", "la-va"]
4691
4692    past = "ante {0}"
4693    future = "in {0}"
4694    and_word = "et"
4695
4696    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
4697        "now": "nunc",
4698        "second": "secundum",
4699        "seconds": "{0} secundis",
4700        "minute": "minutam",
4701        "minutes": "{0} minutis",
4702        "hour": "horam",
4703        "hours": "{0} horas",
4704        "day": "diem",
4705        "days": "{0} dies",
4706        "week": "hebdomadem",
4707        "weeks": "{0} hebdomades",
4708        "month": "mensem",
4709        "months": "{0} mensis",
4710        "year": "annum",
4711        "years": "{0} annos",
4712    }
4713
4714    month_names = [
4715        "",
4716        "Ianuarius",
4717        "Februarius",
4718        "Martius",
4719        "Aprilis",
4720        "Maius",
4721        "Iunius",
4722        "Iulius",
4723        "Augustus",
4724        "September",
4725        "October",
4726        "November",
4727        "December",
4728    ]
4729
4730    month_abbreviations = [
4731        "",
4732        "Ian",
4733        "Febr",
4734        "Mart",
4735        "Apr",
4736        "Mai",
4737        "Iun",
4738        "Iul",
4739        "Aug",
4740        "Sept",
4741        "Oct",
4742        "Nov",
4743        "Dec",
4744    ]
4745
4746    day_names = [
4747        "",
4748        "dies Lunae",
4749        "dies Martis",
4750        "dies Mercurii",
4751        "dies Iovis",
4752        "dies Veneris",
4753        "dies Saturni",
4754        "dies Solis",
4755    ]
4756
4757    day_abbreviations = [
4758        "",
4759        "dies Lunae",
4760        "dies Martis",
4761        "dies Mercurii",
4762        "dies Iovis",
4763        "dies Veneris",
4764        "dies Saturni",
4765        "dies Solis",
4766    ]
4767
4768
4769class LithuanianLocale(Locale):
4770
4771    names = ["lt", "lt-lt"]
4772
4773    past = "prieš {0}"
4774    future = "po {0}"
4775    and_word = "ir"
4776
4777    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
4778        "now": "dabar",
4779        "second": "sekundės",
4780        "seconds": "{0} sekundžių",
4781        "minute": "minutės",
4782        "minutes": "{0} minučių",
4783        "hour": "valandos",
4784        "hours": "{0} valandų",
4785        "day": "dieną",
4786        "days": "{0} dienų",
4787        "week": "savaitės",
4788        "weeks": "{0} savaičių",
4789        "month": "mėnesio",
4790        "months": "{0} mėnesių",
4791        "year": "metų",
4792        "years": "{0} metų",
4793    }
4794
4795    month_names = [
4796        "",
4797        "sausis",
4798        "vasaris",
4799        "kovas",
4800        "balandis",
4801        "gegužė",
4802        "birželis",
4803        "liepa",
4804        "rugpjūtis",
4805        "rugsėjis",
4806        "spalis",
4807        "lapkritis",
4808        "gruodis",
4809    ]
4810
4811    month_abbreviations = [
4812        "",
4813        "saus",
4814        "vas",
4815        "kovas",
4816        "bal",
4817        "geg",
4818        "birž",
4819        "liepa",
4820        "rugp",
4821        "rugs",
4822        "spalis",
4823        "lapkr",
4824        "gr",
4825    ]
4826
4827    day_names = [
4828        "",
4829        "pirmadienis",
4830        "antradienis",
4831        "trečiadienis",
4832        "ketvirtadienis",
4833        "penktadienis",
4834        "šeštadienis",
4835        "sekmadienis",
4836    ]
4837
4838    day_abbreviations = [
4839        "",
4840        "pi",
4841        "an",
4842        "tr",
4843        "ke",
4844        "pe",
4845        "še",
4846        "se",
4847    ]
4848
4849
4850class MalayLocale(Locale):
4851
4852    names = ["ms", "ms-my", "ms-bn"]
4853
4854    past = "{0} yang lalu"
4855    future = "dalam {0}"
4856    and_word = "dan"
4857
4858    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
4859        "now": "sekarang",
4860        "second": "saat",
4861        "seconds": "{0} saat",
4862        "minute": "minit",
4863        "minutes": "{0} minit",
4864        "hour": "jam",
4865        "hours": "{0} jam",
4866        "day": "hari",
4867        "days": "{0} hari",
4868        "week": "minggu",
4869        "weeks": "{0} minggu",
4870        "month": "bulan",
4871        "months": "{0} bulan",
4872        "year": "tahun",
4873        "years": "{0} tahun",
4874    }
4875
4876    month_names = [
4877        "",
4878        "Januari",
4879        "Februari",
4880        "Mac",
4881        "April",
4882        "Mei",
4883        "Jun",
4884        "Julai",
4885        "Ogos",
4886        "September",
4887        "Oktober",
4888        "November",
4889        "Disember",
4890    ]
4891
4892    month_abbreviations = [
4893        "",
4894        "Jan.",
4895        "Feb.",
4896        "Mac",
4897        "Apr.",
4898        "Mei",
4899        "Jun",
4900        "Julai",
4901        "Og.",
4902        "Sept.",
4903        "Okt.",
4904        "Nov.",
4905        "Dis.",
4906    ]
4907
4908    day_names = [
4909        "",
4910        "Isnin",
4911        "Selasa",
4912        "Rabu",
4913        "Khamis",
4914        "Jumaat",
4915        "Sabtu",
4916        "Ahad",
4917    ]
4918
4919    day_abbreviations = [
4920        "",
4921        "Isnin",
4922        "Selasa",
4923        "Rabu",
4924        "Khamis",
4925        "Jumaat",
4926        "Sabtu",
4927        "Ahad",
4928    ]
4929
4930
4931class MalteseLocale(Locale):
4932
4933    names = ["mt", "mt-mt"]
4934
4935    past = "{0} ilu"
4936    future = "fi {0}"
4937    and_word = "u"
4938
4939    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
4940        "now": "issa",
4941        "second": "sekonda",
4942        "seconds": "{0} sekondi",
4943        "minute": "minuta",
4944        "minutes": "{0} minuti",
4945        "hour": "siegħa",
4946        "hours": {"dual": "{0} sagħtejn", "plural": "{0} sigħat"},
4947        "day": "jum",
4948        "days": {"dual": "{0} jumejn", "plural": "{0} ijiem"},
4949        "week": "ġimgħa",
4950        "weeks": {"dual": "{0} ġimagħtejn", "plural": "{0} ġimgħat"},
4951        "month": "xahar",
4952        "months": {"dual": "{0} xahrejn", "plural": "{0} xhur"},
4953        "year": "sena",
4954        "years": {"dual": "{0} sentejn", "plural": "{0} snin"},
4955    }
4956
4957    month_names = [
4958        "",
4959        "Jannar",
4960        "Frar",
4961        "Marzu",
4962        "April",
4963        "Mejju",
4964        "Ġunju",
4965        "Lulju",
4966        "Awwissu",
4967        "Settembru",
4968        "Ottubru",
4969        "Novembru",
4970        "Diċembru",
4971    ]
4972
4973    month_abbreviations = [
4974        "",
4975        "Jan",
4976        "Fr",
4977        "Mar",
4978        "Apr",
4979        "Mejju",
4980        "Ġun",
4981        "Lul",
4982        "Aw",
4983        "Sett",
4984        "Ott",
4985        "Nov",
4986        "Diċ",
4987    ]
4988
4989    day_names = [
4990        "",
4991        "It-Tnejn",
4992        "It-Tlieta",
4993        "L-Erbgħa",
4994        "Il-Ħamis",
4995        "Il-Ġimgħa",
4996        "Is-Sibt",
4997        "Il-Ħadd",
4998    ]
4999
5000    day_abbreviations = [
5001        "",
5002        "T",
5003        "TL",
5004        "E",
5005        "Ħ",
5006        "Ġ",
5007        "S",
5008        "Ħ",
5009    ]
5010
5011    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
5012        form = self.timeframes[timeframe]
5013        delta = abs(delta)
5014        if isinstance(form, Mapping):
5015            if delta == 2:
5016                form = form["dual"]
5017            else:
5018                form = form["plural"]
5019
5020        return form.format(delta)
5021
5022
5023class SamiLocale(Locale):
5024
5025    names = ["se", "se-fi", "se-no", "se-se"]
5026
5027    past = "{0} dassái"
5028    future = "{0} "  # NOTE: couldn't find preposition for Sami here, none needed?
5029
5030    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
5031        "now": "dál",
5032        "second": "sekunda",
5033        "seconds": "{0} sekundda",
5034        "minute": "minuhta",
5035        "minutes": "{0} minuhta",
5036        "hour": "diimmu",
5037        "hours": "{0} diimmu",
5038        "day": "beaivvi",
5039        "days": "{0} beaivvi",
5040        "week": "vahku",
5041        "weeks": "{0} vahku",
5042        "month": "mánu",
5043        "months": "{0} mánu",
5044        "year": "jagi",
5045        "years": "{0} jagi",
5046    }
5047
5048    month_names = [
5049        "",
5050        "Ođđajagimánnu",
5051        "Guovvamánnu",
5052        "Njukčamánnu",
5053        "Cuoŋománnu",
5054        "Miessemánnu",
5055        "Geassemánnu",
5056        "Suoidnemánnu",
5057        "Borgemánnu",
5058        "Čakčamánnu",
5059        "Golggotmánnu",
5060        "Skábmamánnu",
5061        "Juovlamánnu",
5062    ]
5063
5064    month_abbreviations = [
5065        "",
5066        "Ođđajagimánnu",
5067        "Guovvamánnu",
5068        "Njukčamánnu",
5069        "Cuoŋománnu",
5070        "Miessemánnu",
5071        "Geassemánnu",
5072        "Suoidnemánnu",
5073        "Borgemánnu",
5074        "Čakčamánnu",
5075        "Golggotmánnu",
5076        "Skábmamánnu",
5077        "Juovlamánnu",
5078    ]
5079
5080    day_names = [
5081        "",
5082        "Mánnodat",
5083        "Disdat",
5084        "Gaskavahkku",
5085        "Duorastat",
5086        "Bearjadat",
5087        "Lávvordat",
5088        "Sotnabeaivi",
5089    ]
5090
5091    day_abbreviations = [
5092        "",
5093        "Mánnodat",
5094        "Disdat",
5095        "Gaskavahkku",
5096        "Duorastat",
5097        "Bearjadat",
5098        "Lávvordat",
5099        "Sotnabeaivi",
5100    ]
5101
5102
5103class OdiaLocale(Locale):
5104
5105    names = ["or", "or-in"]
5106
5107    past = "{0} ପୂର୍ବେ"
5108    future = "{0} ପରେ"
5109
5110    timeframes = {
5111        "now": "ବର୍ତ୍ତମାନ",
5112        "second": "ଏକ ସେକେଣ୍ଡ",
5113        "seconds": "{0} ସେକେଣ୍ଡ",
5114        "minute": "ଏକ ମିନଟ",
5115        "minutes": "{0} ମିନଟ",
5116        "hour": "ଏକ ଘଣ୍ଟା",
5117        "hours": "{0} ଘଣ୍ଟା",
5118        "day": "ଏକ ଦିନ",
5119        "days": "{0} ଦିନ",
5120        "month": "ଏକ ମାସ",
5121        "months": "{0} ମାସ ",
5122        "year": "ଏକ ବର୍ଷ",
5123        "years": "{0} ବର୍ଷ",
5124    }
5125
5126    meridians = {"am": "ପୂର୍ବାହ୍ନ", "pm": "ଅପରାହ୍ନ", "AM": "ପୂର୍ବାହ୍ନ", "PM": "ଅପରାହ୍ନ"}
5127
5128    month_names = [
5129        "",
5130        "ଜାନୁଆରୀ",
5131        "ଫେବୃଆରୀ",
5132        "ମାର୍ଚ୍ଚ୍",
5133        "ଅପ୍ରେଲ",
5134        "ମଇ",
5135        "ଜୁନ୍",
5136        "ଜୁଲାଇ",
5137        "ଅଗଷ୍ଟ",
5138        "ସେପ୍ଟେମ୍ବର",
5139        "ଅକ୍ଟୋବର୍",
5140        "ନଭେମ୍ବର୍",
5141        "ଡିସେମ୍ବର୍",
5142    ]
5143    month_abbreviations = [
5144        "",
5145        "ଜାନୁ",
5146        "ଫେବୃ",
5147        "ମାର୍ଚ୍ଚ୍",
5148        "ଅପ୍ରେ",
5149        "ମଇ",
5150        "ଜୁନ୍",
5151        "ଜୁଲା",
5152        "ଅଗ",
5153        "ସେପ୍ଟେ",
5154        "ଅକ୍ଟୋ",
5155        "ନଭେ",
5156        "ଡିସେ",
5157    ]
5158
5159    day_names = [
5160        "",
5161        "ସୋମବାର",
5162        "ମଙ୍ଗଳବାର",
5163        "ବୁଧବାର",
5164        "ଗୁରୁବାର",
5165        "ଶୁକ୍ରବାର",
5166        "ଶନିବାର",
5167        "ରବିବାର",
5168    ]
5169    day_abbreviations = [
5170        "",
5171        "ସୋମ",
5172        "ମଙ୍ଗଳ",
5173        "ବୁଧ",
5174        "ଗୁରୁ",
5175        "ଶୁକ୍ର",
5176        "ଶନି",
5177        "ରବି",
5178    ]
5179
5180    def _ordinal_number(self, n: int) -> str:
5181        if n > 10 or n == 0:
5182            return f"{n}ତମ"
5183        if n in [1, 5, 7, 8, 9, 10]:
5184            return f"{n}ମ"
5185        if n in [2, 3]:
5186            return f"{n}ୟ"
5187        if n == 4:
5188            return f"{n}ର୍ଥ"
5189        if n == 6:
5190            return f"{n}ଷ୍ଠ"
5191        return ""
5192
5193
5194class SerbianLocale(Locale):
5195
5196    names = ["sr", "sr-rs", "sr-sp"]
5197
5198    past = "pre {0}"
5199    future = "za {0}"
5200    and_word = "i"
5201
5202    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[str, Mapping[str, str]]]] = {
5203        "now": "sada",
5204        "second": "sekundu",
5205        "seconds": {"double": "{0} sekunde", "higher": "{0} sekundi"},
5206        "minute": "minutu",
5207        "minutes": {"double": "{0} minute", "higher": "{0} minuta"},
5208        "hour": "sat",
5209        "hours": {"double": "{0} sata", "higher": "{0} sati"},
5210        "day": "dan",
5211        "days": {"double": "{0} dana", "higher": "{0} dana"},
5212        "week": "nedelju",
5213        "weeks": {"double": "{0} nedelje", "higher": "{0} nedelja"},
5214        "month": "mesec",
5215        "months": {"double": "{0} meseca", "higher": "{0} meseci"},
5216        "year": "godinu",
5217        "years": {"double": "{0} godine", "higher": "{0} godina"},
5218    }
5219
5220    month_names = [
5221        "",
5222        "januar",  # јануар
5223        "februar",  # фебруар
5224        "mart",  # март
5225        "april",  # април
5226        "maj",  # мај
5227        "jun",  # јун
5228        "jul",  # јул
5229        "avgust",  # август
5230        "septembar",  # септембар
5231        "oktobar",  # октобар
5232        "novembar",  # новембар
5233        "decembar",  # децембар
5234    ]
5235
5236    month_abbreviations = [
5237        "",
5238        "jan",
5239        "feb",
5240        "mar",
5241        "apr",
5242        "maj",
5243        "jun",
5244        "jul",
5245        "avg",
5246        "sep",
5247        "okt",
5248        "nov",
5249        "dec",
5250    ]
5251
5252    day_names = [
5253        "",
5254        "ponedeljak",  # понедељак
5255        "utorak",  # уторак
5256        "sreda",  # среда
5257        "četvrtak",  # четвртак
5258        "petak",  # петак
5259        "subota",  # субота
5260        "nedelja",  # недеља
5261    ]
5262
5263    day_abbreviations = [
5264        "",
5265        "po",  # по
5266        "ut",  # ут
5267        "sr",  # ср
5268        "če",  # че
5269        "pe",  # пе
5270        "su",  # су
5271        "ne",  # не
5272    ]
5273
5274    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
5275        form = self.timeframes[timeframe]
5276        delta = abs(delta)
5277        if isinstance(form, Mapping):
5278            if 1 < delta <= 4:
5279                form = form["double"]
5280            else:
5281                form = form["higher"]
5282
5283        return form.format(delta)
5284
5285
5286class LuxembourgishLocale(Locale):
5287
5288    names = ["lb", "lb-lu"]
5289
5290    past = "virun {0}"
5291    future = "an {0}"
5292    and_word = "an"
5293
5294    timeframes = {
5295        "now": "just elo",
5296        "second": "enger Sekonn",
5297        "seconds": "{0} Sekonnen",
5298        "minute": "enger Minutt",
5299        "minutes": "{0} Minutten",
5300        "hour": "enger Stonn",
5301        "hours": "{0} Stonnen",
5302        "day": "engem Dag",
5303        "days": "{0} Deeg",
5304        "week": "enger Woch",
5305        "weeks": "{0} Wochen",
5306        "month": "engem Mount",
5307        "months": "{0} Méint",
5308        "year": "engem Joer",
5309        "years": "{0} Jahren",
5310    }
5311
5312    timeframes_only_distance = timeframes.copy()
5313    timeframes_only_distance["second"] = "eng Sekonn"
5314    timeframes_only_distance["minute"] = "eng Minutt"
5315    timeframes_only_distance["hour"] = "eng Stonn"
5316    timeframes_only_distance["day"] = "een Dag"
5317    timeframes_only_distance["days"] = "{0} Deeg"
5318    timeframes_only_distance["week"] = "eng Woch"
5319    timeframes_only_distance["month"] = "ee Mount"
5320    timeframes_only_distance["months"] = "{0} Méint"
5321    timeframes_only_distance["year"] = "ee Joer"
5322    timeframes_only_distance["years"] = "{0} Joer"
5323
5324    month_names = [
5325        "",
5326        "Januar",
5327        "Februar",
5328        "Mäerz",
5329        "Abrëll",
5330        "Mee",
5331        "Juni",
5332        "Juli",
5333        "August",
5334        "September",
5335        "Oktouber",
5336        "November",
5337        "Dezember",
5338    ]
5339
5340    month_abbreviations = [
5341        "",
5342        "Jan",
5343        "Feb",
5344        "Mäe",
5345        "Abr",
5346        "Mee",
5347        "Jun",
5348        "Jul",
5349        "Aug",
5350        "Sep",
5351        "Okt",
5352        "Nov",
5353        "Dez",
5354    ]
5355
5356    day_names = [
5357        "",
5358        "Méindeg",
5359        "Dënschdeg",
5360        "Mëttwoch",
5361        "Donneschdeg",
5362        "Freideg",
5363        "Samschdeg",
5364        "Sonndeg",
5365    ]
5366
5367    day_abbreviations = ["", "Méi", "Dën", "Mët", "Don", "Fre", "Sam", "Son"]
5368
5369    def _ordinal_number(self, n: int) -> str:
5370        return f"{n}."
5371
5372    def describe(
5373        self,
5374        timeframe: TimeFrameLiteral,
5375        delta: Union[int, float] = 0,
5376        only_distance: bool = False,
5377    ) -> str:
5378
5379        if not only_distance:
5380            return super().describe(timeframe, delta, only_distance)
5381
5382        # Luxembourgish uses a different case without 'in' or 'ago'
5383        humanized = self.timeframes_only_distance[timeframe].format(trunc(abs(delta)))
5384
5385        return humanized
5386
5387
5388class ZuluLocale(Locale):
5389
5390    names = ["zu", "zu-za"]
5391
5392    past = "{0} edlule"
5393    future = "{0} "
5394    and_word = "futhi"
5395
5396    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[Mapping[str, str], str]]] = {
5397        "now": "manje",
5398        "second": {"past": "umzuzwana", "future": "ngomzuzwana"},
5399        "seconds": {"past": "{0} imizuzwana", "future": "{0} ngemizuzwana"},
5400        "minute": {"past": "umzuzu", "future": "ngomzuzu"},
5401        "minutes": {"past": "{0} imizuzu", "future": "{0} ngemizuzu"},
5402        "hour": {"past": "ihora", "future": "ngehora"},
5403        "hours": {"past": "{0} amahora", "future": "{0} emahoreni"},
5404        "day": {"past": "usuku", "future": "ngosuku"},
5405        "days": {"past": "{0} izinsuku", "future": "{0} ezinsukwini"},
5406        "week": {"past": "isonto", "future": "ngesonto"},
5407        "weeks": {"past": "{0} amasonto", "future": "{0} emasontweni"},
5408        "month": {"past": "inyanga", "future": "ngenyanga"},
5409        "months": {"past": "{0} izinyanga", "future": "{0} ezinyangeni"},
5410        "year": {"past": "unyaka", "future": "ngonyak"},
5411        "years": {"past": "{0} iminyaka", "future": "{0} eminyakeni"},
5412    }
5413
5414    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
5415        """Zulu aware time frame format function, takes into account
5416        the differences between past and future forms."""
5417        abs_delta = abs(delta)
5418        form = self.timeframes[timeframe]
5419
5420        if isinstance(form, str):
5421            return form.format(abs_delta)
5422
5423        if delta > 0:
5424            key = "future"
5425        else:
5426            key = "past"
5427        form = form[key]
5428
5429        return form.format(abs_delta)
5430
5431    month_names = [
5432        "",
5433        "uMasingane",
5434        "uNhlolanja",
5435        "uNdasa",
5436        "UMbasa",
5437        "UNhlaba",
5438        "UNhlangulana",
5439        "uNtulikazi",
5440        "UNcwaba",
5441        "uMandulo",
5442        "uMfumfu",
5443        "uLwezi",
5444        "uZibandlela",
5445    ]
5446
5447    month_abbreviations = [
5448        "",
5449        "uMasingane",
5450        "uNhlolanja",
5451        "uNdasa",
5452        "UMbasa",
5453        "UNhlaba",
5454        "UNhlangulana",
5455        "uNtulikazi",
5456        "UNcwaba",
5457        "uMandulo",
5458        "uMfumfu",
5459        "uLwezi",
5460        "uZibandlela",
5461    ]
5462
5463    day_names = [
5464        "",
5465        "uMsombuluko",
5466        "uLwesibili",
5467        "uLwesithathu",
5468        "uLwesine",
5469        "uLwesihlanu",
5470        "uMgqibelo",
5471        "iSonto",
5472    ]
5473
5474    day_abbreviations = [
5475        "",
5476        "uMsombuluko",
5477        "uLwesibili",
5478        "uLwesithathu",
5479        "uLwesine",
5480        "uLwesihlanu",
5481        "uMgqibelo",
5482        "iSonto",
5483    ]
5484
5485
5486class TamilLocale(Locale):
5487
5488    names = ["ta", "ta-in", "ta-lk"]
5489
5490    past = "{0} நேரத்திற்கு முன்பு"
5491    future = "இல் {0}"
5492
5493    timeframes = {
5494        "now": "இப்போது",
5495        "second": "ஒரு இரண்டாவது",
5496        "seconds": "{0} விநாடிகள்",
5497        "minute": "ஒரு நிமிடம்",
5498        "minutes": "{0} நிமிடங்கள்",
5499        "hour": "ஒரு மணி",
5500        "hours": "{0} மணிநேரம்",
5501        "day": "ஒரு நாள்",
5502        "days": "{0} நாட்கள்",
5503        "week": "ஒரு வாரம்",
5504        "weeks": "{0} வாரங்கள்",
5505        "month": "ஒரு மாதம்",
5506        "months": "{0} மாதங்கள்",
5507        "year": "ஒரு ஆண்டு",
5508        "years": "{0} ஆண்டுகள்",
5509    }
5510
5511    month_names = [
5512        "",
5513        "சித்திரை",
5514        "வைகாசி",
5515        "ஆனி",
5516        "ஆடி",
5517        "ஆவணி",
5518        "புரட்டாசி",
5519        "ஐப்பசி",
5520        "கார்த்திகை",
5521        "மார்கழி",
5522        "தை",
5523        "மாசி",
5524        "பங்குனி",
5525    ]
5526
5527    month_abbreviations = [
5528        "",
5529        "ஜன",
5530        "பிப்",
5531        "மார்",
5532        "ஏப்",
5533        "மே",
5534        "ஜூன்",
5535        "ஜூலை",
5536        "ஆக",
5537        "செப்",
5538        "அக்",
5539        "நவ",
5540        "டிச",
5541    ]
5542
5543    day_names = [
5544        "",
5545        "திங்கட்கிழமை",
5546        "செவ்வாய்க்கிழமை",
5547        "புதன்கிழமை",
5548        "வியாழக்கிழமை",
5549        "வெள்ளிக்கிழமை",
5550        "சனிக்கிழமை",
5551        "ஞாயிற்றுக்கிழமை",
5552    ]
5553
5554    day_abbreviations = [
5555        "",
5556        "திங்கட்",
5557        "செவ்வாய்",
5558        "புதன்",
5559        "வியாழன்",
5560        "வெள்ளி",
5561        "சனி",
5562        "ஞாயிறு",
5563    ]
5564
5565    def _ordinal_number(self, n: int) -> str:
5566        if n == 1:
5567            return f"{n}வது"
5568        elif n >= 0:
5569            return f"{n}ஆம்"
5570        else:
5571            return ""
5572
5573
5574class AlbanianLocale(Locale):
5575
5576    names = ["sq", "sq-al"]
5577
5578    past = "{0} më parë"
5579    future = "në {0}"
5580    and_word = "dhe"
5581
5582    timeframes = {
5583        "now": "tani",
5584        "second": "sekondë",
5585        "seconds": "{0} sekonda",
5586        "minute": "minutë",
5587        "minutes": "{0} minuta",
5588        "hour": "orë",
5589        "hours": "{0} orë",
5590        "day": "ditë",
5591        "days": "{0} ditë",
5592        "week": "javë",
5593        "weeks": "{0} javë",
5594        "month": "muaj",
5595        "months": "{0} muaj",
5596        "year": "vit",
5597        "years": "{0} vjet",
5598    }
5599
5600    month_names = [
5601        "",
5602        "janar",
5603        "shkurt",
5604        "mars",
5605        "prill",
5606        "maj",
5607        "qershor",
5608        "korrik",
5609        "gusht",
5610        "shtator",
5611        "tetor",
5612        "nëntor",
5613        "dhjetor",
5614    ]
5615
5616    month_abbreviations = [
5617        "",
5618        "jan",
5619        "shk",
5620        "mar",
5621        "pri",
5622        "maj",
5623        "qer",
5624        "korr",
5625        "gush",
5626        "sht",
5627        "tet",
5628        "nën",
5629        "dhj",
5630    ]
5631
5632    day_names = [
5633        "",
5634        "e hënë",
5635        "e martë",
5636        "e mërkurë",
5637        "e enjte",
5638        "e premte",
5639        "e shtunë",
5640        "e diel",
5641    ]
5642
5643    day_abbreviations = [
5644        "",
5645        "hën",
5646        "mar",
5647        "mër",
5648        "enj",
5649        "pre",
5650        "sht",
5651        "die",
5652    ]
5653
5654
5655class SinhalaLocale(Locale):
5656
5657    names = ["si", "si-lk"]
5658
5659    past = "{0}ට පෙර"
5660    future = "{0}"
5661    and_word = "සහ"
5662
5663    timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[Mapping[str, str], str]]] = {
5664        "now": "දැන්",
5665        "second": {
5666            "past": "තත්පරයක",
5667            "future": "තත්පරයකින්",
5668        },  # ක් is the article
5669        "seconds": {
5670            "past": "තත්පර {0} ක",
5671            "future": "තත්පර {0} කින්",
5672        },
5673        "minute": {
5674            "past": "විනාඩියක",
5675            "future": "විනාඩියකින්",
5676        },
5677        "minutes": {
5678            "past": "විනාඩි {0} ක",
5679            "future": "මිනිත්තු {0} කින්",
5680        },
5681        "hour": {"past": "පැයක", "future": "පැයකින්"},
5682        "hours": {
5683            "past": "පැය {0} ක",
5684            "future": "පැය {0} කින්",
5685        },
5686        "day": {"past": "දිනක", "future": "දිනකට"},
5687        "days": {
5688            "past": "දින {0} ක",
5689            "future": "දින {0} කින්",
5690        },
5691        "week": {"past": "සතියක", "future": "සතියකින්"},
5692        "weeks": {
5693            "past": "සති {0} ක",
5694            "future": "සති {0} කින්",
5695        },
5696        "month": {"past": "මාසයක", "future": "එය මාසය තුළ"},
5697        "months": {
5698            "past": "මාස {0} ක",
5699            "future": "මාස {0} කින්",
5700        },
5701        "year": {"past": "වසරක", "future": "වසරක් තුළ"},
5702        "years": {
5703            "past": "අවුරුදු {0} ක",
5704            "future": "අවුරුදු {0} තුළ",
5705        },
5706    }
5707    # Sinhala: the general format to describe timeframe is different from past and future,
5708    # so we do not copy the original timeframes dictionary
5709    timeframes_only_distance = dict()
5710    timeframes_only_distance["second"] = "තත්පරයක්"
5711    timeframes_only_distance["seconds"] = "තත්පර {0}"
5712    timeframes_only_distance["minute"] = "මිනිත්තුවක්"
5713    timeframes_only_distance["minutes"] = "විනාඩි {0}"
5714    timeframes_only_distance["hour"] = "පැයක්"
5715    timeframes_only_distance["hours"] = "පැය {0}"
5716    timeframes_only_distance["day"] = "දවසක්"
5717    timeframes_only_distance["days"] = "දවස් {0}"
5718    timeframes_only_distance["week"] = "සතියක්"
5719    timeframes_only_distance["weeks"] = "සති {0}"
5720    timeframes_only_distance["month"] = "මාසයක්"
5721    timeframes_only_distance["months"] = "මාස {0}"
5722    timeframes_only_distance["year"] = "අවුරුද්දක්"
5723    timeframes_only_distance["years"] = "අවුරුදු {0}"
5724
5725    def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
5726        """
5727        Sinhala awares time frame format function, takes into account
5728        the differences between general, past, and future forms (three different suffixes).
5729        """
5730        abs_delta = abs(delta)
5731        form = self.timeframes[timeframe]
5732
5733        if isinstance(form, str):
5734            return form.format(abs_delta)
5735
5736        if delta > 0:
5737            key = "future"
5738        else:
5739            key = "past"
5740        form = form[key]
5741
5742        return form.format(abs_delta)
5743
5744    def describe(
5745        self,
5746        timeframe: TimeFrameLiteral,
5747        delta: Union[float, int] = 1,  # key is always future when only_distance=False
5748        only_distance: bool = False,
5749    ) -> str:
5750        """Describes a delta within a timeframe in plain language.
5751
5752        :param timeframe: a string representing a timeframe.
5753        :param delta: a quantity representing a delta in a timeframe.
5754        :param only_distance: return only distance eg: "11 seconds" without "in" or "ago" keywords
5755        """
5756
5757        if not only_distance:
5758            return super().describe(timeframe, delta, only_distance)
5759        # Sinhala uses a different case without 'in' or 'ago'
5760        humanized = self.timeframes_only_distance[timeframe].format(trunc(abs(delta)))
5761
5762        return humanized
5763
5764    month_names = [
5765        "",
5766        "ජනවාරි",
5767        "පෙබරවාරි",
5768        "මාර්තු",
5769        "අප්‍රේල්",
5770        "මැයි",
5771        "ජූනි",
5772        "ජූලි",
5773        "අගෝස්තු",
5774        "සැප්තැම්බර්",
5775        "ඔක්තෝබර්",
5776        "නොවැම්බර්",
5777        "දෙසැම්බර්",
5778    ]
5779
5780    month_abbreviations = [
5781        "",
5782        "ජන",
5783        "පෙබ",
5784        "මාර්",
5785        "අප්‍රේ",
5786        "මැයි",
5787        "ජුනි",
5788        "ජූලි",
5789        "අගෝ",
5790        "සැප්",
5791        "ඔක්",
5792        "නොවැ",
5793        "දෙසැ",
5794    ]
5795
5796    day_names = [
5797        "",
5798        "සදුදා",
5799        "අඟහරැවදා",
5800        "බදාදා",
5801        "බ්‍රහස්‍පතින්‍දා",
5802        "සිකුරාදා",
5803        "සෙනසුරාදා",
5804        "ඉරිදා",
5805    ]
5806
5807    day_abbreviations = [
5808        "",
5809        "සදුද",
5810        "බදා",
5811        "බදා",
5812        "සිකු",
5813        "සෙන",
5814        "අ",
5815        "ඉරිදා",
5816    ]
5817
5818
5819class UrduLocale(Locale):
5820
5821    names = ["ur", "ur-pk"]
5822
5823    past = "پہلے {0}"
5824    future = "میں {0}"
5825    and_word = "اور"
5826
5827    timeframes = {
5828        "now": "ابھی",
5829        "second": "ایک سیکنڈ",
5830        "seconds": "{0} سیکنڈ",
5831        "minute": "ایک منٹ",
5832        "minutes": "{0} منٹ",
5833        "hour": "ایک گھنٹے",
5834        "hours": "{0} گھنٹے",
5835        "day": "ایک دن",
5836        "days": "{0} دن",
5837        "week": "ایک ہفتے",
5838        "weeks": "{0} ہفتے",
5839        "month": "ایک مہینہ",
5840        "months": "{0} ماہ",
5841        "year": "ایک سال",
5842        "years": "{0} سال",
5843    }
5844
5845    month_names = [
5846        "",
5847        "جنوری",
5848        "فروری",
5849        "مارچ",
5850        "اپریل",
5851        "مئی",
5852        "جون",
5853        "جولائی",
5854        "اگست",
5855        "ستمبر",
5856        "اکتوبر",
5857        "نومبر",
5858        "دسمبر",
5859    ]
5860
5861    month_abbreviations = [
5862        "",
5863        "جنوری",
5864        "فروری",
5865        "مارچ",
5866        "اپریل",
5867        "مئی",
5868        "جون",
5869        "جولائی",
5870        "اگست",
5871        "ستمبر",
5872        "اکتوبر",
5873        "نومبر",
5874        "دسمبر",
5875    ]
5876
5877    day_names = [
5878        "",
5879        "سوموار",
5880        "منگل",
5881        "بدھ",
5882        "جمعرات",
5883        "جمعہ",
5884        "ہفتہ",
5885        "اتوار",
5886    ]
5887
5888    day_abbreviations = [
5889        "",
5890        "سوموار",
5891        "منگل",
5892        "بدھ",
5893        "جمعرات",
5894        "جمعہ",
5895        "ہفتہ",
5896        "اتوار",
5897    ]
5898