Skip to content

Commit c9cae9e

Browse files
authored
Add Amharic Locale (#1093)
1 parent 5ad47f1 commit c9cae9e

File tree

3 files changed

+249
-0
lines changed

3 files changed

+249
-0
lines changed

β€Žarrow/constants.pyβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,6 @@
166166
"ka-ge",
167167
"kk",
168168
"kk-kz",
169+
"am",
170+
"am-et",
169171
}

β€Žarrow/locales.pyβ€Ž

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6100,3 +6100,174 @@ class KazakhLocale(Locale):
61006100
"ЖСксСнбі",
61016101
]
61026102
day_abbreviations = ["", "Дс", "Бс", "Π‘Ρ€", "Бс", "Π–ΠΌ", "Π‘Π±", "Жс"]
6103+
6104+
6105+
class AmharicLocale(Locale):
6106+
names = ["am", "am-et"]
6107+
6108+
past = "{0} α‰ αŠα‰΅"
6109+
future = "{0} α‹αˆ΅αŒ₯"
6110+
and_word = "αŠ₯αŠ“"
6111+
6112+
timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[Mapping[str, str], str]]] = {
6113+
"now": "αŠ αˆαŠ•",
6114+
"second": {
6115+
"past": "αŠ¨αŠ αŠ•α‹΅ αˆ°αŠ¨αŠ•α‹΅",
6116+
"future": "α‰ αŠ αŠ•α‹΅ αˆ°αŠ¨αŠ•α‹΅",
6117+
},
6118+
"seconds": {
6119+
"past": "ከ {0} αˆ°αŠ¨αŠ•α‹΅",
6120+
"future": "α‰  {0} αˆ°αŠ¨αŠ•α‹΅",
6121+
},
6122+
"minute": {
6123+
"past": "αŠ¨αŠ αŠ•α‹΅ ደቂቃ",
6124+
"future": "α‰ αŠ αŠ•α‹΅ ደቂቃ",
6125+
},
6126+
"minutes": {
6127+
"past": "ከ {0} α‹°α‰‚α‰ƒα‹Žα‰½",
6128+
"future": "α‰  {0} α‹°α‰‚α‰ƒα‹Žα‰½",
6129+
},
6130+
"hour": {
6131+
"past": "αŠ¨αŠ αŠ•α‹΅ αˆ°α‹“α‰΅",
6132+
"future": "α‰ αŠ αŠ•α‹΅ αˆ°α‹“α‰΅",
6133+
},
6134+
"hours": {
6135+
"past": "ከ {0} αˆ°α‹“α‰³α‰΅",
6136+
"future": "α‰  {0} αˆ°αŠ¨αŠ•α‹΅",
6137+
},
6138+
"day": {
6139+
"past": "αŠ¨αŠ αŠ•α‹΅ α‰€αŠ•",
6140+
"future": "α‰ αŠ αŠ•α‹΅ α‰€αŠ•",
6141+
},
6142+
"days": {
6143+
"past": "ከ {0} α‰€αŠ“α‰΅",
6144+
"future": "α‰  {0} α‰€αŠ“α‰΅",
6145+
},
6146+
"week": {
6147+
"past": "αŠ¨αŠ αŠ•α‹΅ αˆ³αˆαŠ•α‰΅",
6148+
"future": "α‰ αŠ αŠ•α‹΅ αˆ³αˆαŠ•α‰΅",
6149+
},
6150+
"weeks": {
6151+
"past": "ከ {0} αˆ³αˆαŠ•α‰³α‰΅",
6152+
"future": "α‰  {0} αˆ³αˆαŠ•α‰³α‰΅",
6153+
},
6154+
"month": {
6155+
"past": "αŠ¨αŠ αŠ•α‹΅ α‹ˆαˆ­",
6156+
"future": "α‰ αŠ αŠ•α‹΅ α‹ˆαˆ­",
6157+
},
6158+
"months": {
6159+
"past": "ከ {0} α‹ˆαˆ­",
6160+
"future": "α‰  {0} α‹ˆαˆ«α‰΅",
6161+
},
6162+
"year": {
6163+
"past": "αŠ¨αŠ αŠ•α‹΅ αŠ αˆ˜α‰΅",
6164+
"future": "α‰ αŠ αŠ•α‹΅ αŠ αˆ˜α‰΅",
6165+
},
6166+
"years": {
6167+
"past": "ከ {0} α‹“αˆ˜α‰³α‰΅",
6168+
"future": "α‰  {0} α‹“αˆ˜α‰³α‰΅",
6169+
},
6170+
}
6171+
# Amharic: the general format to describe timeframe is different from past and future,
6172+
# so we do not copy the original timeframes dictionary
6173+
timeframes_only_distance = {
6174+
"second": "αŠ αŠ•α‹΅ αˆ°αŠ¨αŠ•α‹΅",
6175+
"seconds": "{0} αˆ°αŠ¨αŠ•α‹΅",
6176+
"minute": "αŠ αŠ•α‹΅ ደቂቃ",
6177+
"minutes": "{0} α‹°α‰‚α‰ƒα‹Žα‰½",
6178+
"hour": "αŠ αŠ•α‹΅ αˆ°α‹“α‰΅",
6179+
"hours": "{0} αˆ°α‹“α‰΅",
6180+
"day": "αŠ αŠ•α‹΅ α‰€αŠ•",
6181+
"days": "{0} α‰€αŠ“α‰΅",
6182+
"week": "αŠ αŠ•α‹΅ αˆ³αˆαŠ•α‰΅",
6183+
"weeks": "{0} αˆ³αˆαŠ•α‰΅",
6184+
"month": "αŠ αŠ•α‹΅ α‹ˆαˆ­",
6185+
"months": "{0} α‹ˆαˆ«α‰΅",
6186+
"year": "αŠ αŠ•α‹΅ αŠ αˆ˜α‰΅",
6187+
"years": "{0} α‹“αˆ˜α‰³α‰΅",
6188+
}
6189+
6190+
month_names = [
6191+
"",
6192+
"αŒƒαŠ•α‹©α‹ˆαˆͺ",
6193+
"ፌα‰₯αˆ©α‹ˆαˆͺ",
6194+
"αˆ›αˆ­α‰½",
6195+
"αŠ€α•αˆͺል",
6196+
"αˆœα‹­",
6197+
"αŒαŠ•",
6198+
"αŒαˆ‹α‹­",
6199+
"αŠ¦αŒˆαˆ΅α‰΅",
6200+
"αˆ΄α•α‰΄αˆα‰ αˆ­",
6201+
"αŠ¦αŠ­α‰Άα‰ αˆ­",
6202+
"αŠ–α‰¬αˆα‰ αˆ­",
6203+
"α‹²αˆ΄αˆα‰ αˆ­",
6204+
]
6205+
6206+
month_abbreviations = [
6207+
"",
6208+
"αŒƒαŠ•α‹©",
6209+
"ፌα‰₯ሩ",
6210+
"αˆ›αˆ­α‰½",
6211+
"αŠ€α•αˆͺ",
6212+
"αˆœα‹­",
6213+
"αŒαŠ•",
6214+
"αŒαˆ‹α‹­",
6215+
"ኦገሡ",
6216+
"αˆ΄α•α‰΄",
6217+
"αŠ¦αŠ­α‰Ά",
6218+
"αŠ–α‰¬αˆ",
6219+
"α‹²αˆ΄αˆ",
6220+
]
6221+
6222+
day_names = [
6223+
"",
6224+
"ሰኞ",
6225+
"αˆ›αŠ­αˆ°αŠž",
6226+
"αˆ¨α‰‘α‹•",
6227+
"αˆαˆ™αˆ΅",
6228+
"α‹“αˆ­α‰₯",
6229+
"α‰…α‹³αˆœ",
6230+
"αŠ₯αˆ‘α‹΅",
6231+
]
6232+
day_abbreviations = ["", "αŠ₯", "ሰ", "αˆ›", "ረ", "ሐ", "α‹“", "α‰…"]
6233+
6234+
def _ordinal_number(self, n: int) -> str:
6235+
return f"{n}αŠ›"
6236+
6237+
def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str:
6238+
"""
6239+
Amharic awares time frame format function, takes into account
6240+
the differences between general, past, and future forms (three different suffixes).
6241+
"""
6242+
abs_delta = abs(delta)
6243+
form = self.timeframes[timeframe]
6244+
6245+
if isinstance(form, str):
6246+
return form.format(abs_delta)
6247+
6248+
if delta > 0:
6249+
key = "future"
6250+
else:
6251+
key = "past"
6252+
form = form[key]
6253+
6254+
return form.format(abs_delta)
6255+
6256+
def describe(
6257+
self,
6258+
timeframe: TimeFrameLiteral,
6259+
delta: Union[float, int] = 1, # key is always future when only_distance=False
6260+
only_distance: bool = False,
6261+
) -> str:
6262+
"""Describes a delta within a timeframe in plain language.
6263+
6264+
:param timeframe: a string representing a timeframe.
6265+
:param delta: a quantity representing a delta in a timeframe.
6266+
:param only_distance: return only distance eg: "11 seconds" without "in" or "ago" keywords
6267+
"""
6268+
6269+
if not only_distance:
6270+
return super().describe(timeframe, delta, only_distance)
6271+
humanized = self.timeframes_only_distance[timeframe].format(trunc(abs(delta)))
6272+
6273+
return humanized

β€Žtests/test_locales.pyβ€Ž

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2919,3 +2919,79 @@ def test_weekday(self):
29192919
dt = arrow.Arrow(2015, 4, 11, 17, 30, 00)
29202920
assert self.locale.day_name(dt.isoweekday()) == "lΓΈrdag"
29212921
assert self.locale.day_abbreviation(dt.isoweekday()) == "lΓΈr"
2922+
2923+
2924+
@pytest.mark.usefixtures("lang_locale")
2925+
class TestAmharicLocale:
2926+
def test_format_timeframe(self):
2927+
assert self.locale._format_timeframe("now", 0) == "αŠ αˆαŠ•"
2928+
# second(s)
2929+
assert self.locale._format_timeframe("second", 1) == "α‰ αŠ αŠ•α‹΅ αˆ°αŠ¨αŠ•α‹΅"
2930+
assert self.locale._format_timeframe("second", -1) == "αŠ¨αŠ αŠ•α‹΅ αˆ°αŠ¨αŠ•α‹΅"
2931+
assert self.locale._format_timeframe("seconds", 6) == "α‰  6 αˆ°αŠ¨αŠ•α‹΅"
2932+
assert self.locale._format_timeframe("seconds", -36) == "ከ 36 αˆ°αŠ¨αŠ•α‹΅"
2933+
# minute(s)
2934+
assert self.locale._format_timeframe("minute", 1) == "α‰ αŠ αŠ•α‹΅ ደቂቃ"
2935+
assert self.locale._format_timeframe("minute", -1) == "αŠ¨αŠ αŠ•α‹΅ ደቂቃ"
2936+
assert self.locale._format_timeframe("minutes", 7) == "α‰  7 α‹°α‰‚α‰ƒα‹Žα‰½"
2937+
assert self.locale._format_timeframe("minutes", -20) == "ከ 20 α‹°α‰‚α‰ƒα‹Žα‰½"
2938+
# hour(s)
2939+
assert self.locale._format_timeframe("hour", 1) == "α‰ αŠ αŠ•α‹΅ αˆ°α‹“α‰΅"
2940+
assert self.locale._format_timeframe("hour", -1) == "αŠ¨αŠ αŠ•α‹΅ αˆ°α‹“α‰΅"
2941+
assert self.locale._format_timeframe("hours", 7) == "α‰  7 αˆ°αŠ¨αŠ•α‹΅"
2942+
assert self.locale._format_timeframe("hours", -20) == "ከ 20 αˆ°α‹“α‰³α‰΅"
2943+
# day(s)
2944+
assert self.locale._format_timeframe("day", 1) == "α‰ αŠ αŠ•α‹΅ α‰€αŠ•"
2945+
assert self.locale._format_timeframe("day", -1) == "αŠ¨αŠ αŠ•α‹΅ α‰€αŠ•"
2946+
assert self.locale._format_timeframe("days", 7) == "α‰  7 α‰€αŠ“α‰΅"
2947+
assert self.locale._format_timeframe("days", -20) == "ከ 20 α‰€αŠ“α‰΅"
2948+
# week(s)
2949+
assert self.locale._format_timeframe("week", 1) == "α‰ αŠ αŠ•α‹΅ αˆ³αˆαŠ•α‰΅"
2950+
assert self.locale._format_timeframe("week", -1) == "αŠ¨αŠ αŠ•α‹΅ αˆ³αˆαŠ•α‰΅"
2951+
assert self.locale._format_timeframe("weeks", 7) == "α‰  7 αˆ³αˆαŠ•α‰³α‰΅"
2952+
assert self.locale._format_timeframe("weeks", -20) == "ከ 20 αˆ³αˆαŠ•α‰³α‰΅"
2953+
# month(s)
2954+
assert self.locale._format_timeframe("month", 1) == "α‰ αŠ αŠ•α‹΅ α‹ˆαˆ­"
2955+
assert self.locale._format_timeframe("month", -1) == "αŠ¨αŠ αŠ•α‹΅ α‹ˆαˆ­"
2956+
assert self.locale._format_timeframe("months", 7) == "α‰  7 α‹ˆαˆ«α‰΅"
2957+
assert self.locale._format_timeframe("months", -20) == "ከ 20 α‹ˆαˆ­"
2958+
# year(s)
2959+
assert self.locale._format_timeframe("year", 1) == "α‰ αŠ αŠ•α‹΅ αŠ αˆ˜α‰΅"
2960+
assert self.locale._format_timeframe("year", -1) == "αŠ¨αŠ αŠ•α‹΅ αŠ αˆ˜α‰΅"
2961+
assert self.locale._format_timeframe("years", 7) == "α‰  7 α‹“αˆ˜α‰³α‰΅"
2962+
assert self.locale._format_timeframe("years", -20) == "ከ 20 α‹“αˆ˜α‰³α‰΅"
2963+
2964+
def test_describe_am(self):
2965+
assert self.locale.describe("second", only_distance=True) == "αŠ αŠ•α‹΅ αˆ°αŠ¨αŠ•α‹΅"
2966+
assert (
2967+
self.locale.describe("second", only_distance=False) == "α‰ αŠ αŠ•α‹΅ αˆ°αŠ¨αŠ•α‹΅ α‹αˆ΅αŒ₯"
2968+
) # (in) a second
2969+
2970+
assert self.locale.describe("minute", only_distance=True) == "αŠ αŠ•α‹΅ ደቂቃ"
2971+
assert (
2972+
self.locale.describe("minute", only_distance=False) == "α‰ αŠ αŠ•α‹΅ ደቂቃ α‹αˆ΅αŒ₯"
2973+
) # (in) a minute
2974+
2975+
def test_format_relative_now(self):
2976+
result = self.locale._format_relative("αŠ αˆαŠ•", "now", 0)
2977+
assert result == "αŠ αˆαŠ•"
2978+
2979+
def test_ordinal_number(self):
2980+
assert self.locale.ordinal_number(1) == "1αŠ›"
2981+
2982+
def test_format_relative_future(self):
2983+
2984+
result = self.locale._format_relative("α‰ αŠ αŠ•α‹΅ αˆ°α‹“α‰΅", "hour", 1)
2985+
2986+
assert result == "α‰ αŠ αŠ•α‹΅ αˆ°α‹“α‰΅ α‹αˆ΅αŒ₯" # (in) one hour
2987+
2988+
def test_format_relative_past(self):
2989+
2990+
result = self.locale._format_relative("αŠ¨αŠ αŠ•α‹΅ αˆ°α‹“α‰΅", "hour", -1)
2991+
2992+
assert result == "αŠ¨αŠ αŠ•α‹΅ αˆ°α‹“α‰΅ α‰ αŠα‰΅" # an hour ago
2993+
2994+
def test_weekday(self):
2995+
dt = arrow.Arrow(2015, 4, 11, 17, 30, 00)
2996+
assert self.locale.day_name(dt.isoweekday()) == "α‰…α‹³αˆœ"
2997+
assert self.locale.day_abbreviation(dt.isoweekday()) == "α‹“"

0 commit comments

Comments
Β (0)