Skip to content

Commit

Permalink
Update United Kingdom & Isle of Man holidays: add l10n support (#2258)
Browse files Browse the repository at this point in the history
Signed-off-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>
Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>
Co-authored-by: ~Jhellico <KJhellico@users.noreply.github.com>
Co-authored-by: Arkadii Yakovets <ark@cho.red>
  • Loading branch information
4 people authored Feb 10, 2025
1 parent cb2a27d commit ecd0117
Show file tree
Hide file tree
Showing 12 changed files with 736 additions and 78 deletions.
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ All other default values are highlighted with bold:
* - Isle of Man
- IM
-
-
- **en_GB**, en_US, th
-
* - Israel
- IL
Expand Down Expand Up @@ -913,7 +913,7 @@ All other default values are highlighted with bold:
* - United Kingdom
- GB
- Subdivisions: ENG (England), NIR (Northern Ireland), SCT (Scotland), WLS (Wales)
-
- **en_GB**, en_US, th
-
* - United States Minor Outlying Islands
- UM
Expand Down
26 changes: 15 additions & 11 deletions holidays/countries/isle_of_man.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
# Website: https://github.com/vacanza/holidays
# License: MIT (see LICENSE file)

from gettext import gettext as tr

from holidays.countries.united_kingdom import UnitedKingdom, UnitedKingdomStaticHolidays
from holidays.groups import ChristianHolidays, InternationalHolidays, StaticHolidays
from holidays.observed_holiday_base import ObservedHolidayBase, SAT_SUN_TO_NEXT_MON
Expand All @@ -19,6 +21,7 @@ class IsleOfMan(UnitedKingdom):
"""Using existing code in UnitedKingdom for now."""

country = "IM"
parent_entity = UnitedKingdom
subdivisions = () # Override UnitedKingdom subdivisions.
subdivisions_aliases = {} # Override UnitedKingdom subdivisions aliases.

Expand All @@ -31,25 +34,26 @@ def __init__(self, *args, **kwargs): # Override UnitedKingdom __init__().

def _populate_public_holidays(self) -> None:
super()._populate_public_holidays()
# Easter Monday
self._add_easter_monday("Easter Monday")
# Easter Monday.
self._add_easter_monday(tr("Easter Monday"))

# Whit Monday.
if self._year <= 1970:
self._add_whit_monday("Whit Monday")
# Whit Monday.
self._add_whit_monday(tr("Whit Monday"))

# Late Summer bank holiday (last Monday in August)
if self._year >= 1971:
self._add_holiday_last_mon_of_aug("Late Summer Bank Holiday")
# Late Summer Bank Holiday.
self._add_holiday_last_mon_of_aug(tr("Late Summer Bank Holiday"))

# Isle of Man exclusive holidays
# TT bank holiday (first Friday in June)
self._add_holiday_1st_fri_of_jun("TT Bank Holiday")

# Tynwald Day
# Move to the next Monday if falls on a weekend.
jul_5 = self._add_holiday_jul_5("Tynwald Day")
# TT Bank Holiday.
self._add_holiday_1st_fri_of_jun(tr("TT Bank Holiday"))

# Tynwald Day.
jul_5 = self._add_holiday_jul_5(tr("Tynwald Day"))
if self._year >= 1992:
# Move to the next Monday if falls on a weekend.
self._move_holiday(jul_5, show_observed_label=False)


Expand Down
128 changes: 72 additions & 56 deletions holidays/countries/united_kingdom.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# Website: https://github.com/vacanza/holidays
# License: MIT (see LICENSE file)

from gettext import gettext as tr
from typing import Union

from holidays.calendars.gregorian import APR, MAY, JUN, JUL, SEP, DEC
Expand Down Expand Up @@ -37,7 +38,9 @@ class UnitedKingdom(ObservedHolidayBase, ChristianHolidays, InternationalHoliday
"""

country = "GB"
observed_label = "%s (observed)"
default_language = "en_GB"
# %s (observed).
observed_label = tr("%s (observed)")
subdivisions: Union[tuple[()], tuple[str, ...]] = (
"ENG", # England
"NIR", # Northern Ireland
Expand All @@ -50,6 +53,7 @@ class UnitedKingdom(ObservedHolidayBase, ChristianHolidays, InternationalHoliday
"Scotland": "SCT",
"Wales": "WLS",
}
supported_languages = ("en_GB", "en_US", "th")
_deprecated_subdivisions = ("UK",)
# Bank Holidays Act 1871
start_year = 1872
Expand All @@ -64,120 +68,123 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def _populate_public_holidays(self) -> None:
# Good Friday
self._add_good_friday("Good Friday")
# Good Friday.
self._add_good_friday(tr("Good Friday"))

# May Day bank holiday (first Monday in May)
if self._year >= 1978:
name = "May Day"
# May Day.
name = tr("May Day")
if self._year in {1995, 2020}:
self._add_holiday_may_8(name)
else:
self._add_holiday_1st_mon_of_may(name)

# Spring bank holiday (last Monday in May)
if self._year >= 1971:
spring_bank_dates = {
2002: (JUN, 4),
2012: (JUN, 4),
2022: (JUN, 2),
}
name = "Spring Bank Holiday"
# Spring Bank Holiday.
name = tr("Spring Bank Holiday")
if self._year in spring_bank_dates:
self._add_holiday(name, spring_bank_dates[self._year])
else:
self._add_holiday_last_mon_of_may(name)

def _populate_subdiv_holidays(self):
if self.subdiv != "SCT":
# New Year's Day
if self._year >= 1975:
self._add_observed(self._add_new_years_day("New Year's Day"))
# New Year's Day.
self._add_observed(self._add_new_years_day(tr("New Year's Day")))

# Christmas Day
self._add_observed(
self._add_christmas_day("Christmas Day"), rule=SAT_SUN_TO_NEXT_MON_TUE
# Christmas Day.
self._add_christmas_day(tr("Christmas Day")),
rule=SAT_SUN_TO_NEXT_MON_TUE,
)

# Boxing Day
self._add_observed(
self._add_christmas_day_two("Boxing Day"), rule=SAT_SUN_TO_NEXT_MON_TUE
# Boxing Day.
self._add_christmas_day_two(tr("Boxing Day")),
rule=SAT_SUN_TO_NEXT_MON_TUE,
)

super()._populate_subdiv_holidays()

def _populate_subdiv_eng_public_holidays(self):
# Easter Monday
self._add_easter_monday("Easter Monday")
# Easter Monday.
self._add_easter_monday(tr("Easter Monday"))

# Whit Monday.
if self._year <= 1970:
self._add_whit_monday("Whit Monday")
# Whit Monday.
self._add_whit_monday(tr("Whit Monday"))

# Late Summer bank holiday (last Monday in August)
if self._year >= 1971:
self._add_holiday_last_mon_of_aug("Late Summer Bank Holiday")
# Late Summer Bank Holiday.
self._add_holiday_last_mon_of_aug(tr("Late Summer Bank Holiday"))

def _populate_subdiv_nir_public_holidays(self):
if self._year >= 1903:
# Saint Patrick's Day
self._add_observed(self._add_holiday_mar_17("Saint Patrick's Day"))
# Saint Patrick's Day.
self._add_observed(self._add_holiday_mar_17(tr("Saint Patrick's Day")))

# Easter Monday
self._add_easter_monday("Easter Monday")
# Easter Monday.
self._add_easter_monday(tr("Easter Monday"))

# Whit Monday.
if self._year <= 1970:
self._add_whit_monday("Whit Monday")
# Whit Monday.
self._add_whit_monday(tr("Whit Monday"))

# Battle of the Boyne
self._add_observed(self._add_holiday_jul_12("Battle of the Boyne"))
# Battle of the Boyne.
self._add_observed(self._add_holiday_jul_12(tr("Battle of the Boyne")))

# Late Summer bank holiday (last Monday in August)
if self._year >= 1971:
self._add_holiday_last_mon_of_aug("Late Summer Bank Holiday")
# Late Summer Bank Holiday.
self._add_holiday_last_mon_of_aug(tr("Late Summer Bank Holiday"))

def _populate_subdiv_sct_public_holidays(self):
# New Year's Day
jan_1 = self._add_new_years_day("New Year's Day")
# New Year's Day.
jan_1 = self._add_new_years_day(tr("New Year's Day"))

# New Year Holiday
self._add_observed(
self._add_new_years_day_two("New Year Holiday"),
# New Year Holiday.
self._add_new_years_day_two(tr("New Year Holiday")),
rule=SAT_SUN_TO_NEXT_MON_TUE + MON_TO_NEXT_TUE,
)
self._add_observed(jan_1)

# Summer bank holiday (first Monday in August)
self._add_holiday_1st_mon_of_aug("Summer Bank Holiday")
# Summer Bank Holiday.
self._add_holiday_1st_mon_of_aug(tr("Summer Bank Holiday"))

if self._year >= 2006:
# Saint Andrew's Day
self._add_observed(self._add_holiday_nov_30("Saint Andrew's Day"))
# Saint Andrew's Day.
self._add_observed(self._add_holiday_nov_30(tr("Saint Andrew's Day")))

# Christmas Day
self._add_observed(
self._add_christmas_day("Christmas Day"),
# Christmas Day.
self._add_christmas_day(tr("Christmas Day")),
rule=SAT_SUN_TO_NEXT_MON_TUE if self._year >= 1974 else SAT_SUN_TO_NEXT_MON,
)

if self._year >= 1974:
# Boxing Day
self._add_observed(
self._add_christmas_day_two("Boxing Day"), rule=SAT_SUN_TO_NEXT_MON_TUE
# Boxing Day.
self._add_christmas_day_two(tr("Boxing Day")),
rule=SAT_SUN_TO_NEXT_MON_TUE,
)

def _populate_subdiv_wls_public_holidays(self):
# Easter Monday
self._add_easter_monday("Easter Monday")
# Easter Monday.
self._add_easter_monday(tr("Easter Monday"))

# Whit Monday.
if self._year <= 1970:
self._add_whit_monday("Whit Monday")
# Whit Monday.
self._add_whit_monday(tr("Whit Monday"))

# Late Summer bank holiday (last Monday in August)
if self._year >= 1971:
self._add_holiday_last_mon_of_aug("Late Summer Bank Holiday")
# Late Summer Bank Holiday.
self._add_holiday_last_mon_of_aug(tr("Late Summer Bank Holiday"))


class UK(UnitedKingdom):
Expand All @@ -194,15 +201,24 @@ class GBR(UnitedKingdom):

class UnitedKingdomStaticHolidays:
special_public_holidays = {
1977: (JUN, 7, "Silver Jubilee of Elizabeth II"),
1981: (JUL, 29, "Wedding of Charles and Diana"),
1999: (DEC, 31, "Millennium Celebrations"),
2002: (JUN, 3, "Golden Jubilee of Elizabeth II"),
2011: (APR, 29, "Wedding of William and Catherine"),
2012: (JUN, 5, "Diamond Jubilee of Elizabeth II"),
# Silver Jubilee of Elizabeth II.
1977: (JUN, 7, tr("Silver Jubilee of Elizabeth II")),
# Wedding of Charles and Diana.
1981: (JUL, 29, tr("Wedding of Charles and Diana")),
# Millennium Celebrations.
1999: (DEC, 31, tr("Millennium Celebrations")),
# Golden Jubilee of Elizabeth II.
2002: (JUN, 3, tr("Golden Jubilee of Elizabeth II")),
# Wedding of William and Catherine.
2011: (APR, 29, tr("Wedding of William and Catherine")),
# Diamond Jubilee of Elizabeth II.
2012: (JUN, 5, tr("Diamond Jubilee of Elizabeth II")),
2022: (
(JUN, 3, "Platinum Jubilee of Elizabeth II"),
(SEP, 19, "State Funeral of Queen Elizabeth II"),
# Platinum Jubilee of Elizabeth II.
(JUN, 3, tr("Platinum Jubilee of Elizabeth II")),
# State Funeral of Queen Elizabeth II.
(SEP, 19, tr("State Funeral of Queen Elizabeth II")),
),
2023: (MAY, 8, "Coronation of Charles III"),
# Coronation of Charles III.
2023: (MAY, 8, tr("Coronation of Charles III")),
}
36 changes: 27 additions & 9 deletions holidays/holiday_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ def _populate(self, year):
"""Start year of holidays presence for this entity."""
end_year: int = DEFAULT_END_YEAR
"""End year of holidays presence for this entity."""
parent_entity: Optional[type["HolidayBase"]] = None
"""Optional parent entity to reference as a base."""

def __init__(
self,
Expand Down Expand Up @@ -364,16 +366,32 @@ def __init__(
self.weekend_workdays = getattr(self, "weekend_workdays", set())

supported_languages = set(self.supported_languages)
self.tr = (
translation(
if self._entity_code is not None:
fallback = language not in supported_languages
languages = [language] if language in supported_languages else None
locale_directory = str(Path(__file__).with_name("locale"))

# Add entity native content translations.
entity_translation = translation(
self._entity_code,
fallback=language not in supported_languages,
languages=[language] if language in supported_languages else None,
localedir=str(Path(__file__).with_name("locale")),
).gettext
if self._entity_code is not None
else gettext
)
fallback=fallback,
languages=languages,
localedir=locale_directory,
)
# Add a fallback if entity has parent translations.
if parent_entity := self.parent_entity:
entity_translation.add_fallback(
translation(
parent_entity.country or parent_entity.market,
fallback=fallback,
languages=languages,
localedir=locale_directory,
)
)
self.tr = entity_translation.gettext
else:
self.tr = gettext

self.years = _normalize_arguments(int, years)

# Populate holidays.
Expand Down
Loading

0 comments on commit ecd0117

Please sign in to comment.